2002-07-20 Han-Wen <hanwen@cs.uu.nl>
[bpt/guile.git] / libguile / symbols.c
CommitLineData
e81d98ec 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 41
1bbd0b84 42
0f2d19dd
JB
43\f
44
a0599745
MD
45#include "libguile/_scm.h"
46#include "libguile/chars.h"
47#include "libguile/eval.h"
ba393257 48#include "libguile/hash.h"
fb43bf74 49#include "libguile/smob.h"
a0599745
MD
50#include "libguile/variable.h"
51#include "libguile/alist.h"
7e73eaee 52#include "libguile/fluids.h"
a0599745
MD
53#include "libguile/strings.h"
54#include "libguile/vectors.h"
00ffa0e7 55#include "libguile/hashtab.h"
a0599745 56#include "libguile/weaks.h"
eb8db440 57#include "libguile/modules.h"
a0599745
MD
58
59#include "libguile/validate.h"
60#include "libguile/symbols.h"
0f2d19dd 61
95b88819
GH
62#ifdef HAVE_STRING_H
63#include <string.h>
64#endif
65
0f2d19dd
JB
66\f
67
0f979f3f
DH
68static SCM symbols;
69
a4c91488
MD
70#ifdef GUILE_DEBUG
71SCM_DEFINE (scm_sys_symbols, "%symbols", 0, 0, 0,
72 (),
73 "Return the system symbol obarray.")
74#define FUNC_NAME s_scm_sys_symbols
75{
76 return symbols;
77}
78#undef FUNC_NAME
79#endif
80
0f979f3f
DH
81\f
82
0f2d19dd
JB
83/* {Symbols}
84 */
85
1cc91f1b 86
b52e071b 87SCM
1be6b49c 88scm_mem2symbol (const char *name, size_t len)
b52e071b 89{
ac48757b 90 size_t raw_hash = scm_string_hash ((const unsigned char *) name, len)/2;
1be6b49c 91 size_t hash = raw_hash % SCM_VECTOR_LENGTH (symbols);
b52e071b
DH
92
93 {
0f979f3f 94 /* Try to find the symbol in the symbols table */
b52e071b
DH
95
96 SCM l;
97
0f979f3f 98 for (l = SCM_VELTS (symbols) [hash]; !SCM_NULLP (l); l = SCM_CDR (l))
b52e071b 99 {
a7a59ea9 100 SCM sym = SCM_CAAR (l);
25c507d9
MV
101 if (SCM_SYMBOL_HASH (sym) == raw_hash
102 && SCM_SYMBOL_LENGTH (sym) == len)
b52e071b
DH
103 {
104 char *chrs = SCM_SYMBOL_CHARS (sym);
1be6b49c 105 size_t i = len;
b52e071b
DH
106
107 while (i != 0)
108 {
109 --i;
110 if (name[i] != chrs[i])
111 goto next_symbol;
112 }
113
114 return sym;
115 }
116 next_symbol:
8d5a2737 117 ;
b52e071b
DH
118 }
119 }
120
121 {
122 /* The symbol was not found - create it. */
123
124 SCM symbol;
a7a59ea9 125 SCM cell;
b52e071b
DH
126 SCM slot;
127
228a24ef
DH
128 symbol = scm_double_cell (SCM_MAKE_SYMBOL_TAG (len),
129 (scm_t_bits) scm_gc_strndup (name, len,
130 "symbol"),
131 raw_hash,
132 SCM_UNPACK (scm_cons (SCM_BOOL_F, SCM_EOL)));
b52e071b 133
0f979f3f 134 slot = SCM_VELTS (symbols) [hash];
a7a59ea9 135 cell = scm_cons (symbol, SCM_UNDEFINED);
34d19ef6 136 SCM_VECTOR_SET (symbols, hash, scm_cons (cell, slot));
b52e071b
DH
137
138 return symbol;
139 }
140}
141
ac48757b
MV
142SCM
143scm_mem2uninterned_symbol (const char *name, size_t len)
144{
145 size_t raw_hash = (scm_string_hash ((const unsigned char *) name, len)/2
146 + SCM_T_BITS_MAX/2 + 1);
147
228a24ef
DH
148 return scm_double_cell (SCM_MAKE_SYMBOL_TAG (len),
149 (scm_t_bits) scm_gc_strndup (name, len,
150 "symbol"),
151 raw_hash,
152 SCM_UNPACK (scm_cons (SCM_BOOL_F, SCM_EOL)));
ac48757b
MV
153}
154
b52e071b
DH
155SCM
156scm_str2symbol (const char *str)
157{
158 return scm_mem2symbol (str, strlen (str));
159}
160
3b3b36dd 161SCM_DEFINE (scm_symbol_p, "symbol?", 1, 0, 0,
8e93e199 162 (SCM obj),
1e6808ea
MG
163 "Return @code{#t} if @var{obj} is a symbol, otherwise return\n"
164 "@code{#f}.")
1bbd0b84 165#define FUNC_NAME s_scm_symbol_p
0f2d19dd 166{
8e93e199 167 return SCM_BOOL (SCM_SYMBOLP (obj));
0f2d19dd 168}
1bbd0b84 169#undef FUNC_NAME
0f2d19dd 170
ac48757b
MV
171SCM_DEFINE (scm_symbol_interned_p, "symbol-interned?", 1, 0, 0,
172 (SCM symbol),
173 "Return @code{#t} if @var{symbol} is interned, otherwise return\n"
174 "@code{#f}.")
175#define FUNC_NAME s_scm_symbol_interned_p
176{
177 SCM_VALIDATE_SYMBOL (1, symbol);
178 return SCM_BOOL (SCM_SYMBOL_INTERNED_P (symbol));
179}
180#undef FUNC_NAME
181
182SCM_DEFINE (scm_make_symbol, "make-symbol", 1, 0, 0,
183 (SCM name),
184 "Return a new uninterned symbol with the name @var{name}. "
185 "The returned symbol is guaranteed to be unique and future "
d58d5bfc 186 "calls to @code{string->symbol} will not return it.")
ac48757b
MV
187#define FUNC_NAME s_scm_make_symbol
188{
189 SCM sym;
190 SCM_VALIDATE_STRING (1, name);
191 sym = scm_mem2uninterned_symbol (SCM_STRING_CHARS (name),
192 SCM_STRING_LENGTH (name));
193 scm_remember_upto_here_1 (name);
194 return sym;
195}
196#undef FUNC_NAME
197
3b3b36dd 198SCM_DEFINE (scm_symbol_to_string, "symbol->string", 1, 0, 0,
1bbd0b84 199 (SCM s),
1e6808ea
MG
200 "Return the name of @var{symbol} as a string. If the symbol was\n"
201 "part of an object returned as the value of a literal expression\n"
7a095584 202 "(section @pxref{Literal expressions,,,r5rs, The Revised^5\n"
1e6808ea
MG
203 "Report on Scheme}) or by a call to the @code{read} procedure,\n"
204 "and its name contains alphabetic characters, then the string\n"
205 "returned will contain characters in the implementation's\n"
206 "preferred standard case---some implementations will prefer\n"
207 "upper case, others lower case. If the symbol was returned by\n"
208 "@code{string->symbol}, the case of characters in the string\n"
209 "returned will be the same as the case in the string that was\n"
210 "passed to @code{string->symbol}. It is an error to apply\n"
211 "mutation procedures like @code{string-set!} to strings returned\n"
212 "by this procedure.\n"
213 "\n"
942e5b91 214 "The following examples assume that the implementation's\n"
1e6808ea
MG
215 "standard case is lower case:\n"
216 "\n"
942e5b91 217 "@lisp\n"
1e6808ea
MG
218 "(symbol->string 'flying-fish) @result{} \"flying-fish\"\n"
219 "(symbol->string 'Martin) @result{} \"martin\"\n"
5ffe9968 220 "(symbol->string\n"
942e5b91
MG
221 " (string->symbol \"Malvina\")) @result{} \"Malvina\"\n"
222 "@end lisp")
1bbd0b84 223#define FUNC_NAME s_scm_symbol_to_string
0f2d19dd 224{
36284627 225 SCM str;
28b06554 226 SCM_VALIDATE_SYMBOL (1, s);
36284627
DH
227 str = scm_mem2string (SCM_SYMBOL_CHARS (s), SCM_SYMBOL_LENGTH (s));
228 scm_remember_upto_here_1 (s);
229 return str;
0f2d19dd 230}
1bbd0b84 231#undef FUNC_NAME
0f2d19dd
JB
232
233
3b3b36dd 234SCM_DEFINE (scm_string_to_symbol, "string->symbol", 1, 0, 0,
1e6808ea
MG
235 (SCM string),
236 "Return the symbol whose name is @var{string}. This procedure\n"
942e5b91
MG
237 "can create symbols with names containing special characters or\n"
238 "letters in the non-standard case, but it is usually a bad idea\n"
1e6808ea
MG
239 "to create such symbols because in some implementations of\n"
240 "Scheme they cannot be read as themselves. See\n"
241 "@code{symbol->string}.\n"
242 "\n"
942e5b91 243 "The following examples assume that the implementation's\n"
1e6808ea
MG
244 "standard case is lower case:\n"
245 "\n"
942e5b91
MG
246 "@lisp\n"
247 "(eq? 'mISSISSIppi 'mississippi) @result{} #t\n"
248 "(string->symbol \"mISSISSIppi\") @result{} @r{the symbol with name \"mISSISSIppi\"}\n"
249 "(eq? 'bitBlt (string->symbol \"bitBlt\")) @result{} #f\n"
250 "(eq? 'JollyWog\n"
251 " (string->symbol (symbol->string 'JollyWog))) @result{} #t\n"
252 "(string=? \"K. Harper, M.D.\"\n"
253 " (symbol->string\n"
254 " (string->symbol \"K. Harper, M.D.\"))) @result{}#t\n"
255 "@end lisp")
1bbd0b84 256#define FUNC_NAME s_scm_string_to_symbol
0f2d19dd 257{
68dc153d 258 SCM sym;
1e6808ea 259 SCM_VALIDATE_STRING (1, string);
68dc153d
MV
260 sym = scm_mem2symbol (SCM_STRING_CHARS (string),
261 SCM_STRING_LENGTH (string));
262 scm_remember_upto_here_1 (string);
263 return sym;
0f2d19dd 264}
1bbd0b84 265#undef FUNC_NAME
0f2d19dd 266
86d31dfe 267#define MAX_PREFIX_LENGTH 30
0f2d19dd 268
86d31dfe 269static int gensym_counter;
0f2d19dd 270
86d31dfe
MV
271SCM_DEFINE (scm_gensym, "gensym", 0, 1, 0,
272 (SCM prefix),
273 "Create a new symbol with a name constructed from a prefix and\n"
274 "a counter value. The string @var{prefix} can be specified as\n"
68dc153d 275 "an optional argument. Default prefix is @code{ g}. The counter\n"
86d31dfe
MV
276 "is increased by 1 at each call. There is no provision for\n"
277 "resetting the counter.")
278#define FUNC_NAME s_scm_gensym
0f2d19dd 279{
86d31dfe
MV
280 char buf[MAX_PREFIX_LENGTH + SCM_INTBUFLEN];
281 char *name = buf;
1be6b49c 282 size_t len;
86d31dfe
MV
283 if (SCM_UNBNDP (prefix))
284 {
68dc153d
MV
285 name[0] = ' ';
286 name[1] = 'g';
287 len = 2;
86d31dfe
MV
288 }
289 else
290 {
291 SCM_VALIDATE_STRING (1, prefix);
292 len = SCM_STRING_LENGTH (prefix);
293 if (len > MAX_PREFIX_LENGTH)
4c9419ac 294 name = scm_malloc (len + SCM_INTBUFLEN);
8d09eb04 295 memcpy (name, SCM_STRING_CHARS (prefix), len);
86d31dfe 296 }
49bc24fe 297 {
86d31dfe
MV
298 int n_digits = scm_iint2str (gensym_counter++, 10, &name[len]);
299 SCM res = scm_mem2symbol (name, len + n_digits);
300 if (name != buf)
4c9419ac 301 free (name);
86d31dfe 302 return res;
49bc24fe 303 }
0f2d19dd 304}
1bbd0b84 305#undef FUNC_NAME
0f2d19dd 306
86d31dfe
MV
307SCM_DEFINE (scm_symbol_hash, "symbol-hash", 1, 0, 0,
308 (SCM symbol),
309 "Return a hash value for @var{symbol}.")
310#define FUNC_NAME s_scm_symbol_hash
0f2d19dd 311{
86d31dfe 312 SCM_VALIDATE_SYMBOL (1, symbol);
ac48757b 313 return scm_ulong2num (SCM_SYMBOL_HASH (symbol));
0f2d19dd 314}
1bbd0b84 315#undef FUNC_NAME
0f2d19dd 316
3b3b36dd 317SCM_DEFINE (scm_symbol_fref, "symbol-fref", 1, 0, 0,
1bbd0b84 318 (SCM s),
b380b885 319 "Return the contents of @var{symbol}'s @dfn{function slot}.")
1bbd0b84 320#define FUNC_NAME s_scm_symbol_fref
0f2d19dd 321{
34d19ef6 322 SCM_VALIDATE_SYMBOL (1, s);
0f2d19dd
JB
323 return SCM_SYMBOL_FUNC (s);
324}
1bbd0b84 325#undef FUNC_NAME
0f2d19dd
JB
326
327
3b3b36dd 328SCM_DEFINE (scm_symbol_pref, "symbol-pref", 1, 0, 0,
1bbd0b84 329 (SCM s),
b380b885 330 "Return the @dfn{property list} currently associated with @var{symbol}.")
1bbd0b84 331#define FUNC_NAME s_scm_symbol_pref
0f2d19dd 332{
34d19ef6 333 SCM_VALIDATE_SYMBOL (1, s);
0f2d19dd
JB
334 return SCM_SYMBOL_PROPS (s);
335}
1bbd0b84 336#undef FUNC_NAME
0f2d19dd
JB
337
338
3b3b36dd 339SCM_DEFINE (scm_symbol_fset_x, "symbol-fset!", 2, 0, 0,
1bbd0b84 340 (SCM s, SCM val),
b380b885 341 "Change the binding of @var{symbol}'s function slot.")
1bbd0b84 342#define FUNC_NAME s_scm_symbol_fset_x
0f2d19dd 343{
34d19ef6 344 SCM_VALIDATE_SYMBOL (1, s);
cf551a2b 345 SCM_SET_SYMBOL_FUNC (s, val);
0f2d19dd
JB
346 return SCM_UNSPECIFIED;
347}
1bbd0b84 348#undef FUNC_NAME
0f2d19dd
JB
349
350
3b3b36dd 351SCM_DEFINE (scm_symbol_pset_x, "symbol-pset!", 2, 0, 0,
1bbd0b84 352 (SCM s, SCM val),
b380b885 353 "Change the binding of @var{symbol}'s property slot.")
1bbd0b84 354#define FUNC_NAME s_scm_symbol_pset_x
0f2d19dd 355{
34d19ef6 356 SCM_VALIDATE_SYMBOL (1, s);
0f2d19dd 357 SCM_DEFER_INTS;
cf551a2b 358 SCM_SET_SYMBOL_PROPS (s, val);
0f2d19dd
JB
359 SCM_ALLOW_INTS;
360 return SCM_UNSPECIFIED;
361}
1bbd0b84 362#undef FUNC_NAME
0f2d19dd 363
af68e5e5
SJ
364
365/* Converts the given Scheme symbol OBJ into a C string, containing a copy
366 of OBJ's content with a trailing null byte. If LENP is non-NULL, set
367 *LENP to the string's length.
368
369 When STR is non-NULL it receives the copy and is returned by the function,
370 otherwise new memory is allocated and the caller is responsible for
371 freeing it via free(). If out of memory, NULL is returned.
372
373 Note that Scheme symbols may contain arbitrary data, including null
374 characters. This means that null termination is not a reliable way to
375 determine the length of the returned value. However, the function always
376 copies the complete contents of OBJ, and sets *LENP to the length of the
377 scheme symbol (if LENP is non-null). */
378#define FUNC_NAME "scm_c_symbol2str"
379char *
380scm_c_symbol2str (SCM obj, char *str, size_t *lenp)
381{
382 size_t len;
383
384 SCM_ASSERT (SCM_SYMBOLP (obj), obj, SCM_ARG1, FUNC_NAME);
385 len = SCM_SYMBOL_LENGTH (obj);
386
387 if (str == NULL)
388 {
389 /* FIXME: Should we use exported wrappers for malloc (and free), which
390 * allow windows DLLs to call the correct freeing function? */
391 str = (char *) malloc ((len + 1) * sizeof (char));
392 if (str == NULL)
393 return NULL;
394 }
395
396 memcpy (str, SCM_SYMBOL_CHARS (obj), len);
397 scm_remember_upto_here_1 (obj);
398 str[len] = '\0';
399
400 if (lenp != NULL)
401 *lenp = len;
402
403 return str;
404}
405#undef FUNC_NAME
406
407
0f979f3f
DH
408void
409scm_symbols_prehistory ()
410{
a4c91488 411 symbols = scm_make_weak_key_hash_table (SCM_MAKINUM (1009));
0f979f3f
DH
412 scm_permanent_object (symbols);
413}
414
415
0f2d19dd
JB
416void
417scm_init_symbols ()
0f2d19dd 418{
1ff4df7a 419 gensym_counter = 0;
a0599745 420#include "libguile/symbols.x"
0f2d19dd 421}
89e00824
ML
422
423/*
424 Local Variables:
425 c-file-style: "gnu"
426 End:
427*/