# HG changeset patch # User Richard M. Stallman # Date 1004406869 0 # Node ID e8c25a61215d941b708bb1c17a9a0fa2d7e82e4f # Parent 764254527059b07f5d3012ddc699520016933f95 (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. diff -r 764254527059 -r e8c25a61215d src/fns.c --- 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,