passing variable numbers of arguments

Daniel F. Fisher dff at Morgan.COM
Sat Jan 14 09:36:03 AEST 1989


In article <11410 at haddock.ima.isc.com> karl at haddock.ima.isc.com
(Karl Heuer) proposes a va_nbytes() to be used in implementing
portable argument counting.

In article <9358 at smoke.BRL.MIL> gwyn at smoke.BRL.MIL (Doug Gwyn)
indicates that such a construct is not portable because use of
sizeof to adjust the argument byte count is flawed, due to the
alignment differences for array members and normal parameters.

Since arrays cannot be passed by value in C, I fail to see how this
is relevant.  However, I do agree with the conclusion, since one
can postulate calling sequences that are not strictly stack based.
Particularly in an interpreted environment or a massively parallel
architecture.

In evaluating proposals for a portable nargs() like mechanism, it is
necessary to keep in mind the purpose this mechanism.

If, on the one hand, the nargs() mechanism is to be used by functions
so that they do not have to rely on sentinel arguments or information
implicit in a required argument to determine how many arguments they
have, then a portable nargs() like mechanism is clearly required.
_IF_ this is the purpose, I would propose a macro, va_nargs(parg, type),
that evaluates to the number of arguments of the given type remaining.
By this, I do NOT mean to suggest that the calling sequence has to
identify the type of every argument.  All that is required, is that
the va_nargs() macro indicate how many successive va_arg(parg, type)
invocations would succeed given the current state of argument
processing.  But, if this _IS_ the purpose, I believe that these
varargs functions should require the caller to provide the argument
count explicitly as one of the required arguments, instead of
burdening the calling sequence with this overhead on EVERY function
call to ANY function.

If, on the other hand, the nargs() mechanism is to be used as a
run-time sanity check for adherence to a varargs calling convention
making use of a sentinel argument or relying on information present
in some required argument, then what is required is an assert() like
mechanism.  I would propose that the va_arg() macro be modified to
allow it to abort the program if it cannot return an argument of the
indicated type.  If the normal calling sequence does not provide
argument count information, then it would need to be augmented as
appropriate.  Since the new calling sequence and run time checking
in va_arg() might be too time consuming, their use would need to be
controlled by a compile time switch of some type.  Perhaps "#ifndef
NDEBUG" as is used by assert().  While this is easy to do when
selecting which form of the va_arg() macro to use, it presents an
interesting challenge in designing calling sequences.  The basic
problem is how to make the normal and augmented calling sequences
compatible.  (Incompatible calling sequences, would be a pain in the
head.)  I am not sure how to achieve compatibility without making the
normal calling sequence as inefficient as the augmented calling
sequence.

Calling Sequence Compatibility

If a function using the augmented calling sequence calls one expecting
the normal calling sequence, how does the called function ignore
argument count information?  If a function using the normal calling
sequence calls on using the augmented supporting calling sequence,
how does the called function process the arguments correctly and
avoid any argument count checking in va_arg()?  The answers may be
non-trivial.  If the argument count information is at the end of
the argument list, it cannot be located when it is needed.  If the
argument count information is at the beginning of the argument list,
then it cannot be distinguished from the first argument.  If the
argument count information is elsewhere in the argument list, then
there is a combination of these difficulties.  So the argument count
information would need to be kept somewhere else.  If it is a register,
then both calling sequences would need to set it to some meaningful
value.  If it is in a reserved place on the stack, the same is true.
What to do? What to do?

N.B.: By argument count information in the above, I refer to that
information required by va_arg() to determine if it is valid to return
an argument of the requested type.  The precise form this takes would
be an implementation issue.  Implementation in a 3B2 like environment
is straight forward, because the %AP (argument pointer) and %FP
(frame pointer) registers will bound the argument list in known way.
Implementation in a 68020 like environment probably requires that an
argument pointer or argument count be pushed as the last argument in
all function calls.  More exotic calling sequences might require
information about the type of each argument.

-- 
Daniel F. Fisher
dff at morgan.com



More information about the Comp.lang.c mailing list