[comp.std.c] __STDC__ and non-strictly conforming ANSI C compilers

hansen@pegasus.ATT.COM (Tony L. Hansen) (12/14/88)

What do people think a compiler should do with __STDC__ if it is not
strictly conforming? That is, if the compiler conforms to the spec, but has
some of the "common" extensions? Examples are compilers which extend the
31-character name limit to flexnames, permit additional keywords such as
"far" and "near", or have additional functions available such as "read()"
and "write()".

I've seen three solutions so far in as many compilers which plan on being
ANSI C compatible. Each compiler offers different flavors (strictly
conforming versus conforming with extensions) dependent on switches chosen
when compiling. The default is non-strictly conforming for all compilers
I've seen so far.

    1)	Only the strictly conforming flavor will have __STDC__ defined, and
	then to "1".

    2)	In non-strictly conforming mode, __STDC__ will be defined but will
	have a value of "0".

    3)	In all modes, __STDC__ will be defined with the value of "1".

Which choice should be the correct one? Should the Rationale say something
about it? Is there a 4th choice not listed above?

					Tony Hansen
				att!pegasus!hansen, attmail!tony
				    hansen@pegasus.att.com

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/14/88)

In article <3236@pegasus.ATT.COM> hansen@pegasus.att.com writes:
>What do people think a compiler should do with __STDC__ if it is not
>strictly conforming?

Obviously the actual standard cannot constrain nonconforming
implementations.  However, any implementation that defines
__STDC__ at all in a non-conforming mode is doing a severe
disservice to the C programming community.  __STDC__ is
intended to indicate standard conformance, and nothing else,
certainly not "sort of conforming but different in ways I
think you might like, sorry if it breaks your code".

Please don't define __STDC__ at all for non standard-
conforming implementations, even if they provide a lot of
so-called "ANSI C" features.  Programmers are likely to use
either
	#if __STDC__
or
	#ifdef __STDC__
to conditionalize sections of code based on "house C" vs.
"standard C".  In fact I already use the former that way.
I assume full ANSI C conformance when the test succeeds.
I don't think I should have to write
	#if __STDC__ == 1
which would force me to perform massive edits when the next
C standard bumps the value of __STDC__ to 2.

sjs@jcricket.ctt.bellcore.com (Stan Switzer) (12/14/88)

In article <9167@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
> In article <3236@pegasus.ATT.COM> hansen@pegasus.att.com writes:
> >What do people think a compiler should do with __STDC__ if it is not
> >strictly conforming?
> 
> Obviously the actual standard cannot constrain nonconforming
> implementations.  However, any implementation that defines
> __STDC__ at all in a non-conforming mode is doing a severe
> disservice to the C programming community. ...
> 
> Please don't define __STDC__ at all for non standard-
> conforming implementations, even if they provide a lot of
> so-called "ANSI C" features. ...

I certainly agree with Doug here, and I hope that the vendor community
goes along with him in this regard.

Back to some of the original examples though:

A compiler that accepts identifiers longer than 31 characters or even
arbitrarily long identifiers is still a conforming compiler.  It is
only those which do not accept at least 31 characters uniqueness
(within a compilation unit) which do not conform.

A compiler that reserves "near" and "far" as keywords is no-way no-how
a conforming compiler.  Period.  IF such "features" are required (and
I'll admit that if you are stuck writing code that has to be aware of
segments it is nice to have them) then they should go by the names
"_near" or "_far" which is in the vendor's reserved name space.
Perhaps there could be compiler options (-Dfar=_far) which map "near"
and "far" onto the actual keywords.

The committee has gone to great lengths to make strictly-conforming
programs highly portable.  It'd be a shame if the vendors were to
undermine that effort by adding gratuitous "extensions" that break
these programs.  I, for one, am looking forward to that day when it
will be possible to write interesting and portable C programs that are
not sprinkled throughout with "#ifdef" directives.  But in the
interim, I hope that when I say "#ifdef __STDC__" I get no ugly
surprises.

Stan Switzer  sjs@ctt.bellcore.com

gmt@arizona.edu (Gregg Townsend) (12/15/88)

In article <3236@pegasus.ATT.COM> hansen@pegasus.att.com writes:
> What do people think a compiler should do with __STDC__ if it is not
> strictly conforming?

It's important to consider how __STDC__ can and will be used.  I help to
maintain a software system that runs under a large number of environments.
I'd like to be able to check __STDC__ to see if I can (& must) use newstyle
token pasting, "void *", prototypes, and other such things.

If a compiler isn't strictly conforming only because it has an "asm" keyword
or similar extension, then undefining __STDC__ isn't going to help anyone who
uses a variable named "asm".  I don't see how undefining it helps ANYTHING
in this case.

