* character.h (STRING_CHAR, STRING_CHAR_AND_LENGTH): Remove
[bpt/emacs.git] / src / lread.c
index 77c7a3c..97b9410 100644 (file)
@@ -1,14 +1,14 @@
 /* Lisp parsing and input streams.
    Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995,
                  1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+                 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 #include <config.h>
@@ -82,6 +80,14 @@ Boston, MA 02110-1301, USA.  */
 extern int errno;
 #endif
 
+/* hash table read constants */
+Lisp_Object Qhash_table, Qdata;
+Lisp_Object Qtest, Qsize;
+Lisp_Object Qweakness;
+Lisp_Object Qrehash_size;
+Lisp_Object Qrehash_threshold;
+extern Lisp_Object QCtest, QCsize, QCrehash_size, QCrehash_threshold, QCweakness;
+
 Lisp_Object Qread_char, Qget_file_char, Qstandard_input, Qcurrent_load_list;
 Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input, Vafter_load_alist;
 Lisp_Object Qascii_character, Qload, Qload_file_name;
@@ -101,6 +107,7 @@ extern Lisp_Object Qfile_exists_p;
 
 /* non-zero if inside `load' */
 int load_in_progress;
+static Lisp_Object Qload_in_progress;
 
 /* Directory in which the sources were found.  */
 Lisp_Object Vsource_directory;
@@ -127,6 +134,9 @@ Lisp_Object Vload_file_name;
 /* Function to use for reading, in `load' and friends.  */
 Lisp_Object Vload_read_function;
 
+/* Non-nil means read recursive structures using #n= and #n# syntax.  */
+Lisp_Object Vread_circle;
+
 /* The association list of objects read with the #n=object form.
    Each member of the list has the form (n . object), and is used to
    look up the object for the corresponding #n# construct.
@@ -212,6 +222,10 @@ static Lisp_Object Vloads_in_progress;
 
 int load_dangerous_libraries;
 
+/* Non-zero means force printing messages when loading Lisp files.  */
+
+int force_load_messages;
+
 /* A regular expression used to detect files compiled with Emacs.  */
 
 static Lisp_Object Vbytecomp_version_regexp;
@@ -289,7 +303,7 @@ readchar (readcharfun, multibyte)
          /* Fetch the character code from the buffer.  */
          unsigned char *p = BUF_BYTE_ADDRESS (inbuffer, pt_byte);
          BUF_INC_POS (inbuffer, pt_byte);
-         c = STRING_CHAR (p, pt_byte - orig_pt_byte);
+         c = STRING_CHAR (p);
          if (multibyte)
            *multibyte = 1;
        }
@@ -318,7 +332,7 @@ readchar (readcharfun, multibyte)
          /* Fetch the character code from the buffer.  */
          unsigned char *p = BUF_BYTE_ADDRESS (inbuffer, bytepos);
          BUF_INC_POS (inbuffer, bytepos);
-         c = STRING_CHAR (p, bytepos - orig_bytepos);
+         c = STRING_CHAR (p);
          if (multibyte)
            *multibyte = 1;
        }
@@ -425,7 +439,7 @@ readchar (readcharfun, multibyte)
        }
       buf[i++] = c;
     }
-  return STRING_CHAR (buf, i);
+  return STRING_CHAR (buf);
 }
 
 /* Unread the character C in the way appropriate for the stream READCHARFUN.
@@ -793,13 +807,13 @@ floating-point value.  */)
      Lisp_Object prompt, inherit_input_method, seconds;
 {
   Lisp_Object val;
-  int c;
 
   if (! NILP (prompt))
     message_with_string ("%s", prompt, 0);
   val = read_filtered_event (1, 1, 1, ! NILP (inherit_input_method), seconds);
-  c = XINT (val);
-  return make_number (char_resolve_modifier_mask (c));
+
+  return (NILP (val) ? Qnil
+         : make_number (char_resolve_modifier_mask (XINT (val))));
 }
 
 DEFUN ("read-event", Fread_event, Sread_event, 0, 3, 0,
@@ -838,13 +852,14 @@ floating-point value.  */)
      Lisp_Object prompt, inherit_input_method, seconds;
 {
   Lisp_Object val;
-  int c;
 
   if (! NILP (prompt))
     message_with_string ("%s", prompt, 0);
+
   val = read_filtered_event (1, 1, 0, ! NILP (inherit_input_method), seconds);
-  c = XINT (val);
-  return make_number (char_resolve_modifier_mask (c));
+
+  return (NILP (val) ? Qnil
+         : make_number (char_resolve_modifier_mask (XINT (val))));
 }
 
 DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0,
