Fix last change
[bpt/emacs.git] / src / lread.c
index 2418353..8b46f38 100644 (file)
@@ -24,6 +24,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/stat.h>
 #include <sys/file.h>
 #include <errno.h>
+#include <limits.h>    /* for CHAR_BIT */
 #include <setjmp.h>
 #include "lisp.h"
 #include "intervals.h"
@@ -61,20 +62,21 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #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;
-
-Lisp_Object Qread_char, Qget_file_char, Qstandard_input, Qcurrent_load_list;
+static Lisp_Object Qhash_table, Qdata;
+static Lisp_Object Qtest, Qsize;
+static Lisp_Object Qweakness;
+static Lisp_Object Qrehash_size;
+static Lisp_Object Qrehash_threshold;
+
+static Lisp_Object Qread_char, Qget_file_char, Qcurrent_load_list;
+Lisp_Object Qstandard_input;
 Lisp_Object Qvariable_documentation;
-Lisp_Object Qascii_character, Qload, Qload_file_name;
+static Lisp_Object Qascii_character, Qload, Qload_file_name;
 Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
-Lisp_Object Qinhibit_file_name_operation;
-Lisp_Object Qeval_buffer_list;
-Lisp_Object Qlexical_binding;
-Lisp_Object Qfile_truename, Qdo_after_load_evaluation; /* ACM 2006/5/16 */
+static Lisp_Object Qinhibit_file_name_operation;
+static Lisp_Object Qeval_buffer_list;
+static Lisp_Object Qlexical_binding;
+static Lisp_Object Qfile_truename, Qdo_after_load_evaluation; /* ACM 2006/5/16 */
 
 /* Used instead of Qget_file_char while loading *.elc files compiled
    by Emacs 21 or older.  */
@@ -90,7 +92,7 @@ static Lisp_Object Qload_in_progress;
    Each member of the list has the form (n . object), and is used to
    look up the object for the corresponding #n# construct.
    It must be set to nil before all top-level calls to read0.  */
-Lisp_Object read_objects;
+static Lisp_Object read_objects;
 
 /* Nonzero means READCHAR should read bytes one by one (not character)
    when READCHARFUN is Qget_file_char or Qget_emacs_mule_file_char.
@@ -118,9 +120,9 @@ static EMACS_INT readchar_count;
 /* This contains the last string skipped with #@.  */
 static char *saved_doc_string;
 /* Length of buffer allocated in saved_doc_string.  */
-static int saved_doc_string_size;
+static ptrdiff_t saved_doc_string_size;
 /* Length of actual data in saved_doc_string.  */
-static int saved_doc_string_length;
+static ptrdiff_t saved_doc_string_length;
 /* This is the file position that string came from.  */
 static file_offset saved_doc_string_position;
 
@@ -129,9 +131,9 @@ static file_offset saved_doc_string_position;
    is put in saved_doc_string.  */
 static char *prev_saved_doc_string;
 /* Length of buffer allocated in prev_saved_doc_string.  */
-static int prev_saved_doc_string_size;
+static ptrdiff_t prev_saved_doc_string_size;
 /* Length of actual data in prev_saved_doc_string.  */
-static int prev_saved_doc_string_length;
+static ptrdiff_t prev_saved_doc_string_length;
 /* This is the file position that string came from.  */
 static file_offset prev_saved_doc_string_position;
 
@@ -156,7 +158,7 @@ static void readevalloop (Lisp_Object, FILE*, Lisp_Object, int,
 static Lisp_Object load_unwind (Lisp_Object);
 static Lisp_Object load_descriptor_unwind (Lisp_Object);
 
-static void invalid_syntax (const char *, int) NO_RETURN;
+static void invalid_syntax (const char *) NO_RETURN;
 static void end_of_file_error (void) NO_RETURN;
 
 \f
@@ -796,16 +798,16 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun)
       } beg_end_state = NOMINAL;
       int in_file_vars = 0;
 
-#define UPDATE_BEG_END_STATE(ch)                                             \
-  if (beg_end_state == NOMINAL)                                                      \
-    beg_end_state = (ch == '-' ? AFTER_FIRST_DASH : NOMINAL);                \
-  else if (beg_end_state == AFTER_FIRST_DASH)                                \
-    beg_end_state = (ch == '*' ? AFTER_ASTERIX : NOMINAL);                   \
-  else if (beg_end_state == AFTER_ASTERIX)                                   \
-    {                                                                        \
-      if (ch == '-')                                                         \
-       in_file_vars = !in_file_vars;                                         \
-      beg_end_state = NOMINAL;                                               \
+#define UPDATE_BEG_END_STATE(ch)                               \
+  if (beg_end_state == NOMINAL)                                        \
+    beg_end_state = (ch == '-' ? AFTER_FIRST_DASH : NOMINAL);  \
+  else if (beg_end_state == AFTER_FIRST_DASH)                  \
+    beg_end_state = (ch == '*' ? AFTER_ASTERIX : NOMINAL);     \
+  else if (beg_end_state == AFTER_ASTERIX)                     \
+    {                                                          \
+      if (ch == '-')                                           \
+       in_file_vars = !in_file_vars;                           \
+      beg_end_state = NOMINAL;                                 \
     }
 
       /* Skip until we get to the file vars, if any.  */
@@ -818,7 +820,8 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun)
 
       while (in_file_vars)
        {
-         char var[100], *var_end, val[100], *val_end;
+         char var[100], val[100];
+         unsigned i;
 
          ch = READCHAR;
 
@@ -826,19 +829,22 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun)
          while (ch == ' ' || ch == '\t')
            ch = READCHAR;
 
-         var_end = var;
-         while (ch != ':' && ch != '\n' && ch != EOF)
+         i = 0;
+         while (ch != ':' && ch != '\n' && ch != EOF && in_file_vars)
            {
-             if (var_end < var + sizeof var - 1)
-               *var_end++ = ch;
+             if (i < sizeof var - 1)
+               var[i++] = ch;
              UPDATE_BEG_END_STATE (ch);
              ch = READCHAR;
            }
-         
-         while (var_end > var
-                && (var_end[-1] == ' ' || var_end[-1] == '\t'))
-           var_end--;
-         *var_end = '\0';
+
+         /* Stop scanning if no colon was found before end marker.  */
+         if (!in_file_vars)
+           break;
+
+         while (i > 0 && (var[i - 1] == ' ' || var[i - 1] == '\t'))
+           i--;
+         var[i] = '\0';
 
          if (ch == ':')
            {
@@ -848,22 +854,21 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun)
              while (ch == ' ' || ch == '\t')
                ch = READCHAR;
 
-             val_end = val;
+             i = 0;
              while (ch != ';' && ch != '\n' && ch != EOF && in_file_vars)
                {
-                 if (val_end < val + sizeof val - 1)
-                   *val_end++ = ch;
+                 if (i < sizeof val - 1)
+                   val[i++] = ch;
                  UPDATE_BEG_END_STATE (ch);
                  ch = READCHAR;
                }
              if (! in_file_vars)
                /* The value was terminated by an end-marker, which
                   remove.  */
