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