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 (unsigned char *str
, scm_sizet len
, unsigned long n
)
75 scm_strhash (str
, len
, n
)
84 unsigned long h
= 264 % n
;
86 h
= ((h
<< 8) + ((unsigned) (scm_downcase (str
[h
% len
])))) % n
;
94 h
= ((h
<< 8) + ((unsigned) (scm_downcase (str
[--i
])))) % n
;
99 int scm_symhash_dim
= NUM_HASH_BUCKETS
;
103 * looks up the symbol in the symhash table.
107 scm_sym2vcell (SCM sym
, SCM thunk
, SCM definep
)
110 scm_sym2vcell (sym
, thunk
, definep
)
118 SCM var
= scm_apply (thunk
, sym
, scm_cons(definep
, scm_listofnull
));
120 if (var
== SCM_BOOL_F
)
124 if (SCM_IMP(var
) || !SCM_VARIABLEP (var
))
125 scm_wta (sym
, "strangely interned symbol? ", "");
126 return SCM_VARVCELL (var
);
134 scm_sizet scm_hash
= scm_strhash (SCM_UCHARS (sym
), (scm_sizet
) SCM_LENGTH (sym
),
135 (unsigned long) scm_symhash_dim
);
138 for (lsym
= SCM_VELTS (scm_symhash
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
141 if (SCM_CAR (z
) == sym
)
148 for (lsym
= *(lsymp
= &SCM_VELTS (scm_weak_symhash
)[scm_hash
]);
150 lsym
= *(lsymp
= &SCM_CDR (lsym
)))
153 if (SCM_CAR (z
) == sym
)
157 *lsymp
= SCM_CDR (lsym
);
158 SCM_SETCDR (lsym
, SCM_VELTS(scm_symhash
)[scm_hash
]);
159 SCM_VELTS(scm_symhash
)[scm_hash
] = lsym
;
166 return scm_wta (sym
, "uninterned symbol? ", "");
171 * looks up the symbol in an arbitrary obarray (defaulting to scm_symhash).
175 scm_sym2ovcell_soft (SCM sym
, SCM obarray
)
178 scm_sym2ovcell_soft (sym
, obarray
)
186 scm_hash
= scm_strhash (SCM_UCHARS (sym
),
187 (scm_sizet
) SCM_LENGTH (sym
),
188 SCM_LENGTH (obarray
));
190 for (lsym
= SCM_VELTS (obarray
)[scm_hash
];
192 lsym
= SCM_CDR (lsym
))
195 if (SCM_CAR (z
) == sym
)
207 scm_sym2ovcell (SCM sym
, SCM obarray
)
210 scm_sym2ovcell (sym
, obarray
)
216 answer
= scm_sym2ovcell_soft (sym
, obarray
);
217 if (answer
!= SCM_BOOL_F
)
219 scm_wta (sym
, "uninterned symbol? ", "");
220 return SCM_UNSPECIFIED
; /* not reached */
225 scm_intern_obarray_soft (char *name
, scm_sizet len
, SCM obarray
, int softness
)
228 scm_intern_obarray_soft (name
, len
, obarray
, softness
)
237 register scm_sizet i
;
238 register unsigned char *tmp
;
244 tmp
= (unsigned char *) name
;
246 if (obarray
== SCM_BOOL_F
)
248 scm_hash
= scm_strhash (tmp
, i
, 1019);
249 goto uninterned_symbol
;
252 scm_hash
= scm_strhash (tmp
, i
, SCM_LENGTH(obarray
));
255 goto mustintern_symbol
;
258 for (lsym
= SCM_VELTS (obarray
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
262 tmp
= SCM_UCHARS (z
);
263 if (SCM_LENGTH (z
) != len
)
266 if (((unsigned char *) name
)[i
] != tmp
[i
])
277 if (obarray
== scm_symhash
)
279 obarray
= scm_weak_symhash
;
280 goto retry_new_obarray
;
291 lsym
= scm_makfromstr (name
, len
, SCM_SYMBOL_SLOTS
);
293 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_msymbol
);
294 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (lsym
) = SCM_BOOL_F
;
295 SCM_SYMBOL_HASH (lsym
) = scm_hash
;
296 if (obarray
== SCM_BOOL_F
)
300 SCM_NEWCELL (answer
);
302 SCM_CAR (answer
) = lsym
;
303 SCM_CDR (answer
) = SCM_UNDEFINED
;
314 SCM_SETCAR (a
, lsym
);
315 SCM_SETCDR (a
, SCM_UNDEFINED
);
317 SCM_SETCDR (b
, SCM_VELTS(obarray
)[scm_hash
]);
318 SCM_VELTS(obarray
)[scm_hash
] = b
;
326 scm_intern_obarray (char *name
, scm_sizet len
, SCM obarray
)
329 scm_intern_obarray (name
, len
, obarray
)
335 return scm_intern_obarray_soft (name
, len
, obarray
, 0);
341 scm_intern (char *name
, scm_sizet len
)
344 scm_intern (name
, len
)
349 return scm_intern_obarray (name
, len
, scm_symhash
);
354 scm_intern0 (char * name
)
361 return scm_intern (name
, strlen (name
));
367 scm_sysintern (char *name
, SCM val
)
370 scm_sysintern (name
, val
)
377 easy_answer
= scm_intern_obarray_soft (name
, strlen (name
), scm_symhash
, 1);
378 if (SCM_NIMP (easy_answer
))
380 SCM_CDR (easy_answer
) = val
;
387 scm_sizet len
= strlen (name
);
388 register unsigned char *tmp
= (unsigned char *) name
;
389 scm_sizet scm_hash
= scm_strhash (tmp
, len
, (unsigned long) scm_symhash_dim
);
391 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_ssymbol
);
392 SCM_SETCHARS (lsym
, name
);
393 lsym
= scm_cons (lsym
, val
);
394 SCM_VELTS (scm_symhash
)[scm_hash
] = scm_cons (lsym
, SCM_VELTS (scm_symhash
)[scm_hash
]);
401 SCM_PROC(s_symbol_p
, "symbol?", 1, 0, 0, scm_symbol_p
);
411 if SCM_IMP(x
) return SCM_BOOL_F
;
412 return SCM_SYMBOLP(x
) ? SCM_BOOL_T
: SCM_BOOL_F
;
415 SCM_PROC(s_symbol_to_string
, "symbol->string", 1, 0, 0, scm_symbol_to_string
);
418 scm_symbol_to_string(SCM s
)
421 scm_symbol_to_string(s
)
425 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_to_string
);
426 return scm_makfromstr(SCM_CHARS(s
), (scm_sizet
)SCM_LENGTH(s
), 0);
430 SCM_PROC(s_string_to_symbol
, "string->symbol", 1, 0, 0, scm_string_to_symbol
);
433 scm_string_to_symbol(SCM s
)
436 scm_string_to_symbol(s
)
443 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG1
, s_string_to_symbol
);
444 vcell
= scm_intern(SCM_ROCHARS(s
), (scm_sizet
)SCM_LENGTH(s
));
445 answer
= SCM_CAR (vcell
);
446 if (SCM_TYP7 (answer
) == scm_tc7_msymbol
)
448 if (SCM_REGULAR_STRINGP (s
))
449 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_F
;
451 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_T
;
457 SCM_PROC(s_string_to_obarray_symbol
, "string->obarray-symbol", 2, 1, 0, scm_string_to_obarray_symbol
);
460 scm_string_to_obarray_symbol(SCM o
, SCM s
, SCM softp
)
463 scm_string_to_obarray_symbol(o
, s
, softp
)
473 SCM_ASSERT(SCM_NIMP(s
) && SCM_ROSTRINGP(s
), s
, SCM_ARG2
, s_string_to_obarray_symbol
);
474 SCM_ASSERT((o
== SCM_BOOL_F
) || (o
== SCM_BOOL_T
) || (SCM_NIMP(o
) && SCM_VECTORP(o
)),
475 o
, SCM_ARG1
, s_string_to_obarray_symbol
);
477 softness
= ((softp
!= SCM_UNDEFINED
) && (softp
!= SCM_BOOL_F
));
478 /* iron out some screwy calling conventions */
481 else if (o
== SCM_BOOL_T
)
484 vcell
= scm_intern_obarray_soft (SCM_ROCHARS(s
), (scm_sizet
)SCM_ROLENGTH(s
), o
, softness
);
485 if (vcell
== SCM_BOOL_F
)
487 answer
= SCM_CAR (vcell
);
488 if (SCM_TYP7 (s
) == scm_tc7_msymbol
)
490 if (SCM_REGULAR_STRINGP (s
))
491 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_F
;
493 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (answer
) = SCM_BOOL_T
;
498 SCM_PROC(s_intern_symbol
, "intern-symbol", 2, 0, 0, scm_intern_symbol
);
501 scm_intern_symbol(SCM o
, SCM s
)
504 scm_intern_symbol(o
, s
)
510 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_intern_symbol
);
513 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_intern_symbol
);
514 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
515 /* If the symbol is already interned, simply return. */
520 for (lsym
= SCM_VELTS (o
)[hval
];
522 lsym
= SCM_CDR (lsym
))
524 sym
= SCM_CAR (lsym
);
525 if (SCM_CAR (sym
) == s
)
528 return SCM_UNSPECIFIED
;
531 SCM_VELTS (o
)[hval
] =
532 scm_acons (s
, SCM_UNDEFINED
, SCM_VELTS (o
)[hval
]);
535 return SCM_UNSPECIFIED
;
538 SCM_PROC(s_unintern_symbol
, "unintern-symbol", 2, 0, 0, scm_unintern_symbol
);
541 scm_unintern_symbol(SCM o
, SCM s
)
544 scm_unintern_symbol(o
, s
)
550 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_unintern_symbol
);
553 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_unintern_symbol
);
554 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
560 for (lsym
= SCM_VELTS (o
)[hval
], lsym_follow
= SCM_BOOL_F
;
562 lsym_follow
= lsym
, lsym
= SCM_CDR (lsym
))
564 sym
= SCM_CAR (lsym
);
565 if (SCM_CAR (sym
) == s
)
567 /* Found the symbol to unintern. */
568 if (lsym_follow
== SCM_BOOL_F
)
569 SCM_VELTS(o
)[hval
] = lsym
;
571 SCM_CDR(lsym_follow
) = SCM_CDR(lsym
);
581 SCM_PROC(s_symbol_binding
, "symbol-binding", 2, 0, 0, scm_symbol_binding
);
584 scm_symbol_binding (SCM o
, SCM s
)
587 scm_symbol_binding (o
, s
)
593 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_binding
);
596 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_binding
);
597 vcell
= scm_sym2ovcell (s
, o
);
598 return SCM_CDR(vcell
);
602 SCM_PROC(s_symbol_interned_p
, "symbol-interned?", 2, 0, 0, scm_symbol_interned_p
);
605 scm_symbol_interned_p (SCM o
, SCM s
)
608 scm_symbol_interned_p (o
, s
)
614 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_interned_p
);
617 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_interned_p
);
618 vcell
= scm_sym2ovcell_soft (s
, o
);
619 if (SCM_IMP(vcell
) && (o
== scm_symhash
))
620 vcell
= scm_sym2ovcell_soft (s
, scm_weak_symhash
);
621 return (SCM_NIMP(vcell
)
627 SCM_PROC(s_symbol_bound_p
, "symbol-bound?", 2, 0, 0, scm_symbol_bound_p
);
630 scm_symbol_bound_p (SCM o
, SCM s
)
633 scm_symbol_bound_p (o
, s
)
639 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_bound_p
);
642 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_bound_p
);
643 vcell
= scm_sym2ovcell_soft (s
, o
);
644 return (( SCM_NIMP(vcell
)
645 && (SCM_CDR(vcell
) != SCM_UNDEFINED
))
651 SCM_PROC(s_symbol_set_x
, "symbol-set!", 3, 0, 0, scm_symbol_set_x
);
654 scm_symbol_set_x (SCM o
, SCM s
, SCM v
)
657 scm_symbol_set_x (o
, s
, v
)
664 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG2
, s_symbol_set_x
);
667 SCM_ASSERT(SCM_NIMP(o
) && SCM_VECTORP(o
), o
, SCM_ARG1
, s_symbol_set_x
);
668 vcell
= scm_sym2ovcell (s
, o
);
670 return SCM_UNSPECIFIED
;
678 string
= scm_makfromstr (SCM_CHARS (s
), SCM_LENGTH (s
), SCM_SYMBOL_SLOTS
);
679 SCM_SETCHARS (s
, SCM_CHARS (string
));
680 SCM_SETLENGTH (s
, SCM_LENGTH (s
), scm_tc7_msymbol
);
681 SCM_SYMBOL_MULTI_BYTE_SCM_STRINGP (s
) = SCM_BOOL_F
;
682 SCM_CDR (string
) = SCM_EOL
;
683 SCM_CAR (string
) = SCM_EOL
;
687 SCM_PROC(s_symbol_fref
, "symbol-fref", 1, 0, 0, scm_symbol_fref
);
690 scm_symbol_fref (SCM s
)
697 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fref
);
699 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
702 return SCM_SYMBOL_FUNC (s
);
706 SCM_PROC(s_symbol_pref
, "symbol-pref", 1, 0, 0, scm_symbol_pref
);
709 scm_symbol_pref (SCM s
)
716 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_pref
);
718 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
721 return SCM_SYMBOL_PROPS (s
);
725 SCM_PROC(s_symbol_fset_x
, "symbol-fset!", 2, 0, 0, scm_symbol_fset_x
);
728 scm_symbol_fset_x (SCM s
, SCM val
)
731 scm_symbol_fset_x (s
, val
)
736 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_fset_x
);
738 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
741 SCM_SYMBOL_FUNC (s
) = val
;
742 return SCM_UNSPECIFIED
;
746 SCM_PROC(s_symbol_pset_x
, "symbol-pset!", 2, 0, 0, scm_symbol_pset_x
);
749 scm_symbol_pset_x (SCM s
, SCM val
)
752 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
);
770 scm_symbol_hash (SCM s
)
777 SCM_ASSERT(SCM_NIMP(s
) && SCM_SYMBOLP(s
), s
, SCM_ARG1
, s_symbol_hash
);
778 return SCM_MAKINUM ((unsigned long)s
^ SCM_SYMBOL_HASH (s
));
784 scm_init_symbols (void)