@@ -967,7 +982,8 @@ This function searches the directories in `load-path'.
 If optional second arg NOERROR is non-nil,
 report no error if FILE doesn't exist.
 Print messages at start and end of loading unless
-optional third arg NOMESSAGE is non-nil.
+optional third arg NOMESSAGE is non-nil (but `force-load-messages'
+overrides that).
 If optional fourth arg NOSUFFIX is non-nil, don't try adding
 suffixes `.elc' or `.el' to the specified name FILE.
 If optional fifth arg MUST-SUFFIX is non-nil, insist on
@@ -1105,7 +1121,7 @@ Return t if the file exists and loads successfully.  */)
      2000-09-21: It's not possible to just check for the file loaded
      being a member of Vloads_in_progress.  This fails because of the
      way the byte compiler currently works; `provide's are not
-     evaluted, see font-lock.el/jit-lock.el as an example.  This
+     evaluated, see font-lock.el/jit-lock.el as an example.  This
      leads to a certain amount of ``normal'' recursion.
 
      Also, just loading a file recursively is not always an error in
@@ -1114,14 +1130,12 @@ Return t if the file exists and loads successfully.  */)
     int count = 0;
     Lisp_Object tem;
     for (tem = Vloads_in_progress; CONSP (tem); tem = XCDR (tem))
-      if (!NILP (Fequal (found, XCAR (tem))))
-       count++;
-    if (count > 3)
-      {
-       if (fd >= 0)
-         emacs_close (fd);
-       signal_error ("Recursive load", Fcons (found, Vloads_in_progress));
-      }
+      if (!NILP (Fequal (found, XCAR (tem))) && (++count > 3))
+       {
+         if (fd >= 0)
+           emacs_close (fd);
+         signal_error ("Recursive load", Fcons (found, Vloads_in_progress));
+       }
     record_unwind_protect (record_load_unwind, Vloads_in_progress);
     Vloads_in_progress = Fcons (found, Vloads_in_progress);
   }
@@ -1163,7 +1177,7 @@ Return t if the file exists and loads successfully.  */)
                  error ("File `%s' was not compiled in Emacs",
                         SDATA (found));
                }
-             else if (!NILP (nomessage))
+             else if (!NILP (nomessage) && !force_load_messages)
                message_with_string ("File `%s' not compiled in Emacs", found, 1);
            }
 
@@ -1185,7 +1199,7 @@ Return t if the file exists and loads successfully.  */)
              newer = 1;
 
              /* If we won't print another message, mention this anyway.  */
-             if (!NILP (nomessage))
+             if (!NILP (nomessage) && !force_load_messages)
                {
                  Lisp_Object msg_file;
                  msg_file = Fsubstring (found, make_number (0), make_number (-1));
@@ -1207,7 +1221,7 @@ Return t if the file exists and loads successfully.  */)
            emacs_close (fd);
          val = call4 (Vload_source_file_function, found, hist_file_name,
                       NILP (noerror) ? Qnil : Qt,
-                      NILP (nomessage) ? Qnil : Qt);
+                      (NILP (nomessage) || force_load_messages) ? Qnil : Qt);
          return unbind_to (count, val);
        }
     }
@@ -1228,9 +1242,9 @@ Return t if the file exists and loads successfully.  */)
     }
 
   if (! NILP (Vpurify_flag))
-    Vpreloaded_file_list = Fcons (file, Vpreloaded_file_list);
+    Vpreloaded_file_list = Fcons (Fpurecopy(file), Vpreloaded_file_list);
 
-  if (NILP (nomessage))
+  if (NILP (nomessage) || force_load_messages)
     {
       if (!safe_p)
        message_with_string ("Loading %s (compiled; note unsafe, not compiled in Emacs)...",
@@ -1250,7 +1264,7 @@ Return t if the file exists and loads successfully.  */)
   specbind (Qinhibit_file_name_operation, Qnil);
   load_descriptor_list
     = Fcons (make_number (fileno (stream)), load_descriptor_list);
-  load_in_progress++;
+  specbind (Qload_in_progress, Qt);
   if (! version || version >= 22)
     readevalloop (Qget_file_char, stream, hist_file_name,
                  Feval, 0, Qnil, Qnil, Qnil, Qnil);
@@ -1265,23 +1279,20 @@ Return t if the file exists and loads successfully.  */)
   unbind_to (count, Qnil);
 
   /* Run any eval-after-load forms for this file */
-  if (NILP (Vpurify_flag)
-      && (!NILP (Ffboundp (Qdo_after_load_evaluation))))
+  if (!NILP (Ffboundp (Qdo_after_load_evaluation)))
     call1 (Qdo_after_load_evaluation, hist_file_name) ;
 
   UNGCPRO;
 
-  if (saved_doc_string)
-    free (saved_doc_string);
+  xfree (saved_doc_string);
   saved_doc_string = 0;
   saved_doc_string_size = 0;
 
-  if (prev_saved_doc_string)
-    xfree (prev_saved_doc_string);
+  xfree (prev_saved_doc_string);
   prev_saved_doc_string = 0;
   prev_saved_doc_string_size = 0;
 
