[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: define-foreign & C structs



here is my version of the same thing ---- doesnt support the "print"
"cref" and "typename" operations as derek's does, but allows structure
components that are arrays. also, appears to do more syntax error
checking.

enjoy!

'dorab

(herald cstruct)

;;; Copyleft (l) 1989, Dorab Patel <dorab@cs.ucla.edu>

;;; make a T (bytev) version of a C structure
;;; typically called as
;;;
;;; (define-cstruct struct-name (c-type component-name opt-array)...)
;;;
;;; for example ...
;;;
;;; (define-cstruct foo (int x) (char y 4) (short z))
;;;
;;; which defines
;;;
;;; (lset sym (make-foo)) ==> returns a 10 byte bytev
;;; (foo-x sym) ==> accesses the x component (settable)
;;; (foo-y sym i) ==> accesses the i'th element of the y component (settable)
;;; (foo-z sym) ==> accesses the z component (settable)
;;;
;;;
;;; the C types that can be specified are:
;;;
;;; int     30 bits signed
;;; long    30 bits signed
;;; ulong   32 bits unsigned     ; supported via local UCLA hack
;;; short   16 bits signed
;;; ushort  16 bits unsigned
;;; char     8 bits signed
;;; uchar    8 bits unsigned


(define-syntax (define-cstruct structName . componentList)
  (labels (
	   ;; check the type of the argument
	   ((badtype? x)
	    (not (and (pair? x)
		      (let ((y (car x)))
			   (if (pair? y)
			       (let ((l (length y)))
				    (or (fx= l 2) (fx= l 3)))
			       '#f)))))
	   
	   ;; check to see if there is a third value and if
	   ;; the array length seems reasonable
	   ;; returns array length if ok, else 0
	   ((ArrayLength x)
	    (if (pair? (cddr x))
		(let ((y (caddr x)))
		      (if (and (fixnum? y)
			       (fx> y 0))
			  y
			  0))
		0))

	   ;; returns the total length of the structure (bytev)
	   ;; and the list of definitions of the accessors
	   ((makeDefList sName cList)
	    (iterate loop
		     ((componentType (caar cList))
		      (componentName (cadar cList))
		      (componentArrayLength (ArrayLength (car cList)))
		      (structSize 0)	; current offset into structure
		      (defList nil)	; definition list so far
		      (componentNames nil)	; list of component names so far
		      (rest (cdr cList)))	; input still to be looked at
		     (receive-values
		      (lambda (componentAccessor componentSize)
			      (let* ((isArray? (not (fixnum-zero? componentArrayLength)))
				     (totalSize (fx+ structSize 
						     (if isArray?
							 (fx* componentArrayLength componentSize)
							 componentSize)))
				     (thisComponentDef
				      `(define ,(concatenate-symbol
						 sName
						 '-
						 componentName)
					       (operation (lambda (x
								   ,@(if isArray?
									 '(i) nil))
								  (,componentAccessor
								   x
								   ,(if isArray?
									`(fx+ (fx* i ,componentSize) ,structSize)
									structSize)))
							  ((setter self)
							   (lambda (x ,@(if isArray?
									    '(i)
									    nil)
								      val)
								   (set (,componentAccessor
									 x
									 ,(if isArray?
									      `(fx+ (fx* i ,componentSize) ,structSize) structSize))
									val)))))))
				    ;; the order of these cond clauses is IMPORTANT
				    (cond ((mem? equiv? componentName componentNames)
					   (syntax-error
					    "define-cstruct: Multiple components ~a in structure ~a~%"
					    componentName
					    sName))
					  ((null? rest)
					   (return totalSize
						   (cons thisComponentDef defList)))
					  ((badtype? rest)
					   (syntax-error
					    "define-cstruct: Bad component specification in structure ~a~%"
					    sName))
					  (else (loop (caar rest)
						      (cadar rest)
						      (ArrayLength (car rest))
						      totalSize
						      (cons thisComponentDef defList)
						      (cons componentName componentNames)
						      (cdr rest))))))
		      ;; return componentAccessor and componentSize
		      ;; based on componentType
		      (lambda ()
			      (case componentType
				    ((int long)
				     (return 'bref-32 4))
				    ((ulong)
				     (return 'bref-32-u 4))
				    ((short)
				     (return 'bref-16-s 2))
				    ((ushort)
				     (return 'bref-16-u 2))
				    ((char)
				     (return 'bref-8-s 1))
				    ((uchar)
				     (return 'bref-8-u 1))
				    (else (syntax-error
					   "define-cstruct: Unknown type: ~a in structure ~a~%"
					   componentType sName)))))))
	   
	   )
	  
	  ;; beginning of define-cstruct
	  
	  (cond ((not (atom? structName))
		 (syntax-error
		  "define-cstruct: Struct name ~a must be atom~%"
		  structName))
		((badtype? componentList)
		 (syntax-error
		  "define-cstruct: Bad component specification in structure ~a~%"
		  structName))
		(else (receive-values
		       (lambda (totalLength defList)
			       `(block (define
					(,(concatenate-symbol 'make-
							      structName))
					(make-bytev ,totalLength))
				       ,@defList))
		       (lambda () (makeDefList structName componentList)))))))