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 } 273