]> code.delx.au - gnu-emacs/blobdiff - src/lread.c
(compilation-directory-matcher): Doc fix (Nil -> nil).
[gnu-emacs] / src / lread.c
index 3cf68f6455c5ac121b56eba5f8832c4a41168e84..6ce7c6a1aef1be0d8583b6a0b26de2cddcdd8630 100644 (file)
@@ -132,7 +132,7 @@ static int load_force_doc_strings;
 /* Nonzero means read should convert strings to unibyte.  */
 static int load_convert_to_unibyte;
 
-/* Function to use for loading an Emacs lisp source file (not
+/* Function to use for loading an Emacs Lisp source file (not
    compiled) instead of readevalloop.  */
 Lisp_Object Vload_source_file_function;
 
@@ -214,6 +214,9 @@ static void readevalloop P_ ((Lisp_Object, FILE*, Lisp_Object,
 static Lisp_Object load_unwind P_ ((Lisp_Object));
 static Lisp_Object load_descriptor_unwind P_ ((Lisp_Object));
 
+static void invalid_syntax P_ ((const char *, int)) NO_RETURN;
+static void end_of_file_error P_ (()) NO_RETURN;
+
 \f
 /* Handle unreading and rereading of characters.
    Write READCHAR to read a character,
@@ -452,14 +455,19 @@ extern Lisp_Object read_char ();
    character.
 
    If INPUT_METHOD is nonzero, we invoke the current input method
-   if the character warrants that.  */
+   if the character warrants that.
+
+   If SECONDS is a number, we wait that many seconds for input, and
+   return Qnil if no input arrives within that time.  */
 
 Lisp_Object
 read_filtered_event (no_switch_frame, ascii_required, error_nonascii,
-                    input_method)
+                    input_method, seconds)
      int no_switch_frame, ascii_required, error_nonascii, input_method;
+     Lisp_Object seconds;
 {
   Lisp_Object val, delayed_switch_frame;
+  EMACS_TIME end_time;
 
 #ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
@@ -468,11 +476,24 @@ read_filtered_event (no_switch_frame, ascii_required, error_nonascii,
 
   delayed_switch_frame = Qnil;
 
+  /* Compute timeout.  */
+  if (NUMBERP (seconds))
+    {
+      EMACS_TIME wait_time;
+      int sec, usec;
+      double duration = extract_float (seconds);        
+
+      sec  = (int) duration;
+      usec = (duration - sec) * 1000000;
+      EMACS_GET_TIME (end_time);
+      EMACS_SET_SECS_USECS (wait_time, sec, usec);
+      EMACS_ADD_TIME (end_time, end_time, wait_time);
+    }
+
   /* Read until we get an acceptable event.  */
  retry:
-  val = read_char (0, 0, 0,
-                  (input_method ? Qnil : Qt),
-                  0);
+  val = read_char (0, 0, 0, (input_method ? Qnil : Qt), 0,
+                  NUMBERP (seconds) ? &end_time : NULL);
 
   if (BUFFERP (val))
     goto retry;
@@ -490,7 +511,7 @@ read_filtered_event (no_switch_frame, ascii_required, error_nonascii,
       goto retry;
     }
 
-  if (ascii_required)
+  if (ascii_required && !(NUMBERP (seconds) && NILP (val)))
     {
       /* Convert certain symbols to their ASCII equivalents.  */
       if (SYMBOLP (val))
@@ -535,7 +556,7 @@ read_filtered_event (no_switch_frame, ascii_required, error_nonascii,
   return val;
 }
 
-DEFUN ("read-char", Fread_char, Sread_char, 0, 2, 0,
+DEFUN ("read-char", Fread_char, Sread_char, 0, 3, 0,
        doc: /* Read a character from the command input (keyboard or macro).
 It is returned as a number.
 If the user generates an event which is not a character (i.e. a mouse
@@ -548,43 +569,55 @@ If you want to read non-character events, or ignore them, call
 If the optional argument PROMPT is non-nil, display that as a prompt.
 If the optional argument INHERIT-INPUT-METHOD is non-nil and some
 input method is turned on in the current buffer, that input method
-is used for reading a character.  */)
-     (prompt, inherit_input_method)
-     Lisp_Object prompt, inherit_input_method;
+is used for reading a character.
+If the optional argument SECONDS is non-nil, it should be a number
+specifying the maximum number of seconds to wait for input.  If no
+input arrives in that time, return nil.  SECONDS may be a
+floating-point value.  */)
+     (prompt, inherit_input_method, seconds)
+     Lisp_Object prompt, inherit_input_method, seconds;
 {
   if (! NILP (prompt))
     message_with_string ("%s", prompt, 0);
-  return read_filtered_event (1, 1, 1, ! NILP (inherit_input_method));
+  return read_filtered_event (1, 1, 1, ! NILP (inherit_input_method), seconds);
 }
 
-DEFUN ("read-event", Fread_event, Sread_event, 0, 2, 0,
+DEFUN ("read-event", Fread_event, Sread_event, 0, 3, 0,
        doc: /* Read an event object from the input stream.
 If the optional argument PROMPT is non-nil, display that as a prompt.
 If the optional argument INHERIT-INPUT-METHOD is non-nil and some
 input method is turned on in the current buffer, that input method
-is used for reading a character.  */)
-     (prompt, inherit_input_method)
-     Lisp_Object prompt, inherit_input_method;
+is used for reading a character.
+If the optional argument SECONDS is non-nil, it should be a number
+specifying the maximum number of seconds to wait for input.  If no
+input arrives in that time, return nil.  SECONDS may be a
+floating-point value.  */)
+     (prompt, inherit_input_method, seconds)
+     Lisp_Object prompt, inherit_input_method, seconds;
 {
   if (! NILP (prompt))
     message_with_string ("%s", prompt, 0);
-  return read_filtered_event (0, 0, 0, ! NILP (inherit_input_method));
+  return read_filtered_event (0, 0, 0, ! NILP (inherit_input_method), seconds);
 }
 
-DEFUN ("read-char-exclusive", Fread_char_exclusive, Sread_char_exclusive, 0, 2, 0,
+DEFUN ("read-char-exclusive", Fread_char_exclusive, Sread_char_exclusive, 0, 3, 0,
        doc: /* Read a character from the command input (keyboard or macro).
 It is returned as a number.  Non-character events are ignored.
 
 If the optional argument PROMPT is non-nil, display that as a prompt.
 If the optional argument INHERIT-INPUT-METHOD is non-nil and some
 input method is turned on in the current buffer, that input method
-is used for reading a character.  */)
-     (prompt, inherit_input_method)
-     Lisp_Object prompt, inherit_input_method;
+is used for reading a character.
+If the optional argument SECONDS is non-nil, it should be a number
+specifying the maximum number of seconds to wait for input.  If no
+input arrives in that time, return nil.  SECONDS may be a
+floating-point value.  */)
+     (prompt, inherit_input_method, seconds)
+     Lisp_Object prompt, inherit_input_method, seconds;
 {
   if (! NILP (prompt))
     message_with_string ("%s", prompt, 0);
-  return read_filtered_event (1, 1, 0, ! NILP (inherit_input_method));
+  return read_filtered_event (1, 1, 0, ! NILP (inherit_input_method), seconds);
 }
 
 DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0,
@@ -797,10 +830,8 @@ Return t if the file exists and loads successfully.  */)
   if (fd == -1)
     {
       if (NILP (noerror))
-       Fsignal (Qfile_error, Fcons (build_string ("Cannot open load file"),
-                                    Fcons (file, Qnil)));
-      else
-       return Qnil;
+       xsignal2 (Qfile_error, build_string ("Cannot open load file"), file);
+      return Qnil;
     }
 
   /* Tell startup.el whether or not we found the user's init file.  */
@@ -841,8 +872,7 @@ Return t if the file exists and loads successfully.  */)
       {
        if (fd >= 0)
          emacs_close (fd);
-       Fsignal (Qerror, Fcons (build_string ("Recursive load"),
-                               Fcons (found, Vloads_in_progress)));
+       signal_error ("Recursive load", Fcons (found, Vloads_in_progress));
       }
     record_unwind_protect (record_load_unwind, Vloads_in_progress);
     Vloads_in_progress = Fcons (found, Vloads_in_progress);
@@ -1339,11 +1369,9 @@ end_of_file_error ()
   Lisp_Object data;
 
   if (STRINGP (Vload_file_name))
-    data = Fcons (Vload_file_name, Qnil);
-  else
-    data = Qnil;
+    xsignal1 (Qend_of_file, Vload_file_name);
 
-  Fsignal (Qend_of_file, data);
+  xsignal0 (Qend_of_file);
 }
 
 /* UNIBYTE specifies how to set load_convert_to_unibyte
@@ -1369,7 +1397,6 @@ readevalloop (readcharfun, stream, sourcename, evalfun,
   int count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   struct buffer *b = 0;
-  int bpos;
   int continue_reading_p;
   /* Nonzero if reading an entire buffer.  */
   int whole_buffer = 0;
@@ -1379,7 +1406,7 @@ readevalloop (readcharfun, stream, sourcename, evalfun,
   if (MARKERP (readcharfun))
     {
       if (NILP (start))
-       start = readcharfun;    
+       start = readcharfun;
     }
 
   if (BUFFERP (readcharfun))
@@ -1402,8 +1429,8 @@ readevalloop (readcharfun, stream, sourcename, evalfun,
 
   /* Try to ensure sourcename is a truename, except whilst preloading. */
   if (NILP (Vpurify_flag)
-      && !NILP (sourcename) && Ffile_name_absolute_p (sourcename)
-      && (!NILP (Ffboundp (Qfile_truename))))
+      && !NILP (sourcename) && !NILP (Ffile_name_absolute_p (sourcename))
+      && !NILP (Ffboundp (Qfile_truename)))
     sourcename = call1 (Qfile_truename, sourcename) ;
 
   LOADHIST_ATTACH (sourcename);
@@ -1512,7 +1539,7 @@ readevalloop (readcharfun, stream, sourcename, evalfun,
       first_sexp = 0;
     }
 
-  build_load_history (sourcename, 
+  build_load_history (sourcename,
                      stream || whole_buffer);
 
   UNGCPRO;
@@ -1695,6 +1722,21 @@ read_internal_start (stream, start, end)
   return retval;
 }
 \f
+
+/* Signal Qinvalid_read_syntax error.
+   S is error string of length N (if > 0)  */
+
+static void
+invalid_syntax (s, n)
+     const char *s;
+     int n;
+{
+  if (!n)
+    n = strlen (s);
+  xsignal1 (Qinvalid_read_syntax, make_string (s, n));
+}
+
+
 /* Use this for recursive reads, in contexts where internal tokens
    are not allowed. */
 
@@ -1706,12 +1748,11 @@ read0 (readcharfun)
   int c;
 
   val = read1 (readcharfun, &c, 0);
-  if (c)
-    Fsignal (Qinvalid_read_syntax, Fcons (Fmake_string (make_number (1),
-                                                       make_number (c)),
-                                         Qnil));
+  if (!c)
+    return val;
 
-  return val;
+  xsignal1 (Qinvalid_read_syntax,
+           Fmake_string (make_number (1), make_number (c)));
 }
 \f
 static int read_buffer_size;
@@ -1979,7 +2020,6 @@ read_escape (readcharfun, stringp, byterep)
     }
 }
 
