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
&key distrust-length
) e
9 ;; FIXME: this format string doesn't actually guarantee
10 ;; non-multilined-string-constantness, it just makes it more
11 ;; likely. Sort out the required behaviour (and maybe make
12 ;; the generated C more readable, while we're at it...) --
14 (format stream
"printf(\"(sb-grovel::define-c-accessor ~A-~A\\n\\~% ~
16 lisp-name lisp-el-name lisp-name lisp-type
)
18 (format stream
"{ ~A t;printf(\"%d \",((unsigned long)&(t.~A)) - ((unsigned long)&(t)) ); }~%"
22 (format stream
"printf(\"|CL|:|NIL|\");")
23 (format stream
"{ ~A t;printf(\"%d\",(sizeof t.~A));}~%"
25 (format stream
"printf(\")\\n\");~%")))))
27 (defun c-for-function (stream lisp-name alien-defn
)
28 (destructuring-bind (c-name &rest definition
) alien-defn
29 (format stream
"printf(\"(cl:declaim (cl:inline ~A))\\n\");~%" lisp-name
)
31 "printf(\"(sb-grovel::define-foreign-routine (\\\"~A\\\" ~A)\\n\\~%~
32 ~{ ~W~^\\n\\~%~})\\n\");~%"
33 c-name lisp-name definition
)))
35 (defun print-c-source (stream headers definitions package-name
)
36 (let ((*print-right-margin
* nil
))
37 (format stream
"#define SIGNEDP(x) (((x)-1)<0)~%")
38 (format stream
"#define SIGNED_(x) (SIGNEDP(x)?\"\":\"un\")~%")
39 (loop for i in
(cons "stdio.h" headers
)
40 do
(format stream
"#include <~A>~%" i
))
41 (format stream
"main() { ~%
42 printf(\"(in-package ~S)\\\n\");~%" package-name
)
43 (format stream
"printf(\"(cl:deftype int () '(%ssigned-byte %d))\\\n\",SIGNED_(int),8*sizeof (int));~%")
44 (format stream
"printf(\"(cl:deftype char () '(%ssigned-byte %d))\\\n\",SIGNED_(char),8*sizeof (char));~%")
45 (format stream
"printf(\"(cl:deftype long () '(%ssigned-byte %d))\\\n\",SIGNED_(long),8*sizeof (long));~%")
46 (format stream
"printf(\"(cl:defconstant size-of-int %d)\\\n\",sizeof (int));~%")
47 (format stream
"printf(\"(cl:defconstant size-of-char %d)\\\n\",sizeof (char));~%")
48 (format stream
"printf(\"(cl:defconstant size-of-long %d)\\\n\",sizeof (long));~%")
49 (dolist (def definitions
)
50 (destructuring-bind (type lispname cname
&optional doc
) def
51 (cond ((eq type
:integer
)
54 printf(\"(cl:defconstant ~A %d \\\"~A\\\")\\\n\",~A);~%~
56 printf(\"(sb-int:style-warn \\\"Couln't grovel definition for ~A (unknown to the C compiler).\\\")\\n\");~%~
58 cname lispname doc cname cname
))
61 "printf(\"(sb-alien:define-alien-type ~A (sb-alien:%ssigned %d))\\\n\",SIGNED_(~A),8*(sizeof(~A)));~%"
62 lispname cname cname
))
65 "printf(\"(cl:defvar ~A %S \\\"~A\\\")\\\n\",~A);~%"
68 (c-for-function stream lispname cname
))
70 (c-for-structure stream lispname cname
))
73 "printf(\";; Non hablo Espagnol, Monsieur~%")))))
74 (format stream
"exit(0);~%}~%")))
76 (defun c-constants-extract (filename output-file package
)
77 (with-open-file (f output-file
:direction
:output
)
78 (with-open-file (i filename
:direction
:input
)
79 (let* ((headers (read i
))
80 (definitions (read i
)))
81 (print-c-source f headers definitions package
)))))
83 (defclass grovel-constants-file
(asdf:cl-source-file
)
84 ((package :accessor constants-package
:initarg
:package
)))
86 (defmethod asdf:perform
((op asdf
:compile-op
)
87 (component grovel-constants-file
))
88 ;; we want to generate all our temporary files in the fasl directory
89 ;; because that's where we have write permission. Can't use /tmp;
90 ;; it's insecure (these files will later be owned by root)
91 (let* ((output-file (car (output-files op component
)))
92 (filename (component-pathname component
))
94 (if (typep output-file
'logical-pathname
)
95 (translate-logical-pathname output-file
)
96 (pathname output-file
)))
97 (tmp-c-source (merge-pathnames #p
"foo.c" real-output-file
))
98 (tmp-a-dot-out (merge-pathnames #p
"a.out" real-output-file
))
99 (tmp-constants (merge-pathnames #p
"constants.lisp-temp"
101 (princ (list filename output-file real-output-file
102 tmp-c-source tmp-a-dot-out tmp-constants
))
104 (funcall (intern "C-CONSTANTS-EXTRACT" (find-package "SB-GROVEL"))
105 filename tmp-c-source
(constants-package component
))
107 (= (run-shell-command "gcc ~A -o ~S ~S"
108 (if (sb-ext:posix-getenv
"CFLAGS")
109 (sb-ext:posix-getenv
"CFLAGS")
111 (namestring tmp-a-dot-out
)
112 (namestring tmp-c-source
)) 0)
113 (= (run-shell-command "~A >~A"
114 (namestring tmp-a-dot-out
)
115 (namestring tmp-constants
)) 0)
116 (compile-file tmp-constants
:output-file output-file
))))