// Inferno utils/6a/lex.c // http://code.google.com/p/inferno-os/source/browse/utils/6a/lex.c // // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) // Portions Copyright © 1997-1999 Vita Nuova Limited // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) // Portions Copyright © 2004,2006 Bruce Ellis // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others // Portions Copyright © 2009 The Go Authors. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define EXTERN #include #include #include "a.h" #include "y.tab.h" enum { Plan9 = 1<<0, Unix = 1<<1, Windows = 1<<2, }; int systemtype(int sys) { #ifdef _WIN32 return sys&Windows; #else return sys&Plan9; #endif } int pathchar(void) { return '/'; } void main(int argc, char *argv[]) { char *p; int c; thechar = '6'; thestring = "amd64"; ensuresymb(NSYMB); memset(debug, 0, sizeof(debug)); cinit(); outfile = 0; setinclude("."); ARGBEGIN { default: c = ARGC(); if(c >= 0 && c < sizeof(debug)) debug[c] = 1; break; case 'o': outfile = ARGF(); break; case 'D': p = ARGF(); if(p) { if (nDlist%8 == 0) Dlist = allocn(Dlist, nDlist*sizeof(char *), 8*sizeof(char *)); Dlist[nDlist++] = p; } break; case 'I': p = ARGF(); setinclude(p); break; } ARGEND if(*argv == 0) { print("usage: %ca [-options] file.s\n", thechar); errorexit(); } if(argc > 1){ print("can't assemble multiple files\n"); errorexit(); } if(assemble(argv[0])) errorexit(); exits(0); } int assemble(char *file) { char *ofile, *p; int i, of; ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) strcpy(ofile, file); p = utfrrune(ofile, pathchar()); if(p) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; if(outfile){ p = utfrrune(outfile, '.'); if(p) if(p[1] == 's' && p[2] == 0) p[0] = 0; p = utfrune(outfile, 0); p[0] = '.'; p[1] = thechar; p[2] = 0; } else outfile = "/dev/null"; } of = create(outfile, OWRITE, 0664); if(of < 0) { yyerror("%ca: cannot create %s", thechar, outfile); errorexit(); } Binit(&obuf, of, OWRITE); pass = 1; pinit(file); Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); for(i=0; itype != LNAME) yyerror("double initialization %s", itab[i].name); s->type = itab[i].type; s->value = itab[i].value; } pathname = allocn(pathname, 0, 100); if(getwd(pathname, 99) == 0) { pathname = allocn(pathname, 100, 900); if(getwd(pathname, 999) == 0) strcpy(pathname, "/???"); } } void checkscale(int scale) { switch(scale) { case 1: case 2: case 4: case 8: return; } yyerror("scale must be 1248: %d", scale); } void syminit(Sym *s) { s->type = LNAME; s->value = 0; } void cclean(void) { Gen2 g2; g2.from = nullgen; g2.to = nullgen; outcode(AEND, &g2); Bflush(&obuf); } void zname(char *n, int t, int s) { BPUTLE2(&obuf, ANAME); /* as(2) */ BPUTC(&obuf, t); /* type */ BPUTC(&obuf, s); /* sym */ while(*n) { BPUTC(&obuf, *n); n++; } BPUTC(&obuf, 0); } void zaddr(Gen *a, int s) { int32 l; int i, t; char *n; Ieee e; t = 0; if(a->index != D_NONE || a->scale != 0) t |= T_INDEX; if(a->offset != 0) { t |= T_OFFSET; l = a->offset; if((vlong)l != a->offset) t |= T_64; } if(s != 0) t |= T_SYM; switch(a->type) { default: t |= T_TYPE; break; case D_FCONST: t |= T_FCONST; break; case D_SCONST: t |= T_SCONST; break; case D_NONE: break; } BPUTC(&obuf, t); if(t & T_INDEX) { /* implies index, scale */ BPUTC(&obuf, a->index); BPUTC(&obuf, a->scale); } if(t & T_OFFSET) { /* implies offset */ l = a->offset; BPUTLE4(&obuf, l); if(t & T_64) { l = a->offset>>32; BPUTLE4(&obuf, l); } } if(t & T_SYM) /* implies sym */ BPUTC(&obuf, s); if(t & T_FCONST) { ieeedtod(&e, a->dval); l = e.l; BPUTLE4(&obuf, l); l = e.h; BPUTLE4(&obuf, l); return; } if(t & T_SCONST) { n = a->sval; for(i=0; itype); } void outcode(int a, Gen2 *g2) { int sf, st, t; Sym *s; if(pass == 1) goto out; jackpot: sf = 0; s = g2->from.sym; while(s != S) { sf = s->sym; if(sf < 0 || sf >= NSYM) sf = 0; t = g2->from.type; if(t == D_ADDR) t = g2->from.index; if(h[sf].type == t) if(h[sf].sym == s) break; zname(s->name, t, sym); s->sym = sym; h[sym].sym = s; h[sym].type = t; sf = sym; sym++; if(sym >= NSYM) sym = 1; break; } st = 0; s = g2->to.sym; while(s != S) { st = s->sym; if(st < 0 || st >= NSYM) st = 0; t = g2->to.type; if(t == D_ADDR) t = g2->to.index; if(h[st].type == t) if(h[st].sym == s) break; zname(s->name, t, sym); s->sym = sym; h[sym].sym = s; h[sym].type = t; st = sym; sym++; if(sym >= NSYM) sym = 1; if(st == sf) goto jackpot; break; } BPUTLE2(&obuf, a); BPUTLE4(&obuf, stmtline); zaddr(&g2->from, sf); zaddr(&g2->to, st); out: if(a != AGLOBL && a != ADATA) pc++; } void outhist(void) { Gen g; Hist *h; char *p, *q, *op, c; int n; char *tofree; static int first = 1; static char *goroot, *goroot_final; if(first) { // Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL. first = 0; goroot = getenv("GOROOT"); goroot_final = getenv("GOROOT_FINAL"); if(goroot == nil) goroot = ""; if(goroot_final == nil) goroot_final = goroot; if(strcmp(goroot, goroot_final) == 0) { goroot = nil; goroot_final = nil; } } tofree = nil; g = nullgen; c = pathchar(); for(h = hist; h != H; h = h->link) { p = h->name; if(p != nil && goroot != nil) { n = strlen(goroot); if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') { tofree = smprint("%s%s", goroot_final, p+n); p = tofree; } } op = 0; if(systemtype(Windows) && p && p[1] == ':'){ c = p[2]; } else if(p && p[0] != c && h->offset == 0 && pathname){ if(systemtype(Windows) && pathname[1] == ':') { op = p; p = pathname; c = p[2]; } else if(pathname[0] == c){ op = p; p = pathname; } } while(p) { q = strchr(p, c); if(q) { n = q-p; if(n == 0){ n = 1; /* leading "/" */ *p = '/'; /* don't emit "\" on windows */ } q++; } else { n = strlen(p); q = 0; } if(n) { BPUTLE2(&obuf, ANAME); BPUTC(&obuf, D_FILE); /* type */ BPUTC(&obuf, 1); /* sym */ BPUTC(&obuf, '<'); Bwrite(&obuf, p, n); BPUTC(&obuf, 0); } p = q; if(p == 0 && op) { p = op; op = 0; } } g.offset = h->offset; BPUTLE2(&obuf, AHISTORY); BPUTLE4(&obuf, h->line); zaddr(&nullgen, 0); zaddr(&g, 0); if(tofree) { free(tofree); tofree = nil; } } } #include "../cc/lexbody" #include "../cc/macbody"