1 (in-package :sb-grovel)
3 ;;;; The macros defined here are called from #:Gconstants.lisp, which was
4 ;;;; generated from constants.lisp by the C compiler as driven by that
5 ;;;; wacky def-to-lisp thing.
7 ;;; (def-foreign-routine ("stat" STAT ) (INTEGER 32) (FILE-NAME
8 ;;; C-CALL:C-STRING) (BUF (* T)) )
10 ;;; I can't help thinking this was originally going to do something a
12 (defmacro define-foreign-routine
13 (&whole it (c-name lisp-name) return-type &rest args)
14 (declare (ignorable c-name lisp-name return-type args))
15 `(define-alien-routine ,@(cdr it)))
17 (define-c-accessor FOO-PORT SOCKADDR-IN (ARRAY (UNSIGNED 8) 2) 2 2)
18 (define-c-accessor SOCKADDR-IN-FAMILY SOCKADDR-IN INTEGER 6 2)
20 ;;; define-c-accessor makes us a setter and a getter for changing
21 ;;; memory at the appropriate offset
23 ;;; (define-c-accessor STAT-ATIME STAT (INTEGER 32) 56 4)
25 (defmacro define-c-accessor (el structure type offset length)
26 (declare (ignore structure))
28 ((eql type (intern "INTEGER"))
29 `(,type ,(* 8 length)))
30 ((and (listp type) (eql (car type) (intern "*"))) ; pointer
31 `(unsigned ,(* 8 length)))
32 ((eql type (intern "C-STRING")) ; c-string as array
34 ((and (listp type) (eql (car type) (intern "ARRAY")))
36 (sap-ref-? (intern (format nil "~ASAP-REF-~A"
37 (if (member (car ty) '(INTEGER SIGNED))
40 (find-package "SB-SYS"))))
41 (labels ((template (before after)
42 `(let* ((addr (+ 8 (logandc1 7 (sb-kernel:get-lisp-obj-address ptr))))
43 (sap (sb-sys:int-sap (the (unsigned-byte 32) (+ addr ,offset)))))
44 (,before (,sap-ref-? sap index) ,after))))
46 ;;(declaim (inline ,el (setf ,el)))
47 (defun ,el (ptr &optional (index 0))
48 (declare (optimize (speed 3)))
50 ,(if (eql type (intern "C-STRING"))
51 `(naturalize-bounded-c-string ptr ,offset ,length)
52 (template 'prog1 nil))))
53 (defconstant ,(intern (format nil "OFFSET-OF-~A" el)) ,offset)
54 (defun (setf ,el) (newval ptr &optional (index 0))
55 (declare (optimize (speed 3)))
57 ,(if (eql type (intern "C-STRING"))
58 `(set-bounded-c-string ptr ,offset ,length newval)
59 (template 'setf 'newval))))))))
62 ;;; make memory allocator for appropriately-sized block of memory, and
63 ;;; a constant to tell us how big it was anyway
64 (defmacro define-c-struct (name size)
65 (labels ((p (x) (intern (concatenate 'string x (symbol-name name))
66 (symbol-package name))))
68 (defun ,(p "ALLOCATE-") () (make-array ,size :initial-element 0
69 :element-type '(unsigned-byte 8)))
70 (defconstant ,(p "SIZE-OF-") ,size)
71 (defun ,(p "FREE-" ) (p) (declare (ignore p)))
72 (defmacro ,(p "WITH-") (var (&rest field-values) &body body)
73 (labels ((field-name (x)
74 (intern (concatenate 'string
75 (symbol-name ',name) "-"
77 ,(symbol-package name))))
78 (append `(let ((,var ,'(,(p "ALLOCATE-")))))
79 (mapcar (lambda (pair)
80 `(setf (,(field-name (car pair)) ,var) ,(cadr pair)))
84 (defun foreign-nullp (c)
85 "C is a pointer to 0?"
86 (= 0 (sb-sys:sap-int (sb-alien:alien-sap c))))
88 ;;; this could be a lot faster if I cared enough to think about it
89 (defun foreign-vector (pointer size length)
90 "Compose a vector of the words found in foreign memory starting at
91 POINTER. Each word is SIZE bytes long; LENGTH gives the number of
92 elements of the returned vector. See also FOREIGN-VECTOR-UNTIL-ZERO"
96 (sb-sys:system-area-pointer
97 (sap-alien pointer (* (sb-alien:unsigned 8))))
99 (sb-alien:cast pointer (* (sb-alien:unsigned 8))))))
100 (result (make-array length :element-type '(unsigned-byte 8))))
101 (loop for i from 0 to (1- length) by size
102 do (setf (aref result i) (sb-alien:deref ptr i)))
105 (defun naturalize-bounded-c-string (pointer offset &optional max-length)
106 "Return the 0-terminated string starting at (+ POINTER OFFSET) with
107 maximum length MAX-LENGTH, as a lisp object."
110 (sb-sys:system-area-pointer
111 (sap-alien (sb-sys:sap+ pointer offset) (* sb-alien:char)))
113 (sap-alien (sb-sys:sap+ (alien-sap pointer) offset) (* sb-alien:char)))))
114 (length (loop for i upfrom 0
115 until (or (and max-length
116 (= i (1- max-length)))
117 (= (sb-alien:deref ptr i) 0))
119 (result (make-string length
120 :element-type 'base-char)))
121 (sb-kernel:copy-from-system-area (alien-sap ptr) 0
122 result (* sb-vm:vector-data-offset
124 (* length sb-vm:n-byte-bits))
127 (defun set-bounded-c-string (pointer offset max-length value)
128 "Set the range from POINTER + OFFSET to at most POINTER + OFFSET +
129 MAX-LENGTH to the string contained in VALUE."
130 (assert (numberp max-length) nil
131 "Structure field must have a grovelable maximum length.")
132 (assert (< (length value) max-length))
135 (sb-sys:system-area-pointer
136 (sap-alien (sb-sys:sap+ pointer offset) (* sb-alien:char)))
138 (sap-alien (sb-sys:sap+ (alien-sap pointer) offset) (* sb-alien:char)))))
139 (length (length value)))
140 (sb-kernel:copy-to-system-area value (* sb-vm:vector-data-offset
143 (* length sb-vm:n-byte-bits))
144 (setf (sb-alien:deref ptr length) 0)