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