0.8.0.52
[sbcl.git] / src / code / module.lisp
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.
6
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.
15
16 (in-package "SB!IMPL")
17 \f
18 ;;;; exported specials
19
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.")
24
25 (defvar sb!ext::*MODULE-PROVIDER-FUNCTIONS* '(module-provide-contrib)
26   "See function documentation for REQUIRE")
27
28 \f
29 ;;;; PROVIDE and REQUIRE
30
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=)
36   t)
37
38 (defun require (module-name &optional pathnames)
39   #!+sb-doc
40   "Loads a module, unless it already has been loaded. PATHNAMES, if supplied,
41    is a designator for a list of pathnames to be loaded if the module
42    needs to be. If PATHNAMES is not supplied, functions from the list
43    *MODULE-PROVIDER-FUNCTIONS* are called in order with MODULE-NAME
44    as an argument, until one of them returns non-NIL."
45   (let ((saved-modules (copy-list *modules*)))
46     (unless (member (string module-name) *modules* :test #'string=)
47       (cond (pathnames
48              (unless (listp pathnames) (setf pathnames (list pathnames)))
49              ;; ambiguity in standard: should we try all pathnames in the
50              ;; list, or should we stop as soon as one of them calls PROVIDE?
51              (dolist (ele pathnames t)
52                (load ele))
53              ;; should we do this?  Probably can't hurt, while we're
54              ;; taking the above view of "load everything"...  though
55              ;; maybe having REQUIRE directly call PROVIDE is
56              ;; aesthetically suboptimal.
57              (provide module-name))
58             (t
59              (unless (some (lambda (p) (funcall p module-name))
60                            sb!ext::*module-provider-functions*)
61                (error "Don't know how to load ~A" module-name)))))
62     (set-difference *modules* saved-modules)))
63 \f
64 ;;;; miscellany
65
66 (defun module-provide-contrib (name)
67   "Stringify and downcase NAME, then attempt to load the file
68    $SBCL_HOME/name/name"
69   (let ((filesys-name (string-downcase (string name))))
70     (load
71      (merge-pathnames (make-pathname :directory (list :relative filesys-name)
72                                      :name filesys-name)
73                       (truename (posix-getenv "SBCL_HOME")))))
74   (provide name)
75   t)
76
77