dal@midgard.Midgard.MN.ORG (Dale Schumacher) (08/12/89)
I'm working on the header files for a PD LIBC implementation with the goal that it be as close as possible to X3J11 and POSIX conformance. I'm working from the May 13, 1988 draft of the C pANS. In the <stdio.h> header file, the v[fs]printf() function prototypes use the va_list type, but va_list is not defined anywhere in <stdio.h>. The synopsis shows the need to #include both <stdarg.h> and <stdio.h> in order to use v[fs]printf(), but what about #include'ing <stdio.h> in a program which doesn't use these functions? The prototype would then be an error, right? Also, section 4.1.2 (the v[fs]printf() functions are in 4.9.6.[789]) states "Headers may be included in any order; ...". In order for the declaration to work, <stdarg.h> must be #include'd first. The standard also seems to imply that header files do not include each other. Is this the case? Do I have an outdated draft of the standard?
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/13/89)
In article <1140@midgard.Midgard.MN.ORG> dal@midgard.Midgard.MN.ORG (Dale Schumacher) writes: >In the <stdio.h> header file, the v[fs]printf() function prototypes >use the va_list type, but va_list is not defined anywhere in <stdio.h>. This is a frequent question. The answer is that the implementor of <stdio.h> must not attempt to use "va_list" but instead should just use the actual type expressed without use of typedefs. >The standard also seems to imply that header files do not include each >other. Is this the case? Yes, in effect each standard header contains exactly what the Standard says it does and nothing else. (Identifers specifically stated as reserved for implementation use may also be defined/declared in standard headers. Warning! Use __iob or _Iob, not _iob, in your <stdio.h>.)
bright@Data-IO.COM (Walter Bright) (08/15/89)
In article <1140@midgard.Midgard.MN.ORG> dal@midgard.Midgard.MN.ORG (Dale Schumacher) writes:
<I'm working on the header files for a PD LIBC implementation with the
<goal that it be as close as possible to X3J11 and POSIX conformance.
<I'm working from the May 13, 1988 draft of the C pANS.
Finally! Instead of wasting energy worrying about the GNU copyright,
you've got the right idea! Best of luck to you!
<In the <stdio.h> header file, the v[fs]printf() function prototypes
<use the va_list type, but va_list is not defined anywhere in <stdio.h>.
The trick to note is that <stdarg.h> is required for any *user* code that
uses variable argument lists. Since <stdio.h> is supplied by the *vendor*,
the problem can be solved in one of two ways,
1. In stdio.h, include the lines:
#ifndef __STDARG_H /* #define'd by stdarg.h */
#include <stdarg.h> /* get definition of va_list */
#endif
(As has been discussed here before, using 'wrappers' like this means
that order dependent #include's can be #include'd in any order
without a problem.)
2. As the compiler vendor, we *know* what va_list is, so we simply prototype
vprintf and friends as:
int vprintf(const char *,char *);
instead of:
int vprintf(const char *,va_list);
I use 2. because it compiles faster.
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/15/89)
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 <stdarg.h> /* get definition of va_list */
- #endif
No, don't do this. <stdio.h> is not allowed to define the va_* macros.
walter@hpclwjm.HP.COM (Walter Murray) (08/15/89)
Walter Bright writes: > Since <stdio.h> is supplied by the *vendor*, > the problem can be solved in one of two ways, > 1. In stdio.h, include the lines: > #ifndef __STDARG_H /* #define'd by stdarg.h */ > #include <stdarg.h> /* get definition of va_list */ > #endif The problem with this is that it causes trouble for a program like the following, which I think is perfectly legal. #include <stdio.h> #define va_start "My own personal macro" static char *va_list = va_start; main(){printf ("%s\n", va_list);} Note that names like va_start and va_list are not reserved for the implementation if the program has not explicitly included any associated header. Walter Murray -------------
scs@adam.pika.mit.edu (Steve Summit) (08/17/89)
In article <1140@midgard.Midgard.MN.ORG> dal@midgard.Midgard.MN.ORG (Dale Schumacher) writes: >In the <stdio.h> header file, the v[fs]printf() function prototypes >use the va_list type, but va_list is not defined anywhere in <stdio.h>. In article <10720@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >The answer is that the implementor of ><stdio.h> 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 <stdio.h> is not also the implementor of <stdarg.h>. 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 <stdarg.h> /* get definition of va_list */ > #endif This is the right idea, although it assumes that <stdarg.h> #defines __STDARG_H, which again an independently-written <stdio.h> can't do. (The #ifndef isn't really necessary; <stdarg.h> 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. <stdio.h> is not allowed to define the va_* macros. If I were the implementer of both <stdio.h> and <stdarg.h>, 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 <stdarg.h> would then contain #include <va_list.h> typedef __va_list va_list; and <stdio.h> would contain #include <va_list.h> 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 <stdio.h> is in any case only barely workable for implementers of both <stdio.h> and <stdarg.h> (i.e compiler and/or RTL vendors). It is apparently impossible to write a correct, standalone <stdio.h>, 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 <stdio.h>. 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
scs@adam.pika.mit.edu (Steve Summit) (08/17/89)
Last night I posted a long article exploring the impossibility of writing a standalone stdio.h, that is, one that does not not somehow "know" the underlying type of a va_list without #including <stdarg.h>. Doug Gwyn is about to post an article saying that allowing standalone reimplementation of parts of the C run-time library was never an X3J11 requirement, and I'm sure that's true, but I don't have to like it. In fact, there is a way out of this particular dilemma, although it's too late now. The essential problem is the requirement that <stdio.h> contain prototypes for vprintf, vfprintf, and vsprintf. The v*printf family are "crossover functions:" they combine functionality from the stdio and stdarg (nee varargs) subportions of the library. In languages with more formal type and class concepts, explicit means are often required to implement such crossover functions, such as the "friend" function notation of C++. A solution would have been to acknowledge the special nature of the v*printf by putting them in their own header file, vprintf.h: #include <stdio.h> #include <stdarg.h> extern int vprintf(char *, va_list); extern int vfprintf(FILE *, char *, va_list); extern int vsprintf(char *, char *, va_list); In general, I'd have preferred it if X3J11 had been somewhat more granular in their assignment of new header files. As another example, it would be convenient if malloc, realloc, and free were in a <malloc.h> rather than lumped in with everything else in <stdlib.h>. (This could make it easier for implementors of debugging versions of malloc, intended to replace or sit atop the vendor-supplied one.) I realize that picking the right header file granularity involves tradeoffs. There are probably programmers who dislike having to #include everything under the sun and would prefer an opposite extreme, something along the lines of <libc.h> or <everything.h>. Many of my source files start out with 15 or 20 #include directives, and while this may not be ideal, I much prefer the flexibility that finer granularity affords. Steve Summit scs@adam.pika.mit.edu
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/17/89)
In article <13572@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes: >...which is difficult if the implementor of <stdio.h> is not also >the implementor of <stdarg.h>. It is, reasonably I think, assumed that the Standard C implementation on a system is provided as a single integrated whole, rather than assembled piecemeal from several uncooperative sources. >deep breath, and add something like va_list.h: > #ifndef _VA_LIST > #define _VA_LIST > typedef int *__va_list; > #endif ><stdarg.h> would then contain > #include <va_list.h> > typedef __va_list va_list; >and <stdio.h> would contain > #include <va_list.h> > extern int vfprintf(FILE *, char *, __va_list); That's one way to correctly implement these headers (except that the "char*" parameter should be "const char*"). >(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.) Also note that size_t and NULL are defined in more than one standard header; NULL is not much of a problem because of benign redefinition, but since size_t is a typedef it must be protected by some sort of one-time interlock. >It is apparently impossible to write a correct, standalone <stdio.h>, >which is what Dale Schumacher is trying to do. Sure it is, along the lines I suggested. It just won't be fully portable, that's all. But nobody claimed that a fully portable implementation of the standard C library was possible in the first place. Actually I don't think you are absolutely required to use prototypes in the standard header function declarations, except for the ,... functions (which vfprintf() is not). >Also in article <10720@smoke.BRL.MIL>, Doug writes: >>Warning! Use __iob or _Iob, not _iob, in your <stdio.h>. >I'm not sure what is implied here. You should read Sue Meloy's article in the Journal of C Language Translation. Consider: #include <stdio.h> func() { int _iob; _iob = getchar(); }
nfs@notecnirp.Princeton.EDU (Norbert Schlenker) (08/17/89)
In article <10739@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >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 <stdarg.h> /* get definition of va_list */ >- #endif > >No, don't do this. <stdio.h> is not allowed to define the va_* macros. What is <stdio.h> allowed to define? It has to pick up <stddef.h>, because the prototypes in <stdio.h> use size_t. What makes <stddef.h> allowable and <stdarg.h> forbidden?
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/18/89)
In article <18684@princeton.Princeton.EDU> nfs@notecnirp.UUCP (Norbert Schlenker) writes: >What is <stdio.h> allowed to define? It has to pick up <stddef.h>, because >the prototypes in <stdio.h> use size_t. What makes <stddef.h> allowable >and <stdarg.h> forbidden? <stdio.h> must not #include <stddef.h> either. Each standard header is allowed to declare/define only those identifiers specified in the Standard, plus others specifically reserved for implementation use (e.g. "_Iobuf"). For POSIX purposes, #defining _POSIX_SOURCE before including a standard header enables the declaration/definition of the additional identifiers specified in IEEE Std. 1003.1. Other such "feature macros" could be used to further extend the names supplied by the standard headers, but I'd recommend that separate headers be used instead.
datanguay@watmath.waterloo.edu (David Adrien Tanguay) (08/18/89)
Our compiler takes a different route to solve this problem. The parser knows about all the standard types and functions. stdio.h #defines its macros and tells the parser (with a #pragma) to turn on all the other stuff that is defined in stdio.h. Basically, va_list is an internal type which is aliased to the user visible name "va_list" when you #include <stdarg.h>. David Tanguay
bill@twwells.com (T. William Wells) (08/18/89)
In article <18684@princeton.Princeton.EDU> nfs@notecnirp.UUCP (Norbert Schlenker) writes:
: What is <stdio.h> allowed to define? It has to pick up <stddef.h>, because
: the prototypes in <stdio.h> use size_t. What makes <stddef.h> allowable
: and <stdarg.h> forbidden?
Only and exactly what is in the standard. Any names that it defines
that are not specified in the standard must be names that are noted as
reserved.
No, it doesn't have to include <stddef.h>: all it has to do is define
size_t itself. Along with interlocks to prevent multiple definitions.
---
Bill { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com
henry@utzoo.uucp (Henry Spencer) (08/19/89)
In article <13572@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes: >>Warning! Use __iob or _Iob, not _iob, in your <stdio.h>. > >I'm not sure what is implied here. It seems to me that _iob is >no more reserved that any other reserved identifier... >... Doug's point may just have to do with the >distinction between single and double leading underscores or >something.) Pretty much so. __iob and _Iob are both in the name space that is defined as available to the implementor and forbidden to the user. _iob is in the *user* name space and the implementation must not usurp it. -- V7 /bin/mail source: 554 lines.| Henry Spencer at U of Toronto Zoology 1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
henry@utzoo.uucp (Henry Spencer) (08/19/89)
In article <10766@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >You should read Sue Meloy's article in the Journal of C Language >Translation... How about a summary, Doug? Many of us thought JCLT was interesting until we saw the price tag, at which point we said "forget it". -- V7 /bin/mail source: 554 lines.| Henry Spencer at U of Toronto Zoology 1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
libes@cme.nbs.gov (Don Libes) (08/19/89)
In article <1989Aug18.184635.26773@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >In article <10766@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >>You should read Sue Meloy's article in the Journal of C Language >>Translation... > >How about a summary, Doug? Many of us thought JCLT was interesting until >we saw the price tag, at which point we said "forget it". I won't duplicate Doug's effort to post a summary of what was in the first issue, but I will say that V1#1 was worthwhile. In fact, I was extremely impressed. The articles were real "meat" articles spelling out problems and solutions to the real hard problems facing C implementors and programmers today. About half of the essays were absolutely superb. (The rest were just good.) I was especially impressed with a historical article by Plauger who always writes with incredible authority. He answered many questions that I had always wondered about. It is likely that you may see this material if you are a member of any of the C standards committees. Some of it has appeared before in those forums, although some of it is clearly new. Nonetheless, it is entirely different than, say, the C Users Journal (which I occasionally write for, and which is aimed at the C programmer) or this newsgroup (which has entirely too much chaff). JCLT is aimed at people designing C language tools, although it is certainly interesting to other parties (like me). As far as the price, I can't afford it either, but I am asking my employer to buy a subscription. (You'll notice this in your next tax increase.) If you are really as interested in C as you claim to be, get your employer to buy a copy for crissakes. Don Libes libes@cme.nist.gov ...!uunet!cme-durer!libes Disclaimer: I have no connection whatsoever to JCLT.
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/19/89)
In article <1989Aug18.184635.26773@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >How about a summary, Doug? Many of us thought JCLT was interesting until >we saw the price tag, at which point we said "forget it". Me too. However, if somebody is seriously trying to implement the C standard, a subscription to the JCLT may quickly pay for itself. I don't think I should attempt a summary of Sue's article; suffice it to say that it explained how H-P decided to deal with name-space issues in their ANSI C implementation.
bill@twwells.com (T. William Wells) (08/19/89)
In article <1989Aug18.184635.26773@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: : In article <10766@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: : >You should read Sue Meloy's article in the Journal of C Language : >Translation... : : How about a summary, Doug? Many of us thought JCLT was interesting until : we saw the price tag, at which point we said "forget it". Agreed. --- Bill { uunet | novavax | ankh | sunvice } !twwells!bill bill@twwells.com
henry@utzoo.uucp (Henry Spencer) (08/20/89)
In article <1515@muffin.cme.nbs.gov> libes@cme.nbs.gov (Don Libes) writes: >... I will say that V1#1 was worthwhile. In fact, I was >extremely impressed. > >The articles were real "meat" articles spelling out problems and >solutions to the real hard problems facing C implementors and >programmers today. Oh, I agree, the content is good stuff. It's just ludicrously priced. >As far as the price, I can't afford it either, but I am asking my >employer to buy a subscription. (You'll notice this in your next tax >increase.) If you are really as interested in C as you claim to be, >get your employer to buy a copy for crissakes. My employer would look at a PO for it, inquire "what's this?", and on finding out that it was costing about C$2 per page, say "what in God's name kind of paper is it printed on -- gold leaf?!?". The upshot would be "forget it". It is a mistake to assume that C implementors are all rich corporations to whom several hundred dollars a year is petty cash. -- V7 /bin/mail source: 554 lines.| Henry Spencer at U of Toronto Zoology 1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
diamond@csl.sony.co.jp (Norman Diamond) (08/22/89)
In article <13574@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes: >I realize that picking the right header file granularity involves >tradeoffs. There are probably programmers who dislike having to >#include everything under the sun and would prefer an opposite >extreme, something along the lines of <libc.h> or <everything.h>. >Many of my source files start out with 15 or 20 #include >directives, and while this may not be ideal, I much prefer the >flexibility that finer granularity affords. As a quality-of-implementation issue, both needs could be met. <stdlib.h> can just be a list of nested #include's of standard (well, not really standard, but what else do you call them) include files with a finer grain. (At least namespace pollution is not a problem in naming standard include files.) -- -- Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net) The above opinions are inherited by your machine's init process (pid 1), after being disowned and orphaned. However, if you see this at Waterloo or Anterior, then their administrators must have approved of these opinions.