370 lines
5.8 KiB
C
370 lines
5.8 KiB
C
build(op) {
|
|
extern cp[], cvtab, opdope[], maprel[];
|
|
auto p1[], t1, d1, p2[], t2, d2, p3[], t3, d3, t;
|
|
auto d, dope, leftc, cvn, pcvn;
|
|
char cvtab[];
|
|
|
|
if (op==4) { /* [] */
|
|
build(40); /* + */
|
|
op = 36; /* * */
|
|
}
|
|
dope = opdope[op];
|
|
if ((dope&01)!=0) { /* binary */
|
|
p2 = disarray(*--cp);
|
|
t2 = p2[1];
|
|
chkfun(p2);
|
|
d2 = p2[2];
|
|
if (*p2==20)
|
|
d2 = 0;
|
|
}
|
|
p1 = disarray(*--cp);
|
|
if (op!=100 & op!=35) /* call, * */
|
|
chkfun(p1);
|
|
t1 = p1[1];
|
|
d1 = p1[2];
|
|
if (*p1==20)
|
|
d1 = 0;
|
|
pcvn = 0;
|
|
switch (op) {
|
|
|
|
/* : */
|
|
case 8:
|
|
if (t1!=t2)
|
|
error("Type clash in conditional");
|
|
t = t1;
|
|
goto nocv;
|
|
|
|
/* , */
|
|
case 9:
|
|
*cp++ = block(2, 9, 0, 0, p1, p2);
|
|
return;
|
|
|
|
/* ? */
|
|
case 90:
|
|
if (*p2!=8)
|
|
error("Illegal conditional");
|
|
t = t2;
|
|
goto nocv;
|
|
|
|
/* call */
|
|
case 100:
|
|
if ((t1&030) != 020)
|
|
error("Call of non-function");
|
|
*cp++ = block(2,100,decref(t1),24,p1,p2);
|
|
return;
|
|
|
|
/* * */
|
|
case 36:
|
|
if (*p1==35 | *p1==29) { /* & unary */
|
|
*cp++ = p1[3];
|
|
return;
|
|
}
|
|
if (*p1!=20 & d1==0)
|
|
d1 = 1;
|
|
if ((t1&030) == 020) /* function */
|
|
error("Illegal indirection");
|
|
*cp++ = block(1,36,decref(t1),d1,p1);
|
|
return;
|
|
|
|
/* & unary */
|
|
case 35:
|
|
if (*p1==36) { /* * */
|
|
*cp++ = p1[3];
|
|
return;
|
|
}
|
|
if (*p1==20) {
|
|
*cp++ = block(1,p1[3]==5?29:35,incref(t1),1,p1);
|
|
return;
|
|
}
|
|
error("Illegal lvalue");
|
|
break;
|
|
|
|
case 43: /* / */
|
|
case 44: /* % */
|
|
case 73: /* =/ */
|
|
case 74: /* =% */
|
|
d1++;
|
|
d2++;
|
|
|
|
case 42: /* * */
|
|
case 72: /* =* */
|
|
d1++;
|
|
d2++;
|
|
break;
|
|
|
|
case 30: /* ++ -- pre and post */
|
|
case 31:
|
|
case 32:
|
|
case 33:
|
|
chklval(p1);
|
|
*cp++ = block(2,op,t1,max(d1,1),p1,plength(p1));
|
|
return;
|
|
|
|
case 39: /* . (structure ref) */
|
|
case 50: /* -> (indirect structure ref) */
|
|
if (p2[0]!=20 | p2[3]!=4) /* not mos */
|
|
error("Illegal structure ref");
|
|
*cp++ = p1;
|
|
t = t2;
|
|
if ((t&030) == 030) /* array */
|
|
t = decref(t);
|
|
setype(p1, t);
|
|
if (op==39) /* is "." */
|
|
build(35); /* unary & */
|
|
*cp++ = block(1,21,7,0,p2[5]);
|
|
build(40); /* + */
|
|
if ((t2&030) != 030) /* not array */
|
|
build(36); /* unary * */
|
|
return;
|
|
}
|
|
if ((dope&02)!=0) /* lvalue needed on left? */
|
|
chklval(p1);
|
|
if ((dope&020)!=0) /* word operand on left? */
|
|
chkw(p1);
|
|
if ((dope&040)!=0) /* word operand on right? */
|
|
chkw(p2);
|
|
if ((dope&01)==0) { /* unary op? */
|
|
*cp++ = block(1,op,t1,max(d1,1),p1);
|
|
return;
|
|
}
|
|
if (t2==7) {
|
|
t = t1;
|
|
p2[1] = 0; /* no int cv for struct */
|
|
t2 = 0;
|
|
goto nocv;
|
|
}
|
|
cvn = cvtab[11*lintyp(t1)+lintyp(t2)];
|
|
leftc = cvn&0100;
|
|
t = leftc? t2:t1;
|
|
if (op==80 & t1!=4 & t2!=4) { /* = */
|
|
t = t1;
|
|
if (leftc | cvn!=1)
|
|
goto nocv;
|
|
}
|
|
if (cvn =& 077) {
|
|
if (cvn==077) {
|
|
illcv:
|
|
error("Illegal conversion");
|
|
goto nocv;
|
|
}
|
|
if (cvn>4 & cvn<10) { /* ptr conv */
|
|
t = 0; /* integer result */
|
|
cvn = 0;
|
|
if ((dope&04)!=0) /* relational? */
|
|
goto nocv;
|
|
if (op!=41) /* - */
|
|
goto illcv;
|
|
pcvn = cvn;
|
|
goto nocv;
|
|
}
|
|
if (leftc) {
|
|
if ((dope&010) != 0) { /* =op */
|
|
if (cvn == 1) {
|
|
leftc = 0;
|
|
cvn = 8;
|
|
t = t1;
|
|
goto rcvt;
|
|
} else
|
|
goto illcv;
|
|
}
|
|
d1 = (p1=convert(p1, t, d1, cvn, plength(p2)))[2];
|
|
} else {
|
|
rcvt:
|
|
d2 = (p2=convert(p2, t, d2, cvn, plength(p1)))[2];
|
|
}
|
|
nocv:; }
|
|
if (d1==d2)
|
|
d = d1+1; else
|
|
d = max(d1,d2);
|
|
if ((dope&04)!=0) { /* relational? */
|
|
if (op>61 & t>=010)
|
|
op =+ 4; /* ptr relation */
|
|
t = 0; /* relational is integer */
|
|
}
|
|
*cp++ = optim(block(2,op,t,d,p1,p2));
|
|
if (pcvn) {
|
|
p1 = *--cp;
|
|
*cp++ = block(1,50+pcvn,0,d,p1);
|
|
}
|
|
return;
|
|
*cp++ = block(1,op,t1,d1==0?1:d1,p1);
|
|
}
|
|
|
|
setype(p, t)
|
|
int p[];
|
|
{
|
|
int p1[];
|
|
|
|
if ((p[1]&07) != 4) /* not structure */
|
|
return;
|
|
p[1] = t;
|
|
switch(*p) {
|
|
|
|
case 29: /* & */
|
|
case 35:
|
|
setype(p[3], decref(t));
|
|
return;
|
|
|
|
case 36: /* * */
|
|
setype(p[3], incref(t));
|
|
return;
|
|
|
|
case 40: /* + */
|
|
setype(p[4], t);
|
|
}
|
|
}
|
|
|
|
chkfun(p)
|
|
int p[];
|
|
{
|
|
if ((p[1]&030)==020) /* func */
|
|
error("Illegal use of function");
|
|
}
|
|
|
|
optim(p)
|
|
int p[];
|
|
{
|
|
int p1[], p2[], t;
|
|
|
|
if (*p != 40) /* + */
|
|
return(p);
|
|
p1 = p[3];
|
|
p2 = p[4];
|
|
if (*p1==21) { /* const */
|
|
t = p1;
|
|
p1 = p2;
|
|
p2 = t;
|
|
}
|
|
if (*p2 != 21) /* const */
|
|
return(p);
|
|
if ((t=p2[3]) == 0) /* const 0 */
|
|
return(p1);
|
|
if (*p1!=35 & *p1!=29) /* not & */
|
|
return(p);
|
|
p2 = p1[3];
|
|
if (*p2!=20) { /* name? */
|
|
error("C error (optim)");
|
|
return(p);
|
|
}
|
|
p2[4] =+ t;
|
|
return(p1);
|
|
}
|
|
|
|
disarray(p)
|
|
int p[];
|
|
{
|
|
extern cp;
|
|
int t, cp[];
|
|
|
|
if (((t = p[1]) & 030)!=030 | p[0]==20&p[3]==4) /* array & not MOS */
|
|
return(p);
|
|
p[1] = decref(t);
|
|
*cp++ = p;
|
|
build(35); /* add & */
|
|
return(*--cp);
|
|
}
|
|
|
|
convert(p, t, d, cvn, len)
|
|
int p[];
|
|
{
|
|
int c, p1[];
|
|
|
|
if (*p==21) { /* constant */
|
|
c = p[3];
|
|
switch(cvn) {
|
|
|
|
case 4: /* int -> double[] */
|
|
c =<< 1;
|
|
|
|
case 3: /* int -> float[] */
|
|
c =<< 1;
|
|
|
|
case 2: /* int -> int[] */
|
|
c =<< 1;
|
|
p[3] = c;
|
|
return(p);
|
|
|
|
case 10: /* i -> s[] */
|
|
p[3] = c*len;
|
|
return(p);
|
|
}
|
|
}
|
|
if (cvn==10) /* i -> s[]; retrun i*len */
|
|
return(block(2,42,t,d+2,p,block(1,21,0,0,len)));
|
|
return(block(1, 50+cvn, t, max(1,d), p));
|
|
}
|
|
|
|
chkw(p)
|
|
int p[]; {
|
|
extern error;
|
|
auto t;
|
|
|
|
if ((t=p[1])>1 & t<=07)
|
|
error("Integer operand required");
|
|
return;
|
|
}
|
|
|
|
lintyp(t)
|
|
{
|
|
if (t<=07)
|
|
return(t);
|
|
if ((t&037)==t)
|
|
return((t&07)+5);
|
|
return(10);
|
|
}
|
|
|
|
error(s, p1, p2, p3, p4, p5, p6) {
|
|
extern line, fout, nerror;
|
|
int f;
|
|
|
|
nerror++;
|
|
flush();
|
|
f = fout;
|
|
fout = 1;
|
|
printf("%d: ", line);
|
|
printf(s, p1, p2, p3, p4, p5, p6);
|
|
putchar('\n');
|
|
fout = f;
|
|
}
|
|
|
|
block(n, op, t, d, p1,p2,p3)
|
|
int p1[],p2[],p3[]; {
|
|
int p[], ap[], space[];
|
|
extern space;
|
|
|
|
ap = &op;
|
|
n =+ 3;
|
|
p = space;
|
|
while(n--)
|
|
pblock(*ap++);
|
|
return(p);
|
|
}
|
|
|
|
pblock(p)
|
|
{
|
|
extern space, osleft;
|
|
int space[];
|
|
|
|
*space++ = p;
|
|
if (--osleft<=0) {
|
|
error("Expression overflow");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
chklval(p)
|
|
int p[]; {
|
|
extern error;
|
|
|
|
if (*p!=20 & *p !=36)
|
|
error("Lvalue required");
|
|
}
|
|
|
|
max(a, b)
|
|
{
|
|
if (a>b)
|
|
return(a);
|
|
return(b);
|
|
}
|
|
|