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