<HEAD>
<TITLE> CALLBACK manual page </TITLE>
</HEAD>
<BODY>
<H1>CALLBACK 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="#VACALL macros">VACALL macros</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">Porting</A>
<LI> <A HREF="#Author">Author</A>
<LI> <A HREF="#Acknowledgements">Acknowledgements</A>
</UL>
<P>
<HR>
<A NAME="Name">
<H2>Name</H2>
</A>
callback - closures with variable arguments as first-class
C functions
<A NAME="Synopsis">
<H2>Synopsis</H2>
</A>
<PRE>
<CODE>#include <callback.h></CODE>
</PRE>
<P>
<PRE>
<CODE>void <VAR>function</VAR> (<VAR>data</VAR>, <VAR>alist</VAR>)</CODE>
<CODE> void* <VAR>data</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><VAR>callback</VAR> = alloc_callback(<VAR>&function</VAR>, <VAR>data</VAR>);</CODE>
</PRE>
<P>
<PRE>
<CODE>free_callback(<VAR>callback</VAR>);</CODE>
</PRE>
<P>
<PRE>
<CODE>is_callback(<VAR>callback</VAR>)</CODE>
<CODE>callback_address(<VAR>callback</VAR>)</CODE>
<CODE>callback_data(<VAR>callback</VAR>)</CODE>
</PRE>
<A NAME="Description">
<H2>Description</H2>
</A>
These functions implement <EM>closures</EM> with variable arguments
as first-class C functions.
<P>
Closures as <EM>first-class C functions</EM> means that they fit
into a function pointer and can be called exactly like any
other C function. Moreover, they can be called with variable
arguments and can return variable return values.
<P>
<CODE><VAR>callback</VAR> = alloc_callback(<VAR>&function</VAR>, <VAR>data</VAR>)</CODE>
allocates a
callback. When <VAR>callback</VAR> gets called, it arranges to call
<VAR>function</VAR>, passing <VAR>data</VAR> as first argument and, as second
argument, the entire sequence of arguments passed to <VAR>callback</VAR>.
<P>
Function calling conventions differ considerably on different
machines, therefore the arguments are accessed and
the result value is stored through the same macros as used
by the <EM>vacall</EM> package, see below.
<P>
The callbacks are functions with indefinite extent: <CODE><VAR>callback</VAR></CODE>
is only deallocated when <CODE>free_callback(<VAR>callback</VAR>)</CODE> is
called.
<P>
<CODE>is_callback(<VAR>callback</VAR>)</CODE>
checks whether the C function <CODE><VAR>callback</VAR></CODE>
was produced by a call to <CODE>alloc_callback</CODE>. If this
returns true, the arguments given to <CODE>alloc_callback</CODE> can be
retrieved:
<UL>
<LI> <CODE>callback_address(<VAR>callback</VAR>)</CODE> returns <VAR>&function</VAR>,
<LI> <CODE>callback_data(<VAR>callback</VAR>)</CODE> returns <VAR>data</VAR>.
</UL>
<A NAME="VACALL macros">
<H2>VACALL macros</H2>
</A>
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="See also">
<H2>See also</H2>
</A>
<A HREF="vacall(3)"><CODE><B>vacall</B></CODE></A>(3), <A HREF="trampoline(3)"><CODE><B>trampoline</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><callback.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.
<A NAME="Non-Bugs">
<H2>Non-Bugs</H2>
</A>
All information is passed in CPU registers and the stack.
The <CODE><B>callback</B></CODE> package is therefore multithread-safe.
<A NAME="Porting">
<H2>Porting</H2>
</A>
Porting <CODE><B>callback</B></CODE> consists in first porting the <CODE><B>vacall</B></CODE> and
<CODE><B>trampoline</B></CODE> packages, then choosing a CPU register for
passing the closure from <EM>trampoline</EM> to <EM>vacall</EM>. This
register is normally the register designated by
<CODE>STATIC_CHAIN_REGNUM</CODE> in the gcc source, file
<SAMP>gcc-2.7.2/config/<VAR>cpu</VAR>/<VAR>cpu</VAR>.h</SAMP>.
<A NAME="Author">
<H2>Author</H2>
</A>
Bruno Haible <bruno@clisp.org>
<A NAME="Acknowledgements">
<H2>Acknowledgements</H2>
</A>
Many ideas were cribbed from the gcc source.
<P>
<HR>
<ADDRESS>CALLBACK manual page<BR>
Bruno Haible <bruno@clisp.org>
</ADDRESS>
<P>
Last modified: 14 January 2001.
</BODY>