From: RHEA::DECWRL::"elsie!ado@seismo.ARPA" 30-MAY-1985 12:08 To: seismo!minow%rex.DEC@decwrl Subj: scannumber et al. Received: from DECWRL by DEC-RHEA with SMTP; Thu, 30 May 85 09:06-PDT Received: from seismo.ARPA (seismo.arpa.ARPA) by decwrl.ARPA (4.22.01/4.7.34) id AA07004; Thu, 30 May 85 09:07:24 pdt Received: from elsie.UUCP by seismo.ARPA with UUCP; Thu, 30 May 85 12:05:38 EDT Date: Thu, 30 May 85 12:05:38 EDT Return-Path: Message-Id: <8505301605.AA11375@seismo.ARPA> > Have you been talking to Alan Feuer or what. He sent exactly > the same two comments today! Pure coincidence. Still astonishing. > The bloddy committee has added double to #if's, so you probably > have to do that conversion. (And properly handle integer divide > and modulus). Wonderful--so now programs with #if alpha == 2.0 directives won't be portable to "old" (read: ALL existing that I know of) compilers. I'm sure there's some overwhelming benefit to the ability to put floats in "#if"s that compensates for this--I'd sure like to hear it. > by the way, I don't think trigraphs will survive: the ANSI character > set committee found out about that hack and are planning to protest. Good to hear. What's the latest word on "sizeof" in "#if" directives? > > One of our fine-toothed-comb types has discovered that the routine > > scannumber botches parsing of floating point numbers. It fails to > > recognize > > > > 21e04 > > .21e+04 > > > > as floats. . . Well, "21e04" got handled correctly by the "cpp" we have, but the second case (and also "21e+04") got mishandled. The problem was that the variable "signseen" in the function "scannumber" got inappropriately set to TRUE at the bottom of the "for" loop. Here's my notion of a fix, conditioned on "OLDVERSION": scannumber(c, outfun) register int c; /* First char of number */ register int (*outfun)(); /* Output/store func */ /* * Process a number. We know that c is from 0 to 9 or dot. * Algorithm from Dave Conroy's Decus C. */ { register int radix; /* 8, 10, or 16 */ int expseen; /* 'e' seen in floater */ #ifdef OLDVERSION int signseen; /* '+' or '-' seen */ #endif int octal89; /* For bad octal test */ int dotflag; /* TRUE if '.' was seen */ expseen = FALSE; /* No exponent seen yet */ #ifdef OLDVERSION signseen = TRUE; /* No +/- allowed yet */ #endif octal89 = FALSE; /* No bad octal yet */ radix = 10; /* Assume decimal */ if ((dotflag = (c == '.')) != FALSE) { /* . something? */ (*outfun)('.'); /* Always out the dot */ if (type[(c = get())] != DIG) { /* If not a float numb, */ unget(); /* Rescan strange char */ return; /* All done for now */ } } /* End of float test */ else if (c == '0') { /* Octal or hex? */ (*outfun)(c); /* Stuff initial zero */ radix = 8; /* Assume it's octal */ c = get(); /* Look for an 'x' */ if (c == 'x' || c == 'X') { /* Did we get one? */ radix = 16; /* Remember new radix */ (*outfun)(c); /* Stuff the 'x' */ c = get(); /* Get next character */ } } for (;;) { /* Process curr. char. */ /* * Note that this algorithm accepts "012e4" and "03.4" * as legitimate floating-point numbers. */ if (radix != 16 && (c == 'e' || c == 'E')) { if (expseen) /* Already saw 'E'? */ break; /* Exit loop, bad nbr. */ expseen = TRUE; /* Set exponent seen */ #ifdef OLDVERSION signseen = FALSE; /* We can read '+' now */ #endif radix = 10; /* Decimal exponent */ #ifndef OLDVERSION (*outfun)(c); if ((c = get()) != '+' && c != '-') continue; #endif } else if (radix != 16 && c == '.') { if (dotflag) /* Saw dot already? */ break; /* Exit loop, two dots */ dotflag = TRUE; /* Remember the dot */ radix = 10; /* Decimal fraction */ } #ifdef OLDVERSION else if (c == '+' || c == '-') { /* 1.0e+10 */ if (signseen) /* Sign in wrong place? */ break; /* Exit loop, not nbr. */ /* signseen = TRUE; */ /* Remember we saw it */ } #endif else { /* Check the digit */ switch (c) { case '8': case '9': /* Sometimes wrong */ octal89 = TRUE; /* Do check later */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': break; /* Always ok */ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': if (radix == 16) /* Alpha's are ok only */ break; /* if reading hex. */ default: /* At number end */ goto done; /* Break from for loop */ } /* End of switch */ } /* End general case */ (*outfun)(c); /* Accept the character */ #ifdef OLDVERSION signseen = TRUE; /* Don't read sign now */ #endif c = get(); /* Read another char */ } /* End of scan loop */ . . . --ado