You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
3.2 KiB

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);
}