xref: /csrg-svn/old/as.vax/asscan4.c (revision 19831)
15800Srrh /*
2*19831Sdist  * Copyright (c) 1982 Regents of the University of California.
3*19831Sdist  * All rights reserved.  The Berkeley software License Agreement
4*19831Sdist  * specifies the terms and conditions for redistribution.
55800Srrh  */
6*19831Sdist 
75800Srrh #ifndef lint
8*19831Sdist static char sccsid[] = "@(#)asscan4.c	5.1 (Berkeley) 04/30/85";
95800Srrh #endif not lint
105800Srrh 
115800Srrh #include "asscanl.h"
125800Srrh 
135800Srrh #define	reg	register
145800Srrh #define	NUMSIZE	128	/* how many characters long a number can be */
155800Srrh #define	FLTCHAR(x)	(INCHARSET((x),(DIGIT|SIGN|FLOATEXP|POINT)))
165800Srrh 
175800Srrh static char	numbuf[NUMSIZE];
185800Srrh 
1913465Srrh #define	BACK(backval)	intval = backval; goto stuffback;
2013465Srrh 
number(ch)2113465Srrh int number(ch)
225800Srrh 	reg	int	ch;
235800Srrh {
245800Srrh 		int	radix;
255800Srrh 		int	digit;		/* part of number being constructed */
265800Srrh 	reg	int	intval;		/* number being constructed */
275800Srrh 	reg	char	*cp;
285800Srrh 	reg	char	*inbufptr;
2913465Srrh 	reg	int	inbufcnt;
305800Srrh 		char	ch1;
315800Srrh 		Bignum	floatnumber();
325800Srrh 		Ovf	overflow;	/* overflow flag */
335800Srrh 		int	maxstrlg;
345800Srrh 
3513465Srrh 	MEMTOREGBUF;
365800Srrh 	cp = numbuf;
375800Srrh 	radix = 10;
385800Srrh 
395800Srrh 	switch(ch){
405800Srrh 	case '0':
415800Srrh 		switch(ch = getchar()){
425800Srrh 		case 'b':
435800Srrh 			yylval = -1;
4413465Srrh 			BACK(BFINT);
455800Srrh 		case 'f':
465800Srrh 			/*
475800Srrh 			 * Check if it is a local label by peeking ahead
485800Srrh 			 */
495800Srrh 			ch1 = getchar();
505800Srrh 			ungetc(ch1);
515800Srrh 			if (!FLTCHAR(ch1)){
525800Srrh 				yylval = 1;
5313465Srrh 				BACK(BFINT);
545800Srrh 			}
555800Srrh 			/*FALLTHROUGH*/
565800Srrh 		case 'F': ch = 'f';	goto floatnum;
575800Srrh 		case 'd':
585800Srrh 		case 'D': ch = 'd';	goto floatnum;
595800Srrh 		case 'h':
605800Srrh 		case 'H': ch = 'h';	goto floatnum;
615800Srrh 		case 'g':
625800Srrh 		case 'G': ch = 'g';	goto floatnum;
635800Srrh 
645800Srrh 		case 'x':
655800Srrh 		case 'X':
665800Srrh 			ch = '0';
675800Srrh 			radix = 16;
685800Srrh 			break;
695800Srrh 		case '0':
705800Srrh 		case '1': case '2': case '3': case '4':
715800Srrh 		case '5': case '6': case '7': case '8':
725800Srrh 		case '9':
735800Srrh 			radix = 8;
745800Srrh 			break;
755800Srrh 		default:	/* single 0 */
765800Srrh 			ungetc(ch);
775800Srrh 			intval = 0;
785800Srrh 			goto smallnum;
795800Srrh 		}
805800Srrh 		break;
815800Srrh 
825800Srrh 	case '1': case '2': case '3': case '4':
835800Srrh 	case '5': case '6': case '7': case '8':
845800Srrh 	case '9':
855800Srrh 		switch(ch1 = getchar()){
865800Srrh 		case 'f':
875800Srrh 			yylval = ((ch - '0') + 1);
8813465Srrh 			BACK(BFINT);
895800Srrh 		case 'b':
905800Srrh 			yylval = -((ch - '0') + 1);
9113465Srrh 			BACK(BFINT);
925800Srrh 		default:
935800Srrh 			ungetc(ch1);	/* put back non zero */
945800Srrh 		}
955800Srrh 		radix = 10;
965800Srrh 		break;
975800Srrh 	}
985800Srrh 	intval = 0;
995800Srrh 	/*
1005800Srrh 	 *	There is a character in ch that must be used to
1015800Srrh 	 *	cons up the number; we can't ungetc it
1025800Srrh 	 */
1035800Srrh 	do{
1045800Srrh 		digit = ch - '0';
1055800Srrh 		switch(radix){
1065800Srrh 		case 8:
1075800Srrh 			intval <<= 3;
1085800Srrh 			break;
1095800Srrh 		case 10:
1105800Srrh 			intval *= 10;
1115800Srrh 			break;
1125800Srrh 		case 16:
1135800Srrh 			intval <<= 4;
1145800Srrh 			if (INCHARSET(ch, HEXLDIGIT)){
1155800Srrh 				digit = (ch - 'a') + 10;
1165800Srrh 				break;
1175800Srrh 			}
1185800Srrh 			if (INCHARSET(ch, HEXUDIGIT)){
1195800Srrh 				digit = (ch - 'A') + 10;
1205800Srrh 				break;
1215800Srrh 			}
1225800Srrh 		}
1235800Srrh 		*cp++ = ch;
1245800Srrh 		/*
1255800Srrh 		 *	Build a negative number, then negate it
1265800Srrh 		 */
1275800Srrh 		intval -= digit;
1285800Srrh 
1295800Srrh 		ch = getchar();
1305800Srrh 		if(!INCHARSET(ch, DIGIT)){
1315800Srrh 			if (radix != 16)
1325800Srrh 				break;
1335800Srrh 			if(!INCHARSET(ch, (HEXLDIGIT|HEXUDIGIT)))
1345800Srrh 				break;
1355800Srrh 		}
1365800Srrh 	} while (1);
1375800Srrh 	ungetc(ch);
1385800Srrh 	*cp = 0;
1395800Srrh 	maxstrlg = cp - numbuf;
1405800Srrh 	/*
1415800Srrh 	 *	See if the number is too large for our previous calculation
1425800Srrh 	 */
1435800Srrh 	switch(radix){
1445800Srrh 	case 16:
1455800Srrh 		if (maxstrlg > 8)
1465800Srrh 			goto bignum;
1475800Srrh 		break;
1485800Srrh 	case 10:
1495800Srrh 		if (maxstrlg >= 10)
1505800Srrh 			goto bignum;
1515800Srrh 		break;
1525800Srrh 	case 8:
1535800Srrh 		if (maxstrlg > 11)
1545800Srrh 			goto bignum;
1555800Srrh 		if (maxstrlg == 11 && numbuf[0] > 3)
1565800Srrh 			goto bignum;
1575800Srrh 		break;
1585800Srrh 	}
1595800Srrh 	/*
1605800Srrh 	 *	Negate the number
1615800Srrh 	 */
1625800Srrh   smallnum: ;
1635800Srrh 	yylval = -intval;
16413465Srrh 	BACK(INT);
1655800Srrh   bignum: ;
1665800Srrh 	yybignum = as_atoi(numbuf, radix, &overflow);
16713465Srrh 	BACK(BIGNUM);
1685800Srrh   floatnum: ;
16913465Srrh 	REGTOMEMBUF;
17013465Srrh 	yybignum = floatnumber(ch);
1715800Srrh 	return(BIGNUM);
17213465Srrh  stuffback: ;
17313465Srrh 	REGTOMEMBUF;
17413465Srrh 	return(intval);
1755800Srrh }
1765800Srrh 
17713465Srrh #define	TOOLONG \
17813465Srrh 	if (cp == &numbuf[NUMSIZE]){ \
17913465Srrh 		if (passno == 2) \
18013465Srrh 			yywarning(toolong); \
18113465Srrh 			goto process; \
18213465Srrh 	}
18313465Srrh #define	scanit(sign) \
18413465Srrh 	REGTOMEMBUF; \
18513465Srrh 	error |= scanint(sign, &cp); \
18613465Srrh 	MEMTOREGBUF; \
18713465Srrh 	ch = getchar(); \
18813465Srrh 	TOOLONG;
1895800Srrh 
floatnumber(fltradix)19013465Srrh Bignum floatnumber(fltradix)
1915800Srrh 	int	fltradix;
1925800Srrh {
1935800Srrh 		char	*cp;
1945800Srrh 		int	ch;
1955800Srrh 		char	*toolong = "Floating number too long.";
1965800Srrh 		char	*prologue =
1975800Srrh 			"Floating 0%c conflicts with exponent %c; choose %c";
1985800Srrh 		/*
1995800Srrh 		 *	This is not implemented yet:
2005800Srrh 		 *	overflow is set on floating overflow.
2015800Srrh 		 */
2025800Srrh 		Ovf	overflow;
2035800Srrh 		int	error;
2045800Srrh 		int	fractOK;
2055800Srrh 	reg	char	*inbufptr;
20613465Srrh 	reg	int	inbufcnt;
2075800Srrh 
20813465Srrh 	MEMTOREGBUF;
2095800Srrh 	cp = numbuf;
2105800Srrh 	error = 0;
2115800Srrh 	fractOK = 0;
2125800Srrh 
2135800Srrh 	scanit(1);
2145800Srrh 	if(INCHARSET(ch, POINT)){
2155800Srrh 		fractOK++;
2165800Srrh 		*cp++ = '.';
2175800Srrh 		scanit(0);
2185800Srrh 	}
2195800Srrh 	if(INCHARSET(ch, FLOATEXP)){
2205800Srrh 		fractOK++;
2215800Srrh 		if(ch != fltradix){
2225800Srrh 			if (passno == 2)
2235800Srrh 				yywarning(prologue, fltradix, ch, fltradix);
2245800Srrh 		}
2255800Srrh 		switch(fltradix){
2265800Srrh 		case 'd':
2275800Srrh 		case 'f':
2285800Srrh 			*cp++ = 'e';		/* will be read by atof() */
2295800Srrh 			break;
2305800Srrh 		default:
2315800Srrh 			*cp++ = fltradix;	/* will be read by bigatof() */
2325800Srrh 			break;
2335800Srrh 		}
2345800Srrh 		scanit(1);
2355800Srrh 	}
2365800Srrh 	if (error || fractOK == 0){
2375800Srrh 		yyerror("Badly formatted floating point number.");
2385800Srrh 	}
2395800Srrh 	ungetc(ch);
2405800Srrh 	*cp++ = 0;
2415800Srrh 
2425800Srrh   process: ;
2435800Srrh 	switch(fltradix){
2445800Srrh 	case 'f':	fltradix = TYPF;	break;
2455800Srrh 	case 'd':	fltradix = TYPD;	break;
2465800Srrh 	case 'g':	fltradix = TYPG;	nGHnumbers++; break;
2475800Srrh 	case 'h':	fltradix = TYPH;	nGHnumbers++; break;
2485800Srrh 	}
24913465Srrh 	REGTOMEMBUF;
2505800Srrh 	/*
2515800Srrh 	 *	The overflow value is lost in the call to as_atof
2525800Srrh 	 */
2535800Srrh 	return(as_atof(numbuf, fltradix, &overflow));
2545800Srrh }
2555800Srrh /*
2565800Srrh  *	Scan an optionally signed integer, putting back the lookahead
2575800Srrh  *	character when finished scanning.
2585800Srrh  */
scanint(signOK,dstcpp)25913465Srrh int scanint(signOK, dstcpp)
2605800Srrh 	int	signOK;
2615800Srrh 	char	**dstcpp;
2625800Srrh {
26313465Srrh 		int	ch;
26413465Srrh 		int	back = 0;
26513465Srrh 	reg	char	*inbufptr;
26613465Srrh 	reg	int	inbufcnt;
2675800Srrh 
26813465Srrh 	MEMTOREGBUF;
2695800Srrh 	ch = getchar();
2705800Srrh 	while (INCHARSET(ch, SIGN)){
2715800Srrh 		if (signOK && !back)
2725800Srrh 			*((*dstcpp)++) = ch;
2735800Srrh 		else
2745800Srrh 			back = 1;
2755800Srrh 		ch = getchar();
2765800Srrh 	}
2775800Srrh 	while (INCHARSET(ch, DIGIT)){
2785800Srrh 		*((*dstcpp)++) = ch;
2795800Srrh 		ch = getchar();
2805800Srrh 	}
2815800Srrh 	ungetc(ch);
28213465Srrh 	REGTOMEMBUF;
2835800Srrh 	return(back);
2845800Srrh }
285