xref: /inferno-os/utils/c2l/com.c (revision d67b7dad77bb8aa973dad1f7c3ab0c309b114278)
174a4d8c2SCharles.Forsyth #include "cc.h"
274a4d8c2SCharles.Forsyth 
374a4d8c2SCharles.Forsyth void
complex(Node * n)474a4d8c2SCharles.Forsyth complex(Node *n)
574a4d8c2SCharles.Forsyth {
674a4d8c2SCharles.Forsyth 
774a4d8c2SCharles.Forsyth 	if(n == Z)
874a4d8c2SCharles.Forsyth 		return;
974a4d8c2SCharles.Forsyth 
1074a4d8c2SCharles.Forsyth 	nearln = n->lineno;
1174a4d8c2SCharles.Forsyth 	if(tcom(n))
1274a4d8c2SCharles.Forsyth 		return;
1374a4d8c2SCharles.Forsyth 	ccom(n);
1474a4d8c2SCharles.Forsyth 	acom(n);
1574a4d8c2SCharles.Forsyth }
1674a4d8c2SCharles.Forsyth 
1774a4d8c2SCharles.Forsyth /*
1874a4d8c2SCharles.Forsyth  * evaluate types
1974a4d8c2SCharles.Forsyth  * evaluate lvalues (addable == 1)
2074a4d8c2SCharles.Forsyth  */
2174a4d8c2SCharles.Forsyth enum
2274a4d8c2SCharles.Forsyth {
2374a4d8c2SCharles.Forsyth 	ADDROF	= 1<<0,
2474a4d8c2SCharles.Forsyth 	CASTOF	= 1<<1,
2574a4d8c2SCharles.Forsyth 	ADDROP	= 1<<2,
2674a4d8c2SCharles.Forsyth };
2774a4d8c2SCharles.Forsyth 
2874a4d8c2SCharles.Forsyth int
tcom(Node * n)2974a4d8c2SCharles.Forsyth tcom(Node *n)
3074a4d8c2SCharles.Forsyth {
3174a4d8c2SCharles.Forsyth 
3274a4d8c2SCharles.Forsyth 	return tcomo(n, ADDROF);
3374a4d8c2SCharles.Forsyth }
3474a4d8c2SCharles.Forsyth 
3574a4d8c2SCharles.Forsyth int
tcomo(Node * n,int f)3674a4d8c2SCharles.Forsyth tcomo(Node *n, int f)
3774a4d8c2SCharles.Forsyth {
3874a4d8c2SCharles.Forsyth 	Node *l, *r;
3974a4d8c2SCharles.Forsyth 	Type *t;
4074a4d8c2SCharles.Forsyth 	int o;
4174a4d8c2SCharles.Forsyth 
4274a4d8c2SCharles.Forsyth 	if(n == Z) {
4374a4d8c2SCharles.Forsyth 		diag(Z, "Z in tcom");
4474a4d8c2SCharles.Forsyth 		errorexit();
4574a4d8c2SCharles.Forsyth 	}
4674a4d8c2SCharles.Forsyth 	l = n->left;
4774a4d8c2SCharles.Forsyth 	r = n->right;
4874a4d8c2SCharles.Forsyth 
4974a4d8c2SCharles.Forsyth 	switch(n->op) {
5074a4d8c2SCharles.Forsyth 	default:
5174a4d8c2SCharles.Forsyth 		diag(n, "unknown op in type complex: %O", n->op);
5274a4d8c2SCharles.Forsyth 		goto bad;
5374a4d8c2SCharles.Forsyth 
5474a4d8c2SCharles.Forsyth 	case ODOTDOT:
5574a4d8c2SCharles.Forsyth 		/*
5674a4d8c2SCharles.Forsyth 		 * tcom has already been called on this subtree
5774a4d8c2SCharles.Forsyth 		 */
5874a4d8c2SCharles.Forsyth 		*n = *n->left;
5974a4d8c2SCharles.Forsyth 		if(n->type == T)
6074a4d8c2SCharles.Forsyth 			goto bad;
6174a4d8c2SCharles.Forsyth 		break;
6274a4d8c2SCharles.Forsyth 
6374a4d8c2SCharles.Forsyth 	case OCAST:
6474a4d8c2SCharles.Forsyth 		if(n->type == T)
6574a4d8c2SCharles.Forsyth 			break;
6674a4d8c2SCharles.Forsyth 		if(n->type->width == types[TLONG]->width) {
6774a4d8c2SCharles.Forsyth 			if(tcomo(l, ADDROF|CASTOF))
6874a4d8c2SCharles.Forsyth 					goto bad;
6974a4d8c2SCharles.Forsyth 		} else
7074a4d8c2SCharles.Forsyth 			if(tcom(l))
7174a4d8c2SCharles.Forsyth 				goto bad;
7274a4d8c2SCharles.Forsyth 		if(tcompat(n, l->type, n->type, tcast))
7374a4d8c2SCharles.Forsyth 			goto bad;
7474a4d8c2SCharles.Forsyth 		break;
7574a4d8c2SCharles.Forsyth 
7674a4d8c2SCharles.Forsyth 	case ORETURN:
7774a4d8c2SCharles.Forsyth 		if(l == Z) {
7874a4d8c2SCharles.Forsyth 			if(n->type->etype != TVOID)
7974a4d8c2SCharles.Forsyth 				warn(n, "null return of a typed function");
8074a4d8c2SCharles.Forsyth 			break;
8174a4d8c2SCharles.Forsyth 		}
8274a4d8c2SCharles.Forsyth 		if(tcom(l))
8374a4d8c2SCharles.Forsyth 			goto bad;
8474a4d8c2SCharles.Forsyth 		typeext(n->type, l);
8574a4d8c2SCharles.Forsyth 		if(tcompat(n, n->type, l->type, tasign))
8674a4d8c2SCharles.Forsyth 			break;
8774a4d8c2SCharles.Forsyth 		constas(n, n->type, l->type);
8874a4d8c2SCharles.Forsyth 		if(!sametype(n->type, l->type)) {
8974a4d8c2SCharles.Forsyth 			l = new1(OCAST, l, Z);
9074a4d8c2SCharles.Forsyth 			l->type = n->type;
9174a4d8c2SCharles.Forsyth 			n->left = l;
9274a4d8c2SCharles.Forsyth 		}
9374a4d8c2SCharles.Forsyth 		break;
9474a4d8c2SCharles.Forsyth 
9574a4d8c2SCharles.Forsyth 	case OASI:	/* same as as, but no test for const */
9674a4d8c2SCharles.Forsyth 		n->op = OAS;
9774a4d8c2SCharles.Forsyth 		o = tcom(l);
9874a4d8c2SCharles.Forsyth 		if(o | tcom(r))
9974a4d8c2SCharles.Forsyth 			goto bad;
10074a4d8c2SCharles.Forsyth 
10174a4d8c2SCharles.Forsyth 		typeext(l->type, r);
10274a4d8c2SCharles.Forsyth 		if(tlvalue(l) || tcompat(n, l->type, r->type, tasign))
10374a4d8c2SCharles.Forsyth 			goto bad;
10474a4d8c2SCharles.Forsyth 		if(!sametype(l->type, r->type)) {
10574a4d8c2SCharles.Forsyth 			r = new1(OCAST, r, Z);
10674a4d8c2SCharles.Forsyth 			r->type = l->type;
10774a4d8c2SCharles.Forsyth 			n->right = r;
10874a4d8c2SCharles.Forsyth 		}
10974a4d8c2SCharles.Forsyth 		n->type = l->type;
11074a4d8c2SCharles.Forsyth 		break;
11174a4d8c2SCharles.Forsyth 
11274a4d8c2SCharles.Forsyth 	case OAS:
11374a4d8c2SCharles.Forsyth 	case OASD:
11474a4d8c2SCharles.Forsyth 		o = tcom(l);
11574a4d8c2SCharles.Forsyth 		if(o | tcom(r))
11674a4d8c2SCharles.Forsyth 			goto bad;
11774a4d8c2SCharles.Forsyth 
11874a4d8c2SCharles.Forsyth 		typeext(l->type, r);
11974a4d8c2SCharles.Forsyth 		if(tlvalue(l) || tcompat(n, l->type, r->type, tasign))
12074a4d8c2SCharles.Forsyth 			goto bad;
12174a4d8c2SCharles.Forsyth 		constas(n, l->type, r->type);
12274a4d8c2SCharles.Forsyth 		if(!sametype(l->type, r->type)) {
12374a4d8c2SCharles.Forsyth 			r = new1(OCAST, r, Z);
12474a4d8c2SCharles.Forsyth 			r->type = l->type;
12574a4d8c2SCharles.Forsyth 			n->right = r;
12674a4d8c2SCharles.Forsyth 		}
12774a4d8c2SCharles.Forsyth 		n->type = l->type;
12874a4d8c2SCharles.Forsyth 		break;
12974a4d8c2SCharles.Forsyth 
13074a4d8c2SCharles.Forsyth 	case OASADD:
13174a4d8c2SCharles.Forsyth 	case OASSUB:
13274a4d8c2SCharles.Forsyth 		o = tcom(l);
13374a4d8c2SCharles.Forsyth 		if(o | tcom(r))
13474a4d8c2SCharles.Forsyth 			goto bad;
13574a4d8c2SCharles.Forsyth 		typeext1(l->type, r);
13674a4d8c2SCharles.Forsyth 		if(tlvalue(l) || tcompat(n, l->type, r->type, tasadd))
13774a4d8c2SCharles.Forsyth 			goto bad;
13874a4d8c2SCharles.Forsyth 		constas(n, l->type, r->type);
13974a4d8c2SCharles.Forsyth 		t = l->type;
14074a4d8c2SCharles.Forsyth 		arith(n, 0);
14174a4d8c2SCharles.Forsyth 		while(n->left->op == OCAST)
14274a4d8c2SCharles.Forsyth 			n->left = n->left->left;
14374a4d8c2SCharles.Forsyth 		if(!sametype(t, n->type)) {
14474a4d8c2SCharles.Forsyth 			r = new1(OCAST, n->right, Z);
14574a4d8c2SCharles.Forsyth 			r->type = t;
14674a4d8c2SCharles.Forsyth 			n->right = r;
14774a4d8c2SCharles.Forsyth 			n->type = t;
14874a4d8c2SCharles.Forsyth 		}
14974a4d8c2SCharles.Forsyth 		break;
15074a4d8c2SCharles.Forsyth 
15174a4d8c2SCharles.Forsyth 	case OASMUL:
15274a4d8c2SCharles.Forsyth 	case OASLMUL:
15374a4d8c2SCharles.Forsyth 	case OASDIV:
15474a4d8c2SCharles.Forsyth 	case OASLDIV:
15574a4d8c2SCharles.Forsyth 		o = tcom(l);
15674a4d8c2SCharles.Forsyth 		if(o | tcom(r))
15774a4d8c2SCharles.Forsyth 			goto bad;
15874a4d8c2SCharles.Forsyth 		typeext1(l->type, r);
15974a4d8c2SCharles.Forsyth 		if(tlvalue(l) || tcompat(n, l->type, r->type, tmul))
16074a4d8c2SCharles.Forsyth 			goto bad;
16174a4d8c2SCharles.Forsyth 		constas(n, l->type, r->type);
16274a4d8c2SCharles.Forsyth 		t = l->type;
16374a4d8c2SCharles.Forsyth 		arith(n, 0);
16474a4d8c2SCharles.Forsyth 		while(n->left->op == OCAST)
16574a4d8c2SCharles.Forsyth 			n->left = n->left->left;
16674a4d8c2SCharles.Forsyth 		if(!sametype(t, n->type)) {
16774a4d8c2SCharles.Forsyth 			r = new1(OCAST, n->right, Z);
16874a4d8c2SCharles.Forsyth 			r->type = t;
16974a4d8c2SCharles.Forsyth 			n->right = r;
17074a4d8c2SCharles.Forsyth 			n->type = t;
17174a4d8c2SCharles.Forsyth 		}
17274a4d8c2SCharles.Forsyth 		if(typeu[n->type->etype]) {
17374a4d8c2SCharles.Forsyth 			if(n->op == OASDIV)
17474a4d8c2SCharles.Forsyth 				n->op = OASLDIV;
17574a4d8c2SCharles.Forsyth 			if(n->op == OASMUL)
17674a4d8c2SCharles.Forsyth 				n->op = OASLMUL;
17774a4d8c2SCharles.Forsyth 		}
17874a4d8c2SCharles.Forsyth 		break;
17974a4d8c2SCharles.Forsyth 
18074a4d8c2SCharles.Forsyth 	case OASLSHR:
18174a4d8c2SCharles.Forsyth 	case OASASHR:
18274a4d8c2SCharles.Forsyth 	case OASASHL:
18374a4d8c2SCharles.Forsyth 		o = tcom(l);
18474a4d8c2SCharles.Forsyth 		if(o | tcom(r))
18574a4d8c2SCharles.Forsyth 			goto bad;
18674a4d8c2SCharles.Forsyth 		if(tlvalue(l) || tcompat(n, l->type, r->type, tand))
18774a4d8c2SCharles.Forsyth 			goto bad;
18874a4d8c2SCharles.Forsyth 		n->type = l->type;
18974a4d8c2SCharles.Forsyth 		if(typeu[n->type->etype]) {
19074a4d8c2SCharles.Forsyth 			if(n->op == OASASHR)
19174a4d8c2SCharles.Forsyth 				n->op = OASLSHR;
19274a4d8c2SCharles.Forsyth 		}
19374a4d8c2SCharles.Forsyth 		break;
19474a4d8c2SCharles.Forsyth 
19574a4d8c2SCharles.Forsyth 	case OASMOD:
19674a4d8c2SCharles.Forsyth 	case OASLMOD:
19774a4d8c2SCharles.Forsyth 	case OASOR:
19874a4d8c2SCharles.Forsyth 	case OASAND:
19974a4d8c2SCharles.Forsyth 	case OASXOR:
20074a4d8c2SCharles.Forsyth 		o = tcom(l);
20174a4d8c2SCharles.Forsyth 		if(o | tcom(r))
20274a4d8c2SCharles.Forsyth 			goto bad;
20374a4d8c2SCharles.Forsyth 		if(tlvalue(l) || tcompat(n, l->type, r->type, tand))
20474a4d8c2SCharles.Forsyth 			goto bad;
20574a4d8c2SCharles.Forsyth 		t = l->type;
20674a4d8c2SCharles.Forsyth 		arith(n, 0);
20774a4d8c2SCharles.Forsyth 		while(n->left->op == OCAST)
20874a4d8c2SCharles.Forsyth 			n->left = n->left->left;
20974a4d8c2SCharles.Forsyth 		if(!sametype(t, n->type)) {
21074a4d8c2SCharles.Forsyth 			r = new1(OCAST, n->right, Z);
21174a4d8c2SCharles.Forsyth 			r->type = t;
21274a4d8c2SCharles.Forsyth 			n->right = r;
21374a4d8c2SCharles.Forsyth 			n->type = t;
21474a4d8c2SCharles.Forsyth 		}
21574a4d8c2SCharles.Forsyth 		if(typeu[n->type->etype]) {
21674a4d8c2SCharles.Forsyth 			if(n->op == OASMOD)
21774a4d8c2SCharles.Forsyth 				n->op = OASLMOD;
21874a4d8c2SCharles.Forsyth 		}
21974a4d8c2SCharles.Forsyth 		break;
22074a4d8c2SCharles.Forsyth 
22174a4d8c2SCharles.Forsyth 	case OPREINC:
22274a4d8c2SCharles.Forsyth 	case OPREDEC:
22374a4d8c2SCharles.Forsyth 	case OPOSTINC:
22474a4d8c2SCharles.Forsyth 	case OPOSTDEC:
22574a4d8c2SCharles.Forsyth 		if(tcom(l))
22674a4d8c2SCharles.Forsyth 			goto bad;
22774a4d8c2SCharles.Forsyth 		if(tlvalue(l) || tcompat(n, l->type, types[TINT], tadd))
22874a4d8c2SCharles.Forsyth 			goto bad;
22974a4d8c2SCharles.Forsyth 		n->type = l->type;
23074a4d8c2SCharles.Forsyth 		if(n->type->etype == TIND)
23174a4d8c2SCharles.Forsyth 		if(n->type->link->width < 1)
23274a4d8c2SCharles.Forsyth 			diag(n, "inc/dec of a void pointer");
23374a4d8c2SCharles.Forsyth 		break;
23474a4d8c2SCharles.Forsyth 
23574a4d8c2SCharles.Forsyth 	case OEQ:
23674a4d8c2SCharles.Forsyth 	case ONE:
23774a4d8c2SCharles.Forsyth 		o = tcom(l);
23874a4d8c2SCharles.Forsyth 		if(o | tcom(r))
23974a4d8c2SCharles.Forsyth 			goto bad;
24074a4d8c2SCharles.Forsyth 		typeext(l->type, r);
24174a4d8c2SCharles.Forsyth 		typeext(r->type, l);
24274a4d8c2SCharles.Forsyth 		if(tcompat(n, l->type, r->type, trel))
24374a4d8c2SCharles.Forsyth 			goto bad;
24474a4d8c2SCharles.Forsyth 		arith(n, 0);
24574a4d8c2SCharles.Forsyth 		n->type = types[TINT];
24674a4d8c2SCharles.Forsyth 		break;
24774a4d8c2SCharles.Forsyth 
24874a4d8c2SCharles.Forsyth 	case OLT:
24974a4d8c2SCharles.Forsyth 	case OGE:
25074a4d8c2SCharles.Forsyth 	case OGT:
25174a4d8c2SCharles.Forsyth 	case OLE:
25274a4d8c2SCharles.Forsyth 		o = tcom(l);
25374a4d8c2SCharles.Forsyth 		if(o | tcom(r))
25474a4d8c2SCharles.Forsyth 			goto bad;
25574a4d8c2SCharles.Forsyth 		typeext1(l->type, r);
25674a4d8c2SCharles.Forsyth 		typeext1(r->type, l);
25774a4d8c2SCharles.Forsyth 		if(tcompat(n, l->type, r->type, trel))
25874a4d8c2SCharles.Forsyth 			goto bad;
25974a4d8c2SCharles.Forsyth 		arith(n, 0);
26074a4d8c2SCharles.Forsyth 		if(typeu[n->type->etype])
26174a4d8c2SCharles.Forsyth 			n->op = logrel[relindex(n->op)];
26274a4d8c2SCharles.Forsyth 		n->type = types[TINT];
26374a4d8c2SCharles.Forsyth 		break;
26474a4d8c2SCharles.Forsyth 
26574a4d8c2SCharles.Forsyth 	case OCOND:
26674a4d8c2SCharles.Forsyth 		o = tcom(l);
26774a4d8c2SCharles.Forsyth 		o |= tcom(r->left);
26874a4d8c2SCharles.Forsyth 		if(o | tcom(r->right))
26974a4d8c2SCharles.Forsyth 			goto bad;
27074a4d8c2SCharles.Forsyth 		if(r->right->type->etype == TIND && vconst(r->left) == 0) {
27174a4d8c2SCharles.Forsyth 			r->left->type = r->right->type;
27274a4d8c2SCharles.Forsyth 			r->left->vconst = 0;
27374a4d8c2SCharles.Forsyth 		}
27474a4d8c2SCharles.Forsyth 		if(r->left->type->etype == TIND && vconst(r->right) == 0) {
27574a4d8c2SCharles.Forsyth 			r->right->type = r->left->type;
27674a4d8c2SCharles.Forsyth 			r->right->vconst = 0;
27774a4d8c2SCharles.Forsyth 		}
27874a4d8c2SCharles.Forsyth 		if(sametype(r->right->type, r->left->type)) {
27974a4d8c2SCharles.Forsyth 			r->type = r->right->type;
28074a4d8c2SCharles.Forsyth 			n->type = r->type;
28174a4d8c2SCharles.Forsyth 			break;
28274a4d8c2SCharles.Forsyth 		}
28374a4d8c2SCharles.Forsyth 		if(tcompat(r, r->left->type, r->right->type, trel))
28474a4d8c2SCharles.Forsyth 			goto bad;
28574a4d8c2SCharles.Forsyth 		arith(r, 0);
28674a4d8c2SCharles.Forsyth 		n->type = r->type;
28774a4d8c2SCharles.Forsyth 		break;
28874a4d8c2SCharles.Forsyth 
28974a4d8c2SCharles.Forsyth 	case OADD:
29074a4d8c2SCharles.Forsyth 		o = tcom(l);
29174a4d8c2SCharles.Forsyth 		if(o | tcom(r))
29274a4d8c2SCharles.Forsyth 			goto bad;
29374a4d8c2SCharles.Forsyth 		if(tcompat(n, l->type, r->type, tadd))
29474a4d8c2SCharles.Forsyth 			goto bad;
29574a4d8c2SCharles.Forsyth 		arith(n, 1);
29674a4d8c2SCharles.Forsyth 		break;
29774a4d8c2SCharles.Forsyth 
29874a4d8c2SCharles.Forsyth 	case OSUB:
29974a4d8c2SCharles.Forsyth 		o = tcom(l);
30074a4d8c2SCharles.Forsyth 		if(o | tcom(r))
30174a4d8c2SCharles.Forsyth 			goto bad;
30274a4d8c2SCharles.Forsyth 		if(tcompat(n, l->type, r->type, tsub))
30374a4d8c2SCharles.Forsyth 			goto bad;
30474a4d8c2SCharles.Forsyth 		arith(n, 1);
30574a4d8c2SCharles.Forsyth 		break;
30674a4d8c2SCharles.Forsyth 
30774a4d8c2SCharles.Forsyth 	case OMUL:
30874a4d8c2SCharles.Forsyth 	case OLMUL:
30974a4d8c2SCharles.Forsyth 	case ODIV:
31074a4d8c2SCharles.Forsyth 	case OLDIV:
31174a4d8c2SCharles.Forsyth 		o = tcom(l);
31274a4d8c2SCharles.Forsyth 		if(o | tcom(r))
31374a4d8c2SCharles.Forsyth 			goto bad;
31474a4d8c2SCharles.Forsyth 		if(tcompat(n, l->type, r->type, tmul))
31574a4d8c2SCharles.Forsyth 			goto bad;
31674a4d8c2SCharles.Forsyth 		arith(n, 1);
31774a4d8c2SCharles.Forsyth 		if(typeu[n->type->etype]) {
31874a4d8c2SCharles.Forsyth 			if(n->op == ODIV)
31974a4d8c2SCharles.Forsyth 				n->op = OLDIV;
32074a4d8c2SCharles.Forsyth 			if(n->op == OMUL)
32174a4d8c2SCharles.Forsyth 				n->op = OLMUL;
32274a4d8c2SCharles.Forsyth 		}
32374a4d8c2SCharles.Forsyth 		break;
32474a4d8c2SCharles.Forsyth 
32574a4d8c2SCharles.Forsyth 	case OLSHR:
32674a4d8c2SCharles.Forsyth 	case OASHL:
32774a4d8c2SCharles.Forsyth 	case OASHR:
32874a4d8c2SCharles.Forsyth 		o = tcom(l);
32974a4d8c2SCharles.Forsyth 		if(o | tcom(r))
33074a4d8c2SCharles.Forsyth 			goto bad;
33174a4d8c2SCharles.Forsyth 		if(tcompat(n, l->type, r->type, tand))
33274a4d8c2SCharles.Forsyth 			goto bad;
33374a4d8c2SCharles.Forsyth 		n->right = Z;
33474a4d8c2SCharles.Forsyth 		arith(n, 1);
33574a4d8c2SCharles.Forsyth 		n->right = new1(OCAST, r, Z);
33674a4d8c2SCharles.Forsyth 		n->right->type = types[TINT];
33774a4d8c2SCharles.Forsyth 		if(typeu[n->type->etype])
33874a4d8c2SCharles.Forsyth 			if(n->op == OASHR)
33974a4d8c2SCharles.Forsyth 				n->op = OLSHR;
34074a4d8c2SCharles.Forsyth 		break;
34174a4d8c2SCharles.Forsyth 
34274a4d8c2SCharles.Forsyth 	case OAND:
34374a4d8c2SCharles.Forsyth 	case OOR:
34474a4d8c2SCharles.Forsyth 	case OXOR:
34574a4d8c2SCharles.Forsyth 		o = tcom(l);
34674a4d8c2SCharles.Forsyth 		if(o | tcom(r))
34774a4d8c2SCharles.Forsyth 			goto bad;
34874a4d8c2SCharles.Forsyth 		if(tcompat(n, l->type, r->type, tand))
34974a4d8c2SCharles.Forsyth 			goto bad;
35074a4d8c2SCharles.Forsyth 		arith(n, 1);
35174a4d8c2SCharles.Forsyth 		break;
35274a4d8c2SCharles.Forsyth 
35374a4d8c2SCharles.Forsyth 	case OMOD:
35474a4d8c2SCharles.Forsyth 	case OLMOD:
35574a4d8c2SCharles.Forsyth 		o = tcom(l);
35674a4d8c2SCharles.Forsyth 		if(o | tcom(r))
35774a4d8c2SCharles.Forsyth 			goto bad;
35874a4d8c2SCharles.Forsyth 		if(tcompat(n, l->type, r->type, tand))
35974a4d8c2SCharles.Forsyth 			goto bad;
36074a4d8c2SCharles.Forsyth 		arith(n, 1);
36174a4d8c2SCharles.Forsyth 		if(typeu[n->type->etype])
36274a4d8c2SCharles.Forsyth 			n->op = OLMOD;
36374a4d8c2SCharles.Forsyth 		break;
36474a4d8c2SCharles.Forsyth 
36574a4d8c2SCharles.Forsyth 	case ONOT:
36674a4d8c2SCharles.Forsyth 		if(tcom(l))
36774a4d8c2SCharles.Forsyth 			goto bad;
36874a4d8c2SCharles.Forsyth 		if(tcompat(n, T, l->type, tnot))
36974a4d8c2SCharles.Forsyth 			goto bad;
37074a4d8c2SCharles.Forsyth 		n->type = types[TINT];
37174a4d8c2SCharles.Forsyth 		break;
37274a4d8c2SCharles.Forsyth 
37374a4d8c2SCharles.Forsyth 	case OPOS:
37474a4d8c2SCharles.Forsyth 	case ONEG:
37574a4d8c2SCharles.Forsyth 	case OCOM:
37674a4d8c2SCharles.Forsyth 		if(tcom(l))
37774a4d8c2SCharles.Forsyth 			goto bad;
37874a4d8c2SCharles.Forsyth 		n->type = l->type;
37974a4d8c2SCharles.Forsyth 		break;
38074a4d8c2SCharles.Forsyth 
38174a4d8c2SCharles.Forsyth 	case ONUL:
38274a4d8c2SCharles.Forsyth 		break;
38374a4d8c2SCharles.Forsyth 
38474a4d8c2SCharles.Forsyth 	case OIOTA:
38574a4d8c2SCharles.Forsyth 		n->type = types[TINT];
38674a4d8c2SCharles.Forsyth 		break;
38774a4d8c2SCharles.Forsyth 
38874a4d8c2SCharles.Forsyth 	case ODAS:
38974a4d8c2SCharles.Forsyth 		n->type = n->left->type;
39074a4d8c2SCharles.Forsyth 		break;
39174a4d8c2SCharles.Forsyth 
39274a4d8c2SCharles.Forsyth 	case OANDAND:
39374a4d8c2SCharles.Forsyth 	case OOROR:
39474a4d8c2SCharles.Forsyth 		o = tcom(l);
39574a4d8c2SCharles.Forsyth 		if(o | tcom(r))
39674a4d8c2SCharles.Forsyth 			goto bad;
39774a4d8c2SCharles.Forsyth 		if(tcompat(n, T, l->type, tnot) |
39874a4d8c2SCharles.Forsyth 		   tcompat(n, T, r->type, tnot))
39974a4d8c2SCharles.Forsyth 			goto bad;
40074a4d8c2SCharles.Forsyth 		n->type = types[TINT];
40174a4d8c2SCharles.Forsyth 		break;
40274a4d8c2SCharles.Forsyth 
40374a4d8c2SCharles.Forsyth 	case OCOMMA:
40474a4d8c2SCharles.Forsyth 		o = tcom(l);
40574a4d8c2SCharles.Forsyth 		if(o | tcom(r))
40674a4d8c2SCharles.Forsyth 			goto bad;
40774a4d8c2SCharles.Forsyth 		n->type = r->type;
40874a4d8c2SCharles.Forsyth 		break;
40974a4d8c2SCharles.Forsyth 
41074a4d8c2SCharles.Forsyth 
41174a4d8c2SCharles.Forsyth 	case OSIGN:	/* extension signof(type) returns a hash */
41274a4d8c2SCharles.Forsyth 		if(l != Z) {
41374a4d8c2SCharles.Forsyth 			if(l->op != OSTRING && l->op != OLSTRING)
41474a4d8c2SCharles.Forsyth 				if(tcomo(l, 0))
41574a4d8c2SCharles.Forsyth 					goto bad;
41674a4d8c2SCharles.Forsyth 			if(l->op == OBIT) {
41774a4d8c2SCharles.Forsyth 				diag(n, "signof bitfield");
41874a4d8c2SCharles.Forsyth 				goto bad;
41974a4d8c2SCharles.Forsyth 			}
42074a4d8c2SCharles.Forsyth 			n->type = l->type;
42174a4d8c2SCharles.Forsyth 		}
42274a4d8c2SCharles.Forsyth 		if(n->type == T)
42374a4d8c2SCharles.Forsyth 			goto bad;
42474a4d8c2SCharles.Forsyth 		if(n->type->width < 0) {
42574a4d8c2SCharles.Forsyth 			diag(n, "signof undefined type");
42674a4d8c2SCharles.Forsyth 			goto bad;
42774a4d8c2SCharles.Forsyth 		}
42874a4d8c2SCharles.Forsyth 		n->right = ncopy(n);
42974a4d8c2SCharles.Forsyth 		n->op = OCONST;
43074a4d8c2SCharles.Forsyth 		n->left = Z;
43174a4d8c2SCharles.Forsyth 		/* n->right = Z; */
43274a4d8c2SCharles.Forsyth 		n->vconst = convvtox(signature(n->type, 10), TULONG);
43374a4d8c2SCharles.Forsyth 		n->type = types[TULONG];
43474a4d8c2SCharles.Forsyth 		break;
43574a4d8c2SCharles.Forsyth 
43674a4d8c2SCharles.Forsyth 	case OSIZE:
43774a4d8c2SCharles.Forsyth 		if(l != Z) {
43874a4d8c2SCharles.Forsyth 			if(l->op != OSTRING && l->op != OLSTRING)
43974a4d8c2SCharles.Forsyth 				if(tcomo(l, 0))
44074a4d8c2SCharles.Forsyth 					goto bad;
44174a4d8c2SCharles.Forsyth 			if(l->op == OBIT) {
44274a4d8c2SCharles.Forsyth 				diag(n, "sizeof bitfield");
44374a4d8c2SCharles.Forsyth 				goto bad;
44474a4d8c2SCharles.Forsyth 			}
44574a4d8c2SCharles.Forsyth 			n->type = l->type;
44674a4d8c2SCharles.Forsyth 		}
44774a4d8c2SCharles.Forsyth 		if(n->type == T)
44874a4d8c2SCharles.Forsyth 			goto bad;
44974a4d8c2SCharles.Forsyth 		if(n->type->width <= 0) {
45074a4d8c2SCharles.Forsyth 			diag(n, "sizeof undefined type");
45174a4d8c2SCharles.Forsyth 			goto bad;
45274a4d8c2SCharles.Forsyth 		}
45374a4d8c2SCharles.Forsyth 		if(n->type->etype == TFUNC) {
45474a4d8c2SCharles.Forsyth 			diag(n, "sizeof function");
45574a4d8c2SCharles.Forsyth 			goto bad;
45674a4d8c2SCharles.Forsyth 		}
45774a4d8c2SCharles.Forsyth 		n->right = ncopy(n);
45874a4d8c2SCharles.Forsyth 		n->op = OCONST;
45974a4d8c2SCharles.Forsyth 		n->left = Z;
46074a4d8c2SCharles.Forsyth 		/* n->right = Z; */
46174a4d8c2SCharles.Forsyth 		n->vconst = convvtox(n->type->width, TINT);
46274a4d8c2SCharles.Forsyth 		n->type = types[TINT];
46374a4d8c2SCharles.Forsyth 		break;
46474a4d8c2SCharles.Forsyth 
46574a4d8c2SCharles.Forsyth 	case OFUNC:
46674a4d8c2SCharles.Forsyth 		o = tcomo(l, 0);
46774a4d8c2SCharles.Forsyth 		if(o)
46874a4d8c2SCharles.Forsyth 			goto bad;
46974a4d8c2SCharles.Forsyth 		if(l->type->etype == TIND && l->type->link->etype == TFUNC) {
47074a4d8c2SCharles.Forsyth 			l = new1(OIND, l, Z);
47174a4d8c2SCharles.Forsyth 			l->type = l->left->type->link;
47274a4d8c2SCharles.Forsyth 			n->left = l;
47374a4d8c2SCharles.Forsyth 		}
47474a4d8c2SCharles.Forsyth 		if(tcompat(n, T, l->type, tfunct))
47574a4d8c2SCharles.Forsyth 			goto bad;
47674a4d8c2SCharles.Forsyth 		if(o | tcoma(l, r, l->type->down, 1))
47774a4d8c2SCharles.Forsyth 			goto bad;
47874a4d8c2SCharles.Forsyth 		n->type = l->type->link;
47974a4d8c2SCharles.Forsyth 		if(1)
48074a4d8c2SCharles.Forsyth 			if(l->type->down == T || l->type->down->etype == TOLD) {
48174a4d8c2SCharles.Forsyth 				nerrors--;
48274a4d8c2SCharles.Forsyth 				diag(n, "function args not checked: %F", l);
48374a4d8c2SCharles.Forsyth 			}
48474a4d8c2SCharles.Forsyth 		dpcheck(n);
48574a4d8c2SCharles.Forsyth 		break;
48674a4d8c2SCharles.Forsyth 
48774a4d8c2SCharles.Forsyth 	case ONAME:
48874a4d8c2SCharles.Forsyth 		if(n->type == T) {
48974a4d8c2SCharles.Forsyth 			diag(n, "name not declared: %F", n);
49074a4d8c2SCharles.Forsyth 			goto bad;
49174a4d8c2SCharles.Forsyth 		}
49274a4d8c2SCharles.Forsyth 		if(n->type->etype == TENUM) {
49374a4d8c2SCharles.Forsyth 			if(n->sym->tenum->etype == TIND){
49474a4d8c2SCharles.Forsyth 				/* n->op = OSTRING; */
49574a4d8c2SCharles.Forsyth 				n->type = n->sym->tenum;
49674a4d8c2SCharles.Forsyth 				/* n->cstring = n->sym->sconst; */
49774a4d8c2SCharles.Forsyth 				break;
49874a4d8c2SCharles.Forsyth 			}
49974a4d8c2SCharles.Forsyth 			n->left = ncopy(n);
50074a4d8c2SCharles.Forsyth 			n->op = OCONST;
50174a4d8c2SCharles.Forsyth 			n->type = n->sym->tenum;
50274a4d8c2SCharles.Forsyth 			if(!typefd[n->type->etype])
50374a4d8c2SCharles.Forsyth 				n->vconst = n->sym->vconst;
50474a4d8c2SCharles.Forsyth 			else{
50574a4d8c2SCharles.Forsyth 				n->fconst = n->sym->fconst;
50674a4d8c2SCharles.Forsyth 				n->cstring = n->sym->cstring;
50774a4d8c2SCharles.Forsyth 			}
50874a4d8c2SCharles.Forsyth 			break;
50974a4d8c2SCharles.Forsyth 		}
51074a4d8c2SCharles.Forsyth 		break;
51174a4d8c2SCharles.Forsyth 
51274a4d8c2SCharles.Forsyth 	case OLSTRING:
51374a4d8c2SCharles.Forsyth 	case OSTRING:
51474a4d8c2SCharles.Forsyth 	case OCONST:
51574a4d8c2SCharles.Forsyth 		break;
51674a4d8c2SCharles.Forsyth 
51774a4d8c2SCharles.Forsyth 	case ODOT:
51874a4d8c2SCharles.Forsyth 		if(tcom(l))
51974a4d8c2SCharles.Forsyth 			goto bad;
52074a4d8c2SCharles.Forsyth 		if(tcompat(n, T, l->type, tdot))
52174a4d8c2SCharles.Forsyth 			goto bad;
52274a4d8c2SCharles.Forsyth 		if(tcomd(n, l->type))
52374a4d8c2SCharles.Forsyth 			goto bad;
52474a4d8c2SCharles.Forsyth 		break;
52574a4d8c2SCharles.Forsyth 
52674a4d8c2SCharles.Forsyth 	case ODOTIND:
52774a4d8c2SCharles.Forsyth 		if(tcom(l))
52874a4d8c2SCharles.Forsyth 			goto bad;
52974a4d8c2SCharles.Forsyth 		if(tcompat(n, T, l->type, tindir))
53074a4d8c2SCharles.Forsyth 			goto bad;
53174a4d8c2SCharles.Forsyth 		if(tcompat(n, T, l->type->link, tdot))
53274a4d8c2SCharles.Forsyth 			goto bad;
53374a4d8c2SCharles.Forsyth 		if(tcomd(n, l->type->link))
53474a4d8c2SCharles.Forsyth 			goto bad;
53574a4d8c2SCharles.Forsyth 		break;
53674a4d8c2SCharles.Forsyth 
53774a4d8c2SCharles.Forsyth 	case OARRIND:
53874a4d8c2SCharles.Forsyth 		if(tcom(l))
53974a4d8c2SCharles.Forsyth 			goto bad;
54074a4d8c2SCharles.Forsyth 		if(tcompat(n, T, l->type, tindir))
54174a4d8c2SCharles.Forsyth 			goto bad;
54274a4d8c2SCharles.Forsyth 		n->type = l->type->link;
54374a4d8c2SCharles.Forsyth 		if(tcom(r))
54474a4d8c2SCharles.Forsyth 			goto bad;
54574a4d8c2SCharles.Forsyth 		break;
54674a4d8c2SCharles.Forsyth 
54774a4d8c2SCharles.Forsyth 	case OADDR:
54874a4d8c2SCharles.Forsyth 		if(tcomo(l, ADDROP))
54974a4d8c2SCharles.Forsyth 			goto bad;
55074a4d8c2SCharles.Forsyth 		if(tlvalue(l))
55174a4d8c2SCharles.Forsyth 			goto bad;
55274a4d8c2SCharles.Forsyth 		if(l->type->nbits) {
55374a4d8c2SCharles.Forsyth 			diag(n, "address of a bit field");
55474a4d8c2SCharles.Forsyth 			goto bad;
55574a4d8c2SCharles.Forsyth 		}
55674a4d8c2SCharles.Forsyth 		if(l->op == OREGISTER) {
55774a4d8c2SCharles.Forsyth 			diag(n, "address of a register");
55874a4d8c2SCharles.Forsyth 			goto bad;
55974a4d8c2SCharles.Forsyth 		}
56074a4d8c2SCharles.Forsyth 		n->type = typ1(TIND, l->type);
56174a4d8c2SCharles.Forsyth 		n->type->width = types[TIND]->width;
56274a4d8c2SCharles.Forsyth 		break;
56374a4d8c2SCharles.Forsyth 
56474a4d8c2SCharles.Forsyth 	case OIND:
56574a4d8c2SCharles.Forsyth 		if(tcom(l))
56674a4d8c2SCharles.Forsyth 			goto bad;
56774a4d8c2SCharles.Forsyth 		if(tcompat(n, T, l->type, tindir))
56874a4d8c2SCharles.Forsyth 			goto bad;
56974a4d8c2SCharles.Forsyth 		n->type = l->type->link;
57074a4d8c2SCharles.Forsyth 		break;
57174a4d8c2SCharles.Forsyth 
57274a4d8c2SCharles.Forsyth 	case OSTRUCT:
57374a4d8c2SCharles.Forsyth 		if(tcomx(n))
57474a4d8c2SCharles.Forsyth 			goto bad;
57574a4d8c2SCharles.Forsyth 		break;
57674a4d8c2SCharles.Forsyth 	}
57774a4d8c2SCharles.Forsyth 	t = n->type;
57874a4d8c2SCharles.Forsyth 	if(t == T)
57974a4d8c2SCharles.Forsyth 		goto bad;
58074a4d8c2SCharles.Forsyth 	if(t->width < 0) {
58174a4d8c2SCharles.Forsyth 		snap(t);
58274a4d8c2SCharles.Forsyth 		if(t->width < 0) {
58374a4d8c2SCharles.Forsyth 			if(typesu[t->etype] && t->tag)
58474a4d8c2SCharles.Forsyth 				diag(n, "structure not fully declared %s", t->tag->name);
58574a4d8c2SCharles.Forsyth 			else
58674a4d8c2SCharles.Forsyth 				diag(n, "structure not fully declared");
58774a4d8c2SCharles.Forsyth 			goto bad;
58874a4d8c2SCharles.Forsyth 		}
58974a4d8c2SCharles.Forsyth 	}
59074a4d8c2SCharles.Forsyth 	if(typeaf[t->etype]) {
59174a4d8c2SCharles.Forsyth 		if(f & ADDROF)
59274a4d8c2SCharles.Forsyth 			goto addaddr;
59374a4d8c2SCharles.Forsyth 		if(f & ADDROP)
59474a4d8c2SCharles.Forsyth 			warn(n, "address of array/func ignored");
59574a4d8c2SCharles.Forsyth 	}
59674a4d8c2SCharles.Forsyth 	return 0;
59774a4d8c2SCharles.Forsyth 
59874a4d8c2SCharles.Forsyth addaddr:
59974a4d8c2SCharles.Forsyth 	if(n->type->etype == TARRAY)
60074a4d8c2SCharles.Forsyth 		n->type = typ1(TIND, n->type->link);
60174a4d8c2SCharles.Forsyth 	return 0;
602*d67b7dadSforsyth #ifdef WHATEVA
60374a4d8c2SCharles.Forsyth 	if(tlvalue(n))
60474a4d8c2SCharles.Forsyth 		goto bad;
60574a4d8c2SCharles.Forsyth 	l = new1(OXXX, Z, Z);
60674a4d8c2SCharles.Forsyth 	*l = *n;
60774a4d8c2SCharles.Forsyth 	n->op = OADDR;
60874a4d8c2SCharles.Forsyth 	if(l->type->etype == TARRAY)
60974a4d8c2SCharles.Forsyth 		l->type = l->type->link;
61074a4d8c2SCharles.Forsyth 	n->left = l;
61174a4d8c2SCharles.Forsyth 	n->right = Z;
61274a4d8c2SCharles.Forsyth 	n->type = typ1(TIND, l->type);
61374a4d8c2SCharles.Forsyth 	n->type->width = types[TIND]->width;
61474a4d8c2SCharles.Forsyth 	return 0;
615*d67b7dadSforsyth #endif
61674a4d8c2SCharles.Forsyth 
61774a4d8c2SCharles.Forsyth bad:
61874a4d8c2SCharles.Forsyth 	n->type = T;
61974a4d8c2SCharles.Forsyth 	return 1;
62074a4d8c2SCharles.Forsyth }
62174a4d8c2SCharles.Forsyth 
62274a4d8c2SCharles.Forsyth int
tcoma(Node * l,Node * n,Type * t,int f)62374a4d8c2SCharles.Forsyth tcoma(Node *l, Node *n, Type *t, int f)
62474a4d8c2SCharles.Forsyth {
62574a4d8c2SCharles.Forsyth 	Node *n1;
62674a4d8c2SCharles.Forsyth 	int o;
62774a4d8c2SCharles.Forsyth 
62874a4d8c2SCharles.Forsyth 	if(t != T)
62974a4d8c2SCharles.Forsyth 	if(t->etype == TOLD || t->etype == TDOT)	/* .../old in prototype */
63074a4d8c2SCharles.Forsyth 		t = T;
63174a4d8c2SCharles.Forsyth 	if(n == Z) {
63274a4d8c2SCharles.Forsyth 		if(t != T && !sametype(t, types[TVOID])) {
63374a4d8c2SCharles.Forsyth 			diag(n, "not enough function arguments: %F", l);
63474a4d8c2SCharles.Forsyth 			return 1;
63574a4d8c2SCharles.Forsyth 		}
63674a4d8c2SCharles.Forsyth 		return 0;
63774a4d8c2SCharles.Forsyth 	}
63874a4d8c2SCharles.Forsyth 	if(n->op == OLIST) {
63974a4d8c2SCharles.Forsyth 		o = tcoma(l, n->left, t, 0);
64074a4d8c2SCharles.Forsyth 		if(t != T) {
64174a4d8c2SCharles.Forsyth 			t = t->down;
64274a4d8c2SCharles.Forsyth 			if(t == T)
64374a4d8c2SCharles.Forsyth 				t = types[TVOID];
64474a4d8c2SCharles.Forsyth 		}
64574a4d8c2SCharles.Forsyth 		return o | tcoma(l, n->right, t, 1);
64674a4d8c2SCharles.Forsyth 	}
64774a4d8c2SCharles.Forsyth 	if(f && t != T)
64874a4d8c2SCharles.Forsyth 		tcoma(l, Z, t->down, 0);
64974a4d8c2SCharles.Forsyth 	if(tcom(n) || tcompat(n, T, n->type, targ))
65074a4d8c2SCharles.Forsyth 		return 1;
65174a4d8c2SCharles.Forsyth 	if(sametype(t, types[TVOID])) {
65274a4d8c2SCharles.Forsyth 		diag(n, "too many function arguments: %F", l);
65374a4d8c2SCharles.Forsyth 		return 1;
65474a4d8c2SCharles.Forsyth 	}
65574a4d8c2SCharles.Forsyth 	if(t != T) {
65674a4d8c2SCharles.Forsyth 		typeext(t, n);
65774a4d8c2SCharles.Forsyth 		if(stcompat(nodproto, t, n->type, tasign)) {
65874a4d8c2SCharles.Forsyth 			diag(l, "argument prototype mismatch \"%T\" for \"%T\": %F",
65974a4d8c2SCharles.Forsyth 				n->type, t, l);
66074a4d8c2SCharles.Forsyth 			return 1;
66174a4d8c2SCharles.Forsyth 		}
66274a4d8c2SCharles.Forsyth 		switch(t->etype) {
66374a4d8c2SCharles.Forsyth 		case TCHAR:
66474a4d8c2SCharles.Forsyth 		case TSHORT:
66574a4d8c2SCharles.Forsyth 			/* t = types[TINT]; */
66674a4d8c2SCharles.Forsyth 			break;
66774a4d8c2SCharles.Forsyth 
66874a4d8c2SCharles.Forsyth 		case TUCHAR:
66974a4d8c2SCharles.Forsyth 		case TUSHORT:
67074a4d8c2SCharles.Forsyth 			/* t = types[TUINT]; */
67174a4d8c2SCharles.Forsyth 			break;
67274a4d8c2SCharles.Forsyth 		}
67374a4d8c2SCharles.Forsyth 	} else {
67474a4d8c2SCharles.Forsyth 		switch(n->type->etype)
67574a4d8c2SCharles.Forsyth 		{
67674a4d8c2SCharles.Forsyth 		case TCHAR:
67774a4d8c2SCharles.Forsyth 		case TSHORT:
67874a4d8c2SCharles.Forsyth 			/* t = types[TINT]; */
67974a4d8c2SCharles.Forsyth 			t = n->type;
68074a4d8c2SCharles.Forsyth 			break;
68174a4d8c2SCharles.Forsyth 
68274a4d8c2SCharles.Forsyth 		case TUCHAR:
68374a4d8c2SCharles.Forsyth 		case TUSHORT:
68474a4d8c2SCharles.Forsyth 			/* t = types[TUINT]; */
68574a4d8c2SCharles.Forsyth 			t = n->type;
68674a4d8c2SCharles.Forsyth 			break;
68774a4d8c2SCharles.Forsyth 
68874a4d8c2SCharles.Forsyth 		case TFLOAT:
68974a4d8c2SCharles.Forsyth 			/* t = types[TDOUBLE]; */
69074a4d8c2SCharles.Forsyth 			t = n->type;
69174a4d8c2SCharles.Forsyth 		}
69274a4d8c2SCharles.Forsyth 	}
69374a4d8c2SCharles.Forsyth 	if(t != T && !sametype(t, n->type)) {
69474a4d8c2SCharles.Forsyth 		n1 = new1(OXXX, Z, Z);
69574a4d8c2SCharles.Forsyth 		*n1 = *n;
69674a4d8c2SCharles.Forsyth 		n->op = OCAST;
69774a4d8c2SCharles.Forsyth 		n->left = n1;
69874a4d8c2SCharles.Forsyth 		n->right = Z;
69974a4d8c2SCharles.Forsyth 		n->type = t;
70074a4d8c2SCharles.Forsyth 	}
70174a4d8c2SCharles.Forsyth 	return 0;
70274a4d8c2SCharles.Forsyth }
70374a4d8c2SCharles.Forsyth 
70474a4d8c2SCharles.Forsyth int
tcomd(Node * n,Type * t)70574a4d8c2SCharles.Forsyth tcomd(Node *n, Type *t)
70674a4d8c2SCharles.Forsyth {
70774a4d8c2SCharles.Forsyth 	long o;
70874a4d8c2SCharles.Forsyth 
70974a4d8c2SCharles.Forsyth 	o = 0;
71074a4d8c2SCharles.Forsyth 	/* t = n->left->type; */
71174a4d8c2SCharles.Forsyth 	for(;;) {
71274a4d8c2SCharles.Forsyth 		t = dotsearch(n->sym, t->link, n);
71374a4d8c2SCharles.Forsyth 		if(t == T) {
71474a4d8c2SCharles.Forsyth 			diag(n, "not a member of struct/union: %F", n);
71574a4d8c2SCharles.Forsyth 			return 1;
71674a4d8c2SCharles.Forsyth 		}
71774a4d8c2SCharles.Forsyth 		o += t->offset;
71874a4d8c2SCharles.Forsyth 		if(t->sym == n->sym)
71974a4d8c2SCharles.Forsyth 			break;
72074a4d8c2SCharles.Forsyth 		if(sametype(t, n->sym->type))
72174a4d8c2SCharles.Forsyth 			break;
72274a4d8c2SCharles.Forsyth 	}
72374a4d8c2SCharles.Forsyth 	n->type = t;
72474a4d8c2SCharles.Forsyth 	return 0;
72574a4d8c2SCharles.Forsyth }
72674a4d8c2SCharles.Forsyth 
72774a4d8c2SCharles.Forsyth int
tcomx(Node * n)72874a4d8c2SCharles.Forsyth tcomx(Node *n)
72974a4d8c2SCharles.Forsyth {
73074a4d8c2SCharles.Forsyth 	Type *t;
73174a4d8c2SCharles.Forsyth 	Node *l, *r, **ar, **al;
73274a4d8c2SCharles.Forsyth 	int e;
73374a4d8c2SCharles.Forsyth 
73474a4d8c2SCharles.Forsyth 	e = 0;
73574a4d8c2SCharles.Forsyth 	if(n->type->etype != TSTRUCT) {
73674a4d8c2SCharles.Forsyth 		diag(n, "constructor must be a structure");
73774a4d8c2SCharles.Forsyth 		return 1;
73874a4d8c2SCharles.Forsyth 	}
73974a4d8c2SCharles.Forsyth 	l = invert(n->left);
74074a4d8c2SCharles.Forsyth 	n->left = l;
74174a4d8c2SCharles.Forsyth 	al = &n->left;
74274a4d8c2SCharles.Forsyth 	for(t = n->type->link; t != T; t = t->down) {
74374a4d8c2SCharles.Forsyth 		if(l == Z) {
74474a4d8c2SCharles.Forsyth 			diag(n, "constructor list too short");
74574a4d8c2SCharles.Forsyth 			return 1;
74674a4d8c2SCharles.Forsyth 		}
74774a4d8c2SCharles.Forsyth 		if(l->op == OLIST) {
74874a4d8c2SCharles.Forsyth 			r = l->left;
74974a4d8c2SCharles.Forsyth 			ar = &l->left;
75074a4d8c2SCharles.Forsyth 			al = &l->right;
75174a4d8c2SCharles.Forsyth 			l = l->right;
75274a4d8c2SCharles.Forsyth 		} else {
75374a4d8c2SCharles.Forsyth 			r = l;
75474a4d8c2SCharles.Forsyth 			ar = al;
75574a4d8c2SCharles.Forsyth 			l = Z;
75674a4d8c2SCharles.Forsyth 		}
75774a4d8c2SCharles.Forsyth 		if(tcom(r))
75874a4d8c2SCharles.Forsyth 			e++;
75974a4d8c2SCharles.Forsyth 		typeext(t, r);
76074a4d8c2SCharles.Forsyth 		if(tcompat(n, t, r->type, tasign))
76174a4d8c2SCharles.Forsyth 			e++;
76274a4d8c2SCharles.Forsyth 		constas(n, t, r->type);
76374a4d8c2SCharles.Forsyth 		if(!e && !sametype(t, r->type)) {
76474a4d8c2SCharles.Forsyth 			r = new1(OCAST, r, Z);
76574a4d8c2SCharles.Forsyth 			r->type = t;
76674a4d8c2SCharles.Forsyth 			*ar = r;
76774a4d8c2SCharles.Forsyth 		}
76874a4d8c2SCharles.Forsyth 	}
76974a4d8c2SCharles.Forsyth 	if(l != Z) {
77074a4d8c2SCharles.Forsyth 		diag(n, "constructor list too long");
77174a4d8c2SCharles.Forsyth 		return 1;
77274a4d8c2SCharles.Forsyth 	}
77374a4d8c2SCharles.Forsyth 	return e;
77474a4d8c2SCharles.Forsyth }
77574a4d8c2SCharles.Forsyth 
77674a4d8c2SCharles.Forsyth int
tlvalue(Node * n)77774a4d8c2SCharles.Forsyth tlvalue(Node *n)
77874a4d8c2SCharles.Forsyth {
77974a4d8c2SCharles.Forsyth 
78074a4d8c2SCharles.Forsyth 	if(0) {
78174a4d8c2SCharles.Forsyth 		diag(n, "not an l-value");
78274a4d8c2SCharles.Forsyth 		return 1;
78374a4d8c2SCharles.Forsyth 	}
78474a4d8c2SCharles.Forsyth 	return 0;
78574a4d8c2SCharles.Forsyth }
78674a4d8c2SCharles.Forsyth 
78774a4d8c2SCharles.Forsyth /*
78874a4d8c2SCharles.Forsyth  *	general rewrite
78974a4d8c2SCharles.Forsyth  *	(IND(ADDR x)) ==> x
79074a4d8c2SCharles.Forsyth  *	(ADDR(IND x)) ==> x
79174a4d8c2SCharles.Forsyth  *	remove some zero operands
79274a4d8c2SCharles.Forsyth  *	remove no op casts
79374a4d8c2SCharles.Forsyth  *	evaluate constants
79474a4d8c2SCharles.Forsyth  */
79574a4d8c2SCharles.Forsyth void
ccom(Node * n)79674a4d8c2SCharles.Forsyth ccom(Node *n)
79774a4d8c2SCharles.Forsyth {
79874a4d8c2SCharles.Forsyth 	Node *l, *r;
79974a4d8c2SCharles.Forsyth 	int t;
80074a4d8c2SCharles.Forsyth 
80174a4d8c2SCharles.Forsyth 	if(n == Z)
80274a4d8c2SCharles.Forsyth 		return;
80374a4d8c2SCharles.Forsyth 	l = n->left;
80474a4d8c2SCharles.Forsyth 	r = n->right;
80574a4d8c2SCharles.Forsyth 	switch(n->op) {
80674a4d8c2SCharles.Forsyth 
80774a4d8c2SCharles.Forsyth 	case OAS:
80874a4d8c2SCharles.Forsyth 	case OASD:
80974a4d8c2SCharles.Forsyth 	case OASXOR:
81074a4d8c2SCharles.Forsyth 	case OASAND:
81174a4d8c2SCharles.Forsyth 	case OASOR:
81274a4d8c2SCharles.Forsyth 	case OASMOD:
81374a4d8c2SCharles.Forsyth 	case OASLMOD:
81474a4d8c2SCharles.Forsyth 	case OASLSHR:
81574a4d8c2SCharles.Forsyth 	case OASASHR:
81674a4d8c2SCharles.Forsyth 	case OASASHL:
81774a4d8c2SCharles.Forsyth 	case OASDIV:
81874a4d8c2SCharles.Forsyth 	case OASLDIV:
81974a4d8c2SCharles.Forsyth 	case OASMUL:
82074a4d8c2SCharles.Forsyth 	case OASLMUL:
82174a4d8c2SCharles.Forsyth 	case OASSUB:
82274a4d8c2SCharles.Forsyth 	case OASADD:
82374a4d8c2SCharles.Forsyth 		ccom(l);
82474a4d8c2SCharles.Forsyth 		ccom(r);
82574a4d8c2SCharles.Forsyth 		if(n->op == OASLSHR || n->op == OASASHR || n->op == OASASHL)
82674a4d8c2SCharles.Forsyth 		if(r->op == OCONST) {
82774a4d8c2SCharles.Forsyth 			t = n->type->width * 8;	/* bits per byte */
82874a4d8c2SCharles.Forsyth 			if(r->vconst >= t || r->vconst < 0)
82974a4d8c2SCharles.Forsyth 				warn(n, "stupid shift: %lld", r->vconst);
83074a4d8c2SCharles.Forsyth 		}
83174a4d8c2SCharles.Forsyth 		break;
83274a4d8c2SCharles.Forsyth 
83374a4d8c2SCharles.Forsyth 	case OCAST:
83474a4d8c2SCharles.Forsyth 		ccom(l);
83574a4d8c2SCharles.Forsyth 		if(l->op == OCONST) {
83674a4d8c2SCharles.Forsyth 			evconst(n);
83774a4d8c2SCharles.Forsyth 			if(n->op == OCONST)
83874a4d8c2SCharles.Forsyth 				break;
83974a4d8c2SCharles.Forsyth 		}
84074a4d8c2SCharles.Forsyth 		if(nocast(l->type, n->type)) {
84174a4d8c2SCharles.Forsyth 			l->type = n->type;
84274a4d8c2SCharles.Forsyth 			*n = *l;
84374a4d8c2SCharles.Forsyth 		}
84474a4d8c2SCharles.Forsyth 		break;
84574a4d8c2SCharles.Forsyth 
84674a4d8c2SCharles.Forsyth 	case OCOND:
84774a4d8c2SCharles.Forsyth 		ccom(l);
84874a4d8c2SCharles.Forsyth 		ccom(r);
84974a4d8c2SCharles.Forsyth 		break;
85074a4d8c2SCharles.Forsyth 
85174a4d8c2SCharles.Forsyth 	case OREGISTER:
85274a4d8c2SCharles.Forsyth 	case OINDREG:
85374a4d8c2SCharles.Forsyth 	case OCONST:
85474a4d8c2SCharles.Forsyth 	case ONAME:
85574a4d8c2SCharles.Forsyth 		break;
85674a4d8c2SCharles.Forsyth 
85774a4d8c2SCharles.Forsyth 	case OADDR:
85874a4d8c2SCharles.Forsyth 		ccom(l);
85974a4d8c2SCharles.Forsyth 		/* l->etype = TVOID; */
86074a4d8c2SCharles.Forsyth 		if(l->op == OIND) {
86174a4d8c2SCharles.Forsyth 			l->left->type = n->type;
86274a4d8c2SCharles.Forsyth 			*n = *l->left;
86374a4d8c2SCharles.Forsyth 			break;
86474a4d8c2SCharles.Forsyth 		}
86574a4d8c2SCharles.Forsyth 		goto common;
86674a4d8c2SCharles.Forsyth 
86774a4d8c2SCharles.Forsyth 	case OIND:
86874a4d8c2SCharles.Forsyth 		ccom(l);
86974a4d8c2SCharles.Forsyth 		if(l->op == OADDR) {
87074a4d8c2SCharles.Forsyth 			l->left->type = n->type;
87174a4d8c2SCharles.Forsyth 			*n = *l->left;
87274a4d8c2SCharles.Forsyth 			break;
87374a4d8c2SCharles.Forsyth 		}
87474a4d8c2SCharles.Forsyth 		goto common;
87574a4d8c2SCharles.Forsyth 
87674a4d8c2SCharles.Forsyth 	case OEQ:
87774a4d8c2SCharles.Forsyth 	case ONE:
87874a4d8c2SCharles.Forsyth 
87974a4d8c2SCharles.Forsyth 	case OLE:
88074a4d8c2SCharles.Forsyth 	case OGE:
88174a4d8c2SCharles.Forsyth 	case OLT:
88274a4d8c2SCharles.Forsyth 	case OGT:
88374a4d8c2SCharles.Forsyth 
88474a4d8c2SCharles.Forsyth 	case OLS:
88574a4d8c2SCharles.Forsyth 	case OHS:
88674a4d8c2SCharles.Forsyth 	case OLO:
88774a4d8c2SCharles.Forsyth 	case OHI:
88874a4d8c2SCharles.Forsyth 		ccom(l);
88974a4d8c2SCharles.Forsyth 		ccom(r);
89074a4d8c2SCharles.Forsyth 		relcon(l, r);
89174a4d8c2SCharles.Forsyth 		relcon(r, l);
89274a4d8c2SCharles.Forsyth 		goto common;
89374a4d8c2SCharles.Forsyth 
89474a4d8c2SCharles.Forsyth 	case OASHR:
89574a4d8c2SCharles.Forsyth 	case OASHL:
89674a4d8c2SCharles.Forsyth 	case OLSHR:
89774a4d8c2SCharles.Forsyth 		ccom(l);
89874a4d8c2SCharles.Forsyth 		ccom(r);
89974a4d8c2SCharles.Forsyth 		if(r->op == OCONST) {
90074a4d8c2SCharles.Forsyth 			t = n->type->width * 8;	/* bits per byte */
90174a4d8c2SCharles.Forsyth 			if(r->vconst >= t || r->vconst <= -t)
90274a4d8c2SCharles.Forsyth 				warn(n, "stupid shift: %lld", r->vconst);
90374a4d8c2SCharles.Forsyth 		}
90474a4d8c2SCharles.Forsyth 		goto common;
90574a4d8c2SCharles.Forsyth 
90674a4d8c2SCharles.Forsyth 	default:
90774a4d8c2SCharles.Forsyth 		if(l != Z)
90874a4d8c2SCharles.Forsyth 			ccom(l);
90974a4d8c2SCharles.Forsyth 		if(r != Z)
91074a4d8c2SCharles.Forsyth 			ccom(r);
91174a4d8c2SCharles.Forsyth 	common:
91274a4d8c2SCharles.Forsyth 		if(l != Z)
91374a4d8c2SCharles.Forsyth 		if(l->op != OCONST)
91474a4d8c2SCharles.Forsyth 			break;
91574a4d8c2SCharles.Forsyth 		if(r != Z)
91674a4d8c2SCharles.Forsyth 		if(r->op != OCONST)
91774a4d8c2SCharles.Forsyth 			break;
91874a4d8c2SCharles.Forsyth 		evconst(n);
91974a4d8c2SCharles.Forsyth 	}
92074a4d8c2SCharles.Forsyth }
921