xref: /plan9/sys/src/cmd/cc/dcl.c (revision 82726826a7b3d40fb66339b4b0e95b60314f98b9)
13e12c5d1SDavid du Colombier #include "cc.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier Node*
dodecl(void (* f)(int,Type *,Sym *),int c,Type * t,Node * n)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)
29219b2ee8SDavid 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);
407dd7cddfSDavid du Colombier 		t->garb = n->garb;
413e12c5d1SDavid du Colombier 		n = n->left;
423e12c5d1SDavid du Colombier 		goto loop;
433e12c5d1SDavid du Colombier 
443e12c5d1SDavid du Colombier 	case OFUNC:
453e12c5d1SDavid du Colombier 		t = typ(TFUNC, t);
463e12c5d1SDavid du Colombier 		t->down = fnproto(n);
473e12c5d1SDavid du Colombier 		n = n->left;
483e12c5d1SDavid du Colombier 		goto loop;
493e12c5d1SDavid du Colombier 
503e12c5d1SDavid du Colombier 	case OBIT:
513e12c5d1SDavid du Colombier 		n1 = n->right;
523e12c5d1SDavid du Colombier 		complex(n1);
533e12c5d1SDavid du Colombier 		lastfield = -1;
543e12c5d1SDavid du Colombier 		if(n1->op == OCONST)
55219b2ee8SDavid du Colombier 			lastfield = n1->vconst;
563e12c5d1SDavid du Colombier 		if(lastfield < 0) {
573e12c5d1SDavid du Colombier 			diag(n, "field width must be non-negative constant");
583e12c5d1SDavid du Colombier 			lastfield = 1;
593e12c5d1SDavid du Colombier 		}
603e12c5d1SDavid du Colombier 		if(lastfield == 0) {
613e12c5d1SDavid du Colombier 			lastbit = 0;
623e12c5d1SDavid du Colombier 			firstbit = 1;
633e12c5d1SDavid du Colombier 			if(n->left != Z) {
643e12c5d1SDavid du Colombier 				diag(n, "zero width named field");
653e12c5d1SDavid du Colombier 				lastfield = 1;
663e12c5d1SDavid du Colombier 			}
673e12c5d1SDavid du Colombier 		}
68219b2ee8SDavid du Colombier 		if(!typei[t->etype]) {
693e12c5d1SDavid du Colombier 			diag(n, "field type must be int-like");
707dd7cddfSDavid du Colombier 			t = types[TINT];
713e12c5d1SDavid du Colombier 			lastfield = 1;
723e12c5d1SDavid du Colombier 		}
733e12c5d1SDavid du Colombier 		if(lastfield > tfield->width*8) {
743e12c5d1SDavid du Colombier 			diag(n, "field width larger than field unit");
753e12c5d1SDavid du Colombier 			lastfield = 1;
763e12c5d1SDavid du Colombier 		}
773e12c5d1SDavid du Colombier 		lastbit += lastfield;
783e12c5d1SDavid du Colombier 		if(lastbit > tfield->width*8) {
793e12c5d1SDavid du Colombier 			lastbit = lastfield;
803e12c5d1SDavid du Colombier 			firstbit = 1;
813e12c5d1SDavid du Colombier 		}
823e12c5d1SDavid du Colombier 		n = n->left;
833e12c5d1SDavid du Colombier 		goto loop;
843e12c5d1SDavid du Colombier 
853e12c5d1SDavid du Colombier 	case ONAME:
863e12c5d1SDavid du Colombier 		if(f == NODECL)
873e12c5d1SDavid du Colombier 			break;
883e12c5d1SDavid du Colombier 		s = n->sym;
893e12c5d1SDavid du Colombier 		(*f)(c, t, s);
903e12c5d1SDavid du Colombier 		if(s->class == CLOCAL)
913e12c5d1SDavid du Colombier 			s = mkstatic(s);
923e12c5d1SDavid du Colombier 		firstbit = 0;
933e12c5d1SDavid du Colombier 		n->sym = s;
943e12c5d1SDavid du Colombier 		n->type = s->type;
95219b2ee8SDavid du Colombier 		n->xoffset = s->offset;
963e12c5d1SDavid du Colombier 		n->class = s->class;
973e12c5d1SDavid du Colombier 		n->etype = TVOID;
983e12c5d1SDavid du Colombier 		if(n->type != T)
993e12c5d1SDavid du Colombier 			n->etype = n->type->etype;
1003e12c5d1SDavid du Colombier 		if(debug['d'])
1013e12c5d1SDavid du Colombier 			dbgdecl(s);
102219b2ee8SDavid du Colombier 		acidvar(s);
1033e12c5d1SDavid du Colombier 		s->varlineno = lineno;
1043e12c5d1SDavid du Colombier 		break;
1053e12c5d1SDavid du Colombier 	}
1063e12c5d1SDavid du Colombier 	lastdcl = t;
1073e12c5d1SDavid du Colombier 	return n;
1083e12c5d1SDavid du Colombier }
1093e12c5d1SDavid du Colombier 
1103e12c5d1SDavid du Colombier Sym*
mkstatic(Sym * s)1113e12c5d1SDavid du Colombier mkstatic(Sym *s)
1123e12c5d1SDavid du Colombier {
1133e12c5d1SDavid du Colombier 	Sym *s1;
1143e12c5d1SDavid du Colombier 
1153e12c5d1SDavid du Colombier 	if(s->class != CLOCAL)
1163e12c5d1SDavid du Colombier 		return s;
1179a747e4fSDavid du Colombier 	snprint(symb, NSYMB, "%s$%d", s->name, s->block);
1183e12c5d1SDavid du Colombier 	s1 = lookup();
1193e12c5d1SDavid du Colombier 	if(s1->class != CSTATIC) {
1203e12c5d1SDavid du Colombier 		s1->type = s->type;
1213e12c5d1SDavid du Colombier 		s1->offset = s->offset;
1223e12c5d1SDavid du Colombier 		s1->block = s->block;
1233e12c5d1SDavid du Colombier 		s1->class = CSTATIC;
1243e12c5d1SDavid du Colombier 	}
1253e12c5d1SDavid du Colombier 	return s1;
1263e12c5d1SDavid du Colombier }
1273e12c5d1SDavid du Colombier 
1283e12c5d1SDavid du Colombier /*
1293e12c5d1SDavid du Colombier  * make a copy of a typedef
130219b2ee8SDavid du Colombier  * the problem is to split out incomplete
1313e12c5d1SDavid du Colombier  * arrays so that it is in the variable
1323e12c5d1SDavid du Colombier  * rather than the typedef.
1333e12c5d1SDavid du Colombier  */
1343e12c5d1SDavid du Colombier Type*
tcopy(Type * t)1353e12c5d1SDavid du Colombier tcopy(Type *t)
1363e12c5d1SDavid du Colombier {
1373e12c5d1SDavid du Colombier 	Type *tl, *tx;
1383e12c5d1SDavid du Colombier 	int et;
1393e12c5d1SDavid du Colombier 
1403e12c5d1SDavid du Colombier 	if(t == T)
1413e12c5d1SDavid du Colombier 		return t;
1423e12c5d1SDavid du Colombier 	et = t->etype;
1433e12c5d1SDavid du Colombier 	if(typesu[et])
1443e12c5d1SDavid du Colombier 		return t;
1453e12c5d1SDavid du Colombier 	tl = tcopy(t->link);
1463e12c5d1SDavid du Colombier 	if(tl != t->link ||
1473e12c5d1SDavid du Colombier 	  (et == TARRAY && t->width == 0)) {
14880ee5cbfSDavid du Colombier 		tx = copytyp(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*
doinit(Sym * s,Type * t,long o,Node * a)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*
peekinit(void)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*
nextinit(void)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 	if(a == Z)
2213e12c5d1SDavid du Colombier 		return a;
2223e12c5d1SDavid du Colombier 	if(a->op == OLIST) {
2233e12c5d1SDavid du Colombier 		n = a->right;
2243e12c5d1SDavid du Colombier 		a = a->left;
2253e12c5d1SDavid du Colombier 	}
2263e12c5d1SDavid du Colombier 	if(a->op == OUSED) {
2273e12c5d1SDavid du Colombier 		a = a->left;
2283e12c5d1SDavid du Colombier 		b = new(OCONST, Z, Z);
2293e12c5d1SDavid du Colombier 		b->type = a->type->link;
2303e12c5d1SDavid du Colombier 		if(a->op == OSTRING) {
231219b2ee8SDavid du Colombier 			b->vconst = convvtox(*a->cstring, TCHAR);
232219b2ee8SDavid du Colombier 			a->cstring++;
2333e12c5d1SDavid du Colombier 		}
2343e12c5d1SDavid du Colombier 		if(a->op == OLSTRING) {
235*82726826SDavid du Colombier 			b->vconst = convvtox(*a->rstring, TRUNE);
236219b2ee8SDavid du Colombier 			a->rstring++;
2373e12c5d1SDavid du Colombier 		}
2383e12c5d1SDavid du Colombier 		a->type->width -= b->type->width;
2393e12c5d1SDavid du Colombier 		if(a->type->width <= 0)
2403e12c5d1SDavid du Colombier 			initlist = n;
2413e12c5d1SDavid du Colombier 		return b;
2423e12c5d1SDavid du Colombier 	}
2433e12c5d1SDavid du Colombier 	initlist = n;
2443e12c5d1SDavid du Colombier 	return a;
2453e12c5d1SDavid du Colombier }
2463e12c5d1SDavid du Colombier 
2473e12c5d1SDavid du Colombier int
isstruct(Node * a,Type * t)2483e12c5d1SDavid du Colombier isstruct(Node *a, Type *t)
2493e12c5d1SDavid du Colombier {
2503e12c5d1SDavid du Colombier 	Node *n;
2513e12c5d1SDavid du Colombier 
2523e12c5d1SDavid du Colombier 	switch(a->op) {
2533e12c5d1SDavid du Colombier 	case ODOTDOT:
2543e12c5d1SDavid du Colombier 		n = a->left;
2553e12c5d1SDavid du Colombier 		if(n && n->type && sametype(n->type, t))
2563e12c5d1SDavid du Colombier 			return 1;
2573e12c5d1SDavid du Colombier 	case OSTRING:
2583e12c5d1SDavid du Colombier 	case OLSTRING:
2593e12c5d1SDavid du Colombier 	case OCONST:
2603e12c5d1SDavid du Colombier 	case OINIT:
261219b2ee8SDavid du Colombier 	case OELEM:
2623e12c5d1SDavid du Colombier 		return 0;
2633e12c5d1SDavid du Colombier 	}
2643e12c5d1SDavid du Colombier 
2653e12c5d1SDavid du Colombier 	n = new(ODOTDOT, Z, Z);
2663e12c5d1SDavid du Colombier 	*n = *a;
2673e12c5d1SDavid du Colombier 
2683e12c5d1SDavid du Colombier 	/*
2693e12c5d1SDavid du Colombier 	 * ODOTDOT is a flag for tcom
2703e12c5d1SDavid du Colombier 	 * a second tcom will not be performed
2713e12c5d1SDavid du Colombier 	 */
2723e12c5d1SDavid du Colombier 	a->op = ODOTDOT;
2733e12c5d1SDavid du Colombier 	a->left = n;
2743e12c5d1SDavid du Colombier 	a->right = Z;
2753e12c5d1SDavid du Colombier 
2763e12c5d1SDavid du Colombier 	if(tcom(n))
2773e12c5d1SDavid du Colombier 		return 0;
2783e12c5d1SDavid du Colombier 
2793e12c5d1SDavid du Colombier 	if(sametype(n->type, t))
2803e12c5d1SDavid du Colombier 		return 1;
2813e12c5d1SDavid du Colombier 	return 0;
2823e12c5d1SDavid du Colombier }
2833e12c5d1SDavid du Colombier 
2843e12c5d1SDavid du Colombier Node*
init1(Sym * s,Type * t,long o,int exflag)2853e12c5d1SDavid du Colombier init1(Sym *s, Type *t, long o, int exflag)
2863e12c5d1SDavid du Colombier {
2877dd7cddfSDavid du Colombier 	Node *a, *l, *r, nod;
288219b2ee8SDavid du Colombier 	Type *t1;
2893e12c5d1SDavid du Colombier 	long e, w, so, mw;
2903e12c5d1SDavid du Colombier 
2913e12c5d1SDavid du Colombier 	a = peekinit();
2923e12c5d1SDavid du Colombier 	if(a == Z)
2933e12c5d1SDavid du Colombier 		return Z;
2943e12c5d1SDavid du Colombier 
2953e12c5d1SDavid du Colombier 	if(debug['i']) {
2963e12c5d1SDavid du Colombier 		print("t = %T; o = %ld; n = %s\n", t, o, s->name);
2973e12c5d1SDavid du Colombier 		prtree(a, "init1 value");
2983e12c5d1SDavid du Colombier 	}
2993e12c5d1SDavid du Colombier 
3003e12c5d1SDavid du Colombier 	if(exflag && a->op == OINIT)
3013e12c5d1SDavid du Colombier 		return doinit(s, t, o, nextinit());
3023e12c5d1SDavid du Colombier 
3033e12c5d1SDavid du Colombier 	switch(t->etype) {
3043e12c5d1SDavid du Colombier 	default:
3053e12c5d1SDavid du Colombier 		diag(Z, "unknown type in initialization: %T to: %s", t, s->name);
3063e12c5d1SDavid du Colombier 		return Z;
3073e12c5d1SDavid du Colombier 
3083e12c5d1SDavid du Colombier 	case TCHAR:
3093e12c5d1SDavid du Colombier 	case TUCHAR:
3107dd7cddfSDavid du Colombier 	case TINT:
3117dd7cddfSDavid du Colombier 	case TUINT:
3123e12c5d1SDavid du Colombier 	case TSHORT:
3133e12c5d1SDavid du Colombier 	case TUSHORT:
3143e12c5d1SDavid du Colombier 	case TLONG:
3153e12c5d1SDavid du Colombier 	case TULONG:
3163e12c5d1SDavid du Colombier 	case TVLONG:
3177dd7cddfSDavid du Colombier 	case TUVLONG:
3183e12c5d1SDavid du Colombier 	case TFLOAT:
3193e12c5d1SDavid du Colombier 	case TDOUBLE:
3203e12c5d1SDavid du Colombier 	case TIND:
3213e12c5d1SDavid du Colombier 	single:
322219b2ee8SDavid du Colombier 		if(a->op == OARRAY || a->op == OELEM)
3233e12c5d1SDavid du Colombier 			return Z;
3243e12c5d1SDavid du Colombier 
3253e12c5d1SDavid du Colombier 		a = nextinit();
3263e12c5d1SDavid du Colombier 		if(a == Z)
3273e12c5d1SDavid du Colombier 			return Z;
3283e12c5d1SDavid du Colombier 
3293e12c5d1SDavid du Colombier 		if(t->nbits)
3303e12c5d1SDavid du Colombier 			diag(Z, "cannot initialize bitfields");
3313e12c5d1SDavid du Colombier 		if(s->class == CAUTO) {
3323e12c5d1SDavid du Colombier 			l = new(ONAME, Z, Z);
3333e12c5d1SDavid du Colombier 			l->sym = s;
3343e12c5d1SDavid du Colombier 			l->type = t;
3353e12c5d1SDavid du Colombier 			l->etype = TVOID;
3363e12c5d1SDavid du Colombier 			if(s->type)
3373e12c5d1SDavid du Colombier 				l->etype = s->type->etype;
338219b2ee8SDavid du Colombier 			l->xoffset = s->offset + o;
3393e12c5d1SDavid du Colombier 			l->class = s->class;
3403e12c5d1SDavid du Colombier 
3417dd7cddfSDavid du Colombier 			l = new(OASI, l, a);
3423e12c5d1SDavid du Colombier 			return l;
3433e12c5d1SDavid du Colombier 		}
3443e12c5d1SDavid du Colombier 
3453e12c5d1SDavid du Colombier 		complex(a);
3463e12c5d1SDavid du Colombier 		if(a->type == T)
3473e12c5d1SDavid du Colombier 			return Z;
3483e12c5d1SDavid du Colombier 
3493e12c5d1SDavid du Colombier 		if(a->op == OCONST) {
350b05f4f54SDavid du Colombier 			if(vconst(a) && t->etype == TIND && a->type && a->type->etype != TIND){
351b05f4f54SDavid du Colombier 				diag(a, "initialize pointer to an integer: %s", s->name);
352b05f4f54SDavid du Colombier 				return Z;
353b05f4f54SDavid du Colombier 			}
3543e12c5d1SDavid du Colombier 			if(!sametype(a->type, t)) {
3557dd7cddfSDavid du Colombier 				/* hoop jumping to save malloc */
3567dd7cddfSDavid du Colombier 				if(nodcast == Z)
3577dd7cddfSDavid du Colombier 					nodcast = new(OCAST, Z, Z);
3587dd7cddfSDavid du Colombier 				nod = *nodcast;
3597dd7cddfSDavid du Colombier 				nod.left = a;
3607dd7cddfSDavid du Colombier 				nod.type = t;
3617dd7cddfSDavid du Colombier 				nod.lineno = a->lineno;
3627dd7cddfSDavid du Colombier 				complex(&nod);
3637dd7cddfSDavid du Colombier 				if(nod.type)
3647dd7cddfSDavid du Colombier 					*a = nod;
3653e12c5d1SDavid du Colombier 			}
3663e12c5d1SDavid du Colombier 			if(a->op != OCONST) {
3673e12c5d1SDavid du Colombier 				diag(a, "initializer is not a constant: %s",
3683e12c5d1SDavid du Colombier 					s->name);
3693e12c5d1SDavid du Colombier 				return Z;
3703e12c5d1SDavid du Colombier 			}
3713e12c5d1SDavid du Colombier 			if(vconst(a) == 0)
3723e12c5d1SDavid du Colombier 				return Z;
3733e12c5d1SDavid du Colombier 			goto gext;
3743e12c5d1SDavid du Colombier 		}
3753e12c5d1SDavid du Colombier 		if(t->etype == TIND) {
3763e12c5d1SDavid du Colombier 			while(a->op == OCAST) {
3773e12c5d1SDavid du Colombier 				warn(a, "CAST in initialization ignored");
3783e12c5d1SDavid du Colombier 				a = a->left;
3793e12c5d1SDavid du Colombier 			}
3803e12c5d1SDavid du Colombier 			if(!sametype(t, a->type)) {
38173e742d7SDavid du Colombier 				diag(a, "initialization of incompatible pointers: %s\n%T and %T",
38273e742d7SDavid du Colombier 					s->name, t, a->type);
3833e12c5d1SDavid du Colombier 			}
3843e12c5d1SDavid du Colombier 			if(a->op == OADDR)
3853e12c5d1SDavid du Colombier 				a = a->left;
3863e12c5d1SDavid du Colombier 			goto gext;
3873e12c5d1SDavid du Colombier 		}
388219b2ee8SDavid du Colombier 
3893e12c5d1SDavid du Colombier 		while(a->op == OCAST)
3903e12c5d1SDavid du Colombier 			a = a->left;
3913e12c5d1SDavid du Colombier 		if(a->op == OADDR) {
3927dd7cddfSDavid du Colombier 			warn(a, "initialize pointer to an integer: %s", s->name);
3933e12c5d1SDavid du Colombier 			a = a->left;
3943e12c5d1SDavid du Colombier 			goto gext;
3953e12c5d1SDavid du Colombier 		}
3963e12c5d1SDavid du Colombier 		diag(a, "initializer is not a constant: %s", s->name);
3973e12c5d1SDavid du Colombier 		return Z;
3983e12c5d1SDavid du Colombier 
3993e12c5d1SDavid du Colombier 	gext:
4003e12c5d1SDavid du Colombier 		gextern(s, a, o, t->width);
4013e12c5d1SDavid du Colombier 
4023e12c5d1SDavid du Colombier 		return Z;
4033e12c5d1SDavid du Colombier 
4043e12c5d1SDavid du Colombier 	case TARRAY:
4053e12c5d1SDavid du Colombier 		w = t->link->width;
4063e12c5d1SDavid du Colombier 		if(a->op == OSTRING || a->op == OLSTRING)
407219b2ee8SDavid du Colombier 		if(typei[t->link->etype]) {
4083e12c5d1SDavid du Colombier 			/*
4093e12c5d1SDavid du Colombier 			 * get rid of null if sizes match exactly
4103e12c5d1SDavid du Colombier 			 */
4113e12c5d1SDavid du Colombier 			a = nextinit();
4123e12c5d1SDavid du Colombier 			mw = t->width/w;
4133e12c5d1SDavid du Colombier 			so = a->type->width/a->type->link->width;
4143e12c5d1SDavid du Colombier 			if(mw && so > mw) {
4153e12c5d1SDavid du Colombier 				if(so != mw+1)
4163e12c5d1SDavid du Colombier 					diag(a, "string initialization larger than array");
4173e12c5d1SDavid du Colombier 				a->type->width -= a->type->link->width;
4183e12c5d1SDavid du Colombier 			}
4193e12c5d1SDavid du Colombier 
4203e12c5d1SDavid du Colombier 			/*
4213e12c5d1SDavid du Colombier 			 * arrange strings to be expanded
4223e12c5d1SDavid du Colombier 			 * inside OINIT braces.
4233e12c5d1SDavid du Colombier 			 */
4243e12c5d1SDavid du Colombier 			a = new(OUSED, a, Z);
4253e12c5d1SDavid du Colombier 			return doinit(s, t, o, a);
4263e12c5d1SDavid du Colombier 		}
4273e12c5d1SDavid du Colombier 
4283e12c5d1SDavid du Colombier 		mw = -w;
4293e12c5d1SDavid du Colombier 		l = Z;
4303e12c5d1SDavid du Colombier 		for(e=0;;) {
4313e12c5d1SDavid du Colombier 			/*
4323e12c5d1SDavid du Colombier 			 * peek ahead for element initializer
4333e12c5d1SDavid du Colombier 			 */
4343e12c5d1SDavid du Colombier 			a = peekinit();
4353e12c5d1SDavid du Colombier 			if(a == Z)
4363e12c5d1SDavid du Colombier 				break;
437219b2ee8SDavid du Colombier 			if(a->op == OELEM && t->link->etype != TSTRUCT)
438219b2ee8SDavid du Colombier 				break;
4393e12c5d1SDavid du Colombier 			if(a->op == OARRAY) {
4407dd7cddfSDavid du Colombier 				if(e && exflag)
4417dd7cddfSDavid du Colombier 					break;
4423e12c5d1SDavid du Colombier 				a = nextinit();
4433e12c5d1SDavid du Colombier 				r = a->left;
4443e12c5d1SDavid du Colombier 				complex(r);
4453e12c5d1SDavid du Colombier 				if(r->op != OCONST) {
4463e12c5d1SDavid du Colombier 					diag(r, "initializer subscript must be constant");
4473e12c5d1SDavid du Colombier 					return Z;
4483e12c5d1SDavid du Colombier 				}
449219b2ee8SDavid du Colombier 				e = r->vconst;
4503e12c5d1SDavid du Colombier 				if(t->width != 0)
4513e12c5d1SDavid du Colombier 					if(e < 0 || e*w >= t->width) {
4527dd7cddfSDavid du Colombier 						diag(a, "initialization index out of range: %ld", e);
4533e12c5d1SDavid du Colombier 						continue;
4543e12c5d1SDavid du Colombier 					}
4557dd7cddfSDavid du Colombier 			}
4563e12c5d1SDavid du Colombier 
4573e12c5d1SDavid du Colombier 			so = e*w;
4583e12c5d1SDavid du Colombier 			if(so > mw)
4593e12c5d1SDavid du Colombier 				mw = so;
4603e12c5d1SDavid du Colombier 			if(t->width != 0)
4613e12c5d1SDavid du Colombier 				if(mw >= t->width)
4623e12c5d1SDavid du Colombier 					break;
4633e12c5d1SDavid du Colombier 			r = init1(s, t->link, o+so, 1);
4643e12c5d1SDavid du Colombier 			l = newlist(l, r);
4653e12c5d1SDavid du Colombier 			e++;
4663e12c5d1SDavid du Colombier 		}
4673e12c5d1SDavid du Colombier 		if(t->width == 0)
4683e12c5d1SDavid du Colombier 			t->width = mw+w;
4693e12c5d1SDavid du Colombier 		return l;
4703e12c5d1SDavid du Colombier 
4713e12c5d1SDavid du Colombier 	case TUNION:
4723e12c5d1SDavid du Colombier 	case TSTRUCT:
4733e12c5d1SDavid du Colombier 		/*
4743e12c5d1SDavid du Colombier 		 * peek ahead to find type of rhs.
4753e12c5d1SDavid du Colombier 		 * if its a structure, then treat
4763e12c5d1SDavid du Colombier 		 * this element as a variable
4773e12c5d1SDavid du Colombier 		 * rather than an aggregate.
4783e12c5d1SDavid du Colombier 		 */
4793e12c5d1SDavid du Colombier 		if(isstruct(a, t))
4803e12c5d1SDavid du Colombier 			goto single;
4813e12c5d1SDavid du Colombier 
4823e12c5d1SDavid du Colombier 		if(t->width <= 0) {
4833e12c5d1SDavid du Colombier 			diag(Z, "incomplete structure: %s", s->name);
4843e12c5d1SDavid du Colombier 			return Z;
4853e12c5d1SDavid du Colombier 		}
4863e12c5d1SDavid du Colombier 		l = Z;
487219b2ee8SDavid du Colombier 
488219b2ee8SDavid du Colombier 	again:
489219b2ee8SDavid du Colombier 		for(t1 = t->link; t1 != T; t1 = t1->down) {
490219b2ee8SDavid du Colombier 			if(a->op == OARRAY && t1->etype != TARRAY)
491219b2ee8SDavid du Colombier 				break;
492219b2ee8SDavid du Colombier 			if(a->op == OELEM) {
493219b2ee8SDavid du Colombier 				if(t1->sym != a->sym)
494219b2ee8SDavid du Colombier 					continue;
495219b2ee8SDavid du Colombier 				nextinit();
496219b2ee8SDavid du Colombier 			}
497219b2ee8SDavid du Colombier 			r = init1(s, t1, o+t1->offset, 1);
498219b2ee8SDavid du Colombier 			l = newlist(l, r);
4993e12c5d1SDavid du Colombier 			a = peekinit();
5003e12c5d1SDavid du Colombier 			if(a == Z)
5013e12c5d1SDavid du Colombier 				break;
502219b2ee8SDavid du Colombier 			if(a->op == OELEM)
503219b2ee8SDavid du Colombier 				goto again;
5043e12c5d1SDavid du Colombier 		}
505219b2ee8SDavid du Colombier 		if(a && a->op == OELEM)
506219b2ee8SDavid du Colombier 			diag(a, "structure element not found %F", a);
5073e12c5d1SDavid du Colombier 		return l;
5083e12c5d1SDavid du Colombier 	}
5093e12c5d1SDavid du Colombier }
5103e12c5d1SDavid du Colombier 
5113e12c5d1SDavid du Colombier Node*
newlist(Node * l,Node * r)5123e12c5d1SDavid du Colombier newlist(Node *l, Node *r)
5133e12c5d1SDavid du Colombier {
5143e12c5d1SDavid du Colombier 	if(r == Z)
5153e12c5d1SDavid du Colombier 		return l;
5163e12c5d1SDavid du Colombier 	if(l == Z)
5173e12c5d1SDavid du Colombier 		return r;
5183e12c5d1SDavid du Colombier 	return new(OLIST, l, r);
5193e12c5d1SDavid du Colombier }
5203e12c5d1SDavid du Colombier 
5213e12c5d1SDavid du Colombier void
sualign(Type * t)522d40255d8SDavid du Colombier sualign(Type *t)
5233e12c5d1SDavid du Colombier {
5243e12c5d1SDavid du Colombier 	Type *l;
5253e12c5d1SDavid du Colombier 	long o, w;
5263e12c5d1SDavid du Colombier 
5273e12c5d1SDavid du Colombier 	o = 0;
5283e12c5d1SDavid du Colombier 	switch(t->etype) {
5293e12c5d1SDavid du Colombier 
5303e12c5d1SDavid du Colombier 	case TSTRUCT:
5313e12c5d1SDavid du Colombier 		t->offset = 0;
5323e12c5d1SDavid du Colombier 		w = 0;
5333e12c5d1SDavid du Colombier 		for(l = t->link; l != T; l = l->down) {
5343e12c5d1SDavid du Colombier 			if(l->nbits) {
5353e12c5d1SDavid du Colombier 				if(l->shift <= 0) {
5363e12c5d1SDavid du Colombier 					l->shift = -l->shift;
5377dd7cddfSDavid du Colombier 					w = round(w, tfield->width);
5383e12c5d1SDavid du Colombier 					o = w;
5393e12c5d1SDavid du Colombier 					w += tfield->width;
5403e12c5d1SDavid du Colombier 				}
5413e12c5d1SDavid du Colombier 				l->offset = o;
5423e12c5d1SDavid du Colombier 			} else {
5437fd2696aSDavid du Colombier 				if(l->width < 0 ||
5447fd2696aSDavid du Colombier 				   l->width == 0 && l->down != T)
5453e12c5d1SDavid du Colombier 					if(l->sym)
5463e12c5d1SDavid du Colombier 						diag(Z, "incomplete structure element: %s",
5473e12c5d1SDavid du Colombier 							l->sym->name);
5483e12c5d1SDavid du Colombier 					else
5493e12c5d1SDavid du Colombier 						diag(Z, "incomplete structure element");
5507dd7cddfSDavid du Colombier 				w = align(w, l, Ael1);
5513e12c5d1SDavid du Colombier 				l->offset = w;
5527dd7cddfSDavid du Colombier 				w = align(w, l, Ael2);
5533e12c5d1SDavid du Colombier 			}
5543e12c5d1SDavid du Colombier 		}
5557dd7cddfSDavid du Colombier 		w = align(w, t, Asu2);
5563e12c5d1SDavid du Colombier 		t->width = w;
557219b2ee8SDavid du Colombier 		acidtype(t);
55880ee5cbfSDavid du Colombier 		pickletype(t);
5593e12c5d1SDavid du Colombier 		return;
5603e12c5d1SDavid du Colombier 
5613e12c5d1SDavid du Colombier 	case TUNION:
5623e12c5d1SDavid du Colombier 		t->offset = 0;
5633e12c5d1SDavid du Colombier 		w = 0;
5643e12c5d1SDavid du Colombier 		for(l = t->link; l != T; l = l->down) {
5653e12c5d1SDavid du Colombier 			if(l->width <= 0)
5663e12c5d1SDavid du Colombier 				if(l->sym)
5673e12c5d1SDavid du Colombier 					diag(Z, "incomplete union element: %s",
5683e12c5d1SDavid du Colombier 						l->sym->name);
5693e12c5d1SDavid du Colombier 				else
5703e12c5d1SDavid du Colombier 					diag(Z, "incomplete union element");
5713e12c5d1SDavid du Colombier 			l->offset = 0;
5723e12c5d1SDavid du Colombier 			l->shift = 0;
5737dd7cddfSDavid du Colombier 			o = align(align(0, l, Ael1), l, Ael2);
5747dd7cddfSDavid du Colombier 			if(o > w)
5757dd7cddfSDavid du Colombier 				w = o;
5763e12c5d1SDavid du Colombier 		}
5777dd7cddfSDavid du Colombier 		w = align(w, t, Asu2);
5783e12c5d1SDavid du Colombier 		t->width = w;
579219b2ee8SDavid du Colombier 		acidtype(t);
58080ee5cbfSDavid du Colombier 		pickletype(t);
5813e12c5d1SDavid du Colombier 		return;
5823e12c5d1SDavid du Colombier 
5833e12c5d1SDavid du Colombier 	default:
584d40255d8SDavid du Colombier 		diag(Z, "unknown type in sualign: %T", t);
5853e12c5d1SDavid du Colombier 		break;
5863e12c5d1SDavid du Colombier 	}
5873e12c5d1SDavid du Colombier }
5883e12c5d1SDavid du Colombier 
5897dd7cddfSDavid du Colombier long
round(long v,int w)5907dd7cddfSDavid du Colombier round(long v, int w)
5913e12c5d1SDavid du Colombier {
5923e12c5d1SDavid du Colombier 	int r;
5933e12c5d1SDavid du Colombier 
5947dd7cddfSDavid du Colombier 	if(w <= 0 || w > 8) {
5953e12c5d1SDavid du Colombier 		diag(Z, "rounding by %d", w);
5963e12c5d1SDavid du Colombier 		w = 1;
5973e12c5d1SDavid du Colombier 	}
5983e12c5d1SDavid du Colombier 	r = v%w;
5993e12c5d1SDavid du Colombier 	if(r)
6007dd7cddfSDavid du Colombier 		v += w-r;
6017dd7cddfSDavid du Colombier 	return v;
6023e12c5d1SDavid du Colombier }
6033e12c5d1SDavid du Colombier 
6043e12c5d1SDavid du Colombier Type*
ofnproto(Node * n)6053e12c5d1SDavid du Colombier ofnproto(Node *n)
6063e12c5d1SDavid du Colombier {
6073e12c5d1SDavid du Colombier 	Type *tl, *tr, *t;
6083e12c5d1SDavid du Colombier 
6093e12c5d1SDavid du Colombier 	if(n == Z)
6103e12c5d1SDavid du Colombier 		return T;
6113e12c5d1SDavid du Colombier 	switch(n->op) {
6123e12c5d1SDavid du Colombier 	case OLIST:
6133e12c5d1SDavid du Colombier 		tl = ofnproto(n->left);
6143e12c5d1SDavid du Colombier 		tr = ofnproto(n->right);
6153e12c5d1SDavid du Colombier 		if(tl == T)
6163e12c5d1SDavid du Colombier 			return tr;
6173e12c5d1SDavid du Colombier 		tl->down = tr;
6183e12c5d1SDavid du Colombier 		return tl;
6193e12c5d1SDavid du Colombier 
6203e12c5d1SDavid du Colombier 	case ONAME:
62180ee5cbfSDavid du Colombier 		t = copytyp(n->sym->type);
6223e12c5d1SDavid du Colombier 		t->down = T;
6233e12c5d1SDavid du Colombier 		return t;
6243e12c5d1SDavid du Colombier 	}
6253e12c5d1SDavid du Colombier 	return T;
6263e12c5d1SDavid du Colombier }
6273e12c5d1SDavid du Colombier 
6283e12c5d1SDavid du Colombier #define	ANSIPROTO	1
6293e12c5d1SDavid du Colombier #define	OLDPROTO	2
6303e12c5d1SDavid du Colombier 
6313e12c5d1SDavid du Colombier void
argmark(Node * n,int pass)6323e12c5d1SDavid du Colombier argmark(Node *n, int pass)
6333e12c5d1SDavid du Colombier {
6343e12c5d1SDavid du Colombier 	Type *t;
6353e12c5d1SDavid du Colombier 
6367dd7cddfSDavid du Colombier 	autoffset = align(0, thisfn->link, Aarg0);
6373e12c5d1SDavid du Colombier 	stkoff = 0;
6383e12c5d1SDavid du Colombier 	for(; n->left != Z; n = n->left) {
6393e12c5d1SDavid du Colombier 		if(n->op != OFUNC || n->left->op != ONAME)
6403e12c5d1SDavid du Colombier 			continue;
6413e12c5d1SDavid du Colombier 		walkparam(n->right, pass);
6423e12c5d1SDavid du Colombier 		if(pass != 0 && anyproto(n->right) == OLDPROTO) {
6433e12c5d1SDavid du Colombier 			t = typ(TFUNC, n->left->sym->type->link);
6443e12c5d1SDavid du Colombier 			t->down = typ(TOLD, T);
6453e12c5d1SDavid du Colombier 			t->down->down = ofnproto(n->right);
6463e12c5d1SDavid du Colombier 			tmerge(t, n->left->sym);
6473e12c5d1SDavid du Colombier 			n->left->sym->type = t;
6483e12c5d1SDavid du Colombier 		}
6493e12c5d1SDavid du Colombier 		break;
6503e12c5d1SDavid du Colombier 	}
6513e12c5d1SDavid du Colombier 	autoffset = 0;
6523e12c5d1SDavid du Colombier 	stkoff = 0;
6533e12c5d1SDavid du Colombier }
6543e12c5d1SDavid du Colombier 
6553e12c5d1SDavid du Colombier void
walkparam(Node * n,int pass)6563e12c5d1SDavid du Colombier walkparam(Node *n, int pass)
6573e12c5d1SDavid du Colombier {
6583e12c5d1SDavid du Colombier 	Sym *s;
659219b2ee8SDavid du Colombier 	Node *n1;
6603e12c5d1SDavid du Colombier 
6613e12c5d1SDavid du Colombier 	if(n != Z && n->op == OPROTO && n->left == Z && n->type == types[TVOID])
6623e12c5d1SDavid du Colombier 		return;
6633e12c5d1SDavid du Colombier 
6643e12c5d1SDavid du Colombier loop:
6653e12c5d1SDavid du Colombier 	if(n == Z)
6663e12c5d1SDavid du Colombier 		return;
6673e12c5d1SDavid du Colombier 	switch(n->op) {
6683e12c5d1SDavid du Colombier 	default:
6693e12c5d1SDavid du Colombier 		diag(n, "argument not a name/prototype: %O", n->op);
6703e12c5d1SDavid du Colombier 		break;
6713e12c5d1SDavid du Colombier 
6723e12c5d1SDavid du Colombier 	case OLIST:
6733e12c5d1SDavid du Colombier 		walkparam(n->left, pass);
6743e12c5d1SDavid du Colombier 		n = n->right;
6753e12c5d1SDavid du Colombier 		goto loop;
6763e12c5d1SDavid du Colombier 
6773e12c5d1SDavid du Colombier 	case OPROTO:
678219b2ee8SDavid du Colombier 		for(n1 = n; n1 != Z; n1=n1->left)
679219b2ee8SDavid du Colombier 			if(n1->op == ONAME) {
6803e12c5d1SDavid du Colombier 				if(pass == 0) {
681219b2ee8SDavid du Colombier 					s = n1->sym;
6823e12c5d1SDavid du Colombier 					push1(s);
6833e12c5d1SDavid du Colombier 					s->offset = -1;
6843e12c5d1SDavid du Colombier 					break;
6853e12c5d1SDavid du Colombier 				}
686219b2ee8SDavid du Colombier 				dodecl(pdecl, CPARAM, n->type, n->left);
6873e12c5d1SDavid du Colombier 				break;
6883e12c5d1SDavid du Colombier 			}
689219b2ee8SDavid du Colombier 		if(n1)
690219b2ee8SDavid du Colombier 			break;
691219b2ee8SDavid du Colombier 		if(pass == 0) {
692219b2ee8SDavid du Colombier 			/*
693219b2ee8SDavid du Colombier 			 * extension:
694219b2ee8SDavid du Colombier 			 *	allow no name in argument declaration
695219b2ee8SDavid du Colombier 			diag(Z, "no name in argument declaration");
696219b2ee8SDavid du Colombier 			 */
697219b2ee8SDavid du Colombier 			break;
698219b2ee8SDavid du Colombier 		}
699219b2ee8SDavid du Colombier 		dodecl(NODECL, CPARAM, n->type, n->left);
700219b2ee8SDavid du Colombier 		pdecl(CPARAM, lastdcl, S);
7013e12c5d1SDavid du Colombier 		break;
7023e12c5d1SDavid du Colombier 
7033e12c5d1SDavid du Colombier 	case ODOTDOT:
7043e12c5d1SDavid du Colombier 		break;
7053e12c5d1SDavid du Colombier 
7063e12c5d1SDavid du Colombier 	case ONAME:
7073e12c5d1SDavid du Colombier 		s = n->sym;
7083e12c5d1SDavid du Colombier 		if(pass == 0) {
7093e12c5d1SDavid du Colombier 			push1(s);
7103e12c5d1SDavid du Colombier 			s->offset = -1;
7113e12c5d1SDavid du Colombier 			break;
7123e12c5d1SDavid du Colombier 		}
7133e12c5d1SDavid du Colombier 		if(s->offset != -1) {
7143e12c5d1SDavid du Colombier 			if(autoffset == 0) {
7153e12c5d1SDavid du Colombier 				firstarg = s;
7163e12c5d1SDavid du Colombier 				firstargtype = s->type;
7173e12c5d1SDavid du Colombier 			}
7187dd7cddfSDavid du Colombier 			autoffset = align(autoffset, s->type, Aarg1);
7193e12c5d1SDavid du Colombier 			s->offset = autoffset;
7207dd7cddfSDavid du Colombier 			autoffset = align(autoffset, s->type, Aarg2);
7213e12c5d1SDavid du Colombier 		} else
7227dd7cddfSDavid du Colombier 			dodecl(pdecl, CXXX, types[TINT], n);
7233e12c5d1SDavid du Colombier 		break;
7243e12c5d1SDavid du Colombier 	}
7253e12c5d1SDavid du Colombier }
7263e12c5d1SDavid du Colombier 
7273e12c5d1SDavid du Colombier void
markdcl(void)7283e12c5d1SDavid du Colombier markdcl(void)
7293e12c5d1SDavid du Colombier {
7303e12c5d1SDavid du Colombier 	Decl *d;
7313e12c5d1SDavid du Colombier 
7323e12c5d1SDavid du Colombier 	blockno++;
7333e12c5d1SDavid du Colombier 	d = push();
7343e12c5d1SDavid du Colombier 	d->val = DMARK;
7353e12c5d1SDavid du Colombier 	d->offset = autoffset;
7363e12c5d1SDavid du Colombier 	d->block = autobn;
7373e12c5d1SDavid du Colombier 	autobn = blockno;
7383e12c5d1SDavid du Colombier }
7393e12c5d1SDavid du Colombier 
7407dd7cddfSDavid du Colombier Node*
revertdcl(void)7413e12c5d1SDavid du Colombier revertdcl(void)
7423e12c5d1SDavid du Colombier {
7433e12c5d1SDavid du Colombier 	Decl *d;
7443e12c5d1SDavid du Colombier 	Sym *s;
7457dd7cddfSDavid du Colombier 	Node *n, *n1;
7463e12c5d1SDavid du Colombier 
7477dd7cddfSDavid du Colombier 	n = Z;
7483e12c5d1SDavid du Colombier 	for(;;) {
7493e12c5d1SDavid du Colombier 		d = dclstack;
7503e12c5d1SDavid du Colombier 		if(d == D) {
7513e12c5d1SDavid du Colombier 			diag(Z, "pop off dcl stack");
7523e12c5d1SDavid du Colombier 			break;
7533e12c5d1SDavid du Colombier 		}
7543e12c5d1SDavid du Colombier 		dclstack = d->link;
7553e12c5d1SDavid du Colombier 		s = d->sym;
7563e12c5d1SDavid du Colombier 		switch(d->val) {
7573e12c5d1SDavid du Colombier 		case DMARK:
7583e12c5d1SDavid du Colombier 			autoffset = d->offset;
7593e12c5d1SDavid du Colombier 			autobn = d->block;
7607dd7cddfSDavid du Colombier 			return n;
7613e12c5d1SDavid du Colombier 
7623e12c5d1SDavid du Colombier 		case DAUTO:
7633e12c5d1SDavid du Colombier 			if(debug['d'])
7643e12c5d1SDavid du Colombier 				print("revert1 \"%s\"\n", s->name);
7653e12c5d1SDavid du Colombier 			if(s->aused == 0) {
7663e12c5d1SDavid du Colombier 				nearln = s->varlineno;
7673e12c5d1SDavid du Colombier 				if(s->class == CAUTO)
7683e12c5d1SDavid du Colombier 					warn(Z, "auto declared and not used: %s", s->name);
7693e12c5d1SDavid du Colombier 				if(s->class == CPARAM)
7703e12c5d1SDavid du Colombier 					warn(Z, "param declared and not used: %s", s->name);
7713e12c5d1SDavid du Colombier 			}
7727dd7cddfSDavid du Colombier 			if(s->type && (s->type->garb & GVOLATILE)) {
7737dd7cddfSDavid du Colombier 				n1 = new(ONAME, Z, Z);
7747dd7cddfSDavid du Colombier 				n1->sym = s;
7757dd7cddfSDavid du Colombier 				n1->type = s->type;
7767dd7cddfSDavid du Colombier 				n1->etype = TVOID;
7777dd7cddfSDavid du Colombier 				if(n1->type != T)
7787dd7cddfSDavid du Colombier 					n1->etype = n1->type->etype;
7797dd7cddfSDavid du Colombier 				n1->xoffset = s->offset;
7807dd7cddfSDavid du Colombier 				n1->class = s->class;
7817dd7cddfSDavid du Colombier 
7827dd7cddfSDavid du Colombier 				n1 = new(OADDR, n1, Z);
7837dd7cddfSDavid du Colombier 				n1 = new(OUSED, n1, Z);
7847dd7cddfSDavid du Colombier 				if(n == Z)
7857dd7cddfSDavid du Colombier 					n = n1;
7867dd7cddfSDavid du Colombier 				else
7877dd7cddfSDavid du Colombier 					n = new(OLIST, n1, n);
7887dd7cddfSDavid du Colombier 			}
7893e12c5d1SDavid du Colombier 			s->type = d->type;
7903e12c5d1SDavid du Colombier 			s->class = d->class;
7913e12c5d1SDavid du Colombier 			s->offset = d->offset;
7923e12c5d1SDavid du Colombier 			s->block = d->block;
7933e12c5d1SDavid du Colombier 			s->varlineno = d->varlineno;
7943e12c5d1SDavid du Colombier 			s->aused = d->aused;
7953e12c5d1SDavid du Colombier 			break;
7963e12c5d1SDavid du Colombier 
7973e12c5d1SDavid du Colombier 		case DSUE:
7983e12c5d1SDavid du Colombier 			if(debug['d'])
7993e12c5d1SDavid du Colombier 				print("revert2 \"%s\"\n", s->name);
8003e12c5d1SDavid du Colombier 			s->suetag = d->type;
8013e12c5d1SDavid du Colombier 			s->sueblock = d->block;
8023e12c5d1SDavid du Colombier 			break;
8033e12c5d1SDavid du Colombier 
8043e12c5d1SDavid du Colombier 		case DLABEL:
8053e12c5d1SDavid du Colombier 			if(debug['d'])
8063e12c5d1SDavid du Colombier 				print("revert3 \"%s\"\n", s->name);
8077dd7cddfSDavid du Colombier 			if(s->label && s->label->addable == 0)
8087dd7cddfSDavid du Colombier 				warn(s->label, "label declared and not used \"%s\"", s->name);
8093e12c5d1SDavid du Colombier 			s->label = Z;
8103e12c5d1SDavid du Colombier 			break;
8113e12c5d1SDavid du Colombier 		}
8123e12c5d1SDavid du Colombier 	}
8137dd7cddfSDavid du Colombier 	return n;
8143e12c5d1SDavid du Colombier }
8153e12c5d1SDavid du Colombier 
8163e12c5d1SDavid du Colombier Type*
fnproto(Node * n)8173e12c5d1SDavid du Colombier fnproto(Node *n)
8183e12c5d1SDavid du Colombier {
8193e12c5d1SDavid du Colombier 	int r;
8203e12c5d1SDavid du Colombier 
8213e12c5d1SDavid du Colombier 	r = anyproto(n->right);
8223e12c5d1SDavid du Colombier 	if(r == 0 || (r & OLDPROTO)) {
8233e12c5d1SDavid du Colombier 		if(r & ANSIPROTO)
8243e12c5d1SDavid du Colombier 			diag(n, "mixed ansi/old function declaration: %F", n->left);
8253e12c5d1SDavid du Colombier 		return T;
8263e12c5d1SDavid du Colombier 	}
8273e12c5d1SDavid du Colombier 	return fnproto1(n->right);
8283e12c5d1SDavid du Colombier }
8293e12c5d1SDavid du Colombier 
8303e12c5d1SDavid du Colombier int
anyproto(Node * n)8313e12c5d1SDavid du Colombier anyproto(Node *n)
8323e12c5d1SDavid du Colombier {
8333e12c5d1SDavid du Colombier 	int r;
8343e12c5d1SDavid du Colombier 
8353e12c5d1SDavid du Colombier 	r = 0;
8363e12c5d1SDavid du Colombier 
8373e12c5d1SDavid du Colombier loop:
8383e12c5d1SDavid du Colombier 	if(n == Z)
8393e12c5d1SDavid du Colombier 		return r;
8403e12c5d1SDavid du Colombier 	switch(n->op) {
8413e12c5d1SDavid du Colombier 	case OLIST:
8423e12c5d1SDavid du Colombier 		r |= anyproto(n->left);
8433e12c5d1SDavid du Colombier 		n = n->right;
8443e12c5d1SDavid du Colombier 		goto loop;
8453e12c5d1SDavid du Colombier 
8463e12c5d1SDavid du Colombier 	case ODOTDOT:
8473e12c5d1SDavid du Colombier 	case OPROTO:
8483e12c5d1SDavid du Colombier 		return r | ANSIPROTO;
8493e12c5d1SDavid du Colombier 	}
8503e12c5d1SDavid du Colombier 	return r | OLDPROTO;
8513e12c5d1SDavid du Colombier }
8523e12c5d1SDavid du Colombier 
8533e12c5d1SDavid du Colombier Type*
fnproto1(Node * n)8543e12c5d1SDavid du Colombier fnproto1(Node *n)
8553e12c5d1SDavid du Colombier {
8563e12c5d1SDavid du Colombier 	Type *t;
8573e12c5d1SDavid du Colombier 
8583e12c5d1SDavid du Colombier 	if(n == Z)
8593e12c5d1SDavid du Colombier 		return T;
8603e12c5d1SDavid du Colombier 	switch(n->op) {
8613e12c5d1SDavid du Colombier 	case OLIST:
8623e12c5d1SDavid du Colombier 		t = fnproto1(n->left);
8633e12c5d1SDavid du Colombier 		if(t != T)
8643e12c5d1SDavid du Colombier 			t->down = fnproto1(n->right);
8653e12c5d1SDavid du Colombier 		return t;
8663e12c5d1SDavid du Colombier 
8673e12c5d1SDavid du Colombier 	case OPROTO:
8683e12c5d1SDavid du Colombier 		lastdcl = T;
8693e12c5d1SDavid du Colombier 		dodecl(NODECL, CXXX, n->type, n->left);
8703e12c5d1SDavid du Colombier 		t = typ(TXXX, T);
8713e12c5d1SDavid du Colombier 		if(lastdcl != T)
8723e12c5d1SDavid du Colombier 			*t = *paramconv(lastdcl, 1);
8733e12c5d1SDavid du Colombier 		return t;
8743e12c5d1SDavid du Colombier 
8753e12c5d1SDavid du Colombier 	case ONAME:
8763e12c5d1SDavid du Colombier 		diag(n, "incomplete argument prototype");
8777dd7cddfSDavid du Colombier 		return typ(TINT, T);
8783e12c5d1SDavid du Colombier 
8793e12c5d1SDavid du Colombier 	case ODOTDOT:
8803e12c5d1SDavid du Colombier 		return typ(TDOT, T);
8813e12c5d1SDavid du Colombier 	}
8823e12c5d1SDavid du Colombier 	diag(n, "unknown op in fnproto");
8833e12c5d1SDavid du Colombier 	return T;
8843e12c5d1SDavid du Colombier }
8853e12c5d1SDavid du Colombier 
8863e12c5d1SDavid du Colombier void
dbgdecl(Sym * s)8873e12c5d1SDavid du Colombier dbgdecl(Sym *s)
8883e12c5d1SDavid du Colombier {
8897dd7cddfSDavid du Colombier 	print("decl \"%s\": C=%s [B=%d:O=%ld] T=%T\n",
890219b2ee8SDavid du Colombier 		s->name, cnames[s->class], s->block, s->offset, s->type);
8913e12c5d1SDavid du Colombier }
8923e12c5d1SDavid du Colombier 
8933e12c5d1SDavid du Colombier Decl*
push(void)8943e12c5d1SDavid du Colombier push(void)
8953e12c5d1SDavid du Colombier {
8963e12c5d1SDavid du Colombier 	Decl *d;
8973e12c5d1SDavid du Colombier 
8987dd7cddfSDavid du Colombier 	d = alloc(sizeof(*d));
8993e12c5d1SDavid du Colombier 	d->link = dclstack;
9003e12c5d1SDavid du Colombier 	dclstack = d;
9013e12c5d1SDavid du Colombier 	return d;
9023e12c5d1SDavid du Colombier }
9033e12c5d1SDavid du Colombier 
9043e12c5d1SDavid du Colombier Decl*
push1(Sym * s)9053e12c5d1SDavid du Colombier push1(Sym *s)
9063e12c5d1SDavid du Colombier {
9073e12c5d1SDavid du Colombier 	Decl *d;
9083e12c5d1SDavid du Colombier 
9093e12c5d1SDavid du Colombier 	d = push();
9103e12c5d1SDavid du Colombier 	d->sym = s;
9113e12c5d1SDavid du Colombier 	d->val = DAUTO;
9123e12c5d1SDavid du Colombier 	d->type = s->type;
9133e12c5d1SDavid du Colombier 	d->class = s->class;
9143e12c5d1SDavid du Colombier 	d->offset = s->offset;
9153e12c5d1SDavid du Colombier 	d->block = s->block;
9163e12c5d1SDavid du Colombier 	d->varlineno = s->varlineno;
9173e12c5d1SDavid du Colombier 	d->aused = s->aused;
9183e12c5d1SDavid du Colombier 	return d;
9193e12c5d1SDavid du Colombier }
9203e12c5d1SDavid du Colombier 
9213e12c5d1SDavid du Colombier int
sametype(Type * t1,Type * t2)9223e12c5d1SDavid du Colombier sametype(Type *t1, Type *t2)
9233e12c5d1SDavid du Colombier {
9243e12c5d1SDavid du Colombier 
9253e12c5d1SDavid du Colombier 	if(t1 == t2)
9263e12c5d1SDavid du Colombier 		return 1;
9277dd7cddfSDavid du Colombier 	return rsametype(t1, t2, 5, 1);
9283e12c5d1SDavid du Colombier }
9293e12c5d1SDavid du Colombier 
9303e12c5d1SDavid du Colombier int
rsametype(Type * t1,Type * t2,int n,int f)9317dd7cddfSDavid du Colombier rsametype(Type *t1, Type *t2, int n, int f)
9323e12c5d1SDavid du Colombier {
9333e12c5d1SDavid du Colombier 	int et;
9343e12c5d1SDavid du Colombier 
9353e12c5d1SDavid du Colombier 	n--;
9363e12c5d1SDavid du Colombier 	for(;;) {
9373e12c5d1SDavid du Colombier 		if(t1 == t2)
9383e12c5d1SDavid du Colombier 			return 1;
9393e12c5d1SDavid du Colombier 		if(t1 == T || t2 == T)
9403e12c5d1SDavid du Colombier 			return 0;
9413e12c5d1SDavid du Colombier 		if(n <= 0)
9423e12c5d1SDavid du Colombier 			return 1;
9433e12c5d1SDavid du Colombier 		et = t1->etype;
9443e12c5d1SDavid du Colombier 		if(et != t2->etype)
9453e12c5d1SDavid du Colombier 			return 0;
9463e12c5d1SDavid du Colombier 		if(et == TFUNC) {
9477dd7cddfSDavid du Colombier 			if(!rsametype(t1->link, t2->link, n, 0))
9483e12c5d1SDavid du Colombier 				return 0;
9493e12c5d1SDavid du Colombier 			t1 = t1->down;
9503e12c5d1SDavid du Colombier 			t2 = t2->down;
9513e12c5d1SDavid du Colombier 			while(t1 != T && t2 != T) {
9523e12c5d1SDavid du Colombier 				if(t1->etype == TOLD) {
9533e12c5d1SDavid du Colombier 					t1 = t1->down;
9543e12c5d1SDavid du Colombier 					continue;
9553e12c5d1SDavid du Colombier 				}
9563e12c5d1SDavid du Colombier 				if(t2->etype == TOLD) {
9573e12c5d1SDavid du Colombier 					t2 = t2->down;
9583e12c5d1SDavid du Colombier 					continue;
9593e12c5d1SDavid du Colombier 				}
9603e12c5d1SDavid du Colombier 				while(t1 != T || t2 != T) {
9617dd7cddfSDavid du Colombier 					if(!rsametype(t1, t2, n, 0))
9623e12c5d1SDavid du Colombier 						return 0;
9633e12c5d1SDavid du Colombier 					t1 = t1->down;
9643e12c5d1SDavid du Colombier 					t2 = t2->down;
9653e12c5d1SDavid du Colombier 				}
9663e12c5d1SDavid du Colombier 				break;
9673e12c5d1SDavid du Colombier 			}
9683e12c5d1SDavid du Colombier 			return 1;
9693e12c5d1SDavid du Colombier 		}
9707dd7cddfSDavid du Colombier 		if(et == TARRAY)
9717dd7cddfSDavid du Colombier 			if(t1->width != t2->width && t1->width != 0 && t2->width != 0)
9727dd7cddfSDavid du Colombier 				return 0;
9737dd7cddfSDavid du Colombier 		if(typesu[et]) {
9747dd7cddfSDavid du Colombier 			if(t1->link == T)
9757dd7cddfSDavid du Colombier 				snap(t1);
9767dd7cddfSDavid du Colombier 			if(t2->link == T)
9777dd7cddfSDavid du Colombier 				snap(t2);
9786891d857SDavid du Colombier 			if(t1 != t2 && t1->link == T && t2->link == T){
9796891d857SDavid du Colombier 				/* structs with missing or different tag names aren't considered equal */
9806891d857SDavid du Colombier 				if(t1->tag == nil || t2->tag == nil ||
9816891d857SDavid du Colombier 				   strcmp(t1->tag->name, t2->tag->name) != 0)
9826891d857SDavid du Colombier 					return 0;
9836891d857SDavid du Colombier 			}
9843e12c5d1SDavid du Colombier 			t1 = t1->link;
9853e12c5d1SDavid du Colombier 			t2 = t2->link;
9863e12c5d1SDavid du Colombier 			for(;;) {
9873e12c5d1SDavid du Colombier 				if(t1 == t2)
9883e12c5d1SDavid du Colombier 					return 1;
9897dd7cddfSDavid du Colombier 				if(!rsametype(t1, t2, n, 0))
9903e12c5d1SDavid du Colombier 					return 0;
9913e12c5d1SDavid du Colombier 				t1 = t1->down;
9923e12c5d1SDavid du Colombier 				t2 = t2->down;
9933e12c5d1SDavid du Colombier 			}
9947dd7cddfSDavid du Colombier 		}
9957dd7cddfSDavid du Colombier 		t1 = t1->link;
9967dd7cddfSDavid du Colombier 		t2 = t2->link;
9977dd7cddfSDavid du Colombier 		if((f || !debug['V']) && et == TIND) {
9987dd7cddfSDavid du Colombier 			if(t1 != T && t1->etype == TVOID)
9993e12c5d1SDavid du Colombier 				return 1;
10007dd7cddfSDavid du Colombier 			if(t2 != T && t2->etype == TVOID)
10017dd7cddfSDavid du Colombier 				return 1;
10027dd7cddfSDavid du Colombier 		}
10037dd7cddfSDavid du Colombier 	}
10047dd7cddfSDavid du Colombier }
10057dd7cddfSDavid du Colombier 
1006375daca8SDavid du Colombier typedef struct Typetab Typetab;
1007375daca8SDavid du Colombier 
1008375daca8SDavid du Colombier struct Typetab{
1009375daca8SDavid du Colombier 	int n;
1010375daca8SDavid du Colombier 	Type **a;
1011375daca8SDavid du Colombier };
1012375daca8SDavid du Colombier 
1013375daca8SDavid du Colombier static int
sigind(Type * t,Typetab * tt)1014375daca8SDavid du Colombier sigind(Type *t, Typetab *tt)
10157dd7cddfSDavid du Colombier {
1016375daca8SDavid du Colombier 	int n;
1017375daca8SDavid du Colombier 	Type **a, **na, **p, **e;
1018375daca8SDavid du Colombier 
1019375daca8SDavid du Colombier 	n = tt->n;
1020375daca8SDavid du Colombier 	a = tt->a;
1021375daca8SDavid du Colombier 	e = a+n;
1022375daca8SDavid du Colombier 	/* linear search seems ok */
1023375daca8SDavid du Colombier 	for(p = a ; p < e; p++)
1024375daca8SDavid du Colombier 		if(sametype(*p, t))
1025375daca8SDavid du Colombier 			return p-a;
1026375daca8SDavid du Colombier 	if((n&15) == 0){
1027375daca8SDavid du Colombier 		na = malloc((n+16)*sizeof(Type*));
1028375daca8SDavid du Colombier 		memmove(na, a, n*sizeof(Type*));
1029375daca8SDavid du Colombier 		free(a);
1030375daca8SDavid du Colombier 		a = tt->a = na;
1031375daca8SDavid du Colombier 	}
1032375daca8SDavid du Colombier 	a[tt->n++] = t;
1033375daca8SDavid du Colombier 	return -1;
1034375daca8SDavid du Colombier }
1035375daca8SDavid du Colombier 
1036375daca8SDavid du Colombier static ulong
signat(Type * t,Typetab * tt)1037375daca8SDavid du Colombier signat(Type *t, Typetab *tt)
1038375daca8SDavid du Colombier {
1039375daca8SDavid du Colombier 	int i;
10407dd7cddfSDavid du Colombier 	Type *t1;
10417dd7cddfSDavid du Colombier 	long s;
10427dd7cddfSDavid du Colombier 
10437dd7cddfSDavid du Colombier 	s = 0;
10447dd7cddfSDavid du Colombier 	for(; t; t=t->link) {
10457dd7cddfSDavid du Colombier 		s = s*thash1 + thash[t->etype];
1046375daca8SDavid du Colombier 		if(t->garb&GINCOMPLETE)
1047375daca8SDavid du Colombier 			return s;
10487dd7cddfSDavid du Colombier 		switch(t->etype) {
10497dd7cddfSDavid du Colombier 		default:
10507dd7cddfSDavid du Colombier 			return s;
10517dd7cddfSDavid du Colombier 		case TARRAY:
1052375daca8SDavid du Colombier 			s = s*thash2 + 0;	/* was t->width */
10537dd7cddfSDavid du Colombier 			break;
10547dd7cddfSDavid du Colombier 		case TFUNC:
1055375daca8SDavid du Colombier 			for(t1=t->down; t1; t1=t1->down)
1056375daca8SDavid du Colombier 				s = s*thash3 + signat(t1, tt);
1057375daca8SDavid du Colombier 			break;
10587dd7cddfSDavid du Colombier 		case TSTRUCT:
10597dd7cddfSDavid du Colombier 		case TUNION:
1060375daca8SDavid du Colombier 			if((i = sigind(t, tt)) >= 0){
1061375daca8SDavid du Colombier 				s = s*thash2 + i;
1062375daca8SDavid du Colombier 				return s;
1063375daca8SDavid du Colombier 			}
1064375daca8SDavid du Colombier 			for(t1=t->link; t1; t1=t1->down)
1065375daca8SDavid du Colombier 				s = s*thash3 + signat(t1, tt);
1066375daca8SDavid du Colombier 			return s;
10677dd7cddfSDavid du Colombier 		case TIND:
10687dd7cddfSDavid du Colombier 			break;
10697dd7cddfSDavid du Colombier 		}
10707dd7cddfSDavid du Colombier 	}
10717dd7cddfSDavid du Colombier 	return s;
10727dd7cddfSDavid du Colombier }
10737dd7cddfSDavid du Colombier 
1074375daca8SDavid du Colombier ulong
signature(Type * t)1075375daca8SDavid du Colombier signature(Type *t)
1076375daca8SDavid du Colombier {
1077375daca8SDavid du Colombier 	ulong s;
1078375daca8SDavid du Colombier 	Typetab tt;
1079375daca8SDavid du Colombier 
1080375daca8SDavid du Colombier 	tt.n = 0;
1081375daca8SDavid du Colombier 	tt.a = nil;
1082375daca8SDavid du Colombier 	s = signat(t, &tt);
1083375daca8SDavid du Colombier 	free(tt.a);
1084375daca8SDavid du Colombier 	return s;
1085375daca8SDavid du Colombier }
1086375daca8SDavid du Colombier 
1087375daca8SDavid du Colombier ulong
sign(Sym * s)1088375daca8SDavid du Colombier sign(Sym *s)
1089375daca8SDavid du Colombier {
1090375daca8SDavid du Colombier 	ulong v;
1091375daca8SDavid du Colombier 	Type *t;
1092375daca8SDavid du Colombier 
1093375daca8SDavid du Colombier 	if(s->sig == SIGINTERN)
1094375daca8SDavid du Colombier 		return SIGNINTERN;
1095375daca8SDavid du Colombier 	if((t = s->type) == T)
1096375daca8SDavid du Colombier 		return 0;
1097375daca8SDavid du Colombier 	v = signature(t);
1098375daca8SDavid du Colombier 	if(v == 0)
1099375daca8SDavid du Colombier 		v = SIGNINTERN;
1100375daca8SDavid du Colombier 	return v;
1101375daca8SDavid du Colombier }
1102375daca8SDavid du Colombier 
11037dd7cddfSDavid du Colombier void
snap(Type * t)11047dd7cddfSDavid du Colombier snap(Type *t)
11057dd7cddfSDavid du Colombier {
11067dd7cddfSDavid du Colombier 	if(typesu[t->etype])
11077dd7cddfSDavid du Colombier 	if(t->link == T && t->tag && t->tag->suetag) {
11087dd7cddfSDavid du Colombier 		t->link = t->tag->suetag->link;
11097dd7cddfSDavid du Colombier 		t->width = t->tag->suetag->width;
11103e12c5d1SDavid du Colombier 	}
11113e12c5d1SDavid du Colombier }
11123e12c5d1SDavid du Colombier 
1113219b2ee8SDavid du Colombier Type*
dotag(Sym * s,int et,int bn)11143e12c5d1SDavid du Colombier dotag(Sym *s, int et, int bn)
11153e12c5d1SDavid du Colombier {
11163e12c5d1SDavid du Colombier 	Decl *d;
11173e12c5d1SDavid du Colombier 
11183e12c5d1SDavid du Colombier 	if(bn != 0 && bn != s->sueblock) {
11193e12c5d1SDavid du Colombier 		d = push();
11203e12c5d1SDavid du Colombier 		d->sym = s;
11213e12c5d1SDavid du Colombier 		d->val = DSUE;
11223e12c5d1SDavid du Colombier 		d->type = s->suetag;
11233e12c5d1SDavid du Colombier 		d->block = s->sueblock;
11243e12c5d1SDavid du Colombier 		s->suetag = T;
11253e12c5d1SDavid du Colombier 	}
11263e12c5d1SDavid du Colombier 	if(s->suetag == T) {
11273e12c5d1SDavid du Colombier 		s->suetag = typ(et, T);
11283e12c5d1SDavid du Colombier 		s->sueblock = autobn;
11293e12c5d1SDavid du Colombier 	}
11303e12c5d1SDavid du Colombier 	if(s->suetag->etype != et)
11313e12c5d1SDavid du Colombier 		diag(Z, "tag used for more than one type: %s",
11323e12c5d1SDavid du Colombier 			s->name);
11333e12c5d1SDavid du Colombier 	if(s->suetag->tag == S)
11343e12c5d1SDavid du Colombier 		s->suetag->tag = s;
1135219b2ee8SDavid du Colombier 	return s->suetag;
11363e12c5d1SDavid du Colombier }
11373e12c5d1SDavid du Colombier 
11383e12c5d1SDavid du Colombier Node*
dcllabel(Sym * s,int f)11393e12c5d1SDavid du Colombier dcllabel(Sym *s, int f)
11403e12c5d1SDavid du Colombier {
11413e12c5d1SDavid du Colombier 	Decl *d, d1;
11423e12c5d1SDavid du Colombier 	Node *n;
11433e12c5d1SDavid du Colombier 
11443e12c5d1SDavid du Colombier 	n = s->label;
11453e12c5d1SDavid du Colombier 	if(n != Z) {
11463e12c5d1SDavid du Colombier 		if(f) {
11473e12c5d1SDavid du Colombier 			if(n->complex)
11483e12c5d1SDavid du Colombier 				diag(Z, "label reused: %s", s->name);
11497dd7cddfSDavid du Colombier 			n->complex = 1;	// declared
11507dd7cddfSDavid du Colombier 		} else
11517dd7cddfSDavid du Colombier 			n->addable = 1;	// used
11523e12c5d1SDavid du Colombier 		return n;
11533e12c5d1SDavid du Colombier 	}
11543e12c5d1SDavid du Colombier 
11553e12c5d1SDavid du Colombier 	d = push();
11563e12c5d1SDavid du Colombier 	d->sym = s;
11573e12c5d1SDavid du Colombier 	d->val = DLABEL;
11583e12c5d1SDavid du Colombier 	dclstack = d->link;
11593e12c5d1SDavid du Colombier 
11603e12c5d1SDavid du Colombier 	d1 = *firstdcl;
11613e12c5d1SDavid du Colombier 	*firstdcl = *d;
11623e12c5d1SDavid du Colombier 	*d = d1;
11633e12c5d1SDavid du Colombier 
11643e12c5d1SDavid du Colombier 	firstdcl->link = d;
11653e12c5d1SDavid du Colombier 	firstdcl = d;
11663e12c5d1SDavid du Colombier 
11673e12c5d1SDavid du Colombier 	n = new(OXXX, Z, Z);
11683e12c5d1SDavid du Colombier 	n->sym = s;
11693e12c5d1SDavid du Colombier 	n->complex = f;
11707dd7cddfSDavid du Colombier 	n->addable = !f;
11713e12c5d1SDavid du Colombier 	s->label = n;
11723e12c5d1SDavid du Colombier 
11733e12c5d1SDavid du Colombier 	if(debug['d'])
11743e12c5d1SDavid du Colombier 		dbgdecl(s);
11753e12c5d1SDavid du Colombier 	return n;
11763e12c5d1SDavid du Colombier }
11773e12c5d1SDavid du Colombier 
11783e12c5d1SDavid du Colombier Type*
paramconv(Type * t,int f)11793e12c5d1SDavid du Colombier paramconv(Type *t, int f)
11803e12c5d1SDavid du Colombier {
11813e12c5d1SDavid du Colombier 
11823e12c5d1SDavid du Colombier 	switch(t->etype) {
11833e12c5d1SDavid du Colombier 	case TARRAY:
11843e12c5d1SDavid du Colombier 		t = typ(TIND, t->link);
11853e12c5d1SDavid du Colombier 		t->width = types[TIND]->width;
11863e12c5d1SDavid du Colombier 		break;
11873e12c5d1SDavid du Colombier 
11883e12c5d1SDavid du Colombier 	case TFUNC:
11893e12c5d1SDavid du Colombier 		t = typ(TIND, t);
11903e12c5d1SDavid du Colombier 		t->width = types[TIND]->width;
11913e12c5d1SDavid du Colombier 		break;
11923e12c5d1SDavid du Colombier 
11933e12c5d1SDavid du Colombier 	case TFLOAT:
11943e12c5d1SDavid du Colombier 		if(!f)
11953e12c5d1SDavid du Colombier 			t = types[TDOUBLE];
11963e12c5d1SDavid du Colombier 		break;
11973e12c5d1SDavid du Colombier 
11983e12c5d1SDavid du Colombier 	case TCHAR:
11993e12c5d1SDavid du Colombier 	case TSHORT:
12003e12c5d1SDavid du Colombier 		if(!f)
12017dd7cddfSDavid du Colombier 			t = types[TINT];
12023e12c5d1SDavid du Colombier 		break;
12033e12c5d1SDavid du Colombier 
12043e12c5d1SDavid du Colombier 	case TUCHAR:
12053e12c5d1SDavid du Colombier 	case TUSHORT:
12063e12c5d1SDavid du Colombier 		if(!f)
12077dd7cddfSDavid du Colombier 			t = types[TUINT];
12083e12c5d1SDavid du Colombier 		break;
12093e12c5d1SDavid du Colombier 	}
12103e12c5d1SDavid du Colombier 	return t;
12113e12c5d1SDavid du Colombier }
12123e12c5d1SDavid du Colombier 
12133e12c5d1SDavid du Colombier void
adecl(int c,Type * t,Sym * s)12143e12c5d1SDavid du Colombier adecl(int c, Type *t, Sym *s)
12153e12c5d1SDavid du Colombier {
12163e12c5d1SDavid du Colombier 
12173e12c5d1SDavid du Colombier 	if(c == CSTATIC)
12183e12c5d1SDavid du Colombier 		c = CLOCAL;
12193e12c5d1SDavid du Colombier 	if(t->etype == TFUNC) {
12203e12c5d1SDavid du Colombier 		if(c == CXXX)
12213e12c5d1SDavid du Colombier 			c = CEXTERN;
12223e12c5d1SDavid du Colombier 		if(c == CLOCAL)
12233e12c5d1SDavid du Colombier 			c = CSTATIC;
12243e12c5d1SDavid du Colombier 		if(c == CAUTO || c == CEXREG)
12253e12c5d1SDavid du Colombier 			diag(Z, "function cannot be %s %s", cnames[c], s->name);
12263e12c5d1SDavid du Colombier 	}
12273e12c5d1SDavid du Colombier 	if(c == CXXX)
12283e12c5d1SDavid du Colombier 		c = CAUTO;
1229219b2ee8SDavid du Colombier 	if(s) {
1230219b2ee8SDavid du Colombier 		if(s->class == CSTATIC)
12317dd7cddfSDavid du Colombier 			if(c == CEXTERN || c == CGLOBL) {
12327dd7cddfSDavid du Colombier 				warn(Z, "just say static: %s", s->name);
1233219b2ee8SDavid du Colombier 				c = CSTATIC;
12347dd7cddfSDavid du Colombier 			}
12353e12c5d1SDavid du Colombier 		if(s->class == CAUTO || s->class == CPARAM || s->class == CLOCAL)
12363e12c5d1SDavid du Colombier 		if(s->block == autobn)
12373e12c5d1SDavid du Colombier 			diag(Z, "auto redeclaration of: %s", s->name);
12383e12c5d1SDavid du Colombier 		if(c != CPARAM)
12393e12c5d1SDavid du Colombier 			push1(s);
12403e12c5d1SDavid du Colombier 		s->block = autobn;
12413e12c5d1SDavid du Colombier 		s->offset = 0;
12423e12c5d1SDavid du Colombier 		s->type = t;
12433e12c5d1SDavid du Colombier 		s->class = c;
12443e12c5d1SDavid du Colombier 		s->aused = 0;
1245219b2ee8SDavid du Colombier 	}
12467dd7cddfSDavid du Colombier 	switch(c) {
12477dd7cddfSDavid du Colombier 	case CAUTO:
12487dd7cddfSDavid du Colombier 		autoffset = align(autoffset, t, Aaut3);
12497dd7cddfSDavid du Colombier 		stkoff = maxround(stkoff, autoffset);
12507dd7cddfSDavid du Colombier 		s->offset = -autoffset;
12517dd7cddfSDavid du Colombier 		break;
12523e12c5d1SDavid du Colombier 
12537dd7cddfSDavid du Colombier 	case CPARAM:
12547dd7cddfSDavid du Colombier 		if(autoffset == 0) {
12553e12c5d1SDavid du Colombier 			firstarg = s;
12563e12c5d1SDavid du Colombier 			firstargtype = t;
12573e12c5d1SDavid du Colombier 		}
12587dd7cddfSDavid du Colombier 		autoffset = align(autoffset, t, Aarg1);
1259219b2ee8SDavid du Colombier 		if(s)
12603e12c5d1SDavid du Colombier 			s->offset = autoffset;
12617dd7cddfSDavid du Colombier 		autoffset = align(autoffset, t, Aarg2);
12627dd7cddfSDavid du Colombier 		break;
12633e12c5d1SDavid du Colombier 	}
12643e12c5d1SDavid du Colombier }
12653e12c5d1SDavid du Colombier 
12663e12c5d1SDavid du Colombier void
pdecl(int c,Type * t,Sym * s)12673e12c5d1SDavid du Colombier pdecl(int c, Type *t, Sym *s)
12683e12c5d1SDavid du Colombier {
1269219b2ee8SDavid du Colombier 	if(s && s->offset != -1) {
12703e12c5d1SDavid du Colombier 		diag(Z, "not a parameter: %s", s->name);
12713e12c5d1SDavid du Colombier 		return;
12723e12c5d1SDavid du Colombier 	}
12733e12c5d1SDavid du Colombier 	t = paramconv(t, c==CPARAM);
12743e12c5d1SDavid du Colombier 	if(c == CXXX)
12753e12c5d1SDavid du Colombier 		c = CPARAM;
12763e12c5d1SDavid du Colombier 	if(c != CPARAM) {
12773e12c5d1SDavid du Colombier 		diag(Z, "parameter cannot have class: %s", s->name);
12783e12c5d1SDavid du Colombier 		c = CPARAM;
12793e12c5d1SDavid du Colombier 	}
1280d40255d8SDavid du Colombier 	if(typesu[t->etype] && t->width <= 0)
1281d40255d8SDavid du Colombier 		diag(Z, "incomplete structure: %s", t->tag->name);
12823e12c5d1SDavid du Colombier 	adecl(c, t, s);
12833e12c5d1SDavid du Colombier }
12843e12c5d1SDavid du Colombier 
12853e12c5d1SDavid du Colombier void
xdecl(int c,Type * t,Sym * s)12863e12c5d1SDavid du Colombier xdecl(int c, Type *t, Sym *s)
12873e12c5d1SDavid du Colombier {
12883e12c5d1SDavid du Colombier 	long o;
12893e12c5d1SDavid du Colombier 
12903e12c5d1SDavid du Colombier 	o = 0;
129180ee5cbfSDavid du Colombier 	switch(c) {
129280ee5cbfSDavid du Colombier 	case CEXREG:
12933e12c5d1SDavid du Colombier 		o = exreg(t);
12943e12c5d1SDavid du Colombier 		if(o == 0)
12953e12c5d1SDavid du Colombier 			c = CEXTERN;
12963e12c5d1SDavid du Colombier 		if(s->class == CGLOBL)
12973e12c5d1SDavid du Colombier 			c = CGLOBL;
129880ee5cbfSDavid du Colombier 		break;
129980ee5cbfSDavid du Colombier 
130080ee5cbfSDavid du Colombier 	case CEXTERN:
130180ee5cbfSDavid du Colombier 		if(s->class == CGLOBL)
130280ee5cbfSDavid du Colombier 			c = CGLOBL;
130380ee5cbfSDavid du Colombier 		break;
130480ee5cbfSDavid du Colombier 
130580ee5cbfSDavid du Colombier 	case CXXX:
130680ee5cbfSDavid du Colombier 		c = CGLOBL;
130780ee5cbfSDavid du Colombier 		if(s->class == CEXTERN)
130880ee5cbfSDavid du Colombier 			s->class = CGLOBL;
130980ee5cbfSDavid du Colombier 		break;
131080ee5cbfSDavid du Colombier 
131180ee5cbfSDavid du Colombier 	case CAUTO:
13127dd7cddfSDavid du Colombier 		diag(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]);
13133e12c5d1SDavid du Colombier 		c = CEXTERN;
131480ee5cbfSDavid du Colombier 		break;
131580ee5cbfSDavid du Colombier 
131680ee5cbfSDavid du Colombier 	case CTYPESTR:
131780ee5cbfSDavid du Colombier 		if(!typesuv[t->etype]) {
131880ee5cbfSDavid du Colombier 			diag(Z, "typestr must be struct/union: %s", s->name);
131980ee5cbfSDavid du Colombier 			break;
13203e12c5d1SDavid du Colombier 		}
132180ee5cbfSDavid du Colombier 		dclfunct(t, s);
132280ee5cbfSDavid du Colombier 		break;
132380ee5cbfSDavid du Colombier 	}
132480ee5cbfSDavid du Colombier 
13253e12c5d1SDavid du Colombier 	if(s->class == CSTATIC)
13267dd7cddfSDavid du Colombier 		if(c == CEXTERN || c == CGLOBL) {
13277dd7cddfSDavid du Colombier 			warn(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]);
13283e12c5d1SDavid du Colombier 			c = CSTATIC;
13297dd7cddfSDavid du Colombier 		}
13303e12c5d1SDavid du Colombier 	if(s->type != T)
13313e12c5d1SDavid du Colombier 		if(s->class != c || !sametype(t, s->type) || t->etype == TENUM) {
13323e12c5d1SDavid du Colombier 			diag(Z, "external redeclaration of: %s", s->name);
1333eb2d877eSDavid du Colombier 			Bprint(&diagbuf, "	%s %T %L\n", cnames[c], t, nearln);
1334eb2d877eSDavid du Colombier 			Bprint(&diagbuf, "	%s %T %L\n", cnames[s->class], s->type, s->varlineno);
13353e12c5d1SDavid du Colombier 		}
13363e12c5d1SDavid du Colombier 	tmerge(t, s);
13373e12c5d1SDavid du Colombier 	s->type = t;
13383e12c5d1SDavid du Colombier 	s->class = c;
13393e12c5d1SDavid du Colombier 	s->block = 0;
13403e12c5d1SDavid du Colombier 	s->offset = o;
13413e12c5d1SDavid du Colombier }
13423e12c5d1SDavid du Colombier 
13433e12c5d1SDavid du Colombier void
tmerge(Type * t1,Sym * s)13443e12c5d1SDavid du Colombier tmerge(Type *t1, Sym *s)
13453e12c5d1SDavid du Colombier {
13463e12c5d1SDavid du Colombier 	Type *ta, *tb, *t2;
13473e12c5d1SDavid du Colombier 
13483e12c5d1SDavid du Colombier 	t2 = s->type;
13493e12c5d1SDavid du Colombier /*print("merge	%T; %T\n", t1, t2);/**/
13503e12c5d1SDavid du Colombier 	for(;;) {
13513e12c5d1SDavid du Colombier 		if(t1 == T || t2 == T || t1 == t2)
13523e12c5d1SDavid du Colombier 			break;
13533e12c5d1SDavid du Colombier 		if(t1->etype != t2->etype)
13543e12c5d1SDavid du Colombier 			break;
13553e12c5d1SDavid du Colombier 		switch(t1->etype) {
13563e12c5d1SDavid du Colombier 		case TFUNC:
13573e12c5d1SDavid du Colombier 			ta = t1->down;
13583e12c5d1SDavid du Colombier 			tb = t2->down;
13593e12c5d1SDavid du Colombier 			if(ta == T) {
13603e12c5d1SDavid du Colombier 				t1->down = tb;
13613e12c5d1SDavid du Colombier 				break;
13623e12c5d1SDavid du Colombier 			}
13633e12c5d1SDavid du Colombier 			if(tb == T)
13643e12c5d1SDavid du Colombier 				break;
13653e12c5d1SDavid du Colombier 			while(ta != T && tb != T) {
13663e12c5d1SDavid du Colombier 				if(ta == tb)
13673e12c5d1SDavid du Colombier 					break;
13683e12c5d1SDavid du Colombier 				/* ignore old-style flag */
13693e12c5d1SDavid du Colombier 				if(ta->etype == TOLD) {
13703e12c5d1SDavid du Colombier 					ta = ta->down;
13713e12c5d1SDavid du Colombier 					continue;
13723e12c5d1SDavid du Colombier 				}
13733e12c5d1SDavid du Colombier 				if(tb->etype == TOLD) {
13743e12c5d1SDavid du Colombier 					tb = tb->down;
13753e12c5d1SDavid du Colombier 					continue;
13763e12c5d1SDavid du Colombier 				}
13773e12c5d1SDavid du Colombier 				/* checking terminated by ... */
13783e12c5d1SDavid du Colombier 				if(ta->etype == TDOT && tb->etype == TDOT) {
13793e12c5d1SDavid du Colombier 					ta = T;
13803e12c5d1SDavid du Colombier 					tb = T;
13813e12c5d1SDavid du Colombier 					break;
13823e12c5d1SDavid du Colombier 				}
13833e12c5d1SDavid du Colombier 				if(!sametype(ta, tb))
13843e12c5d1SDavid du Colombier 					break;
13853e12c5d1SDavid du Colombier 				ta = ta->down;
13863e12c5d1SDavid du Colombier 				tb = tb->down;
13873e12c5d1SDavid du Colombier 			}
13883e12c5d1SDavid du Colombier 			if(ta != tb)
13893e12c5d1SDavid du Colombier 				diag(Z, "function inconsistently declared: %s", s->name);
13903e12c5d1SDavid du Colombier 
13913e12c5d1SDavid du Colombier 			/* take new-style over old-style */
13923e12c5d1SDavid du Colombier 			ta = t1->down;
13933e12c5d1SDavid du Colombier 			tb = t2->down;
13943e12c5d1SDavid du Colombier 			if(ta != T && ta->etype == TOLD)
13953e12c5d1SDavid du Colombier 				if(tb != T && tb->etype != TOLD)
13963e12c5d1SDavid du Colombier 					t1->down = tb;
13973e12c5d1SDavid du Colombier 			break;
13983e12c5d1SDavid du Colombier 
13993e12c5d1SDavid du Colombier 		case TARRAY:
14003e12c5d1SDavid du Colombier 			/* should we check array size change? */
14013e12c5d1SDavid du Colombier 			if(t2->width > t1->width)
14023e12c5d1SDavid du Colombier 				t1->width = t2->width;
14033e12c5d1SDavid du Colombier 			break;
14043e12c5d1SDavid du Colombier 
14053e12c5d1SDavid du Colombier 		case TUNION:
14063e12c5d1SDavid du Colombier 		case TSTRUCT:
14073e12c5d1SDavid du Colombier 			return;
14083e12c5d1SDavid du Colombier 		}
14093e12c5d1SDavid du Colombier 		t1 = t1->link;
14103e12c5d1SDavid du Colombier 		t2 = t2->link;
14113e12c5d1SDavid du Colombier 	}
14123e12c5d1SDavid du Colombier }
14133e12c5d1SDavid du Colombier 
14143e12c5d1SDavid du Colombier void
edecl(int c,Type * t,Sym * s)14153e12c5d1SDavid du Colombier edecl(int c, Type *t, Sym *s)
14163e12c5d1SDavid du Colombier {
14173e12c5d1SDavid du Colombier 	Type *t1;
14183e12c5d1SDavid du Colombier 
14193e12c5d1SDavid du Colombier 	if(s == S) {
14203e12c5d1SDavid du Colombier 		if(!typesu[t->etype])
14213e12c5d1SDavid du Colombier 			diag(Z, "unnamed structure element must be struct/union");
14223e12c5d1SDavid du Colombier 		if(c != CXXX)
14233e12c5d1SDavid du Colombier 			diag(Z, "unnamed structure element cannot have class");
14243e12c5d1SDavid du Colombier 	} else
14253e12c5d1SDavid du Colombier 		if(c != CXXX)
14263e12c5d1SDavid du Colombier 			diag(Z, "structure element cannot have class: %s", s->name);
14273e12c5d1SDavid du Colombier 	t1 = t;
142880ee5cbfSDavid du Colombier 	t = copytyp(t1);
14293e12c5d1SDavid du Colombier 	t->sym = s;
14303e12c5d1SDavid du Colombier 	t->down = T;
14313e12c5d1SDavid du Colombier 	if(lastfield) {
14323e12c5d1SDavid du Colombier 		t->shift = lastbit - lastfield;
14333e12c5d1SDavid du Colombier 		t->nbits = lastfield;
14343e12c5d1SDavid du Colombier 		if(firstbit)
14353e12c5d1SDavid du Colombier 			t->shift = -t->shift;
14367dd7cddfSDavid du Colombier 		if(typeu[t->etype])
14377dd7cddfSDavid du Colombier 			t->etype = tufield->etype;
14387dd7cddfSDavid du Colombier 		else
14397dd7cddfSDavid du Colombier 			t->etype = tfield->etype;
14403e12c5d1SDavid du Colombier 	}
14413e12c5d1SDavid du Colombier 	if(strf == T)
14423e12c5d1SDavid du Colombier 		strf = t;
14433e12c5d1SDavid du Colombier 	else
14443e12c5d1SDavid du Colombier 		strl->down = t;
14453e12c5d1SDavid du Colombier 	strl = t;
14463e12c5d1SDavid du Colombier }
14473e12c5d1SDavid du Colombier 
14483e12c5d1SDavid du Colombier /*
1449219b2ee8SDavid du Colombier  * this routine is very suspect.
1450219b2ee8SDavid du Colombier  * ansi requires the enum type to
1451219b2ee8SDavid du Colombier  * be represented as an 'int'
1452219b2ee8SDavid du Colombier  * this means that 0x81234567
1453219b2ee8SDavid du Colombier  * would be illegal. this routine
1454219b2ee8SDavid du Colombier  * makes signed and unsigned go
1455219b2ee8SDavid du Colombier  * to unsigned.
14563e12c5d1SDavid du Colombier  */
1457219b2ee8SDavid du Colombier Type*
maxtype(Type * t1,Type * t2)1458219b2ee8SDavid du Colombier maxtype(Type *t1, Type *t2)
1459219b2ee8SDavid du Colombier {
1460219b2ee8SDavid du Colombier 
1461219b2ee8SDavid du Colombier 	if(t1 == T)
1462219b2ee8SDavid du Colombier 		return t2;
1463219b2ee8SDavid du Colombier 	if(t2 == T)
1464219b2ee8SDavid du Colombier 		return t1;
1465219b2ee8SDavid du Colombier 	if(t1->etype > t2->etype)
1466219b2ee8SDavid du Colombier 		return t1;
1467219b2ee8SDavid du Colombier 	return t2;
14683e12c5d1SDavid du Colombier }
14693e12c5d1SDavid du Colombier 
14703e12c5d1SDavid du Colombier void
doenum(Sym * s,Node * n)14713e12c5d1SDavid du Colombier doenum(Sym *s, Node *n)
14723e12c5d1SDavid du Colombier {
14733e12c5d1SDavid du Colombier 
14743e12c5d1SDavid du Colombier 	if(n) {
14753e12c5d1SDavid du Colombier 		complex(n);
1476219b2ee8SDavid du Colombier 		if(n->op != OCONST) {
1477219b2ee8SDavid du Colombier 			diag(n, "enum not a constant: %s", s->name);
14783e12c5d1SDavid du Colombier 			return;
14793e12c5d1SDavid du Colombier 		}
1480219b2ee8SDavid du Colombier 		en.cenum = n->type;
1481219b2ee8SDavid du Colombier 		en.tenum = maxtype(en.cenum, en.tenum);
1482219b2ee8SDavid du Colombier 
1483219b2ee8SDavid du Colombier 		if(!typefd[en.cenum->etype])
1484219b2ee8SDavid du Colombier 			en.lastenum = n->vconst;
1485219b2ee8SDavid du Colombier 		else
1486219b2ee8SDavid du Colombier 			en.floatenum = n->fconst;
14873e12c5d1SDavid du Colombier 	}
14883e12c5d1SDavid du Colombier 	if(dclstack)
14893e12c5d1SDavid du Colombier 		push1(s);
14903e12c5d1SDavid du Colombier 	xdecl(CXXX, types[TENUM], s);
1491219b2ee8SDavid du Colombier 
1492219b2ee8SDavid du Colombier 	if(en.cenum == T) {
14937dd7cddfSDavid du Colombier 		en.tenum = types[TINT];
14947dd7cddfSDavid du Colombier 		en.cenum = types[TINT];
1495219b2ee8SDavid du Colombier 		en.lastenum = 0;
1496219b2ee8SDavid du Colombier 	}
1497219b2ee8SDavid du Colombier 	s->tenum = en.cenum;
1498219b2ee8SDavid du Colombier 
1499219b2ee8SDavid du Colombier 	if(!typefd[s->tenum->etype]) {
1500219b2ee8SDavid du Colombier 		s->vconst = convvtox(en.lastenum, s->tenum->etype);
1501219b2ee8SDavid du Colombier 		en.lastenum++;
1502219b2ee8SDavid du Colombier 	} else {
1503219b2ee8SDavid du Colombier 		s->fconst = en.floatenum;
1504219b2ee8SDavid du Colombier 		en.floatenum++;
1505219b2ee8SDavid du Colombier 	}
1506219b2ee8SDavid du Colombier 
15073e12c5d1SDavid du Colombier 	if(debug['d'])
15083e12c5d1SDavid du Colombier 		dbgdecl(s);
15097dd7cddfSDavid du Colombier 	acidvar(s);
15103e12c5d1SDavid du Colombier }
15113e12c5d1SDavid du Colombier 
15123e12c5d1SDavid du Colombier void
symadjust(Sym * s,Node * n,long del)15133e12c5d1SDavid du Colombier symadjust(Sym *s, Node *n, long del)
15143e12c5d1SDavid du Colombier {
15153e12c5d1SDavid du Colombier 
15163e12c5d1SDavid du Colombier 	switch(n->op) {
15173e12c5d1SDavid du Colombier 	default:
15183e12c5d1SDavid du Colombier 		if(n->left)
15193e12c5d1SDavid du Colombier 			symadjust(s, n->left, del);
15203e12c5d1SDavid du Colombier 		if(n->right)
15213e12c5d1SDavid du Colombier 			symadjust(s, n->right, del);
15223e12c5d1SDavid du Colombier 		return;
15233e12c5d1SDavid du Colombier 
15243e12c5d1SDavid du Colombier 	case ONAME:
15253e12c5d1SDavid du Colombier 		if(n->sym == s)
1526219b2ee8SDavid du Colombier 			n->xoffset -= del;
15273e12c5d1SDavid du Colombier 		return;
15283e12c5d1SDavid du Colombier 
15293e12c5d1SDavid du Colombier 	case OCONST:
15303e12c5d1SDavid du Colombier 	case OSTRING:
15313e12c5d1SDavid du Colombier 	case OLSTRING:
15323e12c5d1SDavid du Colombier 	case OINDREG:
15333e12c5d1SDavid du Colombier 	case OREGISTER:
15343e12c5d1SDavid du Colombier 		return;
15353e12c5d1SDavid du Colombier 	}
15363e12c5d1SDavid du Colombier }
15373e12c5d1SDavid du Colombier 
15383e12c5d1SDavid du Colombier Node*
contig(Sym * s,Node * n,long v)15393e12c5d1SDavid du Colombier contig(Sym *s, Node *n, long v)
15403e12c5d1SDavid du Colombier {
15413e12c5d1SDavid du Colombier 	Node *p, *r, *q, *m;
15423e12c5d1SDavid du Colombier 	long w;
154373e742d7SDavid du Colombier 	Type *zt;
15443e12c5d1SDavid du Colombier 
15459a747e4fSDavid du Colombier 	if(debug['i']) {
15469a747e4fSDavid du Colombier 		print("contig v = %ld; s = %s\n", v, s->name);
15479a747e4fSDavid du Colombier 		prtree(n, "doinit value");
15489a747e4fSDavid du Colombier 	}
15499a747e4fSDavid du Colombier 
15503e12c5d1SDavid du Colombier 	if(n == Z)
15513e12c5d1SDavid du Colombier 		goto no;
15523e12c5d1SDavid du Colombier 	w = s->type->width;
15533e12c5d1SDavid du Colombier 
15543e12c5d1SDavid du Colombier 	/*
15553e12c5d1SDavid du Colombier 	 * nightmare: an automatic array whose size
15563e12c5d1SDavid du Colombier 	 * increases when it is initialized
15573e12c5d1SDavid du Colombier 	 */
15583e12c5d1SDavid du Colombier 	if(v != w) {
15593e12c5d1SDavid du Colombier 		if(v != 0)
15603e12c5d1SDavid du Colombier 			diag(n, "automatic adjustable array: %s", s->name);
15613e12c5d1SDavid du Colombier 		v = s->offset;
15627dd7cddfSDavid du Colombier 		autoffset = align(autoffset, s->type, Aaut3);
15633e12c5d1SDavid du Colombier 		s->offset = -autoffset;
15647dd7cddfSDavid du Colombier 		stkoff = maxround(stkoff, autoffset);
15653e12c5d1SDavid du Colombier 		symadjust(s, n, v - s->offset);
15663e12c5d1SDavid du Colombier 	}
156773e742d7SDavid du Colombier 	if(w <= ewidth[TIND])
15683e12c5d1SDavid du Colombier 		goto no;
15693e12c5d1SDavid du Colombier 	if(n->op == OAS)
15707dd7cddfSDavid du Colombier 		diag(Z, "oops in contig");
15719a747e4fSDavid du Colombier /*ZZZ this appears incorrect
15729a747e4fSDavid du Colombier need to check if the list completely covers the data.
15739a747e4fSDavid du Colombier if not, bail
15749a747e4fSDavid du Colombier  */
15757dd7cddfSDavid du Colombier 	if(n->op == OLIST)
15767dd7cddfSDavid du Colombier 		goto no;
15777dd7cddfSDavid du Colombier 	if(n->op == OASI)
15783e12c5d1SDavid du Colombier 		if(n->left->type)
15793e12c5d1SDavid du Colombier 		if(n->left->type->width == w)
15803e12c5d1SDavid du Colombier 			goto no;
1581b8d70f5aSDavid du Colombier 	while(w & (ewidth[TIND]-1))
1582b8d70f5aSDavid du Colombier 		w++;
15833e12c5d1SDavid du Colombier /*
158473e742d7SDavid du Colombier  * insert the following code, where long becomes vlong if pointers are fat
15853e12c5d1SDavid du Colombier  *
15863e12c5d1SDavid du Colombier 	*(long**)&X = (long*)((char*)X + sizeof(X));
15873e12c5d1SDavid du Colombier 	do {
15883e12c5d1SDavid du Colombier 		*(long**)&X -= 1;
15893e12c5d1SDavid du Colombier 		**(long**)&X = 0;
15903e12c5d1SDavid du Colombier 	} while(*(long**)&X);
15913e12c5d1SDavid du Colombier  */
15923e12c5d1SDavid du Colombier 
15933e12c5d1SDavid du Colombier 	for(q=n; q->op != ONAME; q=q->left)
15943e12c5d1SDavid du Colombier 		;
15953e12c5d1SDavid du Colombier 
159673e742d7SDavid du Colombier 	zt = ewidth[TIND] > ewidth[TLONG]? types[TVLONG]: types[TLONG];
159773e742d7SDavid du Colombier 
15983e12c5d1SDavid du Colombier 	p = new(ONAME, Z, Z);
15993e12c5d1SDavid du Colombier 	*p = *q;
160073e742d7SDavid du Colombier 	p->type = typ(TIND, zt);
1601219b2ee8SDavid du Colombier 	p->xoffset = s->offset;
16023e12c5d1SDavid du Colombier 
16033e12c5d1SDavid du Colombier 	r = new(ONAME, Z, Z);
16043e12c5d1SDavid du Colombier 	*r = *p;
16053e12c5d1SDavid du Colombier 	r = new(OPOSTDEC, r, Z);
16063e12c5d1SDavid du Colombier 
16073e12c5d1SDavid du Colombier 	q = new(ONAME, Z, Z);
16083e12c5d1SDavid du Colombier 	*q = *p;
16093e12c5d1SDavid du Colombier 	q = new(OIND, q, Z);
16103e12c5d1SDavid du Colombier 
16113e12c5d1SDavid du Colombier 	m = new(OCONST, Z, Z);
1612219b2ee8SDavid du Colombier 	m->vconst = 0;
161373e742d7SDavid du Colombier 	m->type = zt;
16143e12c5d1SDavid du Colombier 
16153e12c5d1SDavid du Colombier 	q = new(OAS, q, m);
16163e12c5d1SDavid du Colombier 
16173e12c5d1SDavid du Colombier 	r = new(OLIST, r, q);
16183e12c5d1SDavid du Colombier 
16193e12c5d1SDavid du Colombier 	q = new(ONAME, Z, Z);
16203e12c5d1SDavid du Colombier 	*q = *p;
16213e12c5d1SDavid du Colombier 	r = new(ODWHILE, q, r);
16223e12c5d1SDavid du Colombier 
16233e12c5d1SDavid du Colombier 	q = new(ONAME, Z, Z);
16243e12c5d1SDavid du Colombier 	*q = *p;
16253e12c5d1SDavid du Colombier 	q->type = q->type->link;
1626219b2ee8SDavid du Colombier 	q->xoffset += w;
16273e12c5d1SDavid du Colombier 	q = new(OADDR, q, 0);
16283e12c5d1SDavid du Colombier 
16297dd7cddfSDavid du Colombier 	q = new(OASI, p, q);
16303e12c5d1SDavid du Colombier 	r = new(OLIST, q, r);
16313e12c5d1SDavid du Colombier 
16323e12c5d1SDavid du Colombier 	n = new(OLIST, r, n);
16333e12c5d1SDavid du Colombier 
16343e12c5d1SDavid du Colombier no:
16353e12c5d1SDavid du Colombier 	return n;
16363e12c5d1SDavid du Colombier }
1637