1 /* Copyright (C) 1995,1996 Free Software Foundation, Inc.
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)
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.
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
15 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 * As a special exception, the Free Software Foundation gives permission
18 * for additional uses of the text contained in its release of GUILE.
20 * The exception is that, if you link the GUILE library with other files
21 * to produce an executable, this does not by itself cause the
22 * resulting executable to be covered by the GNU General Public License.
23 * Your use of that executable is in no way restricted on account of
24 * linking the GUILE library code into it.
26 * This exception does not however invalidate any other reasons why
27 * the executable file might be covered by the GNU General Public License.
29 * This exception applies only to the code released by the
30 * Free Software Foundation under the name GUILE. If you copy
31 * code from other Free Software Foundation releases into a copy of
32 * GUILE, as the General Public License permits, the exception does
33 * not apply to the code that you add in this way. To avoid misleading
34 * anyone as to the status of such modified files, you must delete
35 * this exception notice from them.
37 * If you write modifications of your own for GUILE, it is your choice
38 * whether to permit this exception to apply to your modifications.
39 * If you do not wish that, delete this exception notice.
49 #include "mbstrings.h"
60 /* NUM_HASH_BUCKETS is the number of symbol scm_hash table buckets.
62 #define NUM_HASH_BUCKETS 137
72 scm_strhash (str
, len
, n
)
80 unsigned long h
= 264 % n
;
82 h
= ((h
<< 8) + ((unsigned) (scm_downcase (str
[h
% len
])))) % n
;
90 h
= ((h
<< 8) + ((unsigned) (scm_downcase (str
[--i
])))) % n
;
95 int scm_symhash_dim
= NUM_HASH_BUCKETS
;
99 * looks up the symbol in the symhash table.
103 scm_sym2vcell (sym
, thunk
, definep
)
110 SCM var
= scm_apply (thunk
, sym
, scm_cons(definep
, scm_listofnull
));
112 if (var
== SCM_BOOL_F
)
116 if (SCM_IMP(var
) || !SCM_VARIABLEP (var
))
117 scm_wta (sym
, "strangely interned symbol? ", "");
118 return SCM_VARVCELL (var
);
126 scm_sizet scm_hash
= scm_strhash (SCM_UCHARS (sym
), (scm_sizet
) SCM_LENGTH (sym
),
127 (unsigned long) scm_symhash_dim
);
130 for (lsym
= SCM_VELTS (scm_symhash
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
133 if (SCM_CAR (z
) == sym
)
140 for (lsym
= *(lsymp
= &SCM_VELTS (scm_weak_symhash
)[scm_hash
]);
142 lsym
= *(lsymp
= SCM_CDRLOC (lsym
)))
145 if (SCM_CAR (z
) == sym
)
149 /* Move handle from scm_weak_symhash to scm_symhash. */
150 *lsymp
= SCM_CDR (lsym
);
151 SCM_SETCDR (lsym
, SCM_VELTS(scm_symhash
)[scm_hash
]);
152 SCM_VELTS(scm_symhash
)[scm_hash
] = lsym
;
159 return scm_wta (sym
, "uninterned symbol? ", "");
164 * looks up the symbol in an arbitrary obarray.
168 scm_sym2ovcell_soft (sym
, obarray
)
175 scm_hash
= scm_strhash (SCM_UCHARS (sym
),
176 (scm_sizet
) SCM_LENGTH (sym
),
177 SCM_LENGTH (obarray
));
179 for (lsym
= SCM_VELTS (obarray
)[scm_hash
];
181 lsym
= SCM_CDR (lsym
))
184 if (SCM_CAR (z
) == sym
)
196 scm_sym2ovcell (sym
, obarray
)
201 answer
= scm_sym2ovcell_soft (sym
, obarray
);
202 if (answer
!= SCM_BOOL_F
)
204 scm_wta (sym
, "uninterned symbol? ", "");
205 return SCM_UNSPECIFIED
; /* not reached */
208 /* Intern a symbol whose name is the LEN characters at NAME in OBARRAY.
210 OBARRAY should be a vector of lists, indexed by the name's hash
211 value, modulo OBARRAY's length. Each list has the form
212 ((SYMBOL . VALUE) ...), where SYMBOL is a symbol, and VALUE is the
213 value associated with that symbol (in the current module? in the
216 To "intern" a symbol means: if OBARRAY already contains a symbol by
217 that name, return its (SYMBOL . VALUE) pair; otherwise, create a
218 new symbol, add the pair (SYMBOL . SCM_UNDEFINED) to the
219 appropriate list of the OBARRAY, and return the pair.
221 If softness is non-zero, don't create a symbol if it isn't already
222 in OBARRAY; instead, just return #f.
224 If OBARRAY is SCM_BOOL_F, create a symbol listed in no obarray and
225 return (SYMBOL . SCM_UNDEFINED).
227 If OBARRAY is scm_symhash, and that doesn't contain the symbol,
228 check scm_weak_symhash instead. */
232 scm_intern_obarray_soft (name
, len
, obarray
, softness
)
240 register scm_sizet i
;
241 register unsigned char *tmp
;
247 tmp
= (unsigned char *) name
;
249 if (obarray
== SCM_BOOL_F
)
251 scm_hash
= scm_strhash (tmp
, i
, 1019);
252 goto uninterned_symbol
;
255 scm_hash
= scm_strhash (tmp
, i
, SCM_LENGTH(obarray
));
257 /* softness == -1 used to mean that it was known that the symbol
258 wasn't already in the obarray. I don't think there are any
259 callers that use that case any more, but just in case...
265 for (lsym
= SCM_VELTS (obarray
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
269 tmp
= SCM_UCHARS (z
);
270 if (SCM_LENGTH (z
) != len
)
273 if (((unsigned char *) name
)[i
] != tmp
[i
])
284 if (obarray
== scm_symhash
)
286 obarray
= scm_weak_symhash
;
287 goto retry_new_obarray
;
297 lsym
= scm_makfromstr (name
, len
, SCM_SYMBOL_SLOTS
);
299 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_msymbol
);
300 SCM_SYMBOL_MULTI_BYTE_STRINGP (lsym
) = SCM_BOOL_F
;
301 SCM_SYMBOL_HASH (lsym
) = scm_hash
;
302 SCM_SYMBOL_PROPS (lsym
) = SCM_EOL
;
303 if (obarray
== SCM_BOOL_F
)
307 SCM_NEWCELL (answer
);
309 SCM_SETCAR (answer
, lsym
);
310 SCM_SETCDR (answer
, SCM_UNDEFINED
);
321 SCM_SETCAR (a
, lsym
);
322 SCM_SETCDR (a
, SCM_UNDEFINED
);
324 SCM_SETCDR (b
, SCM_VELTS(obarray
)[scm_hash
]);
325 SCM_VELTS(obarray
)[scm_hash
] = b
;
333 scm_intern_obarray (name
, len
, obarray
)
338 return scm_intern_obarray_soft (name
, len
, obarray
, 0);
343 scm_intern (name
, len
)
347 return scm_intern_obarray (name
, len
, scm_symhash
);
355 return scm_intern (name
, strlen (name
));
359 /* Intern the symbol named NAME in scm_symhash, and give it the value VAL.
360 NAME is null-terminated. */
362 scm_sysintern (name
, val
)
368 easy_answer
= scm_intern_obarray_soft (name
, strlen (name
), scm_symhash
, 1);
369 if (SCM_NIMP (easy_answer
))
371 SCM_SETCDR (easy_answer
, val
);
378 scm_sizet len
= strlen (name
);
379 register unsigned char *tmp
= (unsigned char *) name
;
380 scm_sizet scm_hash
= scm_strhash (tmp
, len
, (unsigned long) scm_symhash_dim
);
382 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_ssymbol
);
383 SCM_SETCHARS (lsym
, name
);
384 lsym
= scm_cons (lsym
, val
);
385 SCM_VELTS (scm_symhash
)[scm_hash
] = scm_cons (lsym
, SCM_VELTS (scm_symhash
)[scm_hash
]);
392 SCM_PROC(s_symbol_p
, "symbol?", 1, 0, 0, scm_symbol_p
);
398 if SCM_IMP(x
) return SCM_BOOL_F
;
399 return SCM_SYMBOLP(x
) ? SCM_BOOL_T
: SCM_BOOL_F
;
402 SCM_PROC(s_symbol_to_string
, "symbol->string", 1, 0, 0, scm_symbol_to_string
);
405 scm_symbol_to_string(s
)
408 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_to_string
);
409 return scm_makfromstr(SCM_CHARS(s
), (scm_sizet
)SCM_LENGTH(s
), 0);
413 SCM_PROC(s_string_to_symbol
, "string->symbol", 1, 0, 0, scm_string_to_symbol
);
416 scm_string_to_symbol(s
)
422 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG1
, s_string_to_symbol
);
423 vcell
= scm_intern(SCM_ROCHARS(s
), (scm_sizet
)SCM_LENGTH(s
));
424 answer
= SCM_CAR (vcell
);
425 if (SCM_TYP7 (answer
) == scm_tc7_msymbol
)
427 if (SCM_REGULAR_STRINGP (s
))
428 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_F
;
430 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_T
;
436 SCM_PROC(s_string_to_obarray_symbol
, "string->obarray-symbol", 2, 1, 0, scm_string_to_obarray_symbol
);
439 scm_string_to_obarray_symbol(o
, s
, softp
)
448 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG2
,
449 s_string_to_obarray_symbol
);
450 SCM_ASSERT((o
== SCM_BOOL_F
)
452 || (SCM_NIMP(o
) && SCM_VECTORP(o
)),
455 s_string_to_obarray_symbol
);
457 softness
= ((softp
!= SCM_UNDEFINED
) && (softp
!= SCM_BOOL_F
));
458 /* iron out some screwy calling conventions */
461 else if (o
== SCM_BOOL_T
)
464 vcell
= scm_intern_obarray_soft (SCM_ROCHARS(s
),
465 (scm_sizet
)SCM_ROLENGTH(s
),
468 if (vcell
== SCM_BOOL_F
)
470 answer
= SCM_CAR (vcell
);
471 if (SCM_TYP7 (s
) == scm_tc7_msymbol
)
473 if (SCM_REGULAR_STRINGP (s
))
474 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_F
;
476 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_T
;
481 SCM_PROC(s_intern_symbol
, "intern-symbol", 2, 0, 0, scm_intern_symbol
);
484 scm_intern_symbol(o
, s
)
489 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_intern_symbol
);
492 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_intern_symbol
);
493 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
494 /* If the symbol is already interned, simply return. */
499 for (lsym
= SCM_VELTS (o
)[hval
];
501 lsym
= SCM_CDR (lsym
))
503 sym
= SCM_CAR (lsym
);
504 if (SCM_CAR (sym
) == s
)
507 return SCM_UNSPECIFIED
;
510 SCM_VELTS (o
)[hval
] =
511 scm_acons (s
, SCM_UNDEFINED
, SCM_VELTS (o
)[hval
]);
514 return SCM_UNSPECIFIED
;
517 SCM_PROC(s_unintern_symbol
, "unintern-symbol", 2, 0, 0, scm_unintern_symbol
);
520 scm_unintern_symbol(o
, s
)
525 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_unintern_symbol
);
528 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_unintern_symbol
);
529 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
535 for (lsym
= SCM_VELTS (o
)[hval
], lsym_follow
= SCM_BOOL_F
;
537 lsym_follow
= lsym
, lsym
= SCM_CDR (lsym
))
539 sym
= SCM_CAR (lsym
);
540 if (SCM_CAR (sym
) == s
)
542 /* Found the symbol to unintern. */
543 if (lsym_follow
== SCM_BOOL_F
)
544 SCM_VELTS(o
)[hval
] = lsym
;
546 SCM_SETCDR (lsym_follow
, SCM_CDR(lsym
));
556 SCM_PROC(s_symbol_binding
, "symbol-binding", 2, 0, 0, scm_symbol_binding
);
559 scm_symbol_binding (o
, s
)
564 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_binding
);
567 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_binding
);
568 vcell
= scm_sym2ovcell (s
, o
);
569 return SCM_CDR(vcell
);
573 SCM_PROC(s_symbol_interned_p
, "symbol-interned?", 2, 0, 0, scm_symbol_interned_p
);
576 scm_symbol_interned_p (o
, s
)
581 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_interned_p
);
584 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_interned_p
);
585 vcell
= scm_sym2ovcell_soft (s
, o
);
586 if (SCM_IMP(vcell
) && (o
== scm_symhash
))
587 vcell
= scm_sym2ovcell_soft (s
, scm_weak_symhash
);
588 return (SCM_NIMP(vcell
)
594 SCM_PROC(s_symbol_bound_p
, "symbol-bound?", 2, 0, 0, scm_symbol_bound_p
);
597 scm_symbol_bound_p (o
, s
)
602 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_bound_p
);
605 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_bound_p
);
606 vcell
= scm_sym2ovcell_soft (s
, o
);
607 return (( SCM_NIMP(vcell
)
608 && (SCM_CDR(vcell
) != SCM_UNDEFINED
))
614 SCM_PROC(s_symbol_set_x
, "symbol-set!", 3, 0, 0, scm_symbol_set_x
);
617 scm_symbol_set_x (o
, s
, v
)
623 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_set_x
);
626 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_set_x
);
627 vcell
= scm_sym2ovcell (s
, o
);
628 SCM_SETCDR (vcell
, v
);
629 return SCM_UNSPECIFIED
;
637 string
= scm_makfromstr (SCM_CHARS (s
), SCM_LENGTH (s
), SCM_SYMBOL_SLOTS
);
638 SCM_SETCHARS (s
, SCM_CHARS (string
));
639 SCM_SETLENGTH (s
, SCM_LENGTH (s
), scm_tc7_msymbol
);
640 SCM_SYMBOL_MULTI_BYTE_STRINGP (s
) = SCM_BOOL_F
;
641 SCM_SETCDR (string
, SCM_EOL
);
642 SCM_SETCAR (string
, SCM_EOL
);
646 SCM_PROC(s_symbol_fref
, "symbol-fref", 1, 0, 0, scm_symbol_fref
);
652 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fref
);
654 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
657 return SCM_SYMBOL_FUNC (s
);
661 SCM_PROC(s_symbol_pref
, "symbol-pref", 1, 0, 0, scm_symbol_pref
);
667 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pref
);
669 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
672 return SCM_SYMBOL_PROPS (s
);
676 SCM_PROC(s_symbol_fset_x
, "symbol-fset!", 2, 0, 0, scm_symbol_fset_x
);
679 scm_symbol_fset_x (s
, val
)
683 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fset_x
);
685 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
688 SCM_SYMBOL_FUNC (s
) = val
;
689 return SCM_UNSPECIFIED
;
693 SCM_PROC(s_symbol_pset_x
, "symbol-pset!", 2, 0, 0, scm_symbol_pset_x
);
696 scm_symbol_pset_x (s
, val
)
700 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pset_x
);
702 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
704 SCM_SYMBOL_PROPS (s
) = val
;
706 return SCM_UNSPECIFIED
;
710 SCM_PROC(s_symbol_hash
, "symbol-hash", 1, 0, 0, scm_symbol_hash
);
716 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_hash
);
717 return SCM_MAKINUM ((unsigned long)s
^ SCM_SYMBOL_HASH (s
));