*** empty log message ***
[bpt/guile.git] / libguile / symbols.c
index bf694f9..f02603d 100644 (file)
@@ -1,4 +1,4 @@
-/*     Copyright (C) 1995,1996 Free Software Foundation, Inc.
+/*     Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -12,7 +12,8 @@
  * 
  * You should have received a copy of the GNU General Public License
  * along with this software; see the file COPYING.  If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
  *
  * As a special exception, the Free Software Foundation gives permission
  * for additional uses of the text contained in its release of GUILE.
  *
  * If you write modifications of your own for GUILE, it is your choice
  * whether to permit this exception to apply to your modifications.
- * If you do not wish that, delete this exception notice.  
- */
+ * If you do not wish that, delete this exception notice.  */
+
+/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
+   gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
+
 \f
 
 #include <stdio.h>
@@ -46,8 +50,9 @@
 #include "eval.h"
 #include "variable.h"
 #include "alist.h"
-#include "mbstrings.h"
+#include "weaks.h"
 
+#include "validate.h"
 #include "symbols.h"
 
 #ifdef HAVE_STRING_H
 /* {Symbols}
  */
 
-#ifdef __STDC__
-unsigned long 
-scm_strhash (unsigned char *str, scm_sizet len, unsigned long n)
-#else
+
 unsigned long 
