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