batch compilation changes
authorRobin Templeton <robin@terpri.org>
Mon, 22 Sep 2014 19:47:50 +0000 (15:47 -0400)
committerRobin Templeton <robin@terpri.org>
Mon, 9 Feb 2015 18:04:27 +0000 (13:04 -0500)
Prevent spurious "recursive require" errors by disabling automatic
whole-file compilation in some contexts. Thanks to Eric Brown
<brown@fastmail.fm> and Oleg Sivokon <olegsivokon@gmail.com> for
reporting this problem.

* src/lread.c (Fload): New `recursive' argument, which is true when a
  recursive `require' is in progress. All callers changed.
  (Feval_buffer): New optional `batch' argument.
  (readevalloop): New `batch' argument. Compile the entire file at
  once if `batch' is true and `Vload_compat' is false, or else
  evaluate expressions one by one. All callers changed.
  (Vload_compat): New variable.
* lisp/international/mule.el (load-with-code-conversion): New optional
  `batch' argument.

lisp/international/mule.el
src/chartab.c
src/doc.c
src/eval.c
src/fns.c
src/lread.c

index aba4670..43cd6bf 100644 (file)
@@ -294,7 +294,8 @@ attribute."
     (apply 'define-charset-internal name (mapcar 'cdr attrs))))
 
 
-(defun load-with-code-conversion (fullname file &optional noerror nomessage)
+(defun load-with-code-conversion (fullname file &optional noerror nomessage
+                                           batch)
   "Execute a file of Lisp code named FILE whose absolute name is FULLNAME.
 The file contents are decoded before evaluation if necessary.
 If optional third arg NOERROR is non-nil,
@@ -344,7 +345,7 @@ Return t if file exists."
            (eval-buffer buffer nil
                         ;; This is compatible with what `load' does.
                         (if purify-flag file fullname)
-                        nil t))
+                        nil t batch))
        (let (kill-buffer-hook kill-buffer-query-functions)
          (kill-buffer buffer)))
       (do-after-load-evaluation fullname)
index 3abe322..f4fc9a4 100644 (file)
@@ -1334,7 +1334,7 @@ uniprop_table (Lisp_Object prop)
       struct gcpro gcpro1;
       GCPRO1 (val);
       result = Fload (concat2 (build_string ("international/"), table),
-                     Qt, Qt, Qt, Qt);
+                     Qt, Qt, Qt, Qt, Qnil);
       UNGCPRO;
       if (NILP (result))
        return Qnil;
index e65159d..4b38221 100644 (file)
--- a/src/doc.c
+++ b/src/doc.c
@@ -321,7 +321,7 @@ reread_doc_file (Lisp_Object file)
   if (NILP (file))
     Fsnarf_documentation (Vdoc_file_name);
   else
-    Fload (file, Qt, Qt, Qt, Qnil);
+    Fload (file, Qt, Qt, Qt, Qnil, Qnil);
 
   return 1;
 }
index 5edfa79..ae59651 100644 (file)
@@ -1392,7 +1392,7 @@ it is defines a macro.  */)
   Vautoload_queue = Qt;
   /* If `macro_only', assume this autoload to be a "best-effort",
      so don't signal an error if autoloading fails.  */
-  Fload (Fcar (Fcdr (fundef)), macro_only, Qt, Qnil, Qt);
+  Fload (Fcar (Fcdr (fundef)), macro_only, Qt, Qnil, Qt, Qnil);
 
   /* Once loading finishes, don't undo it.  */
   Vautoload_queue = Qt;
index afd63a7..fda6f93 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -2669,7 +2669,8 @@ The normal messages at start and end of loading FILENAME are suppressed.  */)
       /* Load the file.  */
       GCPRO2 (feature, filename);
       tem = Fload (NILP (filename) ? Fsymbol_name (feature) : filename,
-                  noerror, Qt, Qnil, (NILP (filename) ? Qt : Qnil));
+                   noerror, Qt, Qnil, (NILP (filename) ? Qt : Qnil),
+                   nesting ? Qt : Qnil);
       UNGCPRO;
 
       /* If load failed entirely, return nil.  */
index fd6551c..242c47e 100644 (file)
@@ -147,7 +147,7 @@ static int read_emacs_mule_char (int, int (*) (int, Lisp_Object),
 
 static void readevalloop (Lisp_Object, FILE *, Lisp_Object, bool,
                           Lisp_Object, Lisp_Object,
-                          Lisp_Object, Lisp_Object);
+                          Lisp_Object, Lisp_Object, bool);
 \f
 /* Functions that read one byte from the current source READCHARFUN
    or unreads one byte.  If the integer argument C is -1, it returns
@@ -1002,7 +1002,7 @@ This uses the variables `load-suffixes' and `load-file-rep-suffixes'.  */)
   return Fnreverse (lst);
 }
 
-DEFUN ("load", Fload, Sload, 1, 5, 0,
+DEFUN ("load", Fload, Sload, 1, 6, 0,
        doc: /* Execute a file of Lisp code named FILE.
 First try FILE with `.elc' appended, then try with `.el',
 then try FILE unmodified (the exact suffixes in the exact order are
@@ -1047,7 +1047,7 @@ is bound to the file's name.
 
 Return t if the file exists and loads successfully.  */)
   (Lisp_Object file, Lisp_Object noerror, Lisp_Object nomessage,
-   Lisp_Object nosuffix, Lisp_Object must_suffix)
+   Lisp_Object nosuffix, Lisp_Object must_suffix, Lisp_Object recursive)
 {
   FILE *stream = NULL;
   int fd;
@@ -1304,9 +1304,10 @@ Return t if the file exists and loads successfully.  */)
              emacs_close (fd);
               fd = -1;
            }
