File ffcall/vacall/vacall.html artifact be4f014336 part of check-in b465d05d14


<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 &lt;vacall.h&gt;</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>&amp;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
&lt;= <SAMP>sizeof(long)</SAMP>,  splittable  is ignored and assumed to be 1.
For  structs  of  size  &gt; <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 &amp; 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&amp;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 &lt;varargs.h&gt;
#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 &lt;vacall.h&gt;
#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 = &amp;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>&lt;vacall.h&gt;</CODE> cannot be included  when <CODE>&lt;varargs.h&gt;</CODE>  or
<CODE>&lt;stdarg.h&gt;</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 &lt;bruno@clisp.org&gt;

<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 &lt;bruno@clisp.org&gt;
</ADDRESS>
<P>
Last modified: 14 January 2001.

</BODY>