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