<HEAD>
<TITLE> AVCALL manual page </TITLE>
</HEAD>
<BODY>
<H1>AVCALL manual page</H1>
<UL>
<LI> <A HREF="#Name">Name</A>
<LI> <A HREF="#Synopsis">Synopsis</A>
<LI> <A HREF="#Description">Description</A>
<LI> <A HREF="#Notes">Notes</A>
<LI> <A HREF="#See also">See also</A>
<LI> <A HREF="#Bugs">Bugs</A>
<LI> <A HREF="#Non-Bugs">Non-Bugs</A>
<LI> <A HREF="#Porting AVCALL">Porting AVCALL</A>
<LI> <A HREF="#Author">Author</A>
<LI> <A HREF="#Acknowledgements">Acknowledgements</A>
</UL>
<P>
<HR>
<A NAME="Name">
<H2>Name</H2>
</A>
avcall - build a C argument list incrementally and call a
C function on it.
<A NAME="Synopsis">
<H2>Synopsis</H2>
</A>
<PRE>
<CODE>#include <avcall.h></CODE>
<CODE>av_alist <VAR>alist</VAR>;</CODE>
<CODE>av_start_<VAR>type</VAR> (<VAR>alist</VAR>, &<VAR>func</VAR>, [[<VAR>return_type</VAR>,] &<VAR>return_value</VAR>]);</CODE>
<CODE>av_<VAR>type</VAR> (<VAR>alist</VAR>, [<VAR>arg_type</VAR>,] <VAR>value</VAR>);</CODE>
<CODE>av_call(<VAR>alist</VAR>);</CODE>
</PRE>
<A NAME="Description">
<H2>Description</H2>
</A>
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.
<P>
Function calling conventions differ considerably on different
machines and <CODE>avcall</CODE> attempts to provide some degree
of isolation from such architecture dependencies.
<P>
The interface is like <A HREF="stdarg(3)"><CODE><B>stdarg</B></CODE></A>(3) in reverse. All of the
macros return 0 for success, < 0 for failure (e.g., argument
list overflow or type-not-supported).
<P>
<OL>
<LI> <CODE>#include <avcall.h></CODE> and declare the argument list
structure <CODE>av_alist <VAR>alist</VAR>;</CODE>
<P>
<LI> Set any special flags. This is architecture and compiler
dependent.
Compiler options that affect passing conventions may need
to be flagged by <CODE>#define</CODE>s before the <CODE>#include <avcall.h></CODE>
statement. However, the <SAMP>configure</SAMP> script should have
determined which <CODE>#define</CODE>s are needed and put them
at the top of <SAMP>avcall.h</SAMP>.
<P>
<LI> 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.
<P>
E.g.,
<PRE>
<CODE>av_start_int (<VAR>alist</VAR>, &<VAR>func</VAR>, &<VAR>int_return</VAR>);</CODE>
<CODE>av_start_double (<VAR>alist</VAR>, &<VAR>func</VAR>, &<VAR>double_return</VAR>);</CODE>
<CODE>av_start_void (<VAR>alist</VAR>, &<VAR>func</VAR>);</CODE>
<CODE>av_start_struct (<VAR>alist</VAR>, &<VAR>func</VAR>, <VAR>struct_type</VAR>, <VAR>splittable</VAR>, &<VAR>struct_return</VAR>);</CODE>
<CODE>av_start_ptr (<VAR>alist</VAR>, &<VAR>func</VAR>, <VAR>pointer_type</VAR>, &<VAR>pointer_return</VAR>);</CODE>
</PRE>
The <VAR>splittable</VAR> flag specifies whether the <VAR>struct_type</VAR> 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 <SAMP>2*sizeof(long)</SAMP>. For structs of size
<= <SAMP>sizeof(long)</SAMP>, splittable is ignored and assumed to be 1.
For structs of size > <SAMP>2*sizeof(long)</SAMP>, splittable is
ignored and assumed to be 0. There are some handy macros
for this:
<PRE>
<CODE>av_word_splittable_1 (<VAR>type1</VAR>)</CODE>
<CODE>av_word_splittable_2 (<VAR>type1</VAR>, <VAR>type2</VAR>)</CODE>
<CODE>av_word_splittable_3 (<VAR>type1</VAR>, <VAR>type2</VAR>, <VAR>type3</VAR>)</CODE>
<CODE>av_word_splittable_4 (<VAR>type1</VAR>, <VAR>type2</VAR>, <VAR>type3</VAR>, <VAR>type4</VAR>)</CODE>
</PRE>
For a struct with three slots
<PRE>
<CODE>struct { <VAR>type1 id1</VAR>; <VAR>type2 id2</VAR>; <VAR>type3 id3</VAR>; }</CODE>
</PRE>
you can specify <VAR>splittable</VAR> as
<CODE>av_word_splittable_3 (<VAR>type1</VAR>, <VAR>type2</VAR>, <VAR>type3</VAR>)</CODE>.
<P>
<LI> 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:
<PRE>
<CODE>av_int (<VAR>alist</VAR>, <VAR>int_value</VAR>);</CODE>
<CODE>av_double (<VAR>alist</VAR>, <VAR>double_value</VAR>);</CODE>
<CODE>av_struct (<VAR>alist</VAR>, <VAR>struct_or_union_type</VAR>, <VAR>struct_value</VAR>);</CODE>
<CODE>av_ptr (<VAR>alist</VAR>, <VAR>pointer_type</VAR>, <VAR>pointer_value</VAR>);</CODE>
</PRE>
<LI> Call the function, set the return value, and tidy up:
<CODE>av_call (<VAR>alist</VAR>);</CODE>
</OL>
<A NAME="Notes">
<H2>Notes</H2>
</A>
<OL>
<LI> Functions whose first declaration is in Kernighan &
Ritchie style (i.e., without a typed argument list) MUST
use default K&R C expression promotions (<CODE>char</CODE> and <CODE>short</CODE> to
<CODE>int</CODE>, <CODE>float</CODE> to <CODE>double</CODE>) 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
<CODE>char</CODE>, <CODE>short</CODE> or <CODE>float</CODE> in K&R C is by an explicit cast:
<CODE>func((char)c,(float)f)</CODE> ). Similarly, some K&R compilers
(such as Sun <SAMP>cc</SAMP> on the sparc) actually return a <CODE>float</CODE> as a
<CODE>double</CODE>.
<P>
Hence, for arguments of functions declared in K&R style
you should use <CODE>av_int()</CODE> and </CODE>av_double()</CODE> rather than
<CODE>av_char()</CODE>, <CODE>av_short()</CODE> or <CODE>av_float()</CODE>. If you use a K&R
compiler, the avcall header files may be able to detect
this and define <CODE>av_float()</CODE>, etc, appropriately, but with
an ANSI compiler there is no way <B>avcall</B> can know how a
function was declared, so you have to correct the argument
types yourself.
<P>
<LI> The explicit type arguments of the <CODE>av_struct()</CODE> and
<CODE>av_ptr()</CODE> 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 <CODE>av_start_<VAR>type</VAR>()</CODE>
and <CODE>av_<VAR>type</VAR>()</CODE> macros may be defined.
<P>
<LI> The macros <CODE>av_start_longlong()</CODE>,
<CODE>av_start_ulonglong()</CODE>, <CODE>av_longlong()</CODE> and
<CODE>av_ulonglong()</CODE> work only if the C compiler has a working
<CODE>long long</CODE> 64-bit integer type.
<P>
<LI> The struct types used in <CODE>av_start_struct()</CODE> and
<CODE>av_struct()</CODE> 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.
<P>
</OL>
<A NAME="See also">
<H2>See also</H2>
</A>
<A HREF="stdarg(3)"><CODE><B>stdarg</B></CODE></A>(3), <A HREF="varargs(3)"><CODE><B>varargs</B></CODE></A>(3).
<A NAME="Bugs">
<H2>Bugs</H2>
</A>
<UL>
<LI>
The current implementations have been tested on a selection
of common cases but there are probably still many
bugs.
<LI>
There are typically built-in limits on the size of the
argument-list, which may also include the size of any
structure arguments.
<LI>
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
<CODE>struct { char a,b,c; }</CODE>
in registers and
<CODE>struct { char a[3]; }</CODE>
in memory, although both types have the same size and the same alignment.
</UL>
<A NAME="Non-Bugs">
<H2>Non-Bugs</H2>
</A>
All information is passed in CPU registers and the stack.
The <CODE><B>avcall</B></CODE> package is therefore multithread-safe.
<A NAME="Porting AVCALL">
<H2>Porting AVCALL</H2>
</A>
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.
<P>
Knowledge about argument passing conventions can be found
in the gcc source, file <SAMP>gcc-2.6.3/config/<VAR>cpu</VAR>/<VAR>cpu</VAR>.h</SAMP>, section
<SAMP>"Stack layout; function entry, exit and calling."</SAMP>
<P>
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 <CODE>__builtin_avcall()</CODE>. 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.
<P>
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.
<P>
<A NAME="Author">
<H2>Author</H2>
</A>
Bill Triggs <Bill.Triggs@inrialpes.fr>, <Bill.Triggs@imag.fr>.
<A NAME="Acknowledgements">
<H2>Acknowledgements</H2>
</A>
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
<CODE>asm()</CODE> extensions to good use. Thanks guys!
<P>
This work was partly supported by EC-ESPRIT Basic Research
Action SECOND.
<P>
<HR>
<ADDRESS>AVCALL manual page<BR>
Bruno Haible <bruno@clisp.org>
</ADDRESS>
<P>
Last modified: 14 January 2001.
</BODY>