Clearly, a strictly conforming compiler should define __STDC__ as 1, and a
K&R compiler shouldn't define it.  If a compiler is essentially "ANSI C
with extensions", and it can reasonably be expected to process most
conforming programs without problems, then it's less misleading to define
__STDC__ than not.  The useful distinction is "K&R" vs. "ANSI", not "pure
compilers" vs. "all others".

I agree that compilers shouldn't break programs by adding gratuitous
extensions.  But if they do, undefining __STDC__ won't help.

    Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
    +1 602 621 4325      gmt@Arizona.EDU       110 57 16 W / 32 13 45 N / +758m

jss@hector.UUCP (Jerry Schwarz) (12/15/88)

In article <9167@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>Programmers are likely to use
>either
>	#if __STDC__
>or
>	#ifdef __STDC__
>to conditionalize sections of code based on "house C" vs.
>"standard C".  In fact I already use the former that way.
>I assume full ANSI C conformance when the test succeeds.
>I don't think I should have to write
>	#if __STDC__ == 1
>which would force me to perform massive edits when the next
>C standard bumps the value of __STDC__ to 2.

I agree that you should not have to test the value of __STDC__.  
But I reach an opposite conclusion about what vendors ought to
do. If I arrange that my code is conforming (or strictly
conforming according to taste) when __STDC__ is defined that is about
all I can do.  If I want to make an accomodation to house C then I
should test for something defined in the house C.  Knowing that an
implementation is not conforming is useless unless I know how it
fails to conform.

If a vendor offers both a conforming ANSI and variations, it is
reasonable  that a version containing extensions (e.g. new keywords)
also have __STDC__ set.  If I choose to compile with the version
with extensions then its probably because I want (some of) the extensions.
This means I must accept the burden of making the code work in the
presense of the extension.

Doug would seem to encourage code such as

	#ifdef __STDC__
		char* p ;
	#else
		near char* p ;
	#endif

I want to discourage such code.  The use of "near" ought to be
conditioned on some positive assertion about the compilation system,
not merely that it isn't conforming.

Jerry Schwarz
AT&T Bell Labs, Murray Hill

bradb@ai.toronto.edu (Brad Brown) (12/15/88)

In article <3236@pegasus.ATT.COM> hansen@pegasus.att.com writes:
>What do people think a compiler should do with __STDC__ if it is not
>strictly conforming? ...
>
>I've seen three solutions so far in as many compilers which plan on being
>ANSI C compatible. ...
>
>    1)	Only the strictly conforming flavor will have __STDC__ defined, and
>	then to "1".
>
>    2)	In non-strictly conforming mode, __STDC__ will be defined but will
>	have a value of "0".
>
>    3)	In all modes, __STDC__ will be defined with the value of "1".
>
>Which choice should be the correct one? Should the Rationale say something
>about it? Is there a 4th choice not listed above?

What about having all strictly conforming compilers, including those
with extentions, define __STDC__ -- personally I don't care much what
the value is, and I think most people would not bother to check.  THEN,
when a compiler has extentions, define a couple of new #defines, perhaps
minimally just __STDCEXT__ to indicate that extentions exist.

In most compilers I have seen on the IBM PC, there are standard #defines
for the memory model that the program is currently being compiled for
and for the specific model of compiler.  I guess this is as close as you
could come to defining what the extention flags mean (they have to be
implementation-specific because there's always going to be some new
machine with some new feature) but maybe the standard could say you have
to have a __STDCEXT__ when extentions are present...

					(-:  Brad Brown  :-)
					bradb@ai.toronto.edu

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/15/88)

In article <12643@bellcore.bellcore.com> sjs@sjs@ctt.bellcore.com (Stan Switzer) writes:
>I hope that when I say "#ifdef __STDC__" I get no ugly surprises.

Everything Stan said was correct.

Note that macros such as "near" can be defined (as "__near", for
example) in any non-standard header, as well as under control of
compiler options or a special non-ANSI, backward-compatible
version of the cc command.  The constraints against pollution of
the name space by implementations is a great advance in sanity
and should be taken quite seriously.

Let me add that the so-called "common extensions" listed in the
proposed standard are not all guaranteed to be permitted in
conforming implementations.  Some are, and some aren't.  I don't
think that section even belongs in the standard, but I was
obviously outnumbered.  Politics, politics.

jss@hector.UUCP (Jerry Schwarz) (12/15/88)

In article <9187@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>
>Note that macros such as "near" can be defined (as "__near", for
>example) in any non-standard header, as well as under control of
>compiler options or a special non-ANSI, backward-compatible
>version of the cc command.  The constraints against pollution of
>the name space by implementations is a great advance in sanity
>and should be taken quite seriously.