-         val = call4 (Vload_source_file_function, found, hist_file_name,
+         val = call5 (Vload_source_file_function, found, hist_file_name,
                       NILP (noerror) ? Qnil : Qt,
-                      (NILP (nomessage) || force_load_messages) ? Qnil : Qt);
+                      (NILP (nomessage) || force_load_messages) ? Qnil : Qt,
+                       !NILP (recursive) ? Qnil : Qt);
          dynwind_end ();
          return val;
        }
@@ -1363,14 +1364,14 @@ Return t if the file exists and loads successfully.  */)
 
   if (! version || version >= 22)
     readevalloop (Qget_file_char, stream, hist_file_name,
-                 0, Qnil, Qnil, Qnil, Qnil);
+                 0, Qnil, Qnil, Qnil, Qnil, NILP (recursive));
   else
     {
       /* We can't handle a file which was compiled with
         byte-compile-dynamic by older version of Emacs.  */
       specbind (Qload_force_doc_strings, Qt);
       readevalloop (Qget_emacs_mule_file_char, stream, hist_file_name,
-                   0, Qnil, Qnil, Qnil, Qnil);
+                   0, Qnil, Qnil, Qnil, Qnil, NILP (recursive));
     }
   dynwind_end ();
 
@@ -1801,7 +1802,8 @@ readevalloop (Lisp_Object readcharfun,
              Lisp_Object sourcename,
              bool printflag,
              Lisp_Object unibyte, Lisp_Object readfun,
-             Lisp_Object start, Lisp_Object end)
+             Lisp_Object start, Lisp_Object end,
+              bool batch)
 {
   register int c;
   register Lisp_Object val;
@@ -1816,7 +1818,10 @@ readevalloop (Lisp_Object readcharfun,
   bool first_sexp = 1;
   Lisp_Object form = Fcons (Qprogn, Qnil);
   Lisp_Object tail = form;
-  Lisp_Object compile_fn = 0;
+  static Lisp_Object compile_fn;
+
+  if (!NILP (Vload_compat))
+    batch = false;
 
   if (SCM_UNLIKELY (! compile_fn))
     compile_fn = scm_c_public_ref ("language elisp runtime", "compile-elisp");
@@ -1948,17 +1953,30 @@ readevalloop (Lisp_Object readcharfun,
       /* Restore saved point and BEGV.  */
       dynwind_end ();
 
-      tail = Fsetcdr (tail, Fcons (val, Qnil));
+      if (!batch)
+        {
+          val = eval_sub (val);
+          if (printflag)
+            {
+              Vvalues = Fcons (val, Vvalues);
+              Fprin1 (val, Qnil);
+            }
+        }
+      else
+        tail = Fsetcdr (tail, Fcons (val, Qnil));
 
       first_sexp = 0;
     }
 
-  val = eval_sub (form);
-
-  if (SCM_UNLIKELY (printflag))
+  if (batch)
     {
-      Vvalues = Fcons (val, Vvalues);
-      Fprin1 (val, Qnil);
+      val = scm_call_1 (compile_fn, form);
+
+      if (SCM_UNLIKELY (printflag))
+        {
+          Vvalues = Fcons (val, Vvalues);
+          Fprin1 (val, Qnil);
+        }
     }
 
   build_load_history (sourcename,
@@ -1969,7 +1987,7 @@ readevalloop (Lisp_Object readcharfun,
   dynwind_end ();
 }
 
-DEFUN ("eval-buffer", Feval_buffer, Seval_buffer, 0, 5, "",
+DEFUN ("eval-buffer", Feval_buffer, Seval_buffer, 0, 6, "",
        doc: /* Execute the current buffer as Lisp code.
 When called from a Lisp program (i.e., not interactively), this
 function accepts up to five optional arguments:
@@ -1983,7 +2001,8 @@ DO-ALLOW-PRINT, if non-nil, specifies that `print' and related
  functions should work normally even if PRINTFLAG is nil.
 
 This function preserves the position of point.  */)
-  (Lisp_Object buffer, Lisp_Object printflag, Lisp_Object filename, Lisp_Object unibyte, Lisp_Object do_allow_print)
+  (Lisp_Object buffer, Lisp_Object printflag, Lisp_Object filename,
+   Lisp_Object unibyte, Lisp_Object do_allow_print, Lisp_Object batch)
 {
   dynwind_begin ();
   Lisp_Object tem, buf;
@@ -2009,7 +2028,7 @@ This function preserves the position of point.  */)
   BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf)));
   specbind (Qlexical_binding, lisp_file_lexically_bound_p (buf) ? Qt : Qnil);
   readevalloop (buf, 0, filename,
-               !NILP (printflag), unibyte, Qnil, Qnil, Qnil);
+               !NILP (printflag), unibyte, Qnil, Qnil, Qnil, !NILP (batch));
   dynwind_end ();
 
   return Qnil;
@@ -2045,7 +2064,7 @@ This function does not move point.  */)
   /* `readevalloop' calls functions which check the type of start and end.  */
   readevalloop (cbuf, 0, BVAR (XBUFFER (cbuf), filename),
                !NILP (printflag), Qnil, read_function,
-               start, end);
+               start, end, 0);
 
   dynwind_end ();
   return Qnil;
@@ -4564,6 +4583,9 @@ incompatible byte codes can make Emacs crash when it tries to execute
 them.  */);
   load_dangerous_libraries = 0;
 
+  DEFVAR_LISP ("load-compat", Vload_compat, 0);
+  Vload_compat = Qnil;
+
   DEFVAR_BOOL ("force-load-messages", force_load_messages,
               doc: /* Non-nil means force printing messages when loading Lisp files.
 This overrides the value of the NOMESSAGE argument to `load'.  */);