-scm_strhash (str, len, n)
-     unsigned char *str;
-     scm_sizet len;
-     unsigned long n;
-#endif
+scm_strhash (unsigned char *str,scm_sizet len,unsigned long n)
 {
   if (len > 5)
     {
@@ -102,16 +100,9 @@ int scm_symhash_dim = NUM_HASH_BUCKETS;
 /* scm_sym2vcell
  * looks up the symbol in the symhash table. 
  */
-#ifdef __STDC__
-SCM 
-scm_sym2vcell (SCM sym, SCM thunk, SCM definep)
-#else
+
 SCM 
-scm_sym2vcell (sym, thunk, definep)
-     SCM sym;
-     SCM thunk;
-     SCM definep;
-#endif
+scm_sym2vcell (SCM sym,SCM thunk,SCM definep)
 {
   if (SCM_NIMP(thunk))
     {
@@ -147,13 +138,14 @@ scm_sym2vcell (sym, thunk, definep)
 
       for (lsym = *(lsymp = &SCM_VELTS (scm_weak_symhash)[scm_hash]);
           SCM_NIMP (lsym);
-          lsym = *(lsymp = &SCM_CDR (lsym)))
+          lsym = *(lsymp = SCM_CDRLOC (lsym)))
        {
          z = SCM_CAR (lsym);
          if (SCM_CAR (z) == sym)
            {
-             if (definep)
+             if (SCM_NFALSEP (definep))
                {
+                 /* Move handle from scm_weak_symhash to scm_symhash. */
                  *lsymp = SCM_CDR (lsym);
                  SCM_SETCDR (lsym, SCM_VELTS(scm_symhash)[scm_hash]);
                  SCM_VELTS(scm_symhash)[scm_hash] = lsym;
@@ -168,17 +160,11 @@ scm_sym2vcell (sym, thunk, definep)
 }
 
 /* scm_sym2ovcell
- * looks up the symbol in an arbitrary obarray (defaulting to scm_symhash).
+ * looks up the symbol in an arbitrary obarray.
  */
-#ifdef __STDC__
+
 SCM 
 scm_sym2ovcell_soft (SCM sym, SCM obarray)
-#else
-SCM 
-scm_sym2ovcell_soft (sym, obarray)
-     SCM sym;
-     SCM obarray;
-#endif
 {
   SCM lsym, z;
   scm_sizet scm_hash;
@@ -202,15 +188,9 @@ scm_sym2ovcell_soft (sym, obarray)
   return SCM_BOOL_F;
 }
 
-#ifdef __STDC__
+
 SCM 
 scm_sym2ovcell (SCM sym, SCM obarray)
-#else
-SCM 
-scm_sym2ovcell (sym, obarray)
-     SCM sym;
-     SCM obarray;
-#endif
 {
   SCM answer;
   answer = scm_sym2ovcell_soft (sym, obarray);
@@ -220,17 +200,31 @@ scm_sym2ovcell (sym, obarray)
   return SCM_UNSPECIFIED;              /* not reached */
 }
 
-#ifdef __STDC__
-SCM 
-scm_intern_obarray_soft (char *name, scm_sizet len, SCM obarray, int softness)
-#else
+/* Intern a symbol whose name is the LEN characters at NAME in OBARRAY.
+
+   OBARRAY should be a vector of lists, indexed by the name's hash
+   value, modulo OBARRAY's length.  Each list has the form 
+   ((SYMBOL . VALUE) ...), where SYMBOL is a symbol, and VALUE is the
+   value associated with that symbol (in the current module?  in the
+   system module?)
+
+   To "intern" a symbol means: if OBARRAY already contains a symbol by
+   that name, return its (SYMBOL . VALUE) pair; otherwise, create a
+   new symbol, add the pair (SYMBOL . SCM_UNDEFINED) to the
+   appropriate list of the OBARRAY, and return the pair.
+
+   If softness is non-zero, don't create a symbol if it isn't already
+   in OBARRAY; instead, just return #f.
+
+   If OBARRAY is SCM_BOOL_F, create a symbol listed in no obarray and
+   return (SYMBOL . SCM_UNDEFINED).
+
+   If OBARRAY is scm_symhash, and that doesn't contain the symbol,
+   check scm_weak_symhash instead.  */
+
+
 SCM 
-scm_intern_obarray_soft (name, len, obarray, softness)
-     char *name;
-     scm_sizet len;
-     SCM obarray;
-     int softness;
-#endif
+scm_intern_obarray_soft (const char *name,scm_sizet len,SCM obarray,int softness)
 {
   SCM lsym;
   SCM z;
@@ -251,8 +245,12 @@ scm_intern_obarray_soft (name, len, obarray, softness)
 
   scm_hash = scm_strhash (tmp, i, SCM_LENGTH(obarray));
 
+  /* softness == -1 used to mean that it was known that the symbol
+     wasn't already in the obarray.  I don't think there are any
+     callers that use that case any more, but just in case...
+     -- JimB, Oct 1996  */
   if (softness == -1)
-    goto mustintern_symbol;
+    abort ();
 
  retry_new_obarray:
   for (lsym = SCM_VELTS (obarray)[scm_hash]; SCM_NIMP (lsym); lsym = SCM_CDR (lsym))
@@ -287,20 +285,19 @@ scm_intern_obarray_soft (name, len, obarray, softness)
       return SCM_BOOL_F;
     }
 
- mustintern_symbol:
   lsym = scm_makfromstr (name, len, SCM_SYMBOL_SLOTS);
 
   SCM_SETLENGTH (lsym, (long) len, scm_tc7_msymbol);
-  SCM_SYMBOL_MULTI_BYTE_STRINGP (lsym) = SCM_BOOL_F;
   SCM_SYMBOL_HASH (lsym) = scm_hash;
+  SCM_SYMBOL_PROPS (lsym) = SCM_EOL;
   if (obarray == SCM_BOOL_F)
     {
       SCM answer;
       SCM_REALLOW_INTS;
       SCM_NEWCELL (answer);
       SCM_DEFER_INTS;
-      SCM_CAR (answer) = lsym;
-      SCM_CDR (answer) = SCM_UNDEFINED;
+      SCM_SETCAR (answer, lsym);
+      SCM_SETCDR (answer, SCM_UNDEFINED);
       SCM_REALLOW_INTS;
       return answer;
     }
@@ -321,63 +318,37 @@ scm_intern_obarray_soft (name, len, obarray, softness)
     }
 }
 
-#ifdef __STDC__
-SCM
-scm_intern_obarray (char *name, scm_sizet len, SCM obarray)
-#else
+
 SCM
-scm_intern_obarray (name, len, obarray)
-     char *name;
-     scm_sizet len;
-     SCM obarray;
-#endif
+scm_intern_obarray (const char *name,scm_sizet len,SCM obarray)
 {
   return scm_intern_obarray_soft (name, len, obarray, 0);
 }
 
 
-#ifdef __STDC__
-SCM 
-scm_intern (char *name, scm_sizet len)
-#else
 SCM 
-scm_intern (name, len)
-     char *name;
-     scm_sizet len;
-#endif
+scm_intern (const char *name,scm_sizet len)
 {
   return scm_intern_obarray (name, len, scm_symhash);
 }
 
-#ifdef __STDC__
-SCM
-scm_intern0 (char * name)
-#else
+
 SCM
-scm_intern0 (name)
-     char * name;
-#endif
+scm_intern0 (const char * name)
 {
   return scm_intern (name, strlen (name));
 }
 
 
-#ifdef __STDC__
-SCM 
-scm_sysintern (char *name, SCM val)
-#else
+/* Intern the symbol named NAME in scm_symhash, NAME is null-terminated.  */
 SCM 
-scm_sysintern (name, val)
-     char *name;
-     SCM val;
-#endif
+scm_sysintern0_no_module_lookup (const char *name)
 {
   SCM easy_answer;
   SCM_DEFER_INTS;
   easy_answer = scm_intern_obarray_soft (name, strlen (name), scm_symhash, 1);
   if (SCM_NIMP (easy_answer))
     {
-      SCM_CDR (easy_answer) = val;
       SCM_ALLOW_INTS;
       return easy_answer;
     }
@@ -390,7 +361,7 @@ scm_sysintern (name, val)
       SCM_NEWCELL (lsym);
       SCM_SETLENGTH (lsym, (long) len, scm_tc7_ssymbol);
       SCM_SETCHARS (lsym, name);
-      lsym = scm_cons (lsym, val);
+      lsym = scm_cons (lsym, SCM_UNDEFINED);
       SCM_VELTS (scm_symhash)[scm_hash] = scm_cons (lsym, SCM_VELTS (scm_symhash)[scm_hash]);
       SCM_ALLOW_INTS;
       return lsym;
@@ -398,81 +369,162 @@ scm_sysintern (name, val)
 }
 
 
-SCM_PROC(s_symbol_p, "symbol?", 1, 0, 0, scm_symbol_p);
-#ifdef __STDC__
-SCM
-scm_symbol_p(SCM x)
-#else
+/* Is it safe to access SCM_TOP_LEVEL_LOOKUP_CLOSURE_VAR?
+ */
+int scm_can_use_top_level_lookup_closure_var;
+
+/* Intern the symbol named NAME in scm_symhash, and give it the value
+   VAL.  NAME is null-terminated.  Use the current top_level lookup
+   closure to give NAME its value.
+ */
 SCM
-scm_symbol_p(x)
-     SCM x;
-#endif
+scm_sysintern (const char *name, SCM val)
 {
-       if SCM_IMP(x) return SCM_BOOL_F;
-       return SCM_SYMBOLP(x) ? SCM_BOOL_T : SCM_BOOL_F;
+  SCM vcell = scm_sysintern0 (name);
+  SCM_SETCDR (vcell, val);
+  return vcell;
 }
 
-SCM_PROC(s_symbol_to_string, "symbol->string", 1, 0, 0, scm_symbol_to_string);
-#ifdef __STDC__
-SCM
-scm_symbol_to_string(SCM s)
-#else
 SCM
-scm_symbol_to_string(s)
-     SCM s;
-#endif
+scm_sysintern0 (const char *name)
 {
-       SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_to_string);
-       return scm_makfromstr(SCM_CHARS(s), (scm_sizet)SCM_LENGTH(s), 0);
+  SCM lookup_proc;
+  if (scm_can_use_top_level_lookup_closure_var && 
+      SCM_NIMP (lookup_proc = SCM_CDR (scm_top_level_lookup_closure_var)))
+    {
+      SCM sym = SCM_CAR (scm_intern0 (name));
+      SCM vcell = scm_sym2vcell (sym, lookup_proc, SCM_BOOL_T);
+      if (vcell == SCM_BOOL_F)
+         scm_misc_error ("sysintern0", "can't define variable", sym);
+      return vcell;
+    }
+  else
+    return scm_sysintern0_no_module_lookup (name);
 }
 
-
-SCM_PROC(s_string_to_symbol, "string->symbol", 1, 0, 0, scm_string_to_symbol);
-#ifdef __STDC__
+/* Lookup the value of the symbol named by the nul-terminated string
+   NAME in the current module.  */
 SCM
-scm_string_to_symbol(SCM s)
-#else
-SCM
-scm_string_to_symbol(s)
-     SCM s;
-#endif
+scm_symbol_value0 (const char *name)
+{
+  /* This looks silly - we look up the symbol twice.  But it is in
+     fact necessary given the current module system because the module
+     lookup closures are written in scheme which needs real symbols. */
+  SCM symbol = scm_intern_obarray_soft (name, strlen (name), scm_symhash, 0);
+  SCM vcell = scm_sym2vcell (SCM_CAR (symbol),
+                            SCM_CDR (scm_top_level_lookup_closure_var),
+                            SCM_BOOL_F);
+  if (SCM_FALSEP (vcell))
+    return SCM_UNDEFINED;
+  return SCM_CDR (vcell);
+}
+
+SCM_DEFINE (scm_symbol_p, "symbol?", 1, 0, 0, 
+           (SCM obj),
+           "Returns @t{#t} if @var{obj} is a symbol, otherwise returns @t{#f}. (r5rs)")
+#define FUNC_NAME s_scm_symbol_p
+{
+  if SCM_IMP(obj) return SCM_BOOL_F;
+  return SCM_BOOL(SCM_SYMBOLP(obj));
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_symbol_to_string, "symbol->string", 1, 0, 0, 
+           (SCM s),
+           "Returns the name of @var{symbol} as a string.  If the symbol was part of\n"
+           "an object returned as the value of a literal expression\n"
+           "(section @pxref{Literal expressions}) or by a call to the @samp{read} procedure,\n"
+           "and its name contains alphabetic characters, then the string returned\n"
+           "will contain characters in the implementation's preferred standard\n"
+           "case---some implementations will prefer upper case, others lower case.\n"
+           "If the symbol was returned by @samp{string->symbol}, the case of\n"
+           "characters in the string returned will be the same as the case in the\n"
+           "string that was passed to @samp{string->symbol}.  It is an error\n"
+           "to apply mutation procedures like @code{string-set!} to strings returned\n"
+           "by this procedure. (r5rs)\n\n"
+           "The following examples assume that the implementation's standard case is\n"
+           "lower case:\n\n"
+           "@format\n"
+           "@t{(symbol->string 'flying-fish)     \n"
+           "                                ==>  \"flying-fish\"\n"
+           "(symbol->string 'Martin)               ==>  \"martin\"\n"
+           "(symbol->string\n"
+           "   (string->symbol "Malvina"))     \n"
+            "                           ==>  \"Malvina\"\n"
+           "}\n"
+           "@end format")
+#define FUNC_NAME s_scm_symbol_to_string
+{
+  SCM_VALIDATE_SYMBOL (1,s);
+  return scm_makfromstr(SCM_CHARS(s), (scm_sizet)SCM_LENGTH(s), 0);
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_string_to_symbol, "string->symbol", 1, 0, 0, 
+           (SCM s),
+           "Returns the symbol whose name is @var{string}.  This procedure can\n"
+           "create symbols with names containing special characters or letters in\n"
+           "the non-standard case, but it is usually a bad idea to create such\n"
+           "symbols because in some implementations of Scheme they cannot be read as\n"
+           "themselves.  See @samp{symbol->string}.\n\n"
+           "The following examples assume that the implementation's standard case is\n"
+           "lower case:\n\n"
+"@format\n"
+"@t{(eq? 'mISSISSIppi 'mississippi)  \n"
+"          ==>  #t\n"
+"(string->symbol \"mISSISSIppi\")  \n"
+"          ==>\n"
+"  @r{}the symbol with name \"mISSISSIppi\"\n"
+"(eq? 'bitBlt (string->symbol \"bitBlt\"))     \n"
+"          ==>  #f\n"
+"(eq? 'JollyWog\n"
+"     (string->symbol\n"
+"       (symbol->string 'JollyWog)))  \n"
+"          ==>  #t\n"
+"(string=? \"K. Harper, M.D.\"\n"
+"          (symbol->string\n"
+"            (string->symbol \"K. Harper, M.D.\")))  \n"
+"          ==>  #t\n"
+"}\n"
+           "@end format")
+#define FUNC_NAME s_scm_string_to_symbol
 {
   SCM vcell;
   SCM answer;
 
-  SCM_ASSERT(SCM_NIMP(s) && SCM_ROSTRINGP(s), s, SCM_ARG1, s_string_to_symbol);
+  SCM_VALIDATE_ROSTRING (1,s);
   vcell = scm_intern(SCM_ROCHARS(s), (scm_sizet)SCM_LENGTH(s));
   answer = SCM_CAR (vcell);
-  if (SCM_TYP7 (answer) == scm_tc7_msymbol)
-    {
-      if (SCM_REGULAR_STRINGP (s))
-       SCM_SYMBOL_MULTI_BYTE_STRINGP (answer) = SCM_BOOL_F;
-      else
-       SCM_SYMBOL_MULTI_BYTE_STRINGP (answer) = SCM_BOOL_T;
-    }
   return answer;
 }
-
-
-SCM_PROC(s_string_to_obarray_symbol, "string->obarray-symbol", 2, 1, 0, scm_string_to_obarray_symbol);
-#ifdef __STDC__
-SCM
-scm_string_to_obarray_symbol(SCM o, SCM s, SCM softp)
-#else
-SCM
-scm_string_to_obarray_symbol(o, s, softp)
-     SCM o;
-     SCM s;
-     SCM softp;
-#endif
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_string_to_obarray_symbol, "string->obarray-symbol", 2, 1, 0,
+           (SCM o, SCM s, SCM softp),
+           "Intern a new symbol in @var{obarray}, a symbol table, with name\n"
+           "@var{string}.\n\n"
+           "If @var{obarray} is @code{#f}, use the default system symbol table.  If\n"
+           "@var{obarray} is @code{#t}, the symbol should not be interned in any\n"
+           "symbol table; merely return the pair (@var{symbol}\n"
+           ". @var{#<undefined>}).\n\n"
+           "The @var{soft?} argument determines whether new symbol table entries\n"
+           "should be created when the specified symbol is not already present in\n"
+           "@var{obarray}.  If @var{soft?} is specified and is a true value, then\n"
+           "new entries should not be added for symbols not already present in the\n"
+           "table; instead, simply return @code{#f}.")
+#define FUNC_NAME s_scm_string_to_obarray_symbol
 {
   SCM vcell;
   SCM answer;
   int softness;
 
-  SCM_ASSERT(SCM_NIMP(s) && SCM_ROSTRINGP(s), s, SCM_ARG2, s_string_to_obarray_symbol);
-  SCM_ASSERT((o == SCM_BOOL_F) || (o == SCM_BOOL_T) || (SCM_NIMP(o) && SCM_VECTORP(o)),
-        o, SCM_ARG1, s_string_to_obarray_symbol);
+  SCM_VALIDATE_ROSTRING (2,s);
+  SCM_ASSERT((o == SCM_BOOL_F)
+            || (o == SCM_BOOL_T)
+            || (SCM_VECTORP(o)),
+            o, SCM_ARG1, FUNC_NAME);
 
   softness = ((softp != SCM_UNDEFINED) && (softp != SCM_BOOL_F));
   /* iron out some screwy calling conventions */
@@ -481,140 +533,124 @@ scm_string_to_obarray_symbol(o, s, softp)
   else if (o == SCM_BOOL_T)
     o = SCM_BOOL_F;
     
-  vcell = scm_intern_obarray_soft (SCM_ROCHARS(s), (scm_sizet)SCM_ROLENGTH(s), o, softness);
+  vcell = scm_intern_obarray_soft (SCM_ROCHARS(s),
+                                  (scm_sizet)SCM_ROLENGTH(s),
+                                  o,
+                                  softness);
   if (vcell == SCM_BOOL_F)
     return vcell;
   answer = SCM_CAR (vcell);
-  if (SCM_TYP7 (s) == scm_tc7_msymbol)
-    {
-      if (SCM_REGULAR_STRINGP (s))
-       SCM_SYMBOL_MULTI_BYTE_STRINGP (answer) = SCM_BOOL_F;
-      else
-       SCM_SYMBOL_MULTI_BYTE_STRINGP (answer) = SCM_BOOL_T;
-    }
   return answer;
 }
-
-SCM_PROC(s_intern_symbol, "intern-symbol", 2, 0, 0, scm_intern_symbol);
-#ifdef __STDC__
-SCM
-scm_intern_symbol(SCM o, SCM s)
-#else
-SCM
-scm_intern_symbol(o, s)
-     SCM o;
-     SCM s;
-#endif
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_intern_symbol, "intern-symbol", 2, 0, 0,
+           (SCM o, SCM s),
+           "Add a new symbol to @var{obarray} with name @var{string}, bound to an\n"
+           "unspecified initial value.  The symbol table is not modified if a symbol\n"
+           "with this name is already present.")
+#define FUNC_NAME s_scm_intern_symbol
 {
-        scm_sizet hval;
-       SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_intern_symbol);
-       if (o == SCM_BOOL_F)
-         o = scm_symhash;
-       SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_intern_symbol);
-       hval = scm_strhash (SCM_UCHARS (s), SCM_LENGTH (s), SCM_LENGTH(o));
-       /* If the symbol is already interned, simply return. */
-       SCM_REDEFER_INTS;
-       {
-         SCM lsym;
-         SCM sym;
-         for (lsym = SCM_VELTS (o)[hval];
-              SCM_NIMP (lsym);
-              lsym = SCM_CDR (lsym))
-           {
-             sym = SCM_CAR (lsym);
-             if (SCM_CAR (sym) == s)
-               {
-                 SCM_REALLOW_INTS;
-                 return SCM_UNSPECIFIED;
-               }
-           }
-         SCM_VELTS (o)[hval] =
-           scm_acons (s, SCM_UNDEFINED, SCM_VELTS (o)[hval]);
-       }
-       SCM_REALLOW_INTS;
-       return SCM_UNSPECIFIED;
+  scm_sizet hval;
+  SCM_VALIDATE_SYMBOL (2,s);
+  if (o == SCM_BOOL_F)
+    o = scm_symhash;
+  SCM_VALIDATE_VECTOR (1,o);
+  hval = scm_strhash (SCM_UCHARS (s), SCM_LENGTH (s), SCM_LENGTH(o));
+  /* If the symbol is already interned, simply return. */
+  SCM_REDEFER_INTS;
+  {
+    SCM lsym;
+    SCM sym;
+    for (lsym = SCM_VELTS (o)[hval];
+        SCM_NIMP (lsym);
+        lsym = SCM_CDR (lsym))
+      {
+       sym = SCM_CAR (lsym);
+       if (SCM_CAR (sym) == s)
+         {
+           SCM_REALLOW_INTS;
+           return SCM_UNSPECIFIED;
+         }
+      }
+    SCM_VELTS (o)[hval] =
+      scm_acons (s, SCM_UNDEFINED, SCM_VELTS (o)[hval]);
+  }
+  SCM_REALLOW_INTS;
+  return SCM_UNSPECIFIED;
 }