Lets suppose we take the version route.  Assume that the only
difference between the versions is the treatment of "near". The
question that started this topic was whether the non-conforming
version should define __STDC__.  My answer is yes.  I think Doug's
answer is no.

Does the answer depend on which of the following commands is used
to invoke the non-conforming compiler?

	xcc prog.c
	cc -extended prog.c
	cc -Dnear=__near prog.c

Jerry Schwarz
AT&T Bell Labs, Murray Hill


r

henry@utzoo.uucp (Henry Spencer) (12/16/88)

In article <3236@pegasus.ATT.COM> hansen@pegasus.att.com writes:
>What do people think a compiler should do with __STDC__ if it is not
>strictly conforming? That is, if the compiler conforms to the spec, but has
>some of the "common" extensions? Examples are compilers which extend the
>31-character name limit to flexnames, permit additional keywords such as
>"far" and "near", or have additional functions available such as "read()"
>and "write()".

Much depends on *exactly* which extensions we are talking about, and
*exactly* how the compiler deals with them.  A compiler which will
correctly compile any strictly-conforming program, and will diagnose
any violation of the standard, has every right to define __STDC__ as 1
no matter how many extensions it also accepts.  Given the diagnostic
requirement, many extensions must draw warning messages, but there is
no requirement that a conforming implementation *reject* programs that
use extensions.

Mind you, it will be somewhat tricky for an implementation to conform
if it defines new keywords, since strictly-conforming programs may
quite legitimately use those words as identifiers.  It is possible that
an implementation might be able to cope with this by being clever and
adapting its behavior to the circumstances, given that strictly-conforming
programs will not be using those keywords in their special roles.

Pollution of the general-purpose name space, e.g. new reserved identifiers,
is a no-no for a conforming implementation.  This doesn't necessarily mean
that you can't supply new functions, but it does mean that nothing must go
wrong if the strictly-conforming program defines its own read() function
which is totally unrelated to the system one.

>... Each compiler offers different flavors (strictly
>conforming versus conforming with extensions) dependent on switches...

Uh, what is a "strictly conforming" implementation?  I find no such term
in the October draft.  There are conforming implementations (which accept
all strictly-conforming programs, and diagnose -- but don't necessarily
refuse to compile -- all violations of the ANSI syntax etc.) and non-
conforming implementations.  Period.

>    1)	Only the strictly conforming flavor will have __STDC__ defined, and
>	then to "1".
>
>    2)	In non-strictly conforming mode, __STDC__ will be defined but will
>	have a value of "0".
>
>    3)	In all modes, __STDC__ will be defined with the value of "1".
>
>Which choice should be the correct one? ...

