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.
53 /* NUM_HASH_BUCKETS is the number of symbol scm_hash table buckets.
55 #define NUM_HASH_BUCKETS 137
65 scm_strhash (unsigned char *str
, scm_sizet len
, unsigned long n
)
68 scm_strhash (str
, len
, n
)
77 unsigned long h
= 264 % n
;
79 h
= ((h
<< 8) + ((unsigned) (scm_downcase
[str
[h
% len
]]))) % n
;
87 h
= ((h
<< 8) + ((unsigned) (scm_downcase
[str
[--i
]]))) % n
;
92 int scm_symhash_dim
= NUM_HASH_BUCKETS
;
96 * looks up the symbol in the symhash table.
100 scm_sym2vcell (SCM sym
, SCM thunk
, SCM definep
)
103 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_CDR (lsym
)))
146 if (SCM_CAR (z
) == sym
)
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 (defaulting to scm_symhash).
168 scm_sym2ovcell_soft (SCM sym
, SCM obarray
)
171 scm_sym2ovcell_soft (sym
, obarray
)
179 scm_hash
= scm_strhash (SCM_UCHARS (sym
),
180 (scm_sizet
) SCM_LENGTH (sym
),
181 SCM_LENGTH (obarray
));
183 for (lsym
= SCM_VELTS (obarray
)[scm_hash
];
185 lsym
= SCM_CDR (lsym
))
188 if (SCM_CAR (z
) == sym
)
200 scm_sym2ovcell (SCM sym
, SCM obarray
)
203 scm_sym2ovcell (sym
, obarray
)
209 answer
= scm_sym2ovcell_soft (sym
, obarray
);
210 if (answer
!= SCM_BOOL_F
)
212 scm_wta (sym
, "uninterned symbol? ", "");
213 return SCM_UNSPECIFIED
; /* not reached */
218 scm_intern_obarray_soft (char *name
, scm_sizet len
, SCM obarray
, int softness
)
221 scm_intern_obarray_soft (name
, len
, obarray
, softness
)
230 register scm_sizet i
;
231 register unsigned char *tmp
;
237 tmp
= (unsigned char *) name
;
239 if (obarray
== SCM_BOOL_F
)
241 scm_hash
= scm_strhash (tmp
, i
, 1019);
242 goto uninterned_symbol
;
245 scm_hash
= scm_strhash (tmp
, i
, SCM_LENGTH(obarray
));
248 goto mustintern_symbol
;
251 for (lsym
= SCM_VELTS (obarray
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
255 tmp
= SCM_UCHARS (z
);
256 if (SCM_LENGTH (z
) != len
)
259 if (((unsigned char *) name
)[i
] != tmp
[i
])
270 if (obarray
== scm_symhash
)
272 obarray
= scm_weak_symhash
;
273 goto retry_new_obarray
;
284 lsym
= scm_makfromstr (name
, len
, SCM_SYMBOL_SLOTS
);
286 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_msymbol
);
287 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (lsym
) = SCM_BOOL_F
;
288 SCM_SYMBOL_HASH (lsym
) = scm_hash
;
289 if (obarray
== SCM_BOOL_F
)
293 SCM_NEWCELL (answer
);
295 SCM_CAR (answer
) = lsym
;
296 SCM_CDR (answer
) = SCM_UNDEFINED
;
307 SCM_SETCAR (a
, lsym
);
308 SCM_SETCDR (a
, SCM_UNDEFINED
);
310 SCM_SETCDR (b
, SCM_VELTS(obarray
)[scm_hash
]);
311 SCM_VELTS(obarray
)[scm_hash
] = b
;
319 scm_intern_obarray (char *name
, scm_sizet len
, SCM obarray
)
322 scm_intern_obarray (name
, len
, obarray
)
328 return scm_intern_obarray_soft (name
, len
, obarray
, 0);
334 scm_intern (char *name
, scm_sizet len
)
337 scm_intern (name
, len
)
342 return scm_intern_obarray (name
, len
, scm_symhash
);
347 scm_intern0 (char * name
)
354 return scm_intern (name
, strlen (name
));
360 scm_sysintern (char *name
, SCM val
)
363 scm_sysintern (name
, val
)
370 easy_answer
= scm_intern_obarray_soft (name
, strlen (name
), scm_symhash
, 1);
371 if (SCM_NIMP (easy_answer
))
373 SCM_CDR (easy_answer
) = val
;
380 scm_sizet len
= strlen (name
);
381 register unsigned char *tmp
= (unsigned char *) name
;
382 scm_sizet scm_hash
= scm_strhash (tmp
, len
, (unsigned long) scm_symhash_dim
);
384 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_ssymbol
);
385 SCM_SETCHARS (lsym
, name
);
386 lsym
= scm_cons (lsym
, val
);
387 SCM_VELTS (scm_symhash
)[scm_hash
] = scm_cons (lsym
, SCM_VELTS (scm_symhash
)[scm_hash
]);
394 SCM_PROC(s_symbol_p
, "symbol?", 1, 0, 0, scm_symbol_p
);
404 if SCM_IMP(x
) return SCM_BOOL_F
;
405 return SCM_SYMBOLP(x
) ? SCM_BOOL_T
: SCM_BOOL_F
;
408 SCM_PROC(s_symbol_to_string
, "symbol->string", 1, 0, 0, scm_symbol_to_string
);
411 scm_symbol_to_string(SCM s
)
414 scm_symbol_to_string(s
)
418 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_to_string
);
419 return scm_makfromstr(SCM_CHARS(s
), (scm_sizet
)SCM_LENGTH(s
), 0);
423 SCM_PROC(s_string_to_symbol
, "string->symbol", 1, 0, 0, scm_string_to_symbol
);
426 scm_string_to_symbol(SCM s
)
429 scm_string_to_symbol(s
)
436 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG1
, s_string_to_symbol
);
437 vcell
= scm_intern(SCM_ROCHARS(s
), (scm_sizet
)SCM_LENGTH(s
));
438 answer
= SCM_CAR (vcell
);
439 if (SCM_TYP7 (answer
) == scm_tc7_msymbol
)
441 if (SCM_REGULAR_STRINGP (s
))
442 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_F
;
444 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_T
;
450 SCM_PROC(s_string_to_obarray_symbol
, "string->obarray-symbol", 2, 1, 0, scm_string_to_obarray_symbol
);
453 scm_string_to_obarray_symbol(SCM o
, SCM s
, SCM softp
)
456 scm_string_to_obarray_symbol(o
, s
, softp
)
466 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG2
, s_string_to_obarray_symbol
);
467 SCM_ASSERT((o
== SCM_BOOL_F
) || (o
== SCM_BOOL_T
) || (SCM_NIMP(o
) && SCM_VECTORP(o
)),
468 o
, SCM_ARG1
, s_string_to_obarray_symbol
);
470 softness
= ((softp
!= SCM_UNDEFINED
) && (softp
!= SCM_BOOL_F
));
471 /* iron out some screwy calling conventions */
474 else if (o
== SCM_BOOL_T
)
477 vcell
= scm_intern_obarray_soft (SCM_ROCHARS(s
), (scm_sizet
)SCM_ROLENGTH(s
), o
, softness
);
478 if (vcell
== SCM_BOOL_F
)
480 answer
= SCM_CAR (vcell
);
481 if (SCM_TYP7 (s
) == scm_tc7_msymbol
)
483 if (SCM_REGULAR_STRINGP (s
))
484 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_F
;
486 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_T
;
491 SCM_PROC(s_intern_symbol
, "intern-symbol", 2, 0, 0, scm_intern_symbol
);
494 scm_intern_symbol(SCM o
, SCM s
)
497 scm_intern_symbol(o
, s
)
503 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_intern_symbol
);
506 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_intern_symbol
);
507 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
508 /* If the symbol is already interned, simply return. */
513 for (lsym
= SCM_VELTS (o
)[hval
];
515 lsym
= SCM_CDR (lsym
))
517 sym
= SCM_CAR (lsym
);
518 if (SCM_CAR (sym
) == s
)
521 return SCM_UNSPECIFIED
;
524 SCM_VELTS (o
)[hval
] =
525 scm_acons (s
, SCM_UNDEFINED
, SCM_VELTS (o
)[hval
]);
528 return SCM_UNSPECIFIED
;
531 SCM_PROC(s_unintern_symbol
, "unintern-symbol", 2, 0, 0, scm_unintern_symbol
);
534 scm_unintern_symbol(SCM o
, SCM s
)
537 scm_unintern_symbol(o
, s
)
543 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_unintern_symbol
);
546 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_unintern_symbol
);
547 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
553 for (lsym
= SCM_VELTS (o
)[hval
], lsym_follow
= SCM_BOOL_F
;
555 lsym_follow
= lsym
, lsym
= SCM_CDR (lsym
))
557 sym
= SCM_CAR (lsym
);
558 if (SCM_CAR (sym
) == s
)
560 /* Found the symbol to unintern. */
561 if (lsym_follow
== SCM_BOOL_F
)
562 SCM_VELTS(o
)[hval
] = lsym
;
564 SCM_CDR(lsym_follow
) = SCM_CDR(lsym
);
574 SCM_PROC(s_symbol_binding
, "symbol-binding", 2, 0, 0, scm_symbol_binding
);
577 scm_symbol_binding (SCM o
, SCM s
)
580 scm_symbol_binding (o
, s
)
586 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_binding
);
589 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_binding
);
590 vcell
= scm_sym2ovcell (s
, o
);
591 return SCM_CDR(vcell
);
595 SCM_PROC(s_symbol_interned_p
, "symbol-interned?", 2, 0, 0, scm_symbol_interned_p
);
598 scm_symbol_interned_p (SCM o
, SCM s
)
601 scm_symbol_interned_p (o
, s
)
607 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_interned_p
);
610 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_interned_p
);
611 vcell
= scm_sym2ovcell_soft (s
, o
);
612 if (SCM_IMP(vcell
) && (o
== scm_symhash
))
613 vcell
= scm_sym2ovcell_soft (s
, scm_weak_symhash
);
614 return (SCM_NIMP(vcell
)
620 SCM_PROC(s_symbol_bound_p
, "symbol-bound?", 2, 0, 0, scm_symbol_bound_p
);
623 scm_symbol_bound_p (SCM o
, SCM s
)
626 scm_symbol_bound_p (o
, s
)
632 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_bound_p
);
635 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_bound_p
);
636 vcell
= scm_sym2ovcell_soft (s
, o
);
637 return (( SCM_NIMP(vcell
)
638 && (SCM_CDR(vcell
) != SCM_UNDEFINED
))
644 SCM_PROC(s_symbol_set_x
, "symbol-set!", 3, 0, 0, scm_symbol_set_x
);
647 scm_symbol_set_x (SCM o
, SCM s
, SCM v
)
650 scm_symbol_set_x (o
, s
, v
)
657 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_set_x
);
660 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_set_x
);
661 vcell
= scm_sym2ovcell (s
, o
);
663 return SCM_UNSPECIFIED
;
671 string
= scm_makfromstr (SCM_CHARS (s
), SCM_LENGTH (s
), SCM_SYMBOL_SLOTS
);
672 SCM_SETCHARS (s
, SCM_CHARS (string
));
673 SCM_SETLENGTH (s
, SCM_LENGTH (s
), scm_tc7_msymbol
);
674 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (s
) = SCM_BOOL_F
;
675 SCM_CDR (string
) = SCM_EOL
;
676 SCM_CAR (string
) = SCM_EOL
;
680 SCM_PROC(s_symbol_fref
, "symbol-fref", 1, 0, 0, scm_symbol_fref
);
683 scm_symbol_fref (SCM s
)
690 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fref
);
692 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
695 return SCM_SYMBOL_FUNC (s
);
699 SCM_PROC(s_symbol_pref
, "symbol-pref", 1, 0, 0, scm_symbol_pref
);
702 scm_symbol_pref (SCM s
)
709 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pref
);
711 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
714 return SCM_SYMBOL_PROPS (s
);
718 SCM_PROC(s_symbol_fset_x
, "symbol-fset!", 2, 0, 0, scm_symbol_fset_x
);
721 scm_symbol_fset_x (SCM s
, SCM val
)
724 scm_symbol_fset_x (s
, val
)
729 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fset_x
);
731 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
734 SCM_SYMBOL_FUNC (s
) = val
;
735 return SCM_UNSPECIFIED
;
739 SCM_PROC(s_symbol_pset_x
, "symbol-pset!", 2, 0, 0, scm_symbol_pset_x
);
742 scm_symbol_pset_x (SCM s
, SCM val
)
745 scm_symbol_pset_x (s
, val
)
750 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pset_x
);
752 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
754 SCM_SYMBOL_PROPS (s
) = val
;
756 return SCM_UNSPECIFIED
;
760 SCM_PROC(s_symbol_hash
, "symbol-hash", 1, 0, 0, scm_symbol_hash
);
763 scm_symbol_hash (SCM s
)
770 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_hash
);
771 return SCM_MAKINUM ((unsigned long)s
^ SCM_SYMBOL_HASH (s
));
777 scm_init_symbols (void)