-  if (!noninteractive && NILP (nomessage))
+  if (!noninteractive && (NILP (nomessage) || force_load_messages))
     {
       if (!safe_p)
        message_with_string ("Loading %s (compiled; note unsafe, not compiled in Emacs)...done",
@@ -1295,11 +1306,6 @@ Return t if the file exists and loads successfully.  */)
        message_with_string ("Loading %s...done", file, 1);
     }
 
-  if (!NILP (Fequal (build_string ("obsolete"),
-                    Ffile_name_nondirectory
-                    (Fdirectory_file_name (Ffile_name_directory (found))))))
-    message_with_string ("Package %s is obsolete", file, 1);
-
   return Qt;
 }
 
@@ -1314,7 +1320,6 @@ load_unwind (arg)  /* used as unwind-protect function in load */
       fclose (stream);
       UNBLOCK_INPUT;
     }
-  if (--load_in_progress < 0) load_in_progress = 0;
   return Qnil;
 }
 
@@ -1346,11 +1351,7 @@ complete_filename_p (pathname)
   register const unsigned char *s = SDATA (pathname);
   return (IS_DIRECTORY_SEP (s[0])
          || (SCHARS (pathname) > 2
-             && IS_DEVICE_SEP (s[1]) && IS_DIRECTORY_SEP (s[2]))
-#ifdef VMS
-         || index (s, ':')
-#endif /* VMS */
-         );
+             && IS_DEVICE_SEP (s[1]) && IS_DIRECTORY_SEP (s[2])));
 }
 
 DEFUN ("locate-file-internal", Flocate_file_internal, Slocate_file_internal, 2, 4, 0,
@@ -1812,18 +1813,16 @@ readevalloop (readcharfun, stream, sourcename, evalfun,
 
 DEFUN ("eval-buffer", Feval_buffer, Seval_buffer, 0, 5, "",
        doc: /* Execute the current buffer as Lisp code.
-Programs can pass two arguments, BUFFER and PRINTFLAG.
+When called from a Lisp program (i.e., not interactively), this
+function accepts up to five optional arguments:
 BUFFER is the buffer to evaluate (nil means use current buffer).
 PRINTFLAG controls printing of output:
-A value of nil means discard it; anything else is stream for print.
-
-If the optional third argument FILENAME is non-nil,
-it specifies the file name to use for `load-history'.
-The optional fourth argument UNIBYTE specifies `load-convert-to-unibyte'
-for this invocation.
-
-The optional fifth argument DO-ALLOW-PRINT, if non-nil, specifies that
-`print' and related functions should work normally even if PRINTFLAG is nil.
+ A value of nil means discard it; anything else is stream for print.
+FILENAME specifies the file name to use for `load-history'.
+UNIBYTE, if non-nil, specifies `load-convert-to-unibyte' for this
+ invocation.
+DO-ALLOW-PRINT, if non-nil, specifies that `print' and related
+ functions should work normally even if PRINTFLAG is nil.
 
 This function preserves the position of point.  */)
      (buffer, printflag, filename, unibyte, do_allow_print)
@@ -2037,8 +2036,8 @@ read_escape (readcharfun, stringp)
      int stringp;
 {
   register int c = READCHAR;
-  /* \u allows up to four hex digits, \U up to eight. Default to the
-     behaviour for \u, and change this value in the case that \U is seen. */
+  /* \u allows up to four hex digits, \U up to eight.  Default to the
+     behavior for \u, and change this value in the case that \U is seen. */
   int unicode_hex_count = 4;
 
   switch (c)
@@ -2211,10 +2210,10 @@ read_escape (readcharfun, stringp)
       unicode_hex_count = 8;
     case 'u':
 
-      /* A Unicode escape. We only permit them in strings and characters,
+      /* A Unicode escape.  We only permit them in strings and characters,
         not arbitrarily in the source code, as in some other languages.  */
       {
-       int i = 0;
+       unsigned int i = 0;
        int count = 0;
 
        while (++count <= unicode_hex_count)
@@ -2231,7 +2230,8 @@ read_escape (readcharfun, stringp)
                break;
              }
          }
-
+       if (i > 0x10FFFF)
+         error ("Non-Unicode character: 0x%x", i);
        return i;
       }
 
@@ -2252,7 +2252,8 @@ read_integer (readcharfun, radix)
      int radix;
 {
   int ndigits = 0, invalid_p, c, sign = 0;
-  EMACS_INT number = 0;
+  /* We use a floating point number because  */
+  double number = 0;
 
   if (radix < 2 || radix > 36)
     invalid_p = 1;
@@ -2302,7 +2303,7 @@ read_integer (readcharfun, radix)
       invalid_syntax (buf, 0);
     }
 
-  return make_number (sign * number);
+  return make_fixnum_or_float (sign * number);
 }
 
 
@@ -2348,6 +2349,77 @@ read1 (readcharfun, pch, first_in_list)
 
     case '#':
       c = READCHAR;
