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

📄 dcl.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	int r;	r = anyproto(n->right);	if(r == 0 || (r & OLDPROTO)) {		if(r & ANSIPROTO)			diag(n, "mixed ansi/old function declaration: %F", n->left);		return T;	}	return fnproto1(n->right);}intanyproto(Node *n){	int r;	r = 0;loop:	if(n == Z)		return r;	switch(n->op) {	case OLIST:		r |= anyproto(n->left);		n = n->right;		goto loop;	case ODOTDOT:	case OPROTO:		return r | ANSIPROTO;	}	return r | OLDPROTO;}Type*fnproto1(Node *n){	Type *t;	if(n == Z)		return T;	switch(n->op) {	case OLIST:		t = fnproto1(n->left);		if(t != T)			t->down = fnproto1(n->right);		return t;	case OPROTO:		lastdcl = T;		dodecl(NODECL, CXXX, n->type, n->left);		t = typ(TXXX, T);		if(lastdcl != T)			*t = *paramconv(lastdcl, 1);		return t;	case ONAME:		diag(n, "incomplete argument prototype");		return typ(TINT, T);	case ODOTDOT:		return typ(TDOT, T);	}	diag(n, "unknown op in fnproto");	return T;}voiddbgdecl(Sym *s){	print("decl \"%s\": C=%s [B=%d:O=%ld] T=%T\n",		s->name, cnames[s->class], s->block, s->offset, s->type);}Decl*push(void){	Decl *d;	d = alloc(sizeof(*d));	d->link = dclstack;	dclstack = d;	return d;}Decl*push1(Sym *s){	Decl *d;	d = push();	d->sym = s;	d->val = DAUTO;	d->type = s->type;	d->class = s->class;	d->offset = s->offset;	d->block = s->block;	d->varlineno = s->varlineno;	d->aused = s->aused;	return d;}intsametype(Type *t1, Type *t2){	if(t1 == t2)		return 1;	return rsametype(t1, t2, 5, 1);}intrsametype(Type *t1, Type *t2, int n, int f){	int et;	n--;	for(;;) {		if(t1 == t2)			return 1;		if(t1 == T || t2 == T)			return 0;		if(n <= 0)			return 1;		et = t1->etype;		if(et != t2->etype)			return 0;		if(et == TFUNC) {			if(!rsametype(t1->link, t2->link, n, 0))				return 0;			t1 = t1->down;			t2 = t2->down;			while(t1 != T && t2 != T) {				if(t1->etype == TOLD) {					t1 = t1->down;					continue;				}				if(t2->etype == TOLD) {					t2 = t2->down;					continue;				}				while(t1 != T || t2 != T) {					if(!rsametype(t1, t2, n, 0))						return 0;					t1 = t1->down;					t2 = t2->down;				}				break;			}			return 1;		}		if(et == TARRAY)			if(t1->width != t2->width && t1->width != 0 && t2->width != 0)				return 0;		if(typesu[et]) {			if(t1->link == T)				snap(t1);			if(t2->link == T)				snap(t2);			t1 = t1->link;			t2 = t2->link;			for(;;) {				if(t1 == t2)					return 1;				if(!rsametype(t1, t2, n, 0))					return 0;				t1 = t1->down;				t2 = t2->down;			}		}		t1 = t1->link;		t2 = t2->link;		if((f || !debug['V']) && et == TIND) {			if(t1 != T && t1->etype == TVOID)				return 1;			if(t2 != T && t2->etype == TVOID)				return 1;		}	}}typedef struct Typetab Typetab;struct Typetab{	int n;	Type **a;};static intsigind(Type *t, Typetab *tt){	int n;	Type **a, **na, **p, **e;	n = tt->n;	a = tt->a;	e = a+n;	/* linear search seems ok */	for(p = a ; p < e; p++)		if(sametype(*p, t))			return p-a;	if((n&15) == 0){		na = malloc((n+16)*sizeof(Type*));		memmove(na, a, n*sizeof(Type*));		free(a);		a = tt->a = na;	}	a[tt->n++] = t;	return -1;}static ulongsignat(Type *t, Typetab *tt){	int i;	Type *t1;	long s;	s = 0;	for(; t; t=t->link) {		s = s*thash1 + thash[t->etype];		if(t->garb&GINCOMPLETE)			return s;		switch(t->etype) {		default:			return s;		case TARRAY:			s = s*thash2 + 0;	/* was t->width */			break;		case TFUNC:			for(t1=t->down; t1; t1=t1->down)				s = s*thash3 + signat(t1, tt);			break;		case TSTRUCT:		case TUNION:			if((i = sigind(t, tt)) >= 0){				s = s*thash2 + i;				return s;			}			for(t1=t->link; t1; t1=t1->down)				s = s*thash3 + signat(t1, tt);			return s;		case TIND:			break;		}	}	return s;}ulongsignature(Type *t){	ulong s;	Typetab tt;	tt.n = 0;	tt.a = nil;	s = signat(t, &tt);	free(tt.a);	return s;}ulongsign(Sym *s){	ulong v;	Type *t;	if(s->sig == SIGINTERN)		return SIGNINTERN;	if((t = s->type) == T)		return 0;	v = signature(t);	if(v == 0)		v = SIGNINTERN;	return v;}voidsnap(Type *t){	if(typesu[t->etype])	if(t->link == T && t->tag && t->tag->suetag) {		t->link = t->tag->suetag->link;		t->width = t->tag->suetag->width;	}}Type*dotag(Sym *s, int et, int bn){	Decl *d;	if(bn != 0 && bn != s->sueblock) {		d = push();		d->sym = s;		d->val = DSUE;		d->type = s->suetag;		d->block = s->sueblock;		s->suetag = T;	}	if(s->suetag == T) {		s->suetag = typ(et, T);		s->sueblock = autobn;	}	if(s->suetag->etype != et)		diag(Z, "tag used for more than one type: %s",			s->name);	if(s->suetag->tag == S)		s->suetag->tag = s;	return s->suetag;}Node*dcllabel(Sym *s, int f){	Decl *d, d1;	Node *n;	n = s->label;	if(n != Z) {		if(f) {			if(n->complex)				diag(Z, "label reused: %s", s->name);			n->complex = 1;	// declared		} else			n->addable = 1;	// used		return n;	}	d = push();	d->sym = s;	d->val = DLABEL;	dclstack = d->link;	d1 = *firstdcl;	*firstdcl = *d;	*d = d1;	firstdcl->link = d;	firstdcl = d;	n = new(OXXX, Z, Z);	n->sym = s;	n->complex = f;	n->addable = !f;	s->label = n;	if(debug['d'])		dbgdecl(s);	return n;}Type*paramconv(Type *t, int f){	switch(t->etype) {	case TUNION:	case TSTRUCT:		if(t->width <= 0)			diag(Z, "incomplete structure: %s", t->tag->name);		break;	case TARRAY:		t = typ(TIND, t->link);		t->width = types[TIND]->width;		break;	case TFUNC:		t = typ(TIND, t);		t->width = types[TIND]->width;		break;	case TFLOAT:		if(!f)			t = types[TDOUBLE];		break;	case TCHAR:	case TSHORT:		if(!f)			t = types[TINT];		break;	case TUCHAR:	case TUSHORT:		if(!f)			t = types[TUINT];		break;	}	return t;}voidadecl(int c, Type *t, Sym *s){	if(c == CSTATIC)		c = CLOCAL;	if(t->etype == TFUNC) {		if(c == CXXX)			c = CEXTERN;		if(c == CLOCAL)			c = CSTATIC;		if(c == CAUTO || c == CEXREG)			diag(Z, "function cannot be %s %s", cnames[c], s->name);	}	if(c == CXXX)		c = CAUTO;	if(s) {		if(s->class == CSTATIC)			if(c == CEXTERN || c == CGLOBL) {				warn(Z, "just say static: %s", s->name);				c = CSTATIC;			}		if(s->class == CAUTO || s->class == CPARAM || s->class == CLOCAL)		if(s->block == autobn)			diag(Z, "auto redeclaration of: %s", s->name);		if(c != CPARAM)			push1(s);		s->block = autobn;		s->offset = 0;		s->type = t;		s->class = c;		s->aused = 0;	}	switch(c) {	case CAUTO:		autoffset = align(autoffset, t, Aaut3);		stkoff = maxround(stkoff, autoffset);		s->offset = -autoffset;		break;	case CPARAM:		if(autoffset == 0) {			firstarg = s;			firstargtype = t;		}		autoffset = align(autoffset, t, Aarg1);		if(s)			s->offset = autoffset;		autoffset = align(autoffset, t, Aarg2);		break;	}}voidpdecl(int c, Type *t, Sym *s){	if(s && s->offset != -1) {		diag(Z, "not a parameter: %s", s->name);		return;	}	t = paramconv(t, c==CPARAM);	if(c == CXXX)		c = CPARAM;	if(c != CPARAM) {		diag(Z, "parameter cannot have class: %s", s->name);		c = CPARAM;	}	adecl(c, t, s);}voidxdecl(int c, Type *t, Sym *s){	long o;	o = 0;	switch(c) {	case CEXREG:		o = exreg(t);		if(o == 0)			c = CEXTERN;		if(s->class == CGLOBL)			c = CGLOBL;		break;	case CEXTERN:		if(s->class == CGLOBL)			c = CGLOBL;		break;	case CXXX:		c = CGLOBL;		if(s->class == CEXTERN)			s->class = CGLOBL;		break;	case CAUTO:		diag(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]);		c = CEXTERN;		break;	case CTYPESTR:		if(!typesuv[t->etype]) {			diag(Z, "typestr must be struct/union: %s", s->name);			break;		}		dclfunct(t, s);		break;	}	if(s->class == CSTATIC)		if(c == CEXTERN || c == CGLOBL) {			warn(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]);			c = CSTATIC;		}	if(s->type != T)		if(s->class != c || !sametype(t, s->type) || t->etype == TENUM) {			diag(Z, "external redeclaration of: %s", s->name);			Bprint(&diagbuf, "	%s %T %L\n", cnames[c], t, nearln);			Bprint(&diagbuf, "	%s %T %L\n", cnames[s->class], s->type, s->varlineno);		}	tmerge(t, s);	s->type = t;	s->class = c;	s->block = 0;	s->offset = o;}voidtmerge(Type *t1, Sym *s){	Type *ta, *tb, *t2;	t2 = s->type;/*print("merge	%T; %T\n", t1, t2);/**/	for(;;) {		if(t1 == T || t2 == T || t1 == t2)			break;		if(t1->etype != t2->etype)			break;		switch(t1->etype) {		case TFUNC:			ta = t1->down;			tb = t2->down;			if(ta == T) {				t1->down = tb;				break;			}			if(tb == T)				break;			while(ta != T && tb != T) {				if(ta == tb)					break;				/* ignore old-style flag */				if(ta->etype == TOLD) {					ta = ta->down;					continue;				}				if(tb->etype == TOLD) {					tb = tb->down;					continue;				}				/* checking terminated by ... */				if(ta->etype == TDOT && tb->etype == TDOT) {					ta = T;					tb = T;					break;				}				if(!sametype(ta, tb))					break;				ta = ta->down;				tb = tb->down;			}			if(ta != tb)				diag(Z, "function inconsistently declared: %s", s->name);			/* take new-style over old-style */			ta = t1->down;			tb = t2->down;			if(ta != T && ta->etype == TOLD)				if(tb != T && tb->etype != TOLD)					t1->down = tb;			break;		case TARRAY:			/* should we check array size change? */			if(t2->width > t1->width)				t1->width = t2->width;			break;		case TUNION:		case TSTRUCT:			return;		}		t1 = t1->link;		t2 = t2->link;	}}voidedecl(int c, Type *t, Sym *s){	Type *t1;	if(s == S) {		if(!typesu[t->etype])			diag(Z, "unnamed structure element must be struct/union");		if(c != CXXX)			diag(Z, "unnamed structure element cannot have class");	} else		if(c != CXXX)			diag(Z, "structure element cannot have class: %s", s->name);	t1 = t;	t = copytyp(t1);	t->sym = s;	t->down = T;	if(lastfield) {		t->shift = lastbit - lastfield;		t->nbits = lastfield;		if(firstbit)			t->shift = -t->shift;		if(typeu[t->etype])			t->etype = tufield->etype;		else			t->etype = tfield->etype;	}	if(strf == T)		strf = t;	else		strl->down = t;	strl = t;}/* * this routine is very suspect. * ansi requires the enum type to * be represented as an 'int' * this means that 0x81234567 * would be illegal. this routine * makes signed and unsigned go * to unsigned. */Type*maxtype(Type *t1, Type *t2){	if(t1 == T)		return t2;	if(t2 == T)		return t1;	if(t1->etype > t2->etype)		return t1;	return t2;}voiddoenum(Sym *s, Node *n){	if(n) {		complex(n);		if(n->op != OCONST) {			diag(n, "enum not a constant: %s", s->name);			return;		}		en.cenum = n->type;		en.tenum = maxtype(en.cenum, en.tenum);		if(!typefd[en.cenum->etype])			en.lastenum = n->vconst;		else			en.floatenum = n->fconst;	}	if(dclstack)		push1(s);	xdecl(CXXX, types[TENUM], s);	if(en.cenum == T) {		en.tenum = types[TINT];		en.cenum = types[TINT];		en.lastenum = 0;	}	s->tenum = en.cenum;	if(!typefd[s->tenum->etype]) {		s->vconst = convvtox(en.lastenum, s->tenum->etype);		en.lastenum++;	} else {		s->fconst = en.floatenum;		en.floatenum++;	}	if(debug['d'])		dbgdecl(s);	acidvar(s);}voidsymadjust(Sym *s, Node *n, long del){	switch(n->op) {	default:		if(n->left)			symadjust(s, n->left, del);		if(n->right)			symadjust(s, n->right, del);		return;	case ONAME:		if(n->sym == s)			n->xoffset -= del;		return;	case OCONST:	case OSTRING:	case OLSTRING:	case OINDREG:	case OREGISTER:		return;	}}Node*contig(Sym *s, Node *n, long v){	Node *p, *r, *q, *m;	long w;	Type *zt;	if(debug['i']) {		print("contig v = %ld; s = %s\n", v, s->name);		prtree(n, "doinit value");	}	if(n == Z)		goto no;	w = s->type->width;	/*	 * nightmare: an automatic array whose size	 * increases when it is initialized	 */	if(v != w) {		if(v != 0)			diag(n, "automatic adjustable array: %s", s->name);		v = s->offset;		autoffset = align(autoffset, s->type, Aaut3);		s->offset = -autoffset;		stkoff = maxround(stkoff, autoffset);		symadjust(s, n, v - s->offset);	}	if(w <= ewidth[TIND])		goto no;	if(n->op == OAS)		diag(Z, "oops in contig");/*ZZZ this appears incorrectneed to check if the list completely covers the data.if not, bail */	if(n->op == OLIST)		goto no;	if(n->op == OASI)		if(n->left->type)		if(n->left->type->width == w)			goto no;	while(w & (ewidth[TIND]-1))		w++;/* * insert the following code, where long becomes vlong if pointers are fat *	*(long**)&X = (long*)((char*)X + sizeof(X));	do {		*(long**)&X -= 1;		**(long**)&X = 0;	} while(*(long**)&X); */	for(q=n; q->op != ONAME; q=q->left)		;	zt = ewidth[TIND] > ewidth[TLONG]? types[TVLONG]: types[TLONG];	p = new(ONAME, Z, Z);	*p = *q;	p->type = typ(TIND, zt);	p->xoffset = s->offset;	r = new(ONAME, Z, Z);	*r = *p;	r = new(OPOSTDEC, r, Z);	q = new(ONAME, Z, Z);	*q = *p;	q = new(OIND, q, Z);	m = new(OCONST, Z, Z);	m->vconst = 0;	m->type = zt;	q = new(OAS, q, m);	r = new(OLIST, r, q);	q = new(ONAME, Z, Z);	*q = *p;	r = new(ODWHILE, q, r);	q = new(ONAME, Z, Z);	*q = *p;	q->type = q->type->link;	q->xoffset += w;	q = new(OADDR, q, 0);	q = new(OASI, p, q);	r = new(OLIST, q, r);	n = new(OLIST, r, n);no:	return n;}

⌨️ 快捷键说明

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