Mode 3 is definitely wrong, since __STDC__ of 1 is supposed to indicate
a conforming implementation.  (I assume when you say "non-strictly
conforming", that means "non-conforming".)  Mode 2 is a very interesting
choice, given that it permits distinguishing "is this compiler modern,
accepting prototypes etc.?" from "is this a conforming implementation?"
(ask the former with "#ifdef __STDC__" and the latter with "#if __STDC__").
It appears to me that both modes 1 and 2 are consistent with the October
draft.  I would be very tempted to go with mode 2.
-- 
"God willing, we will return." |     Henry Spencer at U of Toronto Zoology
-Eugene Cernan, the Moon, 1972 | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

henry@utzoo.uucp (Henry Spencer) (12/16/88)

In article <9167@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>Please don't define __STDC__ at all for non standard-
>conforming implementations...
>I assume full ANSI C conformance when [#if __STDC__] succeeds.
>I don't think I should have to write
>	#if __STDC__ == 1
>which would force me to perform massive edits when the next
>C standard bumps the value of __STDC__ to 2.

Uh, Doug, why would you have to write the "== 1"?  "#if __STDC__" will
fail if __STDC__ is defined as zero.  "#ifdef __STDC__" is a different
story, mind you, but as I have pointed out in another posting, the
difference between the two could be useful.

The October draft says "__STDC__   The decimal constant 1, intended to
indicate a conforming implementation.".  It does not seem to me that
defining __STDC__ as 0 for an ANSI-like but non-conforming implementation
is *clearly* a violation of this.  Furthermore, it would appear to me
that only "#if __STDC__" is guaranteed to tell you whether it's a
conforming implementation, and "#ifdef __STDC__" should not be relied on,
given the existing wording.
-- 
"God willing, we will return." |     Henry Spencer at U of Toronto Zoology
-Eugene Cernan, the Moon, 1972 | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

guy@auspex.UUCP (Guy Harris) (12/16/88)

 >__STDC__ is intended to indicate standard conformance, and nothing else,
 >certainly not "sort of conforming but different in ways I
 >think you might like, sorry if it breaks your code".

I'll certainly agree with that for

 >Please don't define __STDC__ at all for non standard-
 >conforming implementations, even if they provide a lot of
 >so-called "ANSI C" features.

There have been reports of a compiler that defines __STDC__ even though
it provides *some*, but not all, ANSI C features; the authors of that
compiler should be horsewhipped.

However, what about a compiler that can be run in at least two modes,
one of which is "strict tight-sphincter ANSI C", meaning "no, there are
NO macros declared, or objects defined, that aren't listed by name in
the ANS, and there are NO other extensions permitted either", and one of
which is "ANSI C plus extensions", e.g. "we define some things in
#include files that may pollute the namespace"?

For instance, consider a program written for a POSIX environment, so
that it might not compile in "strict ANSI C" mode, but written so that
it can use function prototypes if they're present?  Should __STDC__ be
defined by the compiler running in "ANSI C plus extensions" mode, so
that the code can use "__STDC__" to determine whether function
prototypes, or "#" and "##", or... are supported?

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/16/88)

In article <8366@megaron.arizona.edu> gmt@arizona.edu (Gregg Townsend) writes:
>I agree that compilers shouldn't break programs by adding gratuitous
>extensions.  But if they do, undefining __STDC__ won't help.

Sure it will.  I certainly want to hear about it if my use of a
function asm(char*) conflicts with a vendor extension!  __STDC__
is defined as meaning "complies with the standard", and I want to
be able to be warned when the "" phrase does NOT apply -- no matter
WHAT the reason.
	#if !STDC__
	#include "*** ERROR *** This program requires real ANSI C"
	#endif

sjs@ctt.bellcore.com (12/16/88)

In article <9187@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>
> Note that macros such as "near" can be defined (as "__near", for
> example) in any non-standard header, as well as under control of
> compiler options or a special non-ANSI, backward-compatible
> version of the cc command.  The constraints against pollution of
> the name space by implementations is a great advance in sanity
> and should be taken quite seriously.

Proposing that a compiler which conforms but for the addition of a few
keywords should define __STDC__ Jerry Schwarz asks:
>
> Does the answer depend on which of the following commands is used
> to invoke the non-conforming compiler?
> 
> 	xcc prog.c
> 	cc -extended prog.c
> 	cc -Dnear=__near prog.c

This is fine as long as there is SOME set of options, preferably the
default, under which "near", "far", and, for that matter, all other
identifiers are just that: identifiers.

The important question is whether a __STDC__ compiler can be counted
upon to compile strictly conforming programs.  The following fragment
illustrates my point:

	# include <stdlib.h>
	int near( int i, int j ) {
		return ( abs(i-j) < 10 );
	}

If "near" is a reserved keyword this will not compile even though it
is strictly conforming.  It is much better for ALL reserved words
introduced for extensions to begin with "_" and be mapped from
non-underscore values only when requested via an option or an include
file.

I'm not saying that vendors shouldn't add extensions, just that they
should do it without encroaching on the user's name space.  The X3J11
committee as provided perfectly good and totally painless way of doing
this without breaking programs.  Any compiler that doesn't bother to
do it that way shouldn't go around defining "__STDC__".

Probably by now most of us will avoid using the identifier "near" in
our programs because we know that it is a keyword in some compilers.
But this is a point of principle: what other identifiers must we now
worry about?  Perhaps we'll have to start a newsletter to keep track
of the identifiers to avoid because some vendor or another has
made it a keyword.

Let's not let compiler vendors undermine the good work of the
committee toward ending name space pollution.

Stan Switzer  sjs@ctt.bellcore.com

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/16/88)

In article <11002@ulysses.homer.nj.att.com> jss@hector.UUCP (Jerry Schwarz) writes:
>If a vendor offers both a conforming ANSI and variations, it is
>reasonable  that a version containing extensions (e.g. new keywords)
>also have __STDC__ set.

I totally disagree.  Invent your own symbol for your non standard-
conforming implementation; don't overload the meaning of __STDC__.
AT&T has been guilty of FAR too many overloadings in C and UNIX
already.  I know you have heard of the concept of orthogonality;
how about applying it at least HERE where the intention is
unambiguous.

>Doug would seem to encourage code such as
>	#ifdef __STDC__
>		char* p ;
>	#else
>		near char* p ;
>	#endif

No, in fact I fully intend to be able to write:
	#if __STDC__
		#if _BRAIN_DAMAGED
			typedef __far void *far;
		#else
			typedef void *far;
		#endif
		extern far gcalloc(size_t size, far *handle);
	#else
	#	if _BRAIN_DAMAGED
			extern far char *gcalloc();
	#	else
			extern char *gcalloc();
	#	endif
	#endif