+      if (c == 's')
+       {
+         c = READCHAR;
+         if (c == '(')
+           {
+             /* Accept extended format for hashtables (extensible to
+                other types), e.g.
+                #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
+             Lisp_Object tmp = read_list (0, readcharfun);
+             Lisp_Object head = CAR_SAFE (tmp);
+             Lisp_Object data = Qnil;
+             Lisp_Object val = Qnil;
+             /* The size is 2 * number of allowed keywords to
+                make-hash-table. */
+             Lisp_Object params[10];
+             Lisp_Object ht;
+             Lisp_Object key = Qnil;
+             int param_count = 0;
+
+             if (!EQ (head, Qhash_table))
+               error ("Invalid extended read marker at head of #s list "
+                      "(only hash-table allowed)");
+
+             tmp = CDR_SAFE (tmp);
+
+             /* This is repetitive but fast and simple. */
+             params[param_count] = QCsize;
+             params[param_count+1] = Fplist_get (tmp, Qsize);
+             if (!NILP (params[param_count+1]))
+               param_count+=2;
+
+             params[param_count] = QCtest;
+             params[param_count+1] = Fplist_get (tmp, Qtest);
+             if (!NILP (params[param_count+1]))
+               param_count+=2;
+
+             params[param_count] = QCweakness;
+             params[param_count+1] = Fplist_get (tmp, Qweakness);
+             if (!NILP (params[param_count+1]))
+               param_count+=2;
+
+             params[param_count] = QCrehash_size;
+             params[param_count+1] = Fplist_get (tmp, Qrehash_size);
+             if (!NILP (params[param_count+1]))
+               param_count+=2;
+
+             params[param_count] = QCrehash_threshold;
+             params[param_count+1] = Fplist_get (tmp, Qrehash_threshold);
+             if (!NILP (params[param_count+1]))
+               param_count+=2;
+
+             /* This is the hashtable data. */
+             data = Fplist_get (tmp, Qdata);
+
+             /* Now use params to make a new hashtable and fill it. */
+             ht = Fmake_hash_table (param_count, params);
+
+             while (CONSP (data))
+               {
+                 key = XCAR (data);
+                 data = XCDR (data);
+                 if (!CONSP (data))
+                   error ("Odd number of elements in hashtable data");
+                 val = XCAR (data);
+                 data = XCDR (data);
+                 Fputhash (key, val, ht);
+               }
+
+             return ht;
+           }
+       }
       if (c == '^')
        {
          c = READCHAR;
@@ -2568,13 +2640,13 @@ read1 (readcharfun, pch, first_in_list)
              c = READCHAR;
            }
          /* #n=object returns object, but associates it with n for #n#.  */
-         if (c == '=')
+         if (c == '=' && !NILP (Vread_circle))
            {
              /* Make a placeholder for #n# to use temporarily */
              Lisp_Object placeholder;
              Lisp_Object cell;
 
-             placeholder = Fcons(Qnil, Qnil);
+             placeholder = Fcons (Qnil, Qnil);
              cell = Fcons (make_number (n), placeholder);
              read_objects = Fcons (cell, read_objects);
 
@@ -2590,7 +2662,7 @@ read1 (readcharfun, pch, first_in_list)
              return tem;
            }
          /* #n# returns a previously read object.  */
-         if (c == '#')
+         if (c == '#' && !NILP (Vread_circle))
            {
              tem = Fassq (make_number (n), read_objects);
              if (CONSP (tem))
@@ -2924,7 +2996,6 @@ read1 (readcharfun, pch, first_in_list)
        if (!quoted && !uninterned_symbol)
          {
            register char *p1;
-           register Lisp_Object val;
            p1 = read_buffer;
            if (*p1 == '+' || *p1 == '-') p1++;
            /* Is it an integer? */
@@ -2938,15 +3009,21 @@ read1 (readcharfun, pch, first_in_list)
                  {
                    if (p1[-1] == '.')
                      p1[-1] = '\0';
-                   /* Fixme: if we have strtol, use that, and check
-                      for overflow.  */
-                   if (sizeof (int) == sizeof (EMACS_INT))
-                     XSETINT (val, atoi (read_buffer));
-                   else if (sizeof (long) == sizeof (EMACS_INT))
-                     XSETINT (val, atol (read_buffer));
-                   else
-                     abort ();
-                   return val;
+                   {
+                     /* EMACS_INT n = atol (read_buffer); */
+                     char *endptr = NULL;
+                     EMACS_INT n = (errno = 0,
+                                    strtol (read_buffer, &endptr, 10));
+                     if (errno == ERANGE && endptr)
+                       {
+                         Lisp_Object args
+                           = Fcons (make_string (read_buffer,
+                                                 endptr - read_buffer),
+                                    Qnil);
+                         xsignal (Qoverflow_error, args);
+                       }
+                     return make_fixnum_or_float (n);
+                   }
                  }
              }
            if (isfloat_string (read_buffer))
@@ -3057,18 +3134,18 @@ substitute_object_in_subtree (object, placeholder)
 }
 
 /*  Feval doesn't get called from here, so no gc protection is needed. */
