211 lines
3.2 KiB
C
211 lines
3.2 KiB
C
build(op) {
|
|
extern cp[], error, block, opdope[], maprel[], chklval;
|
|
extern chkw, cvtab, lintyp, dcalc;
|
|
auto p1[], t1, d1, p2[], t2, d2, p3[], t3, d3, t;
|
|
auto d, dope, lr, cvn;
|
|
char cvtab[];
|
|
|
|
if (op==4) { /* [] */
|
|
build(40); /* + */
|
|
op = 36;
|
|
}
|
|
dope = opdope[op];
|
|
if ((dope&01)!=0) {
|
|
p2 = *--cp;
|
|
t2 = p2[1];
|
|
d2 = p2[2];
|
|
}
|
|
p1 = *--cp;
|
|
t1 = p1[1];
|
|
d1 = p1[2];
|
|
switch (op) {
|
|
|
|
/* , */
|
|
case 9:
|
|
*cp++ = block(2, 9, 0, 0, p1, p2);
|
|
return;
|
|
|
|
/* ? */
|
|
case 90:
|
|
if (*p2!=8)
|
|
error("Illegal conditional");
|
|
goto goon;
|
|
|
|
/* call */
|
|
case 100:
|
|
*cp++ = block(2,100,t1,24,p1,p2);
|
|
return;
|
|
|
|
/* * */
|
|
case 36:
|
|
if ((t1 =- 16)<0) {
|
|
error("Illegal indirection");
|
|
t1 =+ 16;
|
|
}
|
|
if (*p1!=20 & d1==0)
|
|
d1 = 1;
|
|
*cp++ = block(1,36,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,t1+16,1,p1);
|
|
return;
|
|
}
|
|
error("Illegal lvalue");
|
|
}
|
|
goon:
|
|
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) { /* binary op? */
|
|
cvn = cvtab[9*lintyp(t1)+lintyp(t2)];
|
|
if ((dope&010)!=0) { /* assignment? */
|
|
t = t1;
|
|
lr = 1;
|
|
cvn =& 07;
|
|
} else {
|
|
t = (cvn&0100)!=0? t2:t1;
|
|
lr = cvn&0200;
|
|
cvn = (cvn>>3)&07;
|
|
}
|
|
if (cvn) {
|
|
if (cvn==07) {
|
|
error("Illegal conversion");
|
|
goto nocv;
|
|
}
|
|
cvn =+ (dope&010)!=0? 83:93;
|
|
if (lr) {
|
|
t2 = t;
|
|
d2 = (p2=convert(p2, t, d2, cvn))[2];
|
|
} else {
|
|
t1 = t;
|
|
d1 = (p1=convert(p1, t, d1, cvn))[2];
|
|
}
|
|
nocv:; }
|
|
if (d2>d1 & (dope&0100)!=0) { /* flip commutative? */
|
|
if ((dope&04)!=0) /* relational? */
|
|
op = maprel[op-60];
|
|
d = d1;
|
|
d1 = d2;
|
|
d2 = d;
|
|
d = p1;
|
|
p1 = p2;
|
|
p2 = d;
|
|
d = t1;
|
|
t1 = t2;
|
|
t2 = d;
|
|
}
|
|
if (d1==d2)
|
|
d = d1+1; else
|
|
d = max(d1,d2);
|
|
if ((dope&04)!=0)
|
|
t = 0; /* relational is integer */
|
|
*cp++ = block(2,op,t,d,p1,p2);
|
|
return;
|
|
}
|
|
*cp++ = block(1,op,t1,d1==0?1:d1,p1);
|
|
}
|
|
|
|
convert(p, t, d, cvn)
|
|
int p[];
|
|
{
|
|
auto c;
|
|
if (*p==21) { /* constant */
|
|
c = p[3];
|
|
switch(cvn) {
|
|
|
|
case 99: /* c18 */
|
|
c =<< 1;
|
|
|
|
case 98: /* c14 */
|
|
c =<< 1;
|
|
|
|
case 97: /* c12 */
|
|
c =<< 1;
|
|
|
|
p[3] = c;
|
|
return(p);
|
|
}
|
|
}
|
|
return(block(1, cvn, t, max(1,d), p));
|
|
}
|
|
|
|
chkw(p)
|
|
int p[]; {
|
|
extern error;
|
|
auto t;
|
|
|
|
if ((t=p[1])>1 & t<16)
|
|
error("Integer operand required");
|
|
return;
|
|
}
|
|
|
|
lintyp(t) {
|
|
return(t<16? t:(t<32? t-12: 8));
|
|
}
|
|
|
|
error(s, p1, p2) {
|
|
extern printf, line, fout, flush, putchar, nerror;
|
|
int f;
|
|
|
|
nerror++;
|
|
flush();
|
|
f = fout;
|
|
fout = 1;
|
|
printf("%d: ", line);
|
|
printf(s, p1, p2);
|
|
putchar('\n');
|
|
fout = f;
|
|
}
|
|
|
|
block(n, op, t, d, p1,p2,p3)
|
|
int p1[],p2[],p3[]; {
|
|
extern space[], error, exit, ossiz, ospace[];
|
|
auto p[], ap[];
|
|
|
|
p = space;
|
|
ap = &op;
|
|
n =+ 3;
|
|
if(space+n >= ospace+ossiz) {
|
|
error("Expression overflow");
|
|
exit(1);
|
|
}
|
|
while(n--)
|
|
*space++ = *ap++;
|
|
return(p);
|
|
}
|
|
|
|
chklval(p)
|
|
int p[]; {
|
|
extern error;
|
|
if (*p!=20)
|
|
if (*p!=36)
|
|
error("Lvalue required");
|
|
}
|
|
|
|
notcompat(at, st) {
|
|
|
|
if (st==0) /* word, byte */
|
|
return(at>1 & at<16);
|
|
if (st==1) /* word */
|
|
return(at>0 & at<16);
|
|
return((st-2) != at);
|
|
}
|
|
|
|
max(a, b)
|
|
{
|
|
if (a>b)
|
|
return(a);
|
|
return(b);
|
|
}
|
|
|