]> code.delx.au - gnu-emacs/blobdiff - src/lread.c
Merge from trunk.
[gnu-emacs] / src / lread.c
index e75d61ae98585612d171e0434165888403a84acf..7b3e0df5e8aa0f1d7a80e368eaf9aa0ec86e17a4 100644 (file)
@@ -109,9 +109,9 @@ static FILE *instream;
 static int read_pure;
 
 /* For use within read-from-string (this reader is non-reentrant!!)  */
-static EMACS_INT read_from_string_index;
-static EMACS_INT read_from_string_index_byte;
-static EMACS_INT read_from_string_limit;
+static ptrdiff_t read_from_string_index;
+static ptrdiff_t read_from_string_index_byte;
+static ptrdiff_t read_from_string_limit;
 
 /* Number of characters read in the current call to Fread or
    Fread_from_string. */
@@ -120,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;
 
@@ -131,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;
 
@@ -209,7 +209,7 @@ readchar (Lisp_Object readcharfun, int *multibyte)
     {
       register struct buffer *inbuffer = XBUFFER (readcharfun);
 
-      EMACS_INT pt_byte = BUF_PT_BYTE (inbuffer);
+      ptrdiff_t pt_byte = BUF_PT_BYTE (inbuffer);
 
       if (pt_byte >= BUF_ZV_BYTE (inbuffer))
        return -1;
@@ -238,7 +238,7 @@ readchar (Lisp_Object readcharfun, int *multibyte)
     {
       register struct buffer *inbuffer = XMARKER (readcharfun)->buffer;
 
-      EMACS_INT bytepos = marker_byte_position (readcharfun);
+      ptrdiff_t bytepos = marker_byte_position (readcharfun);
 
       if (bytepos >= BUF_ZV_BYTE (inbuffer))
        return -1;
@@ -372,8 +372,8 @@ unreadchar (Lisp_Object readcharfun, int c)
   else if (BUFFERP (readcharfun))
     {
       struct buffer *b = XBUFFER (readcharfun);
-      EMACS_INT charpos = BUF_PT (b);
-      EMACS_INT bytepos = BUF_PT_BYTE (b);
+      ptrdiff_t charpos = BUF_PT (b);
+      ptrdiff_t bytepos = BUF_PT_BYTE (b);
 
       if (! NILP (BVAR (b, enable_multibyte_characters)))
        BUF_DEC_POS (b, bytepos);
@@ -385,7 +385,7 @@ unreadchar (Lisp_Object readcharfun, int c)
   else if (MARKERP (readcharfun))
     {
       struct buffer *b = XMARKER (readcharfun)->buffer;
-      EMACS_INT bytepos = XMARKER (readcharfun)->bytepos;
+      ptrdiff_t bytepos = XMARKER (readcharfun)->bytepos;
 
       XMARKER (readcharfun)->charpos--;
       if (! NILP (BVAR (b, enable_multibyte_characters)))
@@ -1023,7 +1023,7 @@ Return t if the file exists and loads successfully.  */)
 {
   register FILE *stream;
   register int fd = -1;
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3;
   Lisp_Object found, efound, hist_file_name;
   /* 1 means we printed the ".el is newer" message.  */
@@ -1069,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);
@@ -1124,6 +1124,22 @@ Return t if the file exists and loads successfully.  */)
        handler = Ffind_file_name_handler (found, Qload);
       if (! NILP (handler))
        return call5 (handler, Qload, found, noerror, nomessage, Qt);
+#ifdef DOS_NT
+      /* Tramp has to deal with semi-broken packages that prepend
+        drive letters to remote files.  For that reason, Tramp
+        catches file operations that test for file existence, which
+        makes openp think X:/foo.elc files are remote.  However,
+        Tramp does not catch `load' operations for such files, so we
+        end up with a nil as the `load' handler above.  If we would
+        continue with fd = -2, we will behave wrongly, and in
+        particular try reading a .elc file in the "rt" mode instead
+        of "rb".  See bug #9311 for the results.  To work around
+        this, we try to open the file locally, and go with that if it
+        succeeds.  */
+      fd = emacs_open (SSDATA (ENCODE_FILE (found)), O_RDONLY, 0);
+      if (fd == -1)
+       fd = -2;
+#endif
     }
 
   /* Check if we're stuck in a recursive load cycle.
@@ -1247,9 +1263,17 @@ Return t if the file exists and loads successfully.  */)
   GCPRO3 (file, found, hist_file_name);
 
 #ifdef WINDOWSNT