-#define SUBSTITUTE(get_val, set_val)                 \
-{                                                    \
-  Lisp_Object old_value = get_val;                   \
-  Lisp_Object true_value                             \
-    = substitute_object_recurse (object, placeholder,\
-                              old_value);           \
-                                                     \
-  if (!EQ (old_value, true_value))                   \
-    {                                                \
-       set_val;                                      \
-    }                                                \
-}
+#define SUBSTITUTE(get_val, set_val)                   \
+  do {                                                 \
+    Lisp_Object old_value = get_val;                   \
+    Lisp_Object true_value                             \
+      = substitute_object_recurse (object, placeholder,        \
+                                  old_value);          \
+                                                       \
+    if (!EQ (old_value, true_value))                   \
+      {                                                        \
+       set_val;                                        \
+      }                                                        \
+  } while (0)
 
 static Lisp_Object
 substitute_object_recurse (object, placeholder, subtree)
@@ -3097,23 +3174,33 @@ substitute_object_recurse (object, placeholder, subtree)
     {
     case Lisp_Vectorlike:
       {
-       int i;
-       int length = XINT (Flength(subtree));
+       int i, length = 0;
+       if (BOOL_VECTOR_P (subtree))
+         return subtree;               /* No sub-objects anyway.  */
+       else if (CHAR_TABLE_P (subtree) || SUB_CHAR_TABLE_P (subtree)
+                || COMPILEDP (subtree))
+         length = ASIZE (subtree) & PSEUDOVECTOR_SIZE_MASK;
+       else if (VECTORP (subtree))
+         length = ASIZE (subtree);
+       else
+         /* An unknown pseudovector may contain non-Lisp fields, so we
+            can't just blindly traverse all its fields.  We used to call
+            `Flength' which signaled `sequencep', so I just preserved this
+            behavior.  */
+         wrong_type_argument (Qsequencep, subtree);
+
        for (i = 0; i < length; i++)
-         {
-           Lisp_Object idx = make_number (i);
-           SUBSTITUTE (Faref (subtree, idx),
-                       Faset (subtree, idx, true_value));
-         }
+         SUBSTITUTE (AREF (subtree, i),
+                     ASET (subtree, i, true_value));
        return subtree;
       }
 
     case Lisp_Cons:
       {
-       SUBSTITUTE (Fcar_safe (subtree),
-                   Fsetcar (subtree, true_value));
-       SUBSTITUTE (Fcdr_safe (subtree),
-                   Fsetcdr (subtree, true_value));
+       SUBSTITUTE (XCAR (subtree),
+                   XSETCAR (subtree, true_value));
+       SUBSTITUTE (XCDR (subtree),
+                   XSETCDR (subtree, true_value));
        return subtree;
       }
 
@@ -3146,7 +3233,7 @@ substitute_in_interval (interval, arg)
   Lisp_Object object      = Fcar (arg);
   Lisp_Object placeholder = Fcdr (arg);
 
-  SUBSTITUTE(interval->plist, interval->plist = true_value);
+  SUBSTITUTE (interval->plist, interval->plist = true_value);
 }
 
 \f
@@ -3535,6 +3622,29 @@ intern (str)
   return Fintern (make_string (str, len), obarray);
 }
 
+Lisp_Object
+intern_c_string (const char *str)
+{
+  Lisp_Object tem;
+  int len = strlen (str);
+  Lisp_Object obarray;
+
+  obarray = Vobarray;
+  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+    obarray = check_obarray (obarray);
+  tem = oblookup (obarray, str, len, len);
+  if (SYMBOLP (tem))
+    return tem;
+
+  if (NILP (Vpurify_flag))
+    /* Creating a non-pure string from a string literal not
+       implemented yet.  We could just use make_string here and live
+       with the extra copy.  */
+    abort ();
+
+  return Fintern (make_pure_c_string (str), obarray);
+}
+
 /* Create an uninterned symbol with name STR.  */
 
 Lisp_Object
@@ -3655,6 +3765,13 @@ OBARRAY defaults to the value of the variable `obarray'.  */)
   if (SYMBOLP (name) && !EQ (name, tem))
     return Qnil;
 
+  /* There are plenty of other symbols which will screw up the Emacs
+     session if we unintern them, as well as even more ways to use
+     `setq' or `fset' or whatnot to make the Emacs session
+     unusable.  Let's not go down this silly road.  --Stef  */
+  /* if (EQ (tem, Qnil) || EQ (tem, Qt))
+       error ("Attempt to unintern t or nil"); */
+
   XSYMBOL (tem)->interned = SYMBOL_UNINTERNED;
   XSYMBOL (tem)->constant = 0;
   XSYMBOL (tem)->indirect_variable = 0;
