chiark / gitweb /
Fix to load shared libraries from default locations in CMUCL and CLISP
[clg] / tools / autoexport.lisp
1 (defpackage "AUTOEXPORT"
2   (:use "COMMON-LISP")
3   (:export "LIST-AUTOEXPORTED-SYMBOLS" "LIST-AUTOEXPORTED-SYMBOLS-IN-FILE"
4            "DEFEXPORT" "EXPORT-FROM-FILE" "EXPORT-FROM-FILES" "INTERNAL"
5            "WITH-EXPORT-HANDLERS" "EXPORT-HANDLER-MAKUNBOUND"
6            "EXPORT-DEFCLASS-FORM" "EXPORT-FROM-SYSTEM"))
7
8 (in-package "AUTOEXPORT")
9
10 (declaim (special *internal*))
11
12 (defvar *export-handlers* (make-hash-table))
13 (defvar *noexport-prefix* #\%)
14
15 (defmacro defexport (operator lambda-list &body body)
16   `(setf
17     (gethash ',operator *export-handlers*)
18     #'(lambda ,lambda-list
19         ,@body)))
20
21 (defmacro internal (&rest symbols)
22   (declare (ignore symbols))
23   nil)
24
25 (defun export-handler-makunbound (handler)
26   (remhash handler *export-handlers*))
27
28 (defun list-autoexported-symbols (form)
29   (let ((handler (gethash (first form) *export-handlers*)))
30     (when handler
31       (let ((export (apply handler (cdr form))))
32         (delete-if
33          #'(lambda (symbol)
34              (char= (char (string symbol) 0) *noexport-prefix*))
35          (if (atom export)
36              (list export)
37            export))))))
38
39 (defun export-fname (fname)
40   (if (atom fname)
41       fname
42     (second fname)))
43
44 (defun list-autoexported-symbols-in-file (file)
45   (let ((*internal* nil))
46     (declare (special *internal*))
47     (with-open-file (in file)
48       (labels ((read-file (in)
49                  (let ((form (read in nil nil)))
50                    (when form
51                      (delete-if
52                       #'(lambda (symbol)
53                           (member symbol *internal*))
54                       (delete-duplicates
55                        (nconc
56                         (list-autoexported-symbols form)
57                         (read-file in))))))))
58         (read-file in)))))
59   
60 (defmacro export-from-file (file &optional package)
61   (if package
62       `(export ',(list-autoexported-symbols-in-file file) ,package)
63     `(export ',(list-autoexported-symbols-in-file file))))
64
65 (defmacro export-from-files (files &optional package)
66   `(progn 
67      ,@(loop for file in files collect `(export-from-file ,file ,package))))
68
69 (defmacro export-from-system (&optional package)
70   (let ((depends-on (cdar (asdf:component-depends-on asdf:*operation* asdf:*component*))))
71     `(progn 
72        ,@(loop
73           for component in depends-on
74           as pathname = (asdf:component-pathname 
75                          (asdf:find-component asdf:*system* component))
76           collect `(export-from-file ,pathname ,package)))))
77
78 (defun copy-hash-table (hash-table)
79   (let ((new-hash-table (make-hash-table 
80                          :test (hash-table-test hash-table)
81                          :size (hash-table-size hash-table))))
82     (maphash 
83      #'(lambda (key value)
84          (setf (gethash key new-hash-table) value))
85      hash-table)
86     new-hash-table))
87
88 (defmacro with-export-handlers (&body body)
89   `(let ((*export-handlers* (copy-hash-table *export-handlers*)))
90      ,@body))
91                 
92
93 ;;;; Exporting standard forms
94
95 (defexport defun (fname &rest rest)
96   (declare (ignore rest))
97   (export-fname fname))
98
99 (defexport defvar (name &rest rest)
100   (declare (ignore rest))
101   name)
102
103 (defexport defconstant (name &rest rest)
104   (declare (ignore rest))
105   name)
106
107 (defexport defparameter (name &rest rest)
108   (declare (ignore rest))
109   name)
110
111 (defexport defmacro (name &rest rest)
112   (declare (ignore rest))
113   name)
114
115 (defexport deftype (name &rest rest)
116   (declare (ignore rest))
117   name)
118
119 (defun export-defclass-form (class slotdefs &optional (export-slots-p t))
120   (cons
121    class
122    (apply #'nconc
123     (map 'list
124      #'(lambda (slotdef)
125          (if (symbolp slotdef)
126              (list slotdef)
127            (destructuring-bind
128                (name &key reader writer accessor &allow-other-keys) slotdef
129              (delete nil (list (when export-slots-p name) reader (export-fname writer) accessor)))))
130      slotdefs))))
131
132 (defexport defclass (class superclasses &optional slotdefs &rest options)
133   (declare (ignore superclasses options))
134   (export-defclass-form class slotdefs))
135
136 (defexport define-condition (class superclasses &optional slotdefs &rest options)
137   (declare (ignore superclasses options))
138   (export-defclass-form class slotdefs))
139
140 (defexport defgeneric (fname &rest args)
141   (declare (ignore args))
142   (export-fname fname))
143   
144 ;; (defexport defmethod (name &rest rest)
145 ;;   (declare (ignore rest))
146 ;;   name)
147
148 (defexport progn (&rest body)
149   (apply #'nconc (map 'list #'list-autoexported-symbols body)))
150
151 (defexport eval-when (case &rest body)
152   (declare (ignore case))
153   (apply #'nconc (map 'list #'list-autoexported-symbols body)))
154
155 (defexport internal (&rest symbols)
156   (setq *internal* (nconc *internal* symbols))
157   nil)
158