-
-SCM_PROC(s_unintern_symbol, "unintern-symbol", 2, 0, 0, scm_unintern_symbol);
-#ifdef __STDC__
-SCM
-scm_unintern_symbol(SCM o, SCM s)
-#else
-SCM
-scm_unintern_symbol(o, s)
-     SCM o;
-     SCM s;
-#endif
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_unintern_symbol, "unintern-symbol", 2, 0, 0,
+           (SCM o, SCM s),
+           "Remove the symbol with name @var{string} from @var{obarray}.  This\n"
+           "function returns @code{#t} if the symbol was present and @code{#f}\n"
+           "otherwise.")
+#define FUNC_NAME s_scm_unintern_symbol
 {
-        scm_sizet hval;
-       SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_unintern_symbol);
-       if (o == SCM_BOOL_F)
-         o = scm_symhash;
-       SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_unintern_symbol);
-       hval = scm_strhash (SCM_UCHARS (s), SCM_LENGTH (s), SCM_LENGTH(o));
-       SCM_DEFER_INTS;
-       {
-         SCM lsym_follow;
-         SCM lsym;
-         SCM sym;
-         for (lsym = SCM_VELTS (o)[hval], lsym_follow = SCM_BOOL_F;
-              SCM_NIMP (lsym);
-              lsym_follow = lsym, lsym = SCM_CDR (lsym))
-           {
-             sym = SCM_CAR (lsym);
-             if (SCM_CAR (sym) == s)
-               {
-                 /* Found the symbol to unintern. */
-                 if (lsym_follow == SCM_BOOL_F)
-                   SCM_VELTS(o)[hval] = lsym;
-                 else
-                   SCM_CDR(lsym_follow) = SCM_CDR(lsym);
-                 SCM_ALLOW_INTS;
-                 return SCM_BOOL_T;
-               }
-           }
-       }
-       SCM_ALLOW_INTS;
-       return SCM_BOOL_F;
+  scm_sizet hval;
+  SCM_VALIDATE_SYMBOL (2,s);
+  if (o == SCM_BOOL_F)
+    o = scm_symhash;
+  SCM_VALIDATE_VECTOR (1,o);
+  hval = scm_strhash (SCM_UCHARS (s), SCM_LENGTH (s), SCM_LENGTH(o));
+  SCM_DEFER_INTS;
+  {
+    SCM lsym_follow;
+    SCM lsym;
+    SCM sym;
+    for (lsym = SCM_VELTS (o)[hval], lsym_follow = SCM_BOOL_F;
+        SCM_NIMP (lsym);
+        lsym_follow = lsym, lsym = SCM_CDR (lsym))
+      {
+       sym = SCM_CAR (lsym);
+       if (SCM_CAR (sym) == s)
+         {
+           /* Found the symbol to unintern. */
+           if (lsym_follow == SCM_BOOL_F)
+             SCM_VELTS(o)[hval] = lsym;
+           else
+             SCM_SETCDR (lsym_follow, SCM_CDR(lsym));
+           SCM_ALLOW_INTS;
+           return SCM_BOOL_T;
+         }
+      }
+  }
+  SCM_ALLOW_INTS;
+  return SCM_BOOL_F;
 }
