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