CALLBACK(3) CALLBACK(3) NNAAMMEE callback - closures with variable arguments as first-class C functions SSYYNNOOPPSSIISS ##iinncclluuddee <> 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. <> cannot be included when <> or <> 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 AACCKKNNOOWWLLEEDDGGEEMMEENNTTSS Many ideas were cribbed from the gcc source. 14 January 2001 4