-
-SCM_PROC(s_symbol_binding, "symbol-binding", 2, 0, 0, scm_symbol_binding);
-#ifdef __STDC__
-SCM
-scm_symbol_binding (SCM o, SCM s)
-#else
-SCM
-scm_symbol_binding (o, s)
-     SCM o;
-     SCM s;
-#endif
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_symbol_binding, "symbol-binding", 2, 0, 0,
+           (SCM o, SCM s),
+           "Look up in @var{obarray} the symbol whose name is @var{string}, and\n"
+           "return the value to which it is bound.  If @var{obarray} is @code{#f},\n"
+           "use the global symbol table.  If @var{string} is not interned in\n"
+           "@var{obarray}, an error is signalled.")
+#define FUNC_NAME s_scm_symbol_binding
 {
   SCM vcell;
-  SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_symbol_binding);
+  SCM_VALIDATE_SYMBOL (2,s);
   if (o == SCM_BOOL_F)
     o = scm_symhash;
-  SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_symbol_binding);
+  SCM_VALIDATE_VECTOR (1,o);
   vcell = scm_sym2ovcell (s, o);
   return SCM_CDR(vcell);
 }
+#undef FUNC_NAME
 
 
-SCM_PROC(s_symbol_interned_p, "symbol-interned?", 2, 0, 0, scm_symbol_interned_p);
-#ifdef __STDC__
-SCM
-scm_symbol_interned_p (SCM o, SCM s)
-#else
-SCM
-scm_symbol_interned_p (o, s)
-     SCM o;
-     SCM s;
-#endif
+SCM_DEFINE (scm_symbol_interned_p, "symbol-interned?", 2, 0, 0,
+           (SCM o, SCM s),
+           "Return @var{#t} if @var{obarray} contains a symbol with name\n"
+           "@var{string}, and @var{#f} otherwise.")
+#define FUNC_NAME s_scm_symbol_interned_p
 {
   SCM vcell;
-  SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_symbol_interned_p);
+  SCM_VALIDATE_SYMBOL (2,s);
   if (o == SCM_BOOL_F)
     o = scm_symhash;
