merge trunk
[bpt/emacs.git] / src / lread.c
index 6d0ff9f..3ca644b 100644 (file)
@@ -1,6 +1,7 @@
 /* Lisp parsing and input streams.
 
-Copyright (C) 1985-1989, 1993-1995, 1997-2012  Free Software Foundation, Inc.
+Copyright (C) 1985-1989, 1993-1995, 1997-2013 Free Software Foundation,
+Inc.
 
 This file is part of GNU Emacs.
 
@@ -95,11 +96,6 @@ static Lisp_Object Qload_in_progress;
    It must be set to nil before all top-level calls to read0.  */
 static Lisp_Object read_objects;
 
-/* True means READCHAR should read bytes one by one (not character)
-   when READCHARFUN is Qget_file_char or Qget_emacs_mule_file_char.
-   This is set by read1 temporarily while handling #@NUMBER.  */
-static bool load_each_byte;
-
 /* List of descriptors now open for Fload.  */
 static Lisp_Object load_descriptor_list;
 
@@ -205,6 +201,9 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
 
       ptrdiff_t pt_byte = BUF_PT_BYTE (inbuffer);
 
+      if (! BUFFER_LIVE_P (inbuffer))
+       return -1;
+
       if (pt_byte >= BUF_ZV_BYTE (inbuffer))
        return -1;
 
@@ -327,7 +326,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
       return c;
     }
   c = (*readbyte) (-1, readcharfun);
-  if (c < 0 || load_each_byte)
+  if (c < 0)
     return c;
   if (multibyte)
     *multibyte = 1;
@@ -352,6 +351,46 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
   return STRING_CHAR (buf);
 }
 
+#define FROM_FILE_P(readcharfun)                       \
+  (EQ (readcharfun, Qget_file_char)                    \
+   || EQ (readcharfun, Qget_emacs_mule_file_char))
+
+static void
+skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n)
+{
+  if (FROM_FILE_P (readcharfun))
+    {
+      block_input ();          /* FIXME: Not sure if it's needed.  */
+      fseek (instream, n, SEEK_CUR);
+      unblock_input ();
+    }
+  else
+    { /* We're not reading directly from a file.  In that case, it's difficult
+        to reliably count bytes, since these are usually meant for the file's
+        encoding, whereas we're now typically in the internal encoding.
+        But luckily, skip_dyn_bytes is used to skip over a single
+        dynamic-docstring (or dynamic byte-code) which is always quoted such
+        that \037 is the final char.  */
+      int c;
+      do {
+       c = READCHAR;
+      } while (c >= 0 && c != '\037');
+    }
+}
+
+static void
+skip_dyn_eof (Lisp_Object readcharfun)
+{
+  if (FROM_FILE_P (readcharfun))
+    {
+      block_input ();          /* FIXME: Not sure if it's needed.  */
+      fseek (instream, 0, SEEK_END);
+      unblock_input ();
+    }
+  else
+    while (READCHAR >= 0);
+}
+
 /* Unread the character C in the way appropriate for the stream READCHARFUN.
    If the stream is a user function, call it with the char as argument.  */
 
@@ -403,17 +442,9 @@ unreadchar (Lisp_Object readcharfun, int c)
     {
       unread_char = c;
     }
-  else if (EQ (readcharfun, Qget_file_char)
-          || EQ (readcharfun, Qget_emacs_mule_file_char))
+  else if (FROM_FILE_P (readcharfun))
     {
-      if (load_each_byte)
-       {
-         block_input ();
-         ungetc (c, instream);
-         unblock_input ();
-       }
-      else
-       unread_char = c;
+      unread_char = c;
     }
   else
     call1 (readcharfun, make_number (c));
@@ -440,7 +471,6 @@ readbyte_from_file (int c, Lisp_Object readcharfun)
   block_input ();
   c = getc (instream);
 
