xref: /csrg-svn/old/as.vax/asscan4.c (revision 13465)
15800Srrh /*
25800Srrh  *	Copyright (c) 1982 Regents of the University of California
35800Srrh  */
45800Srrh #ifndef lint
5*13465Srrh static char sccsid[] = "@(#)asscan4.c 4.4 06/30/83";
65800Srrh #endif not lint
75800Srrh 
85800Srrh #include "asscanl.h"
95800Srrh 
105800Srrh #define	reg	register
115800Srrh #define	NUMSIZE	128	/* how many characters long a number can be */
125800Srrh #define	FLTCHAR(x)	(INCHARSET((x),(DIGIT|SIGN|FLOATEXP|POINT)))
135800Srrh 
145800Srrh static char	numbuf[NUMSIZE];
155800Srrh 
16*13465Srrh #define	BACK(backval)	intval = backval; goto stuffback;
17*13465Srrh 
18*13465Srrh int number(ch)
195800Srrh 	reg	int	ch;
205800Srrh {
215800Srrh 		int	radix;
225800Srrh 		int	digit;		/* part of number being constructed */
235800Srrh 	reg	int	intval;		/* number being constructed */
245800Srrh 	reg	char	*cp;
255800Srrh 	reg	char	*inbufptr;
26*13465Srrh 	reg	int	inbufcnt;
275800Srrh 		char	ch1;
285800Srrh 		Bignum	floatnumber();
295800Srrh 		Ovf	overflow;	/* overflow flag */
305800Srrh 		int	maxstrlg;
315800Srrh 
32*13465Srrh 	MEMTOREGBUF;
335800Srrh 	cp = numbuf;
345800Srrh 	radix = 10;
355800Srrh 
365800Srrh 	switch(ch){
375800Srrh 	case '0':
385800Srrh 		switch(ch = getchar()){
395800Srrh 		case 'b':
405800Srrh 			yylval = -1;
41*13465Srrh 			BACK(BFINT);
425800Srrh 		case 'f':
435800Srrh 			/*
445800Srrh 			 * Check if it is a local label by peeking ahead
455800Srrh 			 */
465800Srrh 			ch1 = getchar();
475800Srrh 			ungetc(ch1);
485800Srrh 			if (!FLTCHAR(ch1)){
495800Srrh 				yylval = 1;
50*13465Srrh 				BACK(BFINT);
515800Srrh 			}
525800Srrh 			/*FALLTHROUGH*/
535800Srrh 		case 'F': ch = 'f';	goto floatnum;
545800Srrh 		case 'd':
555800Srrh 		case 'D': ch = 'd';	goto floatnum;
565800Srrh 		case 'h':
575800Srrh 		case 'H': ch = 'h';	goto floatnum;
585800Srrh 		case 'g':
595800Srrh 		case 'G': ch = 'g';	goto floatnum;
605800Srrh 
615800Srrh 		case 'x':
625800Srrh 		case 'X':
635800Srrh 			ch = '0';
645800Srrh 			radix = 16;
655800Srrh 			break;
665800Srrh 		case '0':
675800Srrh 		case '1': case '2': case '3': case '4':
685800Srrh 		case '5': case '6': case '7': case '8':
695800Srrh 		case '9':
705800Srrh 			radix = 8;
715800Srrh 			break;
725800Srrh 		default:	/* single 0 */
735800Srrh 			ungetc(ch);
745800Srrh 			intval = 0;
755800Srrh 			goto smallnum;
765800Srrh 		}
775800Srrh 		break;
785800Srrh 
795800Srrh 	case '1': case '2': case '3': case '4':
805800Srrh 	case '5': case '6': case '7': case '8':
815800Srrh 	case '9':
825800Srrh 		switch(ch1 = getchar()){
835800Srrh 		case 'f':
845800Srrh 			yylval = ((ch - '0') + 1);
85*13465Srrh 			BACK(BFINT);
865800Srrh 		case 'b':
875800Srrh 			yylval = -((ch - '0') + 1);
88*13465Srrh 			BACK(BFINT);
895800Srrh 		default:
905800Srrh 			ungetc(ch1);	/* put back non zero */
915800Srrh 		}
925800Srrh 		radix = 10;
935800Srrh 		break;
945800Srrh 	}
955800Srrh 	intval = 0;
965800Srrh 	/*
975800Srrh 	 *	There is a character in ch that must be used to
985800Srrh 	 *	cons up the number; we can't ungetc it
995800Srrh 	 */
1005800Srrh 	do{
1015800Srrh 		digit = ch - '0';
1025800Srrh 		switch(radix){
1035800Srrh 		case 8:
1045800Srrh 			intval <<= 3;
1055800Srrh 			break;
1065800Srrh 		case 10:
1075800Srrh 			intval *= 10;
1085800Srrh 			break;
1095800Srrh 		case 16:
1105800Srrh 			intval <<= 4;
1115800Srrh 			if (INCHARSET(ch, HEXLDIGIT)){
1125800Srrh 				digit = (ch - 'a') + 10;
1135800Srrh 				break;
1145800Srrh 			}
1155800Srrh 			if (INCHARSET(ch, HEXUDIGIT)){
1165800Srrh 				digit = (ch - 'A') + 10;
1175800Srrh 				break;
1185800Srrh 			}
1195800Srrh 		}
1205800Srrh 		*cp++ = ch;
1215800Srrh 		/*
1225800Srrh 		 *	Build a negative number, then negate it
1235800Srrh 		 */
1245800Srrh 		intval -= digit;
1255800Srrh 
1265800Srrh 		ch = getchar();
1275800Srrh 		if(!INCHARSET(ch, DIGIT)){
1285800Srrh 			if (radix != 16)
1295800Srrh 				break;
1305800Srrh 			if(!INCHARSET(ch, (HEXLDIGIT|HEXUDIGIT)))
1315800Srrh 				break;
1325800Srrh 		}
1335800Srrh 	} while (1);
1345800Srrh 	ungetc(ch);
1355800Srrh 	*cp = 0;
1365800Srrh 	maxstrlg = cp - numbuf;
1375800Srrh 	/*
1385800Srrh 	 *	See if the number is too large for our previous calculation
1395800Srrh 	 */
1405800Srrh 	switch(radix){
1415800Srrh 	case 16:
1425800Srrh 		if (maxstrlg > 8)
1435800Srrh 			goto bignum;
1445800Srrh 		break;
1455800Srrh 	case 10:
1465800Srrh 		if (maxstrlg >= 10)
1475800Srrh 			goto bignum;
1485800Srrh 		break;
1495800Srrh 	case 8:
1505800Srrh 		if (maxstrlg > 11)
1515800Srrh 			goto bignum;
1525800Srrh 		if (maxstrlg == 11 && numbuf[0] > 3)
1535800Srrh 			goto bignum;
1545800Srrh 		break;
1555800Srrh 	}
1565800Srrh 	/*
1575800Srrh 	 *	Negate the number
1585800Srrh 	 */
1595800Srrh   smallnum: ;
1605800Srrh 	yylval = -intval;
161*13465Srrh 	BACK(INT);
1625800Srrh   bignum: ;
1635800Srrh 	yybignum = as_atoi(numbuf, radix, &overflow);
164*13465Srrh 	BACK(BIGNUM);
1655800Srrh   floatnum: ;
166*13465Srrh 	REGTOMEMBUF;
167*13465Srrh 	yybignum = floatnumber(ch);
1685800Srrh 	return(BIGNUM);
169*13465Srrh  stuffback: ;
170*13465Srrh 	REGTOMEMBUF;
171*13465Srrh 	return(intval);
1725800Srrh }
1735800Srrh 
174*13465Srrh #define	TOOLONG \
175*13465Srrh 	if (cp == &numbuf[NUMSIZE]){ \
176*13465Srrh 		if (passno == 2) \
177*13465Srrh 			yywarning(toolong); \
178*13465Srrh 			goto process; \
179*13465Srrh 	}
180*13465Srrh #define	scanit(sign) \
181*13465Srrh 	REGTOMEMBUF; \
182*13465Srrh 	error |= scanint(sign, &cp); \
183*13465Srrh 	MEMTOREGBUF; \
184*13465Srrh 	ch = getchar(); \
185*13465Srrh 	TOOLONG;
1865800Srrh 
187*13465Srrh Bignum floatnumber(fltradix)
1885800Srrh 	int	fltradix;
1895800Srrh {
1905800Srrh 		char	*cp;
1915800Srrh 		int	ch;
1925800Srrh 		char	*toolong = "Floating number too long.";
1935800Srrh 		char	*prologue =
1945800Srrh 			"Floating 0%c conflicts with exponent %c; choose %c";
1955800Srrh 		/*
1965800Srrh 		 *	This is not implemented yet:
1975800Srrh 		 *	overflow is set on floating overflow.
1985800Srrh 		 */
1995800Srrh 		Ovf	overflow;
2005800Srrh 		int	error;
2015800Srrh 		int	fractOK;
2025800Srrh 	reg	char	*inbufptr;
203*13465Srrh 	reg	int	inbufcnt;
2045800Srrh 
205*13465Srrh 	MEMTOREGBUF;
2065800Srrh 	cp = numbuf;
2075800Srrh 	error = 0;
2085800Srrh 	fractOK = 0;
2095800Srrh 
2105800Srrh 	scanit(1);
2115800Srrh 	if(INCHARSET(ch, POINT)){
2125800Srrh 		fractOK++;
2135800Srrh 		*cp++ = '.';
2145800Srrh 		scanit(0);
2155800Srrh 	}
2165800Srrh 	if(INCHARSET(ch, FLOATEXP)){
2175800Srrh 		fractOK++;
2185800Srrh 		if(ch != fltradix){
2195800Srrh 			if (passno == 2)
2205800Srrh 				yywarning(prologue, fltradix, ch, fltradix);
2215800Srrh 		}
2225800Srrh 		switch(fltradix){
2235800Srrh 		case 'd':
2245800Srrh 		case 'f':
2255800Srrh 			*cp++ = 'e';		/* will be read by atof() */
2265800Srrh 			break;
2275800Srrh 		default:
2285800Srrh 			*cp++ = fltradix;	/* will be read by bigatof() */
2295800Srrh 			break;
2305800Srrh 		}
2315800Srrh 		scanit(1);
2325800Srrh 	}
2335800Srrh 	if (error || fractOK == 0){
2345800Srrh 		yyerror("Badly formatted floating point number.");
2355800Srrh 	}
2365800Srrh 	ungetc(ch);
2375800Srrh 	*cp++ = 0;
2385800Srrh 
2395800Srrh   process: ;
2405800Srrh 	switch(fltradix){
2415800Srrh 	case 'f':	fltradix = TYPF;	break;
2425800Srrh 	case 'd':	fltradix = TYPD;	break;
2435800Srrh 	case 'g':	fltradix = TYPG;	nGHnumbers++; break;
2445800Srrh 	case 'h':	fltradix = TYPH;	nGHnumbers++; break;
2455800Srrh 	}
246*13465Srrh 	REGTOMEMBUF;
2475800Srrh 	/*
2485800Srrh 	 *	The overflow value is lost in the call to as_atof
2495800Srrh 	 */
2505800Srrh 	return(as_atof(numbuf, fltradix, &overflow));
2515800Srrh }
2525800Srrh /*
2535800Srrh  *	Scan an optionally signed integer, putting back the lookahead
2545800Srrh  *	character when finished scanning.
2555800Srrh  */
256*13465Srrh int scanint(signOK, dstcpp)
2575800Srrh 	int	signOK;
2585800Srrh 	char	**dstcpp;
2595800Srrh {
260*13465Srrh 		int	ch;
261*13465Srrh 		int	back = 0;
262*13465Srrh 	reg	char	*inbufptr;
263*13465Srrh 	reg	int	inbufcnt;
2645800Srrh 
265*13465Srrh 	MEMTOREGBUF;
2665800Srrh 	ch = getchar();
2675800Srrh 	while (INCHARSET(ch, SIGN)){
2685800Srrh 		if (signOK && !back)
2695800Srrh 			*((*dstcpp)++) = ch;
2705800Srrh 		else
2715800Srrh 			back = 1;
2725800Srrh 		ch = getchar();
2735800Srrh 	}
2745800Srrh 	while (INCHARSET(ch, DIGIT)){
2755800Srrh 		*((*dstcpp)++) = ch;
2765800Srrh 		ch = getchar();
2775800Srrh 	}
2785800Srrh 	ungetc(ch);
279*13465Srrh 	REGTOMEMBUF;
2805800Srrh 	return(back);
2815800Srrh }
282