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