From 5aebec6d3ae6ad58f1ead9571389cda18629c346 Mon Sep 17 00:00:00 2001 From: Nikodemus Siivola Date: Sat, 7 Aug 2004 18:21:05 +0000 Subject: [PATCH] 0.8.13.39: REQUIRE SANITY * Detect infinite recursion in require, and signal a reasonable error before running out of file-handles. * Prettier REQUIRE cross-reference in the manual, even though this makes it slightly more brittle. --- doc/manual/contrib-modules.texinfo | 2 +- src/code/module.lisp | 51 ++++++++++++++++++++++-------------- version.lisp-expr | 2 +- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/doc/manual/contrib-modules.texinfo b/doc/manual/contrib-modules.texinfo index d135cc2..308690e 100644 --- a/doc/manual/contrib-modules.texinfo +++ b/doc/manual/contrib-modules.texinfo @@ -4,7 +4,7 @@ SBCL comes with a number of modules that are not part of the core system. These are loaded via @code{(require :@var{modulename})} -(@pxref{fun-common-lisp-require}). This section contains +(@pxref{Customization Hooks for Users}). This section contains documentation (or pointers to documentation) for the contributed modules. diff --git a/src/code/module.lisp b/src/code/module.lisp index 866b7b3..db40773 100644 --- a/src/code/module.lisp +++ b/src/code/module.lisp @@ -22,7 +22,7 @@ "This is a list of module names that have been loaded into Lisp so far. It is used by PROVIDE and REQUIRE.") -(defvar *module-provider-functions* '(module-provide-contrib) +(defvar *module-provider-functions* (list 'module-provide-contrib) "See function documentation for REQUIRE") ;;;; PROVIDE and REQUIRE @@ -34,6 +34,17 @@ (pushnew (string module-name) *modules* :test #'string=) t) +(defvar *requiring* nil) + +(defun require-error (control &rest arguments) + (error 'extension-failure + :format-control control + :format-arguments arguments + :references + (list + '(:sbcl :variable *module-provider-functions*) + '(:sbcl :function require)))) + (defun require (module-name &optional pathnames) #!+sb-doc "Loads a module, unless it already has been loaded. PATHNAMES, if supplied, @@ -43,24 +54,26 @@ as an argument, until one of them returns non-NIL. User code is responsible for calling PROVIDE to indicate a successful load of the module." - (let ((saved-modules (copy-list *modules*))) - (unless (member (string module-name) *modules* :test #'string=) - (cond (pathnames - (unless (listp pathnames) (setf pathnames (list pathnames))) - ;; ambiguity in standard: should we try all pathnames in the - ;; list, or should we stop as soon as one of them calls PROVIDE? - (dolist (ele pathnames t) - (load ele))) - (t - (unless (some (lambda (p) (funcall p module-name)) - *module-provider-functions*) - (error 'extension-failure - :format-control "Don't know how to ~S ~A" - :format-arguments (list 'require module-name) - :references - (list - '(:sbcl :variable *module-provider-functions*))))))) - (set-difference *modules* saved-modules))) + (let ((name (string module-name))) + (when (member name *requiring* :test #'string=) + (require-error "~@" 'require module-name)) + (let ((saved-modules (copy-list *modules*)) + (*requiring* (cons name *requiring*))) + (unless (member name *modules* :test #'string=) + (cond (pathnames + (unless (listp pathnames) (setf pathnames (list pathnames))) + ;; ambiguity in standard: should we try all pathnames in the + ;; list, or should we stop as soon as one of them calls PROVIDE? + (dolist (ele pathnames t) + (load ele))) + (t + (unless (some (lambda (p) (funcall p module-name)) + *module-provider-functions*) + (require-error "Don't know how to ~S ~A." + 'require module-name))))) + (set-difference *modules* saved-modules)))) + ;;;; miscellany diff --git a/version.lisp-expr b/version.lisp-expr index df7042d..f4c89fc 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"0.8.13.38" +"0.8.13.39" -- 1.7.10.4