-#ifdef EINTR
   /* Interrupted reads have been observed while reading over the network.  */
   while (c == EOF && ferror (instream) && errno == EINTR)
     {
@@ -450,7 +480,6 @@ readbyte_from_file (int c, Lisp_Object readcharfun)
       clearerr (instream);
       c = getc (instream);
     }
-#endif
 
   unblock_input ();
 
@@ -603,17 +632,17 @@ read_filtered_event (bool no_switch_frame, bool ascii_required,
       end_time = add_emacs_time (current_emacs_time (), wait_time);
     }
 
-/* Read until we get an acceptable event.  */
+  /* Read until we get an acceptable event.  */
  retry:
   do
-    val = read_char (0, 0, 0, (input_method ? Qnil : Qt), 0,
+    val = read_char (0, Qnil, (input_method ? Qnil : Qt), 0,
                     NUMBERP (seconds) ? &end_time : NULL);
   while (INTEGERP (val) && XINT (val) == -2); /* wrong_kboard_jmpbuf */
 
   if (BUFFERP (val))
     goto retry;
 
-  /* switch-frame events are put off until after the next ASCII
+  /* `switch-frame' events are put off until after the next ASCII
      character.  This is better than signaling an error just because
      the last characters were typed to a separate minibuffer frame,
      for example.  Eventually, some code which can deal with
@@ -1299,7 +1328,7 @@ Return t if the file exists and loads successfully.  */)
        message_with_string ("Loading %s...", file, 1);
     }
 
-  record_unwind_protect (load_unwind, make_save_value (stream, 0));
+  record_unwind_protect (load_unwind, make_save_pointer (stream));
   record_unwind_protect (load_descriptor_unwind, load_descriptor_list);
   specbind (Qload_file_name, found);
   specbind (Qinhibit_file_name_operation, Qnil);