-  SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_symbol_interned_p);
+  SCM_VALIDATE_VECTOR (1,o);
   vcell = scm_sym2ovcell_soft (s, o);
   if (SCM_IMP(vcell) && (o == scm_symhash))
     vcell = scm_sym2ovcell_soft (s, scm_weak_symhash);
@@ -622,118 +658,103 @@ scm_symbol_interned_p (o, s)
          ? SCM_BOOL_T
          : SCM_BOOL_F);
 }
+#undef FUNC_NAME
 
 
-SCM_PROC(s_symbol_bound_p, "symbol-bound?", 2, 0, 0, scm_symbol_bound_p);
-#ifdef __STDC__
-SCM 
-scm_symbol_bound_p (SCM o, SCM s)
-#else
-SCM 
-scm_symbol_bound_p (o, s)
-     SCM o;
-     SCM s;
-#endif
+SCM_DEFINE (scm_symbol_bound_p, "symbol-bound?", 2, 0, 0,
+           (SCM o, SCM s),
+           "Return @var{#t} if @var{obarray} contains a symbol with name\n"
+           "@var{string} bound to a defined value.  This differs from\n"
+           "@var{symbol-bound?} in that the mere mention of a symbol usually causes\n"
+           "it to be interned; @code{symbol-bound?} determines whether a symbol has\n"
+           "been given any meaningful value.")
+#define FUNC_NAME s_scm_symbol_bound_p
 {
   SCM vcell;
-  SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_symbol_bound_p);
+  SCM_VALIDATE_SYMBOL (2,s);
   if (o == SCM_BOOL_F)
     o = scm_symhash;
