Replace %CODE-ENTRY-POINTS with an array, remove %SIMPLE-FUN-NEXT.
[sbcl.git] / src / code / module.lisp
blob2ba5b526a9739c163896817374e24fb084f086d2
1 ;;;; REQUIRE, PROVIDE, and friends
2 ;;;;
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
8 ;;;; more information.
9 ;;;;
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
20 (defvar *modules* ()
21 #!+sb-doc
22 "This is a list of module names that have been loaded into Lisp so far.
23 It is used by PROVIDE and REQUIRE.")
25 (defvar *module-provider-functions* (list 'module-provide-contrib)
26 #!+sb-doc
27 "See function documentation for REQUIRE.")
29 ;;;; PROVIDE and REQUIRE
31 (defun provide (module-name)
32 #!+sb-doc
33 "Adds a new module name to *MODULES* indicating that it has been loaded.
34 Module-name is a string designator"
35 (pushnew (string module-name) *modules* :test #'string=)
38 (defvar *requiring* nil)
40 (defun require-error (control &rest arguments)
41 (declare (optimize allow-non-returning-tail-call))
42 (error 'extension-failure
43 :format-control control
44 :format-arguments arguments
45 :references
46 (list
47 '(:sbcl :variable *module-provider-functions*)
48 '(:sbcl :function require))))
50 (defun require (module-name &optional pathnames)
51 #!+sb-doc
52 "Loads a module, unless it already has been loaded. PATHNAMES, if supplied,
53 is a designator for a list of pathnames to be loaded if the module
54 needs to be. If PATHNAMES is not supplied, functions from the list
55 *MODULE-PROVIDER-FUNCTIONS* are called in order with MODULE-NAME
56 as an argument, until one of them returns non-NIL. User code is
57 responsible for calling PROVIDE to indicate a successful load of the
58 module."
59 (let ((name (string module-name)))
60 (when (member name *requiring* :test #'string=)
61 (require-error "~@<Could not ~S ~A: circularity detected. Please check ~
62 your configuration.~:@>" 'require module-name))
63 (let ((saved-modules (copy-list *modules*))
64 (*requiring* (cons name *requiring*)))
65 (unless (member name *modules* :test #'string=)
66 (cond (pathnames
67 ;; ambiguity in standard: should we try all pathnames in the
68 ;; list, or should we stop as soon as one of them calls PROVIDE?
69 (dolist (ele (ensure-list pathnames) t)
70 (load ele)))
72 (unless (some (lambda (p) (funcall p module-name))
73 *module-provider-functions*)
74 (require-error "Don't know how to ~S ~A."
75 'require module-name)))))
76 (set-difference *modules* saved-modules))))
79 ;;;; miscellany
81 (defun module-provide-contrib (name)
82 #!+sb-doc
83 "Stringify and downcase NAME, then attempt to load the file
84 $SBCL_HOME/name/name"
85 (let* ((filesys-name (string-downcase (string name)))
86 (unadorned-path
87 (merge-pathnames
88 (make-pathname :directory (list :relative "contrib")
89 :name filesys-name)
90 (truename (or (sbcl-homedir-pathname)
91 (return-from module-provide-contrib nil)))))
92 (fasl-path (merge-pathnames
93 (make-pathname :type *fasl-file-type*)
94 unadorned-path))
95 (lisp-path (merge-pathnames (make-pathname :type "lisp")
96 unadorned-path)))
97 ;; KLUDGE: there's a race condition here; the file we probe could
98 ;; be removed by the time we get round to trying to load it.
99 ;; Maybe factor out the logic in the LOAD guesser as to which file
100 ;; was meant, so that we can use it here on open streams instead?
101 (let ((file (or (probe-file fasl-path)
102 (probe-file unadorned-path)
103 (probe-file lisp-path))))
104 (when file
105 (handler-bind
106 (((or style-warning sb!int:package-at-variance) #'muffle-warning))
107 (load file))
108 t))))