CALLBACK(3) CALLBACK(3)
NNAAMMEE
callback - closures with variable arguments as first-class
C functions
SSYYNNOOPPSSIISS
##iinncclluuddee <<ccaallllbbaacckk..hh>>
vvooiidd _f_u_n_c_t_i_o_n ((_d_a_t_a,, _a_l_i_s_t))
vvooiidd** _d_a_t_a;;
vvaa__aalliisstt _a_l_i_s_t;;
{{
vvaa__ssttaarrtt___t_y_p_e((_a_l_i_s_t[[,, _r_e_t_u_r_n___t_y_p_e]]));;
_a_r_g == vvaa__aarrgg___t_y_p_e((_a_l_i_s_t[[,, _a_r_g___t_y_p_e]]));;
vvaa__rreettuurrnn___t_y_p_e((_a_l_i_s_t[[[[,, _r_e_t_u_r_n___t_y_p_e]],, _r_e_t_u_r_n___v_a_l_u_e]]));;
}}
_c_a_l_l_b_a_c_k == aalllloocc__ccaallllbbaacckk((_&_f_u_n_c_t_i_o_n,, _d_a_t_a));;
ffrreeee__ccaallllbbaacckk((_c_a_l_l_b_a_c_k));;
iiss__ccaallllbbaacckk((_c_a_l_l_b_a_c_k))
ccaallllbbaacckk__aaddddrreessss((_c_a_l_l_b_a_c_k))
ccaallllbbaacckk__ddaattaa((_c_a_l_l_b_a_c_k))
DDEESSCCRRIIPPTTIIOONN
These functions implement _c_l_o_s_u_r_e_s with variable arguments
as first-class C functions.
Closures as _f_i_r_s_t_-_c_l_a_s_s _C _f_u_n_c_t_i_o_n_s means that they fit
into a function pointer and can be called exactly like any
other C function. Moreover, they can be called with vari-
able arguments and can return variable return values.
_c_a_l_l_b_a_c_k == aalllloocc__ccaallllbbaacckk((_&_f_u_n_c_t_i_o_n,, _d_a_t_a)) allocates a
callback. When _c_a_l_l_b_a_c_k gets called, it arranges to call
_f_u_n_c_t_i_o_n, passing _d_a_t_a as first argument and, as second
argument, the entire sequence of arguments passed to _c_a_l_l_-
_b_a_c_k.
Function calling conventions differ considerably on dif-
ferent machines, therefore the arguments are accessed and
the result value is stored through the same macros as used
by the _v_a_c_a_l_l package, see below.
The callbacks are functions with indefinite extent: _c_a_l_l_-
_b_a_c_k is only deallocated when ffrreeee__ccaallllbbaacckk((_c_a_l_l_b_a_c_k)) is
called.
iiss__ccaallllbbaacckk((_c_a_l_l_b_a_c_k)) checks whether the C function _c_a_l_l_-
_b_a_c_k was produced by a call to _a_l_l_o_c___c_a_l_l_b_a_c_k. If this
returns true, the arguments given to _a_l_l_o_c___c_a_l_l_b_a_c_k can be
retrieved:
ccaallllbbaacckk__aaddddrreessss((_c_a_l_l_b_a_c_k)) returns _&_f_u_n_c_t_i_o_n,
14 January 2001 1
CALLBACK(3) CALLBACK(3)
ccaallllbbaacckk__ddaattaa((_c_a_l_l_b_a_c_k)) returns _d_a_t_a.
VVAACCAALLLL MMAACCRROOSS
Within _f_u_n_c_t_i_o_n, the following macros can be used to walk
through the argument list and specify a return value:
vvaa__ssttaarrtt___t_y_p_e((_a_l_i_s_t[[,, _r_e_t_u_r_n___t_y_p_e]]));;
starts the walk through the argument list and spec-
ifies the return type.
_a_r_g == vvaa__aarrgg___t_y_p_e((_a_l_i_s_t[[,, _a_r_g___t_y_p_e]]));;
fetches the next argument from the argument list.
vvaa__rreettuurrnn___t_y_p_e((_a_l_i_s_t[[[[,, _r_e_t_u_r_n___t_y_p_e]],, _r_e_t_u_r_n___v_a_l_u_e]]));;
ends the walk through the argument list and speci-
fies the return value.
The _t_y_p_e in vvaa__ssttaarrtt___t_y_p_e and vvaa__rreettuurrnn___t_y_p_e shall be one
of vvooiidd, iinntt, uuiinntt, lloonngg, uulloonngg, lloonngglloonngg, uulloonngglloonngg, ddoouu--
bbllee, ssttrruucctt, ppttrr or (for ANSI C calling conventions only)
cchhaarr, sscchhaarr, uucchhaarr, sshhoorrtt, uusshhoorrtt, ffllooaatt, depending on the
class of _r_e_t_u_r_n___t_y_p_e.
The _t_y_p_e specifiers in vvaa__ssttaarrtt___t_y_p_e and vvaa__rreettuurrnn___t_y_p_e
must be the same. The _r_e_t_u_r_n___t_y_p_e specifiers passed to
vvaa__ssttaarrtt___t_y_p_e and vvaa__rreettuurrnn___t_y_p_e must be the same.
The _t_y_p_e in vvaa__aarrgg___t_y_p_e shall be one of iinntt, uuiinntt, lloonngg,
uulloonngg, lloonngglloonngg, uulloonngglloonngg, ddoouubbllee, ssttrruucctt, ppttrr or (for
ANSI C calling conventions only) cchhaarr, sscchhaarr, uucchhaarr,
sshhoorrtt, uusshhoorrtt, ffllooaatt, depending on the class of _a_r_g___t_y_p_e.
In vvaa__ssttaarrtt__ssttrruucctt((_a_l_i_s_t,, _r_e_t_u_r_n___t_y_p_e,, _s_p_l_i_t_t_a_b_l_e));; the
_s_p_l_i_t_t_a_b_l_e flag specifies whether the struct _r_e_t_u_r_n___t_y_p_e
can be returned in registers such that every struct field
fits entirely in a single register. This needs to be spec-
ified for structs of size 2*sizeof(long). For structs of
size <= sizeof(long), _s_p_l_i_t_t_a_b_l_e is ignored and assumed to
be 1. For structs of size > 2*sizeof(long), _s_p_l_i_t_t_a_b_l_e is
ignored and assumed to be 0. There are some handy macros
for this:
vvaa__wwoorrdd__sspplliittttaabbllee__11 ((_t_y_p_e_1))
vvaa__wwoorrdd__sspplliittttaabbllee__22 ((_t_y_p_e_1,, _t_y_p_e_2))
vvaa__wwoorrdd__sspplliittttaabbllee__33 ((_t_y_p_e_1,, _t_y_p_e_2,, _t_y_p_e_3))
vvaa__wwoorrdd__sspplliittttaabbllee__44 ((_t_y_p_e_1,, _t_y_p_e_2,, _t_y_p_e_3,, _t_y_p_e_4))
For a struct with three slots
ssttrruucctt {{ _t_y_p_e_1 _i_d_1;; _t_y_p_e_2 _i_d_2;; _t_y_p_e_3 _i_d_3;; }}
you can specify _s_p_l_i_t_t_a_b_l_e as vvaa__wwoorrdd__sspplliittttaabbllee__33 ((_t_y_p_e_1,,
_t_y_p_e_2,, _t_y_p_e_3)) .
NNOOTTEESS
Functions which want to emulate Kernighan & Ritchie style
14 January 2001 2
CALLBACK(3) CALLBACK(3)
functions (i.e., in ANSI C, functions without a typed
argument list) cannot use the _t_y_p_e values cchhaarr, sscchhaarr,
uucchhaarr, sshhoorrtt, uusshhoorrtt, ffllooaatt. As prescribed by the default
K&R C expression promotions, they have to use iinntt instead
of cchhaarr, sscchhaarr, uucchhaarr, sshhoorrtt, uusshhoorrtt and ddoouubbllee instead of
ffllooaatt.
The macros vvaa__ssttaarrtt__lloonngglloonngg(()), vvaa__ssttaarrtt__uulloonngglloonngg(()),
vvaa__rreettuurrnn__lloonngglloonngg(()), vvaa__rreettuurrnn__uulloonngglloonngg(()),
vvaa__aarrgg__lloonngglloonngg(()) and vvaa__aarrgg__uulloonngglloonngg(()) work only if the
C compiler has a working lloonngg lloonngg 64-bit integer type.
The struct types used in vvaa__ssttaarrtt__ssttrruucctt(()) and vvaa__ssttrruucctt(())
must only contain (signed or unsigned) int, long, long
long or pointer fields. Struct types containing (signed
or unsigned) char, short, float, double or other structs
are not supported.
SSEEEE AALLSSOO
vvaaccaallll(3), ttrraammppoolliinnee(3).
BBUUGGSS
The current implementations have been tested on a selec-
tion of common cases but there are probably still many
bugs.
There are typically built-in limits on the size of the
argument-list, which may also include the size of any
structure arguments.
The decision whether a struct is to be returned in regis-
ters or in memory considers only the struct's size and
alignment. This is inaccurate: for example, gcc on m68k-
next returns ssttrruucctt {{ cchhaarr aa,,bb,,cc;; }} in registers and
ssttrruucctt {{ cchhaarr aa[[33]];; }} in memory, although both types have
the same size and the same alignment.
<<ccaallllbbaacckk..hh>> cannot be included when <<vvaarraarrggss..hh>> or
<<ssttddaarrgg..hh>> is included. (Name clash for vvaa__aalliisstt.)
The argument list can only be walked once.
NNOONN--BBUUGGSS
All information is passed in CPU registers and the stack.
The ccaallllbbaacckk package is therefore multithread-safe.
PPOORRTTIINNGG
Porting ccaallllbbaacckk consists in first porting the vvaaccaallll and
ttrraammppoolliinnee packages, then choosing a CPU register for
passing the closure from ttrraammppoolliinnee to vvaaccaallll. This
14 January 2001 3
CALLBACK(3) CALLBACK(3)
register is normally the register designated by
STATIC_CHAIN_REGNUM in the gcc source, file gcc-2.7.2/con-
fig/_c_p_u/_c_p_u.h.
AAUUTTHHOORR
Bruno Haible <bruno@clisp.org>
AACCKKNNOOWWLLEEDDGGEEMMEENNTTSS
Many ideas were cribbed from the gcc source.
14 January 2001 4