Note that I expect __STDC__ to not be true if "far" is defined
as a keyword, because that is not standard-conforming.

>The use of "near" ought to be conditioned on some positive assertion about the compilation system,
>not merely that it isn't conforming.

Quite true and quite obvious.

But __STDC__ must MEAN something or it's not reliably useful.  What would
you have it mean, if not "the implementation conforms with the standard"?

"__STDC__" belongs to X3J11.  We should have made it a trademark,
I suppose.  Don't play games with it.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/16/88)

In article <11005@ulysses.homer.nj.att.com> jss@hector.UUCP (Jerry Schwarz) writes:
>Does the answer depend on which of the following commands is used
>to invoke the non-conforming compiler?

The implementation should not predefine __STDC__ when the compiler
or library are invoked in non-conforming ways.  I realize that that
means that
	ansi_cc -PREDEF near __near foo.c
would have to, because of the standard-violating predefinition of
a symbol not reserved for implementation use, turn off its
predefinition of __STDC__.  The same is true for
	ansi_cc -OPTIM darnell foo.c
(meaning, use the "future direction" suggestion for [] in formal
function parameters), or for anything else you allow to be done to
bring the compilation environment into non-compliance.  This
suggests that the "ansi_cc" documentation should clearly state that
the use if such options will render the compilation environment non
standard-conforming and that __STDC__ will not be predefined in
such a case unless the user adds "-PREDEF __STDC__ 1" to the other
options.  This places the responsibility for safe use of
non-conforming features firmly in the user's hands, rather than
the implementor predefining __STDC__ in a case where it could
cause a problem.

Of course you could supply a "nonansi_cc" command that, with
appropriate combination of options as documented in the ANSI C
conformance guide you provide, would become the official
standard-conforming invocation.  In fact one of the options
you could require the user to provide is "-D__STDC__=1".
That's a whole lot better than you deciding to have the compiler
itself lie about __STDC__ness.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/16/88)

In article <721@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
>For instance, consider a program written for a POSIX environment, so
>that it might not compile in "strict ANSI C" mode, but written so that
>it can use function prototypes if they're present?  Should __STDC__ be
>defined by the compiler running in "ANSI C plus extensions" mode, so
>that the code can use "__STDC__" to determine whether function
>prototypes, or "#" and "##", or... are supported?

The answer is still, no, if the implementation environment does
not fully conform to the standard then it should not set __STDC__.

The reason is this:  The C standard has no "levels" or "options".
Standard conformance is a Boolean attribute, like pregnancy.
If the programmer's test for standard conformance "#if __STDC__"
is to be reliably used, it must mean something definite.  When a
vendor elects to set __STDC__ even though the environment is
not conforming with respect to feature X, there is no way he can
know whether or not the programmer relying on the __STDC__ flag
will have his code broken because of its reliance on standard
behavior with respect to feature X.  How do you know that the
only use the program will make of __STDC__ is for the grossly
different syntactic features (prototypes, pasting, etc.)?  The
answer is, although very likely most uses of __STDC__ will be
for that purpose, by no means all uses will be.  So if __STDC__
is to be 100% reliable it must mean exactly what X3J11 says it
means, and must not be defined otherwise (something that the
standard cannot require, but was thought to be self-evident).

What Jerry seems to want is to "borrow" some of the guarantees
that __STDC__ makes for use in a non standard-conforming
environment also.  Unfortunately for his purpose, __STDC__
promises compliance with the standard, not existence of some
specific subset of ANSI C-like features.

In the case where !__STDC__, things are exactly as messed-up
as always with regard to what features might exist and how
polluted the name space is.  But then, we really intend for
C programming to evolve so that most code is fully
standard conforming; __STDC__  gives the programmer a way to
code for both standard and "other" environments, if he has to
cope with both.  Obviously the "other" environment is not
well defined; that's why we drew up a standard!  Trying to
make a piece of the standard fix long-standing problems in
the "other" environment is not only hopeless, it can damage
the utility of the standard.

rbutterworth@watmath.waterloo.edu (Ray Butterworth) (12/16/88)

In article <1988Dec15.183822.2559@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
> it would appear to me
> that only "#if __STDC__" is guaranteed to tell you whether it's a
> conforming implementation

I think everyone is missing something very obvious.
The only thing that is guaranteed is that "#if !defined(__STDC__)"
will guarantee that the compiler is NOT an ANSI Standard C compiler.

