[gnu.gcc.bug] Behavior of normal gcc vs. `-traditional'

earle@MAHENDO.JPL.NASA.GOV (Greg Earle) (10/13/88)

I'm curious about the differences between `normal' gcc and when using the
`-traditional' switch.  I see things that aren't mentioned in the gcc manual
page.  For example:

[ Aside: no SunView flames, please - I use X11R2 95% of the time
  on my own Sun-3; a disk error crunched some programs and I'm using the
  source to rebuild them instead of restoring from the release tapes - GKE  ]

Most SunView programs use the following construct to create icons:

	static short icon_image[] = {
	#include <images/someimagefromiconedit.icon>
	};
	mpr_static(icon_pixrect, 64, 64, 1, icon_image);

This construct seems to annoy gcc quite a bit, but using the `-traditional'
switch makes gcc perfectly happy.  For example, try building the `clock'
program (sources are in /usr/src/sun/suntool; anyone can do this); I used
gcc v1.29 (vanilla) on a Sun-3/160 running SunOS 4.0:

poseur:2:88 # make -n clock
gcc -v -c -O -DSTANDALONE clock.c
gcc -v -c -O -DSTANDALONE clockhands.c
gcc -v -c -O -DSTANDALONE clockhands.rom.c
gcc -v -O clock.o clockhands.o clockhands.rom.o -o clock -lsuntool -lsunwindow -lpixrect -lrpcsvc -lm

poseur:2:89 # gcc -v -c -O -DSTANDALONE clock.c
gcc version 1.29
 /usr/local/lib/gcc-cpp -v -DSTANDALONE -undef -D__GNU__ -D__GNUC__ -Dmc68000 -Dsun -Dunix -D__OPTIMIZE__ -D__HAVE_68881__ -Dmc68020 clock.c /tmp/cca00375.cpp
GNU CPP version 1.29
/usr/include/suntool/panel.h:35: warning: garbage at end of #ifdef argument
/usr/include/suntool/panel.h:185: warning: garbage at end of #ifdef argument
 /usr/local/lib/gcc-cc1 /tmp/cca00375.cpp -quiet -dumpbase clock.c -O -version -o /tmp/cca00375.s
GNU C version 1.29 (68k, MIT syntax) compiled by GNU C version 1.29.
clock.c:46: parse error before `_data'
clock.c:46: initializer for scalar variable requires one element
clock.c:46: warning: data definition lacks type or storage class
clock.c:46: parse error before `_data'
clock.c:51: parse error before `_data'
clock.c:51: redefinition of `_data'
clock.c:46: previous declaration of `_data'
clock.c:51: initializer for scalar variable requires one element
clock.c:51: warning: data definition lacks type or storage class
clock.c:51: parse error before `_data'
clock.c: In function clock_update_tmp:
clock.c:397: warning: `clock_update_tmp' was declared implicitly `extern'
and later `static'

poseur:2:90 # gcc -v -c -O -traditional -DSTNDALONE clock.c
gcc version 1.29
 /usr/local/lib/gcc-cpp -v -DSTANDALONE -undef -D__GNU__ -D__GNUC__ -Dmc68000 -Dsun -Dunix -D__OPTIMIZE__ -traditional -D__HAVE_68881__ -Dmc68020 clock.c /tmp/cca00388.cpp
GNU CPP version 1.29
 /usr/local/lib/gcc-cc1 /tmp/cca00388.cpp -quiet -dumpbase clock.c -O -traditional -version -o /tmp/cca00388.s
GNU C version 1.29 (68k, MIT syntax) compiled by GNU C version 1.29.
 as -mc68020 /tmp/cca00388.s -o clock.o

poseur:2:91 #

Here's the code context (lines 46, 51 included):

poseur:2:91 # sed -n '42,52p' clock.c

static  u_short icon_data[300] = {
#include <images/clock.icon>
};
mpr_static(clock_default_mpr, 64, 75, 1, icon_data);		Line 46

static u_short icon_rom_data[300] = {
#include <images/clock.rom.icon>
};
mpr_static(clock_default_rom_mpr, 64, 75, 1, icon_rom_data);	Line 51

-------------------------------------------------------------------------

`mpr_static' is a macro (defined in <pixrect/memvar.h>) that looks like this:

/* First a pair of utility macros that allow concatenation in a fashion that
 * won't annoy lint (These belong in a standard header file!):
 */
#ifndef CAT
#undef  IDENT
#define IDENT(x)        x
#define CAT(a,b)        IDENT(a)b
#endif

#define mpr_static(name, w, h, d, image) \
	struct mpr_data CAT(name,_data) = \
		{mpr_linebytes(w,d), (short *)(image), {0, 0}, 0, 0}; \
	Pixrect name = {&mem_ops, w, h, d, (caddr_t)&CAT(name,_data)}

-------------------------------------------------------------------------

It looks like normal gcc doesn't like the Sun `CAT' macro, and therefore
refuses to concatenate the `clock_default_mpr' with `_data', thus leaving a
space between them (the output from gcc-cpp is
	# 44 "clock.c"

};
struct mpr_data clock_default_mpr _data  = {( ... )

whereas `-traditional' gcc concatenates them OK.  gcc also seems to not
like non-alphanumeric (i.e., `.' - the include file has an `#ifdef ecd.color'
in it, causing the gcc-cpp diagnostics above)

So, why does `normal' (i.e., `non-traditional' (^: ) gcc complain about these
lines??  Is this form of concatenation macro no longer valid ANSI C?  Are
non-alphanumeric characters in `#ifdef' statements also illegal?  (I note that
adding `-ansi' has no effect on the diagnostics)

	- Greg Earle
	  Sun Los Angeles Consulting
	  earle@Sun.COM
	  earle@mahendo.JPL.NASA.GOV	(Guest account)

Ed@ALDERAAN.SCRC.SYMBOLICS.COM (Ed Schwalenberg) (10/13/88)

    Date: Thu, 13 Oct 88 02:11:22 PDT
    From: Greg Earle <earle@mahendo.jpl.nasa.gov>
    ...
    /usr/include/suntool/panel.h:35: warning: garbage at end of #ifdef argument
    ...
    gcc also seems to not
    like non-alphanumeric (i.e., `.' - the include file has an `#ifdef ecd.color'
    in it, causing the gcc-cpp diagnostics above)
    ...
    So, why does `normal' (i.e., `non-traditional' (^: ) gcc complain about these
    lines??  ...  Are
    non-alphanumeric characters in `#ifdef' statements also illegal?  (I note that
    adding `-ansi' has no effect on the diagnostics)

Even K&R describes the token after an #ifdef as an identifier, meaning it may
use only the characters A-Z, a-Z, and _.  Various compilers will do various
horrible things in this situation; the gcc cpp is the only one I know of which
will give a reasonable, understandable error message instead of making a random
assumption and quietly screwing the user.

In short, the author of the code in question needs to change his .'s into
_'s, after checking that "ecd_color" doesn't already mean something else.