15800Srrh /* 25800Srrh * Copyright (c) 1982 Regents of the University of California 35800Srrh */ 45800Srrh #ifndef lint 5*13465Srrh static char sccsid[] = "@(#)asscan4.c 4.4 06/30/83"; 65800Srrh #endif not lint 75800Srrh 85800Srrh #include "asscanl.h" 95800Srrh 105800Srrh #define reg register 115800Srrh #define NUMSIZE 128 /* how many characters long a number can be */ 125800Srrh #define FLTCHAR(x) (INCHARSET((x),(DIGIT|SIGN|FLOATEXP|POINT))) 135800Srrh 145800Srrh static char numbuf[NUMSIZE]; 155800Srrh 16*13465Srrh #define BACK(backval) intval = backval; goto stuffback; 17*13465Srrh 18*13465Srrh int number(ch) 195800Srrh reg int ch; 205800Srrh { 215800Srrh int radix; 225800Srrh int digit; /* part of number being constructed */ 235800Srrh reg int intval; /* number being constructed */ 245800Srrh reg char *cp; 255800Srrh reg char *inbufptr; 26*13465Srrh reg int inbufcnt; 275800Srrh char ch1; 285800Srrh Bignum floatnumber(); 295800Srrh Ovf overflow; /* overflow flag */ 305800Srrh int maxstrlg; 315800Srrh 32*13465Srrh MEMTOREGBUF; 335800Srrh cp = numbuf; 345800Srrh radix = 10; 355800Srrh 365800Srrh switch(ch){ 375800Srrh case '0': 385800Srrh switch(ch = getchar()){ 395800Srrh case 'b': 405800Srrh yylval = -1; 41*13465Srrh BACK(BFINT); 425800Srrh case 'f': 435800Srrh /* 445800Srrh * Check if it is a local label by peeking ahead 455800Srrh */ 465800Srrh ch1 = getchar(); 475800Srrh ungetc(ch1); 485800Srrh if (!FLTCHAR(ch1)){ 495800Srrh yylval = 1; 50*13465Srrh BACK(BFINT); 515800Srrh } 525800Srrh /*FALLTHROUGH*/ 535800Srrh case 'F': ch = 'f'; goto floatnum; 545800Srrh case 'd': 555800Srrh case 'D': ch = 'd'; goto floatnum; 565800Srrh case 'h': 575800Srrh case 'H': ch = 'h'; goto floatnum; 585800Srrh case 'g': 595800Srrh case 'G': ch = 'g'; goto floatnum; 605800Srrh 615800Srrh case 'x': 625800Srrh case 'X': 635800Srrh ch = '0'; 645800Srrh radix = 16; 655800Srrh break; 665800Srrh case '0': 675800Srrh case '1': case '2': case '3': case '4': 685800Srrh case '5': case '6': case '7': case '8': 695800Srrh case '9': 705800Srrh radix = 8; 715800Srrh break; 725800Srrh default: /* single 0 */ 735800Srrh ungetc(ch); 745800Srrh intval = 0; 755800Srrh goto smallnum; 765800Srrh } 775800Srrh break; 785800Srrh 795800Srrh case '1': case '2': case '3': case '4': 805800Srrh case '5': case '6': case '7': case '8': 815800Srrh case '9': 825800Srrh switch(ch1 = getchar()){ 835800Srrh case 'f': 845800Srrh yylval = ((ch - '0') + 1); 85*13465Srrh BACK(BFINT); 865800Srrh case 'b': 875800Srrh yylval = -((ch - '0') + 1); 88*13465Srrh BACK(BFINT); 895800Srrh default: 905800Srrh ungetc(ch1); /* put back non zero */ 915800Srrh } 925800Srrh radix = 10; 935800Srrh break; 945800Srrh } 955800Srrh intval = 0; 965800Srrh /* 975800Srrh * There is a character in ch that must be used to 985800Srrh * cons up the number; we can't ungetc it 995800Srrh */ 1005800Srrh do{ 1015800Srrh digit = ch - '0'; 1025800Srrh switch(radix){ 1035800Srrh case 8: 1045800Srrh intval <<= 3; 1055800Srrh break; 1065800Srrh case 10: 1075800Srrh intval *= 10; 1085800Srrh break; 1095800Srrh case 16: 1105800Srrh intval <<= 4; 1115800Srrh if (INCHARSET(ch, HEXLDIGIT)){ 1125800Srrh digit = (ch - 'a') + 10; 1135800Srrh break; 1145800Srrh } 1155800Srrh if (INCHARSET(ch, HEXUDIGIT)){ 1165800Srrh digit = (ch - 'A') + 10; 1175800Srrh break; 1185800Srrh } 1195800Srrh } 1205800Srrh *cp++ = ch; 1215800Srrh /* 1225800Srrh * Build a negative number, then negate it 1235800Srrh */ 1245800Srrh intval -= digit; 1255800Srrh 1265800Srrh ch = getchar(); 1275800Srrh if(!INCHARSET(ch, DIGIT)){ 1285800Srrh if (radix != 16) 1295800Srrh break; 1305800Srrh if(!INCHARSET(ch, (HEXLDIGIT|HEXUDIGIT))) 1315800Srrh break; 1325800Srrh } 1335800Srrh } while (1); 1345800Srrh ungetc(ch); 1355800Srrh *cp = 0; 1365800Srrh maxstrlg = cp - numbuf; 1375800Srrh /* 1385800Srrh * See if the number is too large for our previous calculation 1395800Srrh */ 1405800Srrh switch(radix){ 1415800Srrh case 16: 1425800Srrh if (maxstrlg > 8) 1435800Srrh goto bignum; 1445800Srrh break; 1455800Srrh case 10: 1465800Srrh if (maxstrlg >= 10) 1475800Srrh goto bignum; 1485800Srrh break; 1495800Srrh case 8: 1505800Srrh if (maxstrlg > 11) 1515800Srrh goto bignum; 1525800Srrh if (maxstrlg == 11 && numbuf[0] > 3) 1535800Srrh goto bignum; 1545800Srrh break; 1555800Srrh } 1565800Srrh /* 1575800Srrh * Negate the number 1585800Srrh */ 1595800Srrh smallnum: ; 1605800Srrh yylval = -intval; 161*13465Srrh BACK(INT); 1625800Srrh bignum: ; 1635800Srrh yybignum = as_atoi(numbuf, radix, &overflow); 164*13465Srrh BACK(BIGNUM); 1655800Srrh floatnum: ; 166*13465Srrh REGTOMEMBUF; 167*13465Srrh yybignum = floatnumber(ch); 1685800Srrh return(BIGNUM); 169*13465Srrh stuffback: ; 170*13465Srrh REGTOMEMBUF; 171*13465Srrh return(intval); 1725800Srrh } 1735800Srrh 174*13465Srrh #define TOOLONG \ 175*13465Srrh if (cp == &numbuf[NUMSIZE]){ \ 176*13465Srrh if (passno == 2) \ 177*13465Srrh yywarning(toolong); \ 178*13465Srrh goto process; \ 179*13465Srrh } 180*13465Srrh #define scanit(sign) \ 181*13465Srrh REGTOMEMBUF; \ 182*13465Srrh error |= scanint(sign, &cp); \ 183*13465Srrh MEMTOREGBUF; \ 184*13465Srrh ch = getchar(); \ 185*13465Srrh TOOLONG; 1865800Srrh 187*13465Srrh Bignum floatnumber(fltradix) 1885800Srrh int fltradix; 1895800Srrh { 1905800Srrh char *cp; 1915800Srrh int ch; 1925800Srrh char *toolong = "Floating number too long."; 1935800Srrh char *prologue = 1945800Srrh "Floating 0%c conflicts with exponent %c; choose %c"; 1955800Srrh /* 1965800Srrh * This is not implemented yet: 1975800Srrh * overflow is set on floating overflow. 1985800Srrh */ 1995800Srrh Ovf overflow; 2005800Srrh int error; 2015800Srrh int fractOK; 2025800Srrh reg char *inbufptr; 203*13465Srrh reg int inbufcnt; 2045800Srrh 205*13465Srrh MEMTOREGBUF; 2065800Srrh cp = numbuf; 2075800Srrh error = 0; 2085800Srrh fractOK = 0; 2095800Srrh 2105800Srrh scanit(1); 2115800Srrh if(INCHARSET(ch, POINT)){ 2125800Srrh fractOK++; 2135800Srrh *cp++ = '.'; 2145800Srrh scanit(0); 2155800Srrh } 2165800Srrh if(INCHARSET(ch, FLOATEXP)){ 2175800Srrh fractOK++; 2185800Srrh if(ch != fltradix){ 2195800Srrh if (passno == 2) 2205800Srrh yywarning(prologue, fltradix, ch, fltradix); 2215800Srrh } 2225800Srrh switch(fltradix){ 2235800Srrh case 'd': 2245800Srrh case 'f': 2255800Srrh *cp++ = 'e'; /* will be read by atof() */ 2265800Srrh break; 2275800Srrh default: 2285800Srrh *cp++ = fltradix; /* will be read by bigatof() */ 2295800Srrh break; 2305800Srrh } 2315800Srrh scanit(1); 2325800Srrh } 2335800Srrh if (error || fractOK == 0){ 2345800Srrh yyerror("Badly formatted floating point number."); 2355800Srrh } 2365800Srrh ungetc(ch); 2375800Srrh *cp++ = 0; 2385800Srrh 2395800Srrh process: ; 2405800Srrh switch(fltradix){ 2415800Srrh case 'f': fltradix = TYPF; break; 2425800Srrh case 'd': fltradix = TYPD; break; 2435800Srrh case 'g': fltradix = TYPG; nGHnumbers++; break; 2445800Srrh case 'h': fltradix = TYPH; nGHnumbers++; break; 2455800Srrh } 246*13465Srrh REGTOMEMBUF; 2475800Srrh /* 2485800Srrh * The overflow value is lost in the call to as_atof 2495800Srrh */ 2505800Srrh return(as_atof(numbuf, fltradix, &overflow)); 2515800Srrh } 2525800Srrh /* 2535800Srrh * Scan an optionally signed integer, putting back the lookahead 2545800Srrh * character when finished scanning. 2555800Srrh */ 256*13465Srrh int scanint(signOK, dstcpp) 2575800Srrh int signOK; 2585800Srrh char **dstcpp; 2595800Srrh { 260*13465Srrh int ch; 261*13465Srrh int back = 0; 262*13465Srrh reg char *inbufptr; 263*13465Srrh reg int inbufcnt; 2645800Srrh 265*13465Srrh MEMTOREGBUF; 2665800Srrh ch = getchar(); 2675800Srrh while (INCHARSET(ch, SIGN)){ 2685800Srrh if (signOK && !back) 2695800Srrh *((*dstcpp)++) = ch; 2705800Srrh else 2715800Srrh back = 1; 2725800Srrh ch = getchar(); 2735800Srrh } 2745800Srrh while (INCHARSET(ch, DIGIT)){ 2755800Srrh *((*dstcpp)++) = ch; 2765800Srrh ch = getchar(); 2775800Srrh } 2785800Srrh ungetc(ch); 279*13465Srrh REGTOMEMBUF; 2805800Srrh return(back); 2815800Srrh } 282