There is nothing to stop a compiler (or cpp or any header file)
from defining __STDC__, so long as that compiler doesn't make claims
to being an ANSI Standard C compiler.  I don't believe that ANSI
has registered __STDC__ as their trademark.  It might have been
a better idea to use the identifier __ANSI__ instead, since they
could then legitimitely complain if say BSD were to put something
like  "#define __STDC__(a,b,c) printf(a,b,c)"  into their stdio.h.
It would be a silly thing to do, but as long as BSD doesn't claim
to be a "conforming ANSI implementation", it can do what it likes.

i.e. The Standard only says how conforming implementations must behave.
It has no control over how any compiler or library behaves if that
compiler or library doesn't claim to be fully conforming.

dhesi@bsu-cs.UUCP (Rahul Dhesi) (12/17/88)

Perhaps a solution would be for somebody to come up with a C compiler
validation suite, and also a trade-marked term such as "__VALIDC__".
Only vendors whose compilers had passed the suite would be permitted to
predefine this trade-marked symbol.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/17/88)

In article <1988Dec15.183200.2395@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>A compiler which will correctly compile any strictly-conforming program,
>and will diagnose any violation of the standard, has every right to
>define __STDC__ as 1 no matter how many extensions it also accepts.

This is correct, and the point should be emphasized that there are
standard-conforming ways to add many common extended features; if
there is a standard-conforming way to implement them, then that
should be used, and __STDC__ continue to be defined (as 1).

One really easy way to continue to support such things as "near"
in a standard-conforming environment is to require the applications
that need these historical but non-standard features to #include a
header that the implementation provides to define them, e.g.
	#include <brain-damaged.h>	/* gets "near", etc. */
	near int array[1000];
Of course what such a header would do is
	#define near __near	/* map to built-in conforming keyword */

As Henry pointed out, functions can be added to the standard C library,
so long as the implementation of the standard functions does not use them.

I have to disagree that defining __STDC__ as non-1 values, specifically
0, is a good idea.  Since there is no standard meaning for that, the
only use in portable programming would be
	#if __STDC__ == 1
which as I pointed out previously is quite undesirable.
	#ifdef __STDC__
should suffice; however,
	#if __STDC__
is what I use, just in case some implementation is stupid enough to
	#define __STDC__ 0
for a non-conforming environment, but I hope that nobody does that.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/17/88)

In article <1988Dec15.183822.2559@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
-In article <9167@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
->I don't think I should have to write
->	#if __STDC__ == 1
->which would force me to perform massive edits when the next
->C standard bumps the value of __STDC__ to 2.
-Uh, Doug, why would you have to write the "== 1"?  "#if __STDC__" will
-fail if __STDC__ is defined as zero.  "#ifdef __STDC__" is a different
-story, mind you, but as I have pointed out in another posting, the
-difference between the two could be useful.

It was suggested that __STDC__ be given values other than 0 or 1,
which is what I was addressing with the above comment,

-The October draft says "__STDC__   The decimal constant 1, intended to
-indicate a conforming implementation.".  It does not seem to me that
-defining __STDC__ as 0 for an ANSI-like but non-conforming implementation
-is *clearly* a violation of this.  Furthermore, it would appear to me
-that only "#if __STDC__" is guaranteed to tell you whether it's a
-conforming implementation, and "#ifdef __STDC__" should not be relied on,
-given the existing wording.

Actually, nothing at all can be relied on in a non standard-conforming
environment, including __STDC__ differing from 1!  That's what we're
discussing!  I don't want __STDC__ to even be defined -- no matter what
its value -- in a non standard-conforming environment.  I've made the
arguments for that previously and shouldn't have to repeat them here.

jss@hector.UUCP (Jerry Schwarz) (12/17/88)

In article <9198@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) 
presents a sample of some code

>	#if __STDC__
>		#if _BRAIN_DAMAGED
>			typedef __far void *far;
>		#else
>			typedef void *far;
>		#endif
>		extern far gcalloc(size_t size, far *handle);
>	#else
>	#	if _BRAIN_DAMAGED
>			extern far char *gcalloc();
>	#	else
>			extern char *gcalloc();
>	#	endif
>	#endif

This is conforming (it may work on some conforming compilers) but not
strictly conforming. It will fail on a conforming compiler that
defines _BRAIN_DAMAGED  and doesn't like __far.  A conforming
compiler is entitled to behave this way because you're stepping on
its reserved namespace.

I'd prefer to write something like the following strictly conforming
code.

#if BRAIN_DAMAGE1
	/* stuff to set up for one kind of brain damage */
#elif BRAIN_DATAGE2
	/* stuff for another kind of braindamage. */
#else
	/* This is the only code a conforming compiler will ever see */
	typedef void* far ;
#endif

Jerry Schwarz
AT&T Bell Labs, Murray Hill

I usually don't add a disclaimer, because I think they are redundant.
But the message I'm replying to took a gratuitous swipe at AT&T.  So
for the record:  These are my opinions.  I am not a member of the
department responsible for AT&T's C compilers.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/17/88)

