[net.bugs] Bug in System V and Berkeley C Preprocessors

clewis@mnetor.UUCP (Chris Lewis) (01/30/86)

I was trying to write a parameterized macro that I could refer to within an #if
control line.  Eg:

#define	TEST(x)	(x) != 1

#if	TEST(4)
	...
#endif

Pyramid cpp (appears to be BSD4.2 cpp) gives you "<line number>: syntax error", 
where "line number" is the "#endif".  

USG SVR1 cpp gives you
	<linenumber>: syntax error (in preprocessor if)

Where linenumber appears to be the "#if" line.

With "cc -E" BSD cpp generates on stdout:

	4 != 1
	...
#endif

I looked a little at the BSD source, and it looks like the "#if" expression
YACC parser only looks for expressions of the form:

	<expression> <operator> <expression>
	( <expression> )
	defined ( identifier )
	number

[Note: it appears that the bodies of "#" control lines are not expanded
willy-nilly before evaluation.  This is necessitated by the semantics
of "#define" on duplicate names.  cpp's functions that implement the
control lines seem to do the expansion themselves if they want to]

The lexical analyser looks for strings of characters that can be identifiers.
If it is the token "defined", it returns the "DEFINE" token to the YACC.  
Otherwise, it just assumes that the symbol is an ordinary unparameterized 
macro, does a table lookup for the value, and lexically analyses the result.

Hence, "#if" expression parsing will not handle parameterized macros.

GRRR.

I had to do the parameterized macro expansion with a sed script before
the code was compiled.  Yucko.

We didn't attempt to fix the problem because this was in production
code that has to be portable to unmodified cpp's.
-- 
Chris Lewis,
UUCP: {allegra, linus, ihnp4}!utzoo!mnetor!clewis
BELL: (416)-475-8980 ext. 321