scotte@locus.com (Scott D. Eberline) (06/13/91)
For software that may potentially be ported to platforms not yet ANSI-compliant, some functions taking variable arguments are defined using <varargs.h> instead of <stdarg.h>. I would like to declare full prototypes for these to avoid compiler warnings about missing prototypes. In the module in which these functions are defined, this doesn't seem to be possible: 1. prototypes using the ellipsis notation for variable argument lists don't match varargs-style function definitions; 2. because of the built-in semicolon, prototypes can't contain va_dcl. I'm a bit resigned to having missing prototype warnings for the module that contains the function definitions. I'd still like to have prototypes in all the other modules, and the ellipsis notation seems to be the only way to do this. How dangerous is it to call functions declared externally using the ellipsis notation, but defined using va_dcl? May a conforming implement- ation assume that functions with ellipsis prototypes use <stdarg.h>-style arguments and not <varargs.h>-style? -- Scott D. Eberline scotte@locus.com or lcc!scotte
gwyn@smoke.brl.mil (Doug Gwyn) (06/13/91)
In article <25353@oolong.la.locus.com> scotte@locus.com (Scott D. Eberline) writes: >I'm a bit resigned to having missing prototype warnings for the module >that contains the function definitions. As you have discovered, there is no correct way to use prototypes for <varargs.h>-style variadic functions (when they are supported at all). You ought to simply use the empty-parenthesis (old style) form of declaration for such functions. By the way, I take exception to the implementation warning you that no prototypes exists, unles you have specifically asked for that check. The C standard does not require that prototypes be used. >How dangerous is it to call functions declared externally using the >ellipsis notation, but defined using va_dcl? May a conforming implement- >ation assume that functions with ellipsis prototypes use <stdarg.h>-style >arguments and not <varargs.h>-style? The answer to the second question is "Certainly, and indeed it is likely." Therefore the answer to the first question is that it is not a good idea.
diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/14/91)
In article <16405@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >By the way, I take exception to the implementation warning you that no >prototypes exists, unles you have specifically asked for that check. >The C standard does not require that prototypes be used. But an implementation is allowed to issue spurious diagnostics. Presumably spurious diagnostics can convey useful information :-) We agree that in a quality implementation, there would be an option to turn useful spurious diagnostics on or off. But as for which setting to use for the default, what is high quality to one person seems to be low quality to another person. -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it. Permission is granted to feel this signature, but not to look at it.
markhall@pyrps5.pyramid.com (Mark Hall) (06/15/91)
In article <25353@oolong.la.locus.com> scotte@locus.com (Scott D. Eberline) writes: >For software that may potentially be ported to platforms not yet >ANSI-compliant, some functions taking variable arguments are >defined using <varargs.h> instead of <stdarg.h>. I would like >to declare full prototypes for these to avoid compiler warnings >about missing prototypes. In the module in which these functions >are defined, this doesn't seem to be possible: OK, so you want your code to work with ANSI and non-ansi compilers. Why not accomodate both in your source. That's what the predefined __STDC__ macro is for. Declarations: #ifdef __STDC__ void foo(char *format, ...); #else void foo(); #endif Definitions: #ifdef __STDC__ void foo(char *format, ...) #else void foo(format, va_alist) char *format; va_dcl #endif { va_list ap; #ifdef __STDC__ va_start(ap,format); #else va_start(ap); #endif [ ... rest of stuff the same ... ] } >I'm a bit resigned to having missing prototype warnings for the module >that contains the function definitions. I'd still like to have >prototypes in all the other modules, and the ellipsis notation >seems to be the only way to do this. It's nice to have a compiler which requires having prototypes if you want them. Of course, this isn't required by ANSI. >How dangerous is it to call functions declared externally using the >ellipsis notation, but defined using va_dcl? Very. If a stdarg prototype is visible at a call site, it allows the compiler to generate a different calling sequence. For example, if a compiler normally passes arguments in registers, it may choose to just load them on the data stack instead when it sees a stdarg call site (an optimization; otherwise it would just have to store down the registers on function entry). Since it can depend on the definition of the function to also have the stdarg notation, it will know how to "pick up" the arguements in the function body. >May a conforming implement- >ation assume that functions with ellipsis prototypes use <stdarg.h>-style >arguments and not <varargs.h>-style? Well, it may assume that an ellipsis prototype was visible at every call site of "foo" if "foo" is defined using the ellipsis notation. >-- >Scott D. Eberline scotte@locus.com or lcc!scotte -Mark Hall (smart mailer): markhall@pyrps5.pyramid.com (uucp paths): {uunet|ames|decwrl|sun|seismo}!pyramid!markhall
hansen@pegasus.att.com (Tony L. Hansen) (06/18/91)
< From: markhall@pyrps5.pyramid.com (Mark Hall) < #ifdef __STDC__ < void foo(char *format, ...) < #else < void foo(format, va_alist) char *format; va_dcl < #endif < { < va_list ap; < #ifdef __STDC__ < va_start(ap,format); < #else < va_start(ap); < #endif < < [ ... rest of stuff the same ... ] < } The above form for <varargs.h> usage is wrong. The documentation, and some implementations, REQUIRE you to declare the function as: void foo(va_alist) va_dcl and then pick off the fixed arguments using va_arg: char *format; format = va_arg(ap,char*); Any other usage is non-portable (as portable as you can be using varargs.h, that is. :-) ) Tony Hansen hansen@pegasus.att.com, tony@attmail.com att!pegasus!hansen, attmail!tony
torek@elf.ee.lbl.gov (Chris Torek) (06/19/91)
>In article <159364@pyramid.pyramid.com> markhall@pyrps5.pyramid.com >(Mark Hall) writes: >> #ifdef __STDC__ >> void foo(char *format, ...) >> #else >> void foo(format, va_alist) char *format; va_dcl >> #endif [and on from there] In article <1991Jun18.145823.2512@cbnewsk.att.com> hansen@pegasus.att.com (Tony L. Hansen) writes: >The above form for <varargs.h> usage is wrong. ... This is correct; however, I have used the above, and continue to use it, in 4BSD code, with the excuse that: a) it is far clearer; and b) if your varargs does not handle it, you can probably obtain an ANSI C implementation and use the __STDC__ code anyway. In other words, we are not willing to bend over backwards (for compatibility) until it hurts, only until it is mildly uncomfortable. :-) Chris -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
gwyn@smoke.brl.mil (Doug Gwyn) (06/19/91)
In article <14423@dog.ee.lbl.gov> torek@elf.ee.lbl.gov (Chris Torek) writes: >In other words, we are not willing to bend over backwards (for compatibility) >until it hurts, only until it is mildly uncomfortable. :-) But surely it's not appreciably harder, for the few uses of varargs functions, to type the always correct void foo(va_alist) va_dcl { char *format; ... format = va_arg(ap, char *); ... } instead of the sometimes incorrect void foo(format, va_alist) char *format; va_dcl { ... ... }
torek@elf.ee.lbl.gov (Chris Torek) (06/21/91)
>In article <14423@dog.ee.lbl.gov> I wrote: >>In other words, we are not willing to bend over backwards (for compatibility) >>until it hurts, only until it is mildly uncomfortable. :-) In article <16456@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >But surely it's not appreciably harder, for the few uses of varargs >functions, to type the always correct [and vertically compressed and reformatted a bit by me] > void foo(va_alist) va_dcl { > char *format; ... > format = va_arg(ap, char *); > ... > } >instead of the sometimes incorrect > void foo(format, va_alist) char *format; va_dcl { > ... > } No. However, combine this with the ANSI C version: int #ifdef __STDC__ abc(int level, int type, struct foo *obj, const char *fmt, ...) #else abc(va_alist) va_dcl #endif { #ifndef __STDC__ int level; int type; struct foo *obj; char *fmt; #endif int ret; va_list ap; #ifdef __STDC__ va_start(ap, fmt); #else va_start(ap); level = va_arg(ap, int); type = va_arg(ap, int); obj = va_arg(ap, struct foo *); fmt = va_arg(ap, char *); #endif ret = vabc(level, type, obj, fmt, ap); va_end(ap); return (ret); } Now compare this with the easier (but incorrect unless __STDC__) code: int #ifdef __STDC__ abc(int level, int type, struct foo *obj, const char *fmt, ...) #else abc(level, type, obj, fmt, va_alist) int level; int type; struct foo *obj; char *fmt; va_dcl #endif { int ret; va_list ap; #ifdef __STDC__ va_start(ap, fmt); #else va_start(ap); #endif ret = vabc(level, type, obj, fmt, ap); va_end(ap); return (ret); } This saves six lines (24 vs 30; 20% less) and moves the argument matching maintenance together where it is clearer. (Suppose, for instance, the `type' argument is split into two arguments, or is merged into the `foo' object.) Now multiply this by a dozen varargs functions spread over a few hundred files. We (Keith Bostic and I, at least) would rather deal with the second (technically broken) version, due to easier maintenance, and tell those who have trouble with it to find an ANSI C compiler (and/or port GCC). -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
gwyn@smoke.brl.mil (Doug Gwyn) (06/21/91)
In article <14532@dog.ee.lbl.gov> torek@elf.ee.lbl.gov (Chris Torek) writes: >... and tell those who have trouble with it to find an ANSI C >compiler (and/or port GCC). You could also suggest that the necessary change to the code to attain "portable" usage of <varargs.h> is straightforward, and let them do the extra work if and when the occasion arises.