Path: utzoo!utgpu!watmath!att!tut.cis.ohio-state.edu!ucbvax!bloom-beacon!adam.pika.mit.edu!scs From: scs@adam.pika.mit.edu (Steve Summit) Newsgroups: comp.lang.c Subject: Re: va_list used inKeywords: va_list, X3J11, vfprintf Message-ID: <13572@bloom-beacon.MIT.EDU> Date: 17 Aug 89 05:56:27 GMT References: <1140@midgard.Midgard.MN.ORG> <10720@smoke.BRL.MIL> <2095@dataio.Data-IO.COM> <10739@smoke.BRL.MIL> Sender: daemon@bloom-beacon.MIT.EDU Reply-To: scs@adam.pika.mit.edu (Steve Summit) Lines: 126 In article <1140@midgard.Midgard.MN.ORG> dal@midgard.Midgard.MN.ORG (Dale Schumacher) writes: >In the header file, the v[fs]printf() function prototypes >use the va_list type, but va_list is not defined anywhere in . In article <10720@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >The answer is that the implementor of > must not attempt to use "va_list" but instead should just >use the actual type expressed without use of typedefs. ...which is difficult if the implementor of is not also the implementor of . In article <2095@dataio.Data-IO.COM> bright@dataio.Data-IO.COM (Walter Bright) writes: >1. In stdio.h, include the lines: > #ifndef __STDARG_H /* #define'd by stdarg.h */ > #include /* get definition of va_list */ > #endif This is the right idea, although it assumes that #defines __STDARG_H, which again an independently-written can't do. (The #ifndef isn't really necessary; can independently protect itself against multiple #inclusion, albeit at the cost of an extra open, which some people worry about.) Anyway, it's illegal for a second reason: In article <10739@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >No, don't do this. is not allowed to define the va_* macros. If I were the implementer of both and , I'd shake my head at this conflicting set of requirements, take a deep breath, and add something like va_list.h: #ifndef _VA_LIST #define _VA_LIST typedef int *__va_list; #endif would then contain #include typedef __va_list va_list; and would contain #include extern int vfprintf(FILE *, char *, __va_list); (I'd probably have to do the same thing for off_t, because if fseek() doesn't take one, it should. Schade, off_t is in 1003.1's baliwick, not X3J11's.) This is, I'll admit, fussy, but the rule against defining things in two places (so that an eventual change must then be made in two places) is an extremely good one, which I'll break only under extreme duress. Besides the possible compilation speed degradation due to the extra file-opening overhead, which Walter will remind me of if somebody else doesn't, this solution is distasteful because the prototype extern int vfprintf(FILE *, char *, __va_list); is not "obviously" compatible with the call va_list argp; ... vfprintf(fd, fmt, argp); (Doug's suggestion to use the underlying va_list type directly in the vfprintf prototype has the same difficulty). "Obvious" compatibility is desirable, among other reasons, because header files containing prototypes are a convenient source of on-line documentation. Now, I know that a __va_list is really the same as a va_list, and in fact the pANS guarantees it (typedefs are merely type synonyms, not new types), but it still seems unfortunate, if only because it's another nail in the coffin for that last sentence of chapter 6 of K&R I: Finally, there is always the possibility that in the future the compiler or some other program such as lint may make use of the information contained in typedef declarations to perform some extra checking of a program. Of course, the pANS typedef definition (which merely codifies existing practice) has irreversibly sealed that coffin already, and I doubt that anyone else remembers or cares about the quote above anyway. The correct vfprintf prototype in is in any case only barely workable for implementers of both and (i.e compiler and/or RTL vendors). It is apparently impossible to write a correct, standalone , which is what Dale Schumacher is trying to do. (It happens that I am trying to do the same thing, but had not worried about prototypes. Alas!, I have not posted my efforts yet, so Dale and I are duplicating each other's work.) Am I the only one who gets the same sort of feeling about function prototypes as about symbolic links: a nice idea, but introducing enough complications in practice that maybe they're not so wonderful after all? (Don't respond telling me what prototypes are good for; I know what they're supposed to be good for.) Also in article <10720@smoke.BRL.MIL>, Doug writes: >Warning! Use __iob or _Iob, not _iob, in your . I'm not sure what is implied here. It seems to me that _iob is no more reserved that any other reserved identifier. I'm deliberately calling my buffer list _iob, to afford the possibility of compatibility with previously-compiled object files. (Yes, this possibility is fraught with peril; and yes, I like playing with fire.) Using a different identifier might conceivably avoid a conflict with a system-defined _iob (by "system" I mean the complete C RTL that the purported standalone stdio is attempting to augment), but there are enough other name conflicts ("printf," etc.) that if any part of the "standard" stdio gets linked in (_iob or otherwise) there's bound to be trouble. (I wish the pANS could drop the "p" sometime soon so I could get a copy; Doug's point may just have to do with the distinction between single and double leading underscores or something.) Steve Summit scs@adam.pika.mit.edu