0.pre8.50
[sbcl.git] / contrib / sb-grovel / def-to-lisp.lisp
1 (in-package :SB-GROVEL)
2 (defvar *export-symbols* nil)
3
4 (defun c-for-structure (stream lisp-name c-struct)
5   (destructuring-bind (c-name &rest elements) c-struct
6     (format stream "printf(\"(sb-grovel::define-c-struct ~A %d)\\n\",sizeof (~A));~%" lisp-name c-name)
7     (dolist (e elements)
8       (destructuring-bind (lisp-type lisp-el-name c-type c-el-name) e
9         (format stream "printf(\"(sb-grovel::define-c-accessor ~A-~A ~A ~A \");~%"
10                 lisp-name lisp-el-name lisp-name lisp-type)
11         ;; offset
12         (format stream "{ ~A t;printf(\"%d \",((unsigned long)&(t.~A)) - ((unsigned long)&(t)) ); }~%"
13                 c-name c-el-name)
14         ;; length
15         (format stream "{ ~A t;printf(\"%d\",(sizeof t.~A));}~%"
16                 c-name c-el-name)
17         (format stream "printf(\")\\n\");~%")))))
18
19 (defun c-for-function (stream lisp-name alien-defn)
20   (destructuring-bind (c-name &rest definition) alien-defn
21     (let ((*print-right-margin* nil))
22       (format stream "printf(\"(declaim (inline ~A))\\n\");~%"
23               lisp-name)
24       (princ "printf(\"(sb-grovel::define-foreign-routine (" stream)
25       (princ "\\\"" stream) (princ c-name stream) (princ "\\\" " stream)
26       (princ lisp-name stream)
27       (princ " ) " stream)
28       (dolist (d definition)
29         (write d :length nil
30                :right-margin nil :stream stream)
31         (princ " " stream))
32       (format stream ")\\n\");")
33       (terpri stream))))
34
35
36 (defun print-c-source (stream headers definitions package-name)
37   (let ((*print-right-margin* nil))
38     (loop for i in headers
39           do (format stream "#include <~A>~%" i))
40     (format stream "main() { ~%
41 printf(\"(in-package ~S)\\\n\");~%" package-name)  
42     (format stream "printf(\"(deftype int () '(signed-byte %d))\\\n\",8*sizeof (int));~%")
43     (format stream "printf(\"(deftype char () '(unsigned-byte %d))\\\n\",8*sizeof (char));~%")
44     (format stream "printf(\"(deftype long () '(unsigned-byte %d))\\\n\",8*sizeof (long));~%")
45     (dolist (def definitions)
46       (destructuring-bind (type lispname cname &optional doc) def
47         (cond ((eq type :integer)
48                (format stream
49                        "printf(\"(defconstant ~A %d \\\"~A\\\")\\\n\",~A);~%"
50                        lispname doc cname))
51               ((eq type :string)
52                (format stream
53                        "printf(\"(defvar ~A %S \\\"~A\\\")\\\n\",~A);~%"
54                      lispname doc cname))
55               ((eq type :function)
56                (c-for-function stream lispname cname))
57               ((eq type :structure)
58                (c-for-structure stream lispname cname))
59               (t
60                (format stream
61                        "printf(\";; Non hablo Espagnol, Monsieur~%")))))
62     (format stream "exit(0);~%}")))
63
64 (defun c-constants-extract  (filename output-file package)
65   (with-open-file (f output-file :direction :output)
66     (with-open-file (i filename :direction :input)
67       (let* ((headers (read i))
68              (definitions (read i)))
69         (print-c-source  f headers definitions package)))))
70
71 (defclass grovel-constants-file (asdf:cl-source-file)
72   ((package :accessor constants-package :initarg :package)))
73
74 (defmethod asdf:perform ((op asdf:compile-op)
75                          (component grovel-constants-file))
76   ;; we want to generate all our temporary files in the fasl directory
77   ;; because that's where we have write permission.  Can't use /tmp;
78   ;; it's insecure (these files will later be owned by root)
79   (let* ((output-file (car (output-files op component)))
80          (filename (component-pathname component))
81          (real-output-file
82           (if (typep output-file 'logical-pathname)
83               (translate-logical-pathname output-file)
84               (pathname output-file)))
85          (tmp-c-source (merge-pathnames #p"foo.c" real-output-file))
86          (tmp-a-dot-out (merge-pathnames #p"a.out" real-output-file))
87          (tmp-constants (merge-pathnames #p"constants.lisp-temp"
88                                          real-output-file)))
89     (princ (list filename output-file real-output-file
90                  tmp-c-source tmp-a-dot-out tmp-constants))
91     (terpri)
92     (funcall (intern "C-CONSTANTS-EXTRACT" (find-package "SB-GROVEL"))
93              filename tmp-c-source (constants-package component))
94     (and                
95      (= (run-shell-command "gcc -o ~S ~S" (namestring tmp-a-dot-out)
96          (namestring tmp-c-source)) 0)
97      (= (run-shell-command "~A >~A"
98                            (namestring tmp-a-dot-out)
99                            (namestring tmp-constants)) 0)
100      (compile-file tmp-constants :output-file output-file))))
101