-
 /* 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
@@ -2039,7 +2079,7 @@ read_integer (readcharfun, radix)
     {
       char buf[50];
       sprintf (buf, "integer, radix %d", radix);
-      Fsignal (Qinvalid_read_syntax, Fcons (build_string (buf), Qnil));
+      invalid_syntax (buf, 0);
     }
 
   return make_number (sign * number);
@@ -2150,10 +2190,9 @@ read1 (readcharfun, pch, first_in_list)
                  XCHAR_TABLE (tmp)->top = Qnil;
                  return tmp;
                }
-             Fsignal (Qinvalid_read_syntax,
-                      Fcons (make_string ("#^^", 3), Qnil));
+             invalid_syntax ("#^^", 3);
            }
-         Fsignal (Qinvalid_read_syntax, Fcons (make_string ("#^", 2), Qnil));
+         invalid_syntax ("#^", 2);
        }
       if (c == '&')
        {
@@ -2175,8 +2214,7 @@ read1 (readcharfun, pch, first_in_list)
                     Accept such input in case it came from an old version.  */
                  && ! (XFASTINT (length)
                        == (SCHARS (tmp) - 1) * BOOL_VECTOR_BITS_PER_CHAR))
-               Fsignal (Qinvalid_read_syntax,
-                        Fcons (make_string ("#&...", 5), Qnil));
+               invalid_syntax ("#&...", 5);
 
              val = Fmake_bool_vector (length, Qnil);
              bcopy (SDATA (tmp), XBOOL_VECTOR (val)->data,
@@ -2187,8 +2225,7 @@ read1 (readcharfun, pch, first_in_list)
                  &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
              return val;
            }
