Path: utzoo!attcan!uunet!husc6!mailrus!uflorida!novavax!twwells!bill From: bill@twwells.uucp (T. William Wells) Newsgroups: comp.std.c Subject: Re: __STDC__ and non-conforming ANSI C compilers Message-ID: <344@twwells.uucp> Date: 21 Jan 89 21:38:35 GMT References: <9391@smoke.BRL.MIL> <8731@megaron.arizona.edu> <9405@smoke.BRL.MIL> Reply-To: bill@twwells.UUCP (T. William Wells) Organization: None, Ft. Lauderdale Lines: 141 Summary: Expires: Sender: Followup-To: Distribution: Keywords: In article <9405@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) ) writes: : "Rough ANSI compliance" is meaningless : and useless to the portable application programmer. "Strict ANSI : compliance", on the other hand, is a meaningful notion of considerable : utility to the programmer. In order for it to HAVE this utility, : though, we need the symbol __STDC__ reserved for making the distinction. This is the key to the disagreement: you believe that "Rough ANSI compliance" is "useless to the portable application programmer". Others do not. While it is certainly true that an "almost" ANSI compiler can differ from the standard in any arbitrary way, I suggest that many such will often differ in uninteresting ways, or in ways that are easily dealt with. If this is the case (and the current situation seems to indicate that is how things will be), the "almost" ANSI compiler will be in much the same kind of class as one for BSD or SYSV, that is to say, one which has a core of common features but irritating differences from those in the class, and significant differences from those outside the class. In other words, "almost" ANSI would leave us in exactly the same situation we have now, but with one more common environment to deal with. For those who don't mind (or don't understand) the current situation, adding one more class of environments isn't likely to cause any perceived hardship. For those that do, doing so is like going back to the stone ages. On the other hand, those who want some way of discovering "almost" ANSI compliance have a valid point. Strictly speaking, if I run cc -D..., the compiler is no longer conforming; thus, the compiler ought not define __STDC__. Of course, there is nothing *preventing* the compiler writer from simply documenting that using certain compiler switches makes the compiler non-conforming, and leaving it at that. But if we do that latter, we defile the "purity" of __STDC__. But if we don't, we can't have programs whose compilation depends both on ANSI features and on compile time switches. Here is a suggestion: For "almost" ANSI compilers, I don't use __STDC__ to identify them; instead, I have a set of defines in a universal include file (which gets included before any of my include files) which I turn on for various features available with the compiler. This include file might look like: #ifdef sun3 /* standard SunOS compiler */ #define HAS_VOID #define BROKEN_VOID #define HAS_UCHAR #define HAS_ULONG ... #define SYS_DEFINED #endif #ifdef MSC /* Microsoft compiler */ #define ANSI_PREP #define ANSI_PROTO #define ANSI_INCLUDE #define HAS_VOID #define HAS_UCHAR #define HAS_ULONG ... #define SYS_DEFINED #endif ...etc. /* This SYS_DEFINED is a kludge; it is needed for those !@#$% compilers that define their own symbol and then go on to define __STDC__. Note that this is the only place __STDC__ gets referenced; if one wants an ANSI feature, one needs to have a define for it that gets set here. */ #ifndef SYS_DEFINED #ifdef __STDC__ #define ANSI_PREP #define ANSI_PROTO #define ANSI_INCLUDE #define HAS_VOID #define HAS_UCHAR #define HAS_ULONG ... #endif #endif #undef SYS_DEFINED Now then, we come to the question: what should an implementation do if some compile time switch renders the compiler nonconforming? One solution is for the compiler to reverse the above: without the switch, define __STDC__, with it, define a special symbol for the compiler. I think that is ugly; furthermore, it really doesn't deal with the situation. Since I set the compiler switch, I ought to know what way the switch changes the compiler's behavior; I should have arranged that, when using the switch, the program compiles correctly. In other words, what I want is a compiler which is ANSI, but which has just those changes represented by the compiler switch. (And if I want the compiler to not pretend to be ANSI, I can just -U__STDC__ or the equivalent.) I propose that __STDC__ == 0 be reserved (obviously only custom can apply here) for use by compilers that are conforming when no compiler switches are specified. Those compilers would set __STDC__ == 1 then. When the user specifies any switch that makes the compiler non- conforming, it sets __STDC__ to 0. There are two advantages to the above. The first is that the programmer gets a meaningful __STDC__, even when he has used a compile time switch. This is particularly useful when one is writing conforming (but not strictly conforming) programs which are to be portable between different environments. The second is more subtle: by defining a meaning for __STDC__ == 0, we have a standard by which we can judge the use of __STDC__; pressure to comply with this "standard" may help get rid of those compilers that use __STDC__ == 0 to mean that the compiler is "almost" ANSI. In summary: A compiler whose normal mode is not ANSI should not define __STDC__. A compiler whose normal mode is ANSI should define __STDC__ == 1. A compiler whose normal mode is ANSI, but which is operating in a different mode, specified by compile switches or other means which require the user to turn them on, defines __STDC__ == 0. --- Bill { uunet!proxftl | novavax } !twwells!bill