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, 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
)
147 if (SCM_NFALSEP (definep
))
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, NAME is null-terminated. */
361 scm_sysintern0_no_module_lookup (name
)
366 easy_answer
= scm_intern_obarray_soft (name
, strlen (name
), scm_symhash
, 1);
367 if (SCM_NIMP (easy_answer
))
375 scm_sizet len
= strlen (name
);
376 register unsigned char *tmp
= (unsigned char *) name
;
377 scm_sizet scm_hash
= scm_strhash (tmp
, len
, (unsigned long) scm_symhash_dim
);
379 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_ssymbol
);
380 SCM_SETCHARS (lsym
, name
);
381 lsym
= scm_cons (lsym
, SCM_UNDEFINED
);
382 SCM_VELTS (scm_symhash
)[scm_hash
] = scm_cons (lsym
, SCM_VELTS (scm_symhash
)[scm_hash
]);
389 /* Is it safe to access SCM_TOP_LEVEL_LOOKUP_CLOSURE_VAR?
391 int scm_can_use_top_level_lookup_closure_var
;
393 /* Intern the symbol named NAME in scm_symhash, and give it the value
394 VAL. NAME is null-terminated. Use the current top_level lookup
395 closure to give NAME its value.
398 scm_sysintern (name
, val
)
402 SCM vcell
= scm_sysintern0 (name
);
403 SCM_SETCDR (vcell
, val
);
408 scm_sysintern0 (name
)
412 if (scm_can_use_top_level_lookup_closure_var
&&
413 SCM_NIMP (lookup_proc
= SCM_CDR (scm_top_level_lookup_closure_var
)))
415 SCM sym
= SCM_CAR (scm_intern0 (name
));
416 SCM vcell
= scm_sym2vcell (sym
, lookup_proc
, SCM_BOOL_T
);
417 if (vcell
== SCM_BOOL_F
)
418 scm_misc_error ("sysintern", "can't define variable", sym
);
422 return scm_sysintern0_no_module_lookup (name
);
425 /* Lookup the value of the symbol named by the nul-terminated string
426 NAME in the current module. */
428 scm_symbol_value0 (name
)
431 /* This looks silly - we look up the symbol twice. But it is in
432 fact necessary given the current module system because the module
433 lookup closures are written in scheme which needs real symbols. */
434 SCM symbol
= scm_intern_obarray_soft (name
, strlen (name
), scm_symhash
, 0);
435 SCM vcell
= scm_sym2vcell (SCM_CAR (symbol
),
436 SCM_CDR (scm_top_level_lookup_closure_var
),
438 if (SCM_FALSEP (vcell
))
439 return SCM_UNDEFINED
;
440 return SCM_CDR (vcell
);
443 SCM_PROC(s_symbol_p
, "symbol?", 1, 0, 0, scm_symbol_p
);
449 if SCM_IMP(x
) return SCM_BOOL_F
;
450 return SCM_SYMBOLP(x
) ? SCM_BOOL_T
: SCM_BOOL_F
;
453 SCM_PROC(s_symbol_to_string
, "symbol->string", 1, 0, 0, scm_symbol_to_string
);
456 scm_symbol_to_string(s
)
459 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_to_string
);
460 return scm_makfromstr(SCM_CHARS(s
), (scm_sizet
)SCM_LENGTH(s
), 0);
464 SCM_PROC(s_string_to_symbol
, "string->symbol", 1, 0, 0, scm_string_to_symbol
);
467 scm_string_to_symbol(s
)
473 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG1
, s_string_to_symbol
);
474 vcell
= scm_intern(SCM_ROCHARS(s
), (scm_sizet
)SCM_LENGTH(s
));
475 answer
= SCM_CAR (vcell
);
476 if (SCM_TYP7 (answer
) == scm_tc7_msymbol
)
478 if (SCM_REGULAR_STRINGP (s
))
479 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_F
;
481 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_T
;
487 SCM_PROC(s_string_to_obarray_symbol
, "string->obarray-symbol", 2, 1, 0, scm_string_to_obarray_symbol
);
490 scm_string_to_obarray_symbol(o
, s
, softp
)
499 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG2
,
500 s_string_to_obarray_symbol
);
501 SCM_ASSERT((o
== SCM_BOOL_F
)
503 || (SCM_NIMP(o
) && SCM_VECTORP(o
)),
506 s_string_to_obarray_symbol
);
508 softness
= ((softp
!= SCM_UNDEFINED
) && (softp
!= SCM_BOOL_F
));
509 /* iron out some screwy calling conventions */
512 else if (o
== SCM_BOOL_T
)
515 vcell
= scm_intern_obarray_soft (SCM_ROCHARS(s
),
516 (scm_sizet
)SCM_ROLENGTH(s
),
519 if (vcell
== SCM_BOOL_F
)
521 answer
= SCM_CAR (vcell
);
522 if (SCM_TYP7 (s
) == scm_tc7_msymbol
)
524 if (SCM_REGULAR_STRINGP (s
))
525 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_F
;
527 SCM_SYMBOL_MULTI_BYTE_STRINGP (answer
) = SCM_BOOL_T
;
532 SCM_PROC(s_intern_symbol
, "intern-symbol", 2, 0, 0, scm_intern_symbol
);
535 scm_intern_symbol(o
, s
)
540 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_intern_symbol
);
543 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_intern_symbol
);
544 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
545 /* If the symbol is already interned, simply return. */
550 for (lsym
= SCM_VELTS (o
)[hval
];
552 lsym
= SCM_CDR (lsym
))
554 sym
= SCM_CAR (lsym
);
555 if (SCM_CAR (sym
) == s
)
558 return SCM_UNSPECIFIED
;
561 SCM_VELTS (o
)[hval
] =
562 scm_acons (s
, SCM_UNDEFINED
, SCM_VELTS (o
)[hval
]);
565 return SCM_UNSPECIFIED
;
568 SCM_PROC(s_unintern_symbol
, "unintern-symbol", 2, 0, 0, scm_unintern_symbol
);
571 scm_unintern_symbol(o
, s
)
576 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_unintern_symbol
);
579 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_unintern_symbol
);
580 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
586 for (lsym
= SCM_VELTS (o
)[hval
], lsym_follow
= SCM_BOOL_F
;
588 lsym_follow
= lsym
, lsym
= SCM_CDR (lsym
))
590 sym
= SCM_CAR (lsym
);
591 if (SCM_CAR (sym
) == s
)
593 /* Found the symbol to unintern. */
594 if (lsym_follow
== SCM_BOOL_F
)
595 SCM_VELTS(o
)[hval
] = lsym
;
597 SCM_SETCDR (lsym_follow
, SCM_CDR(lsym
));
607 SCM_PROC(s_symbol_binding
, "symbol-binding", 2, 0, 0, scm_symbol_binding
);
610 scm_symbol_binding (o
, s
)
615 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_binding
);
618 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_binding
);
619 vcell
= scm_sym2ovcell (s
, o
);
620 return SCM_CDR(vcell
);
624 SCM_PROC(s_symbol_interned_p
, "symbol-interned?", 2, 0, 0, scm_symbol_interned_p
);
627 scm_symbol_interned_p (o
, s
)
632 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_interned_p
);
635 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_interned_p
);
636 vcell
= scm_sym2ovcell_soft (s
, o
);
637 if (SCM_IMP(vcell
) && (o
== scm_symhash
))
638 vcell
= scm_sym2ovcell_soft (s
, scm_weak_symhash
);
639 return (SCM_NIMP(vcell
)
645 SCM_PROC(s_symbol_bound_p
, "symbol-bound?", 2, 0, 0, scm_symbol_bound_p
);
648 scm_symbol_bound_p (o
, s
)
653 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_bound_p
);
656 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_bound_p
);
657 vcell
= scm_sym2ovcell_soft (s
, o
);
658 return (( SCM_NIMP(vcell
)
659 && (SCM_CDR(vcell
) != SCM_UNDEFINED
))
665 SCM_PROC(s_symbol_set_x
, "symbol-set!", 3, 0, 0, scm_symbol_set_x
);
668 scm_symbol_set_x (o
, s
, v
)
674 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_set_x
);
677 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_set_x
);
678 vcell
= scm_sym2ovcell (s
, o
);
679 SCM_SETCDR (vcell
, v
);
680 return SCM_UNSPECIFIED
;
688 string
= scm_makfromstr (SCM_CHARS (s
), SCM_LENGTH (s
), SCM_SYMBOL_SLOTS
);
689 SCM_SETCHARS (s
, SCM_CHARS (string
));
690 SCM_SETLENGTH (s
, SCM_LENGTH (s
), scm_tc7_msymbol
);
691 SCM_SYMBOL_MULTI_BYTE_STRINGP (s
) = SCM_BOOL_F
;
692 SCM_SETCDR (string
, SCM_EOL
);
693 SCM_SETCAR (string
, SCM_EOL
);
697 SCM_PROC(s_symbol_fref
, "symbol-fref", 1, 0, 0, scm_symbol_fref
);
703 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fref
);
705 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
708 return SCM_SYMBOL_FUNC (s
);
712 SCM_PROC(s_symbol_pref
, "symbol-pref", 1, 0, 0, scm_symbol_pref
);
718 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pref
);
720 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
723 return SCM_SYMBOL_PROPS (s
);
727 SCM_PROC(s_symbol_fset_x
, "symbol-fset!", 2, 0, 0, scm_symbol_fset_x
);
730 scm_symbol_fset_x (s
, val
)
734 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fset_x
);
736 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
739 SCM_SYMBOL_FUNC (s
) = val
;
740 return SCM_UNSPECIFIED
;
744 SCM_PROC(s_symbol_pset_x
, "symbol-pset!", 2, 0, 0, scm_symbol_pset_x
);
747 scm_symbol_pset_x (s
, val
)
751 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pset_x
);
753 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
755 SCM_SYMBOL_PROPS (s
) = val
;
757 return SCM_UNSPECIFIED
;
761 SCM_PROC(s_symbol_hash
, "symbol-hash", 1, 0, 0, scm_symbol_hash
);
767 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_hash
);
768 return SCM_MAKINUM ((unsigned long)s
^ SCM_SYMBOL_HASH (s
));