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