note FIRST fix in NEWS, fix stupid typo in tests
[sbcl.git] / src / cold / set-up-cold-packages.lisp
1 ;;;; This software is part of the SBCL system. See the README file for
2 ;;;; more information.
3 ;;;;
4 ;;;; This software is derived from the CMU CL system, which was
5 ;;;; written at Carnegie Mellon University and released into the
6 ;;;; public domain. The software is in the public domain and is
7 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
8 ;;;; files for more information.
9
10 (in-package "SB-COLD")
11
12 ;;; an entry in the table which describes the non-standard part (i.e. not
13 ;;; CL/CL-USER/KEYWORD) of the package structure of the SBCL system
14 ;;;
15 ;;; We make no attempt to be fully general; our table doesn't need to be
16 ;;; able to express features which we don't happen to use.
17 (export '(package-data
18           package-data-name
19           package-data-export
20           package-data-reexport
21           package-data-import-from
22           package-data-use))
23 (defstruct package-data
24   ;; a string designator for the package name
25   (name (error "missing PACKAGE-DATA-NAME datum"))
26   ;; a doc string
27   (doc (error "missing PACKAGE-DOC datum"))
28   ;; a tree containing names for exported symbols which'll be set up at package
29   ;; creation time, and NILs, which are ignored. (This is a tree in order to
30   ;; allow constructs like '("ENOSPC" #!+LINUX ("EDQUOT" "EISNAM" "ENAVAIL"
31   ;; "EREMOTEIO")) to be used in initialization. NIL entries in the tree are
32   ;; ignored for the same reason of notational convenience.)
33   export
34   ;; a list of string designators for exported symbols which don't necessarily
35   ;; originate in this package (so their EXPORT operations should be handled
36   ;; after USE operations have been done, so that duplicates aren't created)
37   reexport
38   ;; a list of sublists describing imports. Each sublist has the format as an
39   ;; IMPORT-FROM list in DEFPACKAGE: the first element is the name of the
40   ;; package to import from, and the remaining elements are the names of
41   ;; symbols to import.
42   import-from
43   ;; a tree of string designators for package names of other packages
44   ;; which this package uses
45   use)
46
47 (let ((package-data-list (read-from-file "package-data-list.lisp-expr")))
48
49     ;; Build all packages that we need, and initialize them as far as we
50     ;; can without referring to any other packages.
51     (dolist (package-data package-data-list)
52       (let* ((package (make-package
53                        (package-data-name package-data)
54                        ;; Note: As of 0.7.0, the only nicknames we use
55                        ;; for our implementation packages are hacks
56                        ;; not needed at cross-compile time (e.g. the
57                        ;; deprecated SB-C-CALL nickname for SB-ALIEN).
58                        ;; So support for nicknaming during xc is gone,
59                        ;; since any nicknames are hacked in during
60                        ;; cold init.
61                        :nicknames nil
62                        :use nil)))
63         (progn
64           #!+sb-doc (setf (documentation package t)
65                           (package-data-doc package-data)))
66         ;; Walk the tree of exported names, exporting each name.
67         (labels ((recurse (tree)
68                    (etypecase tree
69                      ;; FIXME: The comments above say the structure is a tree,
70                      ;; but here we're sleazily treating it as though
71                      ;; dotted lists never occur. Replace this LIST case
72                      ;; with separate NULL and CONS cases to fix this.
73                      (list (mapc #'recurse tree))
74                      (string (export (intern tree package) package)))))
75           (recurse (package-data-export package-data)))))
76
77     ;; Now that all packages exist, we can set up package-package
78     ;; references.
79     (dolist (package-data package-data-list)
80       (use-package (package-data-use package-data)
81                    (package-data-name package-data))
82       (dolist (sublist (package-data-import-from package-data))
83         (let* ((from-package (first sublist))
84                (symbol-names (rest sublist))
85                (symbols (mapcar (lambda (name)
86                                   ;; old way, broke for importing symbols
87                                   ;; like SB!C::DEBUG-SOURCE-FORM into
88                                   ;; SB!DI -- WHN 19990714
89                                   #+nil
90                                   (let ((s (find-symbol name from-package)))
91                                     (unless s
92                                       (error "can't find ~S in ~S"
93                                              name
94                                              from-package))
95                                     s)
96                                   ;; new way, works for SB!DI stuff
97                                   ;; -- WHN 19990714
98                                   (intern name from-package))
99                                 symbol-names)))
100           (import symbols (package-data-name package-data)))))
101
102     ;; Now that all package-package references exist, we can handle
103     ;; REEXPORT operations. (We have to wait until now because they
104     ;; interact with USE operations.)  This code handles dependencies
105     ;; properly, but is somewhat ugly.
106     (let (done)
107       (labels
108           ((reexport (package-data)
109              (let ((package (find-package (package-data-name package-data))))
110                (cond
111                  ((member package done))
112                  ((null (package-data-reexport package-data))
113                   (push package done))
114                  (t
115                   (mapcar #'reexport
116                           (remove-if-not
117                            (lambda (x)
118                              (member x (package-data-use package-data)
119                                      :test #'string=))
120                            package-data-list
121                            :key #'package-data-name))
122                   (dolist (symbol-name (package-data-reexport package-data))
123                     (multiple-value-bind (symbol status)
124                         (find-symbol symbol-name package)
125                       (unless status
126                         (error "No symbol named ~S is accessible in ~S."
127                                symbol-name package))
128                       (when (eq (symbol-package symbol) package)
129                         (error
130                          "~S is not inherited/imported, but native to ~S."
131                          symbol-name package))
132                       (export symbol package)))
133                   (push package done))))))
134         (dolist (x package-data-list)
135           (reexport x))
136         (assert (= (length done) (length package-data-list))))))