1 ;;;; REQUIRE, PROVIDE, and friends
3 ;;;; Officially these are deprecated, but in practice they're probably
4 ;;;; even less likely to actually go away than there is to ever be
5 ;;;; another revision of the standard.
7 ;;;; This software is part of the SBCL system. See the README file for
10 ;;;; This software is derived from the CMU CL system, which was
11 ;;;; written at Carnegie Mellon University and released into the
12 ;;;; public domain. The software is in the public domain and is
13 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
14 ;;;; files for more information.
16 (in-package "SB!IMPL")
18 ;;;; exported specials
21 "This is a list of module names that have been loaded into Lisp so far.
22 It is used by PROVIDE and REQUIRE.")
24 (defvar *module-provider-functions
* (list 'module-provide-contrib
)
25 "See function documentation for REQUIRE.")
27 ;;;; PROVIDE and REQUIRE
29 (defun provide (module-name)
30 "Adds a new module name to *MODULES* indicating that it has been loaded.
31 Module-name is a string designator"
32 (pushnew (string module-name
) *modules
* :test
#'string
=)
35 (defvar *requiring
* nil
)
37 (defun require-error (control &rest arguments
)
38 (declare (optimize allow-non-returning-tail-call
))
39 (error 'extension-failure
40 :format-control control
41 :format-arguments arguments
44 '(:sbcl
:variable
*module-provider-functions
*)
45 '(:sbcl
:function require
))))
47 (defun require (module-name &optional pathnames
)
48 "Loads a module, unless it already has been loaded. PATHNAMES, if supplied,
49 is a designator for a list of pathnames to be loaded if the module
50 needs to be. If PATHNAMES is not supplied, functions from the list
51 *MODULE-PROVIDER-FUNCTIONS* are called in order with MODULE-NAME
52 as an argument, until one of them returns non-NIL. User code is
53 responsible for calling PROVIDE to indicate a successful load of the
55 (let ((name (string module-name
)))
56 (when (member name
*requiring
* :test
#'string
=)
57 (require-error "~@<Could not ~S ~A: circularity detected. Please check ~
58 your configuration.~:@>" 'require module-name
))
59 (let ((saved-modules (copy-list *modules
*))
60 (*requiring
* (cons name
*requiring
*)))
61 (unless (member name
*modules
* :test
#'string
=)
63 ;; ambiguity in standard: should we try all pathnames in the
64 ;; list, or should we stop as soon as one of them calls PROVIDE?
65 (dolist (ele (ensure-list pathnames
) t
)
68 (unless (some (lambda (p) (funcall p module-name
))
69 *module-provider-functions
*)
70 (require-error "Don't know how to ~S ~A."
71 'require module-name
)))))
72 (set-difference *modules
* saved-modules
))))
77 (defun module-provide-contrib (name)
78 "Stringify and downcase NAME, then attempt to load the file
80 (let* ((filesys-name (string-downcase (string name
)))
83 (make-pathname :directory
(list :relative
"contrib")
85 (truename (or (sbcl-homedir-pathname)
86 (return-from module-provide-contrib nil
)))))
87 (fasl-path (merge-pathnames
88 (make-pathname :type
*fasl-file-type
*)
90 (lisp-path (merge-pathnames (make-pathname :type
"lisp")
92 ;; KLUDGE: there's a race condition here; the file we probe could
93 ;; be removed by the time we get round to trying to load it.
94 ;; Maybe factor out the logic in the LOAD guesser as to which file
95 ;; was meant, so that we can use it here on open streams instead?
96 (let ((file (or (probe-file fasl-path
)
97 (probe-file unadorned-path
)
98 (probe-file lisp-path
))))
101 (((or style-warning package-at-variance
) #'muffle-warning
))