15798Srrh /*
2*19829Sdist * Copyright (c) 1982 Regents of the University of California.
3*19829Sdist * All rights reserved. The Berkeley software License Agreement
4*19829Sdist * specifies the terms and conditions for redistribution.
55798Srrh */
6*19829Sdist
75798Srrh #ifndef lint
8*19829Sdist static char sccsid[] = "@(#)asscan2.c 5.1 (Berkeley) 04/30/85";
95798Srrh #endif not lint
105798Srrh
115798Srrh #include "asscanl.h"
1213467Srrh
135798Srrh static inttoktype oval = NL;
1413575Srrh #define ASINBUFSIZ 4096
1513467Srrh char inbufunget[8];
1613467Srrh char inbuffer[ASINBUFSIZ];
1713467Srrh char *Ginbufptr = inbuffer;
1813467Srrh int Ginbufcnt = 0;
1913808Srrh int scannerhadeof;
2013467Srrh
fillinbuffer()2113467Srrh fillinbuffer()
2213467Srrh {
2313467Srrh int nread;
2413467Srrh int goal;
2513467Srrh int got;
2613467Srrh
2713467Srrh nread = 0;
2813808Srrh if (scannerhadeof == 0){
2913467Srrh goal = sizeof(inbuffer);
3013467Srrh do {
3113467Srrh got = read(stdin->_file, inbuffer + nread, goal);
3213467Srrh if (got == 0)
3313808Srrh scannerhadeof = 1;
3413467Srrh if (got <= 0)
3513467Srrh break;
3613467Srrh nread += got;
3713467Srrh goal -= got;
3813467Srrh } while (goal);
3913808Srrh } else {
4013808Srrh scannerhadeof = 0;
4113467Srrh }
425798Srrh /*
4313467Srrh * getchar assumes that Ginbufcnt and Ginbufptr
4413467Srrh * are adjusted as if one character has been removed
4513467Srrh * from the input.
465798Srrh */
4713467Srrh if (nread == 0){
4813467Srrh inbuffer[0] = EOFCHAR;
4913467Srrh nread = 1;
5013467Srrh }
5113467Srrh Ginbufcnt = nread - 1;
5213467Srrh Ginbufptr = inbuffer + 1;
5313467Srrh }
545798Srrh
555798Srrh scan_dot_s(bufferbox)
565798Srrh struct tokbufdesc *bufferbox;
575798Srrh {
5813467Srrh reg char *inbufptr;
5913467Srrh reg int inbufcnt;
605798Srrh reg int ryylval; /* local copy of lexical value */
615798Srrh extern int yylval; /* global copy of lexical value */
625798Srrh reg int val; /* the value returned */
635798Srrh int i; /* simple counter */
645798Srrh reg char *rcp;
6513467Srrh int ch; /* treated as a character */
665798Srrh int ch1; /* shadow value */
675798Srrh struct symtab *op;
6813467Srrh ptrall lgbackpatch; /* where to stuff a string length */
695798Srrh reg ptrall bufptr; /* where to stuff tokens */
705798Srrh ptrall bufub; /* where not to stuff tokens */
715798Srrh long intval; /* value of int */
725798Srrh int linescrossed; /* when doing strings and comments */
735798Srrh struct Opcode opstruct;
7413573Srrh reg int strlg; /* the length of a string */
755798Srrh
765798Srrh (bytetoktype *)bufptr = (bytetoktype *) & (bufferbox->toks[0]);
775798Srrh (bytetoktype *)bufub = &(bufferbox->toks[AVAILTOKS]);
785798Srrh
7913467Srrh MEMTOREGBUF;
805798Srrh if (newfflag){
8113448Srrh newfflag = 0;
8213573Srrh ryylval = (int)savestr(newfname, strlen(newfname)+1, STR_BOTH);
8313448Srrh
845798Srrh ptoken(bufptr, IFILE);
855798Srrh ptoken(bufptr, STRING);
8613448Srrh pptr(bufptr, ryylval);
875798Srrh
885798Srrh ptoken(bufptr, ILINENO);
895798Srrh ptoken(bufptr, INT);
905798Srrh pint(bufptr, 1);
915798Srrh }
925798Srrh
935798Srrh while (bufptr < bufub){
945798Srrh loop:
9513467Srrh switch(ryylval = (type+1)[ch = getchar()]) {
965798Srrh case SCANEOF:
9713467Srrh endoffile: ;
985798Srrh inbufptr = 0;
9913467Srrh ptoken(bufptr, PARSEEOF);
10013467Srrh goto done;
1015798Srrh
1025798Srrh case DIV: /*process C style comments*/
1035798Srrh if ( (ch = getchar()) == '*') { /*comment prelude*/
1045798Srrh int incomment;
1055798Srrh linescrossed = 0;
1065798Srrh incomment = 1;
1075798Srrh ch = getchar(); /*skip over the * */
1085798Srrh while(incomment){
1095798Srrh switch(ch){
1105798Srrh case '*':
1115798Srrh ch = getchar();
1125798Srrh incomment = (ch != '/');
1135798Srrh break;
1145798Srrh case '\n':
1155798Srrh scanlineno++;
1165798Srrh linescrossed++;
1175798Srrh ch = getchar();
1185798Srrh break;
1195798Srrh case EOFCHAR:
1205798Srrh goto endoffile;
1215798Srrh default:
1225798Srrh ch = getchar();
1235798Srrh break;
1245798Srrh }
1255798Srrh }
1265798Srrh val = ILINESKIP;
1275798Srrh ryylval = linescrossed;
1285798Srrh goto ret;
1295798Srrh } else { /*just an ordinary DIV*/
1305798Srrh ungetc(ch);
1315798Srrh val = ryylval = DIV;
1325798Srrh goto ret;
1335798Srrh }
1345798Srrh case SH:
1355798Srrh if (oval == NL){
1365798Srrh /*
1375798Srrh * Attempt to recognize a C preprocessor
1385798Srrh * style comment '^#[ \t]*[0-9]*[ \t]*".*"
1395798Srrh */
1405798Srrh ch = getchar(); /*bump the #*/
1415798Srrh while (INCHARSET(ch, SPACE))
1425798Srrh ch = getchar();/*bump white */
1435798Srrh if (INCHARSET(ch, DIGIT)){
1445798Srrh intval = 0;
1455798Srrh while(INCHARSET(ch, DIGIT)){
1465798Srrh intval = intval*10 + ch - '0';
1475798Srrh ch = getchar();
1485798Srrh }
1495798Srrh while (INCHARSET(ch, SPACE))
1505798Srrh ch = getchar();
1515798Srrh if (ch == '"'){
1525798Srrh ptoken(bufptr, ILINENO);
1535798Srrh ptoken(bufptr, INT);
1545798Srrh pint(bufptr, intval - 1);
1555798Srrh ptoken(bufptr, IFILE);
1565798Srrh /*
1575798Srrh * The '"' has already been
1585798Srrh * munched
1595798Srrh *
1605798Srrh * eatstr will not eat
1615798Srrh * the trailing \n, so
1625798Srrh * it is given to the parser
1635798Srrh * and counted.
1645798Srrh */
1655798Srrh goto eatstr;
1665798Srrh }
1675798Srrh }
1685798Srrh }
1695798Srrh /*
1705798Srrh * Well, its just an ordinary decadent comment
1715798Srrh */
1725798Srrh while ((ch != '\n') && (ch != EOFCHAR))
1735798Srrh ch = getchar();
1745798Srrh if (ch == EOFCHAR)
1755798Srrh goto endoffile;
1765798Srrh val = ryylval = oval = NL;
1775798Srrh scanlineno++;
1785798Srrh goto ret;
1795798Srrh
1805798Srrh case NL:
1815798Srrh scanlineno++;
1825798Srrh val = ryylval;
1835798Srrh goto ret;
1845798Srrh
1855798Srrh case SP:
1865798Srrh oval = SP; /*invalidate ^# meta comments*/
1875798Srrh goto loop;
1885798Srrh
1895798Srrh case REGOP: /* % , could be used as modulo, or register*/
1905798Srrh ch = getchar();
1915798Srrh if (INCHARSET(ch, DIGIT)){
1925798Srrh ryylval = ch-'0';
1935798Srrh if (ch=='1') {
1945798Srrh if (INCHARSET( (ch = getchar()), REGDIGIT))
1955798Srrh ryylval = 10+ch-'0';
1965798Srrh else
1975798Srrh ungetc(ch);
1985798Srrh }
1995798Srrh /*
2005798Srrh * God only knows what the original author
2015798Srrh * wanted this undocumented feature to
2025798Srrh * do.
2035798Srrh * %5++ is really r7
2045798Srrh */
2055798Srrh while(INCHARSET( (ch = getchar()), SIGN)) {
2065798Srrh if (ch=='+')
2075798Srrh ryylval++;
2085798Srrh else
2095798Srrh ryylval--;
2105798Srrh }
2115798Srrh ungetc(ch);
2125798Srrh val = REG;
2135798Srrh } else {
2145798Srrh ungetc(ch);
2155798Srrh val = REGOP;
2165798Srrh }
2175798Srrh goto ret;
2185798Srrh
2195798Srrh case ALPH:
2205798Srrh ch1 = ch;
2215798Srrh if (INCHARSET(ch, SZSPECBEGIN)){
2225798Srrh if( (ch = getchar()) == '`' || ch == '^'){
2235798Srrh ch1 |= 0100; /*convert to lower*/
2245798Srrh switch(ch1){
2255798Srrh case 'b': ryylval = 1; break;
2265798Srrh case 'w': ryylval = 2; break;
2275798Srrh case 'l': ryylval = 4; break;
2285798Srrh default: ryylval = d124; break;
2295798Srrh }
2305798Srrh val = SIZESPEC;
2315798Srrh goto ret;
2325798Srrh } else {
2335798Srrh ungetc(ch);
2345798Srrh ch = ch1; /*restore first character*/
2355798Srrh }
2365798Srrh }
2375798Srrh rcp = yytext;
2385798Srrh do {
23913462Srrh if (rcp < &yytext[NCPName])
2405798Srrh *rcp++ = ch;
2415798Srrh } while (INCHARSET ( (ch = getchar()), ALPHA | DIGIT));
2425798Srrh *rcp = '\0';
2435798Srrh while (INCHARSET(ch, SPACE))
2445798Srrh ch = getchar();
2455798Srrh ungetc(ch);
2465798Srrh
2475798Srrh switch((op = *lookup(1))->s_tag){
2485798Srrh case 0:
2495798Srrh case LABELID:
2505798Srrh /*
25113516Srrh * Its a name... (Labels are subsets of name)
2525798Srrh */
2535798Srrh ryylval = (int)op;
2545798Srrh val = NAME;
2555798Srrh break;
2565798Srrh case INST0:
2575798Srrh case INSTn:
2585798Srrh case IJXXX:
2595798Srrh opstruct.Op_popcode = ( (struct instab *)op)->i_popcode;
2605798Srrh opstruct.Op_eopcode = ( (struct instab *)op)->i_eopcode;
2615798Srrh val = op->s_tag;
2625798Srrh break;
2635798Srrh default:
2645798Srrh ryylval = ( (struct instab *)op)->i_popcode;
2655798Srrh val = op->s_tag;
2665798Srrh break;
2675798Srrh }
2685798Srrh goto ret;
2695798Srrh
2705798Srrh case DIG:
2715798Srrh /*
27213467Srrh * restore local inbufptr and inbufcnt
2735798Srrh */
27413467Srrh REGTOMEMBUF;
27513467Srrh val = number(ch);
27613467Srrh MEMTOREGBUF;
2775798Srrh /*
2785798Srrh * yylval or yybignum has been stuffed as a side
2795798Srrh * effect to number(); get the global yylval
2805798Srrh * into our fast local copy in case it was an INT.
2815798Srrh */
2825798Srrh ryylval = yylval;
2835798Srrh goto ret;
2845798Srrh
2855798Srrh case LSH:
2865798Srrh case RSH:
2875798Srrh /*
2885798Srrh * We allow the C style operators
2895798Srrh * << and >>, as well as < and >
2905798Srrh */
2915798Srrh if ( (ch1 = getchar()) != ch)
2925798Srrh ungetc(ch1);
2935798Srrh val = ryylval;
2945798Srrh goto ret;
2955798Srrh
2965798Srrh case MINUS:
2975798Srrh if ( (ch = getchar()) =='(')
2985798Srrh ryylval=val=MP;
2995798Srrh else {
3005798Srrh ungetc(ch);
3015798Srrh val=MINUS;
3025798Srrh }
3035798Srrh goto ret;
3045798Srrh
3055798Srrh case SQ:
3065798Srrh if ((ryylval = getchar()) == '\n')
3075798Srrh scanlineno++; /*not entirely correct*/
3085798Srrh val = INT;
3095798Srrh goto ret;
3105798Srrh
3115798Srrh case DQ:
3125798Srrh eatstr:
3135798Srrh linescrossed = 0;
31413573Srrh for (strlg = 0; /*VOID*/; strlg++){
31513448Srrh switch(ch = getchar()){
31613448Srrh case '"':
31713448Srrh goto tailDQ;
31813448Srrh default:
31913448Srrh stuff:
32013516Srrh putc(ch, strfile);
32113448Srrh break;
32213448Srrh case '\n':
32313448Srrh yywarning("New line in a string constant");
3245798Srrh scanlineno++;
3255798Srrh linescrossed++;
3265798Srrh ch = getchar();
32713448Srrh switch(ch){
32813448Srrh case EOFCHAR:
32913516Srrh putc('\n', strfile);
3305798Srrh ungetc(EOFCHAR);
33113448Srrh goto tailDQ;
33213448Srrh default:
3335798Srrh ungetc(ch);
3345798Srrh ch = '\n';
3355798Srrh goto stuff;
3365798Srrh }
33713448Srrh break;
33813448Srrh
33913448Srrh case '\\':
3405798Srrh ch = getchar(); /*skip the '\\'*/
3415798Srrh if ( INCHARSET(ch, BSESCAPE)){
3425798Srrh switch (ch){
3435798Srrh case 'b': ch = '\b'; goto stuff;
3445798Srrh case 'f': ch = '\f'; goto stuff;
3455798Srrh case 'n': ch = '\n'; goto stuff;
3465798Srrh case 'r': ch = '\r'; goto stuff;
3475798Srrh case 't': ch = '\t'; goto stuff;
3485798Srrh }
3495798Srrh }
35013448Srrh if ( !(INCHARSET(ch, OCTDIGIT)) )
35113448Srrh goto stuff;
3525798Srrh i = 0;
3535798Srrh intval = 0;
3545798Srrh while ( (i < 3) && (INCHARSET(ch, OCTDIGIT))){
35513448Srrh i++;
35613448Srrh intval <<= 3;
35713448Srrh intval += ch - '0';
3585798Srrh ch = getchar();
3595798Srrh }
3605798Srrh ungetc(ch);
3616558Srrh ch = (char)intval;
3625798Srrh goto stuff;
36313448Srrh }
3645798Srrh }
36513448Srrh tailDQ: ;
3665798Srrh /*
36713448Srrh * account for any lines that were crossed
3685798Srrh */
3695798Srrh if (linescrossed){
37013448Srrh ptoken(bufptr, ILINESKIP);
37113448Srrh pint(bufptr, linescrossed);
37213448Srrh }
37313448Srrh /*
37413448Srrh * Cheat: append a trailing null to the string
37513448Srrh * and then adjust the string length to ignore
37613448Srrh * the trailing null. If any STRING client requires
37713448Srrh * the trailing null, the client can just change STRLEN
37813448Srrh */
37913573Srrh putc(0, strfile);
38013573Srrh ryylval = (int)savestr((char *)0, strlg + 1, STR_FILE);
38113448Srrh val = STRING;
38213516Srrh ((struct strdesc *)ryylval)->sd_strlen -= 1;
38313448Srrh goto ret;
3845798Srrh
3855798Srrh case BADCHAR:
3865798Srrh linescrossed = lineno;
3875798Srrh lineno = scanlineno;
3885798Srrh yyerror("Illegal character mapped: %d, char read:(octal) %o",
3895798Srrh ryylval, ch);
3905798Srrh lineno = linescrossed;
3915798Srrh val = BADCHAR;
3925798Srrh goto ret;
3935798Srrh
3945798Srrh default:
3955798Srrh val = ryylval;
3965798Srrh goto ret;
3975798Srrh } /*end of the switch*/
3985798Srrh /*
3995798Srrh * here with one token, so stuff it
4005798Srrh */
4015798Srrh ret:
4025798Srrh oval = val;
4035798Srrh ptoken(bufptr, val);
4045798Srrh switch(val){
4055798Srrh case ILINESKIP:
4065798Srrh pint(bufptr, ryylval);
4075798Srrh break;
4085798Srrh case SIZESPEC:
4095798Srrh pchar(bufptr, ryylval);
4105798Srrh break;
4115798Srrh case BFINT: plong(bufptr, ryylval);
4125798Srrh break;
4135798Srrh case INT: plong(bufptr, ryylval);
4145798Srrh break;
4155798Srrh case BIGNUM: pnumber(bufptr, yybignum);
4165798Srrh break;
41713448Srrh case STRING: pptr(bufptr, (int)(char *)ryylval);
41813448Srrh break;
4195798Srrh case NAME: pptr(bufptr, (int)(struct symtab *)ryylval);
4205798Srrh break;
4215798Srrh case REG: pchar(bufptr, ryylval);
4225798Srrh break;
4235798Srrh case INST0:
4245798Srrh case INSTn:
4255798Srrh popcode(bufptr, opstruct);
4265798Srrh break;
4275798Srrh case IJXXX:
4285798Srrh popcode(bufptr, opstruct);
4295798Srrh pptr(bufptr, (int)(struct symtab *)symalloc());
4305798Srrh break;
4315798Srrh case ISTAB:
4325798Srrh case ISTABSTR:
4335798Srrh case ISTABNONE:
4345798Srrh case ISTABDOT:
4355798Srrh case IALIGN:
4365798Srrh pptr(bufptr, (int)(struct symtab *)symalloc());
4375798Srrh break;
4385798Srrh /*
4395798Srrh * default:
4405798Srrh */
4415798Srrh }
4425798Srrh builtval: ;
4435798Srrh } /*end of the while to stuff the buffer*/
4445798Srrh done:
4455798Srrh bufferbox->tok_count = (bytetoktype *)bufptr - &(bufferbox->toks[0]);
4465798Srrh /*
4475798Srrh * This is a real kludge:
4485798Srrh *
4495798Srrh * We put the last token in the buffer to be a MINUS
4505798Srrh * symbol. This last token will never be picked up
4515798Srrh * in the normal way, but can be looked at during
4525798Srrh * a peekahead look that the short circuit expression
4535798Srrh * evaluator uses to see if an expression is complicated.
4545798Srrh *
4555798Srrh * Consider the following situation:
4565798Srrh *
4575798Srrh * .word 45 + 47
4585798Srrh * buffer 1 | buffer 0
4595798Srrh * the peekahead would want to look across the buffer,
4605798Srrh * but will look in the buffer end zone, see the minus, and
4615798Srrh * fail.
4625798Srrh */
4635798Srrh ptoken(bufptr, MINUS);
46413467Srrh REGTOMEMBUF;
4655798Srrh }
466