-  emacs_close (fd);
   efound = ENCODE_FILE (found);
-  stream = fopen (SSDATA (efound), fmode);
+  /* If we somehow got here with fd == -2, meaning the file is deemed
+     to be remote, don't even try to reopen the file locally; just
+     force a failure instead.  */
+  if (fd >= 0)
+    {
+      emacs_close (fd);
+      stream = fopen (SSDATA (efound), fmode);
+    }
+  else
+    stream = NULL;
 #else  /* not WINDOWSNT */
   stream = fdopen (fd, fmode);
 #endif /* not WINDOWSNT */
@@ -1260,7 +1284,7 @@ Return t if the file exists and loads successfully.  */)
     }
 
   if (! NILP (Vpurify_flag))
-    Vpreloaded_file_list = Fcons (Fpurecopy(file), Vpreloaded_file_list);
+    Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list);
 
   if (NILP (nomessage) || force_load_messages)
     {
@@ -1419,16 +1443,16 @@ int
 openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate)
 {
   register int fd;
-  EMACS_INT fn_size = 100;
+  ptrdiff_t fn_size = 100;
   char buf[100];
   register char *fn = buf;
   int absolute = 0;
-  EMACS_INT want_length;
+  ptrdiff_t want_length;
   Lisp_Object filename;
   struct stat st;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
   Lisp_Object string, tail, encoded_fn;
-  EMACS_INT max_suffix_len = 0;
+  ptrdiff_t max_suffix_len = 0;
 
   CHECK_STRING (str);
 
@@ -1472,7 +1496,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
       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;
 
@@ -1538,7 +1562,9 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
                {
                  /* Check that we can access or open it.  */
                  if (NATNUMP (predicate))
-                   fd = (access (pfn, XFASTINT (predicate)) == 0) ? 1 : -1;
+                   fd = (((XFASTINT (predicate) & ~INT_MAX) == 0
+                          && access (pfn, XFASTINT (predicate)) == 0)
+                         ? 1 : -1);
                  else
                    fd = emacs_open (pfn, O_RDONLY, 0);
 
@@ -1672,7 +1698,7 @@ readevalloop (Lisp_Object readcharfun,
 {
   register int c;
   register Lisp_Object val;
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   struct buffer *b = 0;
   int continue_reading_p;
@@ -1723,7 +1749,7 @@ readevalloop (Lisp_Object readcharfun,
   continue_reading_p = 1;
   while (continue_reading_p)
     {
-      int count1 = SPECPDL_INDEX ();
+      ptrdiff_t count1 = SPECPDL_INDEX ();
 
       if (b != 0 && NILP (BVAR (b, name)))
        error ("Reading from killed buffer");
@@ -1849,7 +1875,7 @@ DO-ALLOW-PRINT, if non-nil, specifies that `print' and related
 This function preserves the position of point.  */)
   (Lisp_Object buffer, Lisp_Object printflag, Lisp_Object filename, Lisp_Object unibyte, Lisp_Object do_allow_print)
 {
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object tem, buf;
 
   if (NILP (buffer))
@@ -1894,7 +1920,7 @@ This function does not move point.  */)
   (Lisp_Object start, Lisp_Object end, Lisp_Object printflag, Lisp_Object read_function)
 {
   /* FIXME: Do the eval-sexp-add-defvars danse!  */
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object tem, cbuf;
 
   cbuf = Fcurrent_buffer ();
@@ -1941,6 +1967,8 @@ STREAM or the value of `standard-input' may be:
 DEFUN ("read-from-string", Fread_from_string, Sread_from_string, 1, 3, 0,
        doc: /* Read one Lisp expression which is represented as text by STRING.
 Returns a cons: (OBJECT-READ . FINAL-STRING-INDEX).
+FINAL-STRING-INDEX is an integer giving the position of the next
+ remaining chararacter in STRING.
 START and END optionally delimit a substring of STRING from which to read;
  they default to 0 and (length STRING) respectively.  */)
   (Lisp_Object string, Lisp_Object start, Lisp_Object end)
@@ -1970,7 +1998,7 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
   if (STRINGP (stream)
       || ((CONSP (stream) && STRINGP (XCAR (stream)))))
     {
-      EMACS_INT startval, endval;
+      ptrdiff_t startval, endval;
       Lisp_Object string;
 
       if (STRINGP (stream))
@@ -1983,9 +2011,9 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
       else
        {
          CHECK_NUMBER (end);
-         endval = XINT (end);
-         if (endval < 0 || endval > SCHARS (string))
+         if (! (0 <= XINT (end) && XINT (end) <= SCHARS (string)))
            args_out_of_range (string, end);
+         endval = XINT (end);
        }
 
       if (NILP (start))
@@ -1993,9 +2021,9 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
       else
        {
          CHECK_NUMBER (start);
-         startval = XINT (start);
-         if (startval < 0 || startval > endval)
+         if (! (0 <= XINT (start) && XINT (start) <= endval))
            args_out_of_range (string, start);
+         startval = XINT (start);
        }
       read_from_string_index = startval;
       read_from_string_index_byte = string_char_to_byte (string, startval);
@@ -2037,7 +2065,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 `\'.
@@ -2208,7 +2236,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)
@@ -2236,10 +2266,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);
@@ -2278,10 +2305,12 @@ digit_to_number (int character, int base)
    range.  */
 
 static Lisp_Object
-read_integer (Lisp_Object readcharfun, int radix)
+read_integer (Lisp_Object readcharfun, EMACS_INT radix)
 {
-  /* Room for sign, leading 0, other digits, trailing null byte.  */
-  char buf[1 + 1 + sizeof (uintmax_t) * CHAR_BIT + 1];
+  /* 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.  */
 
@@ -2326,14 +2355,13 @@ read_integer (Lisp_Object readcharfun, int radix)
          c = READCHAR;
        }
 
-      if (c >= 0)
-       UNREAD (c);
+      UNREAD (c);
       *p = '\0';
     }
 
   if (! valid)
     {
-      sprintf (buf, "integer, radix %d", radix);
+      sprintf (buf, "integer, radix %"pI"d", radix);
       invalid_syntax (buf);
     }
 
@@ -2471,14 +2499,13 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
              if (c == '[')
                {
                  Lisp_Object tmp;
-                 int depth, size;
+                 int depth;
+                 ptrdiff_t size;
 
                  tmp = read_vector (readcharfun, 0);
-                 if (!INTEGERP (AREF (tmp, 0)))
+                 if (! RANGED_INTEGERP (1, AREF (tmp, 0), 3))
                    error ("Invalid depth in char-table");
                  depth = XINT (AREF (tmp, 0));
-                 if (depth < 1 || depth > 3)
-                   error ("Invalid depth in char-table");
                  size = ASIZE (tmp) - 2;
                  if (chartab_size [depth] != size)
                    error ("Invalid size char-table");
@@ -2497,7 +2524,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);
 
@@ -2569,18 +2596,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)
@@ -2594,9 +2623,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;
@@ -2611,14 +2640,14 @@ 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 = (char *) xmalloc (saved_doc_string_size);
+                 saved_doc_string = (char *) xmalloc (nskip + extra);
+                 saved_doc_string_size = nskip + extra;
                }
              if (nskip > saved_doc_string_size)
                {
-                 saved_doc_string_size = nskip + 100;
                  saved_doc_string = (char *) xrealloc (saved_doc_string,
-                                                       saved_doc_string_size);
+                                                       nskip + extra);
+                 saved_doc_string_size = nskip + extra;
                }
 
              saved_doc_string_position = file_tell (instream);
@@ -2656,54 +2685,78 @@ 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;
        }
+      /* ## is the empty symbol.  */
+      if (c == '#')
+       return Fintern (build_string (""), Qnil);
       /* 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')
@@ -2826,7 +2879,7 @@ 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);
@@ -2846,16 +2899,19 @@ 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);
+                                                read_buffer_size * 2);
+               read_buffer_size *= 2;
                p = read_buffer + offset;
                end = read_buffer + read_buffer_size;
              }
@@ -2949,11 +3005,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
@@ -2970,7 +3021,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;
@@ -2985,9 +3036,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;
@@ -2996,9 +3050,12 @@ 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);
+                                                  read_buffer_size * 2);
+                 read_buffer_size *= 2;
                  p = read_buffer + offset;
                  end = read_buffer + read_buffer_size;
                }
@@ -3016,22 +3073,25 @@ 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);
+                                              read_buffer_size * 2);
+             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)
@@ -3042,8 +3102,8 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
          }
        {
          Lisp_Object name, result;
-         EMACS_INT nbytes = p - read_buffer;
-         EMACS_INT nchars
+         ptrdiff_t nbytes = p - read_buffer;
+         ptrdiff_t nchars
            = (multibyte
               ? multibyte_chars_in_text ((unsigned char *) read_buffer,
                                          nbytes)
@@ -3059,12 +3119,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;
        }
@@ -3135,7 +3190,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)
@@ -3358,8 +3413,7 @@ string_to_number (char const *string, int base, int ignore_trailing)
 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;
@@ -3528,15 +3582,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,
@@ -3567,8 +3621,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,
@@ -3626,8 +3681,6 @@ static Lisp_Object initial_obarray;
 
 static size_t oblookup_last_bucket_number;
 
-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.  */
 
@@ -3835,7 +3888,7 @@ OBARRAY defaults to the value of the variable `obarray'.  */)
    Also store the bucket number in oblookup_last_bucket_number.  */
 
 Lisp_Object
-oblookup (Lisp_Object obarray, register const char *ptr, EMACS_INT size, EMACS_INT size_byte)
+oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff_t size_byte)
 {
   size_t hash;
   size_t obsize;
@@ -3870,28 +3923,11 @@ oblookup (Lisp_Object obarray, register const char *ptr, EMACS_INT size, EMACS_I
   XSETINT (tem, hash);
   return tem;
 }
-
-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 size_t hash = 0;
-
-  while (p != end)
-    {
-      c = *p++;
-      if (c >= 0140) c -= 40;
-      hash = (hash << 3) + (hash >> (CHAR_BIT * sizeof hash - 4)) + c;
-    }
-  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 = ASIZE (obarray) - 1; i >= 0; i--)
@@ -3932,6 +3968,7 @@ void
 init_obarray (void)
 {
   Lisp_Object oblength;
+  ptrdiff_t size = 100 + MAX_MULTIBYTE_LENGTH;
 
   XSETFASTINT (oblength, OBARRAY_SIZE);
 
@@ -3962,11 +3999,10 @@ 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);
+  read_buffer = (char *) xmalloc (size);
+  read_buffer_size = size;
 }
 \f
 void
@@ -3980,9 +4016,7 @@ defsubr (struct Lisp_Subr *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);
@@ -3991,7 +4025,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,
@@ -4264,14 +4298,20 @@ init_lread (void)
 void
 dir_warning (const char *format, Lisp_Object dirname)
 {
-  char *buffer
-    = (char *) alloca (SCHARS (dirname) + strlen (format) + 5);
-
   fprintf (stderr, format, SDATA (dirname));
-  sprintf (buffer, format, SDATA (dirname));
+
   /* Don't log the warning before we've initialized!! */
   if (initialized)
-    message_dolog (buffer, strlen (buffer), 0, STRING_MULTIBYTE (dirname));
+    {
+      char *buffer;
+      ptrdiff_t message_len;
+      USE_SAFE_ALLOCA;
+      SAFE_ALLOCA (buffer, char *,
+                  SBYTES (dirname) + strlen (format) - (sizeof "%s" - 1) + 1);
+      message_len = esprintf (buffer, format, SDATA (dirname));
+      message_dolog (buffer, message_len, 0, STRING_MULTIBYTE (dirname));
+      SAFE_FREE ();
+    }
 }
 
 void
@@ -4371,8 +4411,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.
@@ -4401,9 +4440,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.  */);
@@ -4490,10 +4531,11 @@ to load.  See also `load-dangerous-libraries'.  */);
   Qlexical_binding = intern ("lexical-binding");
   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'.  */);
+              doc: /* Whether to use lexical binding when evaluating code.
+Non-nil means that the code in the current buffer should be evaluated
+with lexical binding.
+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,
@@ -4503,67 +4545,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);
 
@@ -4575,18 +4584,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");
 }