⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcl.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#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(vconst(a) && t->etype == TIND && a->type && a->type->etype != TIND){				diag(a, "initialize pointer to an integer: %s", s->name);				return Z;			}			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;		}		if(a && a->op == OELEM)			diag(a, "structure element not found %F", a);		return l;	}}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->down != T)					if(l->sym)						diag(Z, "incomplete structure element: %s",							l->sym->name);					else						diag(Z, "incomplete structure element");				w = align(w, l, Ael1);				l->offset = w;				w = align(w, l, Ael2);			}		}		w = align(w, t, Asu2);		t->width = w;		acidtype(t);		pickletype(t);		return;	case TUNION:		t->offset = 0;		w = 0;		for(l = t->link; l != T; l = l->down) {			if(l->width <= 0)				if(l->sym)					diag(Z, "incomplete union element: %s",						l->sym->name);				else					diag(Z, "incomplete union element");			l->offset = 0;			l->shift = 0;			o = align(align(0, l, Ael1), l, Ael2);			if(o > w)				w = o;		}		w = align(w, t, Asu2);		t->width = w;		acidtype(t);		pickletype(t);		return;	default:		diag(Z, "unknown type in suallign: %T", t);		break;	}}longround(long v, int w){	int r;	if(w <= 0 || w > 8) {		diag(Z, "rounding by %d", w);		w = 1;	}	r = v%w;	if(r)		v += w-r;	return v;}Type*ofnproto(Node *n){	Type *tl, *tr, *t;	if(n == Z)		return T;	switch(n->op) {	case OLIST:		tl = ofnproto(n->left);		tr = ofnproto(n->right);		if(tl == T)			return tr;		tl->down = tr;		return tl;	case ONAME:		t = copytyp(n->sym->type);		t->down = T;		return t;	}	return T;}#define	ANSIPROTO	1#define	OLDPROTO	2voidargmark(Node *n, int pass){	Type *t;	autoffset = align(0, thisfn->link, Aarg0);	stkoff = 0;	for(; n->left != Z; n = n->left) {		if(n->op != OFUNC || n->left->op != ONAME)			continue;		walkparam(n->right, pass);		if(pass != 0 && anyproto(n->right) == OLDPROTO) {			t = typ(TFUNC, n->left->sym->type->link);			t->down = typ(TOLD, T);			t->down->down = ofnproto(n->right);			tmerge(t, n->left->sym);			n->left->sym->type = t;		}		break;	}	autoffset = 0;	stkoff = 0;}voidwalkparam(Node *n, int pass){	Sym *s;	Node *n1;	if(n != Z && n->op == OPROTO && n->left == Z && n->type == types[TVOID])		return;loop:	if(n == Z)		return;	switch(n->op) {	default:		diag(n, "argument not a name/prototype: %O", n->op);		break;	case OLIST:		walkparam(n->left, pass);		n = n->right;		goto loop;	case OPROTO:		for(n1 = n; n1 != Z; n1=n1->left)			if(n1->op == ONAME) {				if(pass == 0) {					s = n1->sym;					push1(s);					s->offset = -1;					break;				}				dodecl(pdecl, CPARAM, n->type, n->left);				break;			}		if(n1)			break;		if(pass == 0) {			/*			 * extension:			 *	allow no name in argument declaration			diag(Z, "no name in argument declaration");			 */			break;		}		dodecl(NODECL, CPARAM, n->type, n->left);		pdecl(CPARAM, lastdcl, S);		break;	case ODOTDOT:		break;		case ONAME:		s = n->sym;		if(pass == 0) {			push1(s);			s->offset = -1;			break;		}		if(s->offset != -1) {			if(autoffset == 0) {				firstarg = s;				firstargtype = s->type;			}			autoffset = align(autoffset, s->type, Aarg1);			s->offset = autoffset;			autoffset = align(autoffset, s->type, Aarg2);		} else			dodecl(pdecl, CXXX, types[TINT], n);		break;	}}voidmarkdcl(void){	Decl *d;	blockno++;	d = push();	d->val = DMARK;	d->offset = autoffset;	d->block = autobn;	autobn = blockno;}Node*revertdcl(void){	Decl *d;	Sym *s;	Node *n, *n1;	n = Z;	for(;;) {		d = dclstack;		if(d == D) {			diag(Z, "pop off dcl stack");			break;		}		dclstack = d->link;		s = d->sym;		switch(d->val) {		case DMARK:			autoffset = d->offset;			autobn = d->block;			return n;		case DAUTO:			if(debug['d'])				print("revert1 \"%s\"\n", s->name);			if(s->aused == 0) {				nearln = s->varlineno;				if(s->class == CAUTO)					warn(Z, "auto declared and not used: %s", s->name);				if(s->class == CPARAM)					warn(Z, "param declared and not used: %s", s->name);			}			if(s->type && (s->type->garb & GVOLATILE)) {				n1 = new(ONAME, Z, Z);				n1->sym = s;				n1->type = s->type;				n1->etype = TVOID;				if(n1->type != T)					n1->etype = n1->type->etype;				n1->xoffset = s->offset;				n1->class = s->class;				n1 = new(OADDR, n1, Z);				n1 = new(OUSED, n1, Z);				if(n == Z)					n = n1;				else					n = new(OLIST, n1, n);			}			s->type = d->type;			s->class = d->class;			s->offset = d->offset;			s->block = d->block;			s->varlineno = d->varlineno;			s->aused = d->aused;			break;		case DSUE:			if(debug['d'])				print("revert2 \"%s\"\n", s->name);			s->suetag = d->type;			s->sueblock = d->block;			break;		case DLABEL:			if(debug['d'])				print("revert3 \"%s\"\n", s->name);			if(s->label && s->label->addable == 0)				warn(s->label, "label declared and not used \"%s\"", s->name);			s->label = Z;			break;		}	}	return n;}Type*fnproto(Node *n){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -