diff options
| author | Richard M. Stallman | 2001-10-30 01:54:29 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 2001-10-30 01:54:29 +0000 |
| commit | 1f79789d4aea615815127596ccb7f3acc0db5c7f (patch) | |
| tree | 14d0a6c4897d1047dea9dd2132628ee6a65d7e3a /src | |
| parent | b2304472681772a10f335a0c1e2f040037d2e085 (diff) | |
| download | emacs-1f79789d4aea615815127596ccb7f3acc0db5c7f.tar.gz emacs-1f79789d4aea615815127596ccb7f3acc0db5c7f.zip | |
(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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fns.c | 44 |
1 files changed, 43 insertions, 1 deletions
| @@ -3075,6 +3075,18 @@ particular subfeatures supported in this version of FEATURE. */) | |||
| 3075 | 3075 | ||
| 3076 | return feature; | 3076 | return feature; |
| 3077 | } | 3077 | } |
| 3078 | |||
| 3079 | /* `require' and its subroutines. */ | ||
| 3080 | |||
| 3081 | /* List of features currently being require'd, innermost first. */ | ||
| 3082 | |||
| 3083 | Lisp_Object require_nesting_list; | ||
| 3084 | |||
| 3085 | require_unwind (old_value) | ||
| 3086 | Lisp_Object old_value; | ||
| 3087 | { | ||
| 3088 | require_nesting_list = old_value; | ||
| 3089 | } | ||
| 3078 | 3090 | ||
| 3079 | DEFUN ("require", Frequire, Srequire, 1, 3, 0, | 3091 | DEFUN ("require", Frequire, Srequire, 1, 3, 0, |
| 3080 | doc: /* If feature FEATURE is not loaded, load it from FILENAME. | 3092 | 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. */) | |||
| 3091 | Lisp_Object feature, filename, noerror; | 3103 | Lisp_Object feature, filename, noerror; |
| 3092 | { | 3104 | { |
| 3093 | register Lisp_Object tem; | 3105 | register Lisp_Object tem; |
| 3106 | struct gcpro gcpro1, gcpro2; | ||
| 3107 | |||
| 3094 | CHECK_SYMBOL (feature, 0); | 3108 | CHECK_SYMBOL (feature, 0); |
| 3109 | |||
| 3095 | tem = Fmemq (feature, Vfeatures); | 3110 | tem = Fmemq (feature, Vfeatures); |
| 3096 | 3111 | ||
| 3097 | LOADHIST_ATTACH (Fcons (Qrequire, feature)); | 3112 | LOADHIST_ATTACH (Fcons (Qrequire, feature)); |
| @@ -3099,26 +3114,50 @@ The normal messages at start and end of loading FILENAME are suppressed. */) | |||
| 3099 | if (NILP (tem)) | 3114 | if (NILP (tem)) |
| 3100 | { | 3115 | { |
| 3101 | int count = specpdl_ptr - specpdl; | 3116 | int count = specpdl_ptr - specpdl; |
| 3117 | int nesting = 0; | ||
| 3118 | |||
| 3119 | /* A certain amount of recursive `require' is legitimate, | ||
| 3120 | but if we require the same feature recursively 3 times, | ||
| 3121 | signal an error. */ | ||
| 3122 | tem = require_nesting_list; | ||
| 3123 | while (! NILP (tem)) | ||
| 3124 | { | ||
| 3125 | if (! NILP (Fequal (feature, XCAR (tem)))) | ||
| 3126 | nesting++; | ||
| 3127 | tem = XCDR (tem); | ||
| 3128 | } | ||
| 3129 | if (nesting > 2) | ||
| 3130 | error ("Recursive `require' for feature `%s'", | ||
| 3131 | XSYMBOL (feature)->name->data); | ||
| 3132 | |||
| 3133 | /* Update the list for any nested `require's that occur. */ | ||
| 3134 | record_unwind_protect (require_unwind, require_nesting_list); | ||
| 3135 | require_nesting_list = Fcons (feature, require_nesting_list); | ||
| 3102 | 3136 | ||
| 3103 | /* Value saved here is to be restored into Vautoload_queue */ | 3137 | /* Value saved here is to be restored into Vautoload_queue */ |
| 3104 | record_unwind_protect (un_autoload, Vautoload_queue); | 3138 | record_unwind_protect (un_autoload, Vautoload_queue); |
| 3105 | Vautoload_queue = Qt; | 3139 | Vautoload_queue = Qt; |
| 3106 | 3140 | ||
| 3141 | /* Load the file. */ | ||
| 3142 | GCPRO2 (feature, filename); | ||
| 3107 | tem = Fload (NILP (filename) ? Fsymbol_name (feature) : filename, | 3143 | tem = Fload (NILP (filename) ? Fsymbol_name (feature) : filename, |
| 3108 | noerror, Qt, Qnil, (NILP (filename) ? Qt : Qnil)); | 3144 | noerror, Qt, Qnil, (NILP (filename) ? Qt : Qnil)); |
| 3145 | UNGCPRO; | ||
| 3146 | |||
| 3109 | /* If load failed entirely, return nil. */ | 3147 | /* If load failed entirely, return nil. */ |
| 3110 | if (NILP (tem)) | 3148 | if (NILP (tem)) |
| 3111 | return unbind_to (count, Qnil); | 3149 | return unbind_to (count, Qnil); |
| 3112 | 3150 | ||
| 3113 | tem = Fmemq (feature, Vfeatures); | 3151 | tem = Fmemq (feature, Vfeatures); |
| 3114 | if (NILP (tem)) | 3152 | if (NILP (tem)) |
| 3115 | error ("Required feature %s was not provided", | 3153 | error ("Required feature `%s' was not provided", |
| 3116 | XSYMBOL (feature)->name->data); | 3154 | XSYMBOL (feature)->name->data); |
| 3117 | 3155 | ||
| 3118 | /* Once loading finishes, don't undo it. */ | 3156 | /* Once loading finishes, don't undo it. */ |
| 3119 | Vautoload_queue = Qt; | 3157 | Vautoload_queue = Qt; |
| 3120 | feature = unbind_to (count, feature); | 3158 | feature = unbind_to (count, feature); |
| 3121 | } | 3159 | } |
| 3160 | |||
| 3122 | return feature; | 3161 | return feature; |
| 3123 | } | 3162 | } |
| 3124 | 3163 | ||
| @@ -5276,6 +5315,9 @@ syms_of_fns () | |||
| 5276 | staticpro (&string_char_byte_cache_string); | 5315 | staticpro (&string_char_byte_cache_string); |
| 5277 | string_char_byte_cache_string = Qnil; | 5316 | string_char_byte_cache_string = Qnil; |
| 5278 | 5317 | ||
| 5318 | require_nesting_list = Qnil; | ||
| 5319 | staticpro (&require_nesting_list); | ||
| 5320 | |||
| 5279 | Fset (Qyes_or_no_p_history, Qnil); | 5321 | Fset (Qyes_or_no_p_history, Qnil); |
| 5280 | 5322 | ||
| 5281 | DEFVAR_LISP ("features", &Vfeatures, | 5323 | DEFVAR_LISP ("features", &Vfeatures, |