337d5c7c3d6292fed5d4df9ab87b574c7069976c
[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(\"(cl:declaim (cl: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       (terpri stream)
29       (dolist (d definition)
30         (write d :length nil
31                :right-margin nil :stream stream)
32         (princ " " stream))
33       (format stream ")\\n\");")
34       (terpri stream))))
35
36
37 (defun print-c-source (stream headers definitions package-name)
38   (let ((*print-right-margin* nil))
39     (format stream "#define SIGNEDP(x) (((x)-1)<0)~%")
40     (format stream "#define SIGNED_(x) (SIGNEDP(x)?\"\":\"un\")~%")
41     (loop for i in headers
42           do (format stream "#include <~A>~%" i))
43     (format stream "main() { ~%
44 printf(\"(in-package ~S)\\\n\");~%" package-name)  
45     (format stream "printf(\"(cl:deftype int () '(%ssigned-byte %d))\\\n\",SIGNED_(int),8*sizeof (int));~%")
46     (format stream "printf(\"(cl:deftype char () '(unsigned-byte %d))\\\n\",SIGNED_(char),8*sizeof (char));~%")
47     (format stream "printf(\"(cl:deftype long () '(unsigned-byte %d))\\\n\",SIGNED_(long),8*sizeof (long));~%")
48     (dolist (def definitions)
49       (destructuring-bind (type lispname cname &optional doc) def
50         (cond ((eq type :integer)
51                (format stream
52                        "printf(\"(cl:defconstant ~A %d \\\"~A\\\")\\\n\",~A);~%"
53                        lispname doc cname))
54               ((eq type :type)
55                (format stream
56                        "printf(\"(sb-alien:define-alien-type ~A (sb-alien:%ssigned %d))\\\n\",SIGNED_(~A),8*(sizeof(~A)));~%"
57                        lispname cname cname))
58               ((eq type :string)
59                (format stream
60                        "printf(\"(cl:defvar ~A %S \\\"~A\\\")\\\n\",~A);~%"
61                      lispname doc cname))
62               ((eq type :function)
63                (c-for-function stream lispname cname))
64               ((eq type :structure)
65                (c-for-structure stream lispname cname))
66               (t
67                (format stream
68                        "printf(\";; Non hablo Espagnol, Monsieur~%")))))
69     (format stream "exit(0);~%}")))
70
71 (defun c-constants-extract  (filename output-file package)
72   (with-open-file (f output-file :direction :output)
73     (with-open-file (i filename :direction :input)
74       (let* ((headers (read i))
75              (definitions (read i)))
76         (print-c-source  f headers definitions package)))))
77
78 (defclass grovel-constants-file (asdf:cl-source-file)
79   ((package :accessor constants-package :initarg :package)))
80
81 (defmethod asdf:perform ((op asdf:compile-op)
82                          (component grovel-constants-file))
83   ;; we want to generate all our temporary files in the fasl directory
84   ;; because that's where we have write permission.  Can't use /tmp;
85   ;; it's insecure (these files will later be owned by root)
86   (let* ((output-file (car (output-files op component)))
87          (filename (component-pathname component))
88          (real-output-file
89           (if (typep output-file 'logical-pathname)
90               (translate-logical-pathname output-file)
91               (pathname output-file)))
92          (tmp-c-source (merge-pathnames #p"foo.c" real-output-file))
93          (tmp-a-dot-out (merge-pathnames #p"a.out" real-output-file))
94          (tmp-constants (merge-pathnames #p"constants.lisp-temp"
95                                          real-output-file)))
96     (princ (list filename output-file real-output-file
97                  tmp-c-source tmp-a-dot-out tmp-constants))
98     (terpri)
99     (funcall (intern "C-CONSTANTS-EXTRACT" (find-package "SB-GROVEL"))
100              filename tmp-c-source (constants-package component))
101     (and                
102      (= (run-shell-command "gcc -o ~S ~S" (namestring tmp-a-dot-out)
103          (namestring tmp-c-source)) 0)
104      (= (run-shell-command "~A >~A"
105                            (namestring tmp-a-dot-out)
106                            (namestring tmp-constants)) 0)
107      (compile-file tmp-constants :output-file output-file))))
108