r3958: Automatic commit for debian_version_1_2_6-1
[uffi.git] / src / functions.lisp
1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:          function.cl
6 ;;;; Purpose:       UFFI source to C function definitions
7 ;;;; Programmer:    Kevin M. Rosenberg
8 ;;;; Date Started:  Feb 2002
9 ;;;;
10 ;;;; $Id: functions.lisp,v 1.7 2003/02/06 06:54:22 kevin Exp $
11 ;;;;
12 ;;;; This file, part of UFFI, is Copyright (c) 2002 by Kevin M. Rosenberg
13 ;;;;
14 ;;;; UFFI users are granted the rights to distribute and use this software
15 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
16 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
17 ;;;; *************************************************************************
18
19 (declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0)))
20 (in-package :uffi)
21
22 (defun process-function-args (args)
23   (if (null args)
24       #+(or lispworks cmu sbcl scl cormanlisp (and mcl (not openmcl))) nil
25       #+allegro '(:void)
26       #+openmcl (values nil nil)
27
28       ;; args not null
29       #+(or lispworks allegro cmu sbcl scl (and mcl (not openmcl)) cormanlisp)
30       (let (processed)
31         (dolist (arg args)
32           (push (process-one-function-arg arg) processed))
33         (nreverse processed))
34       #+openmcl
35       (let ((processed nil)
36             (params nil))
37         (dolist (arg args)
38           (let ((name (car arg))
39                 (type (convert-from-uffi-type (cadr arg) :routine)))
40             ;;(when (and (listp type) (eq (car type) :address))
41             ;;(setf type :address))
42             (push name params)
43             (push type processed)
44             (push name processed)))
45         (values (nreverse params) (nreverse processed)))
46     ))
47
48 (defun process-one-function-arg (arg)
49   (let ((name (car arg))
50         (type (convert-from-uffi-type (cadr arg) :routine)))
51     #+(or cmu sbcl scl)
52     (list name type :in)
53     #+(or allegro lispworks (and mcl (not openmcl)))
54     (if (and (listp type) (listp (car type)))
55         (append (list name) type)
56       (list name type))
57     #+openmcl
58     (declare (ignore name type))
59     ))    
60
61
62 (defun allegro-convert-return-type (type)
63   (if (and (listp type) (not (listp (car type))))
64       (list type)
65     type))
66
67 ;; name is either a string representing foreign name, or a list
68 ;; of foreign-name as a string and lisp name as a symbol
69 (defmacro def-function (names args &key module returning)
70   #+(or cmu sbcl scl allegro mcl cormanlisp) (declare (ignore module))
71   
72   (let* ((result-type (convert-from-uffi-type returning :return))
73          (function-args (process-function-args args))
74          (foreign-name (if (atom names) names (car names)))
75          (lisp-name (if (atom names) (make-lisp-name names) (cadr names))))
76
77     ;; todo: calling-convention :stdcall for cormanlisp
78     #+allegro
79     `(ff:def-foreign-call (,lisp-name ,foreign-name)
80          ,function-args
81        :returning ,(allegro-convert-return-type result-type)
82        :call-direct t
83        :strings-convert nil)
84     #+(or cmu scl)
85     `(alien:def-alien-routine (,foreign-name ,lisp-name)
86          ,result-type
87        ,@function-args)
88     #+sbcl
89     `(sb-alien:define-alien-routine (,foreign-name ,lisp-name)
90          ,result-type
91        ,@function-args)
92     #+lispworks
93     `(fli:define-foreign-function (,lisp-name ,foreign-name :source)
94          ,function-args
95        ,@(if module (list :module module) (values))
96        :result-type ,result-type
97       :language :ansi-c
98        :calling-convention :cdecl)
99     #+(and mcl (not openmcl))
100     `(eval-when (:compile-toplevel :load-toplevel :execute)
101        (ccl:define-entry-point (,lisp-name ,foreign-name)
102          ,function-args
103          ,result-type))
104     #+openmcl
105     (declare (ignore function-args))
106     #+(and openmcl darwinppc-target)
107     (setf foreign-name (concatenate 'string "_" foreign-name))
108     #+openmcl
109     (multiple-value-bind (params args) (process-function-args args)
110       `(defun ,lisp-name ,params
111          (ccl::external-call ,foreign-name ,@args ,result-type)))
112     #+cormanlisp
113     `(ct:defun-dll ,lisp-name (,function-args)
114        :return-type ,result-type
115        ,@(if module (list :library-name module) (values))
116        :entry-name ,foreign-name
117        :linkage-type ,calling-convention) ; we need :pascal
118     ))
119
120
121 (defun make-lisp-name (name)
122   (let ((converted (substitute #\- #\_ name)))
123      (intern 
124       #+case-sensitive converted
125       #-case-sensitive (string-upcase converted))))
126
127