summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard M. Stallman <rms@gnu.org>2001-10-30 01:54:29 +0000
committerRichard M. Stallman <rms@gnu.org>2001-10-30 01:54:29 +0000
commit1f79789d4aea615815127596ccb7f3acc0db5c7f (patch)
tree14d0a6c4897d1047dea9dd2132628ee6a65d7e3a
parentb2304472681772a10f335a0c1e2f040037d2e085 (diff)
downloademacs-1f79789d4aea615815127596ccb7f3acc0db5c7f.tar.gz
(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.
-rw-r--r--src/fns.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/src/fns.c b/src/fns.c
index a948ed7b567..62f9d85682c 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -3075,6 +3075,18 @@ particular subfeatures supported in this version of FEATURE. */)
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 @@ The normal messages at start and end of loading FILENAME are suppressed. */)
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 @@ The normal messages at start and end of loading FILENAME are suppressed. */)
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 @@ syms_of_fns ()
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,