1 /* 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. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)asscan4.c 5.1 (Berkeley) 04/30/85"; 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 19 #define BACK(backval) intval = backval; goto stuffback; 20 21 int number(ch) 22 reg int ch; 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; 29 reg int inbufcnt; 30 char ch1; 31 Bignum floatnumber(); 32 Ovf overflow; /* overflow flag */ 33 int maxstrlg; 34 35 MEMTOREGBUF; 36 cp = numbuf; 37 radix = 10; 38 39 switch(ch){ 40 case '0': 41 switch(ch = getchar()){ 42 case 'b': 43 yylval = -1; 44 BACK(BFINT); 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; 53 BACK(BFINT); 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); 88 BACK(BFINT); 89 case 'b': 90 yylval = -((ch - '0') + 1); 91 BACK(BFINT); 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; 164 BACK(INT); 165 bignum: ; 166 yybignum = as_atoi(numbuf, radix, &overflow); 167 BACK(BIGNUM); 168 floatnum: ; 169 REGTOMEMBUF; 170 yybignum = floatnumber(ch); 171 return(BIGNUM); 172 stuffback: ; 173 REGTOMEMBUF; 174 return(intval); 175 } 176 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; 189 190 Bignum floatnumber(fltradix) 191 int fltradix; 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; 206 reg int inbufcnt; 207 208 MEMTOREGBUF; 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 } 249 REGTOMEMBUF; 250 /* 251 * The overflow value is lost in the call to as_atof 252 */ 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 */ 259 int scanint(signOK, dstcpp) 260 int signOK; 261 char **dstcpp; 262 { 263 int ch; 264 int back = 0; 265 reg char *inbufptr; 266 reg int inbufcnt; 267 268 MEMTOREGBUF; 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); 282 REGTOMEMBUF; 283 return(back); 284 } 285