1 (in-package :SB-GROVEL)
2 (defvar *export-symbols* nil)
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)
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)
12 (format stream "{ ~A t;printf(\"%d \",((unsigned long)&(t.~A)) - ((unsigned long)&(t)) ); }~%"
15 (format stream "{ ~A t;printf(\"%d\",(sizeof t.~A));}~%"
17 (format stream "printf(\")\\n\");~%")))))
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\");~%"
24 (princ "printf(\"(sb-grovel::define-foreign-routine (" stream)
25 (princ "\\\"" stream) (princ c-name stream) (princ "\\\" " stream)
26 (princ lisp-name stream)
28 (dolist (d definition)
30 :right-margin nil :stream stream)
32 (format stream ")\\n\");")
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)
49 "printf(\"(defconstant ~A %d \\\"~A\\\")\\\n\",~A);~%"
53 "printf(\"(defvar ~A %S \\\"~A\\\")\\\n\",~A);~%"
56 (c-for-function stream lispname cname))
58 (c-for-structure stream lispname cname))
61 "printf(\";; Non hablo Espagnol, Monsieur~%")))))
62 (format stream "exit(0);~%}")))
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)))))
71 (defclass grovel-constants-file (asdf:cl-source-file)
72 ((package :accessor constants-package :initarg :package)))
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))
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"
89 (princ (list filename output-file real-output-file
90 tmp-c-source tmp-a-dot-out tmp-constants))
92 (funcall (intern "C-CONSTANTS-EXTRACT" (find-package "SB-GROVEL"))
93 filename tmp-c-source (constants-package component))
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))))