USG_PG3/usr/source/lil/sem.c
#include "common"
test(p1, f) struct at *p1; int f; {return ((p1->flags & f) != 0); }
set(p1, f1, f2) struct at *p1; int f1, f2;
{if (f2) p1->flags =| f1;
else p1->flags =& ~f1; }
struct at *ref(p1) struct at *p1;
{if (test(p1, DEFF)) return (p1);
return (p1->value); }
struct at *reg(p1) struct at *p1;
{if (p1->type == REG) return (ref(p1));
return (NULL); }
struct at *con(p1) struct at *p1;
{int p;
return (p1->type == CON && test(p = ref(p1), DEFF) &&
p->bias == 0 ? p : NULL); }
setvb(p1, v, b) struct at *p1; int v, b;
{p1->value = v; p1->bias = b;
set(p1, DEFF, TRUE); }
define(p1, f, t, v, b) struct symbol *p1; int f, t, v, b;
{int bp;
do {
if (test(p1, DEFF) && p1 != dot)
{error("illegal redefinition of %s", sn(p1->name));
return; }
if (debug) error("%o+%o = %o+%o %s", p1->value, p1->bias,
v, b, sn(p1->name));
bp = p1->bias;
p1->flags =| f; p1->type = t;
setvb(p1, v, b);
if (p1 == dot || p1 == &symtab[bp]) break;
p1 = &symtab[bp];
} while (TRUE);
}
settoelc(p1) struct at *p1;
{if (p1) define(p1, 0, MEM, elc->value, elc->bias); }
struct symbol *localize(n, f, t, v, z) char n[]; int f, t, v, z;
{struct symbol *p;
if ((p = lookup(spsave, n)) == NULL) p = add(n, f, t, v, z);
else {p->flags =| f; p->size = z; }
return (p); }
et() {if (dot->bias != elc->bias || dot->value > elc->value)
setelc(dot->value, dot->bias);
else settoelc(dot); }
dopop(p1) struct at *p1; {
if (skip) return;
if (p1->type == IREG) p1->type = RINC;
else error("%s++ illegal", s(p1)); }
index(p1, p2) struct at *p1, *p2;
{struct at *p, *q;
if (skip) return;
if ((p = reg(p2)) && !test(p2, ATTR) &&
(p1->type == CON || p1->type == MEM))
p1->type = MIDX + p->value;
else if ((p = con(p2)) && p1->type == MEM)
{q = ref(p1);
setvb(p1, q->value + p->value * q->size, q->bias); }
else error("%s[%s] illegal", s(p1), s(p2)); }
indir(p1) struct at *p1;
{if (skip) return;
if (!test(p1, ATTR))
switch (p1->type & ~R) {
case REG:
case RDEC:
case RINC:
case MIDX:
case CON:
case MEM: p1->type =+ I; return;
case IREG: p1->type = IMIDX + (ref(p1)->value & R);
setvb(p1, 0, 0); return;
}
error("[%s] illegal", s(p1)); }
begatime(p1) struct at *p1;
{if (skip) return;
atime =+ 1;
setvb(p1, dot->value, dot->bias); }
endatime(p1, p2) struct at *p1, *p2;
{if (skip) return;
atime =- 1;
set(p2, PUBF | SKPF, FALSE);
}
endexp(p1) struct at *p1;
{struct at *p;
if (skip) return;
if (test(p1, PUBF | DCLF)) return;
p = ref(p1);
if (p1->type == CON || p1->type == MEM)
gen(p->value, p->bias);
else error("illegal constant %s", s(p1)); }
makond(p1) struct at *p1;
{setvb(p1, ref(p1)->value, 0);
p1->type = KOND; }
knot(p1, p2) struct at *p1, *p2;
{int p;
if (skip) return;
if (ref(p1)->value != NOT)
error("%s %s illegal", s(p1), s(p2));
else {
setvb(p2, ref(p2)->value ^ 1, p2->bias);
p = p2->fbran; p2->fbran = p2->tbran; p2->tbran = p; }
}
alloc(p1, p2) struct at *p1, *p2;
{struct at *p;
int v;
if (skip) return;
if (ref(p1)->value != GETS)
error("%s STRING illegal", s(p1));
else {
p = elc;
setelc(symtab[2].value, 2);
v = elc->value;
if (dostring(p2) & 0177400) gen(0, 0);
setelc(p->value, p->bias);
p2->type = CON;
setvb(p2, v, 2); }
}
unop(p1, p2) struct at *p1, *p2;
{struct at *p, *ps;
int op, v;
if (skip) return;
p = ref(p2);
set(p2, DCLF | PUBF, FALSE);
switch (op = ref(p1)->value) {
case NOP: return;
case PUSH: if (p2->type != IREG) break;
p2->type = RDEC; return;
case GETS: if (con(p2) == NULL || p->bias) break;
ps = elc;
setelc(symtab[2].value, 2);
v = elc->value;
gen(p->value, 0);
if (p->value & 0177400) gen(0, 0);
setelc(ps->value, ps->bias);
p2->type = CON;
setvb(p2, v, 2);
return;
case AND:
case MEMOP: set(p2, ATTR, FALSE);
p2->type = op == AND ? CON : MEM; return;
case REGOP: if (!test(p, DEFF) || p->bias ||
p->value < 0 || 7 < p->value) break;
set(p2, ATTR, FALSE);
p2->type = REG; return;
case WORD:
case BYTE: set(p2, ATTR, FALSE);
set(p2, BYTF, op == BYTE);
return;
case MINUS:
case NOT: if (con(p2))
setvb(p2, op == MINUS ? -p->value : ~p->value, 0);
else if (p2->type == KOND && op == NOT)
setvb(p2, p->value ^ 1, p2->bias);
else break;
return;
case SIZE: setvb(p2, p->size, 0);
p2->type = CON;
return;
case RTS:
case JSR: if (reg(p2) == NULL) break;
p2->type = CON;
setvb(p2, op == RTS ? 000200 + p->value
: 004037 + (p->value << 6), 0);
return;
case SYS: if (con(p2) == NULL) break;
setvb(p2, 0104400 + p->value, 0); return;
}
error("%s %s illegal", s(p1), s(p2));
}
compat(p1, p2) struct at *p1, *p2;
{return ((p1->flags & ATTR) == (p2->flags & ATTR)
|| (p1->type == REG || p1->type == CON) && !test(p1, BYTF)
|| (p2->type == REG || p2->type == CON) && !test(p2, BYTF)
?1:0); }
byte(p1, p2) struct at *p1, *p2;
{return((p1 ? test(p1, BYTF) : FALSE) ||
(p2 ? test(p2, BYTF) : FALSE)
? 0100000 : 0); }
rexp(p1) struct at *p1;
{struct at op, pr;
if (p1->type == KOND) return;
op.flags = DEFF; op.value = NE;
pr.type = CON;
pr.flags = DEFF; pr.value = pr.bias = 0;
rop(p1, &op, &pr); copy(&op); }
rop(p1, p2, p3) struct at *p1, *p2, *p3;
{struct at *pl, *pr;
int op;
if (skip) return;
pl = ref(p1);
op = ref(p2)->value;
pr = ref(p3);
p2->type = KOND;
if (atime) {
if (pl->bias != pr->bias)
{error("%s %s %s illegal at compile time",
s(p1), s(p2), s(p3));
return; }
switch (op) {
case GE: op = pl->value >= pr->value; break;
case GT: op = pl->value > pr->value; break;
case NE: op = pl->value != pr->value; break;
case EQ: op = pl->value == pr->value; break;
case LT: op = pl->value < pr->value; break;
case LE: op = pl->value <= pr->value; break;
default: error("%s %s %s illegal at compile time",
s(p1), s(p2), s(p3));
op = FALSE;
}
setvb(p2, op, 0); }
else {
if (!compat(p1, p3))
error("%s %s %s illegal", s(p1), s(p2), s(p3));
else if (con(p3) && pr->value == 0)
{if (test(p1, PUBF) && !test(p1, BCCF)) ;
else geninst(byte(p1, NULL) + 005700, NULL, p1); }
else if (con(p1) && pl->value == 0)
{geninst(byte(p3, NULL) + 005700, NULL, p3);
if (op != EQ && op != NE) setvb(p2, op ^ 1, 0); }
else geninst(byte(p1, p3) + 020000, p1, p3);
}
}