Of these 10 forms of defcfun, the last two are illegal. They have either the name as a string or a symbol as the only element of a list. According to the documentation, they probably should be legal too. I suggest a change to allow it.
(defcfun "gethostname" :int (name :pointer) (namelen :int))
(defcfun gethostname :int (name :pointer) (namelen :int))
(defcfun ("gethostname" lispgethostname) :int (name :pointer) (namelen :int))
(defcfun (lispgethostname "gethostname") :int (name :pointer) (namelen :int))
(defcfun ("gethostname" :convention :stdcall) :int (name :pointer) (namelen :int))
(defcfun (gethostname :convention :stdcall) :int (name :pointer) (namelen :int))
(defcfun (lispgethostname "gethostname" :convention :stdcall) :int (name :pointer) (namelen :int))
(defcfun ("gethostname" lispgethostname :convention :stdcall) :int (name :pointer) (namelen :int))
;; illegal:
(defcfun ("gethostname") :int (name :pointer) (namelen :int))
;; illegal:
(defcfun (gethostname) :int (name :pointer) (namelen :int))
This is from function.lisp.
;;; The following four functions take care of parsing DEFCFUN's first ;;; argument whose syntax can be one of: ;;; ;;; 1. string ;;; 2. symbol ;;; 3. ( string [symbol] options* ) ;;; 4. ( symbol [string] options* ) ;;; ;;; The string argument denotes the foreign function's name. The ;;; symbol argument is used to name the Lisp function. If one isn't ;;; present, its name is derived from the other. See the user ;;; documentation for an explanation of the derivation rules.
And from the documentation of defcfun. This is a bit more clear, except that keyword parameters normally are optional, and in this case they indeed have default values
From the manual:
name-and-options ::= name | (name &key library calling-convention cconv) name ::= lisp-name [foreign-name] | foreign-name [lisp-name]
This is the lisp-name function
Even if the system here is conformant with the documentation, it would not hurt to allow the last two forms. I suggest to change the first test from (keywordp (second spec)) to (oddp (length spec))
(defun lisp-name (spec &optional varp) (etypecase spec (list (if (keywordp (second spec)) (lisp-name (first spec) varp) (if (symbolp (first spec)) (first spec) (lisp-name (second spec) varp)))) (string (intern (format nil (if varp "*~A*" "~A") (canonicalize-symbol-name-case (substitute #- #_ spec))))) (symbol spec)))
The foreign-option function seems to be ok as it is, as it can handle a list of length one:
(defun foreign-options (spec varp) (let ((opts (if (listp spec) (if (keywordp (second spec)) (cdr spec) (cddr spec)) nil))) (if varp (funcall 'parse-defcvar-options opts) (parse-function-options opts))))
What do you think?
Maybe this patch is useful - I am not yet a master of mercurial:
Tue Sep 8 22:13:56 W. Europe Daylight Time 2009 Johan Ur Riise johan@riise-data.no * Accept defcfun name as single element list
New patches:
[Accept defcfun name as single element list Johan Ur Riise johan@riise-data.no**20090908201356 Ignore-this: 8b4f6bf7d6c7a7f6562289e931861e1d ] hunk ./src/functions.lisp 223
(defun lisp-name (spec &optional varp) (etypecase spec - (list (if (keywordp (second spec)) + (list (if (oddp (length spec)) (lisp-name (first spec) varp) (if (symbolp (first spec)) (first spec)
Context:
[Deprecate groveler clause FLAG in favour of CC-FLAGS. Stelian Ionescu sionescu@cddr.org**20090823121108 Ignore-this: e1537717a9e7356b208d5cd14b34ba50 ] [cffi-allegro: define long long types on 64-bit platforms Luis Oliveira loliveira@common-lisp.net**20090821210052
Patch courtesy of John Fremlin. ] [cffi-tests: fix pointer-to-integer casts in libtest.c Luis Oliveira loliveira@common-lisp.net**20090821205447] [cffi-tests: don't use stdcall #ifndef WIN32 Luis Oliveira loliveira@common-lisp.net**20090821205144] [Also canonicalize search paths in library specs. Stelian Ionescu sionescu@cddr.org**20090809005356 Ignore-this: 86a039c7ebbc757c9934fe99368ae0bb ] [Update manual. Stelian Ionescu sionescu@cddr.org**20090808222834 Ignore-this: 15e832e5220a6ca70722730d81edf283
DEFCFUN & co. now take only :CONVENTION. ] [Whitespace. Stelian Ionescu sionescu@cddr.org**20090808221547 Ignore-this: 18d99969b97b190176e88d9eb24a94ce
On Sep 9, 2009, at 12:38 AM, Johan Ur Riise wrote:
This is the lisp-name function
Even if the system here is conformant with the documentation, it would not hurt to allow the last two forms. I suggest to change the first test from (keywordp (second spec)) to (oddp (length spec))
I'm not sure it was a good idea to allow both ("c-name" lisp-name) and (lisp-name "c-name"). I'm more inclined to deprecate the latter than add yet another special case.
On Wed, 2009-09-09 at 12:03 +0100, Luís Oliveira wrote:
On Sep 9, 2009, at 12:38 AM, Johan Ur Riise wrote:
This is the lisp-name function
Even if the system here is conformant with the documentation, it would not hurt to allow the last two forms. I suggest to change the first test from (keywordp (second spec)) to (oddp (length spec))
I'm not sure it was a good idea to allow both ("c-name" lisp-name) and (lisp-name "c-name"). I'm more inclined to deprecate the latter than add yet another special case.
That is all right, but still ("c-name") by itself in parantheses, with no keywords, produces illegal code (defun nil ...) which made my slime / ccl combo hang. The situation was that I had a keyword parameter for calling convention, then I discovered that I could put that in the define-foreign-library form, leaving a paren with one element for defcfun name.
On Wed, Sep 9, 2009 at 8:34 PM, Johan Ur Riise johan@riise-data.no wrote:
That is all right, but still ("c-name") by itself in parantheses, with no keywords, produces illegal code (defun nil ...) which made my slime / ccl combo hang.
Oh, I didn't realize that. You're right, that's unacceptable. Would signalling an error on the ("c-name") and (lisp-name) cases work for you? (Along with the appropriate documentation fixes.) While I'm at it, unless there are any objections, I might make (lisp-name "c-name") signal a style-warning.