? require.diff
Index: module.lsp
===================================================================
RCS file: /cvsroot/ecls/ecls/src/lsp/module.lsp,v
retrieving revision 1.3
diff -u -r1.3 module.lsp
--- module.lsp	15 Oct 2001 16:44:04 -0000	1.3
+++ module.lsp	16 Feb 2005 21:07:51 -0000
@@ -10,37 +10,57 @@
 
 ;;;;	module routines
 
+;; This is taken from SBCL's code/module.lisp which is in the public
+;; domain.
+
 (in-package "SYSTEM")
 
-(defvar *modules* nil
-  "List of module names that have been loaded into ECL.
-See PROVIDE and REQUIRE.")
+;;;; exported specials
+
+(defvar *modules* ()
+  "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* nil
+  "See function documentation for REQUIRE")
+
+;;;; PROVIDE and REQUIRE
 
 (defun provide (module-name)
-  "Args: (module-name)
-Declares the start of a program module.  Usually used at the beginning of a
-program file.  MODULE-NAME may be a string or a symbol.  If it is a string, it
-is pushed onto *MODULES*.  If it is a symbol, its print name is pushed.  See
-REQUIRE."
-  (setq *modules*
-        (adjoin (string module-name) *modules* :test #'string=)))
-
-
-(defun require (module-name
-                &optional (pathname (string-downcase (string module-name))))
-  "Args: (module-name &optional pathname)
-If the specified module name is not found in *MODULES*, then loads the files
-specified by PATHNAME.  Otherwise, does nothing.  MODULE-NAME may be a string
-or a symbol.  If it is a symbol, the print name of the symbol is used as the
-module name.  PATHNAME may be a pathname object or it may be a list of
-pathname objects.  If PATHNAME is not given, then ECL tries to load the file
-whose file name is MODULE-NAME and whose filetype is either .FASL, .LSP, or
-none.  See PROVIDE."
-  (let ((*default-pathname-defaults* #P""))
-    (unless (member (string module-name)
-                    *modules* :test #'string=)
-      (if (atom pathname)
-	  (load pathname)
-	  (dolist (p pathname)
-	    (load p))))))
+  "Adds a new module name to *MODULES* indicating that it has been loaded.
+   Module-name is a string designator"
+  (pushnew (string module-name) *modules* :test #'string=)
+  t)
+
+(defvar *requiring* nil)
+
+(defun require-error (control &rest arguments)
+  (error "Module error: ~?" control arguments))
 
+(defun require (module-name &optional pathnames)
+  "Loads a module, unless it already has been loaded. PATHNAMES, if supplied,
+   is a designator for a list of pathnames to be loaded if the module
+   needs to be. If PATHNAMES is not supplied, functions from the list
+   *MODULE-PROVIDER-FUNCTIONS* are called in order with MODULE-NAME
+   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 ((name (string module-name)))
+    (when (member name *requiring* :test #'string=)
+      (require-error "~@<Could not ~S ~A: circularity detected. Please check ~
+                     your configuration.~:@>" '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))))