@@ -3713,9 +3830,7 @@ oblookup (obarray, ptr, size, size_byte)
     }
   /* This is sometimes needed in the middle of GC.  */
   obsize &= ~ARRAY_MARK_FLAG;
-  /* Combining next two lines breaks VMS C 2.3.  */
-  hash = hash_string (ptr, size_byte);
-  hash %= obsize;
+  hash = hash_string (ptr, size_byte) % obsize;
   bucket = XVECTOR (obarray)->contents[hash];
   oblookup_last_bucket_number = hash;
   if (EQ (bucket, make_number (0)))
@@ -3809,7 +3924,7 @@ init_obarray ()
 
   XSETFASTINT (oblength, OBARRAY_SIZE);
 
-  Qnil = Fmake_symbol (make_pure_string ("nil", 3, 3, 0));
+  Qnil = Fmake_symbol (make_pure_c_string ("nil"));
   Vobarray = Fmake_vector (oblength, make_number (0));
   initial_obarray = Vobarray;
   staticpro (&initial_obarray);
@@ -3824,12 +3939,12 @@ init_obarray ()
   tem = &XVECTOR (Vobarray)->contents[hash];
   *tem = Qnil;
 
-  Qunbound = Fmake_symbol (make_pure_string ("unbound", 7, 7, 0));
+  Qunbound = Fmake_symbol (make_pure_c_string ("unbound"));
   XSYMBOL (Qnil)->function = Qunbound;
   XSYMBOL (Qunbound)->value = Qunbound;
   XSYMBOL (Qunbound)->function = Qunbound;
 
-  Qt = intern ("t");
+  Qt = intern_c_string ("t");
   XSYMBOL (Qnil)->value = Qnil;
   XSYMBOL (Qnil)->plist = Qnil;
   XSYMBOL (Qt)->value = Qt;
@@ -3838,7 +3953,7 @@ init_obarray ()
   /* Qt is correct even if CANNOT_DUMP.  loadup.el will set to nil at end.  */
   Vpurify_flag = Qt;
 
-  Qvariable_documentation = intern ("variable-documentation");
+  Qvariable_documentation = intern_c_string ("variable-documentation");
   staticpro (&Qvariable_documentation);
 
   read_buffer_size = 100 + MAX_MULTIBYTE_LENGTH;
@@ -3850,7 +3965,7 @@ defsubr (sname)
      struct Lisp_Subr *sname;
 {
   Lisp_Object sym;
-  sym = intern (sname->symbol_name);
+  sym = intern_c_string (sname->symbol_name);
   XSETPVECTYPE (sname, PVEC_SUBR);
   XSETSUBR (XSYMBOL (sym)->function, sname);
 }
@@ -3871,12 +3986,10 @@ defalias (sname, string)
    to a C variable of type int.  Sample call:
    DEFVAR_INT ("emacs-priority", &emacs_priority, "Documentation");  */
 void
-defvar_int (namestring, address)
-     char *namestring;
-     EMACS_INT *address;
+defvar_int (const char *namestring, EMACS_INT *address)
 {
   Lisp_Object sym, val;
-  sym = intern (namestring);
+  sym = intern_c_string (namestring);
   val = allocate_misc ();
   XMISCTYPE (val) = Lisp_Misc_Intfwd;
   XINTFWD (val)->intvar = address;
@@ -3886,12 +3999,10 @@ defvar_int (namestring, address)
 /* Similar but define a variable whose value is t if address contains 1,
    nil if address contains 0.  */
 void
-defvar_bool (namestring, address)
-     char *namestring;
-     int *address;
+defvar_bool (const char *namestring, int *address)
 {
   Lisp_Object sym, val;
-  sym = intern (namestring);
+  sym = intern_c_string (namestring);
   val = allocate_misc ();
   XMISCTYPE (val) = Lisp_Misc_Boolfwd;
   XBOOLFWD (val)->boolvar = address;
@@ -3905,12 +4016,10 @@ defvar_bool (namestring, address)
    gc-marked for some other reason, since marking the same slot twice
    can cause trouble with strings.  */
 void
-defvar_lisp_nopro (namestring, address)
-     char *namestring;
-     Lisp_Object *address;
+defvar_lisp_nopro (const char *namestring, Lisp_Object *address)
 {
   Lisp_Object sym, val;
-  sym = intern (namestring);
+  sym = intern_c_string (namestring);
   val = allocate_misc ();
   XMISCTYPE (val) = Lisp_Misc_Objfwd;
   XOBJFWD (val)->objvar = address;
@@ -3918,9 +4027,7 @@ defvar_lisp_nopro (namestring, address)
 }
 
 void
-defvar_lisp (namestring, address)
-     char *namestring;
-     Lisp_Object *address;
+defvar_lisp (const char *namestring, Lisp_Object *address)
 {
   defvar_lisp_nopro (namestring, address);
   staticpro (address);
@@ -3930,12 +4037,10 @@ defvar_lisp (namestring, address)
    at a particular offset in the current kboard object.  */
 
 void
-defvar_kboard (namestring, offset)
-     char *namestring;
-     int offset;
+defvar_kboard (const char *namestring, int offset)
 {
   Lisp_Object sym, val;
-  sym = intern (namestring);
+  sym = intern_c_string (namestring);
   val = allocate_misc ();
   XMISCTYPE (val) = Lisp_Misc_Kboard_Objfwd;
   XKBOARD_OBJFWD (val)->offset = offset;
@@ -4089,15 +4194,11 @@ init_lread ()
     }
 #endif
 
-#if (!(defined(WINDOWSNT) || (defined(HAVE_CARBON))))
+#if (!(defined (WINDOWSNT) || (defined (HAVE_NS))))
   /* When Emacs is invoked over network shares on NT, PATH_LOADSEARCH is
      almost never correct, thereby causing a warning to be printed out that
      confuses users.  Since PATH_LOADSEARCH is always overridden by the
-     EMACSLOADPATH environment variable below, disable the warning on NT.
-     Also, when using the "self-contained" option for Carbon Emacs for MacOSX,
-     the "standard" paths may not exist and would be overridden by
-     EMACSLOADPATH as on NT.  Since this depends on how the executable
-     was build and packaged, turn off the warnings in general */
+     EMACSLOADPATH environment variable below, disable the warning on NT.  */
 
   /* Warn if dirs in the *standard* path don't exist.  */
   if (!turn_off_warning)
@@ -4119,7 +4220,7 @@ init_lread ()
            }
        }
     }