In article <11018@ulysses.homer.nj.att.com> jss@hector.UUCP (Jerry Schwarz) writes:
>This is conforming (it may work on some conforming compilers) but not
>strictly conforming. It will fail on a conforming compiler that
>defines _BRAIN_DAMAGED  and doesn't like __far.  A conforming
>compiler is entitled to behave this way because you're stepping on
>its reserved namespace.

Yes, I know all that.  I had considered using BRAIN_DAMAGED instead,
but figured you would then ask how it got defined, and I didn't want
to get into that.  For purposes of the discussion, let's assume that
either every vendor with __far has agreed to predefine _BRAIN_DAMAGED,
or else change the name to something in the application's name space
and assume the application has arranged to enable it somehow.

Unfortunately, C has no way to test whether an identifier is already
typedefed.  There are numerous occasions when one wants to do that;
this was one of them.

The point of my example is that it is legitimate for me to treat "far"
as in the application's name space, if __STDC__ is set.

My swipe at AT&T was not "gratuitous".  Consider it a swipe at
Dennis if you want, for overloading "static" and "extern".  (They're
just the simplest C examples of problems brought on by lack of
orthogonality; there are many more in the UNIX C programming
environment.)  X3J11 had to work pretty hard in several areas to cope
with such problems; it would have been much better if they had been
handled right in the first place, when there was no existing practice
to protect.  Since we are in "the first place" with __STDC__, let's
try to get AT&T (and other vendors) to not try to multiplex meanings
onto it other than the one assigned by X3J11.

henry@utzoo.uucp (Henry Spencer) (12/18/88)

In article <12666@bellcore.bellcore.com> sjs@ctt.bellcore.com (Stan Switzer) writes:
>The important question is whether a __STDC__ compiler can be counted
>upon to compile strictly conforming programs.  The following fragment
>illustrates my point:
>
>	# include <stdlib.h>
>	int near( int i, int j ) {
>		return ( abs(i-j) < 10 );
>	}
>
>If "near" is a reserved keyword this will not compile even though it
>is strictly conforming...

Actually, it might, depending on your definition of "reserved keyword".
A truly devious compiler might turn off its predefined meaning for "near"
if "near" was encountered in a context indicating that the user was using
it himself.  (It is admitted that the ice might be thin here. :-))  This
would provide magic keywords *without* breaking standard conformance.
-- 
"God willing, we will return." |     Henry Spencer at U of Toronto Zoology
-Eugene Cernan, the Moon, 1972 | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

henry@utzoo.uucp (Henry Spencer) (12/18/88)

In article <9199@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>The implementation should not predefine __STDC__ when the compiler
>or library are invoked in non-conforming ways.  I realize that that
>means that
>	ansi_cc -PREDEF near __near foo.c
>would have to, because of the standard-violating predefinition of
>a symbol not reserved for implementation use, turn off its
>predefinition of __STDC__...

Barf.  Fortunately, no implementor in his right mind is going to do this,
because it will make either -D or __STDC__ (your choice) almost useless.
Well, perhaps that is a *slightly* over-strong statement, but it's still
close to true.  -Dfoo=bar is often used to supply things like configuration
parameters without having to modify source.  People who use it in this
manner are essentially saying "prepend '#define foo bar' to the file,
taking the result as the program to be compiled", not "change the
implementation by predefining foo".  Compiler implementors who insist
that any use of -D is an implementation change will be lynched by software
writers whose packages use -D as part of the program and who want __STDC__
to be a tool rather than a millstone around their necks.

(Speaking as such a software writer, I do *not* consider the suggestion
of doing an explicit -D__STDC__=1 every time to be helpful.  I don't
have to do this after every #define, I don't want to have to do it after
every -D in my Makefile either.)

Unfortunately, it is just a little bit hard for the implementation to
intuit whether a particular predefinition is one or the other.  There
really ought to be a way for a program to specify that a predefinition
of a particular identifier is expected.
-- 
"God willing, we will return." |     Henry Spencer at U of Toronto Zoology
-Eugene Cernan, the Moon, 1972 | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

blarson@skat.usc.edu (Bob Larson) (12/19/88)

In article <1988Dec18.043804.907@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>There
>really ought to be a way for a program to specify that a predefinition
>of a particular identifier is expected.

#ifndef FROBUZ
    ??= error	FROBUZ must be pre-defined!
#endif

(Note use of trigraph so non-ansi compilers won't refuse to compile
this if FROBUZ is defined.  This may be the place trigraphs are realy
useful.)
-- 
Bob Larson	Arpa: Blarson@Ecla.Usc.Edu	blarson@skat.usc.edu
Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson
Prime mailing list:	info-prime-request%ais1@ecla.usc.edu
			oberon!ais1!info-prime-request

