15798Srrh /* 25798Srrh * Copyright (c) 1982 Regents of the University of California 35798Srrh */ 45798Srrh #ifndef lint 5*13573Srrh static char sccsid[] = "@(#)asscan2.c 4.12 07/01/83"; 65798Srrh #endif not lint 75798Srrh 85798Srrh #include "asscanl.h" 913467Srrh 105798Srrh static inttoktype oval = NL; 115798Srrh 1213467Srrh char inbufunget[8]; 1313467Srrh char inbuffer[ASINBUFSIZ]; 1413467Srrh char *Ginbufptr = inbuffer; 1513467Srrh int Ginbufcnt = 0; 1613467Srrh 1713467Srrh fillinbuffer() 1813467Srrh { 1913467Srrh int nread; 2013467Srrh static int hadeof; 2113467Srrh int goal; 2213467Srrh int got; 2313467Srrh 2413467Srrh nread = 0; 2513467Srrh if (hadeof == 0){ 2613467Srrh goal = sizeof(inbuffer); 2713467Srrh do { 2813467Srrh got = read(stdin->_file, inbuffer + nread, goal); 2913467Srrh if (got == 0) 3013467Srrh hadeof = 1; 3113467Srrh if (got <= 0) 3213467Srrh break; 3313467Srrh nread += got; 3413467Srrh goal -= got; 3513467Srrh } while (goal); 3613467Srrh } 375798Srrh /* 3813467Srrh * getchar assumes that Ginbufcnt and Ginbufptr 3913467Srrh * are adjusted as if one character has been removed 4013467Srrh * from the input. 415798Srrh */ 4213467Srrh if (nread == 0){ 4313467Srrh inbuffer[0] = EOFCHAR; 4413467Srrh nread = 1; 4513467Srrh } 4613467Srrh Ginbufcnt = nread - 1; 4713467Srrh Ginbufptr = inbuffer + 1; 4813467Srrh } 495798Srrh 505798Srrh scan_dot_s(bufferbox) 515798Srrh struct tokbufdesc *bufferbox; 525798Srrh { 5313467Srrh reg char *inbufptr; 5413467Srrh reg int inbufcnt; 555798Srrh reg int ryylval; /* local copy of lexical value */ 565798Srrh extern int yylval; /* global copy of lexical value */ 575798Srrh reg int val; /* the value returned */ 585798Srrh int i; /* simple counter */ 595798Srrh reg char *rcp; 6013467Srrh int ch; /* treated as a character */ 615798Srrh int ch1; /* shadow value */ 625798Srrh struct symtab *op; 6313467Srrh ptrall lgbackpatch; /* where to stuff a string length */ 645798Srrh reg ptrall bufptr; /* where to stuff tokens */ 655798Srrh ptrall bufub; /* where not to stuff tokens */ 665798Srrh long intval; /* value of int */ 675798Srrh int linescrossed; /* when doing strings and comments */ 685798Srrh struct Opcode opstruct; 69*13573Srrh reg int strlg; /* the length of a string */ 705798Srrh 715798Srrh (bytetoktype *)bufptr = (bytetoktype *) & (bufferbox->toks[0]); 725798Srrh (bytetoktype *)bufub = &(bufferbox->toks[AVAILTOKS]); 735798Srrh 7413467Srrh MEMTOREGBUF; 755798Srrh if (newfflag){ 7613448Srrh newfflag = 0; 77*13573Srrh ryylval = (int)savestr(newfname, strlen(newfname)+1, STR_BOTH); 7813448Srrh 795798Srrh ptoken(bufptr, IFILE); 805798Srrh ptoken(bufptr, STRING); 8113448Srrh pptr(bufptr, ryylval); 825798Srrh 835798Srrh ptoken(bufptr, ILINENO); 845798Srrh ptoken(bufptr, INT); 855798Srrh pint(bufptr, 1); 865798Srrh } 875798Srrh 885798Srrh while (bufptr < bufub){ 895798Srrh loop: 9013467Srrh switch(ryylval = (type+1)[ch = getchar()]) { 915798Srrh case SCANEOF: 9213467Srrh endoffile: ; 935798Srrh inbufptr = 0; 9413467Srrh ptoken(bufptr, PARSEEOF); 9513467Srrh goto done; 965798Srrh 975798Srrh case DIV: /*process C style comments*/ 985798Srrh if ( (ch = getchar()) == '*') { /*comment prelude*/ 995798Srrh int incomment; 1005798Srrh linescrossed = 0; 1015798Srrh incomment = 1; 1025798Srrh ch = getchar(); /*skip over the * */ 1035798Srrh while(incomment){ 1045798Srrh switch(ch){ 1055798Srrh case '*': 1065798Srrh ch = getchar(); 1075798Srrh incomment = (ch != '/'); 1085798Srrh break; 1095798Srrh case '\n': 1105798Srrh scanlineno++; 1115798Srrh linescrossed++; 1125798Srrh ch = getchar(); 1135798Srrh break; 1145798Srrh case EOFCHAR: 1155798Srrh goto endoffile; 1165798Srrh default: 1175798Srrh ch = getchar(); 1185798Srrh break; 1195798Srrh } 1205798Srrh } 1215798Srrh val = ILINESKIP; 1225798Srrh ryylval = linescrossed; 1235798Srrh goto ret; 1245798Srrh } else { /*just an ordinary DIV*/ 1255798Srrh ungetc(ch); 1265798Srrh val = ryylval = DIV; 1275798Srrh goto ret; 1285798Srrh } 1295798Srrh case SH: 1305798Srrh if (oval == NL){ 1315798Srrh /* 1325798Srrh * Attempt to recognize a C preprocessor 1335798Srrh * style comment '^#[ \t]*[0-9]*[ \t]*".*" 1345798Srrh */ 1355798Srrh ch = getchar(); /*bump the #*/ 1365798Srrh while (INCHARSET(ch, SPACE)) 1375798Srrh ch = getchar();/*bump white */ 1385798Srrh if (INCHARSET(ch, DIGIT)){ 1395798Srrh intval = 0; 1405798Srrh while(INCHARSET(ch, DIGIT)){ 1415798Srrh intval = intval*10 + ch - '0'; 1425798Srrh ch = getchar(); 1435798Srrh } 1445798Srrh while (INCHARSET(ch, SPACE)) 1455798Srrh ch = getchar(); 1465798Srrh if (ch == '"'){ 1475798Srrh ptoken(bufptr, ILINENO); 1485798Srrh ptoken(bufptr, INT); 1495798Srrh pint(bufptr, intval - 1); 1505798Srrh ptoken(bufptr, IFILE); 1515798Srrh /* 1525798Srrh * The '"' has already been 1535798Srrh * munched 1545798Srrh * 1555798Srrh * eatstr will not eat 1565798Srrh * the trailing \n, so 1575798Srrh * it is given to the parser 1585798Srrh * and counted. 1595798Srrh */ 1605798Srrh goto eatstr; 1615798Srrh } 1625798Srrh } 1635798Srrh } 1645798Srrh /* 1655798Srrh * Well, its just an ordinary decadent comment 1665798Srrh */ 1675798Srrh while ((ch != '\n') && (ch != EOFCHAR)) 1685798Srrh ch = getchar(); 1695798Srrh if (ch == EOFCHAR) 1705798Srrh goto endoffile; 1715798Srrh val = ryylval = oval = NL; 1725798Srrh scanlineno++; 1735798Srrh goto ret; 1745798Srrh 1755798Srrh case NL: 1765798Srrh scanlineno++; 1775798Srrh val = ryylval; 1785798Srrh goto ret; 1795798Srrh 1805798Srrh case SP: 1815798Srrh oval = SP; /*invalidate ^# meta comments*/ 1825798Srrh goto loop; 1835798Srrh 1845798Srrh case REGOP: /* % , could be used as modulo, or register*/ 1855798Srrh ch = getchar(); 1865798Srrh if (INCHARSET(ch, DIGIT)){ 1875798Srrh ryylval = ch-'0'; 1885798Srrh if (ch=='1') { 1895798Srrh if (INCHARSET( (ch = getchar()), REGDIGIT)) 1905798Srrh ryylval = 10+ch-'0'; 1915798Srrh else 1925798Srrh ungetc(ch); 1935798Srrh } 1945798Srrh /* 1955798Srrh * God only knows what the original author 1965798Srrh * wanted this undocumented feature to 1975798Srrh * do. 1985798Srrh * %5++ is really r7 1995798Srrh */ 2005798Srrh while(INCHARSET( (ch = getchar()), SIGN)) { 2015798Srrh if (ch=='+') 2025798Srrh ryylval++; 2035798Srrh else 2045798Srrh ryylval--; 2055798Srrh } 2065798Srrh ungetc(ch); 2075798Srrh val = REG; 2085798Srrh } else { 2095798Srrh ungetc(ch); 2105798Srrh val = REGOP; 2115798Srrh } 2125798Srrh goto ret; 2135798Srrh 2145798Srrh case ALPH: 2155798Srrh ch1 = ch; 2165798Srrh if (INCHARSET(ch, SZSPECBEGIN)){ 2175798Srrh if( (ch = getchar()) == '`' || ch == '^'){ 2185798Srrh ch1 |= 0100; /*convert to lower*/ 2195798Srrh switch(ch1){ 2205798Srrh case 'b': ryylval = 1; break; 2215798Srrh case 'w': ryylval = 2; break; 2225798Srrh case 'l': ryylval = 4; break; 2235798Srrh default: ryylval = d124; break; 2245798Srrh } 2255798Srrh val = SIZESPEC; 2265798Srrh goto ret; 2275798Srrh } else { 2285798Srrh ungetc(ch); 2295798Srrh ch = ch1; /*restore first character*/ 2305798Srrh } 2315798Srrh } 2325798Srrh rcp = yytext; 2335798Srrh do { 23413462Srrh if (rcp < &yytext[NCPName]) 2355798Srrh *rcp++ = ch; 2365798Srrh } while (INCHARSET ( (ch = getchar()), ALPHA | DIGIT)); 2375798Srrh *rcp = '\0'; 2385798Srrh while (INCHARSET(ch, SPACE)) 2395798Srrh ch = getchar(); 2405798Srrh ungetc(ch); 2415798Srrh 2425798Srrh switch((op = *lookup(1))->s_tag){ 2435798Srrh case 0: 2445798Srrh case LABELID: 2455798Srrh /* 24613516Srrh * Its a name... (Labels are subsets of name) 2475798Srrh */ 2485798Srrh ryylval = (int)op; 2495798Srrh val = NAME; 2505798Srrh break; 2515798Srrh case INST0: 2525798Srrh case INSTn: 2535798Srrh case IJXXX: 2545798Srrh opstruct.Op_popcode = ( (struct instab *)op)->i_popcode; 2555798Srrh opstruct.Op_eopcode = ( (struct instab *)op)->i_eopcode; 2565798Srrh val = op->s_tag; 2575798Srrh break; 2585798Srrh default: 2595798Srrh ryylval = ( (struct instab *)op)->i_popcode; 2605798Srrh val = op->s_tag; 2615798Srrh break; 2625798Srrh } 2635798Srrh goto ret; 2645798Srrh 2655798Srrh case DIG: 2665798Srrh /* 26713467Srrh * restore local inbufptr and inbufcnt 2685798Srrh */ 26913467Srrh REGTOMEMBUF; 27013467Srrh val = number(ch); 27113467Srrh MEMTOREGBUF; 2725798Srrh /* 2735798Srrh * yylval or yybignum has been stuffed as a side 2745798Srrh * effect to number(); get the global yylval 2755798Srrh * into our fast local copy in case it was an INT. 2765798Srrh */ 2775798Srrh ryylval = yylval; 2785798Srrh goto ret; 2795798Srrh 2805798Srrh case LSH: 2815798Srrh case RSH: 2825798Srrh /* 2835798Srrh * We allow the C style operators 2845798Srrh * << and >>, as well as < and > 2855798Srrh */ 2865798Srrh if ( (ch1 = getchar()) != ch) 2875798Srrh ungetc(ch1); 2885798Srrh val = ryylval; 2895798Srrh goto ret; 2905798Srrh 2915798Srrh case MINUS: 2925798Srrh if ( (ch = getchar()) =='(') 2935798Srrh ryylval=val=MP; 2945798Srrh else { 2955798Srrh ungetc(ch); 2965798Srrh val=MINUS; 2975798Srrh } 2985798Srrh goto ret; 2995798Srrh 3005798Srrh case SQ: 3015798Srrh if ((ryylval = getchar()) == '\n') 3025798Srrh scanlineno++; /*not entirely correct*/ 3035798Srrh val = INT; 3045798Srrh goto ret; 3055798Srrh 3065798Srrh case DQ: 3075798Srrh eatstr: 3085798Srrh linescrossed = 0; 309*13573Srrh for (strlg = 0; /*VOID*/; strlg++){ 31013448Srrh switch(ch = getchar()){ 31113448Srrh case '"': 31213448Srrh goto tailDQ; 31313448Srrh default: 31413448Srrh stuff: 31513516Srrh putc(ch, strfile); 31613448Srrh break; 31713448Srrh case '\n': 31813448Srrh yywarning("New line in a string constant"); 3195798Srrh scanlineno++; 3205798Srrh linescrossed++; 3215798Srrh ch = getchar(); 32213448Srrh switch(ch){ 32313448Srrh case EOFCHAR: 32413516Srrh putc('\n', strfile); 3255798Srrh ungetc(EOFCHAR); 32613448Srrh goto tailDQ; 32713448Srrh default: 3285798Srrh ungetc(ch); 3295798Srrh ch = '\n'; 3305798Srrh goto stuff; 3315798Srrh } 33213448Srrh break; 33313448Srrh 33413448Srrh case '\\': 3355798Srrh ch = getchar(); /*skip the '\\'*/ 3365798Srrh if ( INCHARSET(ch, BSESCAPE)){ 3375798Srrh switch (ch){ 3385798Srrh case 'b': ch = '\b'; goto stuff; 3395798Srrh case 'f': ch = '\f'; goto stuff; 3405798Srrh case 'n': ch = '\n'; goto stuff; 3415798Srrh case 'r': ch = '\r'; goto stuff; 3425798Srrh case 't': ch = '\t'; goto stuff; 3435798Srrh } 3445798Srrh } 34513448Srrh if ( !(INCHARSET(ch, OCTDIGIT)) ) 34613448Srrh goto stuff; 3475798Srrh i = 0; 3485798Srrh intval = 0; 3495798Srrh while ( (i < 3) && (INCHARSET(ch, OCTDIGIT))){ 35013448Srrh i++; 35113448Srrh intval <<= 3; 35213448Srrh intval += ch - '0'; 3535798Srrh ch = getchar(); 3545798Srrh } 3555798Srrh ungetc(ch); 3566558Srrh ch = (char)intval; 3575798Srrh goto stuff; 35813448Srrh } 3595798Srrh } 36013448Srrh tailDQ: ; 3615798Srrh /* 36213448Srrh * account for any lines that were crossed 3635798Srrh */ 3645798Srrh if (linescrossed){ 36513448Srrh ptoken(bufptr, ILINESKIP); 36613448Srrh pint(bufptr, linescrossed); 36713448Srrh } 36813448Srrh /* 36913448Srrh * Cheat: append a trailing null to the string 37013448Srrh * and then adjust the string length to ignore 37113448Srrh * the trailing null. If any STRING client requires 37213448Srrh * the trailing null, the client can just change STRLEN 37313448Srrh */ 374*13573Srrh putc(0, strfile); 375*13573Srrh ryylval = (int)savestr((char *)0, strlg + 1, STR_FILE); 37613448Srrh val = STRING; 37713516Srrh ((struct strdesc *)ryylval)->sd_strlen -= 1; 37813448Srrh goto ret; 3795798Srrh 3805798Srrh case BADCHAR: 3815798Srrh linescrossed = lineno; 3825798Srrh lineno = scanlineno; 3835798Srrh yyerror("Illegal character mapped: %d, char read:(octal) %o", 3845798Srrh ryylval, ch); 3855798Srrh lineno = linescrossed; 3865798Srrh val = BADCHAR; 3875798Srrh goto ret; 3885798Srrh 3895798Srrh default: 3905798Srrh val = ryylval; 3915798Srrh goto ret; 3925798Srrh } /*end of the switch*/ 3935798Srrh /* 3945798Srrh * here with one token, so stuff it 3955798Srrh */ 3965798Srrh ret: 3975798Srrh oval = val; 3985798Srrh ptoken(bufptr, val); 3995798Srrh switch(val){ 4005798Srrh case ILINESKIP: 4015798Srrh pint(bufptr, ryylval); 4025798Srrh break; 4035798Srrh case SIZESPEC: 4045798Srrh pchar(bufptr, ryylval); 4055798Srrh break; 4065798Srrh case BFINT: plong(bufptr, ryylval); 4075798Srrh break; 4085798Srrh case INT: plong(bufptr, ryylval); 4095798Srrh break; 4105798Srrh case BIGNUM: pnumber(bufptr, yybignum); 4115798Srrh break; 41213448Srrh case STRING: pptr(bufptr, (int)(char *)ryylval); 41313448Srrh break; 4145798Srrh case NAME: pptr(bufptr, (int)(struct symtab *)ryylval); 4155798Srrh break; 4165798Srrh case REG: pchar(bufptr, ryylval); 4175798Srrh break; 4185798Srrh case INST0: 4195798Srrh case INSTn: 4205798Srrh popcode(bufptr, opstruct); 4215798Srrh break; 4225798Srrh case IJXXX: 4235798Srrh popcode(bufptr, opstruct); 4245798Srrh pptr(bufptr, (int)(struct symtab *)symalloc()); 4255798Srrh break; 4265798Srrh case ISTAB: 4275798Srrh case ISTABSTR: 4285798Srrh case ISTABNONE: 4295798Srrh case ISTABDOT: 4305798Srrh case IALIGN: 4315798Srrh pptr(bufptr, (int)(struct symtab *)symalloc()); 4325798Srrh break; 4335798Srrh /* 4345798Srrh * default: 4355798Srrh */ 4365798Srrh } 4375798Srrh builtval: ; 4385798Srrh } /*end of the while to stuff the buffer*/ 4395798Srrh done: 4405798Srrh bufferbox->tok_count = (bytetoktype *)bufptr - &(bufferbox->toks[0]); 4415798Srrh /* 4425798Srrh * This is a real kludge: 4435798Srrh * 4445798Srrh * We put the last token in the buffer to be a MINUS 4455798Srrh * symbol. This last token will never be picked up 4465798Srrh * in the normal way, but can be looked at during 4475798Srrh * a peekahead look that the short circuit expression 4485798Srrh * evaluator uses to see if an expression is complicated. 4495798Srrh * 4505798Srrh * Consider the following situation: 4515798Srrh * 4525798Srrh * .word 45 + 47 4535798Srrh * buffer 1 | buffer 0 4545798Srrh * the peekahead would want to look across the buffer, 4555798Srrh * but will look in the buffer end zone, see the minus, and 4565798Srrh * fail. 4575798Srrh */ 4585798Srrh ptoken(bufptr, MINUS); 45913467Srrh REGTOMEMBUF; 4605798Srrh } 461