ref: 81c9ede53f6f9ebd67e7134e664c98e08b9fcca6
dir: /sys/src/cmd/cc/lexbody/
/* * common code for all the assemblers */ void pragpack(void) { while(getnsc() != '\n') ; } void pragvararg(void) { while(getnsc() != '\n') ; } void pragfpround(void) { while(getnsc() != '\n') ; } void pragprofile(void) { while(getnsc() != '\n') ; } void pragincomplete(void) { while(getnsc() != '\n') ; } void setinclude(char *p) { int i; if(p == 0) return; for(i=1; i < ninclude; i++) if(strcmp(p, include[i]) == 0) return; if(ninclude >= nelem(include)) { yyerror("ninclude too small %d", nelem(include)); exits("ninclude"); } include[ninclude++] = p; } void errorexit(void) { if(outfile) remove(outfile); exits("error"); } void pushio(void) { Io *i; i = iostack; if(i == I) { yyerror("botch in pushio"); errorexit(); } i->p = fi.p; i->c = fi.c; } void newio(void) { Io *i; static int pushdepth = 0; i = iofree; if(i == I) { pushdepth++; if(pushdepth > 1000) { yyerror("macro/io expansion too deep"); errorexit(); } i = alloc(sizeof(*i)); } else iofree = i->link; i->c = 0; i->f = -1; ionext = i; } void newfile(char *s, int f) { Io *i; i = ionext; i->link = iostack; iostack = i; i->f = f; if(f < 0) i->f = open(s, 0); if(i->f < 0) { yyerror("%Ca: %r: %s", thechar, s); errorexit(); } fi.c = 0; linehist(s, 0); } Sym* slookup(char *s) { strncpy(symb, s, NSYMB); if(symb[NSYMB-1] != '\0'){ yyerror("symbol too long: %s", s); errorexit(); } return lookup(); } Sym* lookup(void) { Sym *s; ulong h; char *p; int c, n; h = 0; for(p=symb; *p;) { h = h * 3; h += *p++; } n = (p - symb) + 1; if((long)h < 0) h = ~h; h %= NHASH; c = symb[0]; for(s = hash[h]; s != S; s = s->link) { if(s->name[0] != c) continue; if(strcmp(s->name, symb) == 0) return s; } s = alloc(sizeof(*s)); s->name = alloc(n); memmove(s->name, symb, n); s->link = hash[h]; hash[h] = s; syminit(s); return s; } long yylex(void) { int c, c1; char *cp; Sym *s; c = peekc; if(c != IGN) { peekc = IGN; goto l1; } l0: c = GETC(); l1: if(c == EOF) { peekc = EOF; return -1; } if(isspace(c)) { if(c == '\n') { lineno++; return ';'; } goto l0; } if(isalpha(c)) goto talph; if(isdigit(c)) goto tnum; switch(c) { case '\n': lineno++; return ';'; case '#': domacro(); goto l0; case '.': c = GETC(); if(isalpha(c)) { cp = symb; *cp++ = '.'; goto aloop; } if(isdigit(c)) { cp = symb; *cp++ = '.'; goto casedot; } peekc = c; return '.'; talph: case '_': case '@': cp = symb; aloop: if(cp >= &symb[NSYMB-1]) goto toolong; *cp++ = c; c = GETC(); if(isalpha(c) || isdigit(c) || c == '_' || c == '$') goto aloop; *cp = 0; peekc = c; s = lookup(); if(s->macro) { newio(); cp = ionext->b; macexpand(s, cp, sizeof(ionext->b)); pushio(); ionext->link = iostack; iostack = ionext; fi.p = cp; fi.c = strlen(cp); if(peekc != IGN) { cp[fi.c++] = peekc; cp[fi.c] = 0; peekc = IGN; } goto l0; } if(s->type == 0) s->type = LNAME; if(s->type == LNAME || s->type == LVAR || s->type == LLAB) { yylval.sym = s; return s->type; } yylval.lval = s->value; return s->type; tnum: cp = symb; if(c != '0') goto dc; *cp++ = c; c = GETC(); c1 = 3; if(c == 'x' || c == 'X') { c1 = 4; c = GETC(); } else if(c < '0' || c > '7') goto dc; yylval.lval = 0; for(;;) { if(c >= '0' && c <= '9') { if(c > '7' && c1 == 3) break; yylval.lval <<= c1; yylval.lval += c - '0'; c = GETC(); continue; } if(c1 == 3) break; if(c >= 'A' && c <= 'F') c += 'a' - 'A'; if(c >= 'a' && c <= 'f') { yylval.lval <<= c1; yylval.lval += c - 'a' + 10; c = GETC(); continue; } break; } goto ncu; dc: for(;;) { if(!isdigit(c)) break; if(cp >= &symb[NSYMB-1]) goto toolong; *cp++ = c; c = GETC(); } if(c == '.') goto casedot; if(c == 'e' || c == 'E') goto casee; *cp = 0; if(sizeof(yylval.lval) == sizeof(vlong)) yylval.lval = strtoull(symb, nil, 10); else yylval.lval = strtoul(symb, nil, 10); ncu: while(c == 'U' || c == 'u' || c == 'l' || c == 'L') c = GETC(); peekc = c; return LCONST; casedot: for(;;) { if(cp >= &symb[NSYMB-1]) goto toolong; *cp++ = c; c = GETC(); if(!isdigit(c)) break; } if(c == 'e' || c == 'E') goto casee; goto caseout; casee: if(cp >= &symb[NSYMB-1]) goto toolong; *cp++ = 'e'; c = GETC(); if(c == '+' || c == '-') { if(cp >= &symb[NSYMB-1]) goto toolong; *cp++ = c; c = GETC(); } while(isdigit(c)) { if(cp >= &symb[NSYMB-1]) goto toolong; *cp++ = c; c = GETC(); } caseout: *cp = 0; peekc = c; if(FPCHIP) { yylval.dval = atof(symb); return LFCONST; } yyerror("assembler cannot interpret fp constants"); yylval.lval = 1L; return LCONST; case '"': memcpy(yylval.sval, nullgen.sval, sizeof(yylval.sval)); cp = yylval.sval; c1 = 0; for(;;) { c = escchar('"'); if(c == EOF) break; if(c1 < sizeof(yylval.sval)) *cp++ = c; c1++; } if(c1 > sizeof(yylval.sval)) yyerror("string constant too long"); return LSCONST; case '\'': c = escchar('\''); if(c == EOF) c = '\''; if(escchar('\'') != EOF) yyerror("missing '"); yylval.lval = c; return LCONST; case '/': c1 = GETC(); if(c1 == '/') { for(;;) { c = GETC(); if(c == '\n') goto l1; if(c == EOF) { yyerror("eof in comment"); errorexit(); } } } if(c1 == '*') { for(;;) { c = GETC(); while(c == '*') { c = GETC(); if(c == '/') goto l0; } if(c == EOF) { yyerror("eof in comment"); errorexit(); } if(c == '\n') lineno++; } } break; default: return c; } peekc = c1; return c; toolong: yyerror("token too long: %.*s...", utfnlen(symb, cp-symb), symb); errorexit(); return -1; } int getc(void) { int c; c = peekc; if(c != IGN) { peekc = IGN; if(c == '\n') lineno++; return c; } c = GETC(); if(c == '\n') lineno++; if(c == EOF) { yyerror("End of file"); errorexit(); } return c; } int getnsc(void) { int c; for(;;) { c = getc(); if(!isspace(c) || c == '\n') return c; } } void unget(int c) { peekc = c; if(c == '\n') lineno--; } int escchar(int e) { int c, l; loop: c = getc(); if(c == '\n') { yyerror("newline in string"); return EOF; } if(c != '\\') { if(c == e) return EOF; return c; } c = getc(); if(c >= '0' && c <= '7') { l = c - '0'; c = getc(); if(c >= '0' && c <= '7') { l = l*8 + c-'0'; c = getc(); if(c >= '0' && c <= '7') { l = l*8 + c-'0'; return l; } } peekc = c; return l; } switch(c) { case '\n': goto loop; case 'n': return '\n'; case 't': return '\t'; case 'b': return '\b'; case 'r': return '\r'; case 'f': return '\f'; case 'a': return 0x07; case 'v': return 0x0b; case 'z': return 0x00; } return c; } void pinit(char *f) { int i; Sym *s; lineno = 1; newio(); newfile(f, -1); pc = 0; peekc = IGN; sym = 1; for(i=0; i<NSYM; i++) { h[i].type = 0; h[i].sym = S; } for(i=0; i<NHASH; i++) for(s = hash[i]; s != S; s = s->link) s->macro = 0; } int filbuf(void) { Io *i; loop: i = iostack; if(i == I) return EOF; if(i->f < 0) goto pop; fi.c = read(i->f, i->b, BUFSIZ) - 1; if(fi.c < 0) { close(i->f); linehist(0, 0); goto pop; } fi.p = i->b + 1; return i->b[0]; pop: iostack = i->link; i->link = iofree; iofree = i; i = iostack; if(i == I) return EOF; fi.p = i->p; fi.c = i->c; if(--fi.c < 0) goto loop; return *fi.p++; } void yyerror(char *a, ...) { char buf[200]; va_list arg; /* * hack to intercept message from yaccpar */ if(strcmp(a, "syntax error") == 0) { yyerror("syntax error, last name: %s", symb); return; } prfile(lineno); va_start(arg, a); vseprint(buf, buf+sizeof(buf), a, arg); va_end(arg); print("%s\n", buf); nerrors++; if(nerrors > 10) { print("too many errors\n"); errorexit(); } } void prfile(long l) { int i, n; Hist a[HISTSZ], *h; long d; n = 0; for(h = hist; h != H; h = h->link) { if(l < h->line) break; if(h->name) { if(h->offset == 0) { if(n >= 0 && n < HISTSZ) a[n] = *h; n++; continue; } if(n > 0 && n < HISTSZ) if(a[n-1].offset == 0) { a[n] = *h; n++; } else a[n-1] = *h; continue; } n--; if(n >= 0 && n < HISTSZ) { d = h->line - a[n].line; for(i=0; i<n; i++) a[i].line += d; } } if(n > HISTSZ) n = HISTSZ; for(i=0; i<n; i++) print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1)); } void ieeedtod(Ieee *ieee, double native) { double fr, ho, f; int exp; if(native < 0) { ieeedtod(ieee, -native); ieee->h |= 0x80000000L; return; } if(native == 0) { ieee->l = 0; ieee->h = 0; return; } fr = frexp(native, &exp); f = 2097152L; /* shouldnt use fp constants here */ fr = modf(fr*f, &ho); ieee->h = ho; ieee->h &= 0xfffffL; ieee->h |= (exp+1022L) << 20; f = 65536L; fr = modf(fr*f, &ho); ieee->l = ho; ieee->l <<= 16; ieee->l |= (long)(fr*f); }