-  SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_symbol_bound_p);
+  SCM_VALIDATE_VECTOR (1,o);
   vcell = scm_sym2ovcell_soft (s, o);
   return ((  SCM_NIMP(vcell)
           && (SCM_CDR(vcell) != SCM_UNDEFINED))
          ? SCM_BOOL_T
          : SCM_BOOL_F);
 }
+#undef FUNC_NAME
 
 
-SCM_PROC(s_symbol_set_x, "symbol-set!", 3, 0, 0, scm_symbol_set_x);
-#ifdef __STDC__
-SCM 
-scm_symbol_set_x (SCM o, SCM s, SCM v)
-#else
-SCM 
-scm_symbol_set_x (o, s, v)
-     SCM o;
-     SCM s;
-     SCM v;
-#endif
+SCM_DEFINE (scm_symbol_set_x, "symbol-set!", 3, 0, 0,
+           (SCM o, SCM s, SCM v),
+           "Find the symbol in @var{obarray} whose name is @var{string}, and rebind\n"
+           "it to @var{value}.  An error is signalled if @var{string} is not present\n"
+           "in @var{obarray}.")
+#define FUNC_NAME s_scm_symbol_set_x
 {
   SCM vcell;
-  SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG2, s_symbol_set_x);
+  SCM_VALIDATE_SYMBOL (2,s);
   if (o == SCM_BOOL_F)
     o = scm_symhash;