-#endif /* !(WINDOWSNT || HAVE_CARBON) */
+#endif /* !(WINDOWSNT || HAVE_NS) */
 
   /* If the EMACSLOADPATH environment variable is set, use its value.
      This doesn't apply if we're dumping.  */
@@ -4221,6 +4322,10 @@ read multiple times.  The list is in the same order as the symbols
 were read in. */);
   Vread_symbol_positions_list = Qnil;
 
+  DEFVAR_LISP ("read-circle", &Vread_circle,
+              doc: /* Non-nil means read recursive structures using #N= and #N# syntax.  */);
+  Vread_circle = Qt;
+
   DEFVAR_LISP ("load-path", &Vload_path,
               doc: /* *List of directories to search for files to load.
 Each element is a string (directory name) or nil (try default directory).
@@ -4232,8 +4337,8 @@ otherwise to default specified by file `epaths.h' when Emacs was built.  */);
 This list should not include the empty string.
 `load' and related functions try to append these suffixes, in order,
 to the specified file name if a Lisp suffix is allowed or required.  */);
-  Vload_suffixes = Fcons (build_string (".elc"),
-                         Fcons (build_string (".el"), Qnil));
+  Vload_suffixes = Fcons (make_pure_c_string (".elc"),
+                         Fcons (make_pure_c_string (".el"), Qnil));
   DEFVAR_LISP ("load-file-rep-suffixes", &Vload_file_rep_suffixes,
               doc: /* List of suffixes that indicate representations of \
 the same file.
@@ -4251,6 +4356,8 @@ customize `jka-compr-load-suffixes' rather than the present variable.  */);
 
   DEFVAR_BOOL ("load-in-progress", &load_in_progress,
               doc: /* Non-nil if inside of `load'.  */);
+  Qload_in_progress = intern_c_string ("load-in-progress");
+  staticpro (&Qload_in_progress);
 
   DEFVAR_LISP ("after-load-alist", &Vafter_load_alist,
               doc: /* An alist of expressions to be evalled when particular files are loaded.
@@ -4351,6 +4458,11 @@ incompatible byte codes can make Emacs crash when it tries to execute
 them.  */);
   load_dangerous_libraries = 0;
 
+  DEFVAR_BOOL ("force-load-messages", &force_load_messages,
+              doc: /* Non-nil means force printing messages when loading Lisp files.
+This overrides the value of the NOMESSAGE argument to `load'.  */);
+  force_load_messages = 0;
+
   DEFVAR_LISP ("bytecomp-version-regexp", &Vbytecomp_version_regexp,
               doc: /* Regular expression matching safe to load compiled Lisp files.
 When Emacs loads a compiled Lisp file, it reads the first 512 bytes
@@ -4358,7 +4470,7 @@ from the file, and matches them against this regular expression.
 When the regular expression matches, the file is considered to be safe
 to load.  See also `load-dangerous-libraries'.  */);
   Vbytecomp_version_regexp
-    = build_string ("^;;;.\\(in Emacs version\\|bytecomp version FSF\\)");
+    = make_pure_c_string ("^;;;.\\(in Emacs version\\|bytecomp version FSF\\)");
 
   DEFVAR_LISP ("eval-buffer-list", &Veval_buffer_list,
               doc: /* List of buffers being read from by calls to `eval-buffer' and `eval-region'.  */);