henry@utzoo.uucp (Henry Spencer) (12/20/88)

In article <14134@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes:
>>There
>>really ought to be a way for a program to specify that a predefinition
>>of a particular identifier is expected.
>
>#ifndef FROBUZ
>    ??= error	FROBUZ must be pre-defined!
>#endif

No, you miss the point.  What I was saying was not "there ought to be a
way for a program to insist that a predefinition is required" but "there
ought to be a way for a program to tell the compiler that a predefinition
is legitimate and does not mess up the program".
-- 
"God willing, we will return." |     Henry Spencer at U of Toronto Zoology
-Eugene Cernan, the Moon, 1972 | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

english@stromboli.usc.edu (Joe English) (12/21/88)

In article <22765@watmath.waterloo.edu> rbutterworth@watmath.waterloo.edu (Ray Butterworth) writes:

>The only thing that is guaranteed is that "#if !defined(__STDC__)"
>will guarantee that the compiler is NOT an ANSI Standard C compiler.
>

True, since the "defined" directive does not exist in many pre-dpANS
compilers and will cause an error!

I'm still unclear on the meaning of __STDC__... does it mean
"supports prototypes, void, signed, etc.," or "strictly conforming,
no extensions?"  Or is this not specified?  


--Joe English
english@lipari.usc.edu

w-colinp@microsoft.UUCP (Colin Plumb) (12/21/88)

In article <14179@oberon.USC.EDU> english@stromboli.usc.edu (Joe English) writes:
>I'm still unclear on the meaning of __STDC__... does it mean
>"supports prototypes, void, signed, etc.," or "strictly conforming,
>no extensions?"  Or is this not specified?  

It means "will compile any strictly conforming program", strictly conforming
being a program which doesn't use any undefined or implementation-defined
features of the ANSI C standard.

It guarantees that there are no incompatible extensions to the language,
so any program that compiles without the extensions will also compile with
them.  New keywords or identifiers break this badly.

For an example of an extension that is okay with __STDC__=1, try:

anything using @ or $
(since they're not part of the C character set)
int c : 64;
(defining variables in terms of bits)
register int foo();
(e.g. for function inlining)
char x[0];
(as the last element of a struct; I can do malloc(sizeof mystruct + arraysiz);)

or any number of things that don't interfere with existing C.
-- 
	-Colin (uunet!microsof!w-colinp)

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/27/88)

In article <1988Dec18.043804.907@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>(Speaking as such a software writer, I do *not* consider the suggestion
>of doing an explicit -D__STDC__=1 every time to be helpful.  I don't
>have to do this after every #define, I don't want to have to do it after
>every -D in my Makefile either.)

There must be something wrong with your Makefiles, then.
For a large project, each Makefile should contain something like
	include ../../Make.defs
(actually we use three includable pieces in our biggest project)
so that things like CC and CFLAGS can be defined IN ONE PLACE as
appropriate for the target environment:

	CC = /usr/local/bin/ansi_cc
or
	CC = cc -ANSI -D__STDC__=1	# or whatever
or
	CFLAGS = -ANSI -D__STDC__=1	# or whatever

(/usr/local/bin/ansi_cc can be a shell script that supplies the
necessary flags to enter the standard-conforming mode.)

There is a lot more one could say about such configuration, but
this should be enough to demonstrate that "cc" by itself need
not be ANSI-conforming even if it provides (part of) the way
one invokes an ANSI-conforming compiler.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/27/88)

In article <14179@oberon.USC.EDU> english@stromboli.usc.edu (Joe English) writes:
>I'm still unclear on the meaning of __STDC__... does it mean
>"supports prototypes, void, signed, etc.," or "strictly conforming,
>no extensions?"  Or is this not specified?  

__STDC__ must be defined (and have the value 1) by any conforming
implementation.  There are not "degrees" or "levels" of conformance;
either an implementation is standard conforming or it is not.  (There
are, however, both "freestanding" and "hosted" environments, and an
implementation conforms to at most one of these at a time.)

The intention is for the very fact that __STDC__ is defined to
suffice to tip off the application source code that the C Standard
is conformed to, which enables it to use features not available in
older C compilers as well as to help accommodate changes mandated
by the Standard in a specific environment (unsigned-preserving to
value-preserving in UNIX environments, for example).  Somewhere
along the way it was decided that just being "defined" was too
vague, so for this version of the Standard at least, __STDC__ has
the value 1.  It really was not envisioned that non-conforming
implementations would define __STDC__ at all.  (But of course the
Standard is technically unable to constrain non-conforming
implementations.)