


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


