VACALL(3) VACALL(3)
NNAAMMEE
vacall - C functions called with variable arguments
SSYYNNOOPPSSIISS
##iinncclluuddee <<vvaaccaallll..hh>>
eexxtteerrnn vvooiidd** vvaaccaallll__ffuunnccttiioonn;;
vvooiidd _f_u_n_c_t_i_o_n ((_a_l_i_s_t))
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]]));;
}}
vvaaccaallll__ffuunnccttiioonn == _&_f_u_n_c_t_i_o_n;;
_v_a_l == ((((_r_e_t_u_r_n___t_y_p_e ((**)) (()))) vvaaccaallll)) ((_a_r_g_1,,_a_r_g_2,,_._._.));;
DDEESSCCRRIIPPTTIIOONN
This set of macros permit a C function _f_u_n_c_t_i_o_n to be
called with variable arguments and to return variable
return values. This is much like the vvaarraarrggss(3) facility,
but also allows the return value to be specified at run
time.
Function calling conventions differ considerably on dif-
ferent machines, and _v_a_c_a_l_l attempts to provide some
degree of isolation from such architecture dependencies.
The function that can be called with any number and type
of arguments and which will return any type of return
value is vvaaccaallll. It will do some magic and call the func-
tion stored in the variable vvaaccaallll__ffuunnccttiioonn. If you want
to make more than one use of _v_a_c_a_l_l, use the _t_r_a_m_p_o_l_i_n_e(3)
facility to store _&_f_u_n_c_t_i_o_n into vvaaccaallll__ffuunnccttiioonn just
before calling vvaaccaallll.
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
14 January 2001 1
VACALL(3) VACALL(3)
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
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.
14 January 2001 2
VACALL(3) VACALL(3)
EEXXAAMMPPLLEE
This example, a possible implementation of eexxeeccll(3) on top
of eexxeeccvv(2) using vvaarraarrggss(3),
##iinncclluuddee <<vvaarraarrggss..hh>>
##ddeeffiinnee MMAAXXAARRGGSS 110000
//** eexxeeccll iiss ccaalllleedd bbyy eexxeeccll((ffiillee,, aarrgg11,, aarrgg22,, ......,, ((cchhaarr **))00));; **//
iinntt eexxeeccll ((vvaa__aalliisstt))
vvaa__ddccll
{{
vvaa__lliisstt aapp;;
cchhaarr** ffiillee;;
cchhaarr** aarrggss[[MMAAXXAARRGGSS]];;
iinntt aarrggnnoo == 00;;
vvaa__ssttaarrtt ((aapp));;
ffiillee == vvaa__aarrgg((aapp,, cchhaarr**));;
wwhhiillee ((((aarrggss[[aarrggnnoo]] == vvaa__aarrgg((aapp,, cchhaarr**)))) !!== ((cchhaarr **))00))
aarrggnnoo++++;;
vvaa__eenndd ((aapp));;
rreettuurrnn eexxeeccvv((ffiillee,, aarrggss));;
}}
looks like this using vvaaccaallll(3):
##iinncclluuddee <<vvaaccaallll..hh>>
##ddeeffiinnee MMAAXXAARRGGSS 110000
//** eexxeeccll iiss ccaalllleedd bbyy vvaaccaallll((ffiillee,, aarrgg11,, aarrgg22,, ......,, ((cchhaarr **))00));; **//
vvooiidd eexxeeccll ((aapp))
vvaa__aalliisstt aapp;;
{{
cchhaarr** ffiillee;;
cchhaarr** aarrggss[[MMAAXXAARRGGSS]];;
iinntt aarrggnnoo == 00;;
iinntt rreettvvaall;;
vvaa__ssttaarrtt__iinntt ((aapp));;
ffiillee == vvaa__aarrgg__ppttrr((aapp,, cchhaarr**));;
wwhhiillee ((((aarrggss[[aarrggnnoo]] == vvaa__aarrgg__ppttrr((aapp,, cchhaarr**)))) !!== ((cchhaarr **))00))
aarrggnnoo++++;;
rreettvvaall == eexxeeccvv((ffiillee,, aarrggss));;
vvaa__rreettuurrnn__iinntt ((aapp,, rreettvvaall));;
}}
vvaaccaallll__ffuunnccttiioonn == &&eexxeeccll;;
SSEEEE AALLSSOO
vvaarraarrggss(3), ttrraammppoolliinnee(3), ccaallllbbaacckk(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
14 January 2001 3
VACALL(3) VACALL(3)
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.
<<vvaaccaallll..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.
The use of the global variable vvaaccaallll__ffuunnccttiioonn is not
reentrant. This is fixed in the ccaallllbbaacckk(3) package.
PPOORRTTIINNGG
Knowledge about argument passing conventions can be found
in the gcc source, file gcc-2.6.3/config/_c_p_u/_c_p_u.h, sec-
tion "Stack layout; function entry, exit and calling."
The implementation of varargs for gcc can be found in the
gcc source, files gcc-2.6.3/ginclude/va*.h.
gcc's __builtin_saveregs() function is defined in the gcc
source, file gcc-2.6.3/libgcc2.c.
AAUUTTHHOORR
Bruno Haible <bruno@clisp.org>
AACCKKNNOOWWLLEEDDGGEEMMEENNTTSS
Many ideas and a lot of code were cribbed from the gcc
source.
14 January 2001 4