home *** CD-ROM | disk | FTP | other *** search
- #|
- (in-package "FFI")
- (defun ffi::lookup-foreign-function (name description)
- (let ((args (list name description)))
- (format *trace-output* "~&Calling Lookup with ~S.~%" args)
- #'(lambda (&rest rest)
- (format *trace-output* "~&Calling Looked-up(~S) with ~S.~%" args rest)
- nil)))
- (defconstant ffi::ff-flag-alloca (ash 1 0))
- (defconstant ffi::ff-language-c (ash 1 9))
- (defconstant ffi::ff-flag-out (ash 1 4))
- (def-call-out OpenLibrary
- (:name "OpenLibrary")
- (:language :c) ;every integral converted to (U)LONG
- ;;(:library "exec.library")
- (:arguments
- (libname c-string :in :alloca :a0)
- (version uint32 :in :none :d0))
- (:return-type c-pointer :none :d0))
- (def-call-out ReadDOS
- (:name "Read")
- (:language :c)
- (:arguments
- (file c-pointer :in :none :d0)
- (buffer c-string :out :none :d1) ;inexpressible
- (length sint32 :in :none :d2))
- (:return-type sint32 :none :d0))
- |#
-
- (in-package "AFFI")
- #|
- (macroexpand-1 '
- (def-affi-call-out OpenLibrary
- (:name "OpenLibrary")
- (:language :c) ;every integral converted to (U)LONG
- (:library "exec.library") (:offset -552)
- (:arguments
- (libname :c-string :in :alloca :a1)
- (version :ulong :in :none :d0))
- (:return-type :c-pointer :none :d0))
- )
- (defflibfun 'OPENLIBRARY 'SYSBASE -552 #x1A '* 'string 4)
- ;; Read :io c-pointer :none :out
- ;; OpenLibrary string c-string :alloca :in
- ;; Write :io c-pointer :none :in ; :io to avoid copying
- ;; OpenWindow * c-pointer :none :in ; disable string arg?
- |#
-
- (defun error-bad-spec (whole &optional reason)
- (error "Bad FFI specification: ~S" whole))
-
- (defun parse-ffi-type (argspec whole)
- (unless (and (consp argspec)
- (symbolp (first argspec)))
- (error-bad-spec whole))
- (or
- (case (second argspec) ; c-type
- (:boolean 0) ; not implemented in AFFI.D as argument
- (:sint8 -1) ;add :char ?
- ((:uint8 :uchar) 1)
- ((:sint16 :short) -2)
- ((:uint16 :ushort) 2)
- ((:sint32 :long) -4)
- ((:uint32 :ulong) 4)
- ((:c-pointer :c-string) ;TODO revisit (dependency on allocation?)
- (if (eq :return-type (first argspec))
- (if (eq (second argspec) :c-string) 'string '*)
- (case (third argspec) ; param-mode
- (:none '*)
- (:in (if (eq (second argspec) :c-string) 'string '*))
- ((:out :in-out) :io))))
- ((:io string *) (second argspec))) ; special pass-through
- (error-bad-spec whole)))
-
- (defun parse-options (options keywords whole)
- (reverse options))
-
- (defun calc-reg-mask (regs mask)
- (if (null regs) mask
- (calc-reg-mask
- (rest regs)
- (logior
- (ash mask 4)
- (1+ (position
- (first regs)
- '(:D0 :D1 :D2 :D3 :D4 :D5 :D6 :D7
- :A0 :A1 :A2 :A3 :A4 :A5 :A6)
- :test #'eq))))))
-
- (defun calc-register-mask (regs)
- (labels
- ((calc (regs accu)
- (if (null regs) accu
- (calc (rest regs)
- (logior
- (ash accu 4)
- (1+ (let ((reg (first regs))
- (list '(:D0 :D1 :D2 :D3 :D4 :D5 :D6 :D7
- :A0 :A1 :A2 :A3 :A4 :A5 :A6)))
- (if (keywordp reg)
- (position reg list :test #'eq)
- (position (symbol-name reg) list :test #'string-equal :key #'symbol-name)))))))))
- (calc (reverse regs) 0)))
-
- (defmacro def-affi-call-out (&whole whole name &rest options)
- (let* ((alist (parse-options options '(:name :library :offset :language :arguments :return-type) whole))
- (library (first (check-library-name (second (assoc :library alist)))))
- (offset (second (assoc :offset alist)))
- (mask (calc-reg-mask (reverse (mapcar #'fifth (rest (assoc :arguments alist)))) 0))
- (rtype (parse-ffi-type (assoc :return-type alist) whole))
- (c-args (mapcar #'(lambda (spec) (list 'quote (parse-ffi-type spec whole)))
- (rest (assoc :arguments alist))))
- )
- ;; declaim special?
- `(defflibfun ',name ',library ,offset ,mask ',rtype ,@c-args)))
-
-