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 /* NUM_HASH_BUCKETS is the number of symbol scm_hash table buckets.
51 #define NUM_HASH_BUCKETS 137
61 scm_strhash (unsigned char *str
, scm_sizet len
, unsigned long n
)
64 scm_strhash (str
, len
, n
)
73 unsigned long h
= 264 % n
;
75 h
= ((h
<< 8) + ((unsigned) (scm_downcase
[str
[h
% len
]]))) % n
;
83 h
= ((h
<< 8) + ((unsigned) (scm_downcase
[str
[--i
]]))) % n
;
88 int scm_symhash_dim
= NUM_HASH_BUCKETS
;
92 * looks up the symbol in the symhash table.
96 scm_sym2vcell (SCM sym
, SCM thunk
, SCM definep
)
99 scm_sym2vcell (sym
, thunk
, definep
)
107 SCM var
= scm_apply (thunk
, sym
, scm_cons(definep
, scm_listofnull
));
109 if (var
== SCM_BOOL_F
)
113 if (SCM_IMP(var
) || !SCM_VARIABLEP (var
))
114 scm_wta (sym
, "strangely interned symbol? ", "");
115 return SCM_VARVCELL (var
);
123 scm_sizet scm_hash
= scm_strhash (SCM_UCHARS (sym
), (scm_sizet
) SCM_LENGTH (sym
),
124 (unsigned long) scm_symhash_dim
);
127 for (lsym
= SCM_VELTS (scm_symhash
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
130 if (SCM_CAR (z
) == sym
)
137 for (lsym
= *(lsymp
= &SCM_VELTS (scm_weak_symhash
)[scm_hash
]);
139 lsym
= *(lsymp
= &SCM_CDR (lsym
)))
142 if (SCM_CAR (z
) == sym
)
146 *lsymp
= SCM_CDR (lsym
);
147 SCM_SETCDR (lsym
, SCM_VELTS(scm_symhash
)[scm_hash
]);
148 SCM_VELTS(scm_symhash
)[scm_hash
] = lsym
;
155 return scm_wta (sym
, "uninterned symbol? ", "");
160 * looks up the symbol in an arbitrary obarray (defaulting to scm_symhash).
164 scm_sym2ovcell_soft (SCM sym
, SCM obarray
)
167 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 (SCM sym
, SCM obarray
)
199 scm_sym2ovcell (sym
, obarray
)
205 answer
= scm_sym2ovcell_soft (sym
, obarray
);
206 if (answer
!= SCM_BOOL_F
)
208 scm_wta (sym
, "uninterned symbol? ", "");
209 return SCM_UNSPECIFIED
; /* not reached */
214 scm_intern_obarray_soft (char *name
, scm_sizet len
, SCM obarray
, int softness
)
217 scm_intern_obarray_soft (name
, len
, obarray
, softness
)
226 register scm_sizet i
;
227 register unsigned char *tmp
;
233 tmp
= (unsigned char *) name
;
235 if (obarray
== SCM_BOOL_F
)
237 scm_hash
= scm_strhash (tmp
, i
, 1019);
238 goto uninterned_symbol
;
241 scm_hash
= scm_strhash (tmp
, i
, SCM_LENGTH(obarray
));
244 goto mustintern_symbol
;
247 for (lsym
= SCM_VELTS (obarray
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
251 tmp
= SCM_UCHARS (z
);
252 if (SCM_LENGTH (z
) != len
)
255 if (((unsigned char *) name
)[i
] != tmp
[i
])
266 if (obarray
== scm_symhash
)
268 obarray
= scm_weak_symhash
;
269 goto retry_new_obarray
;
280 lsym
= scm_makfromstr (name
, len
, SCM_SYMBOL_SLOTS
);
282 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_msymbol
);
283 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (lsym
) = SCM_BOOL_F
;
284 SCM_SYMBOL_HASH (lsym
) = scm_hash
;
285 if (obarray
== SCM_BOOL_F
)
289 SCM_NEWCELL (answer
);
291 SCM_CAR (answer
) = lsym
;
292 SCM_CDR (answer
) = SCM_UNDEFINED
;
303 SCM_SETCAR (a
, lsym
);
304 SCM_SETCDR (a
, SCM_UNDEFINED
);
306 SCM_SETCDR (b
, SCM_VELTS(obarray
)[scm_hash
]);
307 SCM_VELTS(obarray
)[scm_hash
] = b
;
315 scm_intern_obarray (char *name
, scm_sizet len
, SCM obarray
)
318 scm_intern_obarray (name
, len
, obarray
)
324 return scm_intern_obarray_soft (name
, len
, obarray
, 0);
330 scm_intern (char *name
, scm_sizet len
)
333 scm_intern (name
, len
)
338 return scm_intern_obarray (name
, len
, scm_symhash
);
343 scm_intern0 (char * name
)
350 return scm_intern (name
, strlen (name
));
356 scm_sysintern (char *name
, SCM val
)
359 scm_sysintern (name
, val
)
366 easy_answer
= scm_intern_obarray_soft (name
, strlen (name
), scm_symhash
, 1);
367 if (SCM_NIMP (easy_answer
))
369 SCM_CDR (easy_answer
) = val
;
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
, val
);
383 SCM_VELTS (scm_symhash
)[scm_hash
] = scm_cons (lsym
, SCM_VELTS (scm_symhash
)[scm_hash
]);
390 SCM_PROC(s_symbol_p
, "symbol?", 1, 0, 0, scm_symbol_p
);
400 if SCM_IMP(x
) return SCM_BOOL_F
;
401 return SCM_SYMBOLP(x
) ? SCM_BOOL_T
: SCM_BOOL_F
;
404 SCM_PROC(s_symbol_to_string
, "symbol->string", 1, 0, 0, scm_symbol_to_string
);
407 scm_symbol_to_string(SCM s
)
410 scm_symbol_to_string(s
)
414 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_to_string
);
415 return scm_makfromstr(SCM_CHARS(s
), (scm_sizet
)SCM_LENGTH(s
), 0);
419 SCM_PROC(s_string_to_symbol
, "string->symbol", 1, 0, 0, scm_string_to_symbol
);
422 scm_string_to_symbol(SCM s
)
425 scm_string_to_symbol(s
)
432 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG1
, s_string_to_symbol
);
433 vcell
= scm_intern(SCM_ROCHARS(s
), (scm_sizet
)SCM_LENGTH(s
));
434 answer
= SCM_CAR (vcell
);
435 if (SCM_TYP7 (answer
) == scm_tc7_msymbol
)
437 if (SCM_REGULAR_STRINGP (s
))
438 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_F
;
440 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_T
;
446 SCM_PROC(s_string_to_obarray_symbol
, "string->obarray-symbol", 2, 1, 0, scm_string_to_obarray_symbol
);
449 scm_string_to_obarray_symbol(SCM o
, SCM s
, SCM softp
)
452 scm_string_to_obarray_symbol(o
, s
, softp
)
462 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG2
, s_string_to_obarray_symbol
);
463 SCM_ASSERT((o
== SCM_BOOL_F
) || (o
== SCM_BOOL_T
) || (SCM_NIMP(o
) && SCM_VECTORP(o
)),
464 o
, SCM_ARG1
, s_string_to_obarray_symbol
);
466 softness
= ((softp
!= SCM_UNDEFINED
) && (softp
!= SCM_BOOL_F
));
467 /* iron out some screwy calling conventions */
470 else if (o
== SCM_BOOL_T
)
473 vcell
= scm_intern_obarray_soft (SCM_ROCHARS(s
), (scm_sizet
)SCM_ROLENGTH(s
), o
, softness
);
474 if (vcell
== SCM_BOOL_F
)
476 answer
= SCM_CAR (vcell
);
477 if (SCM_TYP7 (s
) == scm_tc7_msymbol
)
479 if (SCM_REGULAR_STRINGP (s
))
480 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_F
;
482 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_T
;
487 SCM_PROC(s_intern_symbol
, "intern-symbol", 2, 0, 0, scm_intern_symbol
);
490 scm_intern_symbol(SCM o
, SCM s
)
493 scm_intern_symbol(o
, s
)
499 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_intern_symbol
);
502 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_intern_symbol
);
503 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
504 /* If the symbol is already interned, simply return. */
509 for (lsym
= SCM_VELTS (o
)[hval
];
511 lsym
= SCM_CDR (lsym
))
513 sym
= SCM_CAR (lsym
);
514 if (SCM_CAR (sym
) == s
)
517 return SCM_UNSPECIFIED
;
520 SCM_VELTS (o
)[hval
] =
521 scm_acons (s
, SCM_UNDEFINED
, SCM_VELTS (o
)[hval
]);
524 return SCM_UNSPECIFIED
;
527 SCM_PROC(s_unintern_symbol
, "unintern-symbol", 2, 0, 0, scm_unintern_symbol
);
530 scm_unintern_symbol(SCM o
, SCM s
)
533 scm_unintern_symbol(o
, s
)
539 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_unintern_symbol
);
542 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_unintern_symbol
);
543 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
549 for (lsym
= SCM_VELTS (o
)[hval
], lsym_follow
= SCM_BOOL_F
;
551 lsym_follow
= lsym
, lsym
= SCM_CDR (lsym
))
553 sym
= SCM_CAR (lsym
);
554 if (SCM_CAR (sym
) == s
)
556 /* Found the symbol to unintern. */
557 if (lsym_follow
== SCM_BOOL_F
)
558 SCM_VELTS(o
)[hval
] = lsym
;
560 SCM_CDR(lsym_follow
) = SCM_CDR(lsym
);
570 SCM_PROC(s_symbol_binding
, "symbol-binding", 2, 0, 0, scm_symbol_binding
);
573 scm_symbol_binding (SCM o
, SCM s
)
576 scm_symbol_binding (o
, s
)
582 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_binding
);
585 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_binding
);
586 vcell
= scm_sym2ovcell (s
, o
);
587 return SCM_CDR(vcell
);
591 SCM_PROC(s_symbol_interned_p
, "symbol-interned?", 2, 0, 0, scm_symbol_interned_p
);
594 scm_symbol_interned_p (SCM o
, SCM s
)
597 scm_symbol_interned_p (o
, s
)
603 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_interned_p
);
606 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_interned_p
);
607 vcell
= scm_sym2ovcell_soft (s
, o
);
608 if (SCM_IMP(vcell
) && (o
== scm_symhash
))
609 vcell
= scm_sym2ovcell_soft (s
, scm_weak_symhash
);
610 return (SCM_NIMP(vcell
)
616 SCM_PROC(s_symbol_bound_p
, "symbol-bound?", 2, 0, 0, scm_symbol_bound_p
);
619 scm_symbol_bound_p (SCM o
, SCM s
)
622 scm_symbol_bound_p (o
, s
)
628 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_bound_p
);
631 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_bound_p
);
632 vcell
= scm_sym2ovcell_soft (s
, o
);
633 return (( SCM_NIMP(vcell
)
634 && (SCM_CDR(vcell
) != SCM_UNDEFINED
))
640 SCM_PROC(s_symbol_set_x
, "symbol-set!", 3, 0, 0, scm_symbol_set_x
);
643 scm_symbol_set_x (SCM o
, SCM s
, SCM v
)
646 scm_symbol_set_x (o
, s
, v
)
653 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_set_x
);
656 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_set_x
);
657 vcell
= scm_sym2ovcell (s
, o
);
659 return SCM_UNSPECIFIED
;
667 string
= scm_makfromstr (SCM_CHARS (s
), SCM_LENGTH (s
), SCM_SYMBOL_SLOTS
);
668 SCM_SETCHARS (s
, SCM_CHARS (string
));
669 SCM_SETLENGTH (s
, SCM_LENGTH (s
), scm_tc7_msymbol
);
670 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (s
) = SCM_BOOL_F
;
671 SCM_CDR (string
) = SCM_EOL
;
672 SCM_CAR (string
) = SCM_EOL
;
676 SCM_PROC(s_symbol_fref
, "symbol-fref", 1, 0, 0, scm_symbol_fref
);
679 scm_symbol_fref (SCM s
)
686 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fref
);
688 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
691 return SCM_SYMBOL_FUNC (s
);
695 SCM_PROC(s_symbol_pref
, "symbol-pref", 1, 0, 0, scm_symbol_pref
);
698 scm_symbol_pref (SCM s
)
705 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pref
);
707 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
710 return SCM_SYMBOL_PROPS (s
);
714 SCM_PROC(s_symbol_fset_x
, "symbol-fset!", 2, 0, 0, scm_symbol_fset_x
);
717 scm_symbol_fset_x (SCM s
, SCM val
)
720 scm_symbol_fset_x (s
, val
)
725 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fset_x
);
727 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
730 SCM_SYMBOL_FUNC (s
) = val
;
731 return SCM_UNSPECIFIED
;
735 SCM_PROC(s_symbol_pset_x
, "symbol-pset!", 2, 0, 0, scm_symbol_pset_x
);
738 scm_symbol_pset_x (SCM s
, SCM val
)
741 scm_symbol_pset_x (s
, val
)
746 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pset_x
);
748 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
750 SCM_SYMBOL_PROPS (s
) = val
;
752 return SCM_UNSPECIFIED
;
756 SCM_PROC(s_symbol_hash
, "symbol-hash", 1, 0, 0, scm_symbol_hash
);
759 scm_symbol_hash (SCM s
)
766 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_hash
);
767 return SCM_MAKINUM ((unsigned long)s
^ SCM_SYMBOL_HASH (s
));
773 scm_init_symbols (void)