xref: /csrg-svn/old/as.tahoe/asscan4.c (revision 40593)
1*40593Sbostic /*
2*40593Sbostic  *	Copyright (c) 1982 Regents of the University of California
3*40593Sbostic  */
4*40593Sbostic #ifndef lint
5*40593Sbostic static char sccsid[] = "@(#)asscan4.c 4.4 6/30/83";
6*40593Sbostic #endif not lint
7*40593Sbostic 
8*40593Sbostic #include "asscanl.h"
9*40593Sbostic 
10*40593Sbostic #define	reg	register
11*40593Sbostic #define	NUMSIZE	128	/* how many characters long a number can be */
12*40593Sbostic #define	FLTCHAR(x)	(INCHARSET((x),(DIGIT|SIGN|FLOATEXP|POINT)))
13*40593Sbostic 
14*40593Sbostic static char	numbuf[NUMSIZE];
15*40593Sbostic 
16*40593Sbostic #define	BACK(backval)	intval = backval; goto stuffback;
17*40593Sbostic 
number(ch)18*40593Sbostic int number(ch)
19*40593Sbostic 	reg	int	ch;
20*40593Sbostic {
21*40593Sbostic 		int	radix;
22*40593Sbostic 		int	digit;		/* part of number being constructed */
23*40593Sbostic 	reg	int	intval;		/* number being constructed */
24*40593Sbostic 	reg	char	*cp;
25*40593Sbostic 	reg	char	*inbufptr;
26*40593Sbostic 	reg	int	inbufcnt;
27*40593Sbostic 		char	ch1;
28*40593Sbostic 		Bignum	floatnumber();
29*40593Sbostic 		Ovf	overflow;	/* overflow flag */
30*40593Sbostic 		int	maxstrlg;
31*40593Sbostic 
32*40593Sbostic 	MEMTOREGBUF;
33*40593Sbostic 	cp = numbuf;
34*40593Sbostic 	radix = 10;
35*40593Sbostic 
36*40593Sbostic 	switch(ch){
37*40593Sbostic 	case '0':
38*40593Sbostic 		switch(ch = getchar()){
39*40593Sbostic 		case 'b':
40*40593Sbostic 			yylval = -1;
41*40593Sbostic 			BACK(BFINT);
42*40593Sbostic 		case 'f':
43*40593Sbostic 			/*
44*40593Sbostic 			 * Check if it is a local label by peeking ahead
45*40593Sbostic 			 */
46*40593Sbostic 			ch1 = getchar();
47*40593Sbostic 			ungetc(ch1);
48*40593Sbostic 			if (!FLTCHAR(ch1)){
49*40593Sbostic 				yylval = 1;
50*40593Sbostic 				BACK(BFINT);
51*40593Sbostic 			}
52*40593Sbostic 			/*FALLTHROUGH*/
53*40593Sbostic 		case 'F': ch = 'f';	goto floatnum;
54*40593Sbostic 		case 'd':
55*40593Sbostic 		case 'D': ch = 'd';	goto floatnum;
56*40593Sbostic 
57*40593Sbostic 		case 'x':
58*40593Sbostic 		case 'X':
59*40593Sbostic 			ch = '0';
60*40593Sbostic 			radix = 16;
61*40593Sbostic 			break;
62*40593Sbostic 		case '0':
63*40593Sbostic 		case '1': case '2': case '3': case '4':
64*40593Sbostic 		case '5': case '6': case '7': case '8':
65*40593Sbostic 		case '9':
66*40593Sbostic 			radix = 8;
67*40593Sbostic 			break;
68*40593Sbostic 		default:	/* single 0 */
69*40593Sbostic 			ungetc(ch);
70*40593Sbostic 			intval = 0;
71*40593Sbostic 			goto smallnum;
72*40593Sbostic 		}
73*40593Sbostic 		break;
74*40593Sbostic 
75*40593Sbostic 	case '1': case '2': case '3': case '4':
76*40593Sbostic 	case '5': case '6': case '7': case '8':
77*40593Sbostic 	case '9':
78*40593Sbostic 		switch(ch1 = getchar()){
79*40593Sbostic 		case 'f':
80*40593Sbostic 			yylval = ((ch - '0') + 1);
81*40593Sbostic 			BACK(BFINT);
82*40593Sbostic 		case 'b':
83*40593Sbostic 			yylval = -((ch - '0') + 1);
84*40593Sbostic 			BACK(BFINT);
85*40593Sbostic 		default:
86*40593Sbostic 			ungetc(ch1);	/* put back non zero */
87*40593Sbostic 		}
88*40593Sbostic 		radix = 10;
89*40593Sbostic 		break;
90*40593Sbostic 	}
91*40593Sbostic 	intval = 0;
92*40593Sbostic 	/*
93*40593Sbostic 	 *	There is a character in ch that must be used to
94*40593Sbostic 	 *	cons up the number; we can't ungetc it
95*40593Sbostic 	 */
96*40593Sbostic 	do{
97*40593Sbostic 		digit = ch - '0';
98*40593Sbostic 		switch(radix){
99*40593Sbostic 		case 8:
100*40593Sbostic 			intval <<= 3;
101*40593Sbostic 			break;
102*40593Sbostic 		case 10:
103*40593Sbostic 			intval *= 10;
104*40593Sbostic 			break;
105*40593Sbostic 		case 16:
106*40593Sbostic 			intval <<= 4;
107*40593Sbostic 			if (INCHARSET(ch, HEXLDIGIT)){
108*40593Sbostic 				digit = (ch - 'a') + 10;
109*40593Sbostic 				break;
110*40593Sbostic 			}
111*40593Sbostic 			if (INCHARSET(ch, HEXUDIGIT)){
112*40593Sbostic 				digit = (ch - 'A') + 10;
113*40593Sbostic 				break;
114*40593Sbostic 			}
115*40593Sbostic 		}
116*40593Sbostic 		*cp++ = ch;
117*40593Sbostic 		/*
118*40593Sbostic 		 *	Build a negative number, then negate it
119*40593Sbostic 		 */
120*40593Sbostic 		intval -= digit;
121*40593Sbostic 
122*40593Sbostic 		ch = getchar();
123*40593Sbostic 		if(!INCHARSET(ch, DIGIT)){
124*40593Sbostic 			if (radix != 16)
125*40593Sbostic 				break;
126*40593Sbostic 			if(!INCHARSET(ch, (HEXLDIGIT|HEXUDIGIT)))
127*40593Sbostic 				break;
128*40593Sbostic 		}
129*40593Sbostic 	} while (1);
130*40593Sbostic 	ungetc(ch);
131*40593Sbostic 	*cp = 0;
132*40593Sbostic 	maxstrlg = cp - numbuf;
133*40593Sbostic 	/*
134*40593Sbostic 	 *	See if the number is too large for our previous calculation
135*40593Sbostic 	 */
136*40593Sbostic 	switch(radix){
137*40593Sbostic 	case 16:
138*40593Sbostic 		if (maxstrlg > 8)
139*40593Sbostic 			goto bignum;
140*40593Sbostic 		break;
141*40593Sbostic 	case 10:
142*40593Sbostic 		if (maxstrlg >= 10)
143*40593Sbostic 			goto bignum;
144*40593Sbostic 		break;
145*40593Sbostic 	case 8:
146*40593Sbostic 		if (maxstrlg > 11)
147*40593Sbostic 			goto bignum;
148*40593Sbostic 		if (maxstrlg == 11 && numbuf[0] > 3)
149*40593Sbostic 			goto bignum;
150*40593Sbostic 		break;
151*40593Sbostic 	}
152*40593Sbostic 	/*
153*40593Sbostic 	 *	Negate the number
154*40593Sbostic 	 */
155*40593Sbostic   smallnum: ;
156*40593Sbostic 	yylval = -intval;
157*40593Sbostic 	BACK(INT);
158*40593Sbostic   bignum: ;
159*40593Sbostic 	yybignum = as_atoi(numbuf, radix, &overflow);
160*40593Sbostic 	BACK(BIGNUM);
161*40593Sbostic   floatnum: ;
162*40593Sbostic 	REGTOMEMBUF;
163*40593Sbostic 	yybignum = floatnumber(ch);
164*40593Sbostic 	return(BIGNUM);
165*40593Sbostic  stuffback: ;
166*40593Sbostic 	REGTOMEMBUF;
167*40593Sbostic 	return(intval);
168*40593Sbostic }
169*40593Sbostic 
170*40593Sbostic #define	TOOLONG \
171*40593Sbostic 	if (cp == &numbuf[NUMSIZE]){ \
172*40593Sbostic 		if (passno == 2) \
173*40593Sbostic 			yywarning(toolong); \
174*40593Sbostic 			goto process; \
175*40593Sbostic 	}
176*40593Sbostic #define	scanit(sign) \
177*40593Sbostic 	REGTOMEMBUF; \
178*40593Sbostic 	error |= scanint(sign, &cp); \
179*40593Sbostic 	MEMTOREGBUF; \
180*40593Sbostic 	ch = getchar(); \
181*40593Sbostic 	TOOLONG;
182*40593Sbostic 
floatnumber(fltradix)183*40593Sbostic Bignum floatnumber(fltradix)
184*40593Sbostic 	int	fltradix;
185*40593Sbostic {
186*40593Sbostic 		int	tag;
187*40593Sbostic 		char	*cp;
188*40593Sbostic 		int	ch;
189*40593Sbostic 		char	*toolong = "Floating number too long.";
190*40593Sbostic 		char	*prologue =
191*40593Sbostic 			"Floating 0%c conflicts with exponent %c; choose %c";
192*40593Sbostic 		/*
193*40593Sbostic 		 *	This is not implemented yet:
194*40593Sbostic 		 *	overflow is set on floating overflow.
195*40593Sbostic 		 */
196*40593Sbostic 		Ovf	overflow;
197*40593Sbostic 		int	error;
198*40593Sbostic 		int	fractOK;
199*40593Sbostic 	reg	char	*inbufptr;
200*40593Sbostic 	reg	int	inbufcnt;
201*40593Sbostic 
202*40593Sbostic 	MEMTOREGBUF;
203*40593Sbostic 	cp = numbuf;
204*40593Sbostic 	error = 0;
205*40593Sbostic 	fractOK = 0;
206*40593Sbostic 
207*40593Sbostic 	scanit(1);
208*40593Sbostic 	if(INCHARSET(ch, POINT)){
209*40593Sbostic 		fractOK++;
210*40593Sbostic 		*cp++ = '.';
211*40593Sbostic 		scanit(0);
212*40593Sbostic 	}
213*40593Sbostic 	if(INCHARSET(ch, FLOATEXP)){
214*40593Sbostic 		fractOK++;
215*40593Sbostic 		if(ch != fltradix){
216*40593Sbostic 			if (passno == 2)
217*40593Sbostic 				yywarning(prologue, fltradix, ch, fltradix);
218*40593Sbostic 		}
219*40593Sbostic 		switch(fltradix){
220*40593Sbostic 		case 'd':
221*40593Sbostic 			tag = TYPD;
222*40593Sbostic 			*cp++ = 'e';		/* will be read by atof() */
223*40593Sbostic 			break;
224*40593Sbostic 		case 'f':
225*40593Sbostic 			tag = TYPF;
226*40593Sbostic 			*cp++ = 'e';		/* will be read by atof() */
227*40593Sbostic 			break;
228*40593Sbostic 		default:
229*40593Sbostic 			break;
230*40593Sbostic 		}
231*40593Sbostic 		scanit(1);
232*40593Sbostic 	}
233*40593Sbostic 	if (error || fractOK == 0){
234*40593Sbostic 		yyerror("Badly formatted floating point number.");
235*40593Sbostic 	}
236*40593Sbostic 	ungetc(ch);
237*40593Sbostic 	*cp++ = 0;
238*40593Sbostic 
239*40593Sbostic   process: ;
240*40593Sbostic 	REGTOMEMBUF;
241*40593Sbostic 	return(as_atof(numbuf, tag));
242*40593Sbostic }
243*40593Sbostic /*
244*40593Sbostic  *	Scan an optionally signed integer, putting back the lookahead
245*40593Sbostic  *	character when finished scanning.
246*40593Sbostic  */
scanint(signOK,dstcpp)247*40593Sbostic int scanint(signOK, dstcpp)
248*40593Sbostic 	int	signOK;
249*40593Sbostic 	char	**dstcpp;
250*40593Sbostic {
251*40593Sbostic 		int	ch;
252*40593Sbostic 		int	back = 0;
253*40593Sbostic 	reg	char	*inbufptr;
254*40593Sbostic 	reg	int	inbufcnt;
255*40593Sbostic 
256*40593Sbostic 	MEMTOREGBUF;
257*40593Sbostic 	ch = getchar();
258*40593Sbostic 	while (INCHARSET(ch, SIGN)){
259*40593Sbostic 		if (signOK && !back)
260*40593Sbostic 			*((*dstcpp)++) = ch;
261*40593Sbostic 		else
262*40593Sbostic 			back = 1;
263*40593Sbostic 		ch = getchar();
264*40593Sbostic 	}
265*40593Sbostic 	while (INCHARSET(ch, DIGIT)){
266*40593Sbostic 		*((*dstcpp)++) = ch;
267*40593Sbostic 		ch = getchar();
268*40593Sbostic 	}
269*40593Sbostic 	ungetc(ch);
270*40593Sbostic 	REGTOMEMBUF;
271*40593Sbostic 	return(back);
272*40593Sbostic }
273