From: ari@tron.gun.DE (Andreas Arens)
Subject: gcc-141/222 cpp bug
Organization: GNUs Not Usenet
Distribution: gnu
Date: Thu, 10 Sep 1992 00:24:00 GMT

The following is a small patch that fixes two problems I found with
gcc-1.41 cpp. The second one also applies to gcc-2.2.2 cpp.

1. gcc-1.41 cpp (not gcc-2.x) has a problem with '=' in CPP_PREDEFINES.
   Including something like "-D__STRICT_NAMES__=1" in the macro works
   within gcc.c, but fails within cccp.c, since make_definition expects
   a ' ' instead of a '='. 

2. The following small input file demonstrates the problem:
-------cut-------
#define XX 0x00
echo XX
echo 0xEEED-XX
echo 0xEEEE-XX
echo 0xEEEF-XX
echo 0xEEED+XX
echo 0xEEEE+XX
echo 0xEEEF+XX
-----------------
   In normal mode (not with -traditional) the lines 0xEEEE+|-XX do not
   expand the macro XX. This is because ANSI C does not touch floating
   point numbers within the preprocessor. The preprocessor has a very
   rudimentary routine to detect numbers in such a case. It's only way
   to detect a floating point number is an 'e' or 'E' followed by
   a digit or '+' or '-'. Of course this can also happen if a macro is
   added to or subtracted from a hex number, as shown in the sample above.
   The second small patch allways forces the '+' or '-' to end the 
   token if it contained the character 'x' or 'X' before. This fix can
   easily be done to cccc.c in gcc-2.2.2 also.
----- patches follow ------
*** cccp.c	Wed Sep  2 18:01:29 1992
--- cccp.new.c	Wed Sep  9 21:17:35 1992
***************
*** 833,848 ****
  
    /* Do standard #defines that identify processor type.  */
  
    if (!inhibit_predefs) {
      char *p = (char *) alloca (strlen (predefs) + 1);
      strcpy (p, predefs);
      while (*p) {
        char *q;
        if (p[0] != '-' || p[1] != 'D')
  	abort ();
        q = &p[2];
!       while (*p && *p != ' ') p++;
        if (*p != 0)
  	*p++= 0;
        make_definition (q);
      }
--- 833,856 ----
  
    /* Do standard #defines that identify processor type.  */
  
    if (!inhibit_predefs) {
+     int hadeq;
      char *p = (char *) alloca (strlen (predefs) + 1);
      strcpy (p, predefs);
      while (*p) {
        char *q;
        if (p[0] != '-' || p[1] != 'D')
  	abort ();
        q = &p[2];
!       hadeq = 0;
!       while (*p && *p != ' ') {
! 	if (*p == '=' && !hadeq) {
! 	  *p = ' ';
! 	  hadeq = 1;
! 	}
! 	p++;
!       }
        if (*p != 0)
  	*p++= 0;
        make_definition (q);
      }
***************
*** 1648,1655 ****
--- 1656,1664 ----
  	 So copy all alphanumerics that follow without accumulating
  	 as an identifier.  Periods also, for sake of "3.e7".  */
  
        if (ident_length == 0) {
+ 	int is_an_intnum = 0;
  	while (ibp < limit) {
  	  while (ibp < limit && ibp[0] == '\\' && ibp[1] == '\n') {
  	    ++ip->lineno;
  	    ibp += 2;
***************
*** 1657,1669 ****
  	  c = *ibp++;
  	  if (!isalnum (c) && c != '.' && c != '_') {
  	    --ibp;
  	    break;
  	  }
  	  *obp++ = c;
  	  /* A sign can be part of a preprocessing number
  	     if it follows an e.  */
! 	  if (c == 'e' || c == 'E') {
  	    while (ibp < limit && ibp[0] == '\\' && ibp[1] == '\n') {
  	      ++ip->lineno;
  	      ibp += 2;
  	    }
--- 1666,1683 ----
  	  c = *ibp++;
  	  if (!isalnum (c) && c != '.' && c != '_') {
  	    --ibp;
  	    break;
+ 	  } else {
+ 	    /* this will catch 0x... and 0X..., which can also end in 'e' or 'E',
+ 	    but will break the token before '+' and '-' even if not traditional. */
+ 	    if (c == 'x' || c == 'X')
+ 	      is_an_intnum = 1;
  	  }
  	  *obp++ = c;
  	  /* A sign can be part of a preprocessing number
  	     if it follows an e.  */
! 	  if (!is_an_intnum && (c == 'e' || c == 'E')) {
  	    while (ibp < limit && ibp[0] == '\\' && ibp[1] == '\n') {
  	      ++ip->lineno;
  	      ibp += 2;
  	    }

Newsgroups: gnu.gcc.bug