-         Fsignal (Qinvalid_read_syntax, Fcons (make_string ("#&...", 5),
-                                               Qnil));
+         invalid_syntax ("#&...", 5);
        }
       if (c == '[')
        {
@@ -2208,7 +2245,7 @@ read1 (readcharfun, pch, first_in_list)
          /* Read the string itself.  */
          tmp = read1 (readcharfun, &ch, 0);
          if (ch != 0 || !STRINGP (tmp))
-           Fsignal (Qinvalid_read_syntax, Fcons (make_string ("#", 1), Qnil));
+           invalid_syntax ("#", 1);
          GCPRO1 (tmp);
          /* Read the intervals and their properties.  */
          while (1)
@@ -2224,9 +2261,7 @@ read1 (readcharfun, pch, first_in_list)
              if (ch == 0)
                plist = read1 (readcharfun, &ch, 0);
              if (ch)
-               Fsignal (Qinvalid_read_syntax,
-                        Fcons (build_string ("invalid string property list"),
-                               Qnil));
+               invalid_syntax ("Invalid string property list", 0);
              Fset_text_properties (beg, end, plist, tmp);
            }
          UNGCPRO;
@@ -2379,7 +2414,7 @@ read1 (readcharfun, pch, first_in_list)
        return read_integer (readcharfun, 2);
 
       UNREAD (c);
