<HEAD> <TITLE> VACALL manual page </TITLE> </HEAD> <BODY> <H1>VACALL 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="#Example">Example</A> <LI> <A HREF="#See also">See also</A> <LI> <A HREF="#Bugs">Bugs</A> <LI> <A HREF="#Porting">Porting</A> <LI> <A HREF="#Author">Author</A> <LI> <A HREF="#Acknowledgements">Acknowledgements</A> </UL> <P> <HR> <A NAME="Name"> <H2>Name</H2> </A> vacall - C functions called with variable arguments <A NAME="Synopsis"> <H2>Synopsis</H2> </A> <PRE> <CODE>#include <vacall.h></CODE> </PRE> <P> <PRE> <CODE>extern void* vacall_function;</CODE> </PRE> <P> <PRE> <CODE>void <VAR>function</VAR> (<VAR>alist</VAR>)</CODE> <CODE> va_alist <VAR>alist</VAR>;</CODE> <CODE>{</CODE> <CODE> va_start_<VAR>type</VAR>(<VAR>alist</VAR>[, <VAR>return_type</VAR>]);</CODE> <CODE> arg = va_arg_<VAR>type</VAR>(<VAR>alist</VAR>[, <VAR>arg_type</VAR>]);</CODE> <CODE> va_return_<VAR>type</VAR>(<VAR>alist</VAR>[[, <VAR>return_type</VAR>], <VAR>return_value</VAR>]);</CODE> <CODE>}</CODE> </PRE> <P> <PRE> <CODE>vacall_function = <VAR>&function</VAR>;</CODE> </PRE> <P> <PRE> <CODE><VAR>val</VAR> = ((<VAR>return_type</VAR> (*) ()) vacall) (<VAR>arg1</VAR>,<VAR>arg2</VAR>,<VAR>...</VAR>);</CODE> </PRE> <A NAME="Description"> <H2>Description</H2> </A> This set of macros permit a C function <VAR>function</VAR> to be called with variable arguments and to return variable return values. This is much like the <A HREF="varargs(3)"><CODE><B>varargs</B></CODE></A>(3) facility, but also allows the return value to be specified at run time. <P> Function calling conventions differ considerably on different machines, and <SAMP>vacall</SAMP> attempts to provide some degree of isolation from such architecture dependencies. <P> The function that can be called with any number and type of arguments and which will return any type of return value is <CODE>vacall</CODE>. It will do some magic and call the function stored in the variable <CODE>vacall_function</CODE>. If you want to make more than one use of <SAMP>vacall</SAMP>, use the <A HREF="trampoline(3)"><CODE><B>trampoline</B></CODE></A>(3) facility to store <CODE><VAR>&function</VAR></CODE> into <CODE>vacall_function</CODE> just before calling <CODE>vacall</CODE>. <P> Within <VAR>function</VAR>, the following macros can be used to walk through the argument list and specify a return value: <P> <PRE> <CODE>va_start_<VAR>type</VAR>(<VAR>alist</VAR>[, <VAR>return_type</VAR>]);</CODE> </PRE> starts the walk through the argument list and specifies the return type. <P> <PRE> <CODE>arg = va_arg_<VAR>type</VAR>(<VAR>alist</VAR>[, <VAR>arg_type</VAR>]);</CODE> </PRE> fetches the next argument from the argument list. <P> <PRE> <CODE>va_return_<VAR>type</VAR>(<VAR>alist</VAR>[[, <VAR>return_type</VAR>], <VAR>return_value</VAR>]);</CODE> </PRE> ends the walk through the argument list and specifies the return value. <P> The <VAR>type</VAR> in <CODE>va_start_<VAR>type</VAR></CODE> and <CODE>va_return_<VAR>type</VAR></CODE> shall be one of <CODE>void</CODE>, <CODE>int</CODE>, <CODE>uint</CODE>, <CODE>long</CODE>, <CODE>ulong</CODE>, <CODE>longlong</CODE>, <CODE>ulonglong</CODE>, <CODE>double</CODE>, <CODE>struct</CODE>, <CODE>ptr</CODE> or (for ANSI C calling conventions only) <CODE>char</CODE>, <CODE>schar</CODE>, <CODE>uchar</CODE>, <CODE>short</CODE>, <CODE>ushort</CODE>, <CODE>float</CODE>, depending on the class of <VAR>return_type</VAR>. <P> The <VAR>type</VAR> specifiers in <CODE>va_start_<VAR>type</VAR></CODE> and <CODE>va_return_<VAR>type</VAR></CODE> must be the same. The <VAR>return_type</VAR> specifiers passed to <CODE>va_start_<VAR>type</VAR></CODE> and <CODE>va_return_<VAR>type</VAR></CODE> must be the same. <P> The <VAR>type</VAR> in <CODE>va_arg_<VAR>type</VAR></CODE> shall be one of <CODE>int</CODE>, <CODE>uint</CODE>, <CODE>long</CODE>, <CODE>ulong</CODE>, <CODE>longlong</CODE>, <CODE>ulonglong</CODE>, <CODE>double</CODE>, <CODE>struct</CODE>, <CODE>ptr</CODE> or (for ANSI C calling conventions only) <CODE>char</CODE>, <CODE>schar</CODE>, <CODE>uchar</CODE>, <CODE>short</CODE>, <CODE>ushort</CODE>, <CODE>float</CODE>, depending on the class of <VAR>arg_type</VAR>. <P> In <CODE>va_start_struct(<VAR>alist</VAR>, <VAR>return_type</VAR>, <VAR>splittable</VAR>);</CODE> the <VAR>splittable</VAR> flag specifies whether the struct <VAR>return_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>va_word_splittable_1 (<VAR>type1</VAR>)</CODE> <CODE>va_word_splittable_2 (<VAR>type1</VAR>, <VAR>type2</VAR>)</CODE> <CODE>va_word_splittable_3 (<VAR>type1</VAR>, <VAR>type2</VAR>, <VAR>type3</VAR>)</CODE> <CODE>va_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>va_word_splittable_3 (<VAR>type1</VAR>, <VAR>type2</VAR>, <VAR>type3</VAR>)</CODE>. <A NAME="Notes"> <H2>Notes</H2> </A> <OL> <LI> Functions which want to emulate Kernighan & Ritchie style functions (i.e., in ANSI C, functions without a typed argument list) cannot use the <VAR>type</VAR> values <CODE>char</CODE>, <CODE>schar</CODE>, <CODE>uchar</CODE>, <CODE>short</CODE>, <CODE>ushort</CODE>, <CODE>float</CODE>. As prescribed by the default K&R C expression promotions, they have to use <CODE>int</CODE> instead of <CODE>char</CODE>, <CODE>schar</CODE>, <CODE>uchar</CODE>, <CODE>short</CODE>, <CODE>ushort</CODE> and <CODE>double</CODE> instead of <CODE>float</CODE>. <P> <LI> The macros <CODE>va_start_longlong()</CODE>, <CODE>va_start_ulonglong()</CODE>, <CODE>va_return_longlong()</CODE>, <CODE>va_return_ulonglong()</CODE>, <CODE>va_arg_longlong()</CODE> and <CODE>va_arg_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>va_start_struct()</CODE> and <CODE>va_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="Example"> <H2>Example</H2> </A> This example, a possible implementation of <A HREF="execl(3)"><CODE><B>execl</B></CODE></A>(3) on top of <A HREF="execv(2)"><CODE><B>execv</B></CODE></A>(2) using <A HREF="varargs(3)"><CODE><B>varargs</B></CODE></A>(3), <PRE><CODE>#include <varargs.h> #define MAXARGS 100 /* execl is called by execl(file, arg1, arg2, ..., (char *)0); */ int execl (va_alist) va_dcl { va_list ap; char* file; char* args[MAXARGS]; int argno = 0; va_start (ap); file = va_arg(ap, char*); while ((args[argno] = va_arg(ap, char*)) != (char *)0) argno++; va_end (ap); return execv(file, args); } </CODE></PRE> looks like this using <A HREF="vacall(3)"><CODE><B>vacall</B></CODE></A>(3): <PRE><CODE>#include <vacall.h> #define MAXARGS 100 /* execl is called by vacall(file, arg1, arg2, ..., (char *)0); */ void execl (ap) va_alist ap; { char* file; char* args[MAXARGS]; int argno = 0; int retval; va_start_int (ap); file = va_arg_ptr(ap, char*); while ((args[argno] = va_arg_ptr(ap, char*)) != (char *)0) argno++; retval = execv(file, args); va_return_int (ap, retval); } vacall_function = &execl; </CODE></PRE> <P> <A NAME="See also"> <H2>See also</H2> </A> <A HREF="varargs(3)"><CODE><B>varargs</B></CODE></A>(3), <A HREF="trampoline(3)"><CODE><B>trampoline</B></CODE></A>(3), <A HREF="callback(3)"><CODE><B>callback</B></CODE></A>(3). <A NAME="Bugs"> <H2>Bugs</H2> </A> The current implementations have been tested on a selection of common cases but there are probably still many bugs. <P> There are typically built-in limits on the size of the argument-list, which may also include the size of any structure arguments. <P> 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. <P> <CODE><vacall.h></CODE> cannot be included when <CODE><varargs.h></CODE> or <CODE><stdarg.h></CODE> is included. (Name clash for <CODE>va_alist</CODE>.) <P> The argument list can only be walked once. <P> The use of the global variable <CODE>vacall_function</CODE> is not reentrant. This is fixed in the <A HREF="callback(3)"><CODE><B>callback</B></CODE></A>(3) package. <A NAME="Porting"> <H2>Porting</H2> </A> 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 "Stack layout; function entry, exit and calling." <P> The implementation of varargs for gcc can be found in the gcc source, files <SAMP>gcc-2.6.3/ginclude/va*.h</SAMP>. <P> gcc's <CODE>__builtin_saveregs()</CODE> function is defined in the gcc source, file <SAMP>gcc-2.6.3/libgcc2.c</SAMP>. <P> <A NAME="Author"> <H2>Author</H2> </A> Bruno Haible <bruno@clisp.org> <A NAME="Acknowledgements"> <H2>Acknowledgements</H2> </A> Many ideas and a lot of code were cribbed from the gcc source. <P> <HR> <ADDRESS>VACALL manual page<BR> Bruno Haible <bruno@clisp.org> </ADDRESS> <P> Last modified: 14 January 2001. </BODY>