|
|
1.1 root 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:
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:
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: */
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.