[net.unix-wizards] Function with variable number of args

FIRTH%TARTAN@CMU-CS-C.ARPA (06/25/84)

I was amazed to read this statement in a recent post:

	There is *no* fully machine-independent way to write a
	function which takes a variable number of arguments, even
	if all the function is trying to do is to pass its argument
	list on to another function.

The language BCPL has precisely this feature, and as far as I know
there has been no major problem with it in 20 years.  The way to
write the function is to declare it with the maximum number of
arguments, and you can scan the argument list sequentially by
simply building a pointer to the first argument and stepping it:

	ptr := LV arg1
	...
	ptr := ptr + (LV arg2 - LV arg1)
	
(LV in BCPL is & in C).  The language semantics requires the args to be
stored in consecutive cells, though they may run upwards or downwards in
memory, hence the above code.  I've never heard of any implementation
difficulties, and have never encountered any myself in the BCPL ports
I've done.
-------

jeff@AIDS-UNIX.ARPA (06/26/84)

From:  Jeff Dean <jeff@AIDS-UNIX.ARPA>

(flame on)

I disagree that with the idea that handling a "maximum number of
arguments" is the same as handling a variable number of arguments.
Sure, if you make the number large enough, people are unlikely to
run into the limit, but that's not the point.  You need a dynamic
mechanism to handle a variable number of arguments; the "maximum
number of arguments" is a static method, and insufficient.

A variable argument mechanism needs to provide at least two
things:  to subroutine users, it allows an arbitrary number of
arguments (subject to hardware constraints, such as stack size);
to subroutine implementors, it means having a uniform mechanism
for dealing with an unlimited number of arguments (and not having
to guess at the maximum number of arguments any users are likely
to throw at you).

(flame off)

@BRL-AOS.ARPA: (06/26/84)

From:  Eric Benson <@BRL-AOS.ARPA:>

In BCPL, all values are the same size, one "word."  If a function is
called with six arguments, they are contained in exactly six words.
In C, some data types (e.g, doubles on VAXen, longs, floats and
doubles on 11's) do not fit in one word.  _doprnt has to increment its
argument pointer by different amounts depending on the data type,
which it determines by looking at the corresponding printf format.
Notice what happens when you try

printf("This is not an integer: %d, but these are floats: %f, %f and %f",
				1.0,			 2.0, 3.0,   4.0);

You expect garbage to be printed in the first case, but you may be
surprised to see garbage in the other cases as well.  That happens
because you have made the argument pointer point into the middle of
1.0.  The next thing to be printed is not 2.0, but part of 1.0 and
part of 2.0.

It is for this reason, among others, that it is difficult to define a
portable facility for handling a variable number of arguments.

-- Eric
-------

cdl@mplvax.UUCP (06/26/84)

Nobody said that there was any difficulty scanning an argument list,
either forward or backward in memory.  The problem is telling when
you have finished.  Either the *number* of arguments has to be
transmitted (PDP-11 Fortran style) or there has to be some unambiguous
marker for the end of the list.

	carl lowenstein		marine physical lab	u.c. san diego
		sdcsvax!mplvax!cdl

henry@utzoo.UUCP (Henry Spencer) (06/30/84)

>I was amazed to read this statement in a recent post:
>
>	There is *no* fully machine-independent way to write a
>	function which takes a variable number of arguments, even
>	if all the function is trying to do is to pass its argument
>	list on to another function.
>
>The language BCPL has precisely this feature, and as far as I know
>there has been no major problem with it in 20 years.  The way to
>write the function is to declare it with the maximum number of
>arguments, and you can scan the argument list sequentially by
>simply building a pointer to the first argument and stepping it:
>
>	ptr := LV arg1
>	...
>	ptr := ptr + (LV arg2 - LV arg1)
>	
>(LV in BCPL is & in C).  The language semantics requires the args to be
>stored in consecutive cells, though they may run upwards or downwards in
>memory, hence the above code.  I've never heard of any implementation
>difficulties, and have never encountered any myself in the BCPL ports
>I've done.

For one thing, C is not BCPL, and C does *not* require consecutive cell
allocation of arguments.  So you can't (in principle) depend on that.
There are C compilers that put some of the arguments in registers, for
example.  (Please don't tell me that these compilers run into trouble
with various things; I'm quite aware of this.  But they do exist.)

For another thing, while I respect your BCPL porting experience, I would
say that you've never tried to implement BCPL on really difficult machines.
There exist machines -- with Unix implementations running on them -- which
absolutely require that the size of the argument list of a given function
be a compile-time constant, as a fundamental assumption of their only call
primitive.  Such machines break *all* the simplistic variable-arguments
techniques; really heavy kludging is required to make things work.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry