1 /* Copyright (C) 1995,1996,1997 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, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
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.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
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.
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.
40 * If you do not wish that, delete this exception notice. */
49 #include "mbstrings.h"
61 /* NUM_HASH_BUCKETS is the number of symbol scm_hash table buckets.
63 #define NUM_HASH_BUCKETS 137
73 scm_strhash (str
, len
, n
)
81 unsigned long h
= 264 % n
;
83 h
= ((h
<< 8) + ((unsigned) (scm_downcase (str
[h
% len
])))) % n
;
91 h
= ((h
<< 8) + ((unsigned) (scm_downcase (str
[--i
])))) % n
;
96 int scm_symhash_dim
= NUM_HASH_BUCKETS
;
100 * looks up the symbol in the symhash table.
104 scm_sym2vcell (sym
, thunk
, definep
)
111 SCM var
= scm_apply (thunk
, sym
, scm_cons(definep
, scm_listofnull
));
113 if (var
== SCM_BOOL_F
)
117 if (SCM_IMP(var
) || !SCM_VARIABLEP (var
))
118 scm_wta (sym
, "strangely interned symbol? ", "");
119 return SCM_VARVCELL (var
);
127 scm_sizet scm_hash
= scm_strhash (SCM_UCHARS (sym
), (scm_sizet
) SCM_LENGTH (sym
),
128 (unsigned long) scm_symhash_dim
);
131 for (lsym
= SCM_VELTS (scm_symhash
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
134 if (SCM_CAR (z
) == sym
)
141 for (lsym
= *(lsymp
= &SCM_VELTS (scm_weak_symhash
)[scm_hash
]);
143 lsym
= *(lsymp
= SCM_CDRLOC (lsym
)))
146 if (SCM_CAR (z
) == sym
)
148 if (SCM_NFALSEP (definep
))
150 /* Move handle from scm_weak_symhash to scm_symhash. */
151 *lsymp
= SCM_CDR (lsym
);
152 SCM_SETCDR (lsym
, SCM_VELTS(scm_symhash
)[scm_hash
]);
153 SCM_VELTS(scm_symhash
)[scm_hash
] = lsym
;
160 return scm_wta (sym
, "uninterned symbol? ", "");
165 * looks up the symbol in an arbitrary obarray.
169 scm_sym2ovcell_soft (sym
, obarray
)
176 scm_hash
= scm_strhash (SCM_UCHARS (sym
),
177 (scm_sizet
) SCM_LENGTH (sym
),
178 SCM_LENGTH (obarray
));
180 for (lsym
= SCM_VELTS (obarray
)[scm_hash
];
182 lsym
= SCM_CDR (lsym
))
185 if (SCM_CAR (z
) == sym
)
197 scm_sym2ovcell (sym
, obarray
)
202 answer
= scm_sym2ovcell_soft (sym
, obarray
);
203 if (answer
!= SCM_BOOL_F
)
205 scm_wta (sym
, "uninterned symbol? ", "");
206 return SCM_UNSPECIFIED
; /* not reached */
209 /* Intern a symbol whose name is the LEN characters at NAME in OBARRAY.
211 OBARRAY should be a vector of lists, indexed by the name's hash
212 value, modulo OBARRAY's length. Each list has the form
213 ((SYMBOL . VALUE) ...), where SYMBOL is a symbol, and VALUE is the
214 value associated with that symbol (in the current module? in the
217 To "intern" a symbol means: if OBARRAY already contains a symbol by
218 that name, return its (SYMBOL . VALUE) pair; otherwise, create a
219 new symbol, add the pair (SYMBOL . SCM_UNDEFINED) to the
220 appropriate list of the OBARRAY, and return the pair.
222 If softness is non-zero, don't create a symbol if it isn't already
223 in OBARRAY; instead, just return #f.
225 If OBARRAY is SCM_BOOL_F, create a symbol listed in no obarray and
226 return (SYMBOL . SCM_UNDEFINED).
228 If OBARRAY is scm_symhash, and that doesn't contain the symbol,
229 check scm_weak_symhash instead. */
233 scm_intern_obarray_soft (name
, len
, obarray
, softness
)
241 register scm_sizet i
;
242 register unsigned char *tmp
;
248 tmp
= (unsigned char *) name
;
250 if (obarray
== SCM_BOOL_F
)
252 scm_hash
= scm_strhash (tmp
, i
, 1019);
253 goto uninterned_symbol
;
256 scm_hash
= scm_strhash (tmp
, i
, SCM_LENGTH(obarray
));
258 /* softness == -1 used to mean that it was known that the symbol
259 wasn't already in the obarray. I don't think there are any
260 callers that use that case any more, but just in case...
266 for (lsym
= SCM_VELTS (obarray
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
270 tmp
= SCM_UCHARS (z
);
271 if (SCM_LENGTH (z
) != len
)
274 if (((unsigned char *) name
)[i
] != tmp
[i
])
285 if (obarray
== scm_symhash
)
287 obarray
= scm_weak_symhash
;
288 goto retry_new_obarray
;
298 lsym
= scm_makfromstr (name
, len
, SCM_SYMBOL_SLOTS
);
300 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_msymbol
);
301 SCM_SYMBOL_MULTI_BYTE_STRINGP (lsym
) = SCM_BOOL_F
;
302 SCM_SYMBOL_HASH (lsym
) = scm_hash
;
303 SCM_SYMBOL_PROPS (lsym
) = SCM_EOL
;
304 if (obarray
== SCM_BOOL_F
)
308 SCM_NEWCELL (answer
);
310 SCM_SETCAR (answer
, lsym
);
311 SCM_SETCDR (answer
, SCM_UNDEFINED
);
322 SCM_SETCAR (a
, lsym
);
323 SCM_SETCDR (a
, SCM_UNDEFINED
);
325 SCM_SETCDR (b
, SCM_VELTS(obarray
)[scm_hash
]);
326 SCM_VELTS(obarray
)[scm_hash
] = b
;
334 scm_intern_obarray (name
, len
, obarray
)
339 return scm_intern_obarray_soft (name
, len
, obarray
, 0);
344 scm_intern (name
, len
)
348 return scm_intern_obarray (name
, len
, scm_symhash
);
356 return scm_intern (name
, strlen (name
));
360 /* Intern the symbol named NAME in scm_symhash, NAME is null-terminated. */
362 scm_sysintern0_no_module_lookup (name
)
367 easy_answer
= scm_intern_obarray_soft (name
, strlen (name
), scm_symhash
, 1);
368 if (SCM_NIMP (easy_answer
))
376 scm_sizet len
= strlen (name
);
377 register unsigned char *tmp
= (unsigned char *) name
;
378 scm_sizet scm_hash
= scm_strhash (tmp
, len
, (unsigned long) scm_symhash_dim
);
380 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_ssymbol
);
381 SCM_SETCHARS (lsym
, name
);
382 lsym
= scm_cons (lsym
, SCM_UNDEFINED
);
383 SCM_VELTS (scm_symhash
)[scm_hash
] = scm_cons (lsym
, SCM_VELTS (scm_symhash
)[scm_hash
]);
390 /* Is it safe to access SCM_TOP_LEVEL_LOOKUP_CLOSURE_VAR?
392 int scm_can_use_top_level_lookup_closure_var
;
394 /* Intern the symbol named NAME in scm_symhash, and give it the value
395 VAL. NAME is null-terminated. Use the current top_level lookup
396 closure to give NAME its value.
399 scm_sysintern (name
, val
)
403 SCM vcell
= scm_sysintern0 (name
);
404 SCM_SETCDR (vcell
, val
);
409 scm_sysintern0 (name
)
413 if (scm_can_use_top_level_lookup_closure_var
&&
414 SCM_NIMP (lookup_proc
= SCM_CDR (scm_top_level_lookup_closure_var
)))
416 SCM sym
= SCM_CAR (scm_intern0 (name
));
417 SCM vcell
= scm_sym2vcell (sym
, lookup_proc
, SCM_BOOL_T
);
418 if (vcell
== SCM_BOOL_F
)
419 scm_misc_error ("sysintern", "can't define variable", sym
);
423 return scm_sysintern0_no_module_lookup (name
);
426 /* Lookup the value of the symbol named by the nul-terminated string
427 NAME in the current module. */
429 scm_symbol_value0 (name
)
432 /* This looks silly - we look up the symbol twice. But it is in
433 fact necessary given the current module system because the module
434 lookup closures are written in scheme which needs real symbols. */
435 SCM symbol
= scm_intern_obarray_soft (name
, strlen (name
), scm_symhash
, 0);
436 SCM vcell
= scm_sym2vcell (SCM_CAR (symbol
),
437 SCM_CDR (scm_top_level_lookup_closure_var
),
439 if (SCM_FALSEP (vcell
))
440 return SCM_UNDEFINED
;
441 return SCM_CDR (vcell
);
444 SCM_PROC(s_symbol_p
, "symbol?", 1, 0, 0, scm_symbol_p
);
450 if SCM_IMP(x
) return SCM_BOOL_F
;
451 return SCM_SYMBOLP(x
) ? SCM_BOOL_T
: SCM_BOOL_F
;
454 SCM_PROC(s_symbol_to_string
, "symbol->string", 1, 0, 0, scm_symbol_to_string
);
457 scm_symbol_to_string(s
)
460 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_to_string
);
461 return scm_makfromstr(SCM_CHARS(s
), (scm_sizet
)SCM_LENGTH(s
), 0);
465 SCM_PROC(s_string_to_symbol
, "string->symbol", 1, 0, 0, scm_string_to_symbol
);
468 scm_string_to_symbol(s
)
474 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG1
, s_string_to_symbol
);
475 vcell
= scm_intern(SCM_ROCHARS(s
), (scm_sizet
)SCM_LENGTH(s
));
476 answer
= SCM_CAR (vcell
);
477 if (SCM_TYP7 (answer
) == scm_tc7_msymbol
)
479 if (SCM_REGULAR_STRINGP (s
))
480 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_F
;
482 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_T
;
488 SCM_PROC(s_string_to_obarray_symbol
, "string->obarray-symbol", 2, 1, 0, scm_string_to_obarray_symbol
);
491 scm_string_to_obarray_symbol(o
, s
, softp
)
500 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG2
,
501 s_string_to_obarray_symbol
);
502 SCM_ASSERT((o
== SCM_BOOL_F
)
504 || (SCM_NIMP(o
) && SCM_VECTORP(o
)),
507 s_string_to_obarray_symbol
);
509 softness
= ((softp
!= SCM_UNDEFINED
) && (softp
!= SCM_BOOL_F
));
510 /* iron out some screwy calling conventions */
513 else if (o
== SCM_BOOL_T
)
516 vcell
= scm_intern_obarray_soft (SCM_ROCHARS(s
),
517 (scm_sizet
)SCM_ROLENGTH(s
),
520 if (vcell
== SCM_BOOL_F
)
522 answer
= SCM_CAR (vcell
);
523 if (SCM_TYP7 (s
) == scm_tc7_msymbol
)
525 if (SCM_REGULAR_STRINGP (s
))
526 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_F
;
528 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_T
;
533 SCM_PROC(s_intern_symbol
, "intern-symbol", 2, 0, 0, scm_intern_symbol
);
536 scm_intern_symbol(o
, s
)
541 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_intern_symbol
);
544 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_intern_symbol
);
545 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
546 /* If the symbol is already interned, simply return. */
551 for (lsym
= SCM_VELTS (o
)[hval
];
553 lsym
= SCM_CDR (lsym
))
555 sym
= SCM_CAR (lsym
);
556 if (SCM_CAR (sym
) == s
)
559 return SCM_UNSPECIFIED
;
562 SCM_VELTS (o
)[hval
] =
563 scm_acons (s
, SCM_UNDEFINED
, SCM_VELTS (o
)[hval
]);
566 return SCM_UNSPECIFIED
;
569 SCM_PROC(s_unintern_symbol
, "unintern-symbol", 2, 0, 0, scm_unintern_symbol
);
572 scm_unintern_symbol(o
, s
)
577 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_unintern_symbol
);
580 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_unintern_symbol
);
581 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
587 for (lsym
= SCM_VELTS (o
)[hval
], lsym_follow
= SCM_BOOL_F
;
589 lsym_follow
= lsym
, lsym
= SCM_CDR (lsym
))
591 sym
= SCM_CAR (lsym
);
592 if (SCM_CAR (sym
) == s
)
594 /* Found the symbol to unintern. */
595 if (lsym_follow
== SCM_BOOL_F
)
596 SCM_VELTS(o
)[hval
] = lsym
;
598 SCM_SETCDR (lsym_follow
, SCM_CDR(lsym
));
608 SCM_PROC(s_symbol_binding
, "symbol-binding", 2, 0, 0, scm_symbol_binding
);
611 scm_symbol_binding (o
, s
)
616 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_binding
);
619 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_binding
);
620 vcell
= scm_sym2ovcell (s
, o
);
621 return SCM_CDR(vcell
);
625 SCM_PROC(s_symbol_interned_p
, "symbol-interned?", 2, 0, 0, scm_symbol_interned_p
);
628 scm_symbol_interned_p (o
, s
)
633 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_interned_p
);
636 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_interned_p
);
637 vcell
= scm_sym2ovcell_soft (s
, o
);
638 if (SCM_IMP(vcell
) && (o
== scm_symhash
))
639 vcell
= scm_sym2ovcell_soft (s
, scm_weak_symhash
);
640 return (SCM_NIMP(vcell
)
646 SCM_PROC(s_symbol_bound_p
, "symbol-bound?", 2, 0, 0, scm_symbol_bound_p
);
649 scm_symbol_bound_p (o
, s
)
654 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_bound_p
);
657 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_bound_p
);
658 vcell
= scm_sym2ovcell_soft (s
, o
);
659 return (( SCM_NIMP(vcell
)
660 && (SCM_CDR(vcell
) != SCM_UNDEFINED
))
666 SCM_PROC(s_symbol_set_x
, "symbol-set!", 3, 0, 0, scm_symbol_set_x
);
669 scm_symbol_set_x (o
, s
, v
)
675 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_set_x
);
678 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_set_x
);
679 vcell
= scm_sym2ovcell (s
, o
);
680 SCM_SETCDR (vcell
, v
);
681 return SCM_UNSPECIFIED
;
689 string
= scm_makfromstr (SCM_CHARS (s
), SCM_LENGTH (s
), SCM_SYMBOL_SLOTS
);
690 SCM_SETCHARS (s
, SCM_CHARS (string
));
691 SCM_SETLENGTH (s
, SCM_LENGTH (s
), scm_tc7_msymbol
);
692 SCM_SYMBOL_MULTI_BYTE_STRINGP (s
) = SCM_BOOL_F
;
693 SCM_SETCDR (string
, SCM_EOL
);
694 SCM_SETCAR (string
, SCM_EOL
);
695 SCM_SYMBOL_PROPS (s
) = SCM_EOL
;
696 /* If it's a tc7_ssymbol, it comes from scm_symhash */
697 SCM_SYMBOL_HASH (s
) = scm_strhash (SCM_UCHARS (s
),
698 (scm_sizet
) SCM_LENGTH (s
),
699 SCM_LENGTH (scm_symhash
));
703 SCM_PROC(s_symbol_fref
, "symbol-fref", 1, 0, 0, scm_symbol_fref
);
709 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fref
);
711 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
714 return SCM_SYMBOL_FUNC (s
);
718 SCM_PROC(s_symbol_pref
, "symbol-pref", 1, 0, 0, scm_symbol_pref
);
724 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pref
);
726 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
729 return SCM_SYMBOL_PROPS (s
);
733 SCM_PROC(s_symbol_fset_x
, "symbol-fset!", 2, 0, 0, scm_symbol_fset_x
);
736 scm_symbol_fset_x (s
, val
)
740 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fset_x
);
742 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
745 SCM_SYMBOL_FUNC (s
) = val
;
746 return SCM_UNSPECIFIED
;
750 SCM_PROC(s_symbol_pset_x
, "symbol-pset!", 2, 0, 0, scm_symbol_pset_x
);
753 scm_symbol_pset_x (s
, val
)
757 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pset_x
);
759 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
761 SCM_SYMBOL_PROPS (s
) = val
;
763 return SCM_UNSPECIFIED
;
767 SCM_PROC(s_symbol_hash
, "symbol-hash", 1, 0, 0, scm_symbol_hash
);
773 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_hash
);
774 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
776 return SCM_MAKINUM ((unsigned long)s
^ SCM_SYMBOL_HASH (s
));
780 static void copy_and_prune_obarray
SCM_P ((SCM from
, SCM to
));
783 copy_and_prune_obarray (from
, to
)
788 int length
= SCM_LENGTH (from
);
789 for (i
= 0; i
< length
; ++i
)
791 SCM head
= SCM_VELTS (from
)[i
]; /* GC protection */
795 while (SCM_NIMP (ls
))
797 if (!SCM_UNBNDP (SCM_CDAR (ls
)))
799 *lloc
= scm_cons (SCM_CAR (ls
), SCM_EOL
);
800 lloc
= SCM_CDRLOC (*lloc
);
804 SCM_VELTS (to
)[i
] = res
;
809 SCM_PROC(s_builtin_bindings
, "builtin-bindings", 0, 0, 0, scm_builtin_bindings
);
812 scm_builtin_bindings ()
814 int length
= SCM_LENGTH (scm_symhash
);
815 SCM obarray
= scm_make_vector (SCM_MAKINUM (length
), SCM_EOL
, SCM_UNDEFINED
);
816 copy_and_prune_obarray (scm_symhash
, obarray
);
821 SCM_PROC(s_builtin_weak_bindings
, "builtin-weak-bindings", 0, 0, 0, scm_builtin_weak_bindings
);
824 scm_builtin_weak_bindings ()
826 int length
= SCM_LENGTH (scm_weak_symhash
);
827 SCM obarray
= scm_make_doubly_weak_hash_table (SCM_MAKINUM (length
));
828 copy_and_prune_obarray (scm_weak_symhash
, obarray
);