*** 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. */
0f2d19dd
JB
41\f
42
43#include <stdio.h>
44#include "_scm.h"
20e6290e
JB
45#include "chars.h"
46#include "eval.h"
47#include "variable.h"
48#include "alist.h"
b2530d66 49#include "weaks.h"
20e6290e
JB
50
51#include "symbols.h"
0f2d19dd 52
95b88819
GH
53#ifdef HAVE_STRING_H
54#include <string.h>
55#endif
56
0f2d19dd
JB
57\f
58
59
60/* NUM_HASH_BUCKETS is the number of symbol scm_hash table buckets.
61 */
62#define NUM_HASH_BUCKETS 137
63
64\f
65
66
67/* {Symbols}
68 */
69
1cc91f1b 70
0f2d19dd
JB
71unsigned long
72scm_strhash (str, len, n)
73 unsigned char *str;
74 scm_sizet len;
75 unsigned long n;
0f2d19dd
JB
76{
77 if (len > 5)
78 {
79 scm_sizet i = 5;
80 unsigned long h = 264 % n;
81 while (i--)
566011b9 82 h = ((h << 8) + ((unsigned) (scm_downcase (str[h % len])))) % n;
0f2d19dd
JB
83 return h;
84 }
85 else
86 {
87 scm_sizet i = len;
88 unsigned long h = 0;
89 while (i)
566011b9 90 h = ((h << 8) + ((unsigned) (scm_downcase (str[--i])))) % n;
0f2d19dd
JB
91 return h;
92 }
93}
94
95int scm_symhash_dim = NUM_HASH_BUCKETS;
96
97
98/* scm_sym2vcell
99 * looks up the symbol in the symhash table.
100 */
1cc91f1b 101
0f2d19dd
JB
102SCM
103scm_sym2vcell (sym, thunk, definep)
104 SCM sym;
105 SCM thunk;
106 SCM definep;
0f2d19dd
JB
107{
108 if (SCM_NIMP(thunk))
109 {
110 SCM var = scm_apply (thunk, sym, scm_cons(definep, scm_listofnull));
111
112 if (var == SCM_BOOL_F)
113 return SCM_BOOL_F;
114 else
115 {
116 if (SCM_IMP(var) || !SCM_VARIABLEP (var))
117 scm_wta (sym, "strangely interned symbol? ", "");
118 return SCM_VARVCELL (var);
119 }
120 }
121 else
122 {
123 SCM lsym;
124 SCM * lsymp;
125 SCM z;
126 scm_sizet scm_hash = scm_strhash (SCM_UCHARS (sym), (scm_sizet) SCM_LENGTH (sym),
127 (unsigned long) scm_symhash_dim);
128
129 SCM_DEFER_INTS;
130 for (lsym = SCM_VELTS (scm_symhash)[scm_hash]; SCM_NIMP (lsym); lsym = SCM_CDR (lsym))
131 {
132 z = SCM_CAR (lsym);
133 if (SCM_CAR (z) == sym)
134 {
135 SCM_ALLOW_INTS;
136 return z;
137 }
138 }
139
140 for (lsym = *(lsymp = &SCM_VELTS (scm_weak_symhash)[scm_hash]);
141 SCM_NIMP (lsym);
25d8012c 142 lsym = *(lsymp = SCM_CDRLOC (lsym)))
0f2d19dd
JB
143 {
144 z = SCM_CAR (lsym);
145 if (SCM_CAR (z) == sym)
146 {
5aab5d96 147 if (SCM_NFALSEP (definep))
0f2d19dd 148 {
49bc24fe 149 /* Move handle from scm_weak_symhash to scm_symhash. */
0f2d19dd
JB
150 *lsymp = SCM_CDR (lsym);
151 SCM_SETCDR (lsym, SCM_VELTS(scm_symhash)[scm_hash]);
152 SCM_VELTS(scm_symhash)[scm_hash] = lsym;
153 }
154 SCM_ALLOW_INTS;
155 return z;
156 }
157 }
158 SCM_ALLOW_INTS;
159 return scm_wta (sym, "uninterned symbol? ", "");
160 }
161}
162
163/* scm_sym2ovcell
49bc24fe 164 * looks up the symbol in an arbitrary obarray.
0f2d19dd 165 */
1cc91f1b 166
0f2d19dd
JB
167SCM
168scm_sym2ovcell_soft (sym, obarray)
169 SCM sym;
170 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
JB
195SCM
196scm_sym2ovcell (sym, obarray)
197 SCM sym;
198 SCM obarray;
0f2d19dd
JB
199{
200 SCM answer;
201 answer = scm_sym2ovcell_soft (sym, obarray);
202 if (answer != SCM_BOOL_F)
203 return answer;
204 scm_wta (sym, "uninterned symbol? ", "");
205 return SCM_UNSPECIFIED; /* not reached */
206}
207
8ce94504
JB
208/* Intern a symbol whose name is the LEN characters at NAME in OBARRAY.
209
210 OBARRAY should be a vector of lists, indexed by the name's hash
211 value, modulo OBARRAY's length. Each list has the form
212 ((SYMBOL . VALUE) ...), where SYMBOL is a symbol, and VALUE is the
213 value associated with that symbol (in the current module? in the
214 system module?)
215
216 To "intern" a symbol means: if OBARRAY already contains a symbol by
217 that name, return its (SYMBOL . VALUE) pair; otherwise, create a
218 new symbol, add the pair (SYMBOL . SCM_UNDEFINED) to the
219 appropriate list of the OBARRAY, and return the pair.
220
221 If softness is non-zero, don't create a symbol if it isn't already
222 in OBARRAY; instead, just return #f.
223
224 If OBARRAY is SCM_BOOL_F, create a symbol listed in no obarray and
225 return (SYMBOL . SCM_UNDEFINED).
226
227 If OBARRAY is scm_symhash, and that doesn't contain the symbol,
228 check scm_weak_symhash instead. */
229
1cc91f1b 230
0f2d19dd
JB
231SCM
232scm_intern_obarray_soft (name, len, obarray, softness)
3eeba8d4 233 const char *name;
0f2d19dd
JB
234 scm_sizet len;
235 SCM obarray;
236 int softness;
0f2d19dd
JB
237{
238 SCM lsym;
239 SCM z;
240 register scm_sizet i;
241 register unsigned char *tmp;
242 scm_sizet scm_hash;
243
244 SCM_REDEFER_INTS;
245
246 i = len;
247 tmp = (unsigned char *) name;
248
249 if (obarray == SCM_BOOL_F)
250 {
251 scm_hash = scm_strhash (tmp, i, 1019);
252 goto uninterned_symbol;
253 }
254
255 scm_hash = scm_strhash (tmp, i, SCM_LENGTH(obarray));
256
8ce94504
JB
257 /* softness == -1 used to mean that it was known that the symbol
258 wasn't already in the obarray. I don't think there are any
259 callers that use that case any more, but just in case...
260 -- JimB, Oct 1996 */
0f2d19dd 261 if (softness == -1)
8ce94504 262 abort ();
0f2d19dd
JB
263
264 retry_new_obarray:
265 for (lsym = SCM_VELTS (obarray)[scm_hash]; SCM_NIMP (lsym); lsym = SCM_CDR (lsym))
266 {
267 z = SCM_CAR (lsym);
268 z = SCM_CAR (z);
269 tmp = SCM_UCHARS (z);
270 if (SCM_LENGTH (z) != len)
271 goto trynext;
272 for (i = len; i--;)
273 if (((unsigned char *) name)[i] != tmp[i])
274 goto trynext;
275 {
276 SCM a;
277 a = SCM_CAR (lsym);
278 SCM_REALLOW_INTS;
279 return a;
280 }
281 trynext:;
282 }
283
284 if (obarray == scm_symhash)
285 {
286 obarray = scm_weak_symhash;
287 goto retry_new_obarray;
288 }
289
290 uninterned_symbol:
291 if (softness)
292 {
293 SCM_REALLOW_INTS;
294 return SCM_BOOL_F;
295 }
296
0f2d19dd
JB
297 lsym = scm_makfromstr (name, len, SCM_SYMBOL_SLOTS);
298
299 SCM_SETLENGTH (lsym, (long) len, scm_tc7_msymbol);
0f2d19dd 300 SCM_SYMBOL_HASH (lsym) = scm_hash;
3ff63ce6 301 SCM_SYMBOL_PROPS (lsym) = SCM_EOL;
0f2d19dd
JB
302 if (obarray == SCM_BOOL_F)
303 {
304 SCM answer;
305 SCM_REALLOW_INTS;
306 SCM_NEWCELL (answer);
307 SCM_DEFER_INTS;
25d8012c
MD
308 SCM_SETCAR (answer, lsym);
309 SCM_SETCDR (answer, SCM_UNDEFINED);
0f2d19dd
JB
310 SCM_REALLOW_INTS;
311 return answer;
312 }
313 else
314 {
315 SCM a;
316 SCM b;
317
318 SCM_NEWCELL (a);
319 SCM_NEWCELL (b);
320 SCM_SETCAR (a, lsym);
321 SCM_SETCDR (a, SCM_UNDEFINED);
322 SCM_SETCAR (b, a);
323 SCM_SETCDR (b, SCM_VELTS(obarray)[scm_hash]);
324 SCM_VELTS(obarray)[scm_hash] = b;
325 SCM_REALLOW_INTS;
326 return SCM_CAR (b);
327 }
328}
329
1cc91f1b 330
0f2d19dd
JB
331SCM
332scm_intern_obarray (name, len, obarray)
3eeba8d4 333 const char *name;
0f2d19dd
JB
334 scm_sizet len;
335 SCM obarray;
0f2d19dd
JB
336{
337 return scm_intern_obarray_soft (name, len, obarray, 0);
338}
339
340
0f2d19dd
JB
341SCM
342scm_intern (name, len)
3eeba8d4 343 const char *name;
0f2d19dd 344 scm_sizet len;
0f2d19dd
JB
345{
346 return scm_intern_obarray (name, len, scm_symhash);
347}
348
1cc91f1b 349
0f2d19dd
JB
350SCM
351scm_intern0 (name)
3eeba8d4 352 const char * name;
0f2d19dd
JB
353{
354 return scm_intern (name, strlen (name));
355}
356
357
5aab5d96 358/* Intern the symbol named NAME in scm_symhash, NAME is null-terminated. */
0f2d19dd 359SCM
5aab5d96 360scm_sysintern0_no_module_lookup (name)
3eeba8d4 361 const char *name;
0f2d19dd
JB
362{
363 SCM easy_answer;
364 SCM_DEFER_INTS;
365 easy_answer = scm_intern_obarray_soft (name, strlen (name), scm_symhash, 1);
366 if (SCM_NIMP (easy_answer))
367 {
0f2d19dd
JB
368 SCM_ALLOW_INTS;
369 return easy_answer;
370 }
371 else
372 {
373 SCM lsym;
374 scm_sizet len = strlen (name);
375 register unsigned char *tmp = (unsigned char *) name;
376 scm_sizet scm_hash = scm_strhash (tmp, len, (unsigned long) scm_symhash_dim);
377 SCM_NEWCELL (lsym);
378 SCM_SETLENGTH (lsym, (long) len, scm_tc7_ssymbol);
379 SCM_SETCHARS (lsym, name);
5aab5d96 380 lsym = scm_cons (lsym, SCM_UNDEFINED);
0f2d19dd
JB
381 SCM_VELTS (scm_symhash)[scm_hash] = scm_cons (lsym, SCM_VELTS (scm_symhash)[scm_hash]);
382 SCM_ALLOW_INTS;
383 return lsym;
384 }
385}
386
387
9b8d3288
MV
388/* Is it safe to access SCM_TOP_LEVEL_LOOKUP_CLOSURE_VAR?
389 */
390int scm_can_use_top_level_lookup_closure_var;
391
392/* Intern the symbol named NAME in scm_symhash, and give it the value
393 VAL. NAME is null-terminated. Use the current top_level lookup
394 closure to give NAME its value.
395 */
396SCM
397scm_sysintern (name, val)
3eeba8d4 398 const char *name;
9b8d3288 399 SCM val;
5aab5d96
MD
400{
401 SCM vcell = scm_sysintern0 (name);
402 SCM_SETCDR (vcell, val);
403 return vcell;
404}
405
406SCM
407scm_sysintern0 (name)
3eeba8d4 408 const char *name;
9b8d3288
MV
409{
410 SCM lookup_proc;
411 if (scm_can_use_top_level_lookup_closure_var &&
412 SCM_NIMP (lookup_proc = SCM_CDR (scm_top_level_lookup_closure_var)))
413 {
414 SCM sym = SCM_CAR (scm_intern0 (name));
415 SCM vcell = scm_sym2vcell (sym, lookup_proc, SCM_BOOL_T);
416 if (vcell == SCM_BOOL_F)
417 scm_misc_error ("sysintern", "can't define variable", sym);
9b8d3288
MV
418 return vcell;
419 }
420 else
5aab5d96 421 return scm_sysintern0_no_module_lookup (name);
9b8d3288
MV
422}
423
1dd28b3d
MD
424/* Lookup the value of the symbol named by the nul-terminated string
425 NAME in the current module. */
426SCM
427scm_symbol_value0 (name)
3eeba8d4 428 const char *name;
1dd28b3d
MD
429{
430 /* This looks silly - we look up the symbol twice. But it is in
431 fact necessary given the current module system because the module
432 lookup closures are written in scheme which needs real symbols. */
433 SCM symbol = scm_intern_obarray_soft (name, strlen (name), scm_symhash, 0);
434 SCM vcell = scm_sym2vcell (SCM_CAR (symbol),
435 SCM_CDR (scm_top_level_lookup_closure_var),
436 SCM_BOOL_F);
437 if (SCM_FALSEP (vcell))
438 return SCM_UNDEFINED;
439 return SCM_CDR (vcell);
440}
441
0f2d19dd 442SCM_PROC(s_symbol_p, "symbol?", 1, 0, 0, scm_symbol_p);
1cc91f1b 443
0f2d19dd
JB
444SCM
445scm_symbol_p(x)
446 SCM x;
0f2d19dd 447{
49bc24fe
MD
448 if SCM_IMP(x) return SCM_BOOL_F;
449 return SCM_SYMBOLP(x) ? SCM_BOOL_T : SCM_BOOL_F;
0f2d19dd
JB
450}
451
452SCM_PROC(s_symbol_to_string, "symbol->string", 1, 0, 0, scm_symbol_to_string);
1cc91f1b 453
0f2d19dd
JB
454SCM
455scm_symbol_to_string(s)
456 SCM s;
0f2d19dd 457{
49bc24fe
MD
458 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_to_string);
459 return scm_makfromstr(SCM_CHARS(s), (scm_sizet)SCM_LENGTH(s), 0);
0f2d19dd
JB
460}
461
462
463SCM_PROC(s_string_to_symbol, "string->symbol", 1, 0, 0, scm_string_to_symbol);
1cc91f1b 464
0f2d19dd
JB
465SCM
466scm_string_to_symbol(s)
467 SCM s;
0f2d19dd
JB
468{
469 SCM vcell;
470 SCM answer;
471
472 SCM_ASSERT(SCM_NIMP(s) && SCM_ROSTRINGP(s), s, SCM_ARG1, s_string_to_symbol);
473 vcell = scm_intern(SCM_ROCHARS(s), (scm_sizet)SCM_LENGTH(s));
474 answer = SCM_CAR (vcell);
0f2d19dd
JB
475 return answer;
476}
477
478
479SCM_PROC(s_string_to_obarray_symbol, "string->obarray-symbol", 2, 1, 0, scm_string_to_obarray_symbol);
1cc91f1b 480
0f2d19dd
JB
481SCM
482scm_string_to_obarray_symbol(o, s, softp)
483 SCM o;
484 SCM s;
485 SCM softp;
0f2d19dd
JB
486{
487 SCM vcell;
488 SCM answer;
489 int softness;
490
49bc24fe
MD
491 SCM_ASSERT(SCM_NIMP(s) && SCM_ROSTRINGP(s), s, SCM_ARG2,
492 s_string_to_obarray_symbol);
493 SCM_ASSERT((o == SCM_BOOL_F)
494 || (o == SCM_BOOL_T)
495 || (SCM_NIMP(o) && SCM_VECTORP(o)),
496 o,
497 SCM_ARG1,
498 s_string_to_obarray_symbol);
0f2d19dd
JB
499
500 softness = ((softp != SCM_UNDEFINED) && (softp != SCM_BOOL_F));
501 /* iron out some screwy calling conventions */
502 if (o == SCM_BOOL_F)
503 o = scm_symhash;
504 else if (o == SCM_BOOL_T)
505 o = SCM_BOOL_F;
506
49bc24fe
MD
507 vcell = scm_intern_obarray_soft (SCM_ROCHARS(s),
508 (scm_sizet)SCM_ROLENGTH(s),
509 o,
510 softness);
0f2d19dd
JB
511 if (vcell == SCM_BOOL_F)
512 return vcell;
513 answer = SCM_CAR (vcell);
0f2d19dd
JB
514 return answer;
515}
516
517SCM_PROC(s_intern_symbol, "intern-symbol", 2, 0, 0, scm_intern_symbol);
1cc91f1b 518
0f2d19dd
JB
519SCM
520scm_intern_symbol(o, s)
521 SCM o;
522 SCM s;
0f2d19dd 523{
49bc24fe
MD
524 scm_sizet hval;
525 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_intern_symbol);
526 if (o == SCM_BOOL_F)
527 o = scm_symhash;
528 SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_intern_symbol);
529 hval = scm_strhash (SCM_UCHARS (s), SCM_LENGTH (s), SCM_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_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;
0f2d19dd
JB
551}
552
553SCM_PROC(s_unintern_symbol, "unintern-symbol", 2, 0, 0, scm_unintern_symbol);
1cc91f1b 554
0f2d19dd
JB
555SCM
556scm_unintern_symbol(o, s)
557 SCM o;
558 SCM s;
0f2d19dd 559{
49bc24fe
MD
560 scm_sizet hval;
561 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_unintern_symbol);
562 if (o == SCM_BOOL_F)
563 o = scm_symhash;
564 SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_unintern_symbol);
565 hval = scm_strhash (SCM_UCHARS (s), SCM_LENGTH (s), SCM_LENGTH(o));
566 SCM_DEFER_INTS;
567 {
568 SCM lsym_follow;
569 SCM lsym;
570 SCM sym;
571 for (lsym = SCM_VELTS (o)[hval], lsym_follow = SCM_BOOL_F;
572 SCM_NIMP (lsym);
573 lsym_follow = lsym, lsym = SCM_CDR (lsym))
574 {
575 sym = SCM_CAR (lsym);
576 if (SCM_CAR (sym) == s)
577 {
578 /* Found the symbol to unintern. */
579 if (lsym_follow == SCM_BOOL_F)
580 SCM_VELTS(o)[hval] = lsym;
581 else
25d8012c 582 SCM_SETCDR (lsym_follow, SCM_CDR(lsym));
49bc24fe
MD
583 SCM_ALLOW_INTS;
584 return SCM_BOOL_T;
585 }
586 }
587 }
588 SCM_ALLOW_INTS;
589 return SCM_BOOL_F;
0f2d19dd
JB
590}
591
592SCM_PROC(s_symbol_binding, "symbol-binding", 2, 0, 0, scm_symbol_binding);
1cc91f1b 593
0f2d19dd
JB
594SCM
595scm_symbol_binding (o, s)
596 SCM o;
597 SCM s;
0f2d19dd
JB
598{
599 SCM vcell;
600 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_symbol_binding);
601 if (o == SCM_BOOL_F)
602 o = scm_symhash;
603 SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_symbol_binding);
604 vcell = scm_sym2ovcell (s, o);
605 return SCM_CDR(vcell);
606}
607
608
609SCM_PROC(s_symbol_interned_p, "symbol-interned?", 2, 0, 0, scm_symbol_interned_p);
1cc91f1b 610
0f2d19dd
JB
611SCM
612scm_symbol_interned_p (o, s)
613 SCM o;
614 SCM s;
0f2d19dd
JB
615{
616 SCM vcell;
617 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_symbol_interned_p);
618 if (o == SCM_BOOL_F)
619 o = scm_symhash;
620 SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_symbol_interned_p);
621 vcell = scm_sym2ovcell_soft (s, o);
622 if (SCM_IMP(vcell) && (o == scm_symhash))
623 vcell = scm_sym2ovcell_soft (s, scm_weak_symhash);
624 return (SCM_NIMP(vcell)
625 ? SCM_BOOL_T
626 : SCM_BOOL_F);
627}
628
629
630SCM_PROC(s_symbol_bound_p, "symbol-bound?", 2, 0, 0, scm_symbol_bound_p);
1cc91f1b 631
0f2d19dd
JB
632SCM
633scm_symbol_bound_p (o, s)
634 SCM o;
635 SCM s;
0f2d19dd
JB
636{
637 SCM vcell;
638 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_symbol_bound_p);
639 if (o == SCM_BOOL_F)
640 o = scm_symhash;
641 SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_symbol_bound_p);
642 vcell = scm_sym2ovcell_soft (s, o);
643 return (( SCM_NIMP(vcell)
644 && (SCM_CDR(vcell) != SCM_UNDEFINED))
645 ? SCM_BOOL_T
646 : SCM_BOOL_F);
647}
648
649
650SCM_PROC(s_symbol_set_x, "symbol-set!", 3, 0, 0, scm_symbol_set_x);
1cc91f1b 651
0f2d19dd
JB
652SCM
653scm_symbol_set_x (o, s, v)
654 SCM o;
655 SCM s;
656 SCM v;
0f2d19dd
JB
657{
658 SCM vcell;
659 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_symbol_set_x);
660 if (o == SCM_BOOL_F)
661 o = scm_symhash;
662 SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_symbol_set_x);
663 vcell = scm_sym2ovcell (s, o);
25d8012c 664 SCM_SETCDR (vcell, v);
0f2d19dd
JB
665 return SCM_UNSPECIFIED;
666}
667
668static void
669msymbolize (s)
670 SCM s;
671{
672 SCM string;
673 string = scm_makfromstr (SCM_CHARS (s), SCM_LENGTH (s), SCM_SYMBOL_SLOTS);
674 SCM_SETCHARS (s, SCM_CHARS (string));
675 SCM_SETLENGTH (s, SCM_LENGTH (s), scm_tc7_msymbol);
25d8012c
MD
676 SCM_SETCDR (string, SCM_EOL);
677 SCM_SETCAR (string, SCM_EOL);
77a6036b 678 SCM_SYMBOL_PROPS (s) = SCM_EOL;
b2530d66
MD
679 /* If it's a tc7_ssymbol, it comes from scm_symhash */
680 SCM_SYMBOL_HASH (s) = scm_strhash (SCM_UCHARS (s),
681 (scm_sizet) SCM_LENGTH (s),
682 SCM_LENGTH (scm_symhash));
0f2d19dd
JB
683}
684
685
686SCM_PROC(s_symbol_fref, "symbol-fref", 1, 0, 0, scm_symbol_fref);
1cc91f1b 687
0f2d19dd
JB
688SCM
689scm_symbol_fref (s)
690 SCM s;
0f2d19dd
JB
691{
692 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_fref);
693 SCM_DEFER_INTS;
694 if (SCM_TYP7(s) == scm_tc7_ssymbol)
695 msymbolize (s);
696 SCM_ALLOW_INTS;
697 return SCM_SYMBOL_FUNC (s);
698}
699
700
701SCM_PROC(s_symbol_pref, "symbol-pref", 1, 0, 0, scm_symbol_pref);
1cc91f1b 702
0f2d19dd
JB
703SCM
704scm_symbol_pref (s)
705 SCM s;
0f2d19dd
JB
706{
707 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_pref);
708 SCM_DEFER_INTS;
709 if (SCM_TYP7(s) == scm_tc7_ssymbol)
710 msymbolize (s);
711 SCM_ALLOW_INTS;
712 return SCM_SYMBOL_PROPS (s);
713}
714
715
716SCM_PROC(s_symbol_fset_x, "symbol-fset!", 2, 0, 0, scm_symbol_fset_x);
1cc91f1b 717
0f2d19dd
JB
718SCM
719scm_symbol_fset_x (s, val)
720 SCM s;
721 SCM val;
0f2d19dd
JB
722{
723 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_fset_x);
724 SCM_DEFER_INTS;
725 if (SCM_TYP7(s) == scm_tc7_ssymbol)
726 msymbolize (s);
727 SCM_ALLOW_INTS;
728 SCM_SYMBOL_FUNC (s) = val;
729 return SCM_UNSPECIFIED;
730}
731
732
733SCM_PROC(s_symbol_pset_x, "symbol-pset!", 2, 0, 0, scm_symbol_pset_x);
1cc91f1b 734
0f2d19dd
JB
735SCM
736scm_symbol_pset_x (s, val)
737 SCM s;
738 SCM val;
0f2d19dd
JB
739{
740 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_pset_x);
741 SCM_DEFER_INTS;
742 if (SCM_TYP7(s) == scm_tc7_ssymbol)
743 msymbolize (s);
744 SCM_SYMBOL_PROPS (s) = val;
745 SCM_ALLOW_INTS;
746 return SCM_UNSPECIFIED;
747}
748
749
750SCM_PROC(s_symbol_hash, "symbol-hash", 1, 0, 0, scm_symbol_hash);
1cc91f1b 751
0f2d19dd
JB
752SCM
753scm_symbol_hash (s)
754 SCM s;
0f2d19dd
JB
755{
756 SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_hash);
b2530d66
MD
757 if (SCM_TYP7(s) == scm_tc7_ssymbol)
758 msymbolize (s);
0f2d19dd
JB
759 return SCM_MAKINUM ((unsigned long)s ^ SCM_SYMBOL_HASH (s));
760}
761
762
b2530d66
MD
763static void copy_and_prune_obarray SCM_P ((SCM from, SCM to));
764
765static void
766copy_and_prune_obarray (from, to)
767 SCM from;
768 SCM to;
769{
770 int i;
771 int length = SCM_LENGTH (from);
772 for (i = 0; i < length; ++i)
773 {
774 SCM head = SCM_VELTS (from)[i]; /* GC protection */
775 SCM ls = head;
776 SCM res = SCM_EOL;
777 SCM *lloc = &res;
778 while (SCM_NIMP (ls))
779 {
780 if (!SCM_UNBNDP (SCM_CDAR (ls)))
781 {
782 *lloc = scm_cons (SCM_CAR (ls), SCM_EOL);
783 lloc = SCM_CDRLOC (*lloc);
784 }
785 ls = SCM_CDR (ls);
786 }
787 SCM_VELTS (to)[i] = res;
788 }
789}
790
791
792SCM_PROC(s_builtin_bindings, "builtin-bindings", 0, 0, 0, scm_builtin_bindings);
793
794SCM
795scm_builtin_bindings ()
796{
797 int length = SCM_LENGTH (scm_symhash);
a8741caa 798 SCM obarray = scm_make_vector (SCM_MAKINUM (length), SCM_EOL);
b2530d66
MD
799 copy_and_prune_obarray (scm_symhash, obarray);
800 return obarray;
801}
802
803
804SCM_PROC(s_builtin_weak_bindings, "builtin-weak-bindings", 0, 0, 0, scm_builtin_weak_bindings);
805
806SCM
807scm_builtin_weak_bindings ()
808{
809 int length = SCM_LENGTH (scm_weak_symhash);
810 SCM obarray = scm_make_doubly_weak_hash_table (SCM_MAKINUM (length));
811 copy_and_prune_obarray (scm_weak_symhash, obarray);
812 return obarray;
813}
814
1ff4df7a
MD
815static int gensym_counter;
816static SCM gensym_prefix;
b2530d66 817
1ff4df7a
MD
818/*fixme* Optimize */
819SCM_PROC (s_gensym, "gensym", 0, 2, 0, scm_gensym);
820
821SCM
822scm_gensym (name, obarray)
823 SCM name;
824 SCM obarray;
825{
826 SCM new;
827 if (SCM_UNBNDP (name))
828 name = gensym_prefix;
829 else
aea5b792
MD
830 SCM_ASSERT (SCM_NIMP (name) && SCM_ROSTRINGP (name),
831 name, SCM_ARG1, s_gensym);
1ff4df7a
MD
832 new = name;
833 if (SCM_UNBNDP (obarray))
834 {
835 obarray = SCM_BOOL_F;
836 goto skip_test;
837 }
838 else
839 SCM_ASSERT (SCM_NIMP (obarray)
840 && (SCM_VECTORP (obarray) || SCM_WVECTP (obarray)),
841 obarray,
842 SCM_ARG2,
843 s_gensym);
844 while (scm_string_to_obarray_symbol (obarray, new, SCM_BOOL_T)
845 != SCM_BOOL_F)
846 skip_test:
847 new = scm_string_append
848 (scm_cons2 (name,
849 scm_number_to_string (SCM_MAKINUM (gensym_counter++),
850 SCM_UNDEFINED),
851 SCM_EOL));
852 return scm_string_to_obarray_symbol (obarray, new, SCM_BOOL_F);
853}
1cc91f1b 854
0f2d19dd
JB
855void
856scm_init_symbols ()
0f2d19dd 857{
1ff4df7a
MD
858 gensym_counter = 0;
859 gensym_prefix = scm_permanent_object (scm_makfrom0str ("%%gensym"));
0f2d19dd
JB
860#include "symbols.x"
861}