Correct, update, improve and clean up a lot of docstrings in order to make
[bpt/guile.git] / libguile / symbols.c
1 /* Copyright (C) 1995,1996,1997,1998, 2000, 2001 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
45 \f
46
47 #include "libguile/_scm.h"
48 #include "libguile/chars.h"
49 #include "libguile/eval.h"
50 #include "libguile/hash.h"
51 #include "libguile/smob.h"
52 #include "libguile/variable.h"
53 #include "libguile/alist.h"
54 #include "libguile/fluids.h"
55 #include "libguile/strings.h"
56 #include "libguile/vectors.h"
57 #include "libguile/hashtab.h"
58 #include "libguile/weaks.h"
59 #include "libguile/modules.h"
60
61 #include "libguile/validate.h"
62 #include "libguile/symbols.h"
63
64 #ifdef HAVE_STRING_H
65 #include <string.h>
66 #endif
67
68 \f
69
70 static SCM symbols;
71
72 #ifdef GUILE_DEBUG
73 SCM_DEFINE (scm_sys_symbols, "%symbols", 0, 0, 0,
74 (),
75 "Return the system symbol obarray.")
76 #define FUNC_NAME s_scm_sys_symbols
77 {
78 return symbols;
79 }
80 #undef FUNC_NAME
81 #endif
82
83 \f
84
85 static char *
86 duplicate_string (const char * src, unsigned long length)
87 {
88 char * dst = scm_must_malloc (length + 1, "duplicate_string");
89 memcpy (dst, src, length);
90 dst[length] = 0;
91 return dst;
92 }
93
94 \f
95
96 /* {Symbols}
97 */
98
99
100 SCM
101 scm_mem2symbol (const char *name, scm_sizet len)
102 {
103 scm_sizet raw_hash = scm_string_hash ((const unsigned char *) name, len);
104 scm_sizet hash = raw_hash % SCM_VECTOR_LENGTH (symbols);
105
106 {
107 /* Try to find the symbol in the symbols table */
108
109 SCM l;
110
111 for (l = SCM_VELTS (symbols) [hash]; !SCM_NULLP (l); l = SCM_CDR (l))
112 {
113 SCM sym = SCM_CAAR (l);
114 if (SCM_SYMBOL_HASH (sym) == raw_hash && SCM_SYMBOL_LENGTH (sym) == len)
115 {
116 char *chrs = SCM_SYMBOL_CHARS (sym);
117 scm_sizet i = len;
118
119 while (i != 0)
120 {
121 --i;
122 if (name[i] != chrs[i])
123 goto next_symbol;
124 }
125
126 return sym;
127 }
128 next_symbol:
129 ;
130 }
131 }
132
133 {
134 /* The symbol was not found - create it. */
135
136 SCM symbol;
137 SCM cell;
138 SCM slot;
139
140 SCM_NEWCELL2 (symbol);
141 SCM_SET_SYMBOL_CHARS (symbol, duplicate_string (name, len));
142 SCM_SET_SYMBOL_HASH (symbol, raw_hash);
143 SCM_SET_PROP_SLOTS (symbol, scm_cons (SCM_BOOL_F, SCM_EOL));
144 SCM_SET_SYMBOL_LENGTH (symbol, (long) len);
145
146 cell = scm_cons (symbol, SCM_UNDEFINED);
147 slot = SCM_VELTS (symbols) [hash];
148 SCM_VELTS (symbols) [hash] = scm_cons (cell, slot);
149
150 return symbol;
151 }
152 }
153
154
155 SCM
156 scm_str2symbol (const char *str)
157 {
158 return scm_mem2symbol (str, strlen (str));
159 }
160
161
162 /* scm_sym2vcell
163 * looks up the symbol in the symhash table.
164 */
165
166 SCM
167 scm_sym2vcell (SCM sym, SCM thunk, SCM definep)
168 #define FUNC_NAME "scm_sym2vcell"
169 {
170 if (SCM_NIMP (thunk))
171 {
172 SCM var;
173
174 if (SCM_EVAL_CLOSURE_P (thunk))
175 /* Bypass evaluator in the standard case. */
176 var = scm_eval_closure_lookup (thunk, sym, definep);
177 else
178 var = scm_apply (thunk, sym, scm_cons (definep, scm_listofnull));
179
180 if (SCM_FALSEP (var))
181 return SCM_BOOL_F;
182 else if (SCM_VARIABLEP (var))
183 return SCM_VARVCELL (var);
184 else
185 SCM_MISC_ERROR ("strangely interned symbol: ~S", SCM_LIST1 (sym));
186 }
187 else
188 {
189 SCM lsym;
190 scm_sizet hash;
191
192 SCM_DEFER_INTS;
193 hash = SCM_SYMBOL_HASH (sym) % SCM_VECTOR_LENGTH (scm_symhash);
194 for (lsym = SCM_VELTS (scm_symhash)[hash]; SCM_NIMP (lsym); lsym = SCM_CDR (lsym))
195 {
196 SCM z = SCM_CAR (lsym);
197 if (SCM_EQ_P (SCM_CAR (z), sym))
198 {
199 SCM_ALLOW_INTS;
200 return z;
201 }
202 }
203
204 if (!SCM_FALSEP (definep))
205 {
206 SCM cell = scm_cons (sym, SCM_UNDEFINED);
207 SCM slot = SCM_VELTS (scm_symhash) [hash];
208
209 SCM_VELTS (scm_symhash) [hash] = scm_cons (cell, slot);
210
211 SCM_ALLOW_INTS;
212 return cell;
213 }
214 else
215 {
216 SCM_ALLOW_INTS;
217 return SCM_BOOL_F;
218 }
219 }
220 }
221 #undef FUNC_NAME
222
223
224 /* scm_sym2ovcell
225 * looks up the symbol in an arbitrary obarray.
226 */
227
228 SCM
229 scm_sym2ovcell_soft (SCM sym, SCM obarray)
230 {
231 SCM lsym, z;
232 scm_sizet hash = SCM_SYMBOL_HASH (sym) % SCM_VECTOR_LENGTH (obarray);
233 SCM_REDEFER_INTS;
234 for (lsym = SCM_VELTS (obarray)[hash];
235 SCM_NIMP (lsym);
236 lsym = SCM_CDR (lsym))
237 {
238 z = SCM_CAR (lsym);
239 if (SCM_EQ_P (SCM_CAR (z), sym))
240 {
241 SCM_REALLOW_INTS;
242 return z;
243 }
244 }
245 SCM_REALLOW_INTS;
246 return SCM_BOOL_F;
247 }
248
249
250 SCM
251 scm_sym2ovcell (SCM sym, SCM obarray)
252 #define FUNC_NAME "scm_sym2ovcell"
253 {
254 SCM answer;
255 answer = scm_sym2ovcell_soft (sym, obarray);
256 if (!SCM_FALSEP (answer))
257 return answer;
258 SCM_MISC_ERROR ("uninterned symbol: ~S", SCM_LIST1 (sym));
259 return SCM_UNSPECIFIED; /* not reached */
260 }
261 #undef FUNC_NAME
262
263
264 /* Intern a symbol whose name is the LEN characters at NAME in OBARRAY.
265
266 OBARRAY should be a vector of lists, indexed by the name's hash
267 value, modulo OBARRAY's length. Each list has the form
268 ((SYMBOL . VALUE) ...), where SYMBOL is a symbol, and VALUE is the
269 value associated with that symbol (in the current module? in the
270 system module?)
271
272 To "intern" a symbol means: if OBARRAY already contains a symbol by
273 that name, return its (SYMBOL . VALUE) pair; otherwise, create a
274 new symbol, add the pair (SYMBOL . SCM_UNDEFINED) to the
275 appropriate list of the OBARRAY, and return the pair.
276
277 If softness is non-zero, don't create a symbol if it isn't already
278 in OBARRAY; instead, just return #f.
279
280 If OBARRAY is SCM_BOOL_F, create a symbol listed in no obarray and
281 return (SYMBOL . SCM_UNDEFINED). */
282
283
284 SCM
285 scm_intern_obarray_soft (const char *name,scm_sizet len,SCM obarray,unsigned int softness)
286 {
287 SCM symbol = scm_mem2symbol (name, len);
288 scm_sizet raw_hash = SCM_SYMBOL_HASH (symbol);
289 scm_sizet hash;
290 SCM lsym;
291
292 if (SCM_FALSEP (obarray))
293 {
294 if (softness)
295 return SCM_BOOL_F;
296 else
297 return scm_cons (symbol, SCM_UNDEFINED);
298 }
299
300 hash = raw_hash % SCM_VECTOR_LENGTH (obarray);
301
302 for (lsym = SCM_VELTS (obarray)[hash]; SCM_NIMP (lsym); lsym = SCM_CDR (lsym))
303 {
304 SCM a = SCM_CAR (lsym);
305 SCM z = SCM_CAR (a);
306 if (SCM_EQ_P (z, symbol))
307 return a;
308 }
309
310 if (softness)
311 {
312 return SCM_BOOL_F;
313 }
314 else
315 {
316 SCM cell = scm_cons (symbol, SCM_UNDEFINED);
317 SCM slot = SCM_VELTS (obarray) [hash];
318
319 SCM_VELTS (obarray) [hash] = scm_cons (cell, slot);
320
321 return cell;
322 }
323 }
324
325
326 SCM
327 scm_intern_obarray (const char *name,scm_sizet len,SCM obarray)
328 {
329 return scm_intern_obarray_soft (name, len, obarray, 0);
330 }
331
332
333 SCM
334 scm_intern (const char *name,scm_sizet len)
335 {
336 return scm_intern_obarray (name, len, scm_symhash);
337 }
338
339
340 SCM
341 scm_intern0 (const char * name)
342 {
343 return scm_intern (name, strlen (name));
344 }
345
346
347 /* Intern the symbol named NAME in scm_symhash, NAME is null-terminated. */
348 SCM
349 scm_sysintern0_no_module_lookup (const char *name)
350 {
351 scm_sizet len = strlen (name);
352 SCM easy_answer;
353 SCM_DEFER_INTS;
354 easy_answer = scm_intern_obarray_soft (name, len, scm_symhash, 1);
355 if (SCM_NIMP (easy_answer))
356 {
357 SCM_ALLOW_INTS;
358 return easy_answer;
359 }
360 else
361 {
362 SCM symbol = scm_mem2symbol (name, len);
363 scm_sizet raw_hash = SCM_SYMBOL_HASH (symbol);
364 scm_sizet hash = raw_hash % SCM_VECTOR_LENGTH (scm_symhash);
365 SCM cell = scm_cons (symbol, SCM_UNDEFINED);
366 SCM slot = SCM_VELTS (scm_symhash) [hash];
367
368 SCM_VELTS (scm_symhash) [hash] = scm_cons (cell, slot);
369 SCM_ALLOW_INTS;
370 return cell;
371 }
372 }
373
374 /* Intern the symbol named NAME in scm_symhash, and give it the value
375 VAL. NAME is null-terminated. Use the current top_level lookup
376 closure to give NAME its value.
377 */
378 SCM
379 scm_sysintern (const char *name, SCM val)
380 {
381 SCM vcell = scm_sysintern0 (name);
382 SCM_SETCDR (vcell, val);
383 return vcell;
384 }
385
386 SCM
387 scm_sysintern0 (const char *name)
388 {
389 SCM lookup_proc;
390 if (scm_module_system_booted_p
391 && SCM_NIMP (lookup_proc = SCM_TOP_LEVEL_LOOKUP_CLOSURE))
392 {
393 SCM sym = scm_str2symbol (name);
394 SCM vcell = scm_sym2vcell (sym, lookup_proc, SCM_BOOL_T);
395 if (SCM_FALSEP (vcell))
396 scm_misc_error ("sysintern0", "can't define variable", sym);
397 return vcell;
398 }
399 else
400 return scm_sysintern0_no_module_lookup (name);
401 }
402
403 /* Lookup the value of the symbol named by the nul-terminated string
404 NAME in the current module. */
405 SCM
406 scm_symbol_value0 (const char *name)
407 {
408 /* This looks silly - we look up the symbol twice. But it is in
409 fact necessary given the current module system because the module
410 lookup closures are written in scheme which needs real symbols. */
411 SCM symbol = scm_str2symbol (name);
412 SCM vcell = scm_sym2vcell (symbol, SCM_TOP_LEVEL_LOOKUP_CLOSURE, SCM_BOOL_F);
413 if (SCM_FALSEP (vcell))
414 return SCM_UNDEFINED;
415 return SCM_CDR (vcell);
416 }
417
418
419 SCM_DEFINE (scm_symbol_p, "symbol?", 1, 0, 0,
420 (SCM obj),
421 "Return @code{#t} if @var{obj} is a symbol, otherwise return\n"
422 "@code{#f}.")
423 #define FUNC_NAME s_scm_symbol_p
424 {
425 return SCM_BOOL (SCM_SYMBOLP (obj));
426 }
427 #undef FUNC_NAME
428
429 SCM_DEFINE (scm_symbol_to_string, "symbol->string", 1, 0, 0,
430 (SCM s),
431 "Return the name of @var{symbol} as a string. If the symbol was\n"
432 "part of an object returned as the value of a literal expression\n"
433 "(section @pxref{Literal expressions,,,r4rs, The Revised^4\n"
434 "Report on Scheme}) or by a call to the @code{read} procedure,\n"
435 "and its name contains alphabetic characters, then the string\n"
436 "returned will contain characters in the implementation's\n"
437 "preferred standard case---some implementations will prefer\n"
438 "upper case, others lower case. If the symbol was returned by\n"
439 "@code{string->symbol}, the case of characters in the string\n"
440 "returned will be the same as the case in the string that was\n"
441 "passed to @code{string->symbol}. It is an error to apply\n"
442 "mutation procedures like @code{string-set!} to strings returned\n"
443 "by this procedure.\n"
444 "\n"
445 "The following examples assume that the implementation's\n"
446 "standard case is lower case:\n"
447 "\n"
448 "@lisp\n"
449 "(symbol->string 'flying-fish) @result{} \"flying-fish\"\n"
450 "(symbol->string 'Martin) @result{} \"martin\"\n"
451 "(symbol->string\n"
452 " (string->symbol \"Malvina\")) @result{} \"Malvina\"\n"
453 "@end lisp")
454 #define FUNC_NAME s_scm_symbol_to_string
455 {
456 SCM_VALIDATE_SYMBOL (1, s);
457 return scm_makfromstr (SCM_SYMBOL_CHARS (s), SCM_SYMBOL_LENGTH (s), 0);
458 }
459 #undef FUNC_NAME
460
461
462 SCM_DEFINE (scm_string_to_symbol, "string->symbol", 1, 0, 0,
463 (SCM string),
464 "Return the symbol whose name is @var{string}. This procedure\n"
465 "can create symbols with names containing special characters or\n"
466 "letters in the non-standard case, but it is usually a bad idea\n"
467 "to create such symbols because in some implementations of\n"
468 "Scheme they cannot be read as themselves. See\n"
469 "@code{symbol->string}.\n"
470 "\n"
471 "The following examples assume that the implementation's\n"
472 "standard case is lower case:\n"
473 "\n"
474 "@lisp\n"
475 "(eq? 'mISSISSIppi 'mississippi) @result{} #t\n"
476 "(string->symbol \"mISSISSIppi\") @result{} @r{the symbol with name \"mISSISSIppi\"}\n"
477 "(eq? 'bitBlt (string->symbol \"bitBlt\")) @result{} #f\n"
478 "(eq? 'JollyWog\n"
479 " (string->symbol (symbol->string 'JollyWog))) @result{} #t\n"
480 "(string=? \"K. Harper, M.D.\"\n"
481 " (symbol->string\n"
482 " (string->symbol \"K. Harper, M.D.\"))) @result{}#t\n"
483 "@end lisp")
484 #define FUNC_NAME s_scm_string_to_symbol
485 {
486 SCM_VALIDATE_STRING (1, string);
487 return scm_mem2symbol (SCM_STRING_CHARS (string),
488 SCM_STRING_LENGTH (string));
489 }
490 #undef FUNC_NAME
491
492
493 SCM_DEFINE (scm_string_to_obarray_symbol, "string->obarray-symbol", 2, 1, 0,
494 (SCM o, SCM s, SCM softp),
495 "Intern a new symbol in @var{obarray}, a symbol table, with name\n"
496 "@var{string}.\n\n"
497 "If @var{obarray} is @code{#f}, use the default system symbol table. If\n"
498 "@var{obarray} is @code{#t}, the symbol should not be interned in any\n"
499 "symbol table; merely return the pair (@var{symbol}\n"
500 ". @var{#<undefined>}).\n\n"
501 "The @var{soft?} argument determines whether new symbol table entries\n"
502 "should be created when the specified symbol is not already present in\n"
503 "@var{obarray}. If @var{soft?} is specified and is a true value, then\n"
504 "new entries should not be added for symbols not already present in the\n"
505 "table; instead, simply return @code{#f}.")
506 #define FUNC_NAME s_scm_string_to_obarray_symbol
507 {
508 SCM vcell;
509 SCM answer;
510 int softness;
511
512 SCM_VALIDATE_STRING (2, s);
513 SCM_ASSERT (SCM_BOOLP (o) || SCM_VECTORP (o), o, SCM_ARG1, FUNC_NAME);
514
515 softness = (!SCM_UNBNDP (softp) && !SCM_FALSEP(softp));
516 /* iron out some screwy calling conventions */
517 if (SCM_FALSEP (o))
518 o = scm_symhash;
519 else if (SCM_EQ_P (o, SCM_BOOL_T))
520 o = SCM_BOOL_F;
521
522 vcell = scm_intern_obarray_soft (SCM_STRING_CHARS(s),
523 SCM_STRING_LENGTH (s),
524 o,
525 softness);
526 if (SCM_FALSEP (vcell))
527 return vcell;
528 answer = SCM_CAR (vcell);
529 return answer;
530 }
531 #undef FUNC_NAME
532
533 SCM_DEFINE (scm_intern_symbol, "intern-symbol", 2, 0, 0,
534 (SCM o, SCM s),
535 "Add a new symbol to @var{obarray} with name @var{string}, bound to an\n"
536 "unspecified initial value. The symbol table is not modified if a symbol\n"
537 "with this name is already present.")
538 #define FUNC_NAME s_scm_intern_symbol
539 {
540 scm_sizet hval;
541 SCM_VALIDATE_SYMBOL (2,s);
542 if (SCM_FALSEP (o))
543 o = scm_symhash;
544 SCM_VALIDATE_VECTOR (1,o);
545 hval = SCM_SYMBOL_HASH (s) % SCM_VECTOR_LENGTH (o);
546 /* If the symbol is already interned, simply return. */
547 SCM_REDEFER_INTS;
548 {
549 SCM lsym;
550 SCM sym;
551 for (lsym = SCM_VELTS (o)[hval];
552 SCM_NIMP (lsym);
553 lsym = SCM_CDR (lsym))
554 {
555 sym = SCM_CAR (lsym);
556 if (SCM_EQ_P (SCM_CAR (sym), s))
557 {
558 SCM_REALLOW_INTS;
559 return SCM_UNSPECIFIED;
560 }
561 }
562 SCM_VELTS (o)[hval] =
563 scm_acons (s, SCM_UNDEFINED, SCM_VELTS (o)[hval]);
564 }
565 SCM_REALLOW_INTS;
566 return SCM_UNSPECIFIED;
567 }
568 #undef FUNC_NAME
569
570 SCM_DEFINE (scm_unintern_symbol, "unintern-symbol", 2, 0, 0,
571 (SCM o, SCM s),
572 "Remove the symbol with name @var{string} from @var{obarray}. This\n"
573 "function returns @code{#t} if the symbol was present and @code{#f}\n"
574 "otherwise.")
575 #define FUNC_NAME s_scm_unintern_symbol
576 {
577 scm_sizet hval;
578 SCM_VALIDATE_SYMBOL (2,s);
579 if (SCM_FALSEP (o))
580 o = scm_symhash;
581 SCM_VALIDATE_VECTOR (1,o);
582 hval = SCM_SYMBOL_HASH (s) % SCM_VECTOR_LENGTH (o);
583 SCM_DEFER_INTS;
584 {
585 SCM lsym_follow;
586 SCM lsym;
587 SCM sym;
588 for (lsym = SCM_VELTS (o)[hval], lsym_follow = SCM_BOOL_F;
589 SCM_NIMP (lsym);
590 lsym_follow = lsym, lsym = SCM_CDR (lsym))
591 {
592 sym = SCM_CAR (lsym);
593 if (SCM_EQ_P (SCM_CAR (sym), s))
594 {
595 /* Found the symbol to unintern. */
596 if (SCM_FALSEP (lsym_follow))
597 SCM_VELTS(o)[hval] = lsym;
598 else
599 SCM_SETCDR (lsym_follow, SCM_CDR(lsym));
600 SCM_ALLOW_INTS;
601 return SCM_BOOL_T;
602 }
603 }
604 }
605 SCM_ALLOW_INTS;
606 return SCM_BOOL_F;
607 }
608 #undef FUNC_NAME
609
610 SCM_DEFINE (scm_symbol_binding, "symbol-binding", 2, 0, 0,
611 (SCM o, SCM s),
612 "Look up in @var{obarray} the symbol whose name is @var{string}, and\n"
613 "return the value to which it is bound. If @var{obarray} is @code{#f},\n"
614 "use the global symbol table. If @var{string} is not interned in\n"
615 "@var{obarray}, an error is signalled.")
616 #define FUNC_NAME s_scm_symbol_binding
617 {
618 SCM vcell;
619 SCM_VALIDATE_SYMBOL (2,s);
620 if (SCM_FALSEP (o))
621 o = scm_symhash;
622 SCM_VALIDATE_VECTOR (1,o);
623 vcell = scm_sym2ovcell (s, o);
624 return SCM_CDR(vcell);
625 }
626 #undef FUNC_NAME
627
628
629 SCM_DEFINE (scm_symbol_interned_p, "symbol-interned?", 2, 0, 0,
630 (SCM o, SCM s),
631 "Return @code{#t} if @var{obarray} contains a symbol with name\n"
632 "@var{string}, and @code{#f} otherwise.")
633 #define FUNC_NAME s_scm_symbol_interned_p
634 {
635 SCM vcell;
636 SCM_VALIDATE_SYMBOL (2,s);
637 if (SCM_FALSEP (o))
638 o = scm_symhash;
639 SCM_VALIDATE_VECTOR (1,o);
640 vcell = scm_sym2ovcell_soft (s, o);
641 return (SCM_NIMP(vcell)
642 ? SCM_BOOL_T
643 : SCM_BOOL_F);
644 }
645 #undef FUNC_NAME
646
647
648 SCM_DEFINE (scm_symbol_bound_p, "symbol-bound?", 2, 0, 0,
649 (SCM o, SCM s),
650 "Return @code{#t} if @var{obarray} contains a symbol with name\n"
651 "@var{string} bound to a defined value. This differs from\n"
652 "@var{symbol-interned?} in that the mere mention of a symbol\n"
653 "usually causes it to be interned; @code{symbol-bound?}\n"
654 "determines whether a symbol has been given any meaningful\n"
655 "value.")
656 #define FUNC_NAME s_scm_symbol_bound_p
657 {
658 SCM vcell;
659 SCM_VALIDATE_SYMBOL (2,s);
660 if (SCM_FALSEP (o))
661 o = scm_symhash;
662 SCM_VALIDATE_VECTOR (1,o);
663 vcell = scm_sym2ovcell_soft (s, o);
664 return SCM_BOOL (SCM_NIMP (vcell) && !SCM_UNBNDP (SCM_CDR (vcell)));
665 }
666 #undef FUNC_NAME
667
668
669 SCM_DEFINE (scm_symbol_set_x, "symbol-set!", 3, 0, 0,
670 (SCM o, SCM s, SCM v),
671 "Find the symbol in @var{obarray} whose name is @var{string}, and rebind\n"
672 "it to @var{value}. An error is signalled if @var{string} is not present\n"
673 "in @var{obarray}.")
674 #define FUNC_NAME s_scm_symbol_set_x
675 {
676 SCM vcell;
677 SCM_VALIDATE_SYMBOL (2,s);
678 if (SCM_FALSEP (o))
679 o = scm_symhash;
680 SCM_VALIDATE_VECTOR (1,o);
681 vcell = scm_sym2ovcell (s, o);
682 SCM_SETCDR (vcell, v);
683 return SCM_UNSPECIFIED;
684 }
685 #undef FUNC_NAME
686
687
688 SCM_DEFINE (scm_symbol_fref, "symbol-fref", 1, 0, 0,
689 (SCM s),
690 "Return the contents of @var{symbol}'s @dfn{function slot}.")
691 #define FUNC_NAME s_scm_symbol_fref
692 {
693 SCM_VALIDATE_SYMBOL (1,s);
694 return SCM_SYMBOL_FUNC (s);
695 }
696 #undef FUNC_NAME
697
698
699 SCM_DEFINE (scm_symbol_pref, "symbol-pref", 1, 0, 0,
700 (SCM s),
701 "Return the @dfn{property list} currently associated with @var{symbol}.")
702 #define FUNC_NAME s_scm_symbol_pref
703 {
704 SCM_VALIDATE_SYMBOL (1,s);
705 return SCM_SYMBOL_PROPS (s);
706 }
707 #undef FUNC_NAME
708
709
710 SCM_DEFINE (scm_symbol_fset_x, "symbol-fset!", 2, 0, 0,
711 (SCM s, SCM val),
712 "Change the binding of @var{symbol}'s function slot.")
713 #define FUNC_NAME s_scm_symbol_fset_x
714 {
715 SCM_VALIDATE_SYMBOL (1,s);
716 SCM_SET_SYMBOL_FUNC (s, val);
717 return SCM_UNSPECIFIED;
718 }
719 #undef FUNC_NAME
720
721
722 SCM_DEFINE (scm_symbol_pset_x, "symbol-pset!", 2, 0, 0,
723 (SCM s, SCM val),
724 "Change the binding of @var{symbol}'s property slot.")
725 #define FUNC_NAME s_scm_symbol_pset_x
726 {
727 SCM_VALIDATE_SYMBOL (1,s);
728 SCM_DEFER_INTS;
729 SCM_SET_SYMBOL_PROPS (s, val);
730 SCM_ALLOW_INTS;
731 return SCM_UNSPECIFIED;
732 }
733 #undef FUNC_NAME
734
735
736 SCM_DEFINE (scm_symbol_hash, "symbol-hash", 1, 0, 0,
737 (SCM symbol),
738 "Return a hash value for @var{symbol}.")
739 #define FUNC_NAME s_scm_symbol_hash
740 {
741 SCM_VALIDATE_SYMBOL (1, symbol);
742 return SCM_MAKINUM (SCM_SYMBOL_HASH (symbol));
743 }
744 #undef FUNC_NAME
745
746
747 static void
748 copy_and_prune_obarray (SCM from, SCM to)
749 {
750 int i;
751 int length = SCM_VECTOR_LENGTH (from);
752 for (i = 0; i < length; ++i)
753 {
754 SCM head = SCM_VELTS (from)[i]; /* GC protection */
755 SCM ls = head;
756 SCM res = SCM_EOL;
757 SCM *lloc = &res;
758 while (SCM_NIMP (ls))
759 {
760 if (!SCM_UNBNDP (SCM_CDAR (ls)))
761 {
762 *lloc = scm_cons (SCM_CAR (ls), SCM_EOL);
763 lloc = SCM_CDRLOC (*lloc);
764 }
765 ls = SCM_CDR (ls);
766 }
767 SCM_VELTS (to)[i] = res;
768 }
769 }
770
771
772 SCM_DEFINE (scm_builtin_bindings, "builtin-bindings", 0, 0, 0,
773 (),
774 "Create and return a copy of the global symbol table, removing all\n"
775 "unbound symbols.")
776 #define FUNC_NAME s_scm_builtin_bindings
777 {
778 int length = SCM_VECTOR_LENGTH (scm_symhash);
779 SCM obarray = scm_c_make_hash_table (length);
780 copy_and_prune_obarray (scm_symhash, obarray);
781 return obarray;
782 }
783 #undef FUNC_NAME
784
785
786 #define MAX_PREFIX_LENGTH 30
787
788 static int gensym_counter;
789
790 SCM_DEFINE (scm_gensym, "gensym", 0, 1, 0,
791 (SCM prefix),
792 "Create a new symbol with a name constructed from a prefix and\n"
793 "a counter value. The string @var{prefix} can be specified as\n"
794 "an optional argument. Default prefix is @code{g}. The counter\n"
795 "is increased by 1 at each call. There is no provision for\n"
796 "resetting the counter.")
797 #define FUNC_NAME s_scm_gensym
798 {
799 char buf[MAX_PREFIX_LENGTH + SCM_INTBUFLEN];
800 char *name = buf;
801 int len;
802 if (SCM_UNBNDP (prefix))
803 {
804 name[0] = 'g';
805 len = 1;
806 }
807 else
808 {
809 SCM_VALIDATE_STRING (1, prefix);
810 len = SCM_STRING_LENGTH (prefix);
811 if (len > MAX_PREFIX_LENGTH)
812 name = SCM_MUST_MALLOC (MAX_PREFIX_LENGTH + SCM_INTBUFLEN);
813 strncpy (name, SCM_STRING_CHARS (prefix), len);
814 }
815 {
816 int n_digits = scm_iint2str (gensym_counter++, 10, &name[len]);
817 SCM res = scm_mem2symbol (name, len + n_digits);
818 if (name != buf)
819 scm_must_free (name);
820 return res;
821 }
822 }
823 #undef FUNC_NAME
824
825 static int gentemp_counter;
826
827 SCM_DEFINE (scm_gentemp, "gentemp", 0, 2, 0,
828 (SCM prefix, SCM obarray),
829 "Create a new symbol with a name unique in an obarray.\n"
830 "The name is constructed from an optional string @var{prefix}\n"
831 "and a counter value. The default prefix is @code{t}. The\n"
832 "@var{obarray} is specified as a second optional argument.\n"
833 "Default is the system obarray where all normal symbols are\n"
834 "interned. The counter is increased by 1 at each\n"
835 "call. There is no provision for resetting the counter.")
836 #define FUNC_NAME s_scm_gentemp
837 {
838 char buf[MAX_PREFIX_LENGTH + SCM_INTBUFLEN];
839 char *name = buf;
840 int len, n_digits;
841 if (SCM_UNBNDP (prefix))
842 {
843 name[0] = 't';
844 len = 1;
845 }
846 else
847 {
848 SCM_VALIDATE_STRING (1, prefix);
849 len = SCM_STRING_LENGTH (prefix);
850 if (len > MAX_PREFIX_LENGTH)
851 name = SCM_MUST_MALLOC (MAX_PREFIX_LENGTH + SCM_INTBUFLEN);
852 strncpy (name, SCM_STRING_CHARS (prefix), len);
853 }
854
855 if (SCM_UNBNDP (obarray))
856 obarray = scm_symhash;
857 else
858 SCM_ASSERT ((SCM_VECTORP (obarray) || SCM_WVECTP (obarray)),
859 obarray,
860 SCM_ARG2,
861 FUNC_NAME);
862 do
863 n_digits = scm_iint2str (gentemp_counter++, 10, &name[len]);
864 while (!SCM_FALSEP (scm_intern_obarray_soft (name,
865 len + n_digits,
866 obarray,
867 1)));
868 {
869 SCM vcell = scm_intern_obarray_soft (name,
870 len + n_digits,
871 obarray,
872 0);
873 if (name != buf)
874 scm_must_free (name);
875 return SCM_CAR (vcell);
876 }
877 }
878 #undef FUNC_NAME
879
880
881 void
882 scm_symbols_prehistory ()
883 {
884 symbols = scm_make_weak_key_hash_table (SCM_MAKINUM (1009));
885 scm_permanent_object (symbols);
886 }
887
888
889 void
890 scm_init_symbols ()
891 {
892 gensym_counter = 0;
893 gentemp_counter = 0;
894 #ifndef SCM_MAGIC_SNARFER
895 #include "libguile/symbols.x"
896 #endif
897 }
898
899 /*
900 Local Variables:
901 c-file-style: "gnu"
902 End:
903 */