3
$Id: intern.c,v 9.57 2000/12/05 21:23:44 cph Exp $
5
Copyright (c) 1987-2000 Massachusetts Institute of Technology
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or (at
10
your option) any later version.
12
This program is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
/* String hash functions and interning of symbols. */
31
extern int EXFUN (strlen, (const char *));
34
/* These are exported to other parts of the system. */
36
extern SCHEME_OBJECT EXFUN (string_to_symbol, (SCHEME_OBJECT));
37
extern SCHEME_OBJECT EXFUN (char_pointer_to_symbol, (unsigned char *));
38
extern SCHEME_OBJECT EXFUN (memory_to_symbol, (long, unsigned char *));
39
extern SCHEME_OBJECT EXFUN (find_symbol, (long, unsigned char *));
43
#define STRING_HASH_BITS 16
46
DEFUN (string_hash, (length, string),
47
long length AND unsigned char * string)
49
fast unsigned char * scan = string;
50
fast unsigned char * end = (scan + length);
51
fast unsigned int result = 0;
55
result |= (result >> STRING_HASH_BITS);
57
result &= ((1 << STRING_HASH_BITS) - 1);
63
DEFUN (string_equal, (length1, string1, length2, string2),
64
long length1 AND unsigned char * string1
65
AND long length2 AND unsigned char * string2)
67
fast unsigned char * scan1 = string1;
68
fast unsigned char * scan2 = string2;
69
fast long length = length1;
70
fast unsigned char * end1 = (scan1 + length);
73
if (length != length2)
76
if ((*scan1++) != (*scan2++))
81
static SCHEME_OBJECT *
82
DEFUN (find_symbol_internal, (length, string),
83
long length AND unsigned char * string)
85
fast SCHEME_OBJECT * bucket;
87
fast SCHEME_OBJECT obarray = (Get_Fixed_Obj_Slot (OBArray));
90
(((string_hash (length, string))
91
% (VECTOR_LENGTH (obarray)))
94
while ((*bucket) != EMPTY_LIST)
96
fast SCHEME_OBJECT symbol = (PAIR_CAR (*bucket));
97
fast SCHEME_OBJECT name = (FAST_MEMORY_REF (symbol, SYMBOL_NAME));
98
if (string_equal (length, string,
99
(STRING_LENGTH (name)), (STRING_LOC (name, 0))))
100
return (PAIR_CAR_LOC (*bucket));
101
bucket = (PAIR_CDR_LOC (*bucket));
106
/* Set this to be informed of symbols as they are interned. */
107
void EXFUN ((*intern_symbol_hook), (SCHEME_OBJECT)) = 0;
110
DEFUN (link_new_symbol, (symbol, cell),
112
AND SCHEME_OBJECT * cell)
114
/* `symbol' does not exist yet in obarray. `cell' points to the
115
cell containing the final '() in the list. Replace this
116
with a cons of the new symbol and '() (i.e. extend the
117
list in the bucket by 1 new element). */
119
fast SCHEME_OBJECT result = (OBJECT_NEW_TYPE (TC_INTERNED_SYMBOL, symbol));
120
(*cell) = (cons (result, EMPTY_LIST));
121
if (intern_symbol_hook != ((void (*) ()) 0))
122
(*intern_symbol_hook) (result);
127
DEFUN (find_symbol, (length, string), long length AND unsigned char * string)
129
SCHEME_OBJECT result = (* (find_symbol_internal (length, string)));
130
return ((result == EMPTY_LIST) ? SHARP_F : result);
134
DEFUN (make_symbol, (string, cell),
135
SCHEME_OBJECT string AND
136
SCHEME_OBJECT * cell)
138
Primitive_GC_If_Needed (2);
140
SCHEME_OBJECT symbol = (MAKE_POINTER_OBJECT (TC_UNINTERNED_SYMBOL, Free));
141
(Free [SYMBOL_NAME]) = string;
142
(Free [SYMBOL_GLOBAL_VALUE]) = UNBOUND_OBJECT;
144
return (link_new_symbol (symbol, cell));
149
DEFUN (memory_to_symbol, (length, string),
151
unsigned char * string)
153
SCHEME_OBJECT * cell = (find_symbol_internal (length, string));
155
(((*cell) == EMPTY_LIST)
156
? (make_symbol ((memory_to_string (length, string)), cell))
161
DEFUN (char_pointer_to_symbol, (string), unsigned char * string)
163
return (memory_to_symbol ((strlen (string)), string));
167
DEFUN (string_to_symbol, (string), SCHEME_OBJECT string)
169
SCHEME_OBJECT * cell =
170
(find_symbol_internal ((STRING_LENGTH (string)),
171
(STRING_LOC (string, 0))));
172
return (((*cell) == EMPTY_LIST) ? (make_symbol (string, cell)) : (*cell));
176
DEFUN (intern_symbol, (symbol), SCHEME_OBJECT symbol)
178
SCHEME_OBJECT name = (FAST_MEMORY_REF (symbol, SYMBOL_NAME));
179
SCHEME_OBJECT * cell =
180
(find_symbol_internal ((STRING_LENGTH (name)), (STRING_LOC (name, 0))));
181
return (((*cell) == EMPTY_LIST)
182
? (link_new_symbol (symbol, cell))
186
DEFINE_PRIMITIVE ("FIND-SYMBOL", Prim_find_symbol, 1, 1,
187
"(FIND-SYMBOL STRING)\n\
188
Returns the symbol whose name is STRING, or #F if no such symbol exists.")
190
SCHEME_OBJECT string;
191
PRIMITIVE_HEADER (1);
193
CHECK_ARG (1, STRING_P);
194
string = (ARG_REF (1));
196
(find_symbol ((STRING_LENGTH (string)), (STRING_LOC (string, 0))));
199
DEFINE_PRIMITIVE ("STRING->SYMBOL", Prim_string_to_symbol, 1, 1,
200
"(STRING->SYMBOL STRING)\n\
201
Returns the symbol whose name is STRING, constructing a new symbol if needed.")
203
PRIMITIVE_HEADER (1);
205
CHECK_ARG (1, STRING_P);
206
PRIMITIVE_RETURN (string_to_symbol (ARG_REF (1)));
209
DEFINE_PRIMITIVE ("STRING-HASH", Prim_string_hash, 1, 1,
210
"(STRING-HASH STRING)\n\
211
Return a hash value for a string. This uses the hashing\n\
212
algorithm used for interning symbols. It is intended for use by\n\
213
the reader in creating interned symbols.")
215
SCHEME_OBJECT string;
216
PRIMITIVE_HEADER (1);
218
CHECK_ARG (1, STRING_P);
219
string = (ARG_REF (1));
221
(LONG_TO_UNSIGNED_FIXNUM (string_hash ((STRING_LENGTH (string)),
222
(STRING_LOC (string, 0)))));
225
DEFINE_PRIMITIVE ("STRING-HASH-MOD", Prim_string_hash_mod, 2, 2,
226
"(STRING-HASH-MOD STRING DENOMINATOR)\n\
227
DENOMINATOR must be a nonnegative integer.\n\
228
Equivalent to (MOD (STRING-HASH STRING) DENOMINATOR).")
230
SCHEME_OBJECT string;
231
PRIMITIVE_HEADER (2);
233
CHECK_ARG (1, STRING_P);
234
string = (ARG_REF (1));
236
(LONG_TO_UNSIGNED_FIXNUM
237
((string_hash ((STRING_LENGTH (string)),
238
(STRING_LOC (string, 0))))
239
% (arg_nonnegative_integer (2))));