Man Linux: Main Page and Category List

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 function  and  calls
       the  function on it. It significantly reduces the amount of ‘glue’ code
       required for parsers, debuggers, imbedded interpreters, C extensions to
       application   programs   and  other  situations  where  collections  of
       functions need to be called on lists of externally-supplied  arguments.

       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).

       (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  determined
              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, double, where ‘u’ indicates ‘unsigned’). The  macros  for
              functions  returning  structures or pointers require an explicit
              type argument.

       E.g.,

       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  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 sufficient 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 compiler has a working long  long
       64-bit integer type.

       (4)  The  struct  types  used in 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.

SEE ALSO

       stdarg(3), varargs(3).

BUGS

       The current implementations have been tested on a selection  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  registers  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.

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,   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>.

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.

                                14 January 2001