USG_PG3/usr/source/lil/put.c
#include "common"
#define OSIZE 256
#define GEN 0
#define BRAN 1
#define JUMP 2
#define LOAD 3
#define RFLAG 4
select(f) int f;
{if (fout != f) {flush(); fout = f; } }
char *mako(i) int i;
{int j, k;
static char buf[8];
j = k = 0;
if (i < 0)
{buf[k++] = '1';
i =& 077777; }
else for ( ; j < 4; j++)
{if ((i >> 12) & 7) break;
i =<< 3; }
for ( ; j < 5; j++)
{buf[k++] = (i >> 12) & 7 | '0';
i =<< 3; }
buf[k] = '\0';
return(buf); }
puto(i) int i;
{printf(" %s", mako(i)); }
int wdot 0; /* working dot for pipe */
int wbias 1; /* working dot bias for pipe */
int welcs[3] {0, 0, 0}; /* working elc's for pipe */
struct {int o, v, b; }
out[OSIZE]; /* the output pipe */
int hiwater 0; /* high water mark in pipe */
int nout 0; /* no. of words in pipe */
int osize OSIZE; /* working size of pipe */
int shorter 0; /* no. of jumps made shorter */
int longer 0; /* no. of jumps left longer */
putovb(o, v, b) int o, v, b;
{write(fcode, &o, 2);
write(fcode, &v, 2);
write(fcode, &b, 2); }
pipe(o, v, b) int o, v, b;
{int drain, i, j, k;
extern struct token stack[];
extern int sthigh;
extern int stackoff;
if (o == -1) drain = TRUE;
else {
drain = FALSE;
out[nout].o = o;
out[nout].v = v;
out[nout].b = b;
if (debug)
{puto(o); puto(v); puto(b);
putchar('\n'); }
nout++; }
for (i = 0; i < nout; i++)
{o = out[i].o;
b = out[i].b;
if (b > 2 && test(&symtab[b], DEFF))
{v = symtab[b].value;
b = symtab[b].bias; }
else v = out[i].v;
if ((o & 3) != JUMP) switch (o & 3) {
case GEN:
case BRAN: putovb(o, out[i].v, out[i].b);
wdot =+ 2; break;
case LOAD: putovb(o, v, b);
welcs[wbias] = wdot;
wdot = v; wbias = b; break; }
else if (b > 2 && nout < osize && !drain) break;
else if (b > 2 || b != wbias ||
(v - wdot) < -254 || 256 < (v - wdot) || drain)
{putovb(o, out[i].v, out[i].b);
wdot =+ (o >> 8) == TRUE ? 4 : 6;
longer++; }
else {
putovb(o & ~3 | BRAN, out[i].v, out[i].b);
wdot =+ 2;
k = (o >> 8) == TRUE ? 2 : 4;
if (i + 1 >= nout) elc->value =- k;
else {
shorter++;
for (j = i + 1; j < nout; j++)
if (out[j].b == wbias &&
out[j].v >= wdot) out[j].v =- k;
for (j = dot - symtab; j < spused; j++)
if (symtab[j].bias == wbias &&
symtab[j].value >= wdot)
symtab[j].value =- k;
for (j = 0; j <= sthigh; j++)
if (stack[j].sbias == wbias &&
stack[j].start >= wdot)
stack[j].start =- k;
}
}
}
if (i)
{if (i > hiwater && i < nout) hiwater = i;
for (j = i; j < nout; j++)
{out[j - i].o = out[j].o;
out[j - i].v = out[j].v;
out[j - i].b = out[j].b; }
nout =- i;
}
if (drain)
{welcs[wbias] = wdot;
if (stackoff)
error("stack offset %o", stackoff);
}
}
gen(v, b) int v, b;
{if (elc->bias != 1 && elc->bias != 2 || elc->value & 1)
{error("bad . %o+%o", elc->value, elc->bias);
setelc(&symtab[1].value, 1);
if (elc->value & 1) elc->value++; }
settoelc(tlist); tlist = NULL;
elc->value =+ 2;
pipe(GEN, v, b); }
int errors FALSE; /* TRUE if any errors */
error(f, s1, s2, s3, s4, s5) char *f, *s1, *s2, *s3, *s4, *s5;
{errors = TRUE;
select(1);
printf("%d: ", line);
printf(f, s1, s2, s3, s4, s5);
putchar('\n'); }
char sbuf[128]; /* holds diagnostic strings */
char *sp sbuf; /* -> current 32-byte buffer */
char *sterm[] {"EOF", "??", "error", "DECL", ",", "(", ")", "\"", ";", "[",
"]", "++", "OP", "&&", "||", "ROP", "STRING",
"IDENT", "GOTO", "IF", "ELSE", "DO", "BREAK", "WHILE",
"CONDITION", "LABEL" };
char *pre[] {"reg ", "--[", "[", "&", "mem ", "", "[reg ",
"[--[", "[[", "[&", "[mem ", "[" };
char *post[] {"", "]", "]++", "", "", "]", "]",
"]]", "]++]", "]", "]", "]]" };
char *scopy(s1, s2) char *s1, *s2;
{while (*s1) *s2++ = *s1++;
return (s2); }
char *s(p1) struct at *p1;
{int t;
t = p1->type;
if (t < REG) return (test(p1, DEFF) || p1->value == NULL ?
sterm[t] :
sn((p1->value)->name));
t = (t - REG) >> 3;
sp = scopy(pre[t], sp);
if (!test(p1, DEFF)) sp = scopy(sn((p1->value)->name), sp);
else {
if (p1->value || !p1->bias) sp = scopy(mako(p1->value), sp);
if (p1->value && p1->bias) *sp++ = '+';
if (p1->bias) sp = scopy(sn(symtab[p1->bias].name), sp);
}
if ((p1->type & ~R) == MIDX || (p1->type & ~R) == IMIDX)
{*sp++ = '['; *sp++ = 'r';
*sp++ = (p1->type & R) + '0'; }
sp = scopy(post[t], sp);
*sp = '\0';
t = sp - sbuf;
sp = &sbuf[((t + 32) & ~31) % 128];
return (&sbuf[t & ~31]); }
int stackoff 0; /* stack offset during calls */
int nargs; /* no. of arg words in instruction */
int argb[2]; /* offset for stack references */
int argf[2]; /* TRUE if arg is self-relative */
struct at *argp[2]; /* -> stack entry for arg */
doloc(p1) struct at *p1;
{struct at *p;
int c, r, v;
c = p1->type & ~R;
r = p1->type & R;
v = (p = ref(p1))->value;
switch (c) {
case REG: break;
case IREG: v =+ 010; break;
case RINC: v =+ 020; break;
case IRINC: v =+ 030; break;
case RDEC: v =+ 040; break;
case IRDEC: v =+ 050; break;
default: argb[nargs] = 0;
argf[nargs] = FALSE;
argp[nargs] = p;
switch (c) {
case MIDX: if (test(p, DEFF) && v == 0 && p->bias == 0 &&
(stackoff == 0 || r != 6))
return (010 + r);
v = 060 + r; break;
case IMIDX: v = 070 + r; break;
case CON: v = 027; break;
case ICON: v = 037; break;
case MEM: v = 067; argf[nargs] = TRUE; break;
case IMEM: v = 077; argf[nargs] = TRUE; break;
default: v = -1;
}
if ((v & 067) == 066)
argb[nargs] = stackoff;
nargs++;
}
return (v); }
geninst(i, ps, pd) int i; struct at *ps, *pd;
{int j;
nargs = 0;
j = ps ? doloc(ps) << 6 : 0;
if (pd) j =| doloc(pd);
if (j < 0) error ("illegal operand in %s op %s",
s(ps), s(pd));
else {
gen(i | j, 0);
for (j = 0; j < nargs; j++) {
elc->value =+ 2;
pipe(GEN + (argf[j] ? RFLAG : 0),
argb[j] + argp[j]->value,
argp[j]->bias);
}
}
}
target(pp1) struct at **pp1;
{
struct at *linkup();
if (*pp1 == NULL) return;
tlist = linkup(tlist, *pp1);
*pp1 = NULL; }
struct at *fjump(k, p1, p2) int k; struct at *p1, *p2;
{char crname[10];
p1 = linkup(p1, p2);
if (k == FALSE) return (p1);
if (p1 == NULL)
{*scopy(mako(spused), scopy("..", crname))
= '\0';
p1 = add(crname, CRSF, MEM, 0, 0); }
jump(k, p1->value, p1->bias);
return (p1); }
struct at *linkup(p1, p2) struct symbol *p1, *p2;
{struct symbol *p;
if (p1 == NULL) {p1 = p2; p2 = NULL; }
if (p2 == NULL) return (p1);
if (test(p2, DEFF)) {p = p1; p1 = p2; p2 = p; }
if (test(p1, DEFF)) define(p2, 0, MEM, p1->value, p1->bias);
else {
for (p = p1; p != &symtab[p->bias]; p = &symtab[p->bias]) ;
p->bias = p2 - symtab; }
return (p1); }
jump(k, v, b) int k, v, b;
{int i;
if (k == FALSE) return;
if (tlist && k == TRUE)
{if (!test(&symtab[b], DEFF)) linkup(&symtab[b], tlist);
else define(tlist, 0, MEM, v, b); }
else settoelc(tlist);
tlist = NULL;
elc->value =+ (k == TRUE) ? 4 : 6;
pipe(JUMP | (k << 8), v, b);
}
setelc(v, b) int v, b;
{if (b != elc->bias || v > elc->value)
{if (v & 1) v++;
settoelc(tlist); tlist = NULL;
elc = &symtab[b];
elc->value = v;
if (b == 1 || b == 2) pipe(LOAD, v, b);
}
else if (v < elc->value) error("can't back up . to %o+%o", v, b); }