-               val_end -= 3;
-             while (val_end > val
-                    && (val_end[-1] == ' ' || val_end[-1] == '\t'))
-               val_end--;
-             *val_end = '\0';
+               i -= 3;
+             while (i > 0 && (val[i - 1] == ' ' || val[i - 1] == '\t'))
+               i--;
+             val[i] = '\0';
 
              if (strcmp (var, "lexical-binding") == 0)
                /* This is it...  */
@@ -880,7 +885,6 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun)
       return rv;
     }
 }
-
 \f
 /* Value is a version number of byte compiled code if the file
    associated with file descriptor FD is a compiled Lisp file that's
@@ -909,7 +913,7 @@ safe_to_load_p (int fd)
        if (i == 4)
          version = buf[i];
 
-      if (i == nbytes
+      if (i >= nbytes
          || fast_c_string_match_ignore_case (Vbytecomp_version_regexp,
                                              buf + i) < 0)
        safe_p = 0;
@@ -1065,9 +1069,9 @@ Return t if the file exists and loads successfully.  */)
 
   /* Avoid weird lossage with null string as arg,
      since it would try to load a directory as a Lisp file */
-  if (SCHARS (file) > 0)
+  if (SBYTES (file) > 0)
     {
-      int size = SBYTES (file);
+      ptrdiff_t size = SBYTES (file);
 
       found = Qnil;
       GCPRO2 (file, found);
@@ -1199,12 +1203,15 @@ Return t if the file exists and loads successfully.  */)
 #ifdef DOS_NT
          fmode = "rb";
 #endif /* DOS_NT */
-         stat (SSDATA (efound), &s1);
-         SSET (efound, SBYTES (efound) - 1, 0);
-         result = stat (SSDATA (efound), &s2);
-         SSET (efound, SBYTES (efound) - 1, 'c');
+         result = stat (SSDATA (efound), &s1);
+         if (result == 0)
+           {
+             SSET (efound, SBYTES (efound) - 1, 0);
+             result = stat (SSDATA (efound), &s2);
+             SSET (efound, SBYTES (efound) - 1, 'c');
+           }
 
-         if (result >= 0 && (unsigned) s1.st_mtime < (unsigned) s2.st_mtime)
+         if (result == 0 && s1.st_mtime < s2.st_mtime)
            {
              /* Make the progress messages mention that source is newer.  */
              newer = 1;
@@ -1275,7 +1282,6 @@ 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);
-
   specbind (Qload_in_progress, Qt);
 
   instream = stream;
@@ -1413,16 +1419,16 @@ int
 openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate)
 {
   register int fd;
-  int fn_size = 100;
+  EMACS_INT fn_size = 100;
   char buf[100];
   register char *fn = buf;
   int absolute = 0;
-  int want_size;
+  EMACS_INT want_length;
   Lisp_Object filename;
   struct stat st;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
   Lisp_Object string, tail, encoded_fn;
-  int max_suffix_len = 0;
+  EMACS_INT max_suffix_len = 0;
 
   CHECK_STRING (str);
 
@@ -1456,17 +1462,17 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
            continue;
        }
 
-      /* Calculate maximum size of any filename made from
+      /* Calculate maximum length of any filename made from
         this path element/specified file name and any possible suffix.  */
-      want_size = max_suffix_len + SBYTES (filename) + 1;
-      if (fn_size < want_size)
-       fn = (char *) alloca (fn_size = 100 + want_size);
+      want_length = max_suffix_len + SBYTES (filename);
+      if (fn_size <= want_length)
+       fn = (char *) alloca (fn_size = 100 + want_length);
 
       /* Loop over suffixes.  */
       for (tail = NILP (suffixes) ? Fcons (empty_unibyte_string, Qnil) : suffixes;
           CONSP (tail); tail = XCDR (tail))
        {
-         int lsuffix = SBYTES (XCAR (tail));
+         ptrdiff_t lsuffix = SBYTES (XCAR (tail));
          Lisp_Object handler;
          int exists;
 
@@ -1863,11 +1869,9 @@ This function preserves the position of point.  */)
 
   specbind (Qeval_buffer_list, Fcons (buf, Veval_buffer_list));
   specbind (Qstandard_output, tem);
-  specbind (Qlexical_binding, Qnil);
   record_unwind_protect (save_excursion_restore, save_excursion_save ());
   BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf)));
-  if (lisp_file_lexically_bound_p (buf))
-    Fset (Qlexical_binding, Qt);
+  specbind (Qlexical_binding, lisp_file_lexically_bound_p (buf) ? Qt : Qnil);
   readevalloop (buf, 0, filename,
                !NILP (printflag), unibyte, Qnil, Qnil, Qnil);
   unbind_to (count, Qnil);
@@ -2010,11 +2014,9 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
    S is error string of length N (if > 0)  */
 
 static void
-invalid_syntax (const char *s, int n)
+invalid_syntax (const char *s)
 {
-  if (!n)
-    n = strlen (s);
-  xsignal1 (Qinvalid_read_syntax, make_string (s, n));
+  xsignal1 (Qinvalid_read_syntax, build_string (s));
 }
 
 
@@ -2035,7 +2037,7 @@ read0 (Lisp_Object readcharfun)
            Fmake_string (make_number (1), make_number (c)));
 }
 \f
-static int read_buffer_size;
+static ptrdiff_t read_buffer_size;
 static char *read_buffer;
 
 /* Read a \-escape sequence, assuming we already read the `\'.
@@ -2206,7 +2208,9 @@ read_escape (Lisp_Object readcharfun, int stringp)
                UNREAD (c);
                break;
              }
-           count++;
+           if (MAX_CHAR < i)
+             error ("Hex character out of range: \\x%x...", i);
+           count += count < 3;
          }
 
        if (count < 3 && i >= 0x80)
@@ -2234,10 +2238,7 @@ read_escape (Lisp_Object readcharfun, int stringp)
            else if (c >= 'a' && c <= 'f')  i = (i << 4) + (c - 'a') + 10;
             else if (c >= 'A' && c <= 'F')  i = (i << 4) + (c - 'A') + 10;
            else
-             {
-               error ("Non-hex digit used for Unicode escape");
-               break;
-             }
+             error ("Non-hex digit used for Unicode escape");
          }
        if (i > 0x10FFFF)
          error ("Non-Unicode character: 0x%x", i);
@@ -2249,6 +2250,26 @@ read_escape (Lisp_Object readcharfun, int stringp)
     }
 }
 
+/* Return the digit that CHARACTER stands for in the given BASE.
+   Return -1 if CHARACTER is out of range for BASE,
+   and -2 if CHARACTER is not valid for any supported BASE.  */
+static inline int
+digit_to_number (int character, int base)
+{
+  int digit;
+
+  if ('0' <= character && character <= '9')
+    digit = character - '0';
+  else if ('a' <= character && character <= 'z')
+    digit = character - 'a' + 10;
+  else if ('A' <= character && character <= 'Z')
+    digit = character - 'A' + 10;
+  else
+    return -2;
+
+  return digit < base ? digit : -1;
+}
+
 /* Read an integer in radix RADIX using READCHARFUN to read
    characters.  RADIX must be in the interval [2..36]; if it isn't, a
    read error is signaled .  Value is the integer read.  Signals an
@@ -2256,61 +2277,67 @@ read_escape (Lisp_Object readcharfun, int stringp)
    range.  */
 
 static Lisp_Object
