Commit 184eb0ac authored by Russ Cox's avatar Russ Cox

cmd/cc: delete lexbody, macbody

These files were left behind for the C implementation of the assemblers.
They're no longer needed.

This is the last of the cmd/cc directory.

Change-Id: I9231b23c27fead5695000097aeb694824747677d
Reviewed-on: https://go-review.googlesource.com/6367Reviewed-by: default avatarMinux Ma <minux@golang.org>
parent 3317e7f1
// 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
pragcgo(char *name)
{
USED(name);
while(getnsc() != '\n')
;
}
void
pragfpround(void)
{
while(getnsc() != '\n')
;
}
void
pragtextflag(void)
{
while(getnsc() != '\n')
;
}
void
pragdataflag(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)
{
Bflush(&bstdout);
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;
linklinehist(ctxt, lineno, s, 0);
}
Sym*
slookup(char *s)
{
ensuresymb(strlen(s));
strcpy(symb, s);
return lookup();
}
LSym *thetext;
void
settext(LSym *s)
{
thetext = s;
}
Sym*
labellookup(Sym *s)
{
char *p;
Sym *lab;
if(thetext == nil) {
s->labelname = s->name;
return s;
}
p = smprint("%s.%s", thetext->name, s->name);
lab = slookup(p);
free(p);
lab->labelname = s->name;
return lab;
}
Sym*
lookup(void)
{
Sym *s;
uint32 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] = '"';
}
for(r=w=symb; *r; r++) {
// turn · (U+00B7) into .
// turn ∕ (U+2215) into /
if((uchar)*r == 0xc2 && (uchar)*(r+1) == 0xb7) {
*w++ = '.';
r++;
}else if((uchar)*r == 0xe2 && (uchar)*(r+1) == 0x88 && (uchar)*(r+2) == 0x95) {
*w++ = '/';
r++;
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(strcmp(s->name, symb) == 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 = (uvlong)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 = (uvlong)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.u.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;
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;
}
}
unget(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<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);
linklinehist(ctxt, lineno, 0, 0);
goto pop;
}
fi.p = i->b + 1;
return i->b[0] & 0xff;
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++ & 0xff;
}
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)
{
linkprfile(ctxt, l);
}
// Inferno utils/cc/macbody
// http://code.google.com/p/inferno-os/source/browse/utils/cc/macbody
//
// 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 VARMAC 0x80
int32
getnsn(void)
{
int32 n;
int c;
c = getnsc();
if(c < '0' || c > '9')
return -1;
n = 0;
while(c >= '0' && c <= '9') {
n = n*10 + c-'0';
c = getc();
}
unget(c);
return n;
}
Sym*
getsym(void)
{
int c;
char *cp;
c = getnsc();
if(!isalpha(c) && c != '_' && c < 0x80) {
unget(c);
return S;
}
for(cp = symb;;) {
if(cp <= symb+NSYMB-4)
*cp++ = c;
c = getc();
if(isalnum(c) || c == '_' || c >= 0x80)
continue;
unget(c);
break;
}
*cp = 0;
if(cp > symb+NSYMB-4)
yyerror("symbol too large: %s", symb);
return lookup();
}
Sym*
getsymdots(int *dots)
{
int c;
Sym *s;
s = getsym();
if(s != S)
return s;
c = getnsc();
if(c != '.'){
unget(c);
return S;
}
if(getc() != '.' || getc() != '.')
yyerror("bad dots in macro");
*dots = 1;
return slookup("__VA_ARGS__");
}
int
getcom(void)
{
int c;
for(;;) {
c = getnsc();
if(c != '/')
break;
c = getc();
if(c == '/') {
while(c != '\n')
c = getc();
break;
}
if(c != '*')
break;
c = getc();
for(;;) {
if(c == '*') {
c = getc();
if(c != '/')
continue;
c = getc();
break;
}
if(c == '\n') {
yyerror("comment across newline");
break;
}
c = getc();
}
if(c == '\n')
break;
}
return c;
}
void
dodefine(char *cp)
{
Sym *s;
char *p;
int32 l;
ensuresymb(strlen(cp));
strcpy(symb, cp);
p = strchr(symb, '=');
if(p) {
*p++ = 0;
s = lookup();
l = strlen(p) + 2; /* +1 null, +1 nargs */
s->macro = alloc(l);
strcpy(s->macro+1, p);
} else {
s = lookup();
s->macro = "\0001"; /* \000 is nargs */
}
if(debug['m'])
print("#define (-D) %s %s\n", s->name, s->macro+1);
}
struct
{
char *macname;
void (*macf)(void);
} mactab[] =
{
"ifdef", 0, /* macif(0) */
"ifndef", 0, /* macif(1) */
"else", 0, /* macif(2) */
"line", maclin,
"define", macdef,
"include", macinc,
"undef", macund,
"pragma", macprag,
"endif", macend,
0
};
void
domacro(void)
{
int i;
Sym *s;
s = getsym();
if(s == S)
s = slookup("endif");
for(i=0; mactab[i].macname; i++)
if(strcmp(s->name, mactab[i].macname) == 0) {
if(mactab[i].macf)
(*mactab[i].macf)();
else
macif(i);
return;
}
yyerror("unknown #: %s", s->name);
macend();
}
void
macund(void)
{
Sym *s;
s = getsym();
macend();
if(s == S) {
yyerror("syntax in #undef");
return;
}
s->macro = 0;
}
#define NARG 25
void
macdef(void)
{
Sym *s, *a;
char *args[NARG], *np, *base;
int n, i, c, len, dots;
int ischr;
s = getsym();
if(s == S)
goto bad;
if(s->macro)
yyerror("macro redefined: %s", s->name);
c = getc();
n = -1;
dots = 0;
if(c == '(') {
n++;
c = getnsc();
if(c != ')') {
unget(c);
for(;;) {
a = getsymdots(&dots);
if(a == S)
goto bad;
if(n >= NARG) {
yyerror("too many arguments in #define: %s", s->name);
goto bad;
}
args[n++] = a->name;
c = getnsc();
if(c == ')')
break;
if(c != ',' || dots)
goto bad;
}
}
c = getc();
}
if(isspace(c))
if(c != '\n')
c = getnsc();
base = hunk;
len = 1;
ischr = 0;
for(;;) {
if(isalpha(c) || c == '_') {
np = symb;
*np++ = c;
c = getc();
while(isalnum(c) || c == '_') {
*np++ = c;
c = getc();
}
*np = 0;
for(i=0; i<n; i++)
if(strcmp(symb, args[i]) == 0)
break;
if(i >= n) {
i = strlen(symb);
base = allocn(base, len, i);
memcpy(base+len, symb, i);
len += i;
continue;
}
base = allocn(base, len, 2);
base[len++] = '#';
base[len++] = 'a' + i;
continue;
}
if(ischr){
if(c == '\\'){
base = allocn(base, len, 1);
base[len++] = c;
c = getc();
}else if(c == ischr)
ischr = 0;
}else{
if(c == '"' || c == '\''){
base = allocn(base, len, 1);
base[len++] = c;
ischr = c;
c = getc();
continue;
}
if(c == '/') {
c = getc();
if(c == '/'){
c = getc();
for(;;) {
if(c == '\n')
break;
c = getc();
}
continue;
}
if(c == '*'){
c = getc();
for(;;) {
if(c == '*') {
c = getc();
if(c != '/')
continue;
c = getc();
break;
}
if(c == '\n') {
yyerror("comment and newline in define: %s", s->name);
break;
}
c = getc();
}
continue;
}
base = allocn(base, len, 1);
base[len++] = '/';
continue;
}
}
if(c == '\\') {
c = getc();
if(c == '\n') {
c = getc();
continue;
}
else if(c == '\r') {
c = getc();
if(c == '\n') {
c = getc();
continue;
}
}
base = allocn(base, len, 1);
base[len++] = '\\';
continue;
}
if(c == '\n')
break;
if(c == '#')
if(n > 0) {
base = allocn(base, len, 1);
base[len++] = c;
}
base = allocn(base, len, 1);
base[len++] = c;
c = ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff));
if(c == '\n')
lineno++;
if(c == -1) {
yyerror("eof in a macro: %s", s->name);
break;
}
}
do {
base = allocn(base, len, 1);
base[len++] = 0;
} while(len & 3);
*base = n+1;
if(dots)
*base |= VARMAC;
s->macro = base;
if(debug['m'])
print("#define %s %s\n", s->name, s->macro+1);
return;
bad:
if(s == S)
yyerror("syntax in #define");
else
yyerror("syntax in #define: %s", s->name);
macend();
}
void
macexpand(Sym *s, char *b)
{
char buf[2000];
int n, l, c, nargs;
char *arg[NARG], *cp, *ob, *ecp, dots;
ob = b;
if(*s->macro == 0) {
strcpy(b, s->macro+1);
if(debug['m'])
print("#expand %s %s\n", s->name, ob);
return;
}
nargs = (char)(*s->macro & ~VARMAC) - 1;
dots = *s->macro & VARMAC;
c = getnsc();
if(c != '(')
goto bad;
n = 0;
c = getc();
if(c != ')') {
unget(c);
l = 0;
cp = buf;
ecp = cp + sizeof(buf)-4;
arg[n++] = cp;
for(;;) {
if(cp >= ecp)
goto toobig;
c = getc();
if(c == '"')
for(;;) {
if(cp >= ecp)
goto toobig;
*cp++ = c;
c = getc();
if(c == '\\') {
*cp++ = c;
c = getc();
continue;
}
if(c == '\n')
goto bad;
if(c == '"')
break;
}
if(c == '\'')
for(;;) {
if(cp >= ecp)
goto toobig;
*cp++ = c;
c = getc();
if(c == '\\') {
*cp++ = c;
c = getc();
continue;
}
if(c == '\n')
goto bad;
if(c == '\'')
break;
}
if(c == '/') {
c = getc();
switch(c) {
case '*':
for(;;) {
c = getc();
if(c == '*') {
c = getc();
if(c == '/')
break;
}
}
*cp++ = ' ';
continue;
case '/':
while((c = getc()) != '\n')
;
break;
default:
unget(c);
c = '/';
}
}
if(l == 0) {
if(c == ',') {
if(n == nargs && dots) {
*cp++ = ',';
continue;
}
*cp++ = 0;
arg[n++] = cp;
if(n > nargs)
break;
continue;
}
if(c == ')')
break;
}
if(c == '\n')
c = ' ';
*cp++ = c;
if(c == '(')
l++;
if(c == ')')
l--;
}
*cp = 0;
}
if(n != nargs) {
yyerror("argument mismatch expanding: %s", s->name);
*b = 0;
return;
}
cp = s->macro+1;
for(;;) {
c = *cp++;
if(c == '\n')
c = ' ';
if(c != '#') {
*b++ = c;
if(c == 0)
break;
continue;
}
c = *cp++;
if(c == 0)
goto bad;
if(c == '#') {
*b++ = c;
continue;
}
c -= 'a';
if(c < 0 || c >= n)
continue;
strcpy(b, arg[c]);
b += strlen(arg[c]);
}
*b = 0;
if(debug['m'])
print("#expand %s %s\n", s->name, ob);
return;
bad:
yyerror("syntax in macro expansion: %s", s->name);
*b = 0;
return;
toobig:
yyerror("too much text in macro expansion: %s", s->name);
*b = 0;
}
void
macinc(void)
{
int c0, c, i, f;
char str[STRINGSZ], *hp;
c0 = getnsc();
if(c0 != '"') {
c = c0;
if(c0 != '<')
goto bad;
c0 = '>';
}
for(hp = str;;) {
c = getc();
if(c == c0)
break;
if(c == '\n')
goto bad;
*hp++ = c;
}
*hp = 0;
c = getcom();
if(c != '\n')
goto bad;
f = -1;
for(i=0; i<ninclude; i++) {
if(i == 0 && c0 == '>')
continue;
ensuresymb(strlen(include[i])+strlen(str)+2);
strcpy(symb, include[i]);
strcat(symb, "/");
if(strcmp(symb, "./") == 0)
symb[0] = 0;
strcat(symb, str);
f = open(symb, OREAD);
if(f >= 0)
break;
}
if(f < 0)
strcpy(symb, str);
c = strlen(symb) + 1;
hp = alloc(c);
memcpy(hp, symb, c);
newio();
pushio();
newfile(hp, f);
return;
bad:
unget(c);
yyerror("syntax in #include");
macend();
}
void
maclin(void)
{
char *cp;
int c;
int32 n;
n = getnsn();
c = getc();
if(n < 0)
goto bad;
for(;;) {
if(c == ' ' || c == '\t') {
c = getc();
continue;
}
if(c == '"')
break;
if(c == '\n') {
strcpy(symb, "<noname>");
goto nn;
}
goto bad;
}
cp = symb;
for(;;) {
c = getc();
if(c == '"')
break;
*cp++ = c;
}
*cp = 0;
c = getcom();
if(c != '\n')
goto bad;
nn:
c = strlen(symb) + 1;
cp = alloc(c);
memcpy(cp, symb, c);
linklinehist(ctxt, lineno, cp, n);
return;
bad:
unget(c);
yyerror("syntax in #line");
macend();
}
void
macif(int f)
{
int c, l, bol;
Sym *s;
if(f == 2)
goto skip;
s = getsym();
if(s == S)
goto bad;
if(getcom() != '\n')
goto bad;
if((s->macro != 0) ^ f)
return;
skip:
bol = 1;
l = 0;
for(;;) {
c = getc();
if(c != '#') {
if(!isspace(c))
bol = 0;
if(c == '\n')
bol = 1;
continue;
}
if(!bol)
continue;
s = getsym();
if(s == S)
continue;
if(strcmp(s->name, "endif") == 0) {
if(l) {
l--;
continue;
}
macend();
return;
}
if(strcmp(s->name, "ifdef") == 0 || strcmp(s->name, "ifndef") == 0) {
l++;
continue;
}
if(l == 0 && f != 2 && strcmp(s->name, "else") == 0) {
macend();
return;
}
}
bad:
yyerror("syntax in #if(n)def");
macend();
}
void
macprag(void)
{
Sym *s;
int c0, c;
char *hp;
s = getsym();
if(s && strcmp(s->name, "lib") == 0)
goto praglib;
if(s && strcmp(s->name, "pack") == 0) {
pragpack();
return;
}
if(s && strcmp(s->name, "fpround") == 0) {
pragfpround();
return;
}
if(s && strcmp(s->name, "textflag") == 0) {
pragtextflag();
return;
}
if(s && strcmp(s->name, "dataflag") == 0) {
pragdataflag();
return;
}
if(s && strcmp(s->name, "varargck") == 0) {
pragvararg();
return;
}
if(s && strcmp(s->name, "incomplete") == 0) {
pragincomplete();
return;
}
if(s && (strncmp(s->name, "cgo_", 4) == 0 || strncmp(s->name, "dyn", 3) == 0)) {
pragcgo(s->name);
return;
}
while(getnsc() != '\n')
;
return;
praglib:
c0 = getnsc();
if(c0 != '"') {
c = c0;
if(c0 != '<')
goto bad;
c0 = '>';
}
for(hp = symb;;) {
c = getc();
if(c == c0)
break;
if(c == '\n')
goto bad;
*hp++ = c;
}
*hp = 0;
c = getcom();
if(c != '\n')
goto bad;
/*
* put pragma-line in as a funny history
*/
c = strlen(symb) + 1;
hp = alloc(c);
memcpy(hp, symb, c);
linklinehist(ctxt, lineno, hp, -1);
return;
bad:
unget(c);
yyerror("syntax in #pragma lib");
macend();
}
void
macend(void)
{
int c;
for(;;) {
c = getnsc();
if(c < 0 || c == '\n')
return;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment