[comp.lang.c] Standard Clarification

Tim_CDC_Roberts@cup.portal.com (10/20/89)

While attepting to test some of the entries in the Obfuscated C Contest,
I find that Microsoft C 5.0 fails to compile constructs such as the
following:

    #define d define
    #d a include
    #a <stdio.h>

MSC complains that "d" is an unknown preprocessor directive and aborts.
Does the standard require that this construct should compile correctly?

I also encountered one occurrance of something like the following:

    #include <stdio.h>
    #define abcde getchar
           ...
      ch = abcde();

The preprocessor substituted 'getchar' for 'abcde', but then failed to
expand the 'getchar()' macro from stdio.  This resulted in an "Unresolved
External: _getchar" at load time.  Isn't the preprocessor legally and 
morally bound to recursively substitute macros, at least until a cycle
is found?

Tim_CDC_Roberts@cup.portal.com                |  I Survived The
...!sun!portal!cup.portal.com!tim_cdc_roberts |  Great Quake of '89.

henry@utzoo.uucp (Henry Spencer) (10/22/89)

In article <23218@cup.portal.com> Tim_CDC_Roberts@cup.portal.com writes:
>    #define d define
>    #d a include
>    #a <stdio.h>
>
>MSC complains that "d" is an unknown preprocessor directive and aborts.
>Does the standard require that this construct should compile correctly?

Section 3.8.3 (Oct 1988 draft, roughly current except for wording changes):

"If a # preprocessing token, followed by an identifier, occurs lexically
at the point at which a preprocessing directive could begin, the identifier
is not subject to macro replacement."

In other words, ANSI C specifically says that it *doesn't* work.

>    #define abcde getchar
>           ...
>      ch = abcde();
>
>The preprocessor substituted 'getchar' for 'abcde', but then failed to
>expand the 'getchar()' macro from stdio...

Unless I have missed some fine point, your preprocessor is wrong again.
This is legal.

It should be remembered that the preprocessor was *very* vaguely defined
in the old days, and tricky fine points like this varied widely, indeed
wildly, between implementations.  ANSI C has nailed down most of it, but
the macro-replacement section in the draft standard is easily one of the
two or three trickiest parts of the whole document.  (Indeed, there are
still one or two small fuzzy areas that were overlooked.)  It will be
quite a while before all preprocessors comply exactly.
-- 
A bit of tolerance is worth a  |     Henry Spencer at U of Toronto Zoology
megabyte of flaming.           | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/22/89)

In article <23218@cup.portal.com> Tim_CDC_Roberts@cup.portal.com writes:
>    #define d define
>    #d a include
>Does the standard require that this construct should compile correctly?

No, it requires that a diagnostic be issued.

>Isn't the preprocessor legally and morally bound to recursively
>substitute macros, at least until a cycle is found?

Yes; I suspect in the case you reported the compiler failed to look
beyond the replacement buffer for the () necessary for the getchar()
expansion to be triggered.  That's a bug.

davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (10/25/89)

In article <1989Oct21.233915.23217@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:

|  Section 3.8.3 (Oct 1988 draft, roughly current except for wording changes):
|  
|  "If a # preprocessing token, followed by an identifier, occurs lexically
|  at the point at which a preprocessing directive could begin, the identifier
|  is not subject to macro replacement."
|  
|  In other words, ANSI C specifically says that it *doesn't* work.

Another thing doesn't work, although it would be useful. If you have
macros of the form:

	#define FOO		123
	#define BAR		FOO
	#define DEMO(c) 	printf("Demo:"#c"\n")
then:
	DEMO(BAR);
does not do a substitution of FOO for BAR, nor 123 for FOO. To make this
work the value of the argument must be forced to be evaluated first.
	#define XDEMO(c)	DEMO(c)
and:
	XDEMO(BAR);
now substitutes 123. This is how I would expect it to work, from the
section you quote. Both gcc and a beta of MSC work just that way.

Test prog for the terminally curious:

#define FOO		123
#define BAR		FOO
#define X(c)		printf("X:"#c"\n")
#define TMP(c)		X(c)

X(FOO);
X(BAR);
TMP(BAR);

-- 
bill davidsen	(davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
"The world is filled with fools. They blindly follow their so-called
'reason' in the face of the church and common sense. Any fool can see
that the world is flat!" - anon

johnsc@microsoft.UUCP (John Schwabacher) (10/25/89)

In article <1989Oct21.233915.23217@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
}In article <23218@cup.portal.com> Tim_CDC_Roberts@cup.portal.com writes:
}> ... ["#define d define" example removed]
}>MSC complains that "d" is an unknown preprocessor directive and aborts.
}>Does the standard require that this construct should compile correctly?
} ... [ANSI spec removed]
}In other words, ANSI C specifically says that it *doesn't* work.
}
}>    #define abcde getchar
}>           ...
}>      ch = abcde();
}>
}>The preprocessor substituted 'getchar' for 'abcde', but then failed to
}>expand the 'getchar()' macro from stdio...
}
}Unless I have missed some fine point, your preprocessor is wrong again.
}This is legal.
}

Wait a minute. "Wrong again"?  You just said MSC got the first one right.

When I tried the "#define abcde getchar" using MSC 5.10, it worked fine.
I don't have 5.0 handy, so I can't say about that.

*None* of the Obscure C contest winners that I tried to build under Xenix
worked correctly.  Bummer.

henry@utzoo.uucp (Henry Spencer) (10/25/89)

In article <8189@microsoft.UUCP> johnsc@microsoft.UUCP (John Schwabacher) writes:
>}Unless I have missed some fine point, your preprocessor is wrong again.
>}This is legal.
>}
>
>Wait a minute. "Wrong again"?  You just said MSC got the first one right.

As I recall, the original posting discussed two different compilers, one
of which got the first one wrong too.  I should have been clearer.
-- 
A bit of tolerance is worth a  |     Henry Spencer at U of Toronto Zoology
megabyte of flaming.           | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

seanf@sco.COM (Sean Fagan) (10/27/89)

In article <11374@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>>Isn't the preprocessor legally and morally bound to recursively
>>substitute macros, at least until a cycle is found?
>Yes; I suspect in the case you reported the compiler failed to look
>beyond the replacement buffer for the () necessary for the getchar()
>expansion to be triggered.  That's a bug.

Which is fixed in MSC 5.1 (I believe).  At least, it's fixed in our Latest
and Greatest compilers for SCO *nix, which are based on MSC 5.1 currently.

Horrible looking code is generated, though (C code, not the assembly).

-- 
Sean Eric Fagan  | "Time has little to do with infinity and jelly donuts."
seanf@sco.COM    |    -- Thomas Magnum (Tom Selleck), _Magnum, P.I._
(408) 458-1422   | Any opinions expressed are my own, not my employers'.