Path: utzoo!attcan!uunet!mstan!dff From: dff@Morgan.COM (Daniel F. Fisher) Newsgroups: comp.lang.c Subject: Re: passing variable numbers of arguments Summary: va_arg() would include assert(there is an argument) Keywords: varargs assert() nargs() Message-ID: <202@mstan.Morgan.COM> Date: 13 Jan 89 23:36:03 GMT References: <899@thor.stolaf.edu> <15341@mimsy.UUCP> <449@marob.MASA.COM> <9317@smoke.BRL.MIL> <11378@haddock.ima.isc.com> <9321@smoke.BRL.MIL> <11410@haddock.ima.isc.com> <9358@smoke.BRL.MIL> Reply-To: dff@Morgan.COM (Daniel F. Fisher) Distribution: na Organization: Morgan Stanley and Co., NY, NY Lines: 87 Expires: Sender: Followup-To: In article <11410@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) proposes a va_nbytes() to be used in implementing portable argument counting. In article <9358@smoke.BRL.MIL> gwyn@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@morgan.com