Charles.Forsyth20060303644188019 years agoHistory
1630 lines · 26.2 KB · C
RawDownload
#include "cc.h" Node*dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n){	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;		}		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;		n->xoffset = s->offset;		n->class = s->class;		n->etype = TVOID;		if(n->type != T)			n->etype = n->type->etype;		if(debug['d'])			dbgdecl(s);		acidvar(s);		s->varlineno = lineno;		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 = copytyp(t);		tx->link = tl;		return tx;	}	return t;} Node*doinit(Sym *s, Type *t, long o, Node *a){	Node *n; 	if(t == T)		return Z;	if(s->class == CEXTERN) {		s->class = CGLOBL;		if(debug['d'])			dbgdecl(s);	}	if(debug['i']) {		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; 	a = init1(s, t, o, 0);	if(initlist != Z)		diag(initlist, "more initializers than structure: %s",			s->name);	initlist = n; 	return a;} /* * 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, *b, *n; 	a = initlist;	n = Z; 	if(a == Z)		return a;	if(a->op == OLIST) {		n = a->right;		a = a->left;	}	if(a->op == OUSED) {		a = a->left;		b = new(OCONST, Z, Z);		b->type = a->type->link;		if(a->op == OSTRING) {			b->vconst = convvtox(*a->cstring, TCHAR);			a->cstring++;		}		if(a->op == OLSTRING) {			b->vconst = convvtox(*a->rstring, TUSHORT);			a->rstring++;		}		a->type->width -= b->type->width;		if(a->type->width <= 0)			initlist = n;		return b;	}	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;} Node*init1(Sym *s, Type *t, long o, int exflag){	Node *a, *l, *r, nod;	Type *t1;	long e, w, so, mw; 	a = peekinit();	if(a == Z)		return Z; 	if(debug['i']) {		print("t = %T; o = %ld; n = %s\n", t, o, s->name);		prtree(a, "init1 value");	} 	if(exflag && a->op == OINIT)		return doinit(s, t, o, nextinit()); 	switch(t->etype) {	default:		diag(Z, "unknown type in initialization: %T to: %s", t, s->name);		return Z; 	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 Z; 		a = nextinit();		if(a == Z)			return Z; 		if(t->nbits)			diag(Z, "cannot initialize bitfields");		if(s->class == CAUTO) {			l = new(ONAME, Z, Z);			l->sym = s;			l->type = t;			l->etype = TVOID;			if(s->type)				l->etype = s->type->etype;			l->xoffset = s->offset + o;			l->class = s->class; 			l = new(OASI, l, a);			return l;		} 		complex(a);		if(a->type == T)			return Z; 		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 Z;			}			if(vconst(a) == 0)				return Z;			goto gext;		}		if(t->etype == TIND) {			while(a->op == OCAST) {				warn(a, "CAST in initialization ignored");				a = a->left;			}			if(!sametype(t, a->type)) {				diag(a, "initialization of incompatible pointers: %s\n%T and %T",					s->name, t, a->type);			}			if(a->op == OADDR)				a = a->left;			goto gext;		} 		while(a->op == OCAST)			a = a->left;		if(a->op == OADDR) {			warn(a, "initialize pointer to an integer: %s", s->name);			a = a->left;			goto gext;		}		diag(a, "initializer is not a constant: %s", s->name);		return Z; 	gext:		gextern(s, a, o, t->width); 		return Z; 	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(mw && so > mw) {				if(so != mw+1)					diag(a, "string initialization larger than array");				a->type->width -= a->type->link->width;			} 			/*			 * arrange strings to be expanded			 * inside OINIT braces.			 */			a = new(OUSED, a, Z);			return doinit(s, t, o, a);		} 		mw = -w;		l = Z;		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 Z;				}				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;			r = init1(s, t->link, o+so, 1);			l = newlist(l, r);			e++;		}		if(t->width == 0)			t->width = mw+w;		return l; 	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 Z;		}		l = Z; 	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();			}			r = init1(s, t1, o+t1->offset, 1);			l = newlist(l, r);			a = peekinit();			if(a == Z)				break;			if(a->op == OELEM)				goto again;		}

Lines 1–500 of 1630.