-  SCM_ASSERT(SCM_NIMP(o) && SCM_VECTORP(o), o, SCM_ARG1, s_symbol_set_x);
+  SCM_VALIDATE_VECTOR (1,o);
   vcell = scm_sym2ovcell (s, o);
-  SCM_CDR(vcell) = v;
+  SCM_SETCDR (vcell, v);
   return SCM_UNSPECIFIED;
 }
+#undef FUNC_NAME
 
 static void
-msymbolize (s)
-     SCM s;
+msymbolize (SCM s)
 {
   SCM string;
   string = scm_makfromstr (SCM_CHARS (s), SCM_LENGTH (s), SCM_SYMBOL_SLOTS);
   SCM_SETCHARS (s, SCM_CHARS (string));
   SCM_SETLENGTH (s, SCM_LENGTH (s), scm_tc7_msymbol);
-  SCM_SYMBOL_MULTI_BYTE_STRINGP (s) = SCM_BOOL_F;
-  SCM_CDR (string) = SCM_EOL;
-  SCM_CAR (string) = SCM_EOL;
+  SCM_SETCDR (string, SCM_EOL);
+  SCM_SETCAR (string, SCM_EOL);
+  SCM_SYMBOL_PROPS (s) = SCM_EOL;
+  /* If it's a tc7_ssymbol, it comes from scm_symhash */
+  SCM_SYMBOL_HASH (s) = scm_strhash (SCM_UCHARS (s),
+                                    (scm_sizet) SCM_LENGTH (s),
+                                    SCM_LENGTH (scm_symhash));
 }
 
 
-SCM_PROC(s_symbol_fref, "symbol-fref", 1, 0, 0, scm_symbol_fref);
-#ifdef __STDC__
-SCM
-scm_symbol_fref (SCM s)
-#else
-SCM
-scm_symbol_fref (s)
-     SCM s;
-#endif
+SCM_DEFINE (scm_symbol_fref, "symbol-fref", 1, 0, 0, 
+           (SCM s),
+           "Return the contents of @var{symbol}'s @dfn{function slot}.")
+#define FUNC_NAME s_scm_symbol_fref
 {
-  SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_fref);
+  SCM_VALIDATE_SYMBOL (1,s);
   SCM_DEFER_INTS;
   if (SCM_TYP7(s) == scm_tc7_ssymbol)
     msymbolize (s);
   SCM_ALLOW_INTS;
   return SCM_SYMBOL_FUNC (s);
 }
+#undef FUNC_NAME
 
 
-SCM_PROC(s_symbol_pref, "symbol-pref", 1, 0, 0, scm_symbol_pref);
-#ifdef __STDC__
-SCM
-scm_symbol_pref (SCM s)
-#else
-SCM
-scm_symbol_pref (s)
-     SCM s;
-#endif
+SCM_DEFINE (scm_symbol_pref, "symbol-pref", 1, 0, 0, 
+           (SCM s),
+           "Return the @dfn{property list} currently associated with @var{symbol}.")
+#define FUNC_NAME s_scm_symbol_pref
 {
-  SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_pref);
+  SCM_VALIDATE_SYMBOL (1,s);
   SCM_DEFER_INTS;
   if (SCM_TYP7(s) == scm_tc7_ssymbol)
     msymbolize (s);
   SCM_ALLOW_INTS;
   return SCM_SYMBOL_PROPS (s);
 }
+#undef FUNC_NAME
 
 
-SCM_PROC(s_symbol_fset_x, "symbol-fset!", 2, 0, 0, scm_symbol_fset_x);
-#ifdef __STDC__
-SCM
-scm_symbol_fset_x (SCM s, SCM val)
-#else
-SCM
-scm_symbol_fset_x (s, val)
-     SCM s;
-     SCM val;
-#endif
+SCM_DEFINE (scm_symbol_fset_x, "symbol-fset!", 2, 0, 0, 
+           (SCM s, SCM val),
+           "Change the binding of @var{symbol}'s function slot.")
+#define FUNC_NAME s_scm_symbol_fset_x
 {
-  SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_fset_x);
+  SCM_VALIDATE_SYMBOL (1,s);
   SCM_DEFER_INTS;
   if (SCM_TYP7(s) == scm_tc7_ssymbol)
     msymbolize (s);
@@ -741,20 +762,15 @@ scm_symbol_fset_x (s, val)
   SCM_SYMBOL_FUNC (s) = val;
   return SCM_UNSPECIFIED;
 }
+#undef FUNC_NAME
 
 
-SCM_PROC(s_symbol_pset_x, "symbol-pset!", 2, 0, 0, scm_symbol_pset_x);
-#ifdef __STDC__
-SCM
-scm_symbol_pset_x (SCM s, SCM val)
-#else
-SCM
-scm_symbol_pset_x (s, val)
-     SCM s;
-     SCM val;
-#endif
+SCM_DEFINE (scm_symbol_pset_x, "symbol-pset!", 2, 0, 0,
+           (SCM s, SCM val),
+           "Change the binding of @var{symbol}'s property slot.")
+#define FUNC_NAME s_scm_symbol_pset_x
 {
-  SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_pset_x);
+  SCM_VALIDATE_SYMBOL (1,s);
   SCM_DEFER_INTS;
   if (SCM_TYP7(s) == scm_tc7_ssymbol)
     msymbolize (s);
