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