* Makefile.am (DEFS): Added. automake adds -I options to DEFS,
[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>
a0599745
MD
48#include "libguile/_scm.h"
49#include "libguile/chars.h"
50#include "libguile/eval.h"
51#include "libguile/variable.h"
52#include "libguile/alist.h"
53#include "libguile/root.h"
54#include "libguile/strings.h"
55#include "libguile/vectors.h"
56#include "libguile/weaks.h"
57
58#include "libguile/validate.h"
59#include "libguile/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
95c9e176 80scm_strhash (const 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
bc66755e 114 if (SCM_FALSEP (var))
0f2d19dd
JB
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);
bc66755e 135 if (SCM_EQ_P (SCM_CAR (z), sym))
0f2d19dd
JB
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);
bc66755e 147 if (SCM_EQ_P (SCM_CAR (z), sym))
0f2d19dd 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);
bc66755e 184 if (SCM_EQ_P (SCM_CAR (z), sym))
0f2d19dd
JB
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);
bc66755e 200 if (!SCM_FALSEP (answer))
0f2d19dd
JB
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
bc66755e 240 if (SCM_FALSEP (obarray))
0f2d19dd 241 {
95c9e176 242 scm_hash = scm_strhash (name, len, 1019);
0f2d19dd
JB
243 goto uninterned_symbol;
244 }
245
95c9e176 246 scm_hash = scm_strhash (name, len, SCM_LENGTH (obarray));
0f2d19dd 247
8ce94504
JB
248 /* softness == -1 used to mean that it was known that the symbol
249 wasn't already in the obarray. I don't think there are any
250 callers that use that case any more, but just in case...
251 -- JimB, Oct 1996 */
0f2d19dd 252 if (softness == -1)
8ce94504 253 abort ();
0f2d19dd
JB
254
255 retry_new_obarray:
256 for (lsym = SCM_VELTS (obarray)[scm_hash]; SCM_NIMP (lsym); lsym = SCM_CDR (lsym))
257 {
258 z = SCM_CAR (lsym);
259 z = SCM_CAR (z);
260 tmp = SCM_UCHARS (z);
261 if (SCM_LENGTH (z) != len)
262 goto trynext;
263 for (i = len; i--;)
264 if (((unsigned char *) name)[i] != tmp[i])
265 goto trynext;
266 {
267 SCM a;
268 a = SCM_CAR (lsym);
269 SCM_REALLOW_INTS;
270 return a;
271 }
272 trynext:;
273 }
274
bc66755e 275 if (SCM_EQ_P (obarray, scm_symhash))
0f2d19dd
JB
276 {
277 obarray = scm_weak_symhash;
278 goto retry_new_obarray;
279 }
280
281 uninterned_symbol:
282 if (softness)
283 {
284 SCM_REALLOW_INTS;
285 return SCM_BOOL_F;
286 }
287
0f2d19dd
JB
288 lsym = scm_makfromstr (name, len, SCM_SYMBOL_SLOTS);
289
290 SCM_SETLENGTH (lsym, (long) len, scm_tc7_msymbol);
0f2d19dd 291 SCM_SYMBOL_HASH (lsym) = scm_hash;
cf551a2b 292 SCM_SET_SYMBOL_PROPS (lsym, SCM_EOL);
bc66755e 293 if (SCM_FALSEP (obarray))
0f2d19dd
JB
294 {
295 SCM answer;
296 SCM_REALLOW_INTS;
297 SCM_NEWCELL (answer);
298 SCM_DEFER_INTS;
25d8012c
MD
299 SCM_SETCAR (answer, lsym);
300 SCM_SETCDR (answer, SCM_UNDEFINED);
0f2d19dd
JB
301 SCM_REALLOW_INTS;
302 return answer;
303 }
304 else
305 {
306 SCM a;
307 SCM b;
308
309 SCM_NEWCELL (a);
310 SCM_NEWCELL (b);
311 SCM_SETCAR (a, lsym);
312 SCM_SETCDR (a, SCM_UNDEFINED);
313 SCM_SETCAR (b, a);
314 SCM_SETCDR (b, SCM_VELTS(obarray)[scm_hash]);
315 SCM_VELTS(obarray)[scm_hash] = b;
316 SCM_REALLOW_INTS;
317 return SCM_CAR (b);
318 }
319}
320
1cc91f1b 321
0f2d19dd 322SCM
1bbd0b84 323scm_intern_obarray (const char *name,scm_sizet len,SCM obarray)
0f2d19dd
JB
324{
325 return scm_intern_obarray_soft (name, len, obarray, 0);
326}
327
328
0f2d19dd 329SCM
1bbd0b84 330scm_intern (const char *name,scm_sizet len)
0f2d19dd
JB
331{
332 return scm_intern_obarray (name, len, scm_symhash);
333}
334
1cc91f1b 335
0f2d19dd 336SCM
1bbd0b84 337scm_intern0 (const char * name)
0f2d19dd
JB
338{
339 return scm_intern (name, strlen (name));
340}
341
342
5aab5d96 343/* Intern the symbol named NAME in scm_symhash, NAME is null-terminated. */
0f2d19dd 344SCM
1bbd0b84 345scm_sysintern0_no_module_lookup (const char *name)
0f2d19dd
JB
346{
347 SCM easy_answer;
348 SCM_DEFER_INTS;
349 easy_answer = scm_intern_obarray_soft (name, strlen (name), scm_symhash, 1);
350 if (SCM_NIMP (easy_answer))
351 {
0f2d19dd
JB
352 SCM_ALLOW_INTS;
353 return easy_answer;
354 }
355 else
356 {
357 SCM lsym;
358 scm_sizet len = strlen (name);
95c9e176 359 scm_sizet scm_hash = scm_strhash (name, len, (unsigned long) scm_symhash_dim);
0f2d19dd
JB
360 SCM_NEWCELL (lsym);
361 SCM_SETLENGTH (lsym, (long) len, scm_tc7_ssymbol);
362 SCM_SETCHARS (lsym, name);
5aab5d96 363 lsym = scm_cons (lsym, SCM_UNDEFINED);
0f2d19dd
JB
364 SCM_VELTS (scm_symhash)[scm_hash] = scm_cons (lsym, SCM_VELTS (scm_symhash)[scm_hash]);
365 SCM_ALLOW_INTS;
366 return lsym;
367 }
368}
369
370
9b8d3288
MV
371/* Is it safe to access SCM_TOP_LEVEL_LOOKUP_CLOSURE_VAR?
372 */
373int scm_can_use_top_level_lookup_closure_var;
374
375/* Intern the symbol named NAME in scm_symhash, and give it the value
376 VAL. NAME is null-terminated. Use the current top_level lookup
377 closure to give NAME its value.
378 */
379SCM
1bbd0b84 380scm_sysintern (const char *name, SCM val)
5aab5d96
MD
381{
382 SCM vcell = scm_sysintern0 (name);
383 SCM_SETCDR (vcell, val);
384 return vcell;
385}
386
387SCM
1bbd0b84 388scm_sysintern0 (const char *name)
9b8d3288
MV
389{
390 SCM lookup_proc;
391 if (scm_can_use_top_level_lookup_closure_var &&
392 SCM_NIMP (lookup_proc = SCM_CDR (scm_top_level_lookup_closure_var)))
393 {
394 SCM sym = SCM_CAR (scm_intern0 (name));
395 SCM vcell = scm_sym2vcell (sym, lookup_proc, SCM_BOOL_T);
bc66755e 396 if (SCM_FALSEP (vcell))
5d2d2ffc 397 scm_misc_error ("sysintern0", "can't define variable", sym);
9b8d3288
MV
398 return vcell;
399 }
400 else
5aab5d96 401 return scm_sysintern0_no_module_lookup (name);
9b8d3288
MV
402}
403
1dd28b3d
MD
404/* Lookup the value of the symbol named by the nul-terminated string
405 NAME in the current module. */
406SCM
1bbd0b84 407scm_symbol_value0 (const char *name)
1dd28b3d
MD
408{
409 /* This looks silly - we look up the symbol twice. But it is in
410 fact necessary given the current module system because the module
411 lookup closures are written in scheme which needs real symbols. */
412 SCM symbol = scm_intern_obarray_soft (name, strlen (name), scm_symhash, 0);
413 SCM vcell = scm_sym2vcell (SCM_CAR (symbol),
414 SCM_CDR (scm_top_level_lookup_closure_var),
415 SCM_BOOL_F);
416 if (SCM_FALSEP (vcell))
417 return SCM_UNDEFINED;
418 return SCM_CDR (vcell);
419}
420
3b3b36dd 421SCM_DEFINE (scm_symbol_p, "symbol?", 1, 0, 0,
5ffe9968
GB
422 (SCM obj),
423 "Returns @t{#t} if @var{obj} is a symbol, otherwise returns @t{#f}. (r5rs)")
1bbd0b84 424#define FUNC_NAME s_scm_symbol_p
0f2d19dd 425{
5ffe9968
GB
426 if SCM_IMP(obj) return SCM_BOOL_F;
427 return SCM_BOOL(SCM_SYMBOLP(obj));
0f2d19dd 428}
1bbd0b84 429#undef FUNC_NAME
0f2d19dd 430
3b3b36dd 431SCM_DEFINE (scm_symbol_to_string, "symbol->string", 1, 0, 0,
1bbd0b84 432 (SCM s),
5ffe9968
GB
433 "Returns the name of @var{symbol} as a string. If the symbol was part of\n"
434 "an object returned as the value of a literal expression\n"
435 "(section @pxref{Literal expressions}) or by a call to the @samp{read} procedure,\n"
436 "and its name contains alphabetic characters, then the string returned\n"
437 "will contain characters in the implementation's preferred standard\n"
438 "case---some implementations will prefer upper case, others lower case.\n"
439 "If the symbol was returned by @samp{string->symbol}, the case of\n"
440 "characters in the string returned will be the same as the case in the\n"
441 "string that was passed to @samp{string->symbol}. It is an error\n"
442 "to apply mutation procedures like @code{string-set!} to strings returned\n"
443 "by this procedure. (r5rs)\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{(symbol->string 'flying-fish) \n"
448 " ==> \"flying-fish\"\n"
449 "(symbol->string 'Martin) ==> \"martin\"\n"
450 "(symbol->string\n"
451 " (string->symbol "Malvina")) \n"
452 " ==> \"Malvina\"\n"
453 "}\n"
454 "@end format")
1bbd0b84 455#define FUNC_NAME s_scm_symbol_to_string
0f2d19dd 456{
3b3b36dd 457 SCM_VALIDATE_SYMBOL (1,s);
49bc24fe 458 return scm_makfromstr(SCM_CHARS(s), (scm_sizet)SCM_LENGTH(s), 0);
0f2d19dd 459}
1bbd0b84 460#undef FUNC_NAME
0f2d19dd
JB
461
462
3b3b36dd 463SCM_DEFINE (scm_string_to_symbol, "string->symbol", 1, 0, 0,
1bbd0b84 464 (SCM s),
5ffe9968
GB
465 "Returns the symbol whose name is @var{string}. This procedure can\n"
466 "create symbols with names containing special characters or letters in\n"
467 "the non-standard case, but it is usually a bad idea to create such\n"
468 "symbols because in some implementations of Scheme they cannot be read as\n"
469 "themselves. See @samp{symbol->string}.\n\n"
470 "The following examples assume that the implementation's standard case is\n"
471 "lower case:\n\n"
472"@format\n"
473"@t{(eq? 'mISSISSIppi 'mississippi) \n"
474" ==> #t\n"
475"(string->symbol \"mISSISSIppi\") \n"
476" ==>\n"
477" @r{}the symbol with name \"mISSISSIppi\"\n"
478"(eq? 'bitBlt (string->symbol \"bitBlt\")) \n"
479" ==> #f\n"
480"(eq? 'JollyWog\n"
481" (string->symbol\n"
482" (symbol->string 'JollyWog))) \n"
483" ==> #t\n"
484"(string=? \"K. Harper, M.D.\"\n"
485" (symbol->string\n"
486" (string->symbol \"K. Harper, M.D.\"))) \n"
487" ==> #t\n"
488"}\n"
489 "@end format")
1bbd0b84 490#define FUNC_NAME s_scm_string_to_symbol
0f2d19dd
JB
491{
492 SCM vcell;
493 SCM answer;
494
3b3b36dd 495 SCM_VALIDATE_ROSTRING (1,s);
0f2d19dd
JB
496 vcell = scm_intern(SCM_ROCHARS(s), (scm_sizet)SCM_LENGTH(s));
497 answer = SCM_CAR (vcell);
0f2d19dd
JB
498 return answer;
499}
1bbd0b84 500#undef FUNC_NAME
0f2d19dd
JB
501
502
3b3b36dd 503SCM_DEFINE (scm_string_to_obarray_symbol, "string->obarray-symbol", 2, 1, 0,
1bbd0b84 504 (SCM o, SCM s, SCM softp),
a3c8b9fc
MD
505 "Intern a new symbol in @var{obarray}, a symbol table, with name\n"
506 "@var{string}.\n\n"
507 "If @var{obarray} is @code{#f}, use the default system symbol table. If\n"
508 "@var{obarray} is @code{#t}, the symbol should not be interned in any\n"
509 "symbol table; merely return the pair (@var{symbol}\n"
510 ". @var{#<undefined>}).\n\n"
511 "The @var{soft?} argument determines whether new symbol table entries\n"
512 "should be created when the specified symbol is not already present in\n"
513 "@var{obarray}. If @var{soft?} is specified and is a true value, then\n"
514 "new entries should not be added for symbols not already present in the\n"
515 "table; instead, simply return @code{#f}.")
1bbd0b84 516#define FUNC_NAME s_scm_string_to_obarray_symbol
0f2d19dd
JB
517{
518 SCM vcell;
519 SCM answer;
520 int softness;
521
3b3b36dd 522 SCM_VALIDATE_ROSTRING (2,s);
bc66755e 523 SCM_ASSERT (SCM_BOOLP (o) || SCM_VECTORP (o), o, SCM_ARG1, FUNC_NAME);
0f2d19dd 524
bc66755e 525 softness = (!SCM_UNBNDP (softp) && !SCM_FALSEP(softp));
0f2d19dd 526 /* iron out some screwy calling conventions */
bc66755e 527 if (SCM_FALSEP (o))
0f2d19dd 528 o = scm_symhash;
bc66755e 529 else if (SCM_TRUE_P (o))
0f2d19dd
JB
530 o = SCM_BOOL_F;
531
49bc24fe
MD
532 vcell = scm_intern_obarray_soft (SCM_ROCHARS(s),
533 (scm_sizet)SCM_ROLENGTH(s),
534 o,
535 softness);
bc66755e 536 if (SCM_FALSEP (vcell))
0f2d19dd
JB
537 return vcell;
538 answer = SCM_CAR (vcell);
0f2d19dd
JB
539 return answer;
540}
1bbd0b84 541#undef FUNC_NAME
0f2d19dd 542
3b3b36dd 543SCM_DEFINE (scm_intern_symbol, "intern-symbol", 2, 0, 0,
1bbd0b84 544 (SCM o, SCM s),
b380b885
MD
545 "Add a new symbol to @var{obarray} with name @var{string}, bound to an\n"
546 "unspecified initial value. The symbol table is not modified if a symbol\n"
547 "with this name is already present.")
1bbd0b84 548#define FUNC_NAME s_scm_intern_symbol
0f2d19dd 549{
49bc24fe 550 scm_sizet hval;
3b3b36dd 551 SCM_VALIDATE_SYMBOL (2,s);
bc66755e 552 if (SCM_FALSEP (o))
49bc24fe 553 o = scm_symhash;
3b3b36dd 554 SCM_VALIDATE_VECTOR (1,o);
49bc24fe
MD
555 hval = scm_strhash (SCM_UCHARS (s), SCM_LENGTH (s), SCM_LENGTH(o));
556 /* If the symbol is already interned, simply return. */
557 SCM_REDEFER_INTS;
558 {
559 SCM lsym;
560 SCM sym;
561 for (lsym = SCM_VELTS (o)[hval];
562 SCM_NIMP (lsym);
563 lsym = SCM_CDR (lsym))
564 {
565 sym = SCM_CAR (lsym);
bc66755e 566 if (SCM_EQ_P (SCM_CAR (sym), s))
49bc24fe
MD
567 {
568 SCM_REALLOW_INTS;
569 return SCM_UNSPECIFIED;
570 }
571 }
572 SCM_VELTS (o)[hval] =
573 scm_acons (s, SCM_UNDEFINED, SCM_VELTS (o)[hval]);
574 }
575 SCM_REALLOW_INTS;
576 return SCM_UNSPECIFIED;
0f2d19dd 577}
1bbd0b84 578#undef FUNC_NAME
0f2d19dd 579
3b3b36dd 580SCM_DEFINE (scm_unintern_symbol, "unintern-symbol", 2, 0, 0,
1bbd0b84 581 (SCM o, SCM s),
b380b885
MD
582 "Remove the symbol with name @var{string} from @var{obarray}. This\n"
583 "function returns @code{#t} if the symbol was present and @code{#f}\n"
584 "otherwise.")
1bbd0b84 585#define FUNC_NAME s_scm_unintern_symbol
0f2d19dd 586{
49bc24fe 587 scm_sizet hval;
3b3b36dd 588 SCM_VALIDATE_SYMBOL (2,s);
bc66755e 589 if (SCM_FALSEP (o))
49bc24fe 590 o = scm_symhash;
3b3b36dd 591 SCM_VALIDATE_VECTOR (1,o);
49bc24fe
MD
592 hval = scm_strhash (SCM_UCHARS (s), SCM_LENGTH (s), SCM_LENGTH(o));
593 SCM_DEFER_INTS;
594 {
595 SCM lsym_follow;
596 SCM lsym;
597 SCM sym;
598 for (lsym = SCM_VELTS (o)[hval], lsym_follow = SCM_BOOL_F;
599 SCM_NIMP (lsym);
600 lsym_follow = lsym, lsym = SCM_CDR (lsym))
601 {
602 sym = SCM_CAR (lsym);
bc66755e 603 if (SCM_EQ_P (SCM_CAR (sym), s))
49bc24fe
MD
604 {
605 /* Found the symbol to unintern. */
bc66755e 606 if (SCM_FALSEP (lsym_follow))
49bc24fe
MD
607 SCM_VELTS(o)[hval] = lsym;
608 else
25d8012c 609 SCM_SETCDR (lsym_follow, SCM_CDR(lsym));
49bc24fe
MD
610 SCM_ALLOW_INTS;
611 return SCM_BOOL_T;
612 }
613 }
614 }
615 SCM_ALLOW_INTS;
616 return SCM_BOOL_F;
0f2d19dd 617}
1bbd0b84 618#undef FUNC_NAME
0f2d19dd 619
3b3b36dd 620SCM_DEFINE (scm_symbol_binding, "symbol-binding", 2, 0, 0,
1bbd0b84 621 (SCM o, SCM s),
b380b885
MD
622 "Look up in @var{obarray} the symbol whose name is @var{string}, and\n"
623 "return the value to which it is bound. If @var{obarray} is @code{#f},\n"
624 "use the global symbol table. If @var{string} is not interned in\n"
625 "@var{obarray}, an error is signalled.")
1bbd0b84 626#define FUNC_NAME s_scm_symbol_binding
0f2d19dd
JB
627{
628 SCM vcell;
3b3b36dd 629 SCM_VALIDATE_SYMBOL (2,s);
bc66755e 630 if (SCM_FALSEP (o))
0f2d19dd 631 o = scm_symhash;
3b3b36dd 632 SCM_VALIDATE_VECTOR (1,o);
0f2d19dd
JB
633 vcell = scm_sym2ovcell (s, o);
634 return SCM_CDR(vcell);
635}
1bbd0b84 636#undef FUNC_NAME
0f2d19dd
JB
637
638
3b3b36dd 639SCM_DEFINE (scm_symbol_interned_p, "symbol-interned?", 2, 0, 0,
1bbd0b84 640 (SCM o, SCM s),
b380b885
MD
641 "Return @var{#t} if @var{obarray} contains a symbol with name\n"
642 "@var{string}, and @var{#f} otherwise.")
1bbd0b84 643#define FUNC_NAME s_scm_symbol_interned_p
0f2d19dd
JB
644{
645 SCM vcell;
3b3b36dd 646 SCM_VALIDATE_SYMBOL (2,s);
bc66755e 647 if (SCM_FALSEP (o))
0f2d19dd 648 o = scm_symhash;
3b3b36dd 649 SCM_VALIDATE_VECTOR (1,o);
0f2d19dd 650 vcell = scm_sym2ovcell_soft (s, o);
bc66755e 651 if (SCM_IMP (vcell) && SCM_EQ_P (o, scm_symhash))
0f2d19dd
JB
652 vcell = scm_sym2ovcell_soft (s, scm_weak_symhash);
653 return (SCM_NIMP(vcell)
654 ? SCM_BOOL_T
655 : SCM_BOOL_F);
656}
1bbd0b84 657#undef FUNC_NAME
0f2d19dd
JB
658
659
3b3b36dd 660SCM_DEFINE (scm_symbol_bound_p, "symbol-bound?", 2, 0, 0,
1bbd0b84 661 (SCM o, SCM s),
b380b885
MD
662 "Return @var{#t} if @var{obarray} contains a symbol with name\n"
663 "@var{string} bound to a defined value. This differs from\n"
664 "@var{symbol-bound?} in that the mere mention of a symbol usually causes\n"
665 "it to be interned; @code{symbol-bound?} determines whether a symbol has\n"
666 "been given any meaningful value.")
1bbd0b84 667#define FUNC_NAME s_scm_symbol_bound_p
0f2d19dd
JB
668{
669 SCM vcell;
3b3b36dd 670 SCM_VALIDATE_SYMBOL (2,s);
bc66755e 671 if (SCM_FALSEP (o))
0f2d19dd 672 o = scm_symhash;
3b3b36dd 673 SCM_VALIDATE_VECTOR (1,o);
0f2d19dd 674 vcell = scm_sym2ovcell_soft (s, o);
bc66755e 675 return SCM_BOOL (SCM_NIMP (vcell) && !SCM_UNBNDP (SCM_CDR (vcell)));
0f2d19dd 676}
1bbd0b84 677#undef FUNC_NAME
0f2d19dd
JB
678
679
3b3b36dd 680SCM_DEFINE (scm_symbol_set_x, "symbol-set!", 3, 0, 0,
1bbd0b84 681 (SCM o, SCM s, SCM v),
b380b885
MD
682 "Find the symbol in @var{obarray} whose name is @var{string}, and rebind\n"
683 "it to @var{value}. An error is signalled if @var{string} is not present\n"
684 "in @var{obarray}.")
1bbd0b84 685#define FUNC_NAME s_scm_symbol_set_x
0f2d19dd
JB
686{
687 SCM vcell;
3b3b36dd 688 SCM_VALIDATE_SYMBOL (2,s);
bc66755e 689 if (SCM_FALSEP (o))
0f2d19dd 690 o = scm_symhash;
3b3b36dd 691 SCM_VALIDATE_VECTOR (1,o);
0f2d19dd 692 vcell = scm_sym2ovcell (s, o);
25d8012c 693 SCM_SETCDR (vcell, v);
0f2d19dd
JB
694 return SCM_UNSPECIFIED;
695}
1bbd0b84 696#undef FUNC_NAME
0f2d19dd
JB
697
698static void
1bbd0b84 699msymbolize (SCM s)
0f2d19dd
JB
700{
701 SCM string;
702 string = scm_makfromstr (SCM_CHARS (s), SCM_LENGTH (s), SCM_SYMBOL_SLOTS);
703 SCM_SETCHARS (s, SCM_CHARS (string));
704 SCM_SETLENGTH (s, SCM_LENGTH (s), scm_tc7_msymbol);
25d8012c
MD
705 SCM_SETCDR (string, SCM_EOL);
706 SCM_SETCAR (string, SCM_EOL);
cf551a2b 707 SCM_SET_SYMBOL_PROPS (s, SCM_EOL);
b2530d66
MD
708 /* If it's a tc7_ssymbol, it comes from scm_symhash */
709 SCM_SYMBOL_HASH (s) = scm_strhash (SCM_UCHARS (s),
710 (scm_sizet) SCM_LENGTH (s),
711 SCM_LENGTH (scm_symhash));
0f2d19dd
JB
712}
713
714
3b3b36dd 715SCM_DEFINE (scm_symbol_fref, "symbol-fref", 1, 0, 0,
1bbd0b84 716 (SCM s),
b380b885 717 "Return the contents of @var{symbol}'s @dfn{function slot}.")
1bbd0b84 718#define FUNC_NAME s_scm_symbol_fref
0f2d19dd 719{
3b3b36dd 720 SCM_VALIDATE_SYMBOL (1,s);
0f2d19dd
JB
721 SCM_DEFER_INTS;
722 if (SCM_TYP7(s) == scm_tc7_ssymbol)
723 msymbolize (s);
724 SCM_ALLOW_INTS;
725 return SCM_SYMBOL_FUNC (s);
726}
1bbd0b84 727#undef FUNC_NAME
0f2d19dd
JB
728
729
3b3b36dd 730SCM_DEFINE (scm_symbol_pref, "symbol-pref", 1, 0, 0,
1bbd0b84 731 (SCM s),
b380b885 732 "Return the @dfn{property list} currently associated with @var{symbol}.")
1bbd0b84 733#define FUNC_NAME s_scm_symbol_pref
0f2d19dd 734{
3b3b36dd 735 SCM_VALIDATE_SYMBOL (1,s);
0f2d19dd
JB
736 SCM_DEFER_INTS;
737 if (SCM_TYP7(s) == scm_tc7_ssymbol)
738 msymbolize (s);
739 SCM_ALLOW_INTS;
740 return SCM_SYMBOL_PROPS (s);
741}
1bbd0b84 742#undef FUNC_NAME
0f2d19dd
JB
743
744
3b3b36dd 745SCM_DEFINE (scm_symbol_fset_x, "symbol-fset!", 2, 0, 0,
1bbd0b84 746 (SCM s, SCM val),
b380b885 747 "Change the binding of @var{symbol}'s function slot.")
1bbd0b84 748#define FUNC_NAME s_scm_symbol_fset_x
0f2d19dd 749{
3b3b36dd 750 SCM_VALIDATE_SYMBOL (1,s);
0f2d19dd
JB
751 SCM_DEFER_INTS;
752 if (SCM_TYP7(s) == scm_tc7_ssymbol)
753 msymbolize (s);
754 SCM_ALLOW_INTS;
cf551a2b 755 SCM_SET_SYMBOL_FUNC (s, val);
0f2d19dd
JB
756 return SCM_UNSPECIFIED;
757}
1bbd0b84 758#undef FUNC_NAME
0f2d19dd
JB
759
760
3b3b36dd 761SCM_DEFINE (scm_symbol_pset_x, "symbol-pset!", 2, 0, 0,
1bbd0b84 762 (SCM s, SCM val),
b380b885 763 "Change the binding of @var{symbol}'s property slot.")
1bbd0b84 764#define FUNC_NAME s_scm_symbol_pset_x
0f2d19dd 765{
3b3b36dd 766 SCM_VALIDATE_SYMBOL (1,s);
0f2d19dd
JB
767 SCM_DEFER_INTS;
768 if (SCM_TYP7(s) == scm_tc7_ssymbol)
769 msymbolize (s);
cf551a2b 770 SCM_SET_SYMBOL_PROPS (s, val);
0f2d19dd
JB
771 SCM_ALLOW_INTS;
772 return SCM_UNSPECIFIED;
773}
1bbd0b84 774#undef FUNC_NAME
0f2d19dd
JB
775
776
3b3b36dd 777SCM_DEFINE (scm_symbol_hash, "symbol-hash", 1, 0, 0,
1bbd0b84 778 (SCM s),
b380b885
MD
779 "Return the hash value derived from @var{symbol}'s name, i.e. the integer\n"
780 "index into @var{symbol}'s obarray at which it is stored.")
1bbd0b84 781#define FUNC_NAME s_scm_symbol_hash
0f2d19dd 782{
3b3b36dd 783 SCM_VALIDATE_SYMBOL (1,s);
b2530d66
MD
784 if (SCM_TYP7(s) == scm_tc7_ssymbol)
785 msymbolize (s);
cf551a2b 786 return SCM_MAKINUM (SCM_UNPACK (s) ^ SCM_SYMBOL_HASH (s));
0f2d19dd 787}
1bbd0b84 788#undef FUNC_NAME
0f2d19dd
JB
789
790
b2530d66 791static void
1bbd0b84 792copy_and_prune_obarray (SCM from, SCM to)
b2530d66
MD
793{
794 int i;
795 int length = SCM_LENGTH (from);
796 for (i = 0; i < length; ++i)
797 {
798 SCM head = SCM_VELTS (from)[i]; /* GC protection */
799 SCM ls = head;
800 SCM res = SCM_EOL;
801 SCM *lloc = &res;
802 while (SCM_NIMP (ls))
803 {
804 if (!SCM_UNBNDP (SCM_CDAR (ls)))
805 {
806 *lloc = scm_cons (SCM_CAR (ls), SCM_EOL);
807 lloc = SCM_CDRLOC (*lloc);
808 }
809 ls = SCM_CDR (ls);
810 }
811 SCM_VELTS (to)[i] = res;
812 }
813}
814
815
3b3b36dd 816SCM_DEFINE (scm_builtin_bindings, "builtin-bindings", 0, 0, 0,
5ffe9968 817 (),
b380b885
MD
818 "Create and return a copy of the global symbol table, removing all\n"
819 "unbound symbols.")
1bbd0b84 820#define FUNC_NAME s_scm_builtin_bindings
b2530d66
MD
821{
822 int length = SCM_LENGTH (scm_symhash);
a8741caa 823 SCM obarray = scm_make_vector (SCM_MAKINUM (length), SCM_EOL);
b2530d66
MD
824 copy_and_prune_obarray (scm_symhash, obarray);
825 return obarray;
826}
1bbd0b84 827#undef FUNC_NAME
b2530d66
MD
828
829
3b3b36dd 830SCM_DEFINE (scm_builtin_weak_bindings, "builtin-weak-bindings", 0, 0, 0,
5ffe9968 831 (),
b380b885 832 "")
1bbd0b84 833#define FUNC_NAME s_scm_builtin_weak_bindings
b2530d66
MD
834{
835 int length = SCM_LENGTH (scm_weak_symhash);
836 SCM obarray = scm_make_doubly_weak_hash_table (SCM_MAKINUM (length));
837 copy_and_prune_obarray (scm_weak_symhash, obarray);
838 return obarray;
839}
1bbd0b84 840#undef FUNC_NAME
b2530d66 841
1ff4df7a
MD
842static int gensym_counter;
843static SCM gensym_prefix;
b2530d66 844
1bbd0b84 845/* :FIXME:OPTIMIZE */
a1ec6916 846SCM_DEFINE (scm_gensym, "gensym", 0, 2, 0,
1bbd0b84 847 (SCM name, SCM obarray),
b380b885
MD
848 "Create a new, unique symbol in @var{obarray}, using the global symbol\n"
849 "table by default. If @var{name} is specified, it should be used as a\n"
850 "prefix for the new symbol's name. The default prefix is @code{%%gensym}.")
1bbd0b84 851#define FUNC_NAME s_scm_gensym
1ff4df7a
MD
852{
853 SCM new;
854 if (SCM_UNBNDP (name))
855 name = gensym_prefix;
856 else
3b3b36dd 857 SCM_VALIDATE_ROSTRING (1,name);
1bbd0b84 858
1ff4df7a
MD
859 new = name;
860 if (SCM_UNBNDP (obarray))
861 {
862 obarray = SCM_BOOL_F;
863 goto skip_test;
864 }
865 else
368cf54d 866 SCM_ASSERT ((SCM_VECTORP (obarray) || SCM_WVECTP (obarray)),
1ff4df7a
MD
867 obarray,
868 SCM_ARG2,
1bbd0b84 869 FUNC_NAME);
bc66755e 870 while (!SCM_FALSEP (scm_string_to_obarray_symbol (obarray, new, SCM_BOOL_T)))
1ff4df7a
MD
871 skip_test:
872 new = scm_string_append
873 (scm_cons2 (name,
874 scm_number_to_string (SCM_MAKINUM (gensym_counter++),
875 SCM_UNDEFINED),
876 SCM_EOL));
877 return scm_string_to_obarray_symbol (obarray, new, SCM_BOOL_F);
878}
1bbd0b84 879#undef FUNC_NAME
1cc91f1b 880
0f2d19dd
JB
881void
882scm_init_symbols ()
0f2d19dd 883{
1ff4df7a
MD
884 gensym_counter = 0;
885 gensym_prefix = scm_permanent_object (scm_makfrom0str ("%%gensym"));
a0599745 886#include "libguile/symbols.x"
0f2d19dd 887}
89e00824
ML
888
889/*
890 Local Variables:
891 c-file-style: "gnu"
892 End:
893*/