1 /* Copyright (C) 1995,1996,1997,1998 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. */
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
55 #include "scm_validate.h"
65 /* NUM_HASH_BUCKETS is the number of symbol scm_hash table buckets.
67 #define NUM_HASH_BUCKETS 137
77 scm_strhash (unsigned char *str
,scm_sizet len
,unsigned long n
)
82 unsigned long h
= 264 % n
;
84 h
= ((h
<< 8) + ((unsigned) (scm_downcase (str
[h
% len
])))) % n
;
92 h
= ((h
<< 8) + ((unsigned) (scm_downcase (str
[--i
])))) % n
;
97 int scm_symhash_dim
= NUM_HASH_BUCKETS
;
101 * looks up the symbol in the symhash table.
105 scm_sym2vcell (SCM sym
,SCM thunk
,SCM definep
)
109 SCM var
= scm_apply (thunk
, sym
, scm_cons(definep
, scm_listofnull
));
111 if (var
== SCM_BOOL_F
)
115 if (SCM_IMP(var
) || !SCM_VARIABLEP (var
))
116 scm_wta (sym
, "strangely interned symbol? ", "");
117 return SCM_VARVCELL (var
);
125 scm_sizet scm_hash
= scm_strhash (SCM_UCHARS (sym
), (scm_sizet
) SCM_LENGTH (sym
),
126 (unsigned long) scm_symhash_dim
);
129 for (lsym
= SCM_VELTS (scm_symhash
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
132 if (SCM_CAR (z
) == sym
)
139 for (lsym
= *(lsymp
= &SCM_VELTS (scm_weak_symhash
)[scm_hash
]);
141 lsym
= *(lsymp
= SCM_CDRLOC (lsym
)))
144 if (SCM_CAR (z
) == sym
)
146 if (SCM_NFALSEP (definep
))
148 /* Move handle from scm_weak_symhash to scm_symhash. */
149 *lsymp
= SCM_CDR (lsym
);
150 SCM_SETCDR (lsym
, SCM_VELTS(scm_symhash
)[scm_hash
]);
151 SCM_VELTS(scm_symhash
)[scm_hash
] = lsym
;
158 return scm_wta (sym
, "uninterned symbol? ", "");
163 * looks up the symbol in an arbitrary obarray.
167 scm_sym2ovcell_soft (SCM sym
, SCM obarray
)
172 scm_hash
= scm_strhash (SCM_UCHARS (sym
),
173 (scm_sizet
) SCM_LENGTH (sym
),
174 SCM_LENGTH (obarray
));
176 for (lsym
= SCM_VELTS (obarray
)[scm_hash
];
178 lsym
= SCM_CDR (lsym
))
181 if (SCM_CAR (z
) == sym
)
193 scm_sym2ovcell (SCM sym
, SCM obarray
)
196 answer
= scm_sym2ovcell_soft (sym
, obarray
);
197 if (answer
!= SCM_BOOL_F
)
199 scm_wta (sym
, "uninterned symbol? ", "");
200 return SCM_UNSPECIFIED
; /* not reached */
203 /* Intern a symbol whose name is the LEN characters at NAME in OBARRAY.
205 OBARRAY should be a vector of lists, indexed by the name's hash
206 value, modulo OBARRAY's length. Each list has the form
207 ((SYMBOL . VALUE) ...), where SYMBOL is a symbol, and VALUE is the
208 value associated with that symbol (in the current module? in the
211 To "intern" a symbol means: if OBARRAY already contains a symbol by
212 that name, return its (SYMBOL . VALUE) pair; otherwise, create a
213 new symbol, add the pair (SYMBOL . SCM_UNDEFINED) to the
214 appropriate list of the OBARRAY, and return the pair.
216 If softness is non-zero, don't create a symbol if it isn't already
217 in OBARRAY; instead, just return #f.
219 If OBARRAY is SCM_BOOL_F, create a symbol listed in no obarray and
220 return (SYMBOL . SCM_UNDEFINED).
222 If OBARRAY is scm_symhash, and that doesn't contain the symbol,
223 check scm_weak_symhash instead. */
227 scm_intern_obarray_soft (const char *name
,scm_sizet len
,SCM obarray
,int softness
)
231 register scm_sizet i
;
232 register unsigned char *tmp
;
238 tmp
= (unsigned char *) name
;
240 if (obarray
== SCM_BOOL_F
)
242 scm_hash
= scm_strhash (tmp
, i
, 1019);
243 goto uninterned_symbol
;
246 scm_hash
= scm_strhash (tmp
, i
, SCM_LENGTH(obarray
));
248 /* softness == -1 used to mean that it was known that the symbol
249 wasn't already in the obarray. I don't think there are any
250 callers that use that case any more, but just in case...
256 for (lsym
= SCM_VELTS (obarray
)[scm_hash
]; SCM_NIMP (lsym
); lsym
= SCM_CDR (lsym
))
260 tmp
= SCM_UCHARS (z
);
261 if (SCM_LENGTH (z
) != len
)
264 if (((unsigned char *) name
)[i
] != tmp
[i
])
275 if (obarray
== scm_symhash
)
277 obarray
= scm_weak_symhash
;
278 goto retry_new_obarray
;
288 lsym
= scm_makfromstr (name
, len
, SCM_SYMBOL_SLOTS
);
290 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_msymbol
);
291 SCM_SYMBOL_HASH (lsym
) = scm_hash
;
292 SCM_SYMBOL_PROPS (lsym
) = SCM_EOL
;
293 if (obarray
== SCM_BOOL_F
)
297 SCM_NEWCELL (answer
);
299 SCM_SETCAR (answer
, lsym
);
300 SCM_SETCDR (answer
, SCM_UNDEFINED
);
311 SCM_SETCAR (a
, lsym
);
312 SCM_SETCDR (a
, SCM_UNDEFINED
);
314 SCM_SETCDR (b
, SCM_VELTS(obarray
)[scm_hash
]);
315 SCM_VELTS(obarray
)[scm_hash
] = b
;
323 scm_intern_obarray (const char *name
,scm_sizet len
,SCM obarray
)
325 return scm_intern_obarray_soft (name
, len
, obarray
, 0);
330 scm_intern (const char *name
,scm_sizet len
)
332 return scm_intern_obarray (name
, len
, scm_symhash
);
337 scm_intern0 (const char * name
)
339 return scm_intern (name
, strlen (name
));
343 /* Intern the symbol named NAME in scm_symhash, NAME is null-terminated. */
345 scm_sysintern0_no_module_lookup (const char *name
)
349 easy_answer
= scm_intern_obarray_soft (name
, strlen (name
), scm_symhash
, 1);
350 if (SCM_NIMP (easy_answer
))
358 scm_sizet len
= strlen (name
);
359 register unsigned char *tmp
= (unsigned char *) name
;
360 scm_sizet scm_hash
= scm_strhash (tmp
, len
, (unsigned long) scm_symhash_dim
);
362 SCM_SETLENGTH (lsym
, (long) len
, scm_tc7_ssymbol
);
363 SCM_SETCHARS (lsym
, name
);
364 lsym
= scm_cons (lsym
, SCM_UNDEFINED
);
365 SCM_VELTS (scm_symhash
)[scm_hash
] = scm_cons (lsym
, SCM_VELTS (scm_symhash
)[scm_hash
]);
372 /* Is it safe to access SCM_TOP_LEVEL_LOOKUP_CLOSURE_VAR?
374 int scm_can_use_top_level_lookup_closure_var
;
376 /* Intern the symbol named NAME in scm_symhash, and give it the value
377 VAL. NAME is null-terminated. Use the current top_level lookup
378 closure to give NAME its value.
381 scm_sysintern (const char *name
, SCM val
)
383 SCM vcell
= scm_sysintern0 (name
);
384 SCM_SETCDR (vcell
, val
);
389 scm_sysintern0 (const char *name
)
392 if (scm_can_use_top_level_lookup_closure_var
&&
393 SCM_NIMP (lookup_proc
= SCM_CDR (scm_top_level_lookup_closure_var
)))
395 SCM sym
= SCM_CAR (scm_intern0 (name
));
396 SCM vcell
= scm_sym2vcell (sym
, lookup_proc
, SCM_BOOL_T
);
397 if (vcell
== SCM_BOOL_F
)
398 scm_misc_error ("sysintern0", "can't define variable", sym
);
402 return scm_sysintern0_no_module_lookup (name
);
405 /* Lookup the value of the symbol named by the nul-terminated string
406 NAME in the current module. */
408 scm_symbol_value0 (const char *name
)
410 /* This looks silly - we look up the symbol twice. But it is in
411 fact necessary given the current module system because the module
412 lookup closures are written in scheme which needs real symbols. */
413 SCM symbol
= scm_intern_obarray_soft (name
, strlen (name
), scm_symhash
, 0);
414 SCM vcell
= scm_sym2vcell (SCM_CAR (symbol
),
415 SCM_CDR (scm_top_level_lookup_closure_var
),
417 if (SCM_FALSEP (vcell
))
418 return SCM_UNDEFINED
;
419 return SCM_CDR (vcell
);
422 SCM_DEFINE (scm_symbol_p
, "symbol?", 1, 0, 0,
425 #define FUNC_NAME s_scm_symbol_p
427 if SCM_IMP(x
) return SCM_BOOL_F
;
428 return SCM_BOOL(SCM_SYMBOLP(x
));
432 SCM_DEFINE (scm_symbol_to_string
, "symbol->string", 1, 0, 0,
435 #define FUNC_NAME s_scm_symbol_to_string
437 SCM_VALIDATE_SYMBOL (1,s
);
438 return scm_makfromstr(SCM_CHARS(s
), (scm_sizet
)SCM_LENGTH(s
), 0);
443 SCM_DEFINE (scm_string_to_symbol
, "string->symbol", 1, 0, 0,
446 #define FUNC_NAME s_scm_string_to_symbol
451 SCM_VALIDATE_ROSTRING (1,s
);
452 vcell
= scm_intern(SCM_ROCHARS(s
), (scm_sizet
)SCM_LENGTH(s
));
453 answer
= SCM_CAR (vcell
);
459 SCM_DEFINE (scm_string_to_obarray_symbol
, "string->obarray-symbol", 2, 1, 0,
460 (SCM o
, SCM s
, SCM softp
),
461 "Intern a new symbol in @var{obarray}, a symbol table, with name\n"
463 "If @var{obarray} is @code{#f}, use the default system symbol table. If\n"
464 "@var{obarray} is @code{#t}, the symbol should not be interned in any\n"
465 "symbol table; merely return the pair (@var{symbol}\n"
466 ". @var{#<undefined>}).\n\n"
467 "The @var{soft?} argument determines whether new symbol table entries\n"
468 "should be created when the specified symbol is not already present in\n"
469 "@var{obarray}. If @var{soft?} is specified and is a true value, then\n"
470 "new entries should not be added for symbols not already present in the\n"
471 "table; instead, simply return @code{#f}.")
472 #define FUNC_NAME s_scm_string_to_obarray_symbol
478 SCM_VALIDATE_ROSTRING (2,s
);
479 SCM_ASSERT((o
== SCM_BOOL_F
)
482 o
, SCM_ARG1
, FUNC_NAME
);
484 softness
= ((softp
!= SCM_UNDEFINED
) && (softp
!= SCM_BOOL_F
));
485 /* iron out some screwy calling conventions */
488 else if (o
== SCM_BOOL_T
)
491 vcell
= scm_intern_obarray_soft (SCM_ROCHARS(s
),
492 (scm_sizet
)SCM_ROLENGTH(s
),
495 if (vcell
== SCM_BOOL_F
)
497 answer
= SCM_CAR (vcell
);
502 SCM_DEFINE (scm_intern_symbol
, "intern-symbol", 2, 0, 0,
504 "Add a new symbol to @var{obarray} with name @var{string}, bound to an\n"
505 "unspecified initial value. The symbol table is not modified if a symbol\n"
506 "with this name is already present.")
507 #define FUNC_NAME s_scm_intern_symbol
510 SCM_VALIDATE_SYMBOL (2,s
);
513 SCM_VALIDATE_VECTOR (1,o
);
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
;
539 SCM_DEFINE (scm_unintern_symbol
, "unintern-symbol", 2, 0, 0,
541 "Remove the symbol with name @var{string} from @var{obarray}. This\n"
542 "function returns @code{#t} if the symbol was present and @code{#f}\n"
544 #define FUNC_NAME s_scm_unintern_symbol
547 SCM_VALIDATE_SYMBOL (2,s
);
550 SCM_VALIDATE_VECTOR (1,o
);
551 hval
= scm_strhash (SCM_UCHARS (s
), SCM_LENGTH (s
), SCM_LENGTH(o
));
557 for (lsym
= SCM_VELTS (o
)[hval
], lsym_follow
= SCM_BOOL_F
;
559 lsym_follow
= lsym
, lsym
= SCM_CDR (lsym
))
561 sym
= SCM_CAR (lsym
);
562 if (SCM_CAR (sym
) == s
)
564 /* Found the symbol to unintern. */
565 if (lsym_follow
== SCM_BOOL_F
)
566 SCM_VELTS(o
)[hval
] = lsym
;
568 SCM_SETCDR (lsym_follow
, SCM_CDR(lsym
));
579 SCM_DEFINE (scm_symbol_binding
, "symbol-binding", 2, 0, 0,
581 "Look up in @var{obarray} the symbol whose name is @var{string}, and\n"
582 "return the value to which it is bound. If @var{obarray} is @code{#f},\n"
583 "use the global symbol table. If @var{string} is not interned in\n"
584 "@var{obarray}, an error is signalled.")
585 #define FUNC_NAME s_scm_symbol_binding
588 SCM_VALIDATE_SYMBOL (2,s
);
591 SCM_VALIDATE_VECTOR (1,o
);
592 vcell
= scm_sym2ovcell (s
, o
);
593 return SCM_CDR(vcell
);
598 SCM_DEFINE (scm_symbol_interned_p
, "symbol-interned?", 2, 0, 0,
600 "Return @var{#t} if @var{obarray} contains a symbol with name\n"
601 "@var{string}, and @var{#f} otherwise.")
602 #define FUNC_NAME s_scm_symbol_interned_p
605 SCM_VALIDATE_SYMBOL (2,s
);
608 SCM_VALIDATE_VECTOR (1,o
);
609 vcell
= scm_sym2ovcell_soft (s
, o
);
610 if (SCM_IMP(vcell
) && (o
== scm_symhash
))
611 vcell
= scm_sym2ovcell_soft (s
, scm_weak_symhash
);
612 return (SCM_NIMP(vcell
)
619 SCM_DEFINE (scm_symbol_bound_p
, "symbol-bound?", 2, 0, 0,
621 "Return @var{#t} if @var{obarray} contains a symbol with name\n"
622 "@var{string} bound to a defined value. This differs from\n"
623 "@var{symbol-bound?} in that the mere mention of a symbol usually causes\n"
624 "it to be interned; @code{symbol-bound?} determines whether a symbol has\n"
625 "been given any meaningful value.")
626 #define FUNC_NAME s_scm_symbol_bound_p
629 SCM_VALIDATE_SYMBOL (2,s
);
632 SCM_VALIDATE_VECTOR (1,o
);
633 vcell
= scm_sym2ovcell_soft (s
, o
);
634 return (( SCM_NIMP(vcell
)
635 && (SCM_CDR(vcell
) != SCM_UNDEFINED
))
642 SCM_DEFINE (scm_symbol_set_x
, "symbol-set!", 3, 0, 0,
643 (SCM o
, SCM s
, SCM v
),
644 "Find the symbol in @var{obarray} whose name is @var{string}, and rebind\n"
645 "it to @var{value}. An error is signalled if @var{string} is not present\n"
647 #define FUNC_NAME s_scm_symbol_set_x
650 SCM_VALIDATE_SYMBOL (2,s
);
653 SCM_VALIDATE_VECTOR (1,o
);
654 vcell
= scm_sym2ovcell (s
, o
);
655 SCM_SETCDR (vcell
, v
);
656 return SCM_UNSPECIFIED
;
664 string
= scm_makfromstr (SCM_CHARS (s
), SCM_LENGTH (s
), SCM_SYMBOL_SLOTS
);
665 SCM_SETCHARS (s
, SCM_CHARS (string
));
666 SCM_SETLENGTH (s
, SCM_LENGTH (s
), scm_tc7_msymbol
);
667 SCM_SETCDR (string
, SCM_EOL
);
668 SCM_SETCAR (string
, SCM_EOL
);
669 SCM_SYMBOL_PROPS (s
) = SCM_EOL
;
670 /* If it's a tc7_ssymbol, it comes from scm_symhash */
671 SCM_SYMBOL_HASH (s
) = scm_strhash (SCM_UCHARS (s
),
672 (scm_sizet
) SCM_LENGTH (s
),
673 SCM_LENGTH (scm_symhash
));
677 SCM_DEFINE (scm_symbol_fref
, "symbol-fref", 1, 0, 0,
679 "Return the contents of @var{symbol}'s @dfn{function slot}.")
680 #define FUNC_NAME s_scm_symbol_fref
682 SCM_VALIDATE_SYMBOL (1,s
);
684 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
687 return SCM_SYMBOL_FUNC (s
);
692 SCM_DEFINE (scm_symbol_pref
, "symbol-pref", 1, 0, 0,
694 "Return the @dfn{property list} currently associated with @var{symbol}.")
695 #define FUNC_NAME s_scm_symbol_pref
697 SCM_VALIDATE_SYMBOL (1,s
);
699 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
702 return SCM_SYMBOL_PROPS (s
);
707 SCM_DEFINE (scm_symbol_fset_x
, "symbol-fset!", 2, 0, 0,
709 "Change the binding of @var{symbol}'s function slot.")
710 #define FUNC_NAME s_scm_symbol_fset_x
712 SCM_VALIDATE_SYMBOL (1,s
);
714 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
717 SCM_SYMBOL_FUNC (s
) = val
;
718 return SCM_UNSPECIFIED
;
723 SCM_DEFINE (scm_symbol_pset_x
, "symbol-pset!", 2, 0, 0,
725 "Change the binding of @var{symbol}'s property slot.")
726 #define FUNC_NAME s_scm_symbol_pset_x
728 SCM_VALIDATE_SYMBOL (1,s
);
730 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
732 SCM_SYMBOL_PROPS (s
) = val
;
734 return SCM_UNSPECIFIED
;
739 SCM_DEFINE (scm_symbol_hash
, "symbol-hash", 1, 0, 0,
741 "Return the hash value derived from @var{symbol}'s name, i.e. the integer\n"
742 "index into @var{symbol}'s obarray at which it is stored.")
743 #define FUNC_NAME s_scm_symbol_hash
745 SCM_VALIDATE_SYMBOL (1,s
);
746 if (SCM_TYP7(s
) == scm_tc7_ssymbol
)
748 return SCM_MAKINUM ((unsigned long)s
^ SCM_SYMBOL_HASH (s
));
754 copy_and_prune_obarray (SCM from
, SCM to
)
757 int length
= SCM_LENGTH (from
);
758 for (i
= 0; i
< length
; ++i
)
760 SCM head
= SCM_VELTS (from
)[i
]; /* GC protection */
764 while (SCM_NIMP (ls
))
766 if (!SCM_UNBNDP (SCM_CDAR (ls
)))
768 *lloc
= scm_cons (SCM_CAR (ls
), SCM_EOL
);
769 lloc
= SCM_CDRLOC (*lloc
);
773 SCM_VELTS (to
)[i
] = res
;
778 SCM_DEFINE (scm_builtin_bindings
, "builtin-bindings", 0, 0, 0,
780 "Create and return a copy of the global symbol table, removing all\n"
782 #define FUNC_NAME s_scm_builtin_bindings
784 int length
= SCM_LENGTH (scm_symhash
);
785 SCM obarray
= scm_make_vector (SCM_MAKINUM (length
), SCM_EOL
);
786 copy_and_prune_obarray (scm_symhash
, obarray
);
792 SCM_DEFINE (scm_builtin_weak_bindings
, "builtin-weak-bindings", 0, 0, 0,
795 #define FUNC_NAME s_scm_builtin_weak_bindings
797 int length
= SCM_LENGTH (scm_weak_symhash
);
798 SCM obarray
= scm_make_doubly_weak_hash_table (SCM_MAKINUM (length
));
799 copy_and_prune_obarray (scm_weak_symhash
, obarray
);
804 static int gensym_counter
;
805 static SCM gensym_prefix
;
807 /* :FIXME:OPTIMIZE */
808 SCM_DEFINE (scm_gensym
, "gensym", 0, 2, 0,
809 (SCM name
, SCM obarray
),
810 "Create a new, unique symbol in @var{obarray}, using the global symbol\n"
811 "table by default. If @var{name} is specified, it should be used as a\n"
812 "prefix for the new symbol's name. The default prefix is @code{%%gensym}.")
813 #define FUNC_NAME s_scm_gensym
816 if (SCM_UNBNDP (name
))
817 name
= gensym_prefix
;
819 SCM_VALIDATE_ROSTRING (1,name
);
822 if (SCM_UNBNDP (obarray
))
824 obarray
= SCM_BOOL_F
;
828 SCM_ASSERT ((SCM_VECTORP (obarray
) || SCM_WVECTP (obarray
)),
832 while (scm_string_to_obarray_symbol (obarray
, new, SCM_BOOL_T
)
835 new = scm_string_append
837 scm_number_to_string (SCM_MAKINUM (gensym_counter
++),
840 return scm_string_to_obarray_symbol (obarray
, new, SCM_BOOL_F
);
848 gensym_prefix
= scm_permanent_object (scm_makfrom0str ("%%gensym"));