@@ -762,31 +778,118 @@ scm_symbol_pset_x (s, val)
   SCM_ALLOW_INTS;
   return SCM_UNSPECIFIED;
 }
+#undef FUNC_NAME
 
 
-SCM_PROC(s_symbol_hash, "symbol-hash", 1, 0, 0, scm_symbol_hash);
-#ifdef __STDC__
-SCM
-scm_symbol_hash (SCM s)
-#else
-SCM
-scm_symbol_hash (s)
-     SCM s;
-#endif
+SCM_DEFINE (scm_symbol_hash, "symbol-hash", 1, 0, 0, 
+           (SCM s),
+           "Return the hash value derived from @var{symbol}'s name, i.e. the integer\n"
+           "index into @var{symbol}'s obarray at which it is stored.")
+#define FUNC_NAME s_scm_symbol_hash
 {
-  SCM_ASSERT(SCM_NIMP(s) && SCM_SYMBOLP(s), s, SCM_ARG1, s_symbol_hash);
+  SCM_VALIDATE_SYMBOL (1,s);
+  if (SCM_TYP7(s) == scm_tc7_ssymbol)
+    msymbolize (s);
   return SCM_MAKINUM ((unsigned long)s ^ SCM_SYMBOL_HASH (s));
 }
+#undef FUNC_NAME
 
 
-#ifdef __STDC__
-void
-scm_init_symbols (void)
-#else
+static void
+copy_and_prune_obarray (SCM from, SCM to)
+{
+  int i;
+  int length = SCM_LENGTH (from);
+  for (i = 0; i < length; ++i)
+    {
+      SCM head = SCM_VELTS (from)[i]; /* GC protection */
+      SCM ls = head;
+      SCM res = SCM_EOL;
+      SCM *lloc = &res;
+      while (SCM_NIMP (ls))
+       {
+         if (!SCM_UNBNDP (SCM_CDAR (ls)))
+           {
+             *lloc = scm_cons (SCM_CAR (ls), SCM_EOL);
+             lloc = SCM_CDRLOC (*lloc);
+           }
+         ls = SCM_CDR (ls);
+       }
+      SCM_VELTS (to)[i] = res;
+    }
+}
+
+
+SCM_DEFINE (scm_builtin_bindings, "builtin-bindings", 0, 0, 0, 
+            (),
+           "Create and return a copy of the global symbol table, removing all\n"
+           "unbound symbols.")
+#define FUNC_NAME s_scm_builtin_bindings
+{
+  int length = SCM_LENGTH (scm_symhash);
+  SCM obarray = scm_make_vector (SCM_MAKINUM (length), SCM_EOL);
+  copy_and_prune_obarray (scm_symhash, obarray);
+  return obarray;
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_builtin_weak_bindings, "builtin-weak-bindings", 0, 0, 0, 
+            (),
+           "")
+#define FUNC_NAME s_scm_builtin_weak_bindings
+{
+  int length = SCM_LENGTH (scm_weak_symhash);
+  SCM obarray = scm_make_doubly_weak_hash_table (SCM_MAKINUM (length));
+  copy_and_prune_obarray (scm_weak_symhash, obarray);
+  return obarray;
+}
+#undef FUNC_NAME
+
+static int gensym_counter;
+static SCM gensym_prefix;
+
+/* :FIXME:OPTIMIZE */
+SCM_DEFINE (scm_gensym, "gensym", 0, 2, 0,
+            (SCM name, SCM obarray),
+           "Create a new, unique symbol in @var{obarray}, using the global symbol\n"
+           "table by default.  If @var{name} is specified, it should be used as a\n"
+           "prefix for the new symbol's name.  The default prefix is @code{%%gensym}.")
+#define FUNC_NAME s_scm_gensym
+{
+  SCM new;
+  if (SCM_UNBNDP (name))
+    name = gensym_prefix;
+  else
+    SCM_VALIDATE_ROSTRING (1,name);
+
+  new = name;
+  if (SCM_UNBNDP (obarray))
+    {
+      obarray = SCM_BOOL_F;
+      goto skip_test;
+    }
+  else
+    SCM_ASSERT ((SCM_VECTORP (obarray) || SCM_WVECTP (obarray)),
+               obarray,
+               SCM_ARG2,
+               FUNC_NAME);
+  while (scm_string_to_obarray_symbol (obarray, new, SCM_BOOL_T)
+        != SCM_BOOL_F)
+    skip_test:
+    new = scm_string_append
+      (scm_cons2 (name,
+                 scm_number_to_string (SCM_MAKINUM (gensym_counter++),
+                                       SCM_UNDEFINED),
+                 SCM_EOL));
+  return scm_string_to_obarray_symbol (obarray, new, SCM_BOOL_F);
+}
+#undef FUNC_NAME
+
 void
 scm_init_symbols ()
-#endif
 {
+  gensym_counter = 0;
+  gensym_prefix = scm_permanent_object (scm_makfrom0str ("%%gensym"));
 #include "symbols.x"
 }
-