EarlyC/prestructc/c01.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);
}