Skip site navigation (1)Skip section navigation (2)

  
 
  

home | help
AVCALL(3)		    Library Functions Manual		       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 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-sup-
     ported).

     (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.  How-
	    ever, 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, dou-
	    ble, where `u' indicates `unsigned'). The macros for  functions  re-
	    turning 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  com-
     piled 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 ar-
     guments  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 ex-
     ample,  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  pack-
     age 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  re-
     turn  value.  This is called avcall_call(). 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@ro-
     bots.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.

				  23 July 2017			       AVCALL(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=avcall&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help