2002-01-31 Stefan Jahn <stefan@lkcc.org>
[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{
1be6b49c
ML
90 size_t raw_hash = scm_string_hash ((const unsigned char *) name, len);
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
16d4699b
MV
128 symbol = scm_alloc_double_cell (SCM_MAKE_SYMBOL_TAG (len),
129 (scm_t_bits) scm_must_strndup (name, len),
130 raw_hash,
131 SCM_UNPACK (scm_cons (SCM_BOOL_F,
132 SCM_EOL)));
b52e071b 133
0f979f3f 134 slot = SCM_VELTS (symbols) [hash];
a7a59ea9
MV
135 cell = scm_cons (symbol, SCM_UNDEFINED);
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
3b3b36dd 149SCM_DEFINE (scm_symbol_p, "symbol?", 1, 0, 0,
8e93e199 150 (SCM obj),
1e6808ea
MG
151 "Return @code{#t} if @var{obj} is a symbol, otherwise return\n"
152 "@code{#f}.")
1bbd0b84 153#define FUNC_NAME s_scm_symbol_p
0f2d19dd 154{
8e93e199 155 return SCM_BOOL (SCM_SYMBOLP (obj));
0f2d19dd 156}
1bbd0b84 157#undef FUNC_NAME
0f2d19dd 158
3b3b36dd 159SCM_DEFINE (scm_symbol_to_string, "symbol->string", 1, 0, 0,
1bbd0b84 160 (SCM s),
1e6808ea
MG
161 "Return the name of @var{symbol} as a string. If the symbol was\n"
162 "part of an object returned as the value of a literal expression\n"
7a095584 163 "(section @pxref{Literal expressions,,,r5rs, The Revised^5\n"
1e6808ea
MG
164 "Report on Scheme}) or by a call to the @code{read} procedure,\n"
165 "and its name contains alphabetic characters, then the string\n"
166 "returned will contain characters in the implementation's\n"
167 "preferred standard case---some implementations will prefer\n"
168 "upper case, others lower case. If the symbol was returned by\n"
169 "@code{string->symbol}, the case of characters in the string\n"
170 "returned will be the same as the case in the string that was\n"
171 "passed to @code{string->symbol}. It is an error to apply\n"
172 "mutation procedures like @code{string-set!} to strings returned\n"
173 "by this procedure.\n"
174 "\n"
942e5b91 175 "The following examples assume that the implementation's\n"
1e6808ea
MG
176 "standard case is lower case:\n"
177 "\n"
942e5b91 178 "@lisp\n"
1e6808ea
MG
179 "(symbol->string 'flying-fish) @result{} \"flying-fish\"\n"
180 "(symbol->string 'Martin) @result{} \"martin\"\n"
5ffe9968 181 "(symbol->string\n"
942e5b91
MG
182 " (string->symbol \"Malvina\")) @result{} \"Malvina\"\n"
183 "@end lisp")
1bbd0b84 184#define FUNC_NAME s_scm_symbol_to_string
0f2d19dd 185{
36284627 186 SCM str;
28b06554 187 SCM_VALIDATE_SYMBOL (1, s);
36284627
DH
188 str = scm_mem2string (SCM_SYMBOL_CHARS (s), SCM_SYMBOL_LENGTH (s));
189 scm_remember_upto_here_1 (s);
190 return str;
0f2d19dd 191}
1bbd0b84 192#undef FUNC_NAME
0f2d19dd
JB
193
194
3b3b36dd 195SCM_DEFINE (scm_string_to_symbol, "string->symbol", 1, 0, 0,
1e6808ea
MG
196 (SCM string),
197 "Return the symbol whose name is @var{string}. This procedure\n"
942e5b91
MG
198 "can create symbols with names containing special characters or\n"
199 "letters in the non-standard case, but it is usually a bad idea\n"
1e6808ea
MG
200 "to create such symbols because in some implementations of\n"
201 "Scheme they cannot be read as themselves. See\n"
202 "@code{symbol->string}.\n"
203 "\n"
942e5b91 204 "The following examples assume that the implementation's\n"
1e6808ea
MG
205 "standard case is lower case:\n"
206 "\n"
942e5b91
MG
207 "@lisp\n"
208 "(eq? 'mISSISSIppi 'mississippi) @result{} #t\n"
209 "(string->symbol \"mISSISSIppi\") @result{} @r{the symbol with name \"mISSISSIppi\"}\n"
210 "(eq? 'bitBlt (string->symbol \"bitBlt\")) @result{} #f\n"
211 "(eq? 'JollyWog\n"
212 " (string->symbol (symbol->string 'JollyWog))) @result{} #t\n"
213 "(string=? \"K. Harper, M.D.\"\n"
214 " (symbol->string\n"
215 " (string->symbol \"K. Harper, M.D.\"))) @result{}#t\n"
216 "@end lisp")
1bbd0b84 217#define FUNC_NAME s_scm_string_to_symbol
0f2d19dd 218{
1e6808ea
MG
219 SCM_VALIDATE_STRING (1, string);
220 return scm_mem2symbol (SCM_STRING_CHARS (string),
221 SCM_STRING_LENGTH (string));
0f2d19dd 222}
1bbd0b84 223#undef FUNC_NAME
0f2d19dd 224
86d31dfe 225#define MAX_PREFIX_LENGTH 30
0f2d19dd 226
86d31dfe 227static int gensym_counter;
0f2d19dd 228
86d31dfe
MV
229SCM_DEFINE (scm_gensym, "gensym", 0, 1, 0,
230 (SCM prefix),
231 "Create a new symbol with a name constructed from a prefix and\n"
232 "a counter value. The string @var{prefix} can be specified as\n"
233 "an optional argument. Default prefix is @code{g}. The counter\n"
234 "is increased by 1 at each call. There is no provision for\n"
235 "resetting the counter.")
236#define FUNC_NAME s_scm_gensym
0f2d19dd 237{
86d31dfe
MV
238 char buf[MAX_PREFIX_LENGTH + SCM_INTBUFLEN];
239 char *name = buf;
1be6b49c 240 size_t len;
86d31dfe
MV
241 if (SCM_UNBNDP (prefix))
242 {
243 name[0] = 'g';
244 len = 1;
245 }
246 else
247 {
248 SCM_VALIDATE_STRING (1, prefix);
249 len = SCM_STRING_LENGTH (prefix);
250 if (len > MAX_PREFIX_LENGTH)
8d09eb04
MG
251 name = SCM_MUST_MALLOC (len + SCM_INTBUFLEN);
252 memcpy (name, SCM_STRING_CHARS (prefix), len);
86d31dfe 253 }
49bc24fe 254 {
86d31dfe
MV
255 int n_digits = scm_iint2str (gensym_counter++, 10, &name[len]);
256 SCM res = scm_mem2symbol (name, len + n_digits);
257 if (name != buf)
258 scm_must_free (name);
259 return res;
49bc24fe 260 }
0f2d19dd 261}
1bbd0b84 262#undef FUNC_NAME
0f2d19dd 263
86d31dfe
MV
264SCM_DEFINE (scm_symbol_hash, "symbol-hash", 1, 0, 0,
265 (SCM symbol),
266 "Return a hash value for @var{symbol}.")
267#define FUNC_NAME s_scm_symbol_hash
0f2d19dd 268{
86d31dfe
MV
269 SCM_VALIDATE_SYMBOL (1, symbol);
270 return SCM_MAKINUM (SCM_SYMBOL_HASH (symbol));
0f2d19dd 271}
1bbd0b84 272#undef FUNC_NAME
0f2d19dd 273
3b3b36dd 274SCM_DEFINE (scm_symbol_fref, "symbol-fref", 1, 0, 0,
1bbd0b84 275 (SCM s),
b380b885 276 "Return the contents of @var{symbol}'s @dfn{function slot}.")
1bbd0b84 277#define FUNC_NAME s_scm_symbol_fref
0f2d19dd 278{
3b3b36dd 279 SCM_VALIDATE_SYMBOL (1,s);
0f2d19dd
JB
280 return SCM_SYMBOL_FUNC (s);
281}
1bbd0b84 282#undef FUNC_NAME
0f2d19dd
JB
283
284
3b3b36dd 285SCM_DEFINE (scm_symbol_pref, "symbol-pref", 1, 0, 0,
1bbd0b84 286 (SCM s),
b380b885 287 "Return the @dfn{property list} currently associated with @var{symbol}.")
1bbd0b84 288#define FUNC_NAME s_scm_symbol_pref
0f2d19dd 289{
3b3b36dd 290 SCM_VALIDATE_SYMBOL (1,s);
0f2d19dd
JB
291 return SCM_SYMBOL_PROPS (s);
292}
1bbd0b84 293#undef FUNC_NAME
0f2d19dd
JB
294
295
3b3b36dd 296SCM_DEFINE (scm_symbol_fset_x, "symbol-fset!", 2, 0, 0,
1bbd0b84 297 (SCM s, SCM val),
b380b885 298 "Change the binding of @var{symbol}'s function slot.")
1bbd0b84 299#define FUNC_NAME s_scm_symbol_fset_x
0f2d19dd 300{
3b3b36dd 301 SCM_VALIDATE_SYMBOL (1,s);
cf551a2b 302 SCM_SET_SYMBOL_FUNC (s, val);
0f2d19dd
JB
303 return SCM_UNSPECIFIED;
304}
1bbd0b84 305#undef FUNC_NAME
0f2d19dd
JB
306
307
3b3b36dd 308SCM_DEFINE (scm_symbol_pset_x, "symbol-pset!", 2, 0, 0,
1bbd0b84 309 (SCM s, SCM val),
b380b885 310 "Change the binding of @var{symbol}'s property slot.")
1bbd0b84 311#define FUNC_NAME s_scm_symbol_pset_x
0f2d19dd 312{
3b3b36dd 313 SCM_VALIDATE_SYMBOL (1,s);
0f2d19dd 314 SCM_DEFER_INTS;
cf551a2b 315 SCM_SET_SYMBOL_PROPS (s, val);
0f2d19dd
JB
316 SCM_ALLOW_INTS;
317 return SCM_UNSPECIFIED;
318}
1bbd0b84 319#undef FUNC_NAME
0f2d19dd 320
af68e5e5
SJ
321
322/* Converts the given Scheme symbol OBJ into a C string, containing a copy
323 of OBJ's content with a trailing null byte. If LENP is non-NULL, set
324 *LENP to the string's length.
325
326 When STR is non-NULL it receives the copy and is returned by the function,
327 otherwise new memory is allocated and the caller is responsible for
328 freeing it via free(). If out of memory, NULL is returned.
329
330 Note that Scheme symbols may contain arbitrary data, including null
331 characters. This means that null termination is not a reliable way to
332 determine the length of the returned value. However, the function always
333 copies the complete contents of OBJ, and sets *LENP to the length of the
334 scheme symbol (if LENP is non-null). */
335#define FUNC_NAME "scm_c_symbol2str"
336char *
337scm_c_symbol2str (SCM obj, char *str, size_t *lenp)
338{
339 size_t len;
340
341 SCM_ASSERT (SCM_SYMBOLP (obj), obj, SCM_ARG1, FUNC_NAME);
342 len = SCM_SYMBOL_LENGTH (obj);
343
344 if (str == NULL)
345 {
346 /* FIXME: Should we use exported wrappers for malloc (and free), which
347 * allow windows DLLs to call the correct freeing function? */
348 str = (char *) malloc ((len + 1) * sizeof (char));
349 if (str == NULL)
350 return NULL;
351 }
352
353 memcpy (str, SCM_SYMBOL_CHARS (obj), len);
354 scm_remember_upto_here_1 (obj);
355 str[len] = '\0';
356
357 if (lenp != NULL)
358 *lenp = len;
359
360 return str;
361}
362#undef FUNC_NAME
363
364
0f979f3f
DH
365void
366scm_symbols_prehistory ()
367{
a4c91488 368 symbols = scm_make_weak_key_hash_table (SCM_MAKINUM (1009));
0f979f3f
DH
369 scm_permanent_object (symbols);
370}
371
372
0f2d19dd
JB
373void
374scm_init_symbols ()
0f2d19dd 375{
1ff4df7a 376 gensym_counter = 0;
8dc9439f 377#ifndef SCM_MAGIC_SNARFER
a0599745 378#include "libguile/symbols.x"
8dc9439f 379#endif
0f2d19dd 380}
89e00824
ML
381
382/*
383 Local Variables:
384 c-file-style: "gnu"
385 End:
386*/