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