
From:	RHEA::DECWRL::"decvax!minow"    7-OCT-1984 19:52  
To:	decwrl!rhea!rex!minow

Received: from DECWRL by DEC-RHEA with SMTP; Sun,  7 Oct 84 16:52-PDT
Received: by decwrl.ARPA (4.22.01/4.7.34)
	id AA25578; Sun, 7 Oct 84 16:52:47 pdt
Received: by decvax.UUCP (4.12/1.0)
	id AA27822; Sun, 7 Oct 84 19:03:48 edt
Date: Sun, 7 Oct 84 19:03:48 edt
Return-Path: <decvax!minow>
Message-Id: <8410072303.AA27822@decvax.UUCP>

From idis!george Sun Oct  7 00:15:32 1984
Received: by decvax.UUCP (4.12/1.0)
	id AA15585; Sun, 7 Oct 84 00:15:11 edt
Received: by idis.UUCP (4.12/4.7)
	id AA22864; Fri, 5 Oct 84 12:20:41 edt
Date: Fri, 5 Oct 84 12:20:41 edt
From: idis!george (George Rosenberg)
Message-Id: <8410051620.AA22864@idis.UUCP>
To: minow@decvax
Subject: scannumber in decus cpp
Status: R

I received the copy of cpp that you sent me through the mail.
I have not yet had a chance to compile it.
I have looked over scannumber() and get().

Before I rewrote scannumber() I attempted to modify the existing
copy.  It's control flow wasn't structured appropriately,
so I gave up the attempt to modify it and rewrote it instead.
What you consolidated into the new cpp looks more like my aborted attempt.
I checked my copy of the mail I sent you, thinking I may
have sent you that early attempt by mistake.  I had sent you my rewrite.
Apparently you unsuccessfully attempted to consolidate
my changes into the previously existing routine.

Your resulting routine is wrong, I believe that mine is correct.

	02.e3		My routine correctly parses this as a floating
			point constant.  I believe that your new version
			of the routine would parse this as an integer constant
			(followed by a period and an identifier).

	.L		My routine correctly parsed this as a period
			(followed by an identifier).  It was not a special
			case.  I think your new version also correctly
			parsed this, but I think the below statement from it
			is redundant (and very awkward).

		if (!hasdigit)
		    goto gotcha;		/* Catch ".l"		*/

			Assuming neither 'l' nor 'L' was passed to
			scannumber as an argument, a digit must have
			been scanned before the 'l' or 'L',
			so this will always be false.

	.e5		According to k&r 2.4.4 this is not a floating
			point constant.
				"Either the integer part or the fraction
				part (not both) may be missing."
			This is also not a floating point constant according
			to ANSI X3J11 draft 84-131.
			My routine correctly parses this as a period
			(followed by an identifier).
			I believe that your new version of the routine
			also does this correctly.
			There seems to be a curious comment in your routine
			indicating that something is wrong with this.

	Less serious is a stylistic problem.
	The below will work with both ASCII and EBCDIC
	but it is not portable in principle.
	I assume this problem exists in other routines also.

		} while ((c >= '0' && c <= '9')
		      || (c >= 'A' && c <= 'F')
		      || (c >= 'a' && c <= 'f'));
	    }
	    else {
		while (c >= '0' && c <= '7') {		/* It's octal	*/


I have appended another copy of my version of scannumber().
The only difference from the previous copy I sent you
is that "hasdigit" now is declared with storage class "register".

	George Rosenberg
	idis!george


/*
 * Process a number
 */
scannumber(ch,outfun)
register int ch ;
register int (*outfun)() ;
{
	register int hasdigit ;

	hasdigit = FALSE ;

	if (ch == '0') {

		hasdigit = TRUE ;
		(*outfun)(ch) ;
		ch = get() ;

		if (ch == 'x' || ch == 'X')
			for (;;) {

				(*outfun)(ch) ;
				ch = get() ;

				switch (ch) {

					case '0':
					case '1':  case '2':  case '3':
					case '4':  case '5':  case '6':
					case '7':  case '8':  case '9':
					case 'a':  case 'b':  case 'c':
					case 'd':  case 'e':  case 'f':
#if 'a' != 'A'
					case 'A':  case 'B':  case 'C':
					case 'D':  case 'E':  case 'F':
#endif
						continue ;
				}

				if (ch == 'l' || ch == 'L') {

					(*outfun)(ch) ;
					return ;
				}

				unget() ;
				return ;
			}
	}

	while (type[ch] == DIG) {

		hasdigit = TRUE ;
		(*outfun)(ch) ;
		ch = get() ;
	}

	if (ch == 'l' || ch == 'L') {

		(*outfun)(ch) ;
		return ;
	}

	if (ch == '.') {

		(*outfun)(ch) ;
		ch = get() ;

		if (hasdigit == FALSE && type[ch] != DIG) {

			unget() ;
			return ;
		}
	}

	while (type[ch] == DIG) {

		(*outfun)(ch) ;
		ch = get() ;
	}

	if (ch == 'e' || ch == 'E') {

		(*outfun)(ch) ;
		ch = get() ;

		if (ch == '+' || ch == '-') {

			(*outfun)(ch) ;
			ch = get() ;
		}

		while (type[ch] == DIG) {

			(*outfun)(ch) ;
			ch = get() ;
		}
	}

	unget() ;
}

