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