plan9fox/sys/src/cmd/cc/lexbody
cinap_lenrek b3c3c3e63d cc: do not expand function-like macros for non-function invocations
It is a bit of a annoyance that kenc will try to expand
function like macros on any symbol with the same name
and then complain when it doesnt see the '(' in the
invocation.

test case below:

void
foo(int)
{
}

struct Bar
{
	int	baz;	/* <- should not conflict */
};

void
main(void)
{
	baz(123);
}
2021-10-12 03:06:20 +00:00

676 lines
9.1 KiB
Plaintext

/*
* 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;
if(macexpand(s, cp, sizeof(ionext->b)-1)){
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;
} else {
ionext->link = iofree;
iofree = ionext;
}
}
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);
}