15800Srrh /*
2*19831Sdist * Copyright (c) 1982 Regents of the University of California.
3*19831Sdist * All rights reserved. The Berkeley software License Agreement
4*19831Sdist * specifies the terms and conditions for redistribution.
55800Srrh */
6*19831Sdist
75800Srrh #ifndef lint
8*19831Sdist static char sccsid[] = "@(#)asscan4.c 5.1 (Berkeley) 04/30/85";
95800Srrh #endif not lint
105800Srrh
115800Srrh #include "asscanl.h"
125800Srrh
135800Srrh #define reg register
145800Srrh #define NUMSIZE 128 /* how many characters long a number can be */
155800Srrh #define FLTCHAR(x) (INCHARSET((x),(DIGIT|SIGN|FLOATEXP|POINT)))
165800Srrh
175800Srrh static char numbuf[NUMSIZE];
185800Srrh
1913465Srrh #define BACK(backval) intval = backval; goto stuffback;
2013465Srrh
number(ch)2113465Srrh int number(ch)
225800Srrh reg int ch;
235800Srrh {
245800Srrh int radix;
255800Srrh int digit; /* part of number being constructed */
265800Srrh reg int intval; /* number being constructed */
275800Srrh reg char *cp;
285800Srrh reg char *inbufptr;
2913465Srrh reg int inbufcnt;
305800Srrh char ch1;
315800Srrh Bignum floatnumber();
325800Srrh Ovf overflow; /* overflow flag */
335800Srrh int maxstrlg;
345800Srrh
3513465Srrh MEMTOREGBUF;
365800Srrh cp = numbuf;
375800Srrh radix = 10;
385800Srrh
395800Srrh switch(ch){
405800Srrh case '0':
415800Srrh switch(ch = getchar()){
425800Srrh case 'b':
435800Srrh yylval = -1;
4413465Srrh BACK(BFINT);
455800Srrh case 'f':
465800Srrh /*
475800Srrh * Check if it is a local label by peeking ahead
485800Srrh */
495800Srrh ch1 = getchar();
505800Srrh ungetc(ch1);
515800Srrh if (!FLTCHAR(ch1)){
525800Srrh yylval = 1;
5313465Srrh BACK(BFINT);
545800Srrh }
555800Srrh /*FALLTHROUGH*/
565800Srrh case 'F': ch = 'f'; goto floatnum;
575800Srrh case 'd':
585800Srrh case 'D': ch = 'd'; goto floatnum;
595800Srrh case 'h':
605800Srrh case 'H': ch = 'h'; goto floatnum;
615800Srrh case 'g':
625800Srrh case 'G': ch = 'g'; goto floatnum;
635800Srrh
645800Srrh case 'x':
655800Srrh case 'X':
665800Srrh ch = '0';
675800Srrh radix = 16;
685800Srrh break;
695800Srrh case '0':
705800Srrh case '1': case '2': case '3': case '4':
715800Srrh case '5': case '6': case '7': case '8':
725800Srrh case '9':
735800Srrh radix = 8;
745800Srrh break;
755800Srrh default: /* single 0 */
765800Srrh ungetc(ch);
775800Srrh intval = 0;
785800Srrh goto smallnum;
795800Srrh }
805800Srrh break;
815800Srrh
825800Srrh case '1': case '2': case '3': case '4':
835800Srrh case '5': case '6': case '7': case '8':
845800Srrh case '9':
855800Srrh switch(ch1 = getchar()){
865800Srrh case 'f':
875800Srrh yylval = ((ch - '0') + 1);
8813465Srrh BACK(BFINT);
895800Srrh case 'b':
905800Srrh yylval = -((ch - '0') + 1);
9113465Srrh BACK(BFINT);
925800Srrh default:
935800Srrh ungetc(ch1); /* put back non zero */
945800Srrh }
955800Srrh radix = 10;
965800Srrh break;
975800Srrh }
985800Srrh intval = 0;
995800Srrh /*
1005800Srrh * There is a character in ch that must be used to
1015800Srrh * cons up the number; we can't ungetc it
1025800Srrh */
1035800Srrh do{
1045800Srrh digit = ch - '0';
1055800Srrh switch(radix){
1065800Srrh case 8:
1075800Srrh intval <<= 3;
1085800Srrh break;
1095800Srrh case 10:
1105800Srrh intval *= 10;
1115800Srrh break;
1125800Srrh case 16:
1135800Srrh intval <<= 4;
1145800Srrh if (INCHARSET(ch, HEXLDIGIT)){
1155800Srrh digit = (ch - 'a') + 10;
1165800Srrh break;
1175800Srrh }
1185800Srrh if (INCHARSET(ch, HEXUDIGIT)){
1195800Srrh digit = (ch - 'A') + 10;
1205800Srrh break;
1215800Srrh }
1225800Srrh }
1235800Srrh *cp++ = ch;
1245800Srrh /*
1255800Srrh * Build a negative number, then negate it
1265800Srrh */
1275800Srrh intval -= digit;
1285800Srrh
1295800Srrh ch = getchar();
1305800Srrh if(!INCHARSET(ch, DIGIT)){
1315800Srrh if (radix != 16)
1325800Srrh break;
1335800Srrh if(!INCHARSET(ch, (HEXLDIGIT|HEXUDIGIT)))
1345800Srrh break;
1355800Srrh }
1365800Srrh } while (1);
1375800Srrh ungetc(ch);
1385800Srrh *cp = 0;
1395800Srrh maxstrlg = cp - numbuf;
1405800Srrh /*
1415800Srrh * See if the number is too large for our previous calculation
1425800Srrh */
1435800Srrh switch(radix){
1445800Srrh case 16:
1455800Srrh if (maxstrlg > 8)
1465800Srrh goto bignum;
1475800Srrh break;
1485800Srrh case 10:
1495800Srrh if (maxstrlg >= 10)
1505800Srrh goto bignum;
1515800Srrh break;
1525800Srrh case 8:
1535800Srrh if (maxstrlg > 11)
1545800Srrh goto bignum;
1555800Srrh if (maxstrlg == 11 && numbuf[0] > 3)
1565800Srrh goto bignum;
1575800Srrh break;
1585800Srrh }
1595800Srrh /*
1605800Srrh * Negate the number
1615800Srrh */
1625800Srrh smallnum: ;
1635800Srrh yylval = -intval;
16413465Srrh BACK(INT);
1655800Srrh bignum: ;
1665800Srrh yybignum = as_atoi(numbuf, radix, &overflow);
16713465Srrh BACK(BIGNUM);
1685800Srrh floatnum: ;
16913465Srrh REGTOMEMBUF;
17013465Srrh yybignum = floatnumber(ch);
1715800Srrh return(BIGNUM);
17213465Srrh stuffback: ;
17313465Srrh REGTOMEMBUF;
17413465Srrh return(intval);
1755800Srrh }
1765800Srrh
17713465Srrh #define TOOLONG \
17813465Srrh if (cp == &numbuf[NUMSIZE]){ \
17913465Srrh if (passno == 2) \
18013465Srrh yywarning(toolong); \
18113465Srrh goto process; \
18213465Srrh }
18313465Srrh #define scanit(sign) \
18413465Srrh REGTOMEMBUF; \
18513465Srrh error |= scanint(sign, &cp); \
18613465Srrh MEMTOREGBUF; \
18713465Srrh ch = getchar(); \
18813465Srrh TOOLONG;
1895800Srrh
floatnumber(fltradix)19013465Srrh Bignum floatnumber(fltradix)
1915800Srrh int fltradix;
1925800Srrh {
1935800Srrh char *cp;
1945800Srrh int ch;
1955800Srrh char *toolong = "Floating number too long.";
1965800Srrh char *prologue =
1975800Srrh "Floating 0%c conflicts with exponent %c; choose %c";
1985800Srrh /*
1995800Srrh * This is not implemented yet:
2005800Srrh * overflow is set on floating overflow.
2015800Srrh */
2025800Srrh Ovf overflow;
2035800Srrh int error;
2045800Srrh int fractOK;
2055800Srrh reg char *inbufptr;
20613465Srrh reg int inbufcnt;
2075800Srrh
20813465Srrh MEMTOREGBUF;
2095800Srrh cp = numbuf;
2105800Srrh error = 0;
2115800Srrh fractOK = 0;
2125800Srrh
2135800Srrh scanit(1);
2145800Srrh if(INCHARSET(ch, POINT)){
2155800Srrh fractOK++;
2165800Srrh *cp++ = '.';
2175800Srrh scanit(0);
2185800Srrh }
2195800Srrh if(INCHARSET(ch, FLOATEXP)){
2205800Srrh fractOK++;
2215800Srrh if(ch != fltradix){
2225800Srrh if (passno == 2)
2235800Srrh yywarning(prologue, fltradix, ch, fltradix);
2245800Srrh }
2255800Srrh switch(fltradix){
2265800Srrh case 'd':
2275800Srrh case 'f':
2285800Srrh *cp++ = 'e'; /* will be read by atof() */
2295800Srrh break;
2305800Srrh default:
2315800Srrh *cp++ = fltradix; /* will be read by bigatof() */
2325800Srrh break;
2335800Srrh }
2345800Srrh scanit(1);
2355800Srrh }
2365800Srrh if (error || fractOK == 0){
2375800Srrh yyerror("Badly formatted floating point number.");
2385800Srrh }
2395800Srrh ungetc(ch);
2405800Srrh *cp++ = 0;
2415800Srrh
2425800Srrh process: ;
2435800Srrh switch(fltradix){
2445800Srrh case 'f': fltradix = TYPF; break;
2455800Srrh case 'd': fltradix = TYPD; break;
2465800Srrh case 'g': fltradix = TYPG; nGHnumbers++; break;
2475800Srrh case 'h': fltradix = TYPH; nGHnumbers++; break;
2485800Srrh }
24913465Srrh REGTOMEMBUF;
2505800Srrh /*
2515800Srrh * The overflow value is lost in the call to as_atof
2525800Srrh */
2535800Srrh return(as_atof(numbuf, fltradix, &overflow));
2545800Srrh }
2555800Srrh /*
2565800Srrh * Scan an optionally signed integer, putting back the lookahead
2575800Srrh * character when finished scanning.
2585800Srrh */
scanint(signOK,dstcpp)25913465Srrh int scanint(signOK, dstcpp)
2605800Srrh int signOK;
2615800Srrh char **dstcpp;
2625800Srrh {
26313465Srrh int ch;
26413465Srrh int back = 0;
26513465Srrh reg char *inbufptr;
26613465Srrh reg int inbufcnt;
2675800Srrh
26813465Srrh MEMTOREGBUF;
2695800Srrh ch = getchar();
2705800Srrh while (INCHARSET(ch, SIGN)){
2715800Srrh if (signOK && !back)
2725800Srrh *((*dstcpp)++) = ch;
2735800Srrh else
2745800Srrh back = 1;
2755800Srrh ch = getchar();
2765800Srrh }
2775800Srrh while (INCHARSET(ch, DIGIT)){
2785800Srrh *((*dstcpp)++) = ch;
2795800Srrh ch = getchar();
2805800Srrh }
2815800Srrh ungetc(ch);
28213465Srrh REGTOMEMBUF;
2835800Srrh return(back);
2845800Srrh }
285