#include <avcall.h>av_alist alist;av_start_type (alist, &func, [[return_type,] &return_value]);av_type (alist, [arg_type,] value);av_call(alist);
Function  calling  conventions differ considerably on different
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.,  argument
list overflow or type-not-supported).
#include  <avcall.h>  and  declare  the argument list
structure av_alist alist;
#defines before the #include <avcall.h>
statement. However, the configure script should have
determined which #defines are needed and put them
at the top of avcall.h.
E.g.,
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_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);
For a struct with three slotsav_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)
struct { type1 id1; type2 id2; type3 id3; }
you can specify splittable as
av_word_splittable_3 (type1, type2, type3).
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);
av_call (alist);
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
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.
av_struct()  and
av_ptr()  macros  are  typically  used  to calculate size,
alignment, and passing conventions.  This may not be  sufficient  for  some  machines  with  unusual  structure and
pointer handling: in this case additional  av_start_type()
and av_type() macros may be defined.
av_start_longlong(),
av_start_ulonglong(), av_longlong()  and
av_ulonglong() work only if the C compiler has a working
long long 64-bit integer type.
av_start_struct() and
av_struct() 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.
stdarg(3), varargs(3).
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.
avcall package is therefore multithread-safe.
Knowledge about argument passing conventions can be found in the gcc source, file gcc-2.6.3/config/cpu/cpu.h, section "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>, <Bill.Triggs@imag.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
Sun3, Sun4  &  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.
Last modified: 14 January 2001.