


AVCALL(3)                                               AVCALL(3)


NAME
       avcall  - build a C argument list incrementally and call a
       C function on it.

SYNOPSIS
       #include <avcall.h>

       av_alist alist;

       av_start_type(alist, &func [[, return_type], &return_value
       ]);

       av_type(alist, [arg_type,] value);

       av_call(alist);

DESCRIPTION
       This  set  of macros builds an argument list for a C func-
       tion and  calls  the  function  on  it.  It  significantly
       reduces  the  amount  of `glue' code required for parsers,
       debuggers, imbedded interpreters, C extensions to applica-
       tion  programs  and  other situations where collections of
       functions need to be called on  lists  of  externally-sup-
       plied arguments.

       Function  calling  conventions differ considerably on dif-
       ferent machines and avcall attempts to provide some degree
       of isolation from such architecture dependencies.

       The  interface  is  like  stdarg(3) in reverse. All of the
       macros return 0 for success, < 0 for failure (e.g.,  argu-
       ment list overflow or type-not-supported).

       (1)    #include <avcall.h>
              and declare the argument list structure
              av_alist alist;

       (2)    Set  any  special  flags.  This is architecture and
              compiler dependent.  Compiler options  that  affect
              passing  conventions  may  need  to  be  flagged by
              #defines before the #include <avcall.h>  statement.
              However,  the  configure  script should have deter-
              mined which #defines are needed and put them at the
              top of avcall.h.

       (3)    Initialize  the alist with the function address and
              return value pointer (if any). There is a  separate
              macro   for   each  simple  return  type  ([u]char,
              [u]short, [u]int, [u]long, [u]longlong, float, dou-
              ble,  where  `u'  indicates `unsigned'). The macros
              for  functions  returning  structures  or  pointers
              require an explicit type argument.

       E.g.,



                         25 October 1997                        1





AVCALL(3)                                               AVCALL(3)


       av_start_int (alist, &func, &int_return);

       av_start_double (alist, &func, &double_return);

       av_start_void (alist, &func);

       av_start_struct (alist, &func, struct_type, splittable,
                        &struct_return);

       av_start_ptr (alist, &func, pointer_type,
                     &pointer_return);

       The  splittable flag specifies whether the struct_type can
       be returned in registers such that every struct field fits
       entirely  in a single register. This needs to be specified
       for structs of size 2*sizeof(long). For structs of size <=
       sizeof(long),  splittable  is ignored and assumed to be 1.
       For  structs  of  size  >  2*sizeof(long),  splittable  is
       ignored  and  assumed to be 0. There are some handy macros
       for this:
       av_word_splittable_1 (type1)
       av_word_splittable_2 (type1, type2)
       av_word_splittable_3 (type1, type2, type3)
       av_word_splittable_4 (type1, type2, type3, type4)
       For a struct with three slots
       struct { type1 id1; type2 id2; type3 id3; }
       you can specify splittable as av_word_splittable_3 (type1,
       type2, type3) .

       (4)    Push  the  arguments on to the list in order. Again
              there is a macro for each simple built-in type, and
              the  macros  for  structure  and  pointer arguments
              require an extra type argument:

       av_int (alist, int_value);

       av_double (alist, double_value);

       av_struct (alist, struct_or_union_type, struct_value);

       av_ptr (alist, pointer_type, pointer_value);

       (5)    Call the function, set the return value,  and  tidy
              up:

       av_call (alist);


NOTES
       (1)  Functions  whose  first declaration is in Kernighan &
       Ritchie style (i.e., without a typed argument  list)  MUST
       use default K&R C expression promotions (char and short to
       int, float to double) whether they are compiled by  a  K&R
       or  an  ANSI compiler, because the true argument types may



                         25 October 1997                        2





AVCALL(3)                                               AVCALL(3)


       not be known at the call point. Such  functions  typically
       back-convert  their  arguments  to  the  declared types on
       function entry. (In fact, the only  way  to  pass  a  true
       char,  short  or  float  in  K&R C is by an explicit cast:
       func((char)c,(float)f) ).  Similarly, some  K&R  compilers
       (such as Sun cc on the sparc) actually return a float as a
       double.

       Hence, for arguments of functions declared  in  K&R  style
       you  should  use  av_int()  and  av_double()  rather  than
       av_char(), av_short() or av_float().  If  you  use  a  K&R
       compiler,  the  avcall  header files may be able to detect
       this and define av_float(), etc, appropriately,  but  with
       an  ANSI  compiler  there  is no way avcall can know how a
       function was declared, so you have to correct the argument
       types yourself.

       (2)  The  explicit  type  arguments of the av_struct() and
       av_ptr() macros are  typically  used  to  calculate  size,
       alignment,  and passing conventions.  This may not be suf-
       ficient for  some  machines  with  unusual  structure  and
       pointer  handling: in this case additional av_start_type()
       and av_type() macros may be defined.

       (3) The macros av_start_longlong(),  av_start_ulonglong(),
       av_longlong()  and  av_ulonglong() work only if the C com-
       piler has a working long long 64-bit integer type.


SEE ALSO
       stdarg(3), varargs(3).


BUGS
       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  struct  {  char  a,b,c;  } in registers and
       struct { char a[3]; } in memory, although both types  have
       the same size and the same alignment.


NON-BUGS
       All  information is passed in CPU registers and the stack.
       The avcall package is therefore multithread-safe.




                         25 October 1997                        3





AVCALL(3)                                               AVCALL(3)


PORTING AVCALL
       Ports, bug-fixes, and suggestions are  most  welcome.  The
       macros  required  for  argument pushing are pretty grungy,
       but it does seem to be possible to port avcall to a  range
       of  machines. Ports to non-standard or non-32-bit machines
       are especially welcome so we can sort  the  interface  out
       before it's too late.

       Knowledge  about argument passing conventions can be found
       in the gcc source, file  gcc-2.6.3/config/cpu/cpu.h,  sec-
       tion "Stack layout; function entry, exit and calling."

       Some  of  the grunge is usually handled by a C or assembly
       level glue routine that  actually  pushes  the  arguments,
       calls  the function and unpacks any return value.  This is
       called __builtin_avcall(). A precompiled assembler version
       for people without gcc is also made available. The routine
       should ideally have flags for the passing  conventions  of
       other compilers.

       Many  of  the  current routines waste a lot of stack space
       and generally do hairy things to stack frames - a bit more
       assembly code would probably help things along quite a bit
       here.


AUTHOR
       Bill Triggs <Bill.Triggs@inrialpes.fr>.


ACKNOWLEDGEMENTS
       Some initial ideas were stolen from the C interface to the
       Zelk extensions to Oliver Laumann's Elk scheme interpreter
       by J.P.Lewis, NEC  C&C  Research,  <zilla@ccrl.nj.nec.com>
       (for    Sun4    &    SGI),    and    Roy    Featherstone's
       <roy@robots.oxford.ac.uk> personal C interface library for
       Sun[34]  &  SGI.   I  also looked at the machine-dependent
       parts of the GCC and GDB distributions, and  put  the  gcc
       asm() extensions to good use. Thanks guys!

       This work was partly supported by EC-ESPRIT Basic Research
       Action SECOND.















                         25 October 1997                        4