@@ -4367,7 +4479,7 @@ to load.  See also `load-dangerous-libraries'.  */);
   DEFVAR_LISP ("old-style-backquotes", &Vold_style_backquotes,
               doc: /* Set to non-nil when `read' encounters an old-style backquote.  */);
   Vold_style_backquotes = Qnil;
-  Qold_style_backquotes = intern ("old-style-backquotes");
+  Qold_style_backquotes = intern_c_string ("old-style-backquotes");
   staticpro (&Qold_style_backquotes);
 
   /* Vsource_directory was initialized in init_lread.  */
@@ -4375,55 +4487,55 @@ to load.  See also `load-dangerous-libraries'.  */);
   load_descriptor_list = Qnil;
   staticpro (&load_descriptor_list);
 
-  Qcurrent_load_list = intern ("current-load-list");
+  Qcurrent_load_list = intern_c_string ("current-load-list");
   staticpro (&Qcurrent_load_list);
 
-  Qstandard_input = intern ("standard-input");
+  Qstandard_input = intern_c_string ("standard-input");
   staticpro (&Qstandard_input);
 
-  Qread_char = intern ("read-char");
+  Qread_char = intern_c_string ("read-char");
   staticpro (&Qread_char);
 
-  Qget_file_char = intern ("get-file-char");
+  Qget_file_char = intern_c_string ("get-file-char");
   staticpro (&Qget_file_char);
 
-  Qget_emacs_mule_file_char = intern ("get-emacs-mule-file-char");
+  Qget_emacs_mule_file_char = intern_c_string ("get-emacs-mule-file-char");
   staticpro (&Qget_emacs_mule_file_char);
 
-  Qload_force_doc_strings = intern ("load-force-doc-strings");
+  Qload_force_doc_strings = intern_c_string ("load-force-doc-strings");
   staticpro (&Qload_force_doc_strings);
 
-  Qbackquote = intern ("`");
+  Qbackquote = intern_c_string ("`");
   staticpro (&Qbackquote);
-  Qcomma = intern (",");
+  Qcomma = intern_c_string (",");
   staticpro (&Qcomma);
-  Qcomma_at = intern (",@");
+  Qcomma_at = intern_c_string (",@");
   staticpro (&Qcomma_at);
-  Qcomma_dot = intern (",.");
+  Qcomma_dot = intern_c_string (",.");
   staticpro (&Qcomma_dot);
 
-  Qinhibit_file_name_operation = intern ("inhibit-file-name-operation");
+  Qinhibit_file_name_operation = intern_c_string ("inhibit-file-name-operation");
   staticpro (&Qinhibit_file_name_operation);
 
-  Qascii_character = intern ("ascii-character");
+  Qascii_character = intern_c_string ("ascii-character");
   staticpro (&Qascii_character);
 
-  Qfunction = intern ("function");
+  Qfunction = intern_c_string ("function");
   staticpro (&Qfunction);
 
-  Qload = intern ("load");
+  Qload = intern_c_string ("load");
   staticpro (&Qload);
 
-  Qload_file_name = intern ("load-file-name");
+  Qload_file_name = intern_c_string ("load-file-name");
   staticpro (&Qload_file_name);
 
-  Qeval_buffer_list = intern ("eval-buffer-list");
+  Qeval_buffer_list = intern_c_string ("eval-buffer-list");
   staticpro (&Qeval_buffer_list);
 
-  Qfile_truename = intern ("file-truename");
+  Qfile_truename = intern_c_string ("file-truename");
   staticpro (&Qfile_truename) ;
 
-  Qdo_after_load_evaluation = intern ("do-after-load-evaluation");
+  Qdo_after_load_evaluation = intern_c_string ("do-after-load-evaluation");
   staticpro (&Qdo_after_load_evaluation) ;
 
   staticpro (&dump_path);
@@ -4435,6 +4547,21 @@ to load.  See also `load-dangerous-libraries'.  */);
 
   Vloads_in_progress = Qnil;
   staticpro (&Vloads_in_progress);
+
+  Qhash_table = intern_c_string ("hash-table");
+  staticpro (&Qhash_table);
+  Qdata = intern_c_string ("data");
+  staticpro (&Qdata);
+  Qtest = intern_c_string ("test");
+  staticpro (&Qtest);
+  Qsize = intern_c_string ("size");
+  staticpro (&Qsize);
+  Qweakness = intern_c_string ("weakness");
+  staticpro (&Qweakness);
+  Qrehash_size = intern_c_string ("rehash-size");
+  staticpro (&Qrehash_size);
+  Qrehash_threshold = intern_c_string ("rehash-threshold");
+  staticpro (&Qrehash_threshold);
 }
 
 /* arch-tag: a0d02733-0f96-4844-a659-9fd53c4f414d