home *** CD-ROM | disk | FTP | other *** search
- ;; Sample usage: Create lisp defstructs corresponding to C structures:
- (use-package "SLOOP")
- ;; How to: Create a file foo.c which contains just structures
- ;; and possibly some externs.
- ;; cc -E /tmp/foo1.c > /tmp/fo2.c
- ;; ../xbin/strip-ifdef /tmp/fo2.c > /tmp/fo3.c
- ;; then (parse-file "/tmp/fo3.c")
- ;; will return a list of defstructs and appropriate slot offsets.
-
-
- (defun white-space (ch) (member ch '(#\space #\linefeed #\return #\newline #\tab)))
-
- (defvar *eof* (code-char 255))
- (defun delimiter(ch) (or (white-space ch)
- (member ch '(#\, #\; #\{ #\} #\*))))
- (defun next-char (st)
- (let ((char (read-char st nil *eof*)))
-
- (case char
- (#\{ char)
- (
- #\/ (cond ((eql (peek-char nil st nil) #\*)
- (read-char st)
- (sloop when (eql (read-char st) #\*)
- do (cond ((eql (read-char st) #\/ )
- (return-from next-char (next-char st))))))
- (t char)))
- ((#\tab #\linefeed #\return #\newline )
- (cond ((member (peek-char nil st nil) '(#\space #\tab #\linefeed #\return #\newline ))
- (return-from next-char (next-char st))))
- #\space)
- (t char))))
-
- (defun get-token (st &aux tem)
- (sloop while (white-space (peek-char nil st nil))
- do (read-char st))
- (cond ((member (setq tem (peek-char nil st nil)) '(#\, #\; #\* #\{ #\} ))
- (return-from get-token (coerce (list (next-char st)) 'string))))
- (sloop with x = (make-array 10 :element-type 'character :fill-pointer 0
- :adjustable t)
- when (delimiter (setq tem (next-char st)))
- do (cond ((> (length x) 0)
- (or (white-space tem) (unread-char tem st))
- (return x)))
- else
- do
- (cond ((eql tem *eof*) (return *eof*))
- (t (vector-push-extend tem x)))))
- (defvar *parse-list* nil)
- (defvar *structs* nil)
- (defun parse-file (fi &optional *structs*)
- (with-open-file (st fi)
- (let ((*parse-list*
- (sloop while (not (eql *eof* (setq tem (get-token st))))
- collect (intern tem))))
- (print *parse-list*)
- (let ((structs
- (sloop while (setq tem (parse-struct))
- do (push tem *structs*)
- collect tem)))
- (get-sizes fi structs)
- (with-open-file (st "gaz3.lsp")
- (prog1
- (list structs (read st))
- (delete-file "gaz3.lsp")))))))
-
-
-
-
-
- (defparameter *type-alist* '((|short| . signed-short)
- (|unsigned short| . unsigned-short)
- (|char| . signed-char)
- (|unsigned char| . unsigned-char)
- (|int| . fixnum)
- (|long| . fixnum)
- (|object| . t)))
-
-
- (defun parse-type( &aux top)
- (setq top (pop *parse-list*))
- (cond ((member top '(|unsigned| |signed|))
- (push (intern (format nil "~a-~a" (pop *parse-list*))) *parse-list*)
- (parse-type))
- ((eq '* (car *parse-list*)) (pop *parse-list*) 'fixnum)
- ((eq top '|struct|)
- (prog1
- (cond ((car (member (car *parse-list*) *STRUCTS* :key 'cadr)))
- (t (error "unknown struct ~a " (car *parse-list*))))
- (pop *parse-list*)
- ))
- ((cdr (assoc top *type-alist*)))
- (t (error "unknown type ~a " top))))
- (defun expect (x) (or (eql (car *parse-list*) x)
- (error "expected ~a at beginning of ~s" x *parse-list*))
- (pop *parse-list*))
- (defun parse-field ( &aux tem)
- (cond ((eql (car *parse-list*) '|}|)
- (pop *parse-list*)
- (expect '|;|)
- nil)
- (t
- (let ((type (parse-type)))
-
- (sloop until (eql (setq tem (pop *parse-list*)) '|;|)
- append (get-field tem type)
-
- do (or (eq (car *parse-list*) '|;|) (expect '|,|)))))))
- (deftype pointer () `(integer ,most-negative-fixnum most-positive-fixnum))
- (defun get-field (name type)
- (cond ((eq name '|*|)(get-field (pop *parse-list*) 'pointer))
- ((and (consp type) (eq (car type) 'defstruct))
- (sloop for w in (cddr type)
- append (get-field
- (intern (format nil "~a.~a" name (car w)))
- (fourth w))))
- (t
- `((,name ,(if (eq type t) nil 0) :type ,type)))))
-
- (defun parse-struct ()
- (cond ((null *parse-list*) (return-from parse-struct nil)))
- (cond ((not (eq (car *parse-list*) '|struct|))
- (sloop until (eq (pop *parse-list*) '|;|))
- (return-from parse-struct (parse-struct))))
- (expect '|struct|)
- (let* ((name (prog1 (pop *parse-list*)(expect '|{|))))
- `(defstruct ,name ,@
- (sloop while (setq tem (parse-field))
- append tem))))
-
- (defun printf (st x &rest y)
- (format st "~%printf(\"~a\"" x)
- (sloop for w in y do (princ "," st) (princ y st))
- (princ ");" st))
-
- (defun get-sizes (file structs)
- (with-open-file (st "gaz0" :direction :output)
- (sloop for i from 1
- for u in structs
- do (format st "struct ~a SSS~a;~%" (second u) i))
- (format st "~%main() {~%")
- (printf st "(")
- (sloop for i from 1
- for u in structs
- do
- (printf st (format nil "(|~a| " (second u)))
- (sloop for w in (cddr u)
- do
- (printf st " %d "
- (format nil "(char *)&SSS~a.~a - (char *)&SSS~a"
- i (car w) i)))
- (printf st ")"))
- (printf st ")")
- (princ " ;}" st))
- (system
- (format nil "cat ~a gaz0 > tmpx.c ; cc tmpx.c -o tmpx ; (tmpx > gaz3.lsp) ; rm -f gaz0" file)))
-
-