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