-      Fsignal (Qinvalid_read_syntax, Fcons (make_string ("#", 1), Qnil));
+      invalid_syntax ("#", 1);
 
     case ';':
       while ((c = READCHAR) >= 0 && c != '\n');
@@ -2473,10 +2508,10 @@ read1 (readcharfun, pch, first_in_list)
                          || (new_backquote_flag && next_char == ','))));
          }
        UNREAD (next_char);
-       if (!ok)
-         Fsignal (Qinvalid_read_syntax, Fcons (make_string ("?", 1), Qnil));
+       if (ok)
+         return make_number (c);
 
-       return make_number (c);
+       invalid_syntax ("?", 1);
       }
 
     case '"':
@@ -3121,8 +3156,7 @@ read_list (flag, readcharfun)
            {
              if (ch == ']')
                return val;
-             Fsignal (Qinvalid_read_syntax,
-                      Fcons (make_string (") or . in a vector", 18), Qnil));
+             invalid_syntax (") or . in a vector", 18);
            }
          if (ch == ')')
            return val;
@@ -3215,9 +3249,9 @@ read_list (flag, readcharfun)
 
                  return val;
                }
-             return Fsignal (Qinvalid_read_syntax, Fcons (make_string (". in wrong context", 18), Qnil));
+             invalid_syntax (". in wrong context", 18);
            }
-         return Fsignal (Qinvalid_read_syntax, Fcons (make_string ("] in a list", 11), Qnil));
+         invalid_syntax ("] in a list", 11);
        }
       tem = (read_pure && flag <= 0
             ? pure_cons (elt, Qnil)
@@ -3250,12 +3284,11 @@ Lisp_Object
 check_obarray (obarray)
      Lisp_Object obarray;
 {
-  while (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
     {
       /* If Vobarray is now invalid, force it to be valid.  */
       if (EQ (Vobarray, obarray)) Vobarray = initial_obarray;
-
-      obarray = wrong_type_argument (Qvectorp, obarray);
+      wrong_type_argument (Qvectorp, obarray);
     }
   return obarray;
 }
@@ -4084,7 +4117,7 @@ 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.
+              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