xref: /plan9/sys/src/cmd/cc/dcl.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include "cc.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier Node*
43e12c5d1SDavid du Colombier dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n)
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier 	Sym *s;
73e12c5d1SDavid du Colombier 	Node *n1;
83e12c5d1SDavid du Colombier 	long v;
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier 	nearln = lineno;
113e12c5d1SDavid du Colombier 	lastfield = 0;
123e12c5d1SDavid du Colombier 
133e12c5d1SDavid du Colombier loop:
143e12c5d1SDavid du Colombier 	if(n != Z)
153e12c5d1SDavid du Colombier 	switch(n->op) {
163e12c5d1SDavid du Colombier 	default:
173e12c5d1SDavid du Colombier 		diag(n, "unknown declarator: %O", n->op);
183e12c5d1SDavid du Colombier 		break;
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier 	case OARRAY:
213e12c5d1SDavid du Colombier 		t = typ(TARRAY, t);
223e12c5d1SDavid du Colombier 		t->width = 0;
233e12c5d1SDavid du Colombier 		n1 = n->right;
243e12c5d1SDavid du Colombier 		n = n->left;
253e12c5d1SDavid du Colombier 		if(n1 != Z) {
263e12c5d1SDavid du Colombier 			complex(n1);
273e12c5d1SDavid du Colombier 			v = -1;
283e12c5d1SDavid du Colombier 			if(n1->op == OCONST)
29*219b2ee8SDavid du Colombier 				v = n1->vconst;
303e12c5d1SDavid du Colombier 			if(v <= 0) {
313e12c5d1SDavid du Colombier 				diag(n, "array size must be a positive constant");
323e12c5d1SDavid du Colombier 				v = 1;
333e12c5d1SDavid du Colombier 			}
343e12c5d1SDavid du Colombier 			t->width = v * t->link->width;
353e12c5d1SDavid du Colombier 		}
363e12c5d1SDavid du Colombier 		goto loop;
373e12c5d1SDavid du Colombier 
383e12c5d1SDavid du Colombier 	case OIND:
393e12c5d1SDavid du Colombier 		t = typ(TIND, t);
403e12c5d1SDavid du Colombier 		n = n->left;
413e12c5d1SDavid du Colombier 		goto loop;
423e12c5d1SDavid du Colombier 
433e12c5d1SDavid du Colombier 	case OFUNC:
443e12c5d1SDavid du Colombier 		t = typ(TFUNC, t);
453e12c5d1SDavid du Colombier 		t->down = fnproto(n);
463e12c5d1SDavid du Colombier 		n = n->left;
473e12c5d1SDavid du Colombier 		goto loop;
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier 	case OBIT:
503e12c5d1SDavid du Colombier 		n1 = n->right;
513e12c5d1SDavid du Colombier 		complex(n1);
523e12c5d1SDavid du Colombier 		lastfield = -1;
533e12c5d1SDavid du Colombier 		if(n1->op == OCONST)
54*219b2ee8SDavid du Colombier 			lastfield = n1->vconst;
553e12c5d1SDavid du Colombier 		if(lastfield < 0) {
563e12c5d1SDavid du Colombier 			diag(n, "field width must be non-negative constant");
573e12c5d1SDavid du Colombier 			lastfield = 1;
583e12c5d1SDavid du Colombier 		}
593e12c5d1SDavid du Colombier 		if(lastfield == 0) {
603e12c5d1SDavid du Colombier 			lastbit = 0;
613e12c5d1SDavid du Colombier 			firstbit = 1;
623e12c5d1SDavid du Colombier 			if(n->left != Z) {
633e12c5d1SDavid du Colombier 				diag(n, "zero width named field");
643e12c5d1SDavid du Colombier 				lastfield = 1;
653e12c5d1SDavid du Colombier 			}
663e12c5d1SDavid du Colombier 		}
67*219b2ee8SDavid du Colombier 		if(!typei[t->etype]) {
683e12c5d1SDavid du Colombier 			diag(n, "field type must be int-like");
693e12c5d1SDavid du Colombier 			t = tint;
703e12c5d1SDavid du Colombier 			lastfield = 1;
713e12c5d1SDavid du Colombier 		}
723e12c5d1SDavid du Colombier 		if(lastfield > tfield->width*8) {
733e12c5d1SDavid du Colombier 			diag(n, "field width larger than field unit");
743e12c5d1SDavid du Colombier 			lastfield = 1;
753e12c5d1SDavid du Colombier 		}
763e12c5d1SDavid du Colombier 		lastbit += lastfield;
773e12c5d1SDavid du Colombier 		if(lastbit > tfield->width*8) {
783e12c5d1SDavid du Colombier 			lastbit = lastfield;
793e12c5d1SDavid du Colombier 			firstbit = 1;
803e12c5d1SDavid du Colombier 		}
813e12c5d1SDavid du Colombier 		n = n->left;
823e12c5d1SDavid du Colombier 		goto loop;
833e12c5d1SDavid du Colombier 
843e12c5d1SDavid du Colombier 	case ONAME:
853e12c5d1SDavid du Colombier 		if(f == NODECL)
863e12c5d1SDavid du Colombier 			break;
873e12c5d1SDavid du Colombier 		s = n->sym;
883e12c5d1SDavid du Colombier 		(*f)(c, t, s);
893e12c5d1SDavid du Colombier 		if(s->class == CLOCAL)
903e12c5d1SDavid du Colombier 			s = mkstatic(s);
913e12c5d1SDavid du Colombier 		firstbit = 0;
923e12c5d1SDavid du Colombier 		n->sym = s;
933e12c5d1SDavid du Colombier 		n->type = s->type;
94*219b2ee8SDavid du Colombier 		n->xoffset = s->offset;
953e12c5d1SDavid du Colombier 		n->class = s->class;
963e12c5d1SDavid du Colombier 		n->etype = TVOID;
973e12c5d1SDavid du Colombier 		if(n->type != T)
983e12c5d1SDavid du Colombier 			n->etype = n->type->etype;
993e12c5d1SDavid du Colombier 		if(debug['d'])
1003e12c5d1SDavid du Colombier 			dbgdecl(s);
101*219b2ee8SDavid du Colombier 		acidvar(s);
1023e12c5d1SDavid du Colombier 		s->varlineno = lineno;
1033e12c5d1SDavid du Colombier 		break;
1043e12c5d1SDavid du Colombier 	}
1053e12c5d1SDavid du Colombier 	lastdcl = t;
1063e12c5d1SDavid du Colombier 	return n;
1073e12c5d1SDavid du Colombier }
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier Sym*
1103e12c5d1SDavid du Colombier mkstatic(Sym *s)
1113e12c5d1SDavid du Colombier {
1123e12c5d1SDavid du Colombier 	Sym *s1;
1133e12c5d1SDavid du Colombier 
1143e12c5d1SDavid du Colombier 	if(s->class != CLOCAL)
1153e12c5d1SDavid du Colombier 		return s;
116*219b2ee8SDavid du Colombier 	snprint(symb, NSYMB, "%s$%d", s->name, s->block);
1173e12c5d1SDavid du Colombier 	s1 = lookup();
1183e12c5d1SDavid du Colombier 	if(s1->class != CSTATIC) {
1193e12c5d1SDavid du Colombier 		s1->type = s->type;
1203e12c5d1SDavid du Colombier 		s1->offset = s->offset;
1213e12c5d1SDavid du Colombier 		s1->block = s->block;
1223e12c5d1SDavid du Colombier 		s1->class = CSTATIC;
1233e12c5d1SDavid du Colombier 	}
1243e12c5d1SDavid du Colombier 	return s1;
1253e12c5d1SDavid du Colombier }
1263e12c5d1SDavid du Colombier 
1273e12c5d1SDavid du Colombier /*
1283e12c5d1SDavid du Colombier  * make a copy of a typedef
129*219b2ee8SDavid du Colombier  * the problem is to split out incomplete
1303e12c5d1SDavid du Colombier  * arrays so that it is in the variable
1313e12c5d1SDavid du Colombier  * rather than the typedef.
1323e12c5d1SDavid du Colombier  */
1333e12c5d1SDavid du Colombier Type*
1343e12c5d1SDavid du Colombier tcopy(Type *t)
1353e12c5d1SDavid du Colombier {
1363e12c5d1SDavid du Colombier 	Type *tl, *tx;
1373e12c5d1SDavid du Colombier 	int et;
1383e12c5d1SDavid du Colombier 
1393e12c5d1SDavid du Colombier 	if(t == T)
1403e12c5d1SDavid du Colombier 		return t;
1413e12c5d1SDavid du Colombier 	et = t->etype;
1423e12c5d1SDavid du Colombier 	if(typesu[et])
1433e12c5d1SDavid du Colombier 		return t;
1443e12c5d1SDavid du Colombier 	tl = tcopy(t->link);
1453e12c5d1SDavid du Colombier 	if(tl != t->link ||
1463e12c5d1SDavid du Colombier 	  (et == TARRAY && t->width == 0)) {
1473e12c5d1SDavid du Colombier 		tx = typ(TXXX, 0);
1483e12c5d1SDavid du Colombier 		*tx = *t;
1493e12c5d1SDavid du Colombier 		tx->link = tl;
1503e12c5d1SDavid du Colombier 		return tx;
1513e12c5d1SDavid du Colombier 	}
1523e12c5d1SDavid du Colombier 	return t;
1533e12c5d1SDavid du Colombier }
1543e12c5d1SDavid du Colombier 
1553e12c5d1SDavid du Colombier Node*
1563e12c5d1SDavid du Colombier doinit(Sym *s, Type *t, long o, Node *a)
1573e12c5d1SDavid du Colombier {
1583e12c5d1SDavid du Colombier 	Node *n;
1593e12c5d1SDavid du Colombier 
1603e12c5d1SDavid du Colombier 	if(t == T)
1613e12c5d1SDavid du Colombier 		return Z;
1623e12c5d1SDavid du Colombier 	if(s->class == CEXTERN) {
1633e12c5d1SDavid du Colombier 		s->class = CGLOBL;
1643e12c5d1SDavid du Colombier 		if(debug['d'])
1653e12c5d1SDavid du Colombier 			dbgdecl(s);
1663e12c5d1SDavid du Colombier 	}
1673e12c5d1SDavid du Colombier 	if(debug['i']) {
1683e12c5d1SDavid du Colombier 		print("t = %T; o = %ld; n = %s\n", t, o, s->name);
1693e12c5d1SDavid du Colombier 		prtree(a, "doinit value");
1703e12c5d1SDavid du Colombier 	}
1713e12c5d1SDavid du Colombier 
1723e12c5d1SDavid du Colombier 
1733e12c5d1SDavid du Colombier 	n = initlist;
1743e12c5d1SDavid du Colombier 	if(a->op == OINIT)
1753e12c5d1SDavid du Colombier 		a = a->left;
1763e12c5d1SDavid du Colombier 	initlist = a;
1773e12c5d1SDavid du Colombier 
1783e12c5d1SDavid du Colombier 	a = init1(s, t, o, 0);
1793e12c5d1SDavid du Colombier 	if(initlist != Z)
1803e12c5d1SDavid du Colombier 		diag(initlist, "more initializers than structure: %s",
1813e12c5d1SDavid du Colombier 			s->name);
1823e12c5d1SDavid du Colombier 	initlist = n;
1833e12c5d1SDavid du Colombier 
1843e12c5d1SDavid du Colombier 	return a;
1853e12c5d1SDavid du Colombier }
1863e12c5d1SDavid du Colombier 
1873e12c5d1SDavid du Colombier /*
1883e12c5d1SDavid du Colombier  * get next major operator,
1893e12c5d1SDavid du Colombier  * dont advance initlist.
1903e12c5d1SDavid du Colombier  */
1913e12c5d1SDavid du Colombier Node*
1923e12c5d1SDavid du Colombier peekinit(void)
1933e12c5d1SDavid du Colombier {
1943e12c5d1SDavid du Colombier 	Node *a;
1953e12c5d1SDavid du Colombier 
1963e12c5d1SDavid du Colombier 	a = initlist;
1973e12c5d1SDavid du Colombier 
1983e12c5d1SDavid du Colombier loop:
1993e12c5d1SDavid du Colombier 	if(a == Z)
2003e12c5d1SDavid du Colombier 		return a;
2013e12c5d1SDavid du Colombier 	if(a->op == OLIST) {
2023e12c5d1SDavid du Colombier 		a = a->left;
2033e12c5d1SDavid du Colombier 		goto loop;
2043e12c5d1SDavid du Colombier 	}
2053e12c5d1SDavid du Colombier 	return a;
2063e12c5d1SDavid du Colombier }
2073e12c5d1SDavid du Colombier 
2083e12c5d1SDavid du Colombier /*
2093e12c5d1SDavid du Colombier  * consume and return next element on
2103e12c5d1SDavid du Colombier  * initlist. expand strings.
2113e12c5d1SDavid du Colombier  */
2123e12c5d1SDavid du Colombier Node*
2133e12c5d1SDavid du Colombier nextinit(void)
2143e12c5d1SDavid du Colombier {
2153e12c5d1SDavid du Colombier 	Node *a, *b, *n;
2163e12c5d1SDavid du Colombier 
2173e12c5d1SDavid du Colombier 	a = initlist;
2183e12c5d1SDavid du Colombier 	n = Z;
2193e12c5d1SDavid du Colombier 
2203e12c5d1SDavid du Colombier loop:
2213e12c5d1SDavid du Colombier 	if(a == Z)
2223e12c5d1SDavid du Colombier 		return a;
2233e12c5d1SDavid du Colombier 	if(a->op == OLIST) {
2243e12c5d1SDavid du Colombier 		n = a->right;
2253e12c5d1SDavid du Colombier 		a = a->left;
2263e12c5d1SDavid du Colombier 	}
2273e12c5d1SDavid du Colombier 	if(a->op == OUSED) {
2283e12c5d1SDavid du Colombier 		a = a->left;
2293e12c5d1SDavid du Colombier 		b = new(OCONST, Z, Z);
2303e12c5d1SDavid du Colombier 		b->type = a->type->link;
2313e12c5d1SDavid du Colombier 		if(a->op == OSTRING) {
232*219b2ee8SDavid du Colombier 			b->vconst = convvtox(*a->cstring, TCHAR);
233*219b2ee8SDavid du Colombier 			a->cstring++;
2343e12c5d1SDavid du Colombier 		}
2353e12c5d1SDavid du Colombier 		if(a->op == OLSTRING) {
236*219b2ee8SDavid du Colombier 			b->vconst = convvtox(*a->rstring, TUSHORT);
237*219b2ee8SDavid du Colombier 			a->rstring++;
2383e12c5d1SDavid du Colombier 		}
2393e12c5d1SDavid du Colombier 		a->type->width -= b->type->width;
2403e12c5d1SDavid du Colombier 		if(a->type->width <= 0)
2413e12c5d1SDavid du Colombier 			initlist = n;
2423e12c5d1SDavid du Colombier 		return b;
2433e12c5d1SDavid du Colombier 	}
2443e12c5d1SDavid du Colombier 	initlist = n;
2453e12c5d1SDavid du Colombier 	return a;
2463e12c5d1SDavid du Colombier }
2473e12c5d1SDavid du Colombier 
2483e12c5d1SDavid du Colombier int
2493e12c5d1SDavid du Colombier isstruct(Node *a, Type *t)
2503e12c5d1SDavid du Colombier {
2513e12c5d1SDavid du Colombier 	Node *n;
2523e12c5d1SDavid du Colombier 
2533e12c5d1SDavid du Colombier 	switch(a->op) {
2543e12c5d1SDavid du Colombier 	case ODOTDOT:
2553e12c5d1SDavid du Colombier 		n = a->left;
2563e12c5d1SDavid du Colombier 		if(n && n->type && sametype(n->type, t))
2573e12c5d1SDavid du Colombier 			return 1;
2583e12c5d1SDavid du Colombier 	case OSTRING:
2593e12c5d1SDavid du Colombier 	case OLSTRING:
2603e12c5d1SDavid du Colombier 	case OCONST:
2613e12c5d1SDavid du Colombier 	case OINIT:
262*219b2ee8SDavid du Colombier 	case OELEM:
2633e12c5d1SDavid du Colombier 		return 0;
2643e12c5d1SDavid du Colombier 	}
2653e12c5d1SDavid du Colombier 
2663e12c5d1SDavid du Colombier 	n = new(ODOTDOT, Z, Z);
2673e12c5d1SDavid du Colombier 	*n = *a;
2683e12c5d1SDavid du Colombier 
2693e12c5d1SDavid du Colombier 	/*
2703e12c5d1SDavid du Colombier 	 * ODOTDOT is a flag for tcom
2713e12c5d1SDavid du Colombier 	 * a second tcom will not be performed
2723e12c5d1SDavid du Colombier 	 */
2733e12c5d1SDavid du Colombier 	a->op = ODOTDOT;
2743e12c5d1SDavid du Colombier 	a->left = n;
2753e12c5d1SDavid du Colombier 	a->right = Z;
2763e12c5d1SDavid du Colombier 
2773e12c5d1SDavid du Colombier 	if(tcom(n))
2783e12c5d1SDavid du Colombier 		return 0;
2793e12c5d1SDavid du Colombier 
2803e12c5d1SDavid du Colombier 	if(sametype(n->type, t))
2813e12c5d1SDavid du Colombier 		return 1;
2823e12c5d1SDavid du Colombier 	return 0;
2833e12c5d1SDavid du Colombier }
2843e12c5d1SDavid du Colombier 
2853e12c5d1SDavid du Colombier Node*
2863e12c5d1SDavid du Colombier init1(Sym *s, Type *t, long o, int exflag)
2873e12c5d1SDavid du Colombier {
2883e12c5d1SDavid du Colombier 	Node *a, *l, *r;
289*219b2ee8SDavid du Colombier 	Type *t1;
2903e12c5d1SDavid du Colombier 	long e, w, so, mw;
2913e12c5d1SDavid du Colombier 
2923e12c5d1SDavid du Colombier 	a = peekinit();
2933e12c5d1SDavid du Colombier 	if(a == Z)
2943e12c5d1SDavid du Colombier 		return Z;
2953e12c5d1SDavid du Colombier 
2963e12c5d1SDavid du Colombier 	if(debug['i']) {
2973e12c5d1SDavid du Colombier 		print("t = %T; o = %ld; n = %s\n", t, o, s->name);
2983e12c5d1SDavid du Colombier 		prtree(a, "init1 value");
2993e12c5d1SDavid du Colombier 	}
3003e12c5d1SDavid du Colombier 
3013e12c5d1SDavid du Colombier 	if(exflag && a->op == OINIT)
3023e12c5d1SDavid du Colombier 		return doinit(s, t, o, nextinit());
3033e12c5d1SDavid du Colombier 
3043e12c5d1SDavid du Colombier 	switch(t->etype) {
3053e12c5d1SDavid du Colombier 	default:
3063e12c5d1SDavid du Colombier 		diag(Z, "unknown type in initialization: %T to: %s", t, s->name);
3073e12c5d1SDavid du Colombier 		return Z;
3083e12c5d1SDavid du Colombier 
3093e12c5d1SDavid du Colombier 	case TCHAR:
3103e12c5d1SDavid du Colombier 	case TUCHAR:
3113e12c5d1SDavid du Colombier 	case TSHORT:
3123e12c5d1SDavid du Colombier 	case TUSHORT:
3133e12c5d1SDavid du Colombier 	case TLONG:
3143e12c5d1SDavid du Colombier 	case TULONG:
3153e12c5d1SDavid du Colombier 	case TVLONG:
3163e12c5d1SDavid du Colombier 	case TFLOAT:
3173e12c5d1SDavid du Colombier 	case TDOUBLE:
3183e12c5d1SDavid du Colombier 	case TIND:
3193e12c5d1SDavid du Colombier 	single:
320*219b2ee8SDavid du Colombier 		if(a->op == OARRAY || a->op == OELEM)
3213e12c5d1SDavid du Colombier 			return Z;
3223e12c5d1SDavid du Colombier 
3233e12c5d1SDavid du Colombier 		a = nextinit();
3243e12c5d1SDavid du Colombier 		if(a == Z)
3253e12c5d1SDavid du Colombier 			return Z;
3263e12c5d1SDavid du Colombier 
3273e12c5d1SDavid du Colombier 		if(t->nbits)
3283e12c5d1SDavid du Colombier 			diag(Z, "cannot initialize bitfields");
3293e12c5d1SDavid du Colombier 		if(s->class == CAUTO) {
3303e12c5d1SDavid du Colombier 			l = new(ONAME, Z, Z);
3313e12c5d1SDavid du Colombier 			l->sym = s;
3323e12c5d1SDavid du Colombier 			l->type = t;
3333e12c5d1SDavid du Colombier 			l->etype = TVOID;
3343e12c5d1SDavid du Colombier 			if(s->type)
3353e12c5d1SDavid du Colombier 				l->etype = s->type->etype;
336*219b2ee8SDavid du Colombier 			l->xoffset = s->offset + o;
3373e12c5d1SDavid du Colombier 			l->class = s->class;
3383e12c5d1SDavid du Colombier 
3393e12c5d1SDavid du Colombier 			l = new(OAS, l, a);
3403e12c5d1SDavid du Colombier 			return l;
3413e12c5d1SDavid du Colombier 		}
3423e12c5d1SDavid du Colombier 
3433e12c5d1SDavid du Colombier 		complex(a);
3443e12c5d1SDavid du Colombier 		if(a->type == T)
3453e12c5d1SDavid du Colombier 			return Z;
3463e12c5d1SDavid du Colombier 
3473e12c5d1SDavid du Colombier 		if(a->op == OCONST) {
3483e12c5d1SDavid du Colombier 			if(!sametype(a->type, t)) {
3493e12c5d1SDavid du Colombier 				e = a->lineno;
3503e12c5d1SDavid du Colombier 				a = new(OCAST, a, Z);
3513e12c5d1SDavid du Colombier 				a->lineno = e;
3523e12c5d1SDavid du Colombier 				a->type = t;
3533e12c5d1SDavid du Colombier 				complex(a);
3543e12c5d1SDavid du Colombier 			}
3553e12c5d1SDavid du Colombier 			if(a->op != OCONST) {
3563e12c5d1SDavid du Colombier 				diag(a, "initializer is not a constant: %s",
3573e12c5d1SDavid du Colombier 					s->name);
3583e12c5d1SDavid du Colombier 				return Z;
3593e12c5d1SDavid du Colombier 			}
3603e12c5d1SDavid du Colombier 			if(vconst(a) == 0)
3613e12c5d1SDavid du Colombier 				return Z;
3623e12c5d1SDavid du Colombier 			goto gext;
3633e12c5d1SDavid du Colombier 		}
3643e12c5d1SDavid du Colombier 		if(t->etype == TIND) {
3653e12c5d1SDavid du Colombier 			while(a->op == OCAST) {
3663e12c5d1SDavid du Colombier 				warn(a, "CAST in initialization ignored");
3673e12c5d1SDavid du Colombier 				a = a->left;
3683e12c5d1SDavid du Colombier 			}
3693e12c5d1SDavid du Colombier 			if(!sametype(t, a->type)) {
3703e12c5d1SDavid du Colombier 				diag(a, "initialization of incompatible pointers: %s",
3713e12c5d1SDavid du Colombier 					s->name);
3723e12c5d1SDavid du Colombier 				print("%T and %T\n", t, a->type);
3733e12c5d1SDavid du Colombier 			}
3743e12c5d1SDavid du Colombier 			if(a->op == OADDR)
3753e12c5d1SDavid du Colombier 				a = a->left;
3763e12c5d1SDavid du Colombier 			goto gext;
3773e12c5d1SDavid du Colombier 		}
378*219b2ee8SDavid du Colombier 
3793e12c5d1SDavid du Colombier 		while(a->op == OCAST)
3803e12c5d1SDavid du Colombier 			a = a->left;
3813e12c5d1SDavid du Colombier 		if(a->op == OADDR) {
3823e12c5d1SDavid du Colombier 			warn(a, "initialize pointer to an integer", s->name);
3833e12c5d1SDavid du Colombier 			a = a->left;
3843e12c5d1SDavid du Colombier 			goto gext;
3853e12c5d1SDavid du Colombier 		}
3863e12c5d1SDavid du Colombier 		diag(a, "initializer is not a constant: %s", s->name);
3873e12c5d1SDavid du Colombier 		return Z;
3883e12c5d1SDavid du Colombier 
3893e12c5d1SDavid du Colombier 	gext:
3903e12c5d1SDavid du Colombier 		gextern(s, a, o, t->width);
3913e12c5d1SDavid du Colombier 
3923e12c5d1SDavid du Colombier 		return Z;
3933e12c5d1SDavid du Colombier 
3943e12c5d1SDavid du Colombier 	case TARRAY:
3953e12c5d1SDavid du Colombier 		w = t->link->width;
3963e12c5d1SDavid du Colombier 		if(a->op == OSTRING || a->op == OLSTRING)
397*219b2ee8SDavid du Colombier 		if(typei[t->link->etype]) {
3983e12c5d1SDavid du Colombier 			/*
3993e12c5d1SDavid du Colombier 			 * get rid of null if sizes match exactly
4003e12c5d1SDavid du Colombier 			 */
4013e12c5d1SDavid du Colombier 			a = nextinit();
4023e12c5d1SDavid du Colombier 			mw = t->width/w;
4033e12c5d1SDavid du Colombier 			so = a->type->width/a->type->link->width;
4043e12c5d1SDavid du Colombier 			if(mw && so > mw) {
4053e12c5d1SDavid du Colombier 				if(so != mw+1)
4063e12c5d1SDavid du Colombier 					diag(a, "string initialization larger than array");
4073e12c5d1SDavid du Colombier 				a->type->width -= a->type->link->width;
4083e12c5d1SDavid du Colombier 			}
4093e12c5d1SDavid du Colombier 
4103e12c5d1SDavid du Colombier 			/*
4113e12c5d1SDavid du Colombier 			 * arrange strings to be expanded
4123e12c5d1SDavid du Colombier 			 * inside OINIT braces.
4133e12c5d1SDavid du Colombier 			 */
4143e12c5d1SDavid du Colombier 			a = new(OUSED, a, Z);
4153e12c5d1SDavid du Colombier 			return doinit(s, t, o, a);
4163e12c5d1SDavid du Colombier 		}
4173e12c5d1SDavid du Colombier 
4183e12c5d1SDavid du Colombier 		mw = -w;
4193e12c5d1SDavid du Colombier 		l = Z;
4203e12c5d1SDavid du Colombier 		for(e=0;;) {
4213e12c5d1SDavid du Colombier 			/*
4223e12c5d1SDavid du Colombier 			 * peek ahead for element initializer
4233e12c5d1SDavid du Colombier 			 */
4243e12c5d1SDavid du Colombier 			a = peekinit();
4253e12c5d1SDavid du Colombier 			if(a == Z)
4263e12c5d1SDavid du Colombier 				break;
427*219b2ee8SDavid du Colombier 			if(a->op == OELEM && t->link->etype != TSTRUCT)
428*219b2ee8SDavid du Colombier 				break;
4293e12c5d1SDavid du Colombier 			if(a->op == OARRAY) {
4303e12c5d1SDavid du Colombier 				a = nextinit();
4313e12c5d1SDavid du Colombier 				r = a->left;
4323e12c5d1SDavid du Colombier 				complex(r);
4333e12c5d1SDavid du Colombier 				if(r->op != OCONST) {
4343e12c5d1SDavid du Colombier 					diag(r, "initializer subscript must be constant");
4353e12c5d1SDavid du Colombier 					return Z;
4363e12c5d1SDavid du Colombier 				}
437*219b2ee8SDavid du Colombier 				e = r->vconst;
4383e12c5d1SDavid du Colombier 				if(t->width != 0)
4393e12c5d1SDavid du Colombier 					if(e < 0 || e*w >= t->width) {
4403e12c5d1SDavid du Colombier 						diag(a, "initilization index out of range: %ld", e);
4413e12c5d1SDavid du Colombier 						e = 0;
4423e12c5d1SDavid du Colombier 					}
4433e12c5d1SDavid du Colombier 				continue;
4443e12c5d1SDavid du Colombier 			}
4453e12c5d1SDavid du Colombier 
4463e12c5d1SDavid du Colombier 			so = e*w;
4473e12c5d1SDavid du Colombier 			if(so > mw)
4483e12c5d1SDavid du Colombier 				mw = so;
4493e12c5d1SDavid du Colombier 			if(t->width != 0)
4503e12c5d1SDavid du Colombier 				if(mw >= t->width)
4513e12c5d1SDavid du Colombier 					break;
4523e12c5d1SDavid du Colombier 			r = init1(s, t->link, o+so, 1);
4533e12c5d1SDavid du Colombier 			l = newlist(l, r);
4543e12c5d1SDavid du Colombier 			e++;
4553e12c5d1SDavid du Colombier 		}
4563e12c5d1SDavid du Colombier 		if(t->width == 0)
4573e12c5d1SDavid du Colombier 			t->width = mw+w;
4583e12c5d1SDavid du Colombier 		return l;
4593e12c5d1SDavid du Colombier 
4603e12c5d1SDavid du Colombier 	case TUNION:
4613e12c5d1SDavid du Colombier 	case TSTRUCT:
4623e12c5d1SDavid du Colombier 		/*
4633e12c5d1SDavid du Colombier 		 * peek ahead to find type of rhs.
4643e12c5d1SDavid du Colombier 		 * if its a structure, then treat
4653e12c5d1SDavid du Colombier 		 * this element as a variable
4663e12c5d1SDavid du Colombier 		 * rather than an aggregate.
4673e12c5d1SDavid du Colombier 		 */
4683e12c5d1SDavid du Colombier 		if(isstruct(a, t))
4693e12c5d1SDavid du Colombier 			goto single;
4703e12c5d1SDavid du Colombier 
4713e12c5d1SDavid du Colombier 		if(t->width <= 0) {
4723e12c5d1SDavid du Colombier 			diag(Z, "incomplete structure: %s", s->name);
4733e12c5d1SDavid du Colombier 			return Z;
4743e12c5d1SDavid du Colombier 		}
4753e12c5d1SDavid du Colombier 		l = Z;
476*219b2ee8SDavid du Colombier 
477*219b2ee8SDavid du Colombier 	again:
478*219b2ee8SDavid du Colombier 		for(t1 = t->link; t1 != T; t1 = t1->down) {
479*219b2ee8SDavid du Colombier 			if(a->op == OARRAY && t1->etype != TARRAY)
480*219b2ee8SDavid du Colombier 				break;
481*219b2ee8SDavid du Colombier 			if(a->op == OELEM) {
482*219b2ee8SDavid du Colombier 				if(t1->sym != a->sym)
483*219b2ee8SDavid du Colombier 					continue;
484*219b2ee8SDavid du Colombier 				nextinit();
485*219b2ee8SDavid du Colombier 			}
486*219b2ee8SDavid du Colombier 			r = init1(s, t1, o+t1->offset, 1);
487*219b2ee8SDavid du Colombier 			l = newlist(l, r);
4883e12c5d1SDavid du Colombier 			a = peekinit();
4893e12c5d1SDavid du Colombier 			if(a == Z)
4903e12c5d1SDavid du Colombier 				break;
491*219b2ee8SDavid du Colombier 			if(a->op == OELEM)
492*219b2ee8SDavid du Colombier 				goto again;
4933e12c5d1SDavid du Colombier 		}
494*219b2ee8SDavid du Colombier 		if(a && a->op == OELEM)
495*219b2ee8SDavid du Colombier 			diag(a, "structure element not found %F", a);
4963e12c5d1SDavid du Colombier 		return l;
4973e12c5d1SDavid du Colombier 	}
4983e12c5d1SDavid du Colombier }
4993e12c5d1SDavid du Colombier 
5003e12c5d1SDavid du Colombier Node*
5013e12c5d1SDavid du Colombier newlist(Node *l, Node *r)
5023e12c5d1SDavid du Colombier {
5033e12c5d1SDavid du Colombier 	if(r == Z)
5043e12c5d1SDavid du Colombier 		return l;
5053e12c5d1SDavid du Colombier 	if(l == Z)
5063e12c5d1SDavid du Colombier 		return r;
5073e12c5d1SDavid du Colombier 	return new(OLIST, l, r);
5083e12c5d1SDavid du Colombier }
5093e12c5d1SDavid du Colombier 
5103e12c5d1SDavid du Colombier void
5113e12c5d1SDavid du Colombier suallign(Type *t)
5123e12c5d1SDavid du Colombier {
5133e12c5d1SDavid du Colombier 	Type *l;
5143e12c5d1SDavid du Colombier 	long o, w;
5153e12c5d1SDavid du Colombier 
5163e12c5d1SDavid du Colombier 	o = 0;
5173e12c5d1SDavid du Colombier 	switch(t->etype) {
5183e12c5d1SDavid du Colombier 
5193e12c5d1SDavid du Colombier 	case TSTRUCT:
5203e12c5d1SDavid du Colombier 		t->offset = 0;
5213e12c5d1SDavid du Colombier 		w = 0;
5223e12c5d1SDavid du Colombier 		for(l = t->link; l != T; l = l->down) {
5233e12c5d1SDavid du Colombier 			if(l->nbits) {
5243e12c5d1SDavid du Colombier 				if(l->shift <= 0) {
5253e12c5d1SDavid du Colombier 					l->shift = -l->shift;
5263e12c5d1SDavid du Colombier 					w += round(w, tfield->width);
5273e12c5d1SDavid du Colombier 					o = w;
5283e12c5d1SDavid du Colombier 					w += tfield->width;
5293e12c5d1SDavid du Colombier 				}
5303e12c5d1SDavid du Colombier 				l->offset = o;
5313e12c5d1SDavid du Colombier 			} else {
5323e12c5d1SDavid du Colombier 				if(l->width <= 0)
5333e12c5d1SDavid du Colombier 					if(l->sym)
5343e12c5d1SDavid du Colombier 						diag(Z, "incomplete structure element: %s",
5353e12c5d1SDavid du Colombier 							l->sym->name);
5363e12c5d1SDavid du Colombier 					else
5373e12c5d1SDavid du Colombier 						diag(Z, "incomplete structure element");
5383e12c5d1SDavid du Colombier 				w += round(w, allign(l));
5393e12c5d1SDavid du Colombier 				l->offset = w;
5403e12c5d1SDavid du Colombier 				w += l->width;
5413e12c5d1SDavid du Colombier 			}
5423e12c5d1SDavid du Colombier 		}
5433e12c5d1SDavid du Colombier 		w += round(w, supad);
5443e12c5d1SDavid du Colombier 		t->width = w;
545*219b2ee8SDavid du Colombier 		acidtype(t);
5463e12c5d1SDavid du Colombier 		return;
5473e12c5d1SDavid du Colombier 
5483e12c5d1SDavid du Colombier 	case TUNION:
5493e12c5d1SDavid du Colombier 		t->offset = 0;
5503e12c5d1SDavid du Colombier 		w = 0;
5513e12c5d1SDavid du Colombier 		for(l = t->link; l != T; l = l->down) {
5523e12c5d1SDavid du Colombier 			if(l->width <= 0)
5533e12c5d1SDavid du Colombier 				if(l->sym)
5543e12c5d1SDavid du Colombier 					diag(Z, "incomplete union element: %s",
5553e12c5d1SDavid du Colombier 						l->sym->name);
5563e12c5d1SDavid du Colombier 				else
5573e12c5d1SDavid du Colombier 					diag(Z, "incomplete union element");
5583e12c5d1SDavid du Colombier 			l->offset = 0;
5593e12c5d1SDavid du Colombier 			l->shift = 0;
5603e12c5d1SDavid du Colombier 			if(l->width > w)
5613e12c5d1SDavid du Colombier 				w = l->width;
5623e12c5d1SDavid du Colombier 		}
5633e12c5d1SDavid du Colombier 		w += round(w, supad);
5643e12c5d1SDavid du Colombier 		t->width = w;
565*219b2ee8SDavid du Colombier 		acidtype(t);
5663e12c5d1SDavid du Colombier 		return;
5673e12c5d1SDavid du Colombier 
5683e12c5d1SDavid du Colombier 	default:
5693e12c5d1SDavid du Colombier 		diag(Z, "unknown type in suallign: %T", t);
5703e12c5d1SDavid du Colombier 		break;
5713e12c5d1SDavid du Colombier 	}
5723e12c5d1SDavid du Colombier }
5733e12c5d1SDavid du Colombier 
5743e12c5d1SDavid du Colombier int
5753e12c5d1SDavid du Colombier allign(Type *t)
5763e12c5d1SDavid du Colombier {
5773e12c5d1SDavid du Colombier 	int w;
5783e12c5d1SDavid du Colombier 
5793e12c5d1SDavid du Colombier 	while(t->etype == TARRAY)
5803e12c5d1SDavid du Colombier 		t = t->link;
5813e12c5d1SDavid du Colombier 	w = ewidth[t->etype];
5823e12c5d1SDavid du Colombier 	if(w <= 0 || w > suround)
5833e12c5d1SDavid du Colombier 		w = suround;
5843e12c5d1SDavid du Colombier 	return w;
5853e12c5d1SDavid du Colombier }
5863e12c5d1SDavid du Colombier 
5873e12c5d1SDavid du Colombier int
5883e12c5d1SDavid du Colombier round(long v, long w)
5893e12c5d1SDavid du Colombier {
5903e12c5d1SDavid du Colombier 	int r;
5913e12c5d1SDavid du Colombier 
5923e12c5d1SDavid du Colombier 	if(w <= 0) {
5933e12c5d1SDavid du Colombier 		diag(Z, "rounding by %d", w);
5943e12c5d1SDavid du Colombier 		w = 1;
5953e12c5d1SDavid du Colombier 	}
596*219b2ee8SDavid du Colombier 	if(w > types[TVLONG]->width)
597*219b2ee8SDavid du Colombier 		w = types[TVLONG]->width;
5983e12c5d1SDavid du Colombier 	r = v%w;
5993e12c5d1SDavid du Colombier 	if(r)
6003e12c5d1SDavid du Colombier 		r = w-r;
6013e12c5d1SDavid du Colombier 	return r;
6023e12c5d1SDavid du Colombier }
6033e12c5d1SDavid du Colombier 
6043e12c5d1SDavid du Colombier Type*
6053e12c5d1SDavid du Colombier ofnproto(Node *n)
6063e12c5d1SDavid du Colombier {
6073e12c5d1SDavid du Colombier 	Type *tl, *tr, *t;
6083e12c5d1SDavid du Colombier 
6093e12c5d1SDavid du Colombier loop:
6103e12c5d1SDavid du Colombier 	if(n == Z)
6113e12c5d1SDavid du Colombier 		return T;
6123e12c5d1SDavid du Colombier 	switch(n->op) {
6133e12c5d1SDavid du Colombier 	case OLIST:
6143e12c5d1SDavid du Colombier 		tl = ofnproto(n->left);
6153e12c5d1SDavid du Colombier 		tr = ofnproto(n->right);
6163e12c5d1SDavid du Colombier 		if(tl == T)
6173e12c5d1SDavid du Colombier 			return tr;
6183e12c5d1SDavid du Colombier 		tl->down = tr;
6193e12c5d1SDavid du Colombier 		return tl;
6203e12c5d1SDavid du Colombier 
6213e12c5d1SDavid du Colombier 	case ONAME:
6223e12c5d1SDavid du Colombier 		t = typ(TXXX, T);
6233e12c5d1SDavid du Colombier 		*t = *n->sym->type;
6243e12c5d1SDavid du Colombier 		t->down = T;
6253e12c5d1SDavid du Colombier 		return t;
6263e12c5d1SDavid du Colombier 	}
6273e12c5d1SDavid du Colombier 	return T;
6283e12c5d1SDavid du Colombier }
6293e12c5d1SDavid du Colombier 
6303e12c5d1SDavid du Colombier #define	ANSIPROTO	1
6313e12c5d1SDavid du Colombier #define	OLDPROTO	2
6323e12c5d1SDavid du Colombier 
6333e12c5d1SDavid du Colombier void
6343e12c5d1SDavid du Colombier argmark(Node *n, int pass)
6353e12c5d1SDavid du Colombier {
6363e12c5d1SDavid du Colombier 	Type *t;
6373e12c5d1SDavid du Colombier 
6383e12c5d1SDavid du Colombier 	autoffset = 0;
639*219b2ee8SDavid du Colombier 	if(passbypointer(thisfn->link->etype)) {
6403e12c5d1SDavid du Colombier 		autoffset += types[TIND]->width;
6413e12c5d1SDavid du Colombier 		autoffset += round(autoffset, tint->width);
6423e12c5d1SDavid du Colombier 	}
6433e12c5d1SDavid du Colombier 	stkoff = 0;
6443e12c5d1SDavid du Colombier 	for(; n->left != Z; n = n->left) {
6453e12c5d1SDavid du Colombier 		if(n->op != OFUNC || n->left->op != ONAME)
6463e12c5d1SDavid du Colombier 			continue;
6473e12c5d1SDavid du Colombier 		walkparam(n->right, pass);
6483e12c5d1SDavid du Colombier 		if(pass != 0 && anyproto(n->right) == OLDPROTO) {
6493e12c5d1SDavid du Colombier 			t = typ(TFUNC, n->left->sym->type->link);
6503e12c5d1SDavid du Colombier 			t->down = typ(TOLD, T);
6513e12c5d1SDavid du Colombier 			t->down->down = ofnproto(n->right);
6523e12c5d1SDavid du Colombier 			tmerge(t, n->left->sym);
6533e12c5d1SDavid du Colombier 			n->left->sym->type = t;
6543e12c5d1SDavid du Colombier 		}
6553e12c5d1SDavid du Colombier 		break;
6563e12c5d1SDavid du Colombier 	}
6573e12c5d1SDavid du Colombier 	autoffset = 0;
6583e12c5d1SDavid du Colombier 	stkoff = 0;
6593e12c5d1SDavid du Colombier }
6603e12c5d1SDavid du Colombier 
6613e12c5d1SDavid du Colombier void
6623e12c5d1SDavid du Colombier walkparam(Node *n, int pass)
6633e12c5d1SDavid du Colombier {
6643e12c5d1SDavid du Colombier 	Sym *s;
665*219b2ee8SDavid du Colombier 	Node *n1;
6663e12c5d1SDavid du Colombier 
6673e12c5d1SDavid du Colombier 	if(n != Z && n->op == OPROTO && n->left == Z && n->type == types[TVOID])
6683e12c5d1SDavid du Colombier 		return;
6693e12c5d1SDavid du Colombier 
6703e12c5d1SDavid du Colombier loop:
6713e12c5d1SDavid du Colombier 	if(n == Z)
6723e12c5d1SDavid du Colombier 		return;
6733e12c5d1SDavid du Colombier 	switch(n->op) {
6743e12c5d1SDavid du Colombier 	default:
6753e12c5d1SDavid du Colombier 		diag(n, "argument not a name/prototype: %O", n->op);
6763e12c5d1SDavid du Colombier 		break;
6773e12c5d1SDavid du Colombier 
6783e12c5d1SDavid du Colombier 	case OLIST:
6793e12c5d1SDavid du Colombier 		walkparam(n->left, pass);
6803e12c5d1SDavid du Colombier 		n = n->right;
6813e12c5d1SDavid du Colombier 		goto loop;
6823e12c5d1SDavid du Colombier 
6833e12c5d1SDavid du Colombier 	case OPROTO:
684*219b2ee8SDavid du Colombier 		for(n1 = n; n1 != Z; n1=n1->left)
685*219b2ee8SDavid du Colombier 			if(n1->op == ONAME) {
6863e12c5d1SDavid du Colombier 				if(pass == 0) {
687*219b2ee8SDavid du Colombier 					s = n1->sym;
6883e12c5d1SDavid du Colombier 					push1(s);
6893e12c5d1SDavid du Colombier 					s->offset = -1;
6903e12c5d1SDavid du Colombier 					break;
6913e12c5d1SDavid du Colombier 				}
692*219b2ee8SDavid du Colombier 				dodecl(pdecl, CPARAM, n->type, n->left);
6933e12c5d1SDavid du Colombier 				break;
6943e12c5d1SDavid du Colombier 			}
695*219b2ee8SDavid du Colombier 		if(n1)
696*219b2ee8SDavid du Colombier 			break;
697*219b2ee8SDavid du Colombier 		if(pass == 0) {
698*219b2ee8SDavid du Colombier 			/*
699*219b2ee8SDavid du Colombier 			 * extension:
700*219b2ee8SDavid du Colombier 			 *	allow no name in argument declaration
701*219b2ee8SDavid du Colombier 			diag(Z, "no name in argument declaration");
702*219b2ee8SDavid du Colombier 			 */
703*219b2ee8SDavid du Colombier 			break;
704*219b2ee8SDavid du Colombier 		}
705*219b2ee8SDavid du Colombier 		dodecl(NODECL, CPARAM, n->type, n->left);
706*219b2ee8SDavid du Colombier 		pdecl(CPARAM, lastdcl, S);
7073e12c5d1SDavid du Colombier 		break;
7083e12c5d1SDavid du Colombier 
7093e12c5d1SDavid du Colombier 	case ODOTDOT:
7103e12c5d1SDavid du Colombier 		break;
7113e12c5d1SDavid du Colombier 
7123e12c5d1SDavid du Colombier 	case ONAME:
7133e12c5d1SDavid du Colombier 		s = n->sym;
7143e12c5d1SDavid du Colombier 		if(pass == 0) {
7153e12c5d1SDavid du Colombier 			push1(s);
7163e12c5d1SDavid du Colombier 			s->offset = -1;
7173e12c5d1SDavid du Colombier 			break;
7183e12c5d1SDavid du Colombier 		}
7193e12c5d1SDavid du Colombier 		if(s->offset != -1) {
7203e12c5d1SDavid du Colombier 			if(autoffset == 0) {
7213e12c5d1SDavid du Colombier 				firstarg = s;
7223e12c5d1SDavid du Colombier 				firstargtype = s->type;
7233e12c5d1SDavid du Colombier 			}
7243e12c5d1SDavid du Colombier 			s->offset = autoffset;
7253e12c5d1SDavid du Colombier 			autoffset += s->type->width;
7263e12c5d1SDavid du Colombier 			autoffset += round(autoffset, tint->width);
7273e12c5d1SDavid du Colombier 		} else
7283e12c5d1SDavid du Colombier 			dodecl(pdecl, CXXX, tint, n);
7293e12c5d1SDavid du Colombier 		break;
7303e12c5d1SDavid du Colombier 	}
7313e12c5d1SDavid du Colombier }
7323e12c5d1SDavid du Colombier 
7333e12c5d1SDavid du Colombier void
7343e12c5d1SDavid du Colombier markdcl(void)
7353e12c5d1SDavid du Colombier {
7363e12c5d1SDavid du Colombier 	Decl *d;
7373e12c5d1SDavid du Colombier 
7383e12c5d1SDavid du Colombier 	blockno++;
7393e12c5d1SDavid du Colombier 	d = push();
7403e12c5d1SDavid du Colombier 	d->val = DMARK;
7413e12c5d1SDavid du Colombier 	d->offset = autoffset;
7423e12c5d1SDavid du Colombier 	d->block = autobn;
7433e12c5d1SDavid du Colombier 	autobn = blockno;
7443e12c5d1SDavid du Colombier }
7453e12c5d1SDavid du Colombier 
7463e12c5d1SDavid du Colombier void
7473e12c5d1SDavid du Colombier revertdcl(void)
7483e12c5d1SDavid du Colombier {
7493e12c5d1SDavid du Colombier 	Decl *d;
7503e12c5d1SDavid du Colombier 	Sym *s;
7513e12c5d1SDavid du Colombier 
7523e12c5d1SDavid du Colombier 	for(;;) {
7533e12c5d1SDavid du Colombier 		d = dclstack;
7543e12c5d1SDavid du Colombier 		if(d == D) {
7553e12c5d1SDavid du Colombier 			diag(Z, "pop off dcl stack");
7563e12c5d1SDavid du Colombier 			break;
7573e12c5d1SDavid du Colombier 		}
7583e12c5d1SDavid du Colombier 		dclstack = d->link;
7593e12c5d1SDavid du Colombier 		s = d->sym;
7603e12c5d1SDavid du Colombier 		switch(d->val) {
7613e12c5d1SDavid du Colombier 		case DMARK:
7623e12c5d1SDavid du Colombier 			autoffset = d->offset;
7633e12c5d1SDavid du Colombier 			autobn = d->block;
7643e12c5d1SDavid du Colombier 			return;
7653e12c5d1SDavid du Colombier 
7663e12c5d1SDavid du Colombier 		case DAUTO:
7673e12c5d1SDavid du Colombier 			if(debug['d'])
7683e12c5d1SDavid du Colombier 				print("revert1 \"%s\"\n", s->name);
7693e12c5d1SDavid du Colombier 			if(s->aused == 0) {
7703e12c5d1SDavid du Colombier 				nearln = s->varlineno;
7713e12c5d1SDavid du Colombier 				if(s->class == CAUTO)
7723e12c5d1SDavid du Colombier 					warn(Z, "auto declared and not used: %s", s->name);
7733e12c5d1SDavid du Colombier 				if(s->class == CPARAM)
7743e12c5d1SDavid du Colombier 					warn(Z, "param declared and not used: %s", s->name);
7753e12c5d1SDavid du Colombier 			}
7763e12c5d1SDavid du Colombier 			s->type = d->type;
7773e12c5d1SDavid du Colombier 			s->class = d->class;
7783e12c5d1SDavid du Colombier 			s->offset = d->offset;
7793e12c5d1SDavid du Colombier 			s->block = d->block;
7803e12c5d1SDavid du Colombier 			s->varlineno = d->varlineno;
7813e12c5d1SDavid du Colombier 			s->aused = d->aused;
7823e12c5d1SDavid du Colombier 			break;
7833e12c5d1SDavid du Colombier 
7843e12c5d1SDavid du Colombier 		case DSUE:
7853e12c5d1SDavid du Colombier 			if(debug['d'])
7863e12c5d1SDavid du Colombier 				print("revert2 \"%s\"\n", s->name);
7873e12c5d1SDavid du Colombier 			s->suetag = d->type;
7883e12c5d1SDavid du Colombier 			s->sueblock = d->block;
7893e12c5d1SDavid du Colombier 			break;
7903e12c5d1SDavid du Colombier 
7913e12c5d1SDavid du Colombier 		case DLABEL:
7923e12c5d1SDavid du Colombier 			if(debug['d'])
7933e12c5d1SDavid du Colombier 				print("revert3 \"%s\"\n", s->name);
7943e12c5d1SDavid du Colombier 			s->label = Z;
7953e12c5d1SDavid du Colombier 			break;
7963e12c5d1SDavid du Colombier 		}
7973e12c5d1SDavid du Colombier 	}
7983e12c5d1SDavid du Colombier }
7993e12c5d1SDavid du Colombier 
8003e12c5d1SDavid du Colombier Type*
8013e12c5d1SDavid du Colombier fnproto(Node *n)
8023e12c5d1SDavid du Colombier {
8033e12c5d1SDavid du Colombier 	int r;
8043e12c5d1SDavid du Colombier 
8053e12c5d1SDavid du Colombier 	r = anyproto(n->right);
8063e12c5d1SDavid du Colombier 	if(r == 0 || (r & OLDPROTO)) {
8073e12c5d1SDavid du Colombier 		if(r & ANSIPROTO)
8083e12c5d1SDavid du Colombier 			diag(n, "mixed ansi/old function declaration: %F", n->left);
8093e12c5d1SDavid du Colombier 		return T;
8103e12c5d1SDavid du Colombier 	}
8113e12c5d1SDavid du Colombier 	return fnproto1(n->right);
8123e12c5d1SDavid du Colombier }
8133e12c5d1SDavid du Colombier 
8143e12c5d1SDavid du Colombier int
8153e12c5d1SDavid du Colombier anyproto(Node *n)
8163e12c5d1SDavid du Colombier {
8173e12c5d1SDavid du Colombier 	int r;
8183e12c5d1SDavid du Colombier 
8193e12c5d1SDavid du Colombier 	r = 0;
8203e12c5d1SDavid du Colombier 
8213e12c5d1SDavid du Colombier loop:
8223e12c5d1SDavid du Colombier 	if(n == Z)
8233e12c5d1SDavid du Colombier 		return r;
8243e12c5d1SDavid du Colombier 	switch(n->op) {
8253e12c5d1SDavid du Colombier 	case OLIST:
8263e12c5d1SDavid du Colombier 		r |= anyproto(n->left);
8273e12c5d1SDavid du Colombier 		n = n->right;
8283e12c5d1SDavid du Colombier 		goto loop;
8293e12c5d1SDavid du Colombier 
8303e12c5d1SDavid du Colombier 	case ODOTDOT:
8313e12c5d1SDavid du Colombier 	case OPROTO:
8323e12c5d1SDavid du Colombier 		return r | ANSIPROTO;
8333e12c5d1SDavid du Colombier 	}
8343e12c5d1SDavid du Colombier 	return r | OLDPROTO;
8353e12c5d1SDavid du Colombier }
8363e12c5d1SDavid du Colombier 
8373e12c5d1SDavid du Colombier Type*
8383e12c5d1SDavid du Colombier fnproto1(Node *n)
8393e12c5d1SDavid du Colombier {
8403e12c5d1SDavid du Colombier 	Type *t;
8413e12c5d1SDavid du Colombier 
8423e12c5d1SDavid du Colombier 	if(n == Z)
8433e12c5d1SDavid du Colombier 		return T;
8443e12c5d1SDavid du Colombier 	switch(n->op) {
8453e12c5d1SDavid du Colombier 	case OLIST:
8463e12c5d1SDavid du Colombier 		t = fnproto1(n->left);
8473e12c5d1SDavid du Colombier 		if(t != T)
8483e12c5d1SDavid du Colombier 			t->down = fnproto1(n->right);
8493e12c5d1SDavid du Colombier 		return t;
8503e12c5d1SDavid du Colombier 
8513e12c5d1SDavid du Colombier 	case OPROTO:
8523e12c5d1SDavid du Colombier 		lastdcl = T;
8533e12c5d1SDavid du Colombier 		dodecl(NODECL, CXXX, n->type, n->left);
8543e12c5d1SDavid du Colombier 		t = typ(TXXX, T);
8553e12c5d1SDavid du Colombier 		if(lastdcl != T)
8563e12c5d1SDavid du Colombier 			*t = *paramconv(lastdcl, 1);
8573e12c5d1SDavid du Colombier 		return t;
8583e12c5d1SDavid du Colombier 
8593e12c5d1SDavid du Colombier 	case ONAME:
8603e12c5d1SDavid du Colombier 		diag(n, "incomplete argument prototype");
8613e12c5d1SDavid du Colombier 		return typ(tint->etype, T);
8623e12c5d1SDavid du Colombier 
8633e12c5d1SDavid du Colombier 	case ODOTDOT:
8643e12c5d1SDavid du Colombier 		return typ(TDOT, T);
8653e12c5d1SDavid du Colombier 	}
8663e12c5d1SDavid du Colombier 	diag(n, "unknown op in fnproto");
8673e12c5d1SDavid du Colombier 	return T;
8683e12c5d1SDavid du Colombier }
8693e12c5d1SDavid du Colombier 
8703e12c5d1SDavid du Colombier void
8713e12c5d1SDavid du Colombier dbgdecl(Sym *s)
8723e12c5d1SDavid du Colombier {
8733e12c5d1SDavid du Colombier 
8743e12c5d1SDavid du Colombier 	if(s->class == CAUTO)
875*219b2ee8SDavid du Colombier 		print("decl \"%s\": %s [%d:%ld] %T",
876*219b2ee8SDavid du Colombier 			s->name, cnames[s->class], s->block, s->offset, s->type);
877*219b2ee8SDavid du Colombier 	else
878*219b2ee8SDavid du Colombier 		print("decl \"%s\": %s [%d] %T\n",
879*219b2ee8SDavid du Colombier 			s->name, cnames[s->class], s->block, s->type);
8803e12c5d1SDavid du Colombier }
8813e12c5d1SDavid du Colombier 
8823e12c5d1SDavid du Colombier Decl*
8833e12c5d1SDavid du Colombier push(void)
8843e12c5d1SDavid du Colombier {
8853e12c5d1SDavid du Colombier 	Decl *d;
8863e12c5d1SDavid du Colombier 
8873e12c5d1SDavid du Colombier 	ALLOC(d, Decl);
8883e12c5d1SDavid du Colombier 	d->link = dclstack;
8893e12c5d1SDavid du Colombier 	dclstack = d;
8903e12c5d1SDavid du Colombier 	return d;
8913e12c5d1SDavid du Colombier }
8923e12c5d1SDavid du Colombier 
8933e12c5d1SDavid du Colombier Decl*
8943e12c5d1SDavid du Colombier push1(Sym *s)
8953e12c5d1SDavid du Colombier {
8963e12c5d1SDavid du Colombier 	Decl *d;
8973e12c5d1SDavid du Colombier 
8983e12c5d1SDavid du Colombier 	d = push();
8993e12c5d1SDavid du Colombier 	d->sym = s;
9003e12c5d1SDavid du Colombier 	d->val = DAUTO;
9013e12c5d1SDavid du Colombier 	d->type = s->type;
9023e12c5d1SDavid du Colombier 	d->class = s->class;
9033e12c5d1SDavid du Colombier 	d->offset = s->offset;
9043e12c5d1SDavid du Colombier 	d->block = s->block;
9053e12c5d1SDavid du Colombier 	d->varlineno = s->varlineno;
9063e12c5d1SDavid du Colombier 	d->aused = s->aused;
9073e12c5d1SDavid du Colombier 	return d;
9083e12c5d1SDavid du Colombier }
9093e12c5d1SDavid du Colombier 
9103e12c5d1SDavid du Colombier int
9113e12c5d1SDavid du Colombier sametype(Type *t1, Type *t2)
9123e12c5d1SDavid du Colombier {
9133e12c5d1SDavid du Colombier 
9143e12c5d1SDavid du Colombier 	if(t1 == t2)
9153e12c5d1SDavid du Colombier 		return 1;
9163e12c5d1SDavid du Colombier 	return rsametype(t1, t2, 5);
9173e12c5d1SDavid du Colombier }
9183e12c5d1SDavid du Colombier 
9193e12c5d1SDavid du Colombier int
9203e12c5d1SDavid du Colombier rsametype(Type *t1, Type *t2, int n)
9213e12c5d1SDavid du Colombier {
9223e12c5d1SDavid du Colombier 	int et;
9233e12c5d1SDavid du Colombier 
9243e12c5d1SDavid du Colombier 	n--;
9253e12c5d1SDavid du Colombier 	for(;;) {
9263e12c5d1SDavid du Colombier 		if(t1 == t2)
9273e12c5d1SDavid du Colombier 			return 1;
9283e12c5d1SDavid du Colombier 		if(t1 == T || t2 == T)
9293e12c5d1SDavid du Colombier 			return 0;
9303e12c5d1SDavid du Colombier 		if(n <= 0)
9313e12c5d1SDavid du Colombier 			return 1;
9323e12c5d1SDavid du Colombier 		et = t1->etype;
9333e12c5d1SDavid du Colombier 		if(et != t2->etype)
9343e12c5d1SDavid du Colombier 			return 0;
9353e12c5d1SDavid du Colombier 		if(et == TFUNC) {
9363e12c5d1SDavid du Colombier 			if(!rsametype(t1->link, t2->link, n))
9373e12c5d1SDavid du Colombier 				return 0;
9383e12c5d1SDavid du Colombier 			t1 = t1->down;
9393e12c5d1SDavid du Colombier 			t2 = t2->down;
9403e12c5d1SDavid du Colombier 			while(t1 != T && t2 != T) {
9413e12c5d1SDavid du Colombier 				if(t1->etype == TOLD) {
9423e12c5d1SDavid du Colombier 					t1 = t1->down;
9433e12c5d1SDavid du Colombier 					continue;
9443e12c5d1SDavid du Colombier 				}
9453e12c5d1SDavid du Colombier 				if(t2->etype == TOLD) {
9463e12c5d1SDavid du Colombier 					t2 = t2->down;
9473e12c5d1SDavid du Colombier 					continue;
9483e12c5d1SDavid du Colombier 				}
9493e12c5d1SDavid du Colombier 				while(t1 != T || t2 != T) {
9503e12c5d1SDavid du Colombier 					if(!rsametype(t1, t2, n))
9513e12c5d1SDavid du Colombier 						return 0;
9523e12c5d1SDavid du Colombier 					t1 = t1->down;
9533e12c5d1SDavid du Colombier 					t2 = t2->down;
9543e12c5d1SDavid du Colombier 				}
9553e12c5d1SDavid du Colombier 				break;
9563e12c5d1SDavid du Colombier 			}
9573e12c5d1SDavid du Colombier 			return 1;
9583e12c5d1SDavid du Colombier 		}
9593e12c5d1SDavid du Colombier 		t1 = t1->link;
9603e12c5d1SDavid du Colombier 		t2 = t2->link;
9613e12c5d1SDavid du Colombier 		if(typesu[et])
9623e12c5d1SDavid du Colombier 			for(;;) {
9633e12c5d1SDavid du Colombier 				if(t1 == t2)
9643e12c5d1SDavid du Colombier 					return 1;
9653e12c5d1SDavid du Colombier 				if(!rsametype(t1, t2, n))
9663e12c5d1SDavid du Colombier 					return 0;
9673e12c5d1SDavid du Colombier 				t1 = t1->down;
9683e12c5d1SDavid du Colombier 				t2 = t2->down;
9693e12c5d1SDavid du Colombier 			}
9703e12c5d1SDavid du Colombier 		if(et == TIND)
9713e12c5d1SDavid du Colombier 			if(t1->etype == TVOID || t2->etype == TVOID)
9723e12c5d1SDavid du Colombier 				return 1;
9733e12c5d1SDavid du Colombier 	}
9743e12c5d1SDavid du Colombier }
9753e12c5d1SDavid du Colombier 
976*219b2ee8SDavid du Colombier Type*
9773e12c5d1SDavid du Colombier dotag(Sym *s, int et, int bn)
9783e12c5d1SDavid du Colombier {
9793e12c5d1SDavid du Colombier 	Decl *d;
9803e12c5d1SDavid du Colombier 
9813e12c5d1SDavid du Colombier 	if(bn != 0 && bn != s->sueblock) {
9823e12c5d1SDavid du Colombier 		d = push();
9833e12c5d1SDavid du Colombier 		d->sym = s;
9843e12c5d1SDavid du Colombier 		d->val = DSUE;
9853e12c5d1SDavid du Colombier 		d->type = s->suetag;
9863e12c5d1SDavid du Colombier 		d->block = s->sueblock;
9873e12c5d1SDavid du Colombier 		s->suetag = T;
9883e12c5d1SDavid du Colombier 	}
9893e12c5d1SDavid du Colombier 	if(s->suetag == T) {
9903e12c5d1SDavid du Colombier 		s->suetag = typ(et, T);
9913e12c5d1SDavid du Colombier 		s->sueblock = autobn;
9923e12c5d1SDavid du Colombier 	}
9933e12c5d1SDavid du Colombier 	if(s->suetag->etype != et)
9943e12c5d1SDavid du Colombier 		diag(Z, "tag used for more than one type: %s",
9953e12c5d1SDavid du Colombier 			s->name);
9963e12c5d1SDavid du Colombier 	if(s->suetag->tag == S)
9973e12c5d1SDavid du Colombier 		s->suetag->tag = s;
998*219b2ee8SDavid du Colombier 	return s->suetag;
9993e12c5d1SDavid du Colombier }
10003e12c5d1SDavid du Colombier 
10013e12c5d1SDavid du Colombier Node*
10023e12c5d1SDavid du Colombier dcllabel(Sym *s, int f)
10033e12c5d1SDavid du Colombier {
10043e12c5d1SDavid du Colombier 	Decl *d, d1;
10053e12c5d1SDavid du Colombier 	Node *n;
10063e12c5d1SDavid du Colombier 
10073e12c5d1SDavid du Colombier 	n = s->label;
10083e12c5d1SDavid du Colombier 	if(n != Z) {
10093e12c5d1SDavid du Colombier 		if(f) {
10103e12c5d1SDavid du Colombier 			if(n->complex)
10113e12c5d1SDavid du Colombier 				diag(Z, "label reused: %s", s->name);
10123e12c5d1SDavid du Colombier 			n->complex = 1;
10133e12c5d1SDavid du Colombier 		}
10143e12c5d1SDavid du Colombier 		return n;
10153e12c5d1SDavid du Colombier 	}
10163e12c5d1SDavid du Colombier 
10173e12c5d1SDavid du Colombier 	d = push();
10183e12c5d1SDavid du Colombier 	d->sym = s;
10193e12c5d1SDavid du Colombier 	d->val = DLABEL;
10203e12c5d1SDavid du Colombier 	dclstack = d->link;
10213e12c5d1SDavid du Colombier 
10223e12c5d1SDavid du Colombier 	d1 = *firstdcl;
10233e12c5d1SDavid du Colombier 	*firstdcl = *d;
10243e12c5d1SDavid du Colombier 	*d = d1;
10253e12c5d1SDavid du Colombier 
10263e12c5d1SDavid du Colombier 	firstdcl->link = d;
10273e12c5d1SDavid du Colombier 	firstdcl = d;
10283e12c5d1SDavid du Colombier 
10293e12c5d1SDavid du Colombier 	n = new(OXXX, Z, Z);
10303e12c5d1SDavid du Colombier 	n->sym = s;
10313e12c5d1SDavid du Colombier 	n->complex = f;
10323e12c5d1SDavid du Colombier 	s->label = n;
10333e12c5d1SDavid du Colombier 
10343e12c5d1SDavid du Colombier 	if(debug['d'])
10353e12c5d1SDavid du Colombier 		dbgdecl(s);
10363e12c5d1SDavid du Colombier 	return n;
10373e12c5d1SDavid du Colombier }
10383e12c5d1SDavid du Colombier 
10393e12c5d1SDavid du Colombier Type*
10403e12c5d1SDavid du Colombier paramconv(Type *t, int f)
10413e12c5d1SDavid du Colombier {
10423e12c5d1SDavid du Colombier 
10433e12c5d1SDavid du Colombier 	switch(t->etype) {
10443e12c5d1SDavid du Colombier 	case TARRAY:
10453e12c5d1SDavid du Colombier 		t = typ(TIND, t->link);
10463e12c5d1SDavid du Colombier 		t->width = types[TIND]->width;
10473e12c5d1SDavid du Colombier 		break;
10483e12c5d1SDavid du Colombier 
10493e12c5d1SDavid du Colombier 	case TFUNC:
10503e12c5d1SDavid du Colombier 		t = typ(TIND, t);
10513e12c5d1SDavid du Colombier 		t->width = types[TIND]->width;
10523e12c5d1SDavid du Colombier 		break;
10533e12c5d1SDavid du Colombier 
10543e12c5d1SDavid du Colombier 	case TFLOAT:
10553e12c5d1SDavid du Colombier 		if(!f)
10563e12c5d1SDavid du Colombier 			t = types[TDOUBLE];
10573e12c5d1SDavid du Colombier 		break;
10583e12c5d1SDavid du Colombier 
10593e12c5d1SDavid du Colombier 	case TCHAR:
10603e12c5d1SDavid du Colombier 	case TSHORT:
10613e12c5d1SDavid du Colombier 		if(!f)
10623e12c5d1SDavid du Colombier 			t = tint;
10633e12c5d1SDavid du Colombier 		break;
10643e12c5d1SDavid du Colombier 
10653e12c5d1SDavid du Colombier 	case TUCHAR:
10663e12c5d1SDavid du Colombier 	case TUSHORT:
10673e12c5d1SDavid du Colombier 		if(!f)
10683e12c5d1SDavid du Colombier 			t = tuint;
10693e12c5d1SDavid du Colombier 		break;
10703e12c5d1SDavid du Colombier 	}
10713e12c5d1SDavid du Colombier 	return t;
10723e12c5d1SDavid du Colombier }
10733e12c5d1SDavid du Colombier 
10743e12c5d1SDavid du Colombier void
10753e12c5d1SDavid du Colombier adecl(int c, Type *t, Sym *s)
10763e12c5d1SDavid du Colombier {
10773e12c5d1SDavid du Colombier 
10783e12c5d1SDavid du Colombier 	if(c == CSTATIC)
10793e12c5d1SDavid du Colombier 		c = CLOCAL;
10803e12c5d1SDavid du Colombier 	if(t->etype == TFUNC) {
10813e12c5d1SDavid du Colombier 		if(c == CXXX)
10823e12c5d1SDavid du Colombier 			c = CEXTERN;
10833e12c5d1SDavid du Colombier 		if(c == CLOCAL)
10843e12c5d1SDavid du Colombier 			c = CSTATIC;
10853e12c5d1SDavid du Colombier 		if(c == CAUTO || c == CEXREG)
10863e12c5d1SDavid du Colombier 			diag(Z, "function cannot be %s %s", cnames[c], s->name);
10873e12c5d1SDavid du Colombier 	}
10883e12c5d1SDavid du Colombier 	if(c == CXXX)
10893e12c5d1SDavid du Colombier 		c = CAUTO;
1090*219b2ee8SDavid du Colombier 	if(s) {
1091*219b2ee8SDavid du Colombier 		if(s->class == CSTATIC)
1092*219b2ee8SDavid du Colombier 			if(c == CEXTERN || c == CGLOBL)
1093*219b2ee8SDavid du Colombier 				c = CSTATIC;
10943e12c5d1SDavid du Colombier 		if(s->class == CAUTO || s->class == CPARAM || s->class == CLOCAL)
10953e12c5d1SDavid du Colombier 		if(s->block == autobn)
10963e12c5d1SDavid du Colombier 			diag(Z, "auto redeclaration of: %s", s->name);
10973e12c5d1SDavid du Colombier 		if(c != CPARAM)
10983e12c5d1SDavid du Colombier 			push1(s);
10993e12c5d1SDavid du Colombier 		s->block = autobn;
11003e12c5d1SDavid du Colombier 		s->offset = 0;
11013e12c5d1SDavid du Colombier 		s->type = t;
11023e12c5d1SDavid du Colombier 		s->class = c;
11033e12c5d1SDavid du Colombier 		s->aused = 0;
1104*219b2ee8SDavid du Colombier 	}
11053e12c5d1SDavid du Colombier 
11063e12c5d1SDavid du Colombier 	if(c != CAUTO && c != CPARAM)
11073e12c5d1SDavid du Colombier 		return;
11083e12c5d1SDavid du Colombier 	if(c == CPARAM && autoffset == 0) {
11093e12c5d1SDavid du Colombier 		firstarg = s;
11103e12c5d1SDavid du Colombier 		firstargtype = t;
11113e12c5d1SDavid du Colombier 	}
11123e12c5d1SDavid du Colombier 	if(t->width < tint->width)
11133e12c5d1SDavid du Colombier 		autoffset += endian(t->width);
1114*219b2ee8SDavid du Colombier 	if(s)
11153e12c5d1SDavid du Colombier 		s->offset = autoffset;
11163e12c5d1SDavid du Colombier 	autoffset += t->width;
11173e12c5d1SDavid du Colombier 	autoffset += round(autoffset, tint->width);
11183e12c5d1SDavid du Colombier 	if(c == CAUTO)
11193e12c5d1SDavid du Colombier 		s->offset = -autoffset;
11203e12c5d1SDavid du Colombier 	if(autoffset > stkoff) {
11213e12c5d1SDavid du Colombier 		stkoff = autoffset;
11223e12c5d1SDavid du Colombier 		stkoff += round(stkoff, types[TLONG]->width);
11233e12c5d1SDavid du Colombier 	}
11243e12c5d1SDavid du Colombier }
11253e12c5d1SDavid du Colombier 
11263e12c5d1SDavid du Colombier void
11273e12c5d1SDavid du Colombier pdecl(int c, Type *t, Sym *s)
11283e12c5d1SDavid du Colombier {
1129*219b2ee8SDavid du Colombier 	if(s && s->offset != -1) {
11303e12c5d1SDavid du Colombier 		diag(Z, "not a parameter: %s", s->name);
11313e12c5d1SDavid du Colombier 		return;
11323e12c5d1SDavid du Colombier 	}
11333e12c5d1SDavid du Colombier 	t = paramconv(t, c==CPARAM);
11343e12c5d1SDavid du Colombier 	if(c == CXXX)
11353e12c5d1SDavid du Colombier 		c = CPARAM;
11363e12c5d1SDavid du Colombier 	if(c != CPARAM) {
11373e12c5d1SDavid du Colombier 		diag(Z, "parameter cannot have class: %s", s->name);
11383e12c5d1SDavid du Colombier 		c = CPARAM;
11393e12c5d1SDavid du Colombier 	}
11403e12c5d1SDavid du Colombier 	adecl(c, t, s);
11413e12c5d1SDavid du Colombier }
11423e12c5d1SDavid du Colombier 
11433e12c5d1SDavid du Colombier void
11443e12c5d1SDavid du Colombier xdecl(int c, Type *t, Sym *s)
11453e12c5d1SDavid du Colombier {
11463e12c5d1SDavid du Colombier 	long o;
11473e12c5d1SDavid du Colombier 
11483e12c5d1SDavid du Colombier 	o = 0;
11493e12c5d1SDavid du Colombier 	if(c == CEXREG) {
11503e12c5d1SDavid du Colombier 		o = exreg(t);
11513e12c5d1SDavid du Colombier 		if(o == 0)
11523e12c5d1SDavid du Colombier 			c = CEXTERN;
11533e12c5d1SDavid du Colombier 	}
11543e12c5d1SDavid du Colombier 	if(c == CXXX) {
11553e12c5d1SDavid du Colombier 		c = CGLOBL;
11563e12c5d1SDavid du Colombier 		if(s->class == CEXTERN)
11573e12c5d1SDavid du Colombier 			s->class = c;
11583e12c5d1SDavid du Colombier 	}
11593e12c5d1SDavid du Colombier 	if(c == CEXTERN)
11603e12c5d1SDavid du Colombier 		if(s->class == CGLOBL)
11613e12c5d1SDavid du Colombier 			c = CGLOBL;
11623e12c5d1SDavid du Colombier 	if(c == CAUTO) {
11633e12c5d1SDavid du Colombier 		diag(Z, "external declaration cannot be auto: %s", s->name);
11643e12c5d1SDavid du Colombier 		c = CEXTERN;
11653e12c5d1SDavid du Colombier 	}
11663e12c5d1SDavid du Colombier 	if(s->class == CSTATIC)
11673e12c5d1SDavid du Colombier 		if(c == CEXTERN || c == CGLOBL)
11683e12c5d1SDavid du Colombier 			c = CSTATIC;
11693e12c5d1SDavid du Colombier 	if(s->type != T)
11703e12c5d1SDavid du Colombier 		if(s->class != c || !sametype(t, s->type) || t->etype == TENUM) {
11713e12c5d1SDavid du Colombier 			diag(Z, "external redeclaration of: %s", s->name);
11723e12c5d1SDavid du Colombier 			print("	%T; %T\n", t, s->type);
11733e12c5d1SDavid du Colombier 		}
11743e12c5d1SDavid du Colombier 	tmerge(t, s);
11753e12c5d1SDavid du Colombier 	s->type = t;
11763e12c5d1SDavid du Colombier 	s->class = c;
11773e12c5d1SDavid du Colombier 	s->block = 0;
11783e12c5d1SDavid du Colombier 	s->offset = o;
11793e12c5d1SDavid du Colombier }
11803e12c5d1SDavid du Colombier 
11813e12c5d1SDavid du Colombier void
11823e12c5d1SDavid du Colombier tmerge(Type *t1, Sym *s)
11833e12c5d1SDavid du Colombier {
11843e12c5d1SDavid du Colombier 	Type *ta, *tb, *t2;
11853e12c5d1SDavid du Colombier 
11863e12c5d1SDavid du Colombier 	t2 = s->type;
11873e12c5d1SDavid du Colombier /*print("merge	%T; %T\n", t1, t2);/**/
11883e12c5d1SDavid du Colombier 	for(;;) {
11893e12c5d1SDavid du Colombier 		if(t1 == T || t2 == T || t1 == t2)
11903e12c5d1SDavid du Colombier 			break;
11913e12c5d1SDavid du Colombier 		if(t1->etype != t2->etype)
11923e12c5d1SDavid du Colombier 			break;
11933e12c5d1SDavid du Colombier 		switch(t1->etype) {
11943e12c5d1SDavid du Colombier 		case TFUNC:
11953e12c5d1SDavid du Colombier 			ta = t1->down;
11963e12c5d1SDavid du Colombier 			tb = t2->down;
11973e12c5d1SDavid du Colombier 			if(ta == T) {
11983e12c5d1SDavid du Colombier 				t1->down = tb;
11993e12c5d1SDavid du Colombier 				break;
12003e12c5d1SDavid du Colombier 			}
12013e12c5d1SDavid du Colombier 			if(tb == T)
12023e12c5d1SDavid du Colombier 				break;
12033e12c5d1SDavid du Colombier 			while(ta != T && tb != T) {
12043e12c5d1SDavid du Colombier 				if(ta == tb)
12053e12c5d1SDavid du Colombier 					break;
12063e12c5d1SDavid du Colombier 				/* ignore old-style flag */
12073e12c5d1SDavid du Colombier 				if(ta->etype == TOLD) {
12083e12c5d1SDavid du Colombier 					ta = ta->down;
12093e12c5d1SDavid du Colombier 					continue;
12103e12c5d1SDavid du Colombier 				}
12113e12c5d1SDavid du Colombier 				if(tb->etype == TOLD) {
12123e12c5d1SDavid du Colombier 					tb = tb->down;
12133e12c5d1SDavid du Colombier 					continue;
12143e12c5d1SDavid du Colombier 				}
12153e12c5d1SDavid du Colombier 				/* checking terminated by ... */
12163e12c5d1SDavid du Colombier 				if(ta->etype == TDOT && tb->etype == TDOT) {
12173e12c5d1SDavid du Colombier 					ta = T;
12183e12c5d1SDavid du Colombier 					tb = T;
12193e12c5d1SDavid du Colombier 					break;
12203e12c5d1SDavid du Colombier 				}
12213e12c5d1SDavid du Colombier 				if(!sametype(ta, tb))
12223e12c5d1SDavid du Colombier 					break;
12233e12c5d1SDavid du Colombier 				ta = ta->down;
12243e12c5d1SDavid du Colombier 				tb = tb->down;
12253e12c5d1SDavid du Colombier 			}
12263e12c5d1SDavid du Colombier 			if(ta != tb)
12273e12c5d1SDavid du Colombier 				diag(Z, "function inconsistently declared: %s", s->name);
12283e12c5d1SDavid du Colombier 
12293e12c5d1SDavid du Colombier 			/* take new-style over old-style */
12303e12c5d1SDavid du Colombier 			ta = t1->down;
12313e12c5d1SDavid du Colombier 			tb = t2->down;
12323e12c5d1SDavid du Colombier 			if(ta != T && ta->etype == TOLD)
12333e12c5d1SDavid du Colombier 				if(tb != T && tb->etype != TOLD)
12343e12c5d1SDavid du Colombier 					t1->down = tb;
12353e12c5d1SDavid du Colombier 			break;
12363e12c5d1SDavid du Colombier 
12373e12c5d1SDavid du Colombier 		case TARRAY:
12383e12c5d1SDavid du Colombier 			/* should we check array size change? */
12393e12c5d1SDavid du Colombier 			if(t2->width > t1->width)
12403e12c5d1SDavid du Colombier 				t1->width = t2->width;
12413e12c5d1SDavid du Colombier 			break;
12423e12c5d1SDavid du Colombier 
12433e12c5d1SDavid du Colombier 		case TUNION:
12443e12c5d1SDavid du Colombier 		case TSTRUCT:
12453e12c5d1SDavid du Colombier 			return;
12463e12c5d1SDavid du Colombier 		}
12473e12c5d1SDavid du Colombier 		t1 = t1->link;
12483e12c5d1SDavid du Colombier 		t2 = t2->link;
12493e12c5d1SDavid du Colombier 	}
12503e12c5d1SDavid du Colombier }
12513e12c5d1SDavid du Colombier 
12523e12c5d1SDavid du Colombier void
12533e12c5d1SDavid du Colombier edecl(int c, Type *t, Sym *s)
12543e12c5d1SDavid du Colombier {
12553e12c5d1SDavid du Colombier 	Type *t1;
12563e12c5d1SDavid du Colombier 
12573e12c5d1SDavid du Colombier 	if(s == S) {
12583e12c5d1SDavid du Colombier 		if(!typesu[t->etype])
12593e12c5d1SDavid du Colombier 			diag(Z, "unnamed structure element must be struct/union");
12603e12c5d1SDavid du Colombier 		if(c != CXXX)
12613e12c5d1SDavid du Colombier 			diag(Z, "unnamed structure element cannot have class");
12623e12c5d1SDavid du Colombier 	} else
12633e12c5d1SDavid du Colombier 		if(c != CXXX)
12643e12c5d1SDavid du Colombier 			diag(Z, "structure element cannot have class: %s", s->name);
12653e12c5d1SDavid du Colombier 	t1 = t;
12663e12c5d1SDavid du Colombier 	t = typ(TXXX, T);
12673e12c5d1SDavid du Colombier 	*t = *t1;
12683e12c5d1SDavid du Colombier 	t->sym = s;
12693e12c5d1SDavid du Colombier 	t->down = T;
12703e12c5d1SDavid du Colombier 	if(lastfield) {
12713e12c5d1SDavid du Colombier 		t->shift = lastbit - lastfield;
12723e12c5d1SDavid du Colombier 		t->nbits = lastfield;
12733e12c5d1SDavid du Colombier 		if(firstbit)
12743e12c5d1SDavid du Colombier 			t->shift = -t->shift;
12753e12c5d1SDavid du Colombier 	}
12763e12c5d1SDavid du Colombier 	if(strf == T)
12773e12c5d1SDavid du Colombier 		strf = t;
12783e12c5d1SDavid du Colombier 	else
12793e12c5d1SDavid du Colombier 		strl->down = t;
12803e12c5d1SDavid du Colombier 	strl = t;
12813e12c5d1SDavid du Colombier }
12823e12c5d1SDavid du Colombier 
12833e12c5d1SDavid du Colombier /*
1284*219b2ee8SDavid du Colombier  * this routine is very suspect.
1285*219b2ee8SDavid du Colombier  * ansi requires the enum type to
1286*219b2ee8SDavid du Colombier  * be represented as an 'int'
1287*219b2ee8SDavid du Colombier  * this means that 0x81234567
1288*219b2ee8SDavid du Colombier  * would be illegal. this routine
1289*219b2ee8SDavid du Colombier  * makes signed and unsigned go
1290*219b2ee8SDavid du Colombier  * to unsigned.
12913e12c5d1SDavid du Colombier  */
1292*219b2ee8SDavid du Colombier Type*
1293*219b2ee8SDavid du Colombier maxtype(Type *t1, Type *t2)
1294*219b2ee8SDavid du Colombier {
1295*219b2ee8SDavid du Colombier 
1296*219b2ee8SDavid du Colombier 	if(t1 == T)
1297*219b2ee8SDavid du Colombier 		return t2;
1298*219b2ee8SDavid du Colombier 	if(t2 == T)
1299*219b2ee8SDavid du Colombier 		return t1;
1300*219b2ee8SDavid du Colombier 	if(t1->etype > t2->etype)
1301*219b2ee8SDavid du Colombier 		return t1;
1302*219b2ee8SDavid du Colombier 	return t2;
13033e12c5d1SDavid du Colombier }
13043e12c5d1SDavid du Colombier 
13053e12c5d1SDavid du Colombier void
13063e12c5d1SDavid du Colombier doenum(Sym *s, Node *n)
13073e12c5d1SDavid du Colombier {
13083e12c5d1SDavid du Colombier 
13093e12c5d1SDavid du Colombier 	if(n) {
13103e12c5d1SDavid du Colombier 		complex(n);
1311*219b2ee8SDavid du Colombier 		if(n->op != OCONST) {
1312*219b2ee8SDavid du Colombier 			diag(n, "enum not a constant: %s", s->name);
13133e12c5d1SDavid du Colombier 			return;
13143e12c5d1SDavid du Colombier 		}
1315*219b2ee8SDavid du Colombier 		en.cenum = n->type;
1316*219b2ee8SDavid du Colombier 		en.tenum = maxtype(en.cenum, en.tenum);
1317*219b2ee8SDavid du Colombier 
1318*219b2ee8SDavid du Colombier 		if(!typefd[en.cenum->etype])
1319*219b2ee8SDavid du Colombier 			en.lastenum = n->vconst;
1320*219b2ee8SDavid du Colombier 		else
1321*219b2ee8SDavid du Colombier 			en.floatenum = n->fconst;
13223e12c5d1SDavid du Colombier 	}
13233e12c5d1SDavid du Colombier 	if(dclstack)
13243e12c5d1SDavid du Colombier 		push1(s);
13253e12c5d1SDavid du Colombier 	xdecl(CXXX, types[TENUM], s);
1326*219b2ee8SDavid du Colombier 
1327*219b2ee8SDavid du Colombier 	if(en.cenum == T) {
1328*219b2ee8SDavid du Colombier 		en.tenum = tint;
1329*219b2ee8SDavid du Colombier 		en.cenum = tint;
1330*219b2ee8SDavid du Colombier 		en.lastenum = 0;
1331*219b2ee8SDavid du Colombier 	}
1332*219b2ee8SDavid du Colombier 	s->tenum = en.cenum;
1333*219b2ee8SDavid du Colombier 
1334*219b2ee8SDavid du Colombier 	if(!typefd[s->tenum->etype]) {
1335*219b2ee8SDavid du Colombier 		s->vconst = convvtox(en.lastenum, s->tenum->etype);
1336*219b2ee8SDavid du Colombier 		en.lastenum++;
1337*219b2ee8SDavid du Colombier 	} else {
1338*219b2ee8SDavid du Colombier 		s->fconst = en.floatenum;
1339*219b2ee8SDavid du Colombier 		en.floatenum++;
1340*219b2ee8SDavid du Colombier 	}
1341*219b2ee8SDavid du Colombier 
13423e12c5d1SDavid du Colombier 	if(debug['d'])
13433e12c5d1SDavid du Colombier 		dbgdecl(s);
13443e12c5d1SDavid du Colombier }
13453e12c5d1SDavid du Colombier 
13463e12c5d1SDavid du Colombier void
13473e12c5d1SDavid du Colombier symadjust(Sym *s, Node *n, long del)
13483e12c5d1SDavid du Colombier {
13493e12c5d1SDavid du Colombier 
13503e12c5d1SDavid du Colombier 	switch(n->op) {
13513e12c5d1SDavid du Colombier 	default:
13523e12c5d1SDavid du Colombier 		if(n->left)
13533e12c5d1SDavid du Colombier 			symadjust(s, n->left, del);
13543e12c5d1SDavid du Colombier 		if(n->right)
13553e12c5d1SDavid du Colombier 			symadjust(s, n->right, del);
13563e12c5d1SDavid du Colombier 		return;
13573e12c5d1SDavid du Colombier 
13583e12c5d1SDavid du Colombier 	case ONAME:
13593e12c5d1SDavid du Colombier 		if(n->sym == s)
1360*219b2ee8SDavid du Colombier 			n->xoffset -= del;
13613e12c5d1SDavid du Colombier 		return;
13623e12c5d1SDavid du Colombier 
13633e12c5d1SDavid du Colombier 	case OCONST:
13643e12c5d1SDavid du Colombier 	case OSTRING:
13653e12c5d1SDavid du Colombier 	case OLSTRING:
13663e12c5d1SDavid du Colombier 	case OINDREG:
13673e12c5d1SDavid du Colombier 	case OREGISTER:
13683e12c5d1SDavid du Colombier 		return;
13693e12c5d1SDavid du Colombier 	}
13703e12c5d1SDavid du Colombier }
13713e12c5d1SDavid du Colombier 
13723e12c5d1SDavid du Colombier Node*
13733e12c5d1SDavid du Colombier contig(Sym *s, Node *n, long v)
13743e12c5d1SDavid du Colombier {
13753e12c5d1SDavid du Colombier 	Node *p, *r, *q, *m;
13763e12c5d1SDavid du Colombier 	long w;
13773e12c5d1SDavid du Colombier 
13783e12c5d1SDavid du Colombier 	if(n == Z)
13793e12c5d1SDavid du Colombier 		goto no;
13803e12c5d1SDavid du Colombier 	w = s->type->width;
13813e12c5d1SDavid du Colombier 
13823e12c5d1SDavid du Colombier 	/*
13833e12c5d1SDavid du Colombier 	 * nightmare: an automatic array whose size
13843e12c5d1SDavid du Colombier 	 * increases when it is initialized
13853e12c5d1SDavid du Colombier 	 */
13863e12c5d1SDavid du Colombier 	if(v != w) {
13873e12c5d1SDavid du Colombier 		if(v != 0)
13883e12c5d1SDavid du Colombier 			diag(n, "automatic adjustable array: %s", s->name);
13893e12c5d1SDavid du Colombier 		v = s->offset;
13903e12c5d1SDavid du Colombier 		autoffset += w;
13913e12c5d1SDavid du Colombier 		autoffset += round(autoffset, tint->width);
13923e12c5d1SDavid du Colombier 		s->offset = -autoffset;
13933e12c5d1SDavid du Colombier 		if(autoffset > stkoff) {
13943e12c5d1SDavid du Colombier 			stkoff = autoffset;
13953e12c5d1SDavid du Colombier 			stkoff += round(stkoff, types[TLONG]->width);
13963e12c5d1SDavid du Colombier 		}
13973e12c5d1SDavid du Colombier 		symadjust(s, n, v - s->offset);
13983e12c5d1SDavid du Colombier 	}
13993e12c5d1SDavid du Colombier 	if(w <= 4)
14003e12c5d1SDavid du Colombier 		goto no;
14013e12c5d1SDavid du Colombier 	if(n->op == OAS)
14023e12c5d1SDavid du Colombier 		if(n->left->type)
14033e12c5d1SDavid du Colombier 		if(n->left->type->width == w)
14043e12c5d1SDavid du Colombier 			goto no;
14053e12c5d1SDavid du Colombier 	while(w & 3)
14063e12c5d1SDavid du Colombier 		w++;	/* is this a bug?? */
14073e12c5d1SDavid du Colombier /*
14083e12c5d1SDavid du Colombier  * insert the following code
14093e12c5d1SDavid du Colombier  *
14103e12c5d1SDavid du Colombier 	*(long**)&X = (long*)((char*)X + sizeof(X));
14113e12c5d1SDavid du Colombier 	do {
14123e12c5d1SDavid du Colombier 		*(long**)&X -= 1;
14133e12c5d1SDavid du Colombier 		**(long**)&X = 0;
14143e12c5d1SDavid du Colombier 	} while(*(long**)&X);
14153e12c5d1SDavid du Colombier  */
14163e12c5d1SDavid du Colombier 
14173e12c5d1SDavid du Colombier 	for(q=n; q->op != ONAME; q=q->left)
14183e12c5d1SDavid du Colombier 		;
14193e12c5d1SDavid du Colombier 
14203e12c5d1SDavid du Colombier 	p = new(ONAME, Z, Z);
14213e12c5d1SDavid du Colombier 	*p = *q;
14223e12c5d1SDavid du Colombier 	p->type = typ(TIND, types[TLONG]);
1423*219b2ee8SDavid du Colombier 	p->xoffset = s->offset;
14243e12c5d1SDavid du Colombier 
14253e12c5d1SDavid du Colombier 	r = new(ONAME, Z, Z);
14263e12c5d1SDavid du Colombier 	*r = *p;
14273e12c5d1SDavid du Colombier 	r = new(OPOSTDEC, r, Z);
14283e12c5d1SDavid du Colombier 
14293e12c5d1SDavid du Colombier 	q = new(ONAME, Z, Z);
14303e12c5d1SDavid du Colombier 	*q = *p;
14313e12c5d1SDavid du Colombier 	q = new(OIND, q, Z);
14323e12c5d1SDavid du Colombier 
14333e12c5d1SDavid du Colombier 	m = new(OCONST, Z, Z);
1434*219b2ee8SDavid du Colombier 	m->vconst = 0;
14353e12c5d1SDavid du Colombier 	m->type = types[TLONG];
14363e12c5d1SDavid du Colombier 
14373e12c5d1SDavid du Colombier 	q = new(OAS, q, m);
14383e12c5d1SDavid du Colombier 
14393e12c5d1SDavid du Colombier 	r = new(OLIST, r, q);
14403e12c5d1SDavid du Colombier 
14413e12c5d1SDavid du Colombier 	q = new(ONAME, Z, Z);
14423e12c5d1SDavid du Colombier 	*q = *p;
14433e12c5d1SDavid du Colombier 	r = new(ODWHILE, q, r);
14443e12c5d1SDavid du Colombier 
14453e12c5d1SDavid du Colombier 	q = new(ONAME, Z, Z);
14463e12c5d1SDavid du Colombier 	*q = *p;
14473e12c5d1SDavid du Colombier 	q->type = q->type->link;
1448*219b2ee8SDavid du Colombier 	q->xoffset += w;
14493e12c5d1SDavid du Colombier 	q = new(OADDR, q, 0);
14503e12c5d1SDavid du Colombier 
14513e12c5d1SDavid du Colombier 	q = new(OAS, p, q);
14523e12c5d1SDavid du Colombier 	r = new(OLIST, q, r);
14533e12c5d1SDavid du Colombier 
14543e12c5d1SDavid du Colombier 	n = new(OLIST, r, n);
14553e12c5d1SDavid du Colombier 
14563e12c5d1SDavid du Colombier no:
14573e12c5d1SDavid du Colombier 	return n;
14583e12c5d1SDavid du Colombier }
1459