summaryrefslogtreecommitdiff
path: root/src/cmd/cc/lexbody
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/cc/lexbody')
-rw-r--r--src/cmd/cc/lexbody769
1 files changed, 769 insertions, 0 deletions
diff --git a/src/cmd/cc/lexbody b/src/cmd/cc/lexbody
new file mode 100644
index 000000000..f4cc19c2e
--- /dev/null
+++ b/src/cmd/cc/lexbody
@@ -0,0 +1,769 @@
+// Inferno utils/cc/lexbody
+// http://code.google.com/p/inferno-os/source/browse/utils/cc/lexbody
+//
+// 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.
+
+/*
+ * common code for all the assemblers
+ */
+
+void
+pragpack(void)
+{
+ while(getnsc() != '\n')
+ ;
+}
+
+void
+pragvararg(void)
+{
+ while(getnsc() != '\n')
+ ;
+}
+
+void
+pragdynimport(void)
+{
+ while(getnsc() != '\n')
+ ;
+}
+
+void
+pragdynexport(void)
+{
+ while(getnsc() != '\n')
+ ;
+}
+
+void
+pragfpround(void)
+{
+ while(getnsc() != '\n')
+ ;
+}
+
+void
+pragtextflag(void)
+{
+ while(getnsc() != '\n')
+ ;
+}
+
+void
+pragprofile(void)
+{
+ while(getnsc() != '\n')
+ ;
+}
+
+void
+pragincomplete(void)
+{
+ while(getnsc() != '\n')
+ ;
+}
+
+void*
+alloc(int32 n)
+{
+ void *p;
+
+ p = malloc(n);
+ if(p == nil) {
+ print("alloc out of mem\n");
+ exits("alloc: out of mem");
+ }
+ memset(p, 0, n);
+ return p;
+}
+
+void*
+allocn(void *p, int32 n, int32 d)
+{
+ if(p == nil)
+ return alloc(n+d);
+ p = realloc(p, n+d);
+ if(p == nil) {
+ print("allocn out of mem\n");
+ exits("allocn: out of mem");
+ }
+ if(d > 0)
+ memset((char*)p+n, 0, d);
+ return p;
+}
+
+void
+ensuresymb(int32 n)
+{
+ if(symb == nil) {
+ symb = alloc(NSYMB+1);
+ nsymb = NSYMB;
+ }
+
+ if(n > nsymb) {
+ symb = allocn(symb, nsymb, n+1-nsymb);
+ nsymb = 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%8 == 0)
+ include = allocn(include, ninclude*sizeof(char *),
+ 8*sizeof(char *));
+ 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)
+{
+ ensuresymb(strlen(s));
+ strcpy(symb, s);
+ return lookup();
+}
+
+Sym*
+lookup(void)
+{
+ Sym *s;
+ int32 h;
+ char *p;
+ int c, l;
+ char *r, *w;
+
+ if((uchar)symb[0] == 0xc2 && (uchar)symb[1] == 0xb7) {
+ // turn leading · into ""·
+ h = strlen(symb);
+ ensuresymb(h+2);
+ memmove(symb+2, symb, h+1);
+ symb[0] = '"';
+ symb[1] = '"';
+ }
+
+ // turn · into .
+ for(r=w=symb; *r; r++) {
+ if((uchar)*r == 0xc2 && (uchar)*(r+1) == 0xb7) {
+ *w++ = '.';
+ r++;
+ }else
+ *w++ = *r;
+ }
+ *w = '\0';
+
+ h = 0;
+ for(p=symb; c = *p; p++)
+ h = h+h+h + c;
+ l = (p - symb) + 1;
+ h &= 0xffffff;
+ 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->name = alloc(l);
+ memmove(s->name, symb, l);
+
+ s->link = hash[h];
+ hash[h] = s;
+ syminit(s);
+ return s;
+}
+
+int
+ISALPHA(int c)
+{
+ if(isalpha(c))
+ return 1;
+ if(c >= Runeself)
+ return 1;
+ return 0;
+}
+
+int32
+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;
+ if(sizeof(yylval.lval) == sizeof(vlong))
+ yylval.lval = strtoll(symb, nil, 10);
+ else
+ yylval.lval = strtol(symb, nil, 10);
+
+ ncu:
+ while(c == 'U' || c == 'u' || c == 'l' || c == 'L')
+ c = GETC();
+ 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')
+ 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;
+}
+
+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);
+ 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(int32 l)
+{
+ int i, n;
+ Hist a[HISTSZ], *h;
+ int32 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 |= (int32)(fr*f);
+}