Charles.Forsyth20060303644188019 years agoHistory
1387 lines · 21.9 KB · C
RawDownload
#include "cc.h" Node*dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n, int gen){	Sym *s;	Node *n1;	long v; 	nearln = lineno;	lastfield = 0; loop:	if(n != Z)	switch(n->op) {	default:		diag(n, "unknown declarator: %O", n->op);		break; 	case OARRAY:		t = typ(TARRAY, t);		t->width = 0;		n1 = n->right;		n = n->left;		if(n1 != Z) {			complex(n1);			v = -1;			if(n1->op == OCONST)				v = n1->vconst;			if(v <= 0) {				diag(n, "array size must be a positive constant");				v = 1;			}			t->width = v * t->link->width;			t->nwidth = n1->left;		}		goto loop; 	case OIND:		t = typ(TIND, t);		t->garb = n->garb;		n = n->left;		goto loop; 	case OFUNC:		t = typ(TFUNC, t);		t->down = fnproto(n);		n = n->left;		goto loop; 	case OBIT:		n1 = n->right;		complex(n1);		lastfield = -1;		if(n1->op == OCONST)			lastfield = n1->vconst;		if(lastfield < 0) {			diag(n, "field width must be non-negative constant");			lastfield = 1;		}		if(lastfield == 0) {			lastbit = 0;			firstbit = 1;			if(n->left != Z) {				diag(n, "zero width named field");				lastfield = 1;			}		}		if(!typei[t->etype]) {			diag(n, "field type must be int-like");			t = types[TINT];			lastfield = 1;		}		if(lastfield > tfield->width*8) {			diag(n, "field width larger than field unit");			lastfield = 1;		}		lastbit += lastfield;		if(lastbit > tfield->width*8) {			lastbit = lastfield;			firstbit = 1;		}		n = n->left;		goto loop; 	case ONAME:		if(f == NODECL)			break;		s = n->sym;		(*f)(c, t, s);		if(s->class == CLOCAL)			s = mkstatic(s);		firstbit = 0;		n->sym = s;		n->type = s->type;		acidvar(s);		if(gen)			vtgen(n);		break;	}	lastdcl = t;	return n;} Sym*mkstatic(Sym *s){	Sym *s1; 	if(s->class != CLOCAL)		return s;	snprint(symb, NSYMB, "%s$%d", s->name, s->block);	s1 = lookup();	if(s1->class != CSTATIC) {		s1->type = s->type;		s1->offset = s->offset;		s1->block = s->block;		s1->class = CSTATIC;	}	return s1;} /* * make a copy of a typedef * the problem is to split out incomplete * arrays so that it is in the variable * rather than the typedef. */Type*tcopy(Type *t){	Type *tl, *tx;	int et; 	if(t == T)		return t;	et = t->etype;	if(typesu[et])		return t;	tl = tcopy(t->link);	if(tl != t->link ||	  (et == TARRAY && t->width == 0)) {		tx = typ(TXXX, 0);		*tx = *t;		tx->link = tl;		return tx;	}	return t;} Node*doinit(Sym *s, Type *t, long o, Node *a){	Node *n, *reta; 	if(t == T)		return Z;	if(s->class == CEXTERN)		s->class = CGLOBL;	if(0) {		print("t = %T; o = %ld; n = %s\n", t, o, s->name);		prtree(a, "doinit value");	} 	n = initlist;	if(a->op == OINIT)		a = a->left;	initlist = a; 	reta = a;	init1(s, t, o, 0);	if(initlist != Z)		diag(initlist, "more initializers than structure: %s",			s->name);	initlist = n; 	return reta;} /* * get next major operator, * dont advance initlist. */Node*peekinit(void){	Node *a; 	a = initlist; loop:	if(a == Z)		return a;	if(a->op == OLIST) {		a = a->left;		goto loop;	}	return a;} /* * consume and return next element on * initlist. expand strings. */Node*nextinit(void){	Node *a, *n; 	a = initlist;	n = Z; 	if(a == Z)		return a;	if(a->op == OLIST) {		n = a->right;		a = a->left;	}	initlist = n;	return a;} intisstruct(Node *a, Type *t){	Node *n; 	switch(a->op) {	case ODOTDOT:		n = a->left;		if(n && n->type && sametype(n->type, t))			return 1;	case OSTRING:	case OLSTRING:	case OCONST:	case OINIT:	case OELEM:		return 0;	} 	n = new(ODOTDOT, Z, Z);	*n = *a; 	/*	 * ODOTDOT is a flag for tcom	 * a second tcom will not be performed	 */	a->op = ODOTDOT;	a->left = n;	a->right = Z; 	if(tcom(n))		return 0; 	if(sametype(n->type, t))		return 1;	return 0;} voidinit1(Sym *s, Type *t, long o, int exflag){	Node *a, *r, nod;	Type *t1;	long e, w, so, mw; 	a = peekinit();	if(a == Z)		return; 	if(0) {		print("t = %T; o = %ld; n = %s\n", t, o, s->name);		prtree(a, "init1 value");	} 	if(exflag && a->op == OINIT){		doinit(s, t, o, nextinit());		return;	} 	switch(t->etype) {	default:		diag(Z, "unknown type in initialization: %T to: %s", t, s->name);		return; 	case TCHAR:	case TUCHAR:	case TINT:	case TUINT:	case TSHORT:	case TUSHORT:	case TLONG:	case TULONG:	case TVLONG:	case TUVLONG:	case TFLOAT:	case TDOUBLE:	case TIND:	single:		if(a->op == OARRAY || a->op == OELEM)			return; 		a = nextinit();		if(a == Z)			return; 		if(t->nbits)			diag(Z, "cannot initialize bitfields");		if(0 && s->class == CAUTO)			return; 		complex(a);		if(a->type == T)			return; 		if(a->op == OCONST) {			if(!sametype(a->type, t)) {				/* hoop jumping to save malloc */				if(nodcast == Z)					nodcast = new(OCAST, Z, Z);				nod = *nodcast;				nod.left = a;				nod.type = t;				nod.lineno = a->lineno;				complex(&nod);				if(nod.type)					*a = nod;			}			if(a->op != OCONST) {/*				diag(a, "initializer is not a constant: %s",					s->name);*/				return;			}			if(vconst(a) == 0)				return;			return;		}		if(t->etype == TIND) {			while(a->op == OCAST) {				warn(a, "CAST in initialization ignored");				a = a->left;			}			if(0 && !sametype(t, a->type)) {				diag(a, "initialization of incompatible pointers: %s",					s->name);				print("%T and %T\n", t, a->type);			}/*			if(a->op == OADDR)				a = a->left;*/			return;		} 		while(a->op == OCAST)			a = a->left;		if(a->op == OADDR) {			warn(a, "initialize pointer to an integer: %s", s->name);			/* a = a->left; */			return;		}		/* diag(a, "initializer is not a constant: %s", s->name); */		return; 	case TARRAY:		w = t->link->width;		if(a->op == OSTRING || a->op == OLSTRING)		if(typei[t->link->etype]) { 			/*			 * get rid of null if sizes match exactly			 */			a = nextinit();			/* mw = t->width/w; */			so = a->type->width/a->type->link->width;			if(t->width <= 0)				t->width = w*(so-1);			USED(a);			return;		} 		mw = -w;		for(e=0;;) {			/*			 * peek ahead for element initializer			 */			a = peekinit();			if(a == Z)				break;			if(a->op == OELEM && t->link->etype != TSTRUCT)				break;			if(a->op == OARRAY) {				if(e && exflag)					break;				a = nextinit();				r = a->left;				complex(r);				if(r->op != OCONST) {					diag(r, "initializer subscript must be constant");					return;				}				e = r->vconst;				if(t->width != 0)					if(e < 0 || e*w >= t->width) {						diag(a, "initialization index out of range: %ld", e);						continue;					}			} 			so = e*w;			if(so > mw)				mw = so;			if(t->width != 0)				if(mw >= t->width)					break;			init1(s, t->link, o+so, 1);			e++;		}		if(t->width == 0)			t->width = mw+w;		return; 	case TUNION:	case TSTRUCT:		/*		 * peek ahead to find type of rhs.		 * if its a structure, then treat		 * this element as a variable		 * rather than an aggregate.		 */		if(isstruct(a, t))			goto single; 		if(t->width <= 0) {			diag(Z, "incomplete structure: %s", s->name);			return;		} 	again:		for(t1 = t->link; t1 != T; t1 = t1->down) {			if(a->op == OARRAY && t1->etype != TARRAY)				break;			if(a->op == OELEM) {				if(t1->sym != a->sym)					continue;				nextinit();			}			init1(s, t1, o+t1->offset, 1);			a = peekinit();			if(a == Z)				break;			if(a->op == OELEM)				goto again;		}		if(a && a->op == OELEM)			diag(a, "structure element not found %F", a);		return;	}} /*Node*newlist(Node *l, Node *r){	if(r == Z)		return l;	if(l == Z)		return r;	return new(OLIST, l, r);}*/ voidsuallign(Type *t){	Type *l;	long o, w; 	o = 0;	switch(t->etype) { 	case TSTRUCT:		t->offset = 0;		w = 0;		for(l = t->link; l != T; l = l->down) {			if(l->nbits) {				if(l->shift <= 0) {					l->shift = -l->shift;					w = round(w, tfield->width);					o = w;					w += tfield->width;				}				l->offset = o;			} else {				if(l->width <= 0)					if(l->sym)						diag(Z, "incomplete structure element: %s",							l->sym->name);

Lines 1–500 of 1387.