changeset 40474:e8c25a61215d

(Frequire): Detect recursive try to require the same feature 3 or more levels deep, and get error. (require_unwind): New subroutine. (require_nesting_list): New variable. (syms_of_fns): Init and staticpro it.
author Richard M. Stallman <rms@gnu.org>
date Tue, 30 Oct 2001 01:54:29 +0000
parents 764254527059
children 3bf0c64f4520
files src/fns.c
diffstat 1 files changed, 43 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/fns.c	Tue Oct 30 01:54:19 2001 +0000
+++ b/src/fns.c	Tue Oct 30 01:54:29 2001 +0000
@@ -3075,6 +3075,18 @@
 
   return feature;
 }
+
+/* `require' and its subroutines.  */
+
+/* List of features currently being require'd, innermost first.  */
+
+Lisp_Object require_nesting_list;
+
+require_unwind (old_value)
+     Lisp_Object old_value;
+{
+  require_nesting_list = old_value;
+}
 
 DEFUN ("require", Frequire, Srequire, 1, 3, 0,
        doc: /* If feature FEATURE is not loaded, load it from FILENAME.
@@ -3091,7 +3103,10 @@
      Lisp_Object feature, filename, noerror;
 {
   register Lisp_Object tem;
+  struct gcpro gcpro1, gcpro2;
+
   CHECK_SYMBOL (feature, 0);
+
   tem = Fmemq (feature, Vfeatures);
 
   LOADHIST_ATTACH (Fcons (Qrequire, feature));
@@ -3099,26 +3114,50 @@
   if (NILP (tem))
     {
       int count = specpdl_ptr - specpdl;
+      int nesting = 0;
+      
+      /* A certain amount of recursive `require' is legitimate,
+	 but if we require the same feature recursively 3 times,
+	 signal an error.  */
+      tem = require_nesting_list;
+      while (! NILP (tem))
+	{
+	  if (! NILP (Fequal (feature, XCAR (tem))))
+	    nesting++;
+	  tem = XCDR (tem);
+	}
+      if (nesting > 2)
+	error ("Recursive `require' for feature `%s'",
+	       XSYMBOL (feature)->name->data);
+
+      /* Update the list for any nested `require's that occur.  */
+      record_unwind_protect (require_unwind, require_nesting_list);
+      require_nesting_list = Fcons (feature, require_nesting_list);
 
       /* Value saved here is to be restored into Vautoload_queue */
       record_unwind_protect (un_autoload, Vautoload_queue);
       Vautoload_queue = Qt;
 
+      /* Load the file.  */
+      GCPRO2 (feature, filename);
       tem = Fload (NILP (filename) ? Fsymbol_name (feature) : filename,
 		   noerror, Qt, Qnil, (NILP (filename) ? Qt : Qnil));
+      UNGCPRO;
+
       /* If load failed entirely, return nil.  */
       if (NILP (tem))
 	return unbind_to (count, Qnil);
 
       tem = Fmemq (feature, Vfeatures);
       if (NILP (tem))
-	error ("Required feature %s was not provided",
+	error ("Required feature `%s' was not provided",
 	       XSYMBOL (feature)->name->data);
 
       /* Once loading finishes, don't undo it.  */
       Vautoload_queue = Qt;
       feature = unbind_to (count, feature);
     }
+
   return feature;
 }
 
@@ -5276,6 +5315,9 @@
   staticpro (&string_char_byte_cache_string);
   string_char_byte_cache_string = Qnil;
 
+  require_nesting_list = Qnil;
+  staticpro (&require_nesting_list);
+
   Fset (Qyes_or_no_p_history, Qnil);
 
   DEFVAR_LISP ("features", &Vfeatures,