-read_integer (Lisp_Object readcharfun, int radix)
+read_integer (Lisp_Object readcharfun, EMACS_INT radix)
 {
-  int ndigits = 0, invalid_p, c, sign = 0;
-  /* We use a floating point number because  */
-  double number = 0;
+  /* Room for sign, leading 0, other digits, trailing null byte.
+     Also, room for invalid syntax diagnostic.  */
+  char buf[max (1 + 1 + sizeof (uintmax_t) * CHAR_BIT + 1,
+               sizeof "integer, radix " + INT_STRLEN_BOUND (EMACS_INT))];
+
+  int valid = -1; /* 1 if valid, 0 if not, -1 if incomplete.  */
 
   if (radix < 2 || radix > 36)
-    invalid_p = 1;
+    valid = 0;
   else
     {
-      number = ndigits = invalid_p = 0;
-      sign = 1;
+      char *p = buf;
+      int c, digit;
 
       c = READCHAR;
-      if (c == '-')
+      if (c == '-' || c == '+')
        {
+         *p++ = c;
          c = READCHAR;
-         sign = -1;
        }
-      else if (c == '+')
-       c = READCHAR;
 
-      while (c >= 0)
+      if (c == '0')
        {
-         int digit;
-
-         if (c >= '0' && c <= '9')
-           digit = c - '0';
-         else if (c >= 'a' && c <= 'z')
-           digit = c - 'a' + 10;
-         else if (c >= 'A' && c <= 'Z')
-           digit = c - 'A' + 10;
-         else
-           {
-             UNREAD (c);
-             break;
-           }
+         *p++ = c;
+         valid = 1;
+
+         /* Ignore redundant leading zeros, so the buffer doesn't
+            fill up with them.  */
+         do
+           c = READCHAR;
+         while (c == '0');
+       }
 
-         if (digit < 0 || digit >= radix)
-           invalid_p = 1;
+      while (-1 <= (digit = digit_to_number (c, radix)))
+       {
+         if (digit == -1)
+           valid = 0;
+         if (valid < 0)
+           valid = 1;
+
+         if (p < buf + sizeof buf - 1)
+           *p++ = c;
+         else
+           valid = 0;
 
-         number = radix * number + digit;
-         ++ndigits;
          c = READCHAR;
        }
+
+      UNREAD (c);
+      *p = '\0';
     }
 
-  if (ndigits == 0 || invalid_p)
+  if (! valid)
     {
-      char buf[50];
-      sprintf (buf, "integer, radix %d", radix);
-      invalid_syntax (buf, 0);
+      sprintf (buf, "integer, radix %"pI"d", radix);
+      invalid_syntax (buf);
     }
 
-  return make_fixnum_or_float (sign * number);
+  return string_to_number (buf, radix, 0);
 }
 
 
@@ -2324,7 +2351,7 @@ static Lisp_Object
 read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
 {
   register int c;
-  int uninterned_symbol = 0;
+  unsigned uninterned_symbol = 0;
   int multibyte;
 
   *pch = 0;
@@ -2424,7 +2451,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
              return ht;
            }
          UNREAD (c);
-         invalid_syntax ("#", 1);
+         invalid_syntax ("#");
        }
       if (c == '^')
        {
@@ -2433,7 +2460,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
            {
              Lisp_Object tmp;
              tmp = read_vector (readcharfun, 0);
-             if (XVECTOR (tmp)->size < CHAR_TABLE_STANDARD_SLOTS)
+             if (ASIZE (tmp) < CHAR_TABLE_STANDARD_SLOTS)
                error ("Invalid size char-table");
              XSETPVECTYPE (XVECTOR (tmp), PVEC_CHAR_TABLE);
              return tmp;
@@ -2444,7 +2471,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
              if (c == '[')
                {
                  Lisp_Object tmp;
-                 int depth, size;
+                 EMACS_INT depth, size;
 
                  tmp = read_vector (readcharfun, 0);
                  if (!INTEGERP (AREF (tmp, 0)))
@@ -2452,15 +2479,15 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
                  depth = XINT (AREF (tmp, 0));
                  if (depth < 1 || depth > 3)
                    error ("Invalid depth in char-table");
-                 size = XVECTOR (tmp)->size - 2;
+                 size = ASIZE (tmp) - 2;
                  if (chartab_size [depth] != size)
                    error ("Invalid size char-table");
                  XSETPVECTYPE (XVECTOR (tmp), PVEC_SUB_CHAR_TABLE);
                  return tmp;
                }
-             invalid_syntax ("#^^", 3);
+             invalid_syntax ("#^^");
            }
-         invalid_syntax ("#^", 2);
+         invalid_syntax ("#^");
        }
       if (c == '&')
        {
@@ -2470,7 +2497,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
          if (c == '"')
            {
              Lisp_Object tmp, val;
-             int size_in_chars
+             EMACS_INT size_in_chars
                = ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1)
                   / BOOL_VECTOR_BITS_PER_CHAR);
 
@@ -2484,7 +2511,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
                         version.  */
                      && ! (XFASTINT (length)
                            == (SCHARS (tmp) - 1) * BOOL_VECTOR_BITS_PER_CHAR)))
-               invalid_syntax ("#&...", 5);
+               invalid_syntax ("#&...");
 
              val = Fmake_bool_vector (length, Qnil);
              memcpy (XBOOL_VECTOR (val)->data, SDATA (tmp), size_in_chars);
@@ -2494,7 +2521,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
                  &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
              return val;
            }
-         invalid_syntax ("#&...", 5);
+         invalid_syntax ("#&...");
        }
       if (c == '[')
        {
@@ -2502,7 +2529,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
             build them using function calls.  */
          Lisp_Object tmp;
          tmp = read_vector (readcharfun, 1);
-         return Fmake_byte_code (XVECTOR (tmp)->size,
+         return Fmake_byte_code (ASIZE (tmp),
                                  XVECTOR (tmp)->contents);
        }
       if (c == '(')
@@ -2514,7 +2541,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
          /* Read the string itself.  */
          tmp = read1 (readcharfun, &ch, 0);
          if (ch != 0 || !STRINGP (tmp))
-           invalid_syntax ("#", 1);
+           invalid_syntax ("#");
          GCPRO1 (tmp);
          /* Read the intervals and their properties.  */
          while (1)
@@ -2530,7 +2557,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
              if (ch == 0)
                plist = read1 (readcharfun, &ch, 0);
              if (ch)
-               invalid_syntax ("Invalid string property list", 0);
+               invalid_syntax ("Invalid string property list");
              Fset_text_properties (beg, end, plist, tmp);
            }
          UNGCPRO;
