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