@@ -1358,7 +1387,7 @@ Return t if the file exists and loads successfully.  */)
 static Lisp_Object
 load_unwind (Lisp_Object arg)  /* Used as unwind-protect function in load.  */
 {
-  FILE *stream = (FILE *) XSAVE_VALUE (arg)->pointer;
+  FILE *stream = XSAVE_POINTER (arg, 0);
   if (stream != NULL)
     {
       block_input ();
@@ -1558,7 +1587,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
                {
                  struct stat st;
                  fd = emacs_open (pfn, O_RDONLY, 0);
-                 if (0 <= fd
+                 if (fd >= 0
                      && (fstat (fd, &st) != 0 || S_ISDIR (st.st_mode)))
                    {
                      emacs_close (fd);
@@ -1963,7 +1992,9 @@ STREAM or the value of `standard-input' may be:
   if (EQ (stream, Qt))
     stream = Qread_char;
   if (EQ (stream, Qread_char))
-    return Fread_minibuffer (build_string ("Lisp expression: "), Qnil);
+    /* FIXME: ¿¡ When is this used !?  */
+    return call1 (intern ("read-minibuffer"),
+                 build_string ("Lisp expression: "));
 
   return read_internal_start (stream, Qnil, Qnil);
 }
@@ -2346,7 +2377,7 @@ read_integer (Lisp_Object readcharfun, EMACS_INT radix)
          while (c == '0');
        }
 
-      while (-1 <= (digit = digit_to_number (c, radix)))
+      while ((digit = digit_to_number (c, radix)) >= -1)
        {
          if (digit == -1)
            valid = 0;
@@ -2389,7 +2420,6 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
   bool multibyte;
 
   *pch = 0;
-  load_each_byte = 0;
 
  retry:
 
@@ -2599,29 +2629,40 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
          return tmp;
        }
 
-      /* #@NUMBER is used to skip NUMBER following characters.
+      /* #@NUMBER is used to skip NUMBER following bytes.
         That's used in .elc files to skip over doc strings
         and function definitions.  */
       if (c == '@')
        {
          enum { extra = 100 };
-         ptrdiff_t i, nskip = 0;
+         ptrdiff_t i, nskip = 0, digits = 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 ();
+             digits++;
              nskip *= 10;
              nskip += c - '0';
+             if (digits == 2 && nskip == 0)
+               { /* We've just seen #@00, which means "skip to end".  */
+                 skip_dyn_eof (readcharfun);
+                 return Qnil;
+               }
            }
-         UNREAD (c);
+         if (nskip > 0)
+           /* We can't use UNREAD here, because in the code below we side-step
+               READCHAR.  Instead, assume the first char after #@NNN occupies
+               a single byte, which is the case normally since it's just
+               a space.  */
+           nskip--;
+         else
+           UNREAD (c);
 
          if (load_force_doc_strings
-             && (EQ (readcharfun, Qget_file_char)
-                 || EQ (readcharfun, Qget_emacs_mule_file_char)))
+             && (FROM_FILE_P (readcharfun)))
            {
              /* If we are supposed to force doc strings into core right now,
                 record the last string that we skipped,
@@ -2660,19 +2701,17 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
              saved_doc_string_position = file_tell (instream);
 
              /* Copy that many characters into saved_doc_string.  */
+             block_input ();
              for (i = 0; i < nskip && c >= 0; i++)
-               saved_doc_string[i] = c = READCHAR;
+               saved_doc_string[i] = c = getc (instream);
+             unblock_input ();
 
              saved_doc_string_length = i;
            }
          else
-           {
-             /* Skip that many characters.  */
-             for (i = 0; i < nskip && c >= 0; i++)
-               c = READCHAR;
-           }
+           /* Skip that many bytes.  */
+           skip_dyn_bytes (readcharfun, nskip);
 
-         load_each_byte = 0;
          goto retry;
        }
       if (c == '!')
@@ -3283,12 +3322,12 @@ string_to_number (char const *string, int base, bool ignore_trailing)
   state = 0;
 
   leading_digit = digit_to_number (*cp, base);
-  if (0 <= leading_digit)
+  if (leading_digit >= 0)
     {
       state |= LEAD_INT;
       do
        ++cp;
-      while (0 <= digit_to_number (*cp, base));
+      while (digit_to_number (*cp, base) >= 0);
     }
   if (*cp == '.')
     {
@@ -3365,7 +3404,7 @@ string_to_number (char const *string, int base, bool ignore_trailing)
 
   /* 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)
+  if (leading_digit >= 0 && ! float_syntax)
     {
       uintmax_t n;
 
@@ -3518,7 +3557,7 @@ read_list (bool flag, Lisp_Object readcharfun)
        {
          if (NILP (Vdoc_file_name))
            /* We have not yet called Snarf-documentation, so assume
-              this file is described in the DOC-MM.NN file
+              this file is described in the DOC file
               and Snarf-documentation will fill in the right value later.
               For now, replace the whole list with 0.  */
            doc_reference = 1;
@@ -3559,8 +3598,10 @@ read_list (bool flag, Lisp_Object readcharfun)
                {
                  if (doc_reference == 1)
                    return make_number (0);
-                 if (doc_reference == 2)
+                 if (doc_reference == 2 && INTEGERP (XCDR (val)))
                    {
+                     char *saved = NULL;
+                     file_offset saved_position;
                      /* Get a doc string from the file we are loading.
                         If it's in saved_doc_string, get it from there.
 
@@ -3571,72 +3612,48 @@ read_list (bool flag, Lisp_Object readcharfun)
                         doc string, caller must make it
                         multibyte.  */
 
-                     EMACS_INT pos = XINT (XCDR (val));
                      /* Position is negative for user variables.  */
-                     if (pos < 0) pos = -pos;
+                     EMACS_INT pos = eabs (XINT (XCDR (val)));
                      if (pos >= saved_doc_string_position
                          && pos < (saved_doc_string_position
                                    + saved_doc_string_length))
                        {
-                         ptrdiff_t start = pos - saved_doc_string_position;
-                         ptrdiff_t from, to;
-
-                         /* Process quoting with ^A,
-                            and find the end of the string,
-                            which is marked with ^_ (037).  */
-                         for (from = start, to = start;
-                              saved_doc_string[from] != 037;)
-                           {
-                             int c = saved_doc_string[from++];
-                             if (c == 1)
-                               {
-                                 c = saved_doc_string[from++];
-                                 if (c == 1)
-                                   saved_doc_string[to++] = c;
-                                 else if (c == '0')
-                                   saved_doc_string[to++] = 0;
-                                 else if (c == '_')
-                                   saved_doc_string[to++] = 037;
-                               }
-                             else
-                               saved_doc_string[to++] = c;
-                           }
-
-                         return make_unibyte_string (saved_doc_string + start,
-                                                     to - start);
+                         saved = saved_doc_string;
+                         saved_position = saved_doc_string_position;
                        }
                      /* Look in prev_saved_doc_string the same way.  */
                      else if (pos >= prev_saved_doc_string_position
                               && pos < (prev_saved_doc_string_position
                                         + prev_saved_doc_string_length))
                        {
-                         ptrdiff_t start =
-                           pos - prev_saved_doc_string_position;
+                         saved = prev_saved_doc_string;
+                         saved_position = prev_saved_doc_string_position;
+                       }
+                     if (saved)
+                       {
+                         ptrdiff_t start = pos - saved_position;
                          ptrdiff_t from, to;
 
                          /* Process quoting with ^A,
                             and find the end of the string,
                             which is marked with ^_ (037).  */
                          for (from = start, to = start;
-                              prev_saved_doc_string[from] != 037;)
+                              saved[from] != 037;)
                            {
-                             int c = prev_saved_doc_string[from++];
+                             int c = saved[from++];
                              if (c == 1)
                                {
-                                 c = prev_saved_doc_string[from++];
-                                 if (c == 1)
-                                   prev_saved_doc_string[to++] = c;
-                                 else if (c == '0')
-                                   prev_saved_doc_string[to++] = 0;
-                                 else if (c == '_')
-                                   prev_saved_doc_string[to++] = 037;
+                                 c = saved[from++];
+                                 saved[to++] = (c == 1 ? c
+                                                : c == '0' ? 0
+                                                : c == '_' ? 037
+                                                : c);
                                }
                              else
-                               prev_saved_doc_string[to++] = c;
+                               saved[to++] = c;
                            }
 
-                         return make_unibyte_string (prev_saved_doc_string
-                                                     + start,
+                         return make_unibyte_string (saved + start,
                                                      to - start);
                        }
                      else
@@ -4527,12 +4544,16 @@ The default is nil, which means use the function `read'.  */);
   Vload_read_function = Qnil;
 
   DEFVAR_LISP ("load-source-file-function", Vload_source_file_function,
-              doc: /* Function called in `load' for loading an Emacs Lisp source file.
-This function is for doing code conversion before reading the source file.
-If nil, loading is done without any code conversion.
-Arguments are FULLNAME, FILE, NOERROR, NOMESSAGE, where
- FULLNAME is the full name of FILE.
-See `load' for the meaning of the remaining arguments.  */);
+              doc: /* Function called in `load' to load an Emacs Lisp source file.
+The value should be a function for doing code conversion before
+reading a source file.  It can also be nil, in which case loading is
+done without any code conversion.
+
+If the value is a function, it is called with four arguments,
+FULLNAME, FILE, NOERROR, NOMESSAGE.  FULLNAME is the absolute name of
+the file to load, FILE is the non-absolute name (for messages etc.),
+and NOERROR and NOMESSAGE are the corresponding arguments passed to
+`load'.  The function should return t if the file was loaded.  */);
   Vload_source_file_function = Qnil;
 
   DEFVAR_BOOL ("load-force-doc-strings", load_force_doc_strings,