chiark / gitweb /
gforeign.lisp renamed and updated for CMUCL 19a and glib-2.4
authorespen <espen>
Wed, 27 Oct 2004 14:46:01 +0000 (14:46 +0000)
committerespen <espen>
Wed, 27 Oct 2004 14:46:01 +0000 (14:46 +0000)
glib/ffi.lisp [new file with mode: 0644]

diff --git a/glib/ffi.lisp b/glib/ffi.lisp
new file mode 100644 (file)
index 0000000..6fe93a5
--- /dev/null
@@ -0,0 +1,762 @@
+;; Common Lisp bindings for GTK+ v2.0
+;; Copyright (C) 1999-2001 Espen S. Johnsen <esj@stud.cs.uit.no>
+;;
+;; This library is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU Lesser General Public
+;; License as published by the Free Software Foundation; either
+;; version 2 of the License, or (at your option) any later version.
+;;
+;; This library is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; Lesser General Public License for more details.
+;;
+;; You should have received a copy of the GNU Lesser General Public
+;; License along with this library; if not, write to the Free Software
+;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+;; $Id: ffi.lisp,v 1.1 2004-10-27 14:46:01 espen Exp $
+
+(in-package "GLIB")
+
+;;;; Type methods
+
+(defvar *type-methods* (make-hash-table))
+
+(defun ensure-type-method-fun (fname)
+  (unless (fboundp fname)
+    (setf
+     (symbol-function fname)
+     #'(lambda (type-spec &rest args)
+        (apply
+         (find-applicable-type-method type-spec fname) type-spec args)))))
+
+(defmacro define-type-method-fun (fname lambda-list)
+  (declare (ignore lambda-list))
+  `(defun ,fname (type-spec &rest args)
+     (apply
+      (find-applicable-type-method type-spec ',fname) type-spec args)))
+
+
+(defun ensure-type-name (type)
+  (etypecase type
+    (symbol type)
+    (pcl::class (class-name type))))
+
+(defun add-type-method (type fname function)
+  (push
+   (cons fname function)
+   (gethash (ensure-type-name type) *type-methods*)))
+
+(defun find-type-method (type fname)
+  (cdr (assoc fname (gethash (ensure-type-name type) *type-methods*))))
+
+(defun find-applicable-type-method (type-spec fname &optional (error t))
+  (flet ((find-superclass-method (class)
+          (when (and class (class-finalized-p class))
+;           (unless (class-finalized-p class)
+;             (finalize-inheritance class))
+            (dolist (super (cdr (pcl::class-precedence-list class)))
+              (return-if (find-type-method super fname)))))
+        (find-expanded-type-method (type-spec)
+          (multiple-value-bind (expanded-type-spec expanded-p)
+              (type-expand-1 type-spec)
+            (cond
+             (expanded-p 
+              (find-applicable-type-method expanded-type-spec fname nil))
+             ((neq type-spec t)
+              (find-applicable-type-method t fname nil))))))
+
+    (or
+     (typecase type-spec
+       (pcl::class
+       (or
+        (find-type-method type-spec fname)
+        (find-superclass-method type-spec)))
+       (symbol
+       (or
+        (find-type-method type-spec fname)
+        (find-expanded-type-method type-spec)
+        (find-superclass-method (find-class type-spec nil))))
+       (cons
+       (or
+        (find-type-method (first type-spec) fname)
+        (find-expanded-type-method type-spec)))
+       (t
+       (error "Invalid type specifier ~A" type-spec)))
+     (and
+      error
+      (error
+       "No applicable method for ~A when called with type specifier ~A"
+       fname type-spec)))))
+
+(defmacro deftype-method (fname type lambda-list &body body)
+  `(progn
+     (ensure-type-method-fun ',fname)
+     (add-type-method ',type ',fname #'(lambda ,lambda-list ,@body))
+     ',fname))
+  
+;; To make the compiler happy
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (define-type-method-fun translate-type-spec (type-spec))
+  (define-type-method-fun size-of (type-spec))
+  (define-type-method-fun translate-to-alien (type-spec expr &optional weak-ref))
+  (define-type-method-fun translate-from-alien (type-spec expr &optional weak-ref))
+  (define-type-method-fun cleanup-alien (type-spec sap &otional weak-ref))
+  (define-type-method-fun unreference-alien (type-spec sap)))
+
+
+;;;; 
+
+(defvar *type-function-cache* (make-hash-table :test #'equal))
+
+(defun get-cached-function (type-spec fname)
+  (cdr (assoc fname (gethash type-spec *type-function-cache*))))
+
+(defun set-cached-function (type-spec fname function)
+  (push (cons fname function) (gethash type-spec *type-function-cache*))
+  function)
+  
+
+(defun intern-argument-translator (type-spec)
+  (or
+   (get-cached-function type-spec 'argument-translator)
+   (set-cached-function type-spec 'argument-translator
+    (compile
+     nil
+     `(lambda (object)
+       (declare (ignorable object))
+       ,(translate-to-alien type-spec 'object t))))))
+
+(defun intern-return-value-translator (type-spec)
+  (or
+   (get-cached-function type-spec 'return-value-translator)
+   (set-cached-function type-spec 'return-value-translator
+    (compile
+     nil
+     `(lambda (alien)
+       (declare (ignorable alien))
+       ,(translate-from-alien type-spec 'alien nil))))))
+
+(defun intern-cleanup-function (type-spec)
+  (or
+   (get-cached-function type-spec 'cleanup-function)
+   (set-cached-function type-spec 'cleanup-function
+    (compile
+     nil
+     `(lambda (alien)
+       (declare (ignorable alien))
+       ,(cleanup-alien type-spec 'alien t))))))
+
+
+
+;; Returns a function to write an object of the specified type
+;; to a memory location
+(defun intern-writer-function (type-spec)
+  (or
+   (get-cached-function type-spec 'writer-function)
+   (set-cached-function type-spec 'writer-function
+    (compile
+     nil
+     `(lambda (value sap offset)
+       (declare (ignorable value sap offset))
+       (setf
+        (,(sap-ref-fname type-spec) sap offset)
+        ,(translate-to-alien type-spec 'value nil)))))))
+
+;; Returns a function to read an object of the specified type
+;; from a memory location
+(defun intern-reader-function (type-spec)
+  (or
+   (get-cached-function type-spec 'reader-function)
+   (set-cached-function type-spec 'reader-function
+    (compile
+     nil
+     `(lambda (sap offset)      
+       (declare (ignorable sap offset))
+       ,(translate-from-alien
+         type-spec `(,(sap-ref-fname type-spec) sap offset) t))))))
+
+(defun intern-destroy-function (type-spec)
+  (if (atomic-type-p type-spec)
+      #'(lambda (sap offset)    
+         (declare (ignore sap offset)))
+    (or
+     (get-cached-function type-spec 'destroy-function)
+     (set-cached-function type-spec 'destroy-function
+       (compile
+       nil
+       `(lambda (sap offset)    
+          (declare (ignorable sap offset))
+          ,(unreference-alien
+            type-spec `(,(sap-ref-fname type-spec) sap offset))))))))
+
+
+
+;;;;
+
+(defconstant +bits-per-unit+ 8
+  "Number of bits in an addressable unit (byte)")
+
+;; Sizes of fundamental C types in addressable units
+(defconstant +size-of-short+ 2)
+(defconstant +size-of-int+ 4)
+(defconstant +size-of-long+ 4)
+(defconstant +size-of-sap+ 4)
+(defconstant +size-of-float+ 4)
+(defconstant +size-of-double+ 8)
+
+(defun sap-ref-unsigned (sap offset)
+  (sap-ref-32 sap offset))
+
+(defun sap-ref-signed (sap offset)
+  (signed-sap-ref-32 sap offset))
+
+(defun sap-ref-fname (type-spec)
+  (let ((alien-type-spec (mklist (translate-type-spec type-spec))))
+    (ecase (first alien-type-spec)
+      (unsigned
+       (ecase (second alien-type-spec)
+        (8 'sap-ref-8)
+        (16 'sap-ref-16)
+        (32 'sap-ref-32)
+        (64 'sap-ref-64)))
+      (signed
+       (ecase (second alien-type-spec)
+        (8 'signed-sap-ref-8)
+        (16 'signed-sap-ref-16)
+        (32 'signed-sap-ref-32)
+        (64 'signed-sap-ref-64)))
+      (system-area-pointer 'sap-ref-sap)
+      (single-float 'sap-ref-single)
+      (double-float 'sap-ref-double))))
+
+
+;;;; Foreign function call interface
+
+(defvar *package-prefix* nil)
+
+(defun set-package-prefix (prefix &optional (package *package*))
+  (let ((package (find-package package)))
+    (delete-if #'(lambda (assoc) (eq (car assoc) package)) *package-prefix*)
+    (push (cons package prefix) *package-prefix*))
+  prefix)
+
+(defun package-prefix (&optional (package *package*))
+  (let ((package (find-package package)))
+    (or
+     (cdr (assoc package *package-prefix*))
+     (substitute #\_ #\- (string-downcase (package-name package))))))
+
+(defun find-prefix-package (prefix)
+  (or
+   (car (rassoc (string-downcase prefix) *package-prefix* :test #'string=))
+   (find-package (string-upcase prefix))))
+
+(defmacro use-prefix (prefix &optional (package *package*))
+  `(eval-when (:compile-toplevel :load-toplevel :execute)
+     (set-package-prefix ,prefix ,package)))
+
+
+(defun default-alien-fname (lisp-name)
+  (let* ((lisp-name-string
+         (if (char= (char (the simple-string (string lisp-name)) 0) #\%)
+             (subseq (the simple-string (string lisp-name)) 1)
+           (string lisp-name)))
+        (prefix (package-prefix *package*))
+        (name (substitute #\_ #\- (string-downcase lisp-name-string))))
+    (if (or (not prefix) (string= prefix ""))
+       name
+      (format nil "~A_~A" prefix name))))
+
+(defun default-alien-type-name (type-name)
+  (let ((prefix (package-prefix *package*)))
+    (apply
+     #'concatenate
+     'string
+     (mapcar
+      #'string-capitalize    
+      (cons prefix (split-string (symbol-name type-name) #\-))))))
+
+(defun default-type-name (alien-name)
+  (let ((parts
+        (mapcar
+         #'string-upcase
+         (split-string-if alien-name #'upper-case-p))))
+    (intern
+     (concatenate-strings
+      (rest parts) #\-) (find-prefix-package (first parts)))))
+    
+        
+(defmacro defbinding (name lambda-list return-type-spec &rest docs/args)
+  (multiple-value-bind (lisp-name c-name)
+      (if (atom name)
+         (values name (default-alien-fname name))
+       (values-list name))
+                      
+    (let ((supplied-lambda-list lambda-list)
+         (docs nil)
+         (args nil))
+      (dolist (doc/arg docs/args)
+       (if (stringp doc/arg)
+           (push doc/arg docs)
+         (progn
+           (destructuring-bind (expr type &optional (style :in)) doc/arg
+             (unless (member style '(:in :out :in-out))
+               (error "Bogus argument style ~S in ~S." style doc/arg))
+             (when (and
+                    (not supplied-lambda-list)
+                    (namep expr) (member style '(:in :in-out)))
+               (push expr lambda-list))
+             (push
+              (list (if (namep expr) (make-symbol (string expr)) (gensym)) expr type style) args)))))
+      
+      (%defbinding
+       c-name lisp-name (or supplied-lambda-list (nreverse lambda-list))
+       return-type-spec (reverse docs) (reverse args)))))
+
+#+cmu
+(defun %defbinding (foreign-name lisp-name lambda-list
+                   return-type-spec docs args)
+  (ext:collect ((alien-types) (alien-bindings) (alien-parameters)
+               (alien-values) (alien-deallocators))
+    (dolist (arg args)
+      (destructuring-bind (var expr type-spec style) arg
+       (let ((declaration (translate-type-spec type-spec))
+             (deallocation (cleanup-alien type-spec var t)))
+         (cond
+          ((member style '(:out :in-out))
+           (alien-types `(* ,declaration))
+           (alien-parameters `(addr ,var))
+           (alien-bindings
+            `(,var ,declaration
+              ,@(when (eq style :in-out)
+                  (list (translate-to-alien type-spec expr t)))))
+           (alien-values (translate-from-alien type-spec var nil)))
+         (deallocation
+          (alien-types declaration)
+          (alien-bindings
+           `(,var ,declaration ,(translate-to-alien type-spec expr t)))
+          (alien-parameters var)
+          (alien-deallocators deallocation))
+         (t
+          (alien-types declaration)
+          (alien-parameters (translate-to-alien type-spec expr t)))))))
+
+    (let* ((alien-name (make-symbol (string lisp-name)))
+          (alien-funcall `(alien-funcall ,alien-name ,@(alien-parameters))))
+      `(defun ,lisp-name ,lambda-list
+        ,@docs
+        (declare (optimize (ext:inhibit-warnings 3)))
+        (with-alien ((,alien-name
+                      (function
+                       ,(translate-type-spec return-type-spec)
+                       ,@(alien-types))
+                      :extern ,foreign-name)
+                     ,@(alien-bindings))
+          ,(if return-type-spec
+               `(let ((result
+                       ,(translate-from-alien return-type-spec alien-funcall nil)))
+                  ,@(alien-deallocators)
+                  (values result ,@(alien-values)))
+             `(progn
+                ,alien-funcall
+                ,@(alien-deallocators)
+                (values ,@(alien-values)))))))))
+
+
+(defun mkbinding (name return-type &rest arg-types)
+   (declare (optimize (ext:inhibit-warnings 3)))
+   (let* ((ftype
+          `(function
+            ,@(mapcar #'translate-type-spec (cons return-type arg-types))))
+        (alien
+         (alien::%heap-alien
+          (alien::make-heap-alien-info
+           :type (alien::parse-alien-type ftype)
+           :sap-form (system:foreign-symbol-address name :flavor :code))))
+        (translate-arguments
+         (mapcar #'intern-argument-translator arg-types))
+        (translate-return-value (intern-return-value-translator return-type))
+        (cleanup-arguments (mapcar #'intern-cleanup-function arg-types)))
+        
+    #'(lambda (&rest args)
+       (map-into args #'funcall translate-arguments args)
+       (prog1
+           (funcall
+            translate-return-value (apply #'alien:alien-funcall alien args))
+         (mapc #'funcall cleanup-arguments args)))))
+
+
+(defun type-translateable-p (type-spec)
+  (find-applicable-type-method type-spec 'translate-type-spec nil))
+
+(defun every-type-translateable-p (type-specs)
+  (every #'type-translateable-p type-specs))
+
+(defun mkbinding-late (name return-type &rest arg-types)
+  (if (every-type-translateable-p (cons return-type arg-types))
+      (apply #'mkbinding name return-type arg-types)
+    (let ((binding nil))
+      #'(lambda (&rest args)
+         (cond
+          (binding (apply binding args))
+          ((every-type-translateable-p (cons return-type arg-types))
+           (setq binding (apply #'mkbinding name return-type arg-types))
+           (apply binding args))
+          (t
+           (dolist (type-spec (cons return-type arg-types))
+             (unless (type-translateable-p type-spec)
+               (error "Can't translate type ~A" type-spec)))))))))
+
+  
+
+;;;; Definitons and translations of fundamental types
+
+(deftype long (&optional (min '*) (max '*)) `(integer ,min ,max))
+(deftype unsigned-long (&optional (min '*) (max '*)) `(integer ,min ,max))
+(deftype int (&optional (min '*) (max '*)) `(long ,min ,max))
+(deftype unsigned-int (&optional (min '*) (max '*)) `(unsigned-long ,min ,max))
+(deftype short (&optional (min '*) (max '*)) `(int ,min ,max))
+(deftype unsigned-short (&optional (min '*) (max '*)) `(unsigned-int ,min ,max))
+(deftype signed (&optional (size '*)) `(signed-byte ,size))
+(deftype unsigned (&optional (size '*)) `(signed-byte ,size))
+(deftype char () 'base-char)
+(deftype pointer () 'system-area-pointer)
+(deftype boolean (&optional (size '*))
+  (declare (ignore size))
+  `(member t nil))
+(deftype invalid () nil)
+
+(defun atomic-type-p (type-spec)
+  (or
+   (eq type-spec 'pointer)
+   (not (eq (translate-type-spec type-spec) 'system-area-pointer))))
+
+
+(deftype-method cleanup-alien t (type-spec sap &optional weak-ref)
+  (declare (ignore type-spec sap weak-ref))
+  nil)
+
+
+(deftype-method translate-to-alien integer (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+(deftype-method translate-from-alien integer (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+
+(deftype-method translate-type-spec fixnum (type-spec)
+  (declare (ignore type-spec))
+  (translate-type-spec 'signed))
+
+(deftype-method size-of fixnum (type-spec)
+  (declare (ignore type-spec))
+  (size-of 'signed))
+
+(deftype-method translate-to-alien fixnum (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+(deftype-method translate-from-alien fixnum (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+
+(deftype-method translate-type-spec long (type-spec)
+  (declare (ignore type-spec))
+  `(signed ,(* +bits-per-unit+ +size-of-long+)))
+
+(deftype-method size-of long (type-spec)
+  (declare (ignore type-spec))
+  +size-of-long+)
+
+
+(deftype-method translate-type-spec unsigned-long (type-spec)
+  (declare (ignore type-spec))
+  `(unsigned ,(* +bits-per-unit+ +size-of-long+)))
+
+(deftype-method size-of unsigned-long (type-spec)
+  (declare (ignore type-spec))
+  +size-of-long+)
+
+
+(deftype-method translate-type-spec int (type-spec)
+  (declare (ignore type-spec))
+  `(signed ,(* +bits-per-unit+ +size-of-int+)))
+
+(deftype-method size-of int (type-spec)
+  (declare (ignore type-spec))
+  +size-of-int+)
+
+
+(deftype-method translate-type-spec unsigned-int (type-spec)
+  (declare (ignore type-spec))
+  `(unsigned ,(* +bits-per-unit+ +size-of-int+)))
+
+(deftype-method size-of unsigned-int (type-spec)
+  (declare (ignore type-spec))
+  +size-of-int+)
+
+
+(deftype-method translate-type-spec short (type-spec)
+  (declare (ignore type-spec))
+  `(signed ,(* +bits-per-unit+ +size-of-short+)))
+
+(deftype-method size-of short (type-spec)
+  (declare (ignore type-spec))
+  +size-of-short+)
+
+
+(deftype-method translate-type-spec unsigned-short (type-spec)
+  (declare (ignore type-spec))
+  `(unsigned ,(* +bits-per-unit+ +size-of-short+)))
+
+(deftype-method size-of unsigned-short (type-spec)
+  (declare (ignore type-spec))
+  +size-of-short+)
+
+
+(deftype-method translate-type-spec signed-byte (type-spec)
+  (let ((size (second (mklist (type-expand-to 'signed-byte type-spec)))))
+    `(signed
+      ,(cond
+       ((member size '(nil *)) (* +bits-per-unit+ +size-of-int+))
+       (t size)))))
+
+(deftype-method size-of signed-byte (type-spec)
+  (let ((size (second (mklist (type-expand-to 'signed-byte type-spec)))))
+    (cond
+     ((member size '(nil *)) +size-of-int+)
+     (t (/ size +bits-per-unit+)))))
+
+(deftype-method translate-to-alien signed-byte (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+(deftype-method translate-from-alien signed-byte
+    (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+
+(deftype-method translate-type-spec unsigned-byte (type-spec)
+  (let ((size (second (mklist (type-expand-to 'unsigned-byte type-spec)))))
+    `(signed
+      ,(cond
+       ((member size '(nil *)) (* +bits-per-unit+ +size-of-int+))
+       (t size)))))
+
+(deftype-method size-of unsigned-byte (type-spec)
+  (let ((size (second (mklist (type-expand-to 'unsigned-byte type-spec)))))
+    (cond
+     ((member size '(nil *)) +size-of-int+)
+     (t (/ size +bits-per-unit+)))))
+
+(deftype-method translate-to-alien unsigned-byte (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+(deftype-method translate-from-alien unsigned-byte
+    (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+
+(deftype-method translate-type-spec single-float (type-spec)
+  (declare (ignore type-spec))
+  'single-float)
+
+(deftype-method size-of single-float (type-spec)
+  (declare (ignore type-spec))
+  +size-of-float+)
+
+(deftype-method translate-to-alien single-float (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+(deftype-method translate-from-alien single-float
+    (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+
+(deftype-method translate-type-spec double-float (type-spec)
+  (declare (ignore type-spec))
+  'double-float)
+
+(deftype-method size-of double-float (type-spec)
+  (declare (ignore type-spec))
+  +size-of-double+)
+
+(deftype-method translate-to-alien double-float (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  `(coerce ,number 'double-float))
+
+(deftype-method translate-from-alien double-float
+    (type-spec number &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  number)
+
+
+(deftype-method translate-type-spec base-char (type-spec)
+  (declare (ignore type-spec))
+  `(unsigned ,+bits-per-unit+))
+
+(deftype-method size-of base-char (type-spec)
+  (declare (ignore type-spec))
+  1)
+
+(deftype-method translate-to-alien base-char (type-spec char &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  `(char-code ,char))
+
+(deftype-method translate-from-alien base-char (type-spec code &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  `(code-char ,code))
+
+
+(deftype-method translate-type-spec string (type-spec)
+  (declare (ignore type-spec))
+  'system-area-pointer)
+
+(deftype-method size-of string (type-spec)
+  (declare (ignore type-spec))
+  +size-of-sap+)
+
+(deftype-method translate-to-alien string (type-spec string &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  `(let ((string ,string))
+     ;; Always copy strings to prevent seg fault due to GC
+     (copy-memory
+      (make-pointer (1+ (kernel:get-lisp-obj-address string)))
+      (1+ (length string)))))
+
+(deftype-method translate-from-alien string
+    (type-spec c-string &optional weak-ref)
+  (declare (ignore type-spec))
+  `(let ((c-string ,c-string))
+     (unless (null-pointer-p c-string)
+       (prog1
+          (c-call::%naturalize-c-string c-string)
+        ;,(unless weak-ref `(deallocate-memory c-string))
+        ))))
+
+(deftype-method cleanup-alien string (type-spec c-string &optional weak-ref)
+  (when weak-ref
+    (unreference-alien type-spec c-string)))
+
+(deftype-method unreference-alien string (type-spec c-string)
+  (declare (ignore type-spec))
+  `(let ((c-string ,c-string))
+     (unless (null-pointer-p c-string)
+       (deallocate-memory c-string))))
+
+
+;;; Pathname
+
+(deftype-method translate-type-spec pathname (type-spec)
+  (declare (ignore type-spec))
+  (translate-type-spec 'string))
+
+(deftype-method size-of pathname (type-spec)
+  (declare (ignore type-spec))
+  (size-of 'string))
+
+(deftype-method translate-to-alien pathname (type-spec path &optional weak-ref)
+  (declare (ignore type-spec))
+  (translate-to-alien 'string 
+   `(namestring (translate-logical-pathname ,path)) weak-ref))
+
+(deftype-method translate-from-alien pathname (type-spec c-string &optional weak-ref)
+  (declare (ignore type-spec))
+  `(parse-namestring ,(translate-from-alien 'string c-string weak-ref)))
+
+(deftype-method cleanup-alien pathname (type-spec c-string &optional weak-ref)
+  (declare (ignore type-spec))
+  (cleanup-alien 'string c-string weak-ref))
+
+(deftype-method unreference-alien pathname (type-spec c-string)
+  (declare (ignore type-spec))
+  (unreference-alien 'string c-string))
+  
+
+(deftype-method translate-type-spec boolean (type-spec)
+  (translate-type-spec
+   (cons 'unsigned (cdr (mklist (type-expand-to 'boolean type-spec))))))
+
+(deftype-method size-of boolean (type-spec)
+  (size-of
+   (cons 'unsigned (cdr (mklist (type-expand-to 'boolean type-spec))))))
+
+(deftype-method translate-to-alien boolean (type-spec boolean &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  `(if ,boolean 1 0))
+
+(deftype-method translate-from-alien boolean (type-spec int &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  `(not (zerop ,int)))
+
+
+(deftype-method translate-type-spec or (union-type)
+  (let* ((member-types (cdr (type-expand-to 'or union-type)))
+        (alien-type (translate-type-spec (first member-types))))
+    (dolist (type (cdr member-types))
+      (unless (eq alien-type (translate-type-spec type))
+       (error "No common alien type specifier for union type: ~A" union-type)))
+    alien-type))
+
+(deftype-method size-of or (union-type)
+  (size-of (first (cdr (type-expand-to 'or union-type)))))
+
+(deftype-method translate-to-alien or (union-type-spec expr &optional weak-ref)
+  (destructuring-bind (name &rest type-specs)
+      (type-expand-to 'or union-type-spec)
+    (declare (ignore name))
+    `(let ((value ,expr))
+       (etypecase value
+        ,@(map
+           'list
+             #'(lambda (type-spec)
+                 (list type-spec (translate-to-alien type-spec 'value weak-ref)))
+             type-specs)))))
+
+
+(deftype-method translate-type-spec system-area-pointer (type-spec)
+  (declare (ignore type-spec))
+  'system-area-pointer)
+
+(deftype-method size-of system-area-pointer (type-spec)
+  (declare (ignore type-spec))
+  +size-of-sap+)
+
+(deftype-method translate-to-alien system-area-pointer (type-spec sap &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  sap)
+
+(deftype-method translate-from-alien system-area-pointer
+    (type-spec sap &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  sap)
+
+
+(deftype-method translate-type-spec null (type-spec)
+  (declare (ignore type-spec))
+  'system-area-pointer)
+
+(deftype-method translate-to-alien null (type-spec expr &optional weak-ref)
+  (declare (ignore type-spec expr weak-ref))
+  `(make-pointer 0))
+
+
+(deftype-method translate-type-spec nil (type-spec)
+  (declare (ignore type-spec))
+  'void)
+
+(deftype-method translate-from-alien nil (type-spec expr &optional weak-ref)
+  (declare (ignore type-spec weak-ref))
+  `(progn
+     ,expr
+     (values)))