@@ -2542,18 +2569,20 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
         and function definitions.  */
       if (c == '@')
        {
-         int i, nskip = 0;
+         enum { extra = 100 };
+         ptrdiff_t i, nskip = 0;
 
          load_each_byte = 1;
          /* Read a decimal integer.  */
          while ((c = READCHAR) >= 0
                 && c >= '0' && c <= '9')
            {
+             if ((STRING_BYTES_BOUND - extra) / 10 <= nskip)
+               string_overflow ();
              nskip *= 10;
              nskip += c - '0';
            }
-         if (c >= 0)
-           UNREAD (c);
+         UNREAD (c);
 
          if (load_force_doc_strings
              && (EQ (readcharfun, Qget_file_char)
@@ -2567,9 +2596,9 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
                 with prev_saved_doc_string, so we save two strings.  */
              {
                char *temp = saved_doc_string;
-               int temp_size = saved_doc_string_size;
+               ptrdiff_t temp_size = saved_doc_string_size;
                file_offset temp_pos = saved_doc_string_position;
-               int temp_len = saved_doc_string_length;
+               ptrdiff_t temp_len = saved_doc_string_length;
 
                saved_doc_string = prev_saved_doc_string;
                saved_doc_string_size = prev_saved_doc_string_size;
@@ -2584,12 +2613,12 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
 
              if (saved_doc_string_size == 0)
                {
-                 saved_doc_string_size = nskip + 100;
+                 saved_doc_string_size = nskip + extra;
                  saved_doc_string = (char *) xmalloc (saved_doc_string_size);
                }
              if (nskip > saved_doc_string_size)
                {
-                 saved_doc_string_size = nskip + 100;
+                 saved_doc_string_size = nskip + extra;
                  saved_doc_string = (char *) xrealloc (saved_doc_string,
                                                        saved_doc_string_size);
                }
@@ -2629,54 +2658,75 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
        {
          uninterned_symbol = 1;
          c = READCHAR;
-         goto default_label;
+         if (!(c > 040
+               && c != 0x8a0
+               && (c >= 0200
+                   || strchr ("\"';()[]#`,", c) == NULL)))
+           {
+             /* No symbol character follows, this is the empty
+                symbol.  */
+             UNREAD (c);
+             return Fmake_symbol (build_string (""));
+           }
+         goto read_symbol;
        }
       /* Reader forms that can reuse previously read objects.  */
       if (c >= '0' && c <= '9')
        {
-         int n = 0;
+         EMACS_INT n = 0;
          Lisp_Object tem;
 
          /* Read a non-negative integer.  */
          while (c >= '0' && c <= '9')
            {
-             n *= 10;
-             n += c - '0';
+             if (MOST_POSITIVE_FIXNUM / 10 < n
+                 || MOST_POSITIVE_FIXNUM < n * 10 + c - '0')
+               n = MOST_POSITIVE_FIXNUM + 1;
+             else
+               n = n * 10 + c - '0';
              c = READCHAR;
            }
-         /* #n=object returns object, but associates it with n for #n#.  */
-         if (c == '=' && !NILP (Vread_circle))
+
+         if (n <= MOST_POSITIVE_FIXNUM)
            {
-             /* Make a placeholder for #n# to use temporarily */
-             Lisp_Object placeholder;
-             Lisp_Object cell;
+             if (c == 'r' || c == 'R')
+               return read_integer (readcharfun, n);
 
-             placeholder = Fcons (Qnil, Qnil);
-             cell = Fcons (make_number (n), placeholder);
-             read_objects = Fcons (cell, read_objects);
+             if (! NILP (Vread_circle))
+               {
+                 /* #n=object returns object, but associates it with
+                      n for #n#.  */
+                 if (c == '=')
+                   {
+                     /* Make a placeholder for #n# to use temporarily */
+                     Lisp_Object placeholder;
+                     Lisp_Object cell;
 
-             /* Read the object itself. */
-             tem = read0 (readcharfun);
+                     placeholder = Fcons (Qnil, Qnil);
+                     cell = Fcons (make_number (n), placeholder);
+                     read_objects = Fcons (cell, read_objects);
 
-             /* Now put it everywhere the placeholder was... */
-             substitute_object_in_subtree (tem, placeholder);
+                     /* Read the object itself. */
+                     tem = read0 (readcharfun);
 
-             /* ...and #n# will use the real value from now on.  */
-             Fsetcdr (cell, tem);
+                     /* Now put it everywhere the placeholder was... */
+                     substitute_object_in_subtree (tem, placeholder);
 
-             return tem;
-           }
-         /* #n# returns a previously read object.  */
-         if (c == '#' && !NILP (Vread_circle))
-           {
-             tem = Fassq (make_number (n), read_objects);
-             if (CONSP (tem))
-               return XCDR (tem);
-             /* Fall through to error message.  */
-           }
-         else if (c == 'r' ||  c == 'R')
-           return read_integer (readcharfun, n);
+                     /* ...and #n# will use the real value from now on.  */
+                     Fsetcdr (cell, tem);
+
+                     return tem;
+                   }
 
+                 /* #n# returns a previously read object.  */
+                 if (c == '#')
+                   {
+                     tem = Fassq (make_number (n), read_objects);
+                     if (CONSP (tem))
+                       return XCDR (tem);
+                   }
+               }
+           }
          /* Fall through to error message.  */
        }
       else if (c == 'x' || c == 'X')
@@ -2687,7 +2737,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
        return read_integer (readcharfun, 2);
 
       UNREAD (c);
-      invalid_syntax ("#", 1);
+      invalid_syntax ("#");
 
     case ';':
       while ((c = READCHAR) >= 0 && c != '\n');
@@ -2799,12 +2849,12 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
        next_char = READCHAR;
        ok = (next_char <= 040
              || (next_char < 0200
-                 && (strchr ("\"';()[]#?`,.", next_char))));
+                 && strchr ("\"';()[]#?`,.", next_char) != NULL));
        UNREAD (next_char);
        if (ok)
          return make_number (c);
 
-       invalid_syntax ("?", 1);
+       invalid_syntax ("?");
       }
 
     case '"':
@@ -2819,14 +2869,16 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
           a single-byte character.  */
        int force_singlebyte = 0;
        int cancel = 0;
