diff options
Diffstat (limited to 'utils/c2l/lexbody')
| -rw-r--r-- | utils/c2l/lexbody | 650 |
1 files changed, 650 insertions, 0 deletions
diff --git a/utils/c2l/lexbody b/utils/c2l/lexbody new file mode 100644 index 00000000..ab7e2439 --- /dev/null +++ b/utils/c2l/lexbody @@ -0,0 +1,650 @@ +/* + * common code for all the assemblers + */ + +/* + * real allocs + */ +void* +alloc(long n) +{ + void *p; + + while((ulong)hunk & MAXALIGN) { + hunk++; + nhunk--; + } + while(nhunk < n) + gethunk(); + p = hunk; + nhunk -= n; + hunk += n; + return p; +} + +void* +allocn(void *p, long on, long n) +{ + void *q; + + q = (uchar*)p + on; + if(q != hunk || nhunk < n) { + while(nhunk < on+n) + gethunk(); + memmove(hunk, p, on); + p = hunk; + hunk += on; + nhunk -= on; + } + hunk += n; + nhunk -= n; + return p; +} + +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 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) +{ + + strcpy(symb, s); + return lookup(); +} + +Sym* +lookup(void) +{ + static Sym zsym; + Sym *s; + long h; + char *p; + int c, l; + + h = 0; + for(p=symb; c = *p; p++) + h = h+h+h + c; + l = (p - symb) + 1; + if(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(memcmp(s->name, symb, l) == 0) + return s; + } + s = alloc(sizeof(*s)); + *s = zsym; + s->name = alloc(l); + memmove(s->name, symb, l); + + 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: + *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); + 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; + *cp++ = c; + c = GETC(); + } + if(c == '.') + goto casedot; + if(c == 'e' || c == 'E') + goto casee; + *cp = 0; + yylval.lval = atol(symb); + + ncu: + peekc = c; + return LCONST; + + casedot: + for(;;) { + *cp++ = c; + c = GETC(); + if(!isdigit(c)) + break; + } + if(c == 'e' || c == 'E') + goto casee; + goto caseout; + + casee: + *cp++ = 'e'; + c = GETC(); + if(c == '+' || c == '-') { + *cp++ = c; + c = GETC(); + } + while(isdigit(c)) { + *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') { + lineno++; + goto l0; + } + 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; +} + +int +getc(void) +{ + int c; + + c = peekc; + if(c != IGN) { + peekc = IGN; + 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); + doprint(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); +} |
