[comp.emacs] varargs

scs@adam.pika.mit.edu (Steve Summit) (08/18/89)

In article <9847@j.cc.purdue.edu> nwd@j.cc.purdue.edu (Daniel Lawrence) writes:
>I support uEMACS on a
>number of systems and compilers that do not have varargs.h, and I do not
>want to simply tell a lot of users there machines must be updated or
>changed because of this.

If you can implement varargs functions without <varargs.h>,
hoping that it will work on unknown systems, then you can write
your own <varargs.h> (or, better yet, <stdarg.h>) and supply it
with your distribution, for use by recipients whose (beleagured)
systems do not have the proper header file.  Of course, this
solution won't work for all recipients, but it's no worse than
"simulating" varargs in-line.  In fact, it's better: it works for
the same cases, it fails for systems that don't have the header
file and for which the hardwired code code wouldn't have worked
either, and (key point:) it allows the program to work on "weird"
systems for which the handcoded stuff wouldn't work but on which
a working varargs and/or stdarg implementation is provided.

Here's my own <stdarg.h>, which you're all welcome to. (Just
leave my name on it.)  For those who don't know, stdarg is the
X3J11 (ANSI) C standard package which supplants, and is said
to be more widely implementable than, varargs.  Since it is now
(or almost) standard, it is a good choice for portable code,
particularly if a quasi-portable implementation can be supplied
for systems which don't yet have it.

I find the stdarg package slightly easier to use than varargs.
There is no va_dcl macro or va_alist placeholder argument.  The
varargs function is compiled with at least one fixed argument
(some find this requirement discouraging); the name of the last
fixed argument is passed to the va_start macro, along with the
argument pointer variable, which is of type va_list.  The va_arg
and va_end macros are used just as under <varargs.h>.

                                            Steve Summit
                                            scs@adam.pika.mit.edu

--------8<--------8<--------stdarg.h--------8<--------8<--------
#ifndef _STDARG_H
#define _STDARG_H

/*
 *  stdarg implementation for "conventional" architectures with
 *  downward-growing stacks.  The stack is assumed to be aligned
 *  to word, i.e. int, sized boundaries, with smaller arguments
 *  widened when passed and larger arguments equal to (or rounded
 *  up to) a multiple of the word size.
 *
 *  The stack word size can be changed by adjusting the
 *  _stacktype typedef.
 *
 *  The va_arg macro looks inefficient, with its embedded
 *  conditional, and lint may complain about "constant in
 *  conditional context," but the optimizers I have tried it
 *  under successfully remove the "dead" case (the controlling
 *  expression is a compile-time constant), and the remaining
 *  postincrement int pointer expression (the more common case)
 *  is considerably nicer in space and time.
 *
 *  Bug: doesn't know that float arguments are widened to double
 *  when passed.  Don't, therefore, call va_arg(..., float).
 *
 *  Steve Summit  4/15/89
 */

typedef int _stacktype;
typedef _stacktype *va_list;

#define _argsize(type) ((sizeof(type) + (sizeof(_stacktype) - 1)) \
				/ sizeof(_stacktype))

#define va_start(vaptr, lastarg) vaptr = (_stacktype *)&lastarg + 1

#define va_arg(vaptr, type) (_argsize(type) == 1 ? \
	*(type *)((vaptr)++) : \
		*(type *)(((vaptr) += _argsize(type)) - _argsize(type)))

#define va_end(vaptr)

#endif