-       int nchars = 0;
+       ptrdiff_t nchars = 0;
 
        while ((ch = READCHAR) >= 0
               && ch != '\"')
          {
            if (end - p < MAX_MULTIBYTE_LENGTH)
              {
-               int offset = p - read_buffer;
+               ptrdiff_t offset = p - read_buffer;
+               if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
+                 memory_full (SIZE_MAX);
                read_buffer = (char *) xrealloc (read_buffer,
                                                 read_buffer_size *= 2);
                p = read_buffer + offset;
@@ -2922,11 +2974,6 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
            /* Otherwise, READ_BUFFER contains only ASCII.  */
          }
 
-       /* We want readchar_count to be the number of characters, not
-          bytes.  Hence we adjust for multibyte characters in the
-          string.  ... But it doesn't seem to be necessary, because
-          READCHAR *does* read multibyte characters from buffers. */
-       /* readchar_count -= (p - read_buffer) - nchars; */
        if (read_pure)
          return make_pure_string (read_buffer, nchars, p - read_buffer,
                                   (force_multibyte
@@ -2943,7 +2990,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
 
        if (next_char <= 040
            || (next_char < 0200
-               && (strchr ("\"';([#?`,", next_char))))
+               && strchr ("\"';([#?`,", next_char) != NULL))
          {
            *pch = c;
            return Qnil;
@@ -2958,9 +3005,12 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
       if (c <= 040) goto retry;
       if (c == 0x8a0) /* NBSP */
        goto retry;
+
+    read_symbol:
       {
        char *p = read_buffer;
        int quoted = 0;
+       EMACS_INT start_position = readchar_count - 1;
 
        {
          char *end = read_buffer + read_buffer_size;
@@ -2969,7 +3019,9 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
            {
              if (end - p < MAX_MULTIBYTE_LENGTH)
                {
-                 int offset = p - read_buffer;
+                 ptrdiff_t offset = p - read_buffer;
+                 if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
+                   memory_full (SIZE_MAX);
                  read_buffer = (char *) xrealloc (read_buffer,
                                                   read_buffer_size *= 2);
                  p = read_buffer + offset;
@@ -2989,106 +3041,31 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
              else
                *p++ = c;
              c = READCHAR;
-           } while (c > 040
-                    && c != 0x8a0 /* NBSP */
-                    && (c >= 0200
-                        || !(strchr ("\"';()[]#`,", c))));
+           }
+         while (c > 040
+                && c != 0x8a0 /* NBSP */
+                && (c >= 0200
+                    || strchr ("\"';()[]#`,", c) == NULL));
 
          if (p == end)
            {
-             int offset = p - read_buffer;
+             ptrdiff_t offset = p - read_buffer;
+             if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
+               memory_full (SIZE_MAX);
              read_buffer = (char *) xrealloc (read_buffer,
                                               read_buffer_size *= 2);
              p = read_buffer + offset;
              end = read_buffer + read_buffer_size;
            }
          *p = 0;
-         if (c >= 0)
-           UNREAD (c);
+         UNREAD (c);
        }
 
        if (!quoted && !uninterned_symbol)
          {
-           register char *p1;
-           p1 = read_buffer;
-           if (*p1 == '+' || *p1 == '-') p1++;
-           /* Is it an integer? */
-           if (p1 != p)
-             {
-               while (p1 != p && (c = *p1) >= '0' && c <= '9') p1++;
-               /* Integers can have trailing decimal points.  */
-               if (p1 > read_buffer && p1 < p && *p1 == '.') p1++;
-               if (p1 == p)
-                 /* It is an integer. */
-                 {
-                   if (p1[-1] == '.')
-                     p1[-1] = '\0';
-                   {
-                     /* 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, 0))
-             {
-               /* Compute NaN and infinities using 0.0 in a variable,
-                  to cope with compilers that think they are smarter
-                  than we are.  */
-               double zero = 0.0;
-
-               double value;
-
-               /* Negate the value ourselves.  This treats 0, NaNs,
-                  and infinity properly on IEEE floating point hosts,
-                  and works around a common bug where atof ("-0.0")
-                  drops the sign.  */
-               int negative = read_buffer[0] == '-';
-
-               /* The only way p[-1] can be 'F' or 'N', after isfloat_string
-                  returns 1, is if the input ends in e+INF or e+NaN.  */
-               switch (p[-1])
-                 {
-                 case 'F':
-                   value = 1.0 / zero;
-                   break;
-                 case 'N':
-                   value = zero / zero;
-
-                   /* If that made a "negative" NaN, negate it.  */
-
-                   {
-                     int i;
-                     union { double d; char c[sizeof (double)]; } u_data, u_minus_zero;
-
-                     u_data.d = value;
-                     u_minus_zero.d = - 0.0;
-                     for (i = 0; i < sizeof (double); i++)
-                       if (u_data.c[i] & u_minus_zero.c[i])
-                         {
-                           value = - value;
-                           break;
-                         }
-                   }
-                   /* Now VALUE is a positive NaN.  */
-                   break;
-                 default:
-                   value = atof (read_buffer + negative);
-                   break;
-                 }
-
-               return make_float (negative ? - value : value);
-             }
+           Lisp_Object result = string_to_number (read_buffer, 10, 0);
+           if (! NILP (result))
+             return result;
          }
        {
          Lisp_Object name, result;
@@ -3109,12 +3086,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
          if (EQ (Vread_with_symbol_positions, Qt)
              || EQ (Vread_with_symbol_positions, readcharfun))
            Vread_symbol_positions_list =
-             /* Kind of a hack; this will probably fail if characters
-                in the symbol name were escaped.  Not really a big
-                deal, though.  */
-             Fcons (Fcons (result,
-                           make_number (readchar_count
-                                        - XFASTINT (Flength (Fsymbol_name (result))))),
+             Fcons (Fcons (result, make_number (start_position)),
                     Vread_symbol_positions_list);
          return result;
        }
@@ -3185,7 +3157,7 @@ substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Obj
     {
     case Lisp_Vectorlike:
       {
-       int i, length = 0;
+       ptrdiff_t 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)
@@ -3249,79 +3221,166 @@ substitute_in_interval (INTERVAL interval, Lisp_Object arg)
 #define LEAD_INT 1
 #define DOT_CHAR 2
 #define TRAIL_INT 4
-#define E_CHAR 8
-#define EXP_INT 16
+#define E_EXP 16
 
-int
-isfloat_string (const char *cp, int ignore_trailing)
+
+/* Convert STRING to a number, assuming base BASE.  Return a fixnum if CP has
+   integer syntax and fits in a fixnum, else return the nearest float if CP has
+   either floating point or integer syntax and BASE is 10, else return nil.  If
+   IGNORE_TRAILING is nonzero, consider just the longest prefix of CP that has
+   valid floating point syntax.  Signal an overflow if BASE is not 10 and the
+   number has integer syntax but does not fit.  */
+
+Lisp_Object
+string_to_number (char const *string, int base, int ignore_trailing)
 {
   int state;
-  const char *start = cp;
+  char const *cp = string;
+  int leading_digit;
+  int float_syntax = 0;
+  double value = 0;
+
+  /* Compute NaN and infinities using a variable, to cope with compilers that
+     think they are smarter than we are.  */
+  double zero = 0;
+
+  /* Negate the value ourselves.  This treats 0, NaNs, and infinity properly on
+     IEEE floating point hosts, and works around a formerly-common bug where
+     atof ("-0.0") drops the sign.  */
+  int negative = *cp == '-';
+
+  int signedp = negative || *cp == '+';
+  cp += signedp;
 
   state = 0;
-  if (*cp == '+' || *cp == '-')
-    cp++;
 
-  if (*cp >= '0' && *cp <= '9')
+  leading_digit = digit_to_number (*cp, base);
+  if (0 <= leading_digit)
     {
       state |= LEAD_INT;
-      while (*cp >= '0' && *cp <= '9')
-       cp++;
+      do
+       ++cp;
+      while (0 <= digit_to_number (*cp, base));
     }
   if (*cp == '.')
     {
       state |= DOT_CHAR;
       cp++;
     }
-  if (*cp >= '0' && *cp <= '9')
-    {
-      state |= TRAIL_INT;
-      while (*cp >= '0' && *cp <= '9')
-       cp++;
-    }
-  if (*cp == 'e' || *cp == 'E')
-    {
-      state |= E_CHAR;
-      cp++;
-      if (*cp == '+' || *cp == '-')
-       cp++;
-    }
 
-  if (*cp >= '0' && *cp <= '9')
-    {
-      state |= EXP_INT;
-      while (*cp >= '0' && *cp <= '9')
-       cp++;
-    }
-  else if (cp == start)
-    ;
-  else if (cp[-1] == '+' && cp[0] == 'I' && cp[1] == 'N' && cp[2] == 'F')
+  if (base == 10)
     {
-      state |= EXP_INT;
-      cp += 3;
+      if ('0' <= *cp && *cp <= '9')
+       {
+         state |= TRAIL_INT;
+         do
+           cp++;
+         while ('0' <= *cp && *cp <= '9');
+       }
+      if (*cp == 'e' || *cp == 'E')
+       {
+         char const *ecp = cp;
+         cp++;
+         if (*cp == '+' || *cp == '-')
+           cp++;
+         if ('0' <= *cp && *cp <= '9')
+           {
+             state |= E_EXP;
+             do
+               cp++;
+             while ('0' <= *cp && *cp <= '9');
+           }
+         else if (cp[-1] == '+'
+                  && cp[0] == 'I' && cp[1] == 'N' && cp[2] == 'F')
+           {
+             state |= E_EXP;
+             cp += 3;
+             value = 1.0 / zero;
+           }
+         else if (cp[-1] == '+'
+                  && cp[0] == 'N' && cp[1] == 'a' && cp[2] == 'N')
+           {
+             state |= E_EXP;
+             cp += 3;
+             value = zero / zero;
+
+             /* If that made a "negative" NaN, negate it.  */
+             {
+               int i;
+               union { double d; char c[sizeof (double)]; }
+                 u_data, u_minus_zero;
+               u_data.d = value;
+               u_minus_zero.d = -0.0;
+               for (i = 0; i < sizeof (double); i++)
+                 if (u_data.c[i] & u_minus_zero.c[i])
+                   {
+                     value = -value;
+                     break;
+                   }
+             }
+             /* Now VALUE is a positive NaN.  */
+           }
+         else
+           cp = ecp;
+       }
+
+      float_syntax = ((state & (DOT_CHAR|TRAIL_INT)) == (DOT_CHAR|TRAIL_INT)
+                     || state == (LEAD_INT|E_EXP));
     }
-  else if (cp[-1] == '+' && cp[0] == 'N' && cp[1] == 'a' && cp[2] == 'N')
+
+  /* Return nil if the number uses invalid syntax.  If IGNORE_TRAILING, accept
+     any prefix that matches.  Otherwise, the entire string must match.  */
+  if (! (ignore_trailing
+        ? ((state & LEAD_INT) != 0 || float_syntax)
+        : (!*cp && ((state & ~DOT_CHAR) == LEAD_INT || float_syntax))))
+    return Qnil;
+
+  /* If the number uses integer and not float syntax, and is in C-language
+     range, use its value, preferably as a fixnum.  */
+  if (0 <= leading_digit && ! float_syntax)
     {
-      state |= EXP_INT;
-      cp += 3;
+      uintmax_t n;
+
+      /* Fast special case for single-digit integers.  This also avoids a
+        glitch when BASE is 16 and IGNORE_TRAILING is nonzero, because in that
+        case some versions of strtoumax accept numbers like "0x1" that Emacs
+        does not allow.  */
+      if (digit_to_number (string[signedp + 1], base) < 0)
+       return make_number (negative ? -leading_digit : leading_digit);
+
+      errno = 0;
+      n = strtoumax (string + signedp, NULL, base);
+      if (errno == ERANGE)
+       {
+         /* Unfortunately there's no simple and accurate way to convert
+            non-base-10 numbers that are out of C-language range.  */
+         if (base != 10)
+           xsignal1 (Qoverflow_error, build_string (string));
+       }
+      else if (n <= (negative ? -MOST_NEGATIVE_FIXNUM : MOST_POSITIVE_FIXNUM))
+       {
+         EMACS_INT signed_n = n;
+         return make_number (negative ? -signed_n : signed_n);
+       }
+      else
+       value = n;
     }
 
-  return ((ignore_trailing
-          || *cp == 0 || *cp == ' ' || *cp == '\t' || *cp == '\n'
-          || *cp == '\r' || *cp == '\f')
-         && (state == (LEAD_INT|DOT_CHAR|TRAIL_INT)
-             || state == (DOT_CHAR|TRAIL_INT)
-             || state == (LEAD_INT|E_CHAR|EXP_INT)
-             || state == (LEAD_INT|DOT_CHAR|TRAIL_INT|E_CHAR|EXP_INT)
-             || state == (DOT_CHAR|TRAIL_INT|E_CHAR|EXP_INT)));
+  /* Either the number uses float syntax, or it does not fit into a fixnum.
+     Convert it from string to floating point, unless the value is already
+     known because it is an infinity, a NAN, or its absolute value fits in
+     uintmax_t.  */
+  if (! value)
+    value = atof (string + signedp);
+
+  return make_float (negative ? -value : value);
 }
 
 \f
 static Lisp_Object
 read_vector (Lisp_Object readcharfun, int bytecodeflag)
 {
-  register int i;
-  register int size;
+  ptrdiff_t i, size;
   register Lisp_Object *ptr;
   register Lisp_Object tem, item, vector;
   register struct Lisp_Cons *otem;
@@ -3331,12 +3390,11 @@ read_vector (Lisp_Object readcharfun, int bytecodeflag)
   len = Flength (tem);
   vector = (read_pure ? make_pure_vector (XINT (len)) : Fmake_vector (len, Qnil));
 
-  size = XVECTOR (vector)->size;
+  size = ASIZE (vector);
   ptr = XVECTOR (vector)->contents;
   for (i = 0; i < size; i++)
     {
       item = Fcar (tem);
-
       /* If `load-force-doc-strings' is t when reading a lazily-loaded
         bytecode object, the docstring containing the bytecode and
         constants values must be treated as unibyte and passed to
@@ -3394,7 +3452,6 @@ read_vector (Lisp_Object readcharfun, int bytecodeflag)
       tem = Fcdr (tem);
       free_cons (otem);
     }
-
   return vector;
 }
 
@@ -3463,7 +3520,7 @@ read_list (int flag, register Lisp_Object readcharfun)
            {
              if (ch == ']')
                return val;
-             invalid_syntax (") or . in a vector", 18);
+             invalid_syntax (") or . in a vector");
            }
          if (ch == ')')
            return val;
@@ -3492,15 +3549,15 @@ read_list (int flag, register Lisp_Object readcharfun)
                         doc string, caller must make it
                         multibyte.  */
 
-                     int pos = XINT (XCDR (val));
+                     EMACS_INT pos = XINT (XCDR (val));
                      /* Position is negative for user variables.  */
                      if (pos < 0) pos = -pos;
                      if (pos >= saved_doc_string_position
                          && pos < (saved_doc_string_position
                                    + saved_doc_string_length))
                        {
-                         int start = pos - saved_doc_string_position;
-                         int from, to;
+                         ptrdiff_t start = pos - saved_doc_string_position;
+                         ptrdiff_t from, to;
 
                          /* Process quoting with ^A,
                             and find the end of the string,
@@ -3531,8 +3588,9 @@ read_list (int flag, register Lisp_Object readcharfun)
                               && pos < (prev_saved_doc_string_position
                                         + prev_saved_doc_string_length))
                        {
-                         int start = pos - prev_saved_doc_string_position;
-                         int from, to;
+                         ptrdiff_t start =
+                           pos - prev_saved_doc_string_position;
+                         ptrdiff_t from, to;
 
                          /* Process quoting with ^A,
                             and find the end of the string,
@@ -3565,9 +3623,9 @@ read_list (int flag, register Lisp_Object readcharfun)
 
                  return val;
                }
-             invalid_syntax (". in wrong context", 18);
+             invalid_syntax (". in wrong context");
            }
-         invalid_syntax ("] in a list", 11);
+         invalid_syntax ("] in a list");
        }
       tem = (read_pure && flag <= 0
             ? pure_cons (elt, Qnil)
@@ -3584,13 +3642,13 @@ read_list (int flag, register Lisp_Object readcharfun)
     }
 }
 \f
-Lisp_Object initial_obarray;
+static Lisp_Object initial_obarray;
 
 /* oblookup stores the bucket number here, for the sake of Funintern.  */
 
-int oblookup_last_bucket_number;
+static size_t oblookup_last_bucket_number;
 
-static int hash_string (const char *ptr, int len);
+static size_t hash_string (const char *ptr, size_t len);
 
 /* Get an error if OBARRAY is not an obarray.
    If it is one, return it.  */
@@ -3598,7 +3656,7 @@ static int hash_string (const char *ptr, int len);
 Lisp_Object
 check_obarray (Lisp_Object obarray)
 {
-  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+  if (!VECTORP (obarray) || ASIZE (obarray) == 0)
     {
       /* If Vobarray is now invalid, force it to be valid.  */
       if (EQ (Vobarray, obarray)) Vobarray = initial_obarray;
@@ -3614,11 +3672,11 @@ Lisp_Object
 intern (const char *str)
 {
   Lisp_Object tem;
-  int len = strlen (str);
+  ptrdiff_t len = strlen (str);
   Lisp_Object obarray;
 
   obarray = Vobarray;
-  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+  if (!VECTORP (obarray) || ASIZE (obarray) == 0)
     obarray = check_obarray (obarray);
   tem = oblookup (obarray, str, len, len);
   if (SYMBOLP (tem))
@@ -3630,11 +3688,11 @@ Lisp_Object
 intern_c_string (const char *str)
 {
   Lisp_Object tem;
-  int len = strlen (str);
+  ptrdiff_t len = strlen (str);
   Lisp_Object obarray;
 
   obarray = Vobarray;
-  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+  if (!VECTORP (obarray) || ASIZE (obarray) == 0)
     obarray = check_obarray (obarray);
   tem = oblookup (obarray, str, len, len);
   if (SYMBOLP (tem))
@@ -3648,18 +3706,6 @@ intern_c_string (const char *str)
 
   return Fintern (make_pure_c_string (str), obarray);
 }
-
-/* Create an uninterned symbol with name STR.  */
-
-Lisp_Object
-make_symbol (const char *str)
-{
-  int len = strlen (str);
-
-  return Fmake_symbol (!NILP (Vpurify_flag)
-                      ? make_pure_string (str, len, len, 0)
-                      : make_string (str, len));
-}
 \f
 DEFUN ("intern", Fintern, Sintern, 1, 2, 0,
        doc: /* Return the canonical symbol whose name is STRING.
@@ -3744,7 +3790,7 @@ OBARRAY defaults to the value of the variable `obarray'.  */)
   (Lisp_Object name, Lisp_Object obarray)
 {
   register Lisp_Object string, tem;
-  int hash;
+  size_t hash;
 
   if (NILP (obarray)) obarray = Vobarray;
   obarray = check_obarray (obarray);
@@ -3813,16 +3859,16 @@ OBARRAY defaults to the value of the variable `obarray'.  */)
 Lisp_Object
 oblookup (Lisp_Object obarray, register const char *ptr, EMACS_INT size, EMACS_INT size_byte)
 {
-  int hash;
-  int obsize;
+  size_t hash;
+  size_t obsize;
   register Lisp_Object tail;
   Lisp_Object bucket, tem;
 
   if (!VECTORP (obarray)
-      || (obsize = XVECTOR (obarray)->size) == 0)
+      || (obsize = ASIZE (obarray)) == 0)
     {
       obarray = check_obarray (obarray);
-      obsize = XVECTOR (obarray)->size;
+      obsize = ASIZE (obarray);
     }
   /* This is sometimes needed in the middle of GC.  */
   obsize &= ~ARRAY_MARK_FLAG;
@@ -3847,30 +3893,30 @@ oblookup (Lisp_Object obarray, register const char *ptr, EMACS_INT size, EMACS_I
   return tem;
 }
 
-static int
-hash_string (const char *ptr, int len)
+static size_t
+hash_string (const char *ptr, size_t len)
 {
   register const char *p = ptr;
   register const char *end = p + len;
   register unsigned char c;
-  register int hash = 0;
+  register size_t hash = 0;
 
   while (p != end)
     {
       c = *p++;
       if (c >= 0140) c -= 40;
-      hash = ((hash<<3) + (hash>>28) + c);
+      hash = (hash << 3) + (hash >> (CHAR_BIT * sizeof hash - 4)) + c;
     }
-  return hash & 07777777777;
+  return hash;
 }
 \f
 void
 map_obarray (Lisp_Object obarray, void (*fn) (Lisp_Object, Lisp_Object), Lisp_Object arg)
 {
-  register int i;
+  ptrdiff_t i;
   register Lisp_Object tail;
   CHECK_VECTOR (obarray);
-  for (i = XVECTOR (obarray)->size - 1; i >= 0; i--)
+  for (i = ASIZE (obarray) - 1; i >= 0; i--)
     {
       tail = XVECTOR (obarray)->contents[i];
       if (SYMBOLP (tail))
@@ -3938,8 +3984,7 @@ init_obarray (void)
   /* Qt is correct even if CANNOT_DUMP.  loadup.el will set to nil at end.  */
   Vpurify_flag = Qt;
 
-  Qvariable_documentation = intern_c_string ("variable-documentation");
-  staticpro (&Qvariable_documentation);
+  DEFSYM (Qvariable_documentation, "variable-documentation");
 
   read_buffer_size = 100 + MAX_MULTIBYTE_LENGTH;
   read_buffer = (char *) xmalloc (read_buffer_size);
@@ -3950,15 +3995,13 @@ defsubr (struct Lisp_Subr *sname)
 {
   Lisp_Object sym;
   sym = intern_c_string (sname->symbol_name);
-  XSETPVECTYPE (sname, PVEC_SUBR);
+  XSETTYPED_PVECTYPE (sname, size, PVEC_SUBR);
   XSETSUBR (XSYMBOL (sym)->function, sname);
 }
 
 #ifdef NOTDEF /* use fset in subr.el now */
 void
-defalias (sname, string)
-     struct Lisp_Subr *sname;
-     char *string;
+defalias (struct Lisp_Subr *sname, char *string)
 {
   Lisp_Object sym;
   sym = intern (string);
@@ -3967,7 +4010,7 @@ defalias (sname, string)
 #endif /* NOTDEF */
 
 /* Define an "integer variable"; a symbol whose value is forwarded to a
-   C variable of type int.  Sample call (munged w "xx" to fool make-docfile):
+   C variable of type EMACS_INT.  Sample call (with "xx" to fool make-docfile):
    DEFxxVAR_INT ("emacs-priority", &emacs_priority, "Documentation");  */
 void
 defvar_int (struct Lisp_Intfwd *i_fwd,
@@ -4024,7 +4067,6 @@ defvar_lisp (struct Lisp_Objfwd *o_fwd,
   staticpro (address);
 }
 
-
 /* Similar but define a variable whose value is the Lisp Object stored
    at a particular offset in the current kboard object.  */
 
@@ -4348,8 +4390,7 @@ 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);
+  DEFSYM (Qload_in_progress, "load-in-progress");
 
   DEFVAR_LISP ("after-load-alist", Vafter_load_alist,
               doc: /* An alist of expressions to be evalled when particular files are loaded.
@@ -4378,9 +4419,11 @@ The remaining ENTRIES in the alist element describe the functions and
 variables defined in that file, the features provided, and the
 features required.  Each entry has the form `(provide . FEATURE)',
 `(require . FEATURE)', `(defun . FUNCTION)', `(autoload . SYMBOL)',
-`(defface . SYMBOL)', or `(t . SYMBOL)'.  In addition, an entry `(t
-. SYMBOL)' may precede an entry `(defun . FUNCTION)', and means that
-SYMBOL was an autoload before this file redefined it as a function.
+`(defface . SYMBOL)', or `(t . SYMBOL)'.  Entries like `(t . SYMBOL)'
+may precede a `(defun . FUNCTION)' entry, and means that SYMBOL was an
+autoload before this file redefined it as a function.  In addition,
+entries may also be single symbols, which means that SYMBOL was
+defined by `defvar' or `defconst'.
 
 During preloading, the file name recorded is relative to the main Lisp
 directory.  These file names are converted to absolute at startup.  */);
@@ -4468,9 +4511,11 @@ to load.  See also `load-dangerous-libraries'.  */);
   staticpro (&Qlexical_binding);
   DEFVAR_LISP ("lexical-binding", Vlexical_binding,
               doc: /* If non-nil, use lexical binding when evaluating code.
-This only applies to code evaluated by `eval-buffer' and `eval-region'.
-This variable is automatically set from the file variables of an interpreted
-  lisp file read using `load'.  */);
+This applies to code evaluated by `eval-buffer' and `eval-region' and
+other commands that call these functions, like `eval-defun' and
+the like.
+This variable is automatically set from the file variables of an
+interpreted Lisp file read using `load'.  */);
   Fmake_variable_buffer_local (Qlexical_binding);
 
   DEFVAR_LISP ("eval-buffer-list", Veval_buffer_list,
@@ -4480,67 +4525,34 @@ This variable is automatically set from the file variables of an interpreted
   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_c_string ("old-style-backquotes");
-  staticpro (&Qold_style_backquotes);
+  DEFSYM (Qold_style_backquotes, "old-style-backquotes");
 
   /* Vsource_directory was initialized in init_lread.  */
 
   load_descriptor_list = Qnil;
   staticpro (&load_descriptor_list);
 
-  Qcurrent_load_list = intern_c_string ("current-load-list");
-  staticpro (&Qcurrent_load_list);
-
-  Qstandard_input = intern_c_string ("standard-input");
-  staticpro (&Qstandard_input);
-
-  Qread_char = intern_c_string ("read-char");
-  staticpro (&Qread_char);
-
-  Qget_file_char = intern_c_string ("get-file-char");
-  staticpro (&Qget_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_c_string ("load-force-doc-strings");
-  staticpro (&Qload_force_doc_strings);
-
-  Qbackquote = intern_c_string ("`");
-  staticpro (&Qbackquote);
-  Qcomma = intern_c_string (",");
-  staticpro (&Qcomma);
-  Qcomma_at = intern_c_string (",@");
-  staticpro (&Qcomma_at);
-  Qcomma_dot = intern_c_string (",.");
-  staticpro (&Qcomma_dot);
-
-  Qinhibit_file_name_operation = intern_c_string ("inhibit-file-name-operation");
-  staticpro (&Qinhibit_file_name_operation);
-
-  Qascii_character = intern_c_string ("ascii-character");
-  staticpro (&Qascii_character);
-
-  Qfunction = intern_c_string ("function");
-  staticpro (&Qfunction);
-
-  Qload = intern_c_string ("load");
-  staticpro (&Qload);
-
-  Qload_file_name = intern_c_string ("load-file-name");
-  staticpro (&Qload_file_name);
-
-  Qeval_buffer_list = intern_c_string ("eval-buffer-list");
-  staticpro (&Qeval_buffer_list);
-
-  Qfile_truename = intern_c_string ("file-truename");
-  staticpro (&Qfile_truename) ;
-
-  Qdir_ok = intern_c_string ("dir-ok");
-  staticpro (&Qdir_ok);
-
-  Qdo_after_load_evaluation = intern_c_string ("do-after-load-evaluation");
-  staticpro (&Qdo_after_load_evaluation) ;
+  DEFSYM (Qcurrent_load_list, "current-load-list");
+  DEFSYM (Qstandard_input, "standard-input");
+  DEFSYM (Qread_char, "read-char");
+  DEFSYM (Qget_file_char, "get-file-char");
+  DEFSYM (Qget_emacs_mule_file_char, "get-emacs-mule-file-char");
+  DEFSYM (Qload_force_doc_strings, "load-force-doc-strings");
+
+  DEFSYM (Qbackquote, "`");
+  DEFSYM (Qcomma, ",");
+  DEFSYM (Qcomma_at, ",@");
+  DEFSYM (Qcomma_dot, ",.");
+
+  DEFSYM (Qinhibit_file_name_operation, "inhibit-file-name-operation");
+  DEFSYM (Qascii_character, "ascii-character");
+  DEFSYM (Qfunction, "function");
+  DEFSYM (Qload, "load");
+  DEFSYM (Qload_file_name, "load-file-name");
+  DEFSYM (Qeval_buffer_list, "eval-buffer-list");
+  DEFSYM (Qfile_truename, "file-truename");
+  DEFSYM (Qdir_ok, "dir-ok");
+  DEFSYM (Qdo_after_load_evaluation, "do-after-load-evaluation");
 
   staticpro (&dump_path);
 
@@ -4552,18 +4564,11 @@ This variable is automatically set from the file variables of an interpreted
   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);
+  DEFSYM (Qhash_table, "hash-table");
+  DEFSYM (Qdata, "data");
+  DEFSYM (Qtest, "test");
+  DEFSYM (Qsize, "size");
+  DEFSYM (Qweakness, "weakness");
+  DEFSYM (Qrehash_size, "rehash-size");
+  DEFSYM (Qrehash_threshold, "rehash-threshold");
 }