1 /* 2 * Copyright (c) 1982 Regents of the University of California 3 */ 4 #ifndef lint 5 static char sccsid[] = "@(#)asscan4.c 4.4 06/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 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); 85 BACK(BFINT); 86 case 'b': 87 yylval = -((ch - '0') + 1); 88 BACK(BFINT); 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; 161 BACK(INT); 162 bignum: ; 163 yybignum = as_atoi(numbuf, radix, &overflow); 164 BACK(BIGNUM); 165 floatnum: ; 166 REGTOMEMBUF; 167 yybignum = floatnumber(ch); 168 return(BIGNUM); 169 stuffback: ; 170 REGTOMEMBUF; 171 return(intval); 172 } 173 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; 186 187 Bignum floatnumber(fltradix) 188 int fltradix; 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; 203 reg int inbufcnt; 204 205 MEMTOREGBUF; 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 } 246 REGTOMEMBUF; 247 /* 248 * The overflow value is lost in the call to as_atof 249 */ 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 */ 256 int scanint(signOK, dstcpp) 257 int signOK; 258 char **dstcpp; 259 { 260 int ch; 261 int back = 0; 262 reg char *inbufptr; 263 reg int inbufcnt; 264 265 MEMTOREGBUF; 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); 279 REGTOMEMBUF; 280 return(back); 281 } 282