toolkit types, constants, and functions. Callback functions to be
passed to the toolkit are also specified here.
-There are some limitations on the C types that can be declared.
-Basic, struct, union, enum and pointer types are allowed, but
-bit-field members are not supported. C function parameters can be
-basic, enum or pointer types. The return type of a C function is the
-same plus @code{void}. Basically, no struct or union argument or
-return types, at the moment.
-
Each top-level form in the C declaration file must look like one of
these:
(struct Name (Member @var{type}) @dots{})
(union Name (Member @var{type}) @dots{})
(enum @i{Name} (Member) @dots{})
-(extern @var{return-type} Name (param1 @var{arg-type}) @dots{})
-(callback @var{return-type} Name (param1 @var{arg-type}) @dots{})
+(extern @var{function-type} Name (param1 @var{arg-type}) @dots{})
+(callback @var{callback-type} Name (param1 @var{callback-arg-type}) @dots{})
@end smallexample
-An enum's @i{@var{Name}} is optional.
+The @code{include} expression includes another @file{.cdecl} file in
+the current @file{.cdecl} file. The string argument is interpreted
+relative to the current file's directory.
+
+@var{any} can be a @var{type} or the word @code{void}.
+
+@var{arg-type} can be any @var{type} @emph{except} anonymous structs
+and unions.
-@var{arg-type} is currently restricted to the following forms. It is
-assumed that a lone @var{Name} is defined as a type on this list:
+@var{function-type} can be any @var{arg-type} or @code{void}.
+
+@var{callback-arg-type} can be any @var{type} @emph{except} struct and
+union types.
+
+@var{callback-type} can be any @var{callback-arg-type} or @code{void}.
+
+@var{type} can look like any of these:
@smallexample
Name
(* @var{any})
(enum Name)
(enum @i{Name} (Member) @dots{})
-@end smallexample
-
-@var{return-type} can be either @var{arg-type} or the word @code{void}.
-
-@var{basics} can be any of the words: @code{char}, @code{uchar},
-@code{short}, @code{ushort}, @code{int}, @code{uint}, @code{long},
-@code{ulong}, @code{float}, or @code{double} (all lowercase).
-
-@var{type} includes structs and unions:
-
-@smallexample
-@var{arg-type}
(struct Name)
(struct @i{Name} (Member @var{type}) @dots{})
(union Name)
(union @i{Name} (Member @var{type}) @dots{})
@end smallexample
-@var{any} is any @var{type} @emph{or} @code{void}.
+@var{Name} should be defined via a @code{typedef} form somewhere in
+the (included) file(s). It does not have to be defined before it is
+referenced. It does not have to be defined @emph{at all} if it is
+only the target of a pointer type.
-The @code{include} expression includes another @file{.cdecl} file in
-the current @file{.cdecl} file. The string argument is interpreted
-relative to the current file's directory.
+@var{basics} can be any of the words: @code{char}, @code{uchar},
+@code{short}, @code{ushort}, @code{int}, @code{uint}, @code{long},
+@code{ulong}, @code{float}, or @code{double} (all lowercase).
-While the informal grammar above allows anonymous structs to be
-specified for argument or member types, they are of little use outside
-top-level, @i{named} struct or union declarations. The peek and poke
-(@code{C->} and @code{C->=}) syntax expects a type name (e.g.
-@code{"GdkEventAny"} or @code{"struct _GdkEventAny"}) before any
-member names.
+While the informal grammar above allows anonymous structs to be member
+types, they are useless outside a named type declaration. The peek
+and poke (@code{C->} and @code{C->=}) syntaxes require a type name
+(e.g. @code{"GdkEventAny"} or @code{"struct _GdkEventAny"}) before
+any member names.
@smallexample
(C-include "prhello")
invoke the trampoline (via @code{#[primitive c-call]}). The
trampoline gets its arguments off the Scheme stack, converts them to C
values, calls the C function, conses a result, and returns it to
-Scheme. As a special case a function returning a pointer type
-expects an extra first argument. If this argument is @code{#f}, the
-return value is discarded. If the argument is an alien, the
-function's return value clobbers the alien's address. This makes it
-easy to grab pointers to toolkit resources without dropping them, or
-avoid unnecessary consing of aliens.
+Scheme.
+
+A function returning a pointer type is treated specially.
+Its trampoline expects an extra (first) argument.
+If the argument is @code{#f}, the return value is ignored.
+If the argument is an alien, the function's return value clobbers the
+alien's address. This makes it easy to grab pointers to toolkit
+resources without dropping them, and to avoid unnecessary consing of
+aliens.
+
+A function returning a struct or union type is treated similarly.
+Its trampoline expects an extra (first) argument.
+If the argument is @code{#f}, the return value is ignored.
+If the argument is an alien, the returned struct or union is copied to
+that address.
+
+Struct and union type parameters of a function are treated similarly.
+The function's trampoline expects an alien argument for each such
+parameter and copies the struct or union from the argument address
+into a local variable. Callbacks currently cannot receive struct or
+union type arguments, though they @emph{can} receive pointer type
+arguments (consing an alien for each).
The @code{alien-function} structures are fasdumpable. The caching
mechanism invalidates the cache when a band is restored, or a
(define (callout-return tos-var ret-var ret-ctype includes)
(let ((ctype (definite-ctype ret-ctype includes)))
(string-append
- (if (ctype/void? ctype)
- (string-append "
- "ret-var"s = unspecific();")
- (string-append "
- "ret-var"s = "(callout-return-converter ctype)" ("ret-var");")) "
+ (cond ((ctype/void? ctype)
+ (string-append "
+ "ret-var"s = unspecific();"))
+ ((or (ctype/struct? ctype) (ctype/union? ctype))
+ (let ((decl (decl-string ret-ctype)))
+ (string-append "
+ "ret-var"s = struct_to_scm (&"ret-var", sizeof("decl"));")))
+ ((ctype/pointer? ctype)
+ (string-append "
+ "ret-var"s = pointer_to_scm ("ret-var");"))
+ ((or (ctype/basic? ctype) (ctype/enum? ctype))
+ (let ((func (basic-scm-converter ctype)))
+ (string-append "
+ "ret-var"s = "func" ("ret-var");")))
+ (else (error "Unexpected callout return type:" ctype ret-ctype))) "
callout_pop ("tos-var");
return ("ret-var"s);")))
((UCHAR USHORT UINT ULONG) "arg_ulong")
((FLOAT DOUBLE) "arg_double")
(else (error "Unexpected parameter type:" arg-ctype))))
+ ((or (ctype/struct? ctype) (ctype/union? ctype))
+ (string-append "*("decl"*) arg_pointer"))
(else (error "Unexpected parameter type:" arg-ctype)))))
-(define (callout-return-converter ctype)
+(define (basic-scm-converter ctype)
;; Returns the name of a C function that converts from the definite
- ;; C type CTYPE to the analogous Scheme object. Note that the
- ;; pointer converter, pointer_to_scm, returns pointers via c-call's
- ;; second argument.
- (cond ((ctype/pointer? ctype) "pointer_to_scm")
- ((ctype/enum? ctype) "ulong_to_scm")
+ ;; C type CTYPE to the analogous Scheme object.
+ (cond ((ctype/enum? ctype) "ulong_to_scm")
((ctype/basic? ctype)
(case ctype
((CHAR SHORT INT LONG) "long_to_scm")
((UCHAR USHORT UINT ULONG) "ulong_to_scm")
((FLOAT DOUBLE) "double_to_scm")
((VOID) #f)
- (else (error "Unexpected return type:" ctype))))
- (else (error "Unexpected return type:" ctype))))
+ (else (error "Unexpected C type:" ctype))))
+ (else (error "Unexpected C type:" ctype))))
(define (callout-return-variable params)
;; Returns a name (string) for a variable that will hold the return
;; Returns a function call that applies the appropriate Scheme
;; constructor to the ARG-CTYPE variable ARG-NAME.
(let ((ctype (definite-ctype arg-ctype includes)))
- (if (ctype/pointer? ctype)
- (string-append "cons_alien((void*)"arg-name")")
- (let ((func (callout-return-converter ctype)))
- (string-append func"("arg-name")")))))
+ (cond ((ctype/pointer? ctype)
+ (string-append "cons_alien((void*)"arg-name")"))
+ ((or (ctype/struct? ctype) (ctype/union? ctype))
+ (error "Unsupported callback argument type:" arg-ctype arg-name))
+ ((or (ctype/basic? ctype) (ctype/enum? ctype))
+ (let ((func (basic-scm-converter ctype)))
+ (string-append func"("arg-name")")))
+ (else
+ (error "Unexpected callback argument type:" arg-ctype arg-name)))))
(define (callback-return-converter ret-type includes)
;; Returns the name of the C function that takes no arguments and
((CHAR SHORT INT LONG) "long_value")
((UCHAR USHORT UINT ULONG) "ulong_value")
((FLOAT DOUBLE) "double_value")
- (else (error "Unexpected return type:" ctype))))
- (else (error "Unexpected return type:" ctype)))))
+ (else (error "Unexpected callback return type:" ctype))))
+ (else (error "Unexpected callback return type:" ctype)))))
\f
;;; Groveler