470 lines
7.0 KiB
C
470 lines
7.0 KiB
C
/*
|
|
|
|
C compiler, part 2
|
|
|
|
Copyright 1972 Bell Telephone Laboratories, Inc.
|
|
|
|
*/
|
|
|
|
ospace() {} /* fake */
|
|
|
|
waste() /* waste space */
|
|
{
|
|
waste(waste(waste),waste(waste),waste(waste));
|
|
waste(waste(waste),waste(waste),waste(waste));
|
|
waste(waste(waste),waste(waste),waste(waste));
|
|
waste(waste(waste),waste(waste),waste(waste));
|
|
waste(waste(waste),waste(waste),waste(waste));
|
|
waste(waste(waste),waste(waste),waste(waste));
|
|
waste(waste(waste),waste(waste),waste(waste));
|
|
waste(waste(waste),waste(waste),waste(waste));
|
|
}
|
|
main(argc, argv)
|
|
char argv[][];
|
|
{
|
|
extern fout, fin, nerror, line;
|
|
extern getwrd, rcexpr, ospace, tmpfil;
|
|
extern cctab[], regtab[], efftab[], sptab[];
|
|
int sp[], c, table[], tabtab[3][], tree;
|
|
|
|
if (argc<4) {
|
|
error("Arg count");
|
|
exit(1);
|
|
}
|
|
if((fin=open(argv[1],0))<0) {
|
|
error("Cant't find %s", argv[1]);
|
|
exit(1);
|
|
}
|
|
if((fout=creat(argv[3],017))<0) {
|
|
error("Can't create %s", argv[3]);
|
|
exit(1);
|
|
}
|
|
tmpfil = argv[2];
|
|
|
|
tabtab[0] = regtab;
|
|
tabtab[1] = efftab;
|
|
tabtab[2] = cctab;
|
|
tabtab[3] = sptab;
|
|
while(c=getchar()) {
|
|
if(c=='#') {
|
|
sp = ospace;
|
|
c = getwrd();
|
|
tree = getwrd();
|
|
table = tabtab[getwrd()];
|
|
line = getwrd();
|
|
while(c--)
|
|
*sp++ = getwrd();
|
|
rcexpr(tree, table, 0);
|
|
} else
|
|
putchar(c);
|
|
}
|
|
flush();
|
|
exit(nerror!=0);
|
|
}
|
|
|
|
match(tree, table, nreg)
|
|
int tree[], table[]; {
|
|
extern opdope[], dcalc, notcompat;
|
|
int op, d1, d2, t1, t2, p1[], p2[];
|
|
char mp[];
|
|
|
|
if (tree==0)
|
|
return(0);
|
|
op = *tree;
|
|
if (op>=29) /* if not leaf */
|
|
p1 = tree[3];
|
|
else
|
|
p1 = tree;
|
|
t1 = p1[1];
|
|
d1 = dcalc(p1, nreg);
|
|
if ((opdope[op]&01)!=0) { /* binary? */
|
|
p2 = tree[4];
|
|
t2 = p2[1];
|
|
d2 = dcalc(p2, nreg);
|
|
}
|
|
while(*table) {
|
|
if (*table++ == op) goto foundop;
|
|
table++;
|
|
}
|
|
return(0);
|
|
foundop:
|
|
table = *table;
|
|
nxtry:
|
|
mp = table;
|
|
if (*mp == 0)
|
|
return(0);
|
|
if (d1 > (*mp&077) | (*mp>=0100)&(*p1!=36))
|
|
goto notyet;
|
|
if (notcompat(t1, mp[1]))
|
|
goto notyet;
|
|
if ((opdope[op]&01)!=0 & p2!=0) {
|
|
if (d2 > (mp[2]&077) | (mp[2]>=0100)&(*p2!=36))
|
|
goto notyet;
|
|
if (notcompat(t2,mp[3]))
|
|
goto notyet;
|
|
}
|
|
now:
|
|
return(table[2]);
|
|
notyet:
|
|
table = table+3;
|
|
goto nxtry;
|
|
}
|
|
|
|
rcexpr(tree, table, reg)
|
|
int tree[]; {
|
|
extern cexpr, regtab, cctab, sptab, printf, error;
|
|
extern jumpc, cbranch;
|
|
|
|
if(tree==0)
|
|
return;
|
|
if(*tree >= 103) {
|
|
(*tree==103?jumpc:cbranch)(tree[1],tree[2],tree[3],0);
|
|
return;
|
|
}
|
|
if (cexpr(tree, table, reg))
|
|
return;
|
|
if (table!=regtab)
|
|
if(cexpr(tree, regtab, reg)) {
|
|
if (table==sptab)
|
|
printf("mov r%d,-(sp)\n", reg);
|
|
if (table==cctab)
|
|
printf("tst r%d\n", reg);
|
|
return;
|
|
}
|
|
error("No match for op %d", *tree);
|
|
}
|
|
|
|
cexpr(tree, table, reg)
|
|
int tree[][], table[]; {
|
|
extern match, nreg, printf, pname, putchar, regtab;
|
|
extern sptab, cctab, rcexpr, prins, rlength, popstk;
|
|
extern collcon, isn, label, branch, cbranch, fltmod;
|
|
int p1[], p2[], c, r, p[], otable[], ctable[], regtab[], cctab[];
|
|
char string[], match[];
|
|
|
|
if ((c = *tree)==100) { /* call */
|
|
p1 = tree[3];
|
|
p2 = tree[4];
|
|
r = 0;
|
|
if(p2) {
|
|
while (*p2==9) { /* comma */
|
|
rcexpr(p2[4], sptab, 0);
|
|
r =+ rlength((p=p2[4])[1]);
|
|
p2 = p2[3];
|
|
}
|
|
rcexpr(p2, sptab, 0);
|
|
r =+ rlength(p2[1]);
|
|
}
|
|
*tree = 101;
|
|
tree[2] = r; /* save arg length */
|
|
}
|
|
if(c==90) { /* ? */
|
|
cbranch(tree[3], c=isn++, 0, reg);
|
|
rcexpr(tree[4][3], table, reg);
|
|
branch(r=isn++, 0);
|
|
label(c);
|
|
rcexpr(tree[4][4], table, reg);
|
|
label(r);
|
|
return(1);
|
|
}
|
|
if ((string=match(tree, table, nreg-reg))==0)
|
|
return(0);
|
|
p1 = tree[3];
|
|
p2 = tree[4];
|
|
loop:
|
|
switch(c = *string++) {
|
|
|
|
case '\0':
|
|
p = tree;
|
|
if (*p==101 & p[2]>0) {
|
|
popstk(p[2]);
|
|
}
|
|
return(1);
|
|
|
|
/* A1 */
|
|
case 'A':
|
|
p = tree[3];
|
|
goto adr;
|
|
|
|
/* A2 */
|
|
case 'B':
|
|
p = tree[4];
|
|
goto adr;
|
|
|
|
/* A */
|
|
case 'O':
|
|
p = tree;
|
|
adr:
|
|
pname(p);
|
|
goto loop;
|
|
|
|
/* I */
|
|
case 'M':
|
|
if ((c = *string)=='\'')
|
|
string++; else
|
|
c = 0;
|
|
prins(*tree, c);
|
|
goto loop;
|
|
|
|
/* B1 */
|
|
case 'C':
|
|
p = tree[3];
|
|
goto pbyte;
|
|
|
|
/* BF */
|
|
case 'P':
|
|
p = tree;
|
|
goto pb1;
|
|
|
|
/* B2 */
|
|
case 'D':
|
|
p = tree[4];
|
|
pbyte:
|
|
if (p[1]==1) /* char type? */
|
|
putchar('b');
|
|
pb1:
|
|
if (isfloat(p))
|
|
putchar('f');
|
|
goto loop;
|
|
|
|
/* BE */
|
|
case 'L':
|
|
if (tree[3][1]==1 | tree[4][1]==1)
|
|
putchar('b');
|
|
goto loop;
|
|
|
|
/* C1 */
|
|
case 'E':
|
|
p = p1[3];
|
|
goto const;
|
|
|
|
/* C2 */
|
|
case 'F':
|
|
p = p2[3];
|
|
const:
|
|
printf("%o", p);
|
|
goto loop;
|
|
|
|
/* F */
|
|
case 'G':
|
|
p = p1;
|
|
goto subtre;
|
|
|
|
/* S */
|
|
case 'K':
|
|
p = p2;
|
|
goto subtre;
|
|
|
|
/* H */
|
|
case 'H':
|
|
p = tree;
|
|
|
|
subtre:
|
|
ctable = regtab;
|
|
r = reg;
|
|
c = *string++ - 'A';
|
|
if ((c&02)!=0)
|
|
ctable = sptab;
|
|
if ((c&04)!=0)
|
|
ctable = cctab;
|
|
if((c&010)!=0)
|
|
r = reg+1;
|
|
if((c&01)!=0)
|
|
if(*p==36) {
|
|
p = p[3];
|
|
if(collcon(p) & ctable!=sptab)
|
|
p = p[3];
|
|
}
|
|
rcexpr(p, ctable, r);
|
|
goto loop;
|
|
|
|
/* R */
|
|
case 'I':
|
|
r = reg;
|
|
goto preg;
|
|
|
|
/* R1 */
|
|
case 'J':
|
|
r = reg+1;
|
|
preg:
|
|
printf("r%d", r);
|
|
goto loop;
|
|
|
|
case '#':
|
|
p = p1[3];
|
|
goto nmbr;
|
|
|
|
case '"':
|
|
p = p2[3];
|
|
goto nmbr;
|
|
case '~':
|
|
p = tree[3];
|
|
|
|
nmbr:
|
|
if(collcon(p)) {
|
|
c = *p;
|
|
if(r = (p=p[4])[3])
|
|
printf("%o", c==40?r:-r);
|
|
}
|
|
goto loop;
|
|
|
|
/* M */
|
|
case 'N':
|
|
if ((c=isfloat(tree, &string))==fltmod)
|
|
goto loop;
|
|
printf((fltmod=c)==2?"setf\n":"setd\n");
|
|
goto loop;
|
|
|
|
/* Z */
|
|
case 'Z':
|
|
printf("$%o", p1[4]);
|
|
goto loop;
|
|
}
|
|
putchar(c);
|
|
goto loop;
|
|
}
|
|
|
|
pname(p)
|
|
int p[][][]; {
|
|
extern putchar, printf, error;
|
|
char np[];
|
|
int i;
|
|
|
|
loop:
|
|
switch(*p) {
|
|
|
|
case 21: /* const */
|
|
printf("$%o", p[3]);
|
|
return;
|
|
|
|
case 22: /* string */
|
|
printf("$l%d", p[3]);
|
|
return;
|
|
|
|
case 20: /* name */
|
|
switch(p[3]) {
|
|
|
|
case 5: /* auto, param */
|
|
printf("%o(r5)", p[4]);
|
|
return;
|
|
|
|
/* extern */
|
|
case 6:
|
|
printf("%p", &p[4]);
|
|
return;
|
|
|
|
}
|
|
printf("L%d", p[4]);
|
|
return;
|
|
|
|
case 35: /* & */
|
|
putchar('$');
|
|
p = p[3];
|
|
goto loop;
|
|
|
|
case 36: /* * */
|
|
putchar('*');
|
|
p = p[3];
|
|
goto loop;
|
|
}
|
|
error("pname called illegally");
|
|
}
|
|
|
|
dcalc(p, nreg)
|
|
int p[]; {
|
|
int op, t;
|
|
|
|
if (p==0)
|
|
return(0);
|
|
op = *p;
|
|
switch (op) {
|
|
|
|
case 20: /* name */
|
|
case 22: /* string */
|
|
case 23: /* float */
|
|
case 24: /* double */
|
|
return(12);
|
|
|
|
case 21: /* short constant */
|
|
return(p[3]==0? 4:8);
|
|
|
|
case 35: /* & */
|
|
return(12);
|
|
|
|
case 36: /* * */
|
|
if ((op=dcalc(p[3], nreg))<16)
|
|
return(16);
|
|
}
|
|
|
|
def:
|
|
return(p[2]<=nreg? 20: 24);
|
|
}
|
|
|
|
notcompat(at, st) {
|
|
|
|
if (st==0) /* word, byte */
|
|
return(at>1 & at<16);
|
|
if (st==1) /* word */
|
|
return(at>0 & at<16);
|
|
st =- 2;
|
|
if (st==2 & at==3)
|
|
at = 2;
|
|
return(st != at);
|
|
}
|
|
|
|
prins(op, c) {
|
|
extern instab[], printf;
|
|
int insp[];
|
|
|
|
insp = instab;
|
|
while(*insp) {
|
|
if (*insp++ == op) {
|
|
if ((c = insp[c!=0])==0)
|
|
goto err;
|
|
printf("%s", c);
|
|
return;
|
|
} else
|
|
insp = insp + 2;
|
|
}
|
|
err:
|
|
error("No match' for op %d", op);
|
|
}
|
|
|
|
collcon(p)
|
|
int p[]; {
|
|
int p1[];
|
|
|
|
if(*p==40 | *p==41)
|
|
if(*(p1=p[4])==21)
|
|
return(1);
|
|
return(0);
|
|
}
|
|
|
|
isfloat(t, s)
|
|
int t[];
|
|
char s[][];
|
|
{
|
|
extern opdope[];
|
|
int rt;
|
|
|
|
rt = **s - '0';
|
|
if (rt==2 | rt==4) {
|
|
(*s)++;
|
|
return(rt>2?3:2);
|
|
}
|
|
if ((opdope[t[0]]&010)!=0) /* relational */
|
|
t = t[3];
|
|
if ((rt=t[1])>=2 & rt<=3)
|
|
return(rt);
|
|
return(0);
|
|
}
|
|
|
|
nreg 4;
|
|
isn 10000;
|
|
namsiz 8;
|
|
line;
|
|
tmpfil;
|
|
nerror;
|
|
fltmod;
|
|
|