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

📄 c01.c

📁 unix v6 的c compiler 很老了
💻 C
字号:
#/* * C compiler * * */#include "c0h.c"/* * Called from tree, this routine takes the top 1, 2, or 3 * operands on the expression stack, makes a new node with * the operator op, and puts it on the stack. * Essentially all the work is in inserting * appropriate conversions. */build(op) {	register int t1;	int t2, t3, t;	struct tnode *p3, *disarray();	register struct tnode *p1, *p2;	int d, dope, leftc, cvn, pcvn;	/*	 * a[i] => *(a+i)	 */	if (op==LBRACK) {		build(PLUS);		op = STAR;	}	dope = opdope[op];	if ((dope&BINARY)!=0) {		p2 = chkfun(disarray(*--cp));		t2 = p2->type;	}	p1 = *--cp;	/*	 * sizeof gets turned into a number here.	 * Bug: sizeof(structure-member-array) is 2 because	 * the array has been turned into a ptr already.	 */	if (op==SIZEOF) {		t1 = length(p1);		p1->op = CON;		p1->type = INT;		p1->dimp = 0;		p1->value = t1;		*cp++ = p1;		return;	}	if (op!=AMPER) {		p1 = disarray(p1);		if (op!=CALL)			p1 = chkfun(p1);	}	t1 = p1->type;	pcvn = 0;	t = INT;	switch (op) {	/* end of expression */	case 0:		*cp++ = p1;		return;	/* no-conversion operators */	case QUEST:		if (p2->op!=COLON)			error("Illegal conditional");		t = t2;	case COMMA:	case LOGAND:	case LOGOR:		*cp++ = block(2, op, t, 0, p1, p2);		return;	case CALL:		if ((t1&XTYPE) != FUNC)			error("Call of non-function");		*cp++ = block(2,CALL,decref(t1),p1->dimp,p1,p2);		return;	case STAR:		if (p1->op==AMPER ) {			*cp++ = p1->tr1;			return;		}		if ((t1&XTYPE) == FUNC)			error("Illegal indirection");		*cp++ = block(1,STAR,decref(t1),p1->dimp,p1);		return;	case AMPER:		if (p1->op==STAR) {			p1->tr1->dimp = p1->dimp;			p1->tr1->type = incref(t1);			*cp++ = p1->tr1;			return;		}		if (p1->op==NAME) {			*cp++ = block(1,op,incref(t1),p1->dimp,p1);			return;		}		error("Illegal lvalue");		break;	/*	 * a->b goes to (*a).b	 */	case ARROW:		*cp++ = p1;		chkw(p1, -1);		p1->type = PTR+STRUCT;		build(STAR);		p1 = *--cp;	/*	 * In a.b, a fairly complicated process has to	 * be used to make the left operand look	 * as if it had the type of the second.	 * Also, the offset in the structure has to be	 * given a special type to prevent conversion.	 */	case DOT:		if (p2->op!=NAME || (p2->class!=MOS && p2->class!=FMOS))			error("Illegal structure ref");		*cp++ = p1;		t = t2;		if ((t&XTYPE) == ARRAY) {			t = decref(t);			p2->ssp++;		}		setype(p1, t, p2->dimp);		build(AMPER);		*cp++ = block(1,CON,NOTYPE,0,p2->nloc);		build(PLUS);		if ((t2&XTYPE) != ARRAY)			build(STAR);		if (p2->class == FMOS)			*cp++ = block(2, FSEL, t, 0, *--cp, p2->dimp);		return;	}	if ((dope&LVALUE)!=0)		chklval(p1);	if ((dope&LWORD)!=0)		chkw(p1, LONG);	if ((dope&RWORD)!=0)		chkw(p2, LONG);	if ((dope&BINARY)==0) {		if (op==ITOF)			t1 = DOUBLE;		else if (op==FTOI)			t1 = INT;		if (!fold(op, p1, 0))			*cp++ = block(1,op,t1,p1->dimp,p1);		return;	}	cvn = 0;	if (t1==STRUCT || t2==STRUCT) {		error("Unimplemented structure operation");		t1 = t2 = INT;	}	if (t2==NOTYPE) {		t = t1;		p2->type = INT;	/* no int cv for struct */		t2 = INT;	} else		cvn = cvtab[lintyp(t1)][lintyp(t2)];	leftc = (cvn>>4)&017;	cvn =& 017;	t = leftc? t2:t1;	if (dope&ASSGOP) {		t = t1;		if (op==ASSIGN && (cvn==ITP||cvn==PTI))			cvn = leftc = 0;		if (leftc)			cvn = leftc;		leftc = 0;	} else if (op==COLON && t1>=PTR && t1==t2)		cvn = 0;	else if (dope&RELAT) {		if (op>=LESSEQ && (t1>=PTR || t2>=PTR))			op =+ LESSEQP-LESSEQ;		if (cvn==PTI)			cvn = 0;	}	if (cvn==PTI) {		cvn = 0;		if (op==MINUS) {			t = INT;			pcvn++;		} else {			if (t1!=t2 || t1!=(PTR+CHAR))				cvn = XX;		}	}	if (cvn) {		t1 = plength(p1);		t2 = plength(p2);		if (cvn==XX || (cvn==PTI&&t1!=t2))			error("Illegal conversion");		else if (leftc)			p1 = convert(p1, t, cvn, t2);		else			p2 = convert(p2, t, cvn, t1);	}	if (dope&RELAT)		t = INT;	if (fold(op, p1, p2)==0)		*cp++ = block(2,op,t,(p1->dimp==0? p2:p1)->dimp,p1,p2);	if (pcvn && t1!=(PTR+CHAR)) {		p1 = *--cp;		*cp++ = convert(p1, 0, PTI, plength(p1->tr1));	}}/* * Generate the appropirate conversion operator. * For pointer <=> integer this is a multiplication * or division, otherwise a special operator. */convert(p, t, cvn, len)struct tnode *p;{	register int n;	switch(cvn) {	case PTI:	case ITP:		if (len==1)			return(p);		return(block(2, (cvn==PTI?DIVIDE:TIMES), t, 0, p,			block(1, CON, 0, 0, len)));	case ITF:		n = ITOF;		break;	case FTI:		n = FTOI;		break;	case ITL:		n = ITOL;		break;	case LTI:		n = LTOI;		break;	case FTL:		n = FTOL;		break;	case LTF:		n = LTOF;		break;	}	return(block(1, n, t, 0, p));}/* * Traverse an expression tree, adjust things * so the types of things in it are consistent * with the view that its top node has * type at. * Used with structure references. */setype(ap, at, adimptr)struct tnode *ap;{	register struct tnode *p;	register t, dimptr;	p = ap;	t = at;	dimptr = adimptr;	p->type = t;	if (dimptr != -1)		p->dimp = dimptr;	switch(p->op) {	case AMPER:		setype(p->tr1, decref(t), dimptr);		return;	case STAR:		setype(p->tr1, incref(t), dimptr);		return;	case PLUS:	case MINUS:		setype(p->tr1, t, dimptr);	}}/* * A mention of a function name is turned into * a pointer to that function. */chkfun(ap)struct tnode *ap;{	register struct tnode *p;	register int t;	p = ap;	if (((t = p->type)&XTYPE)==FUNC)		return(block(1,AMPER,incref(t),p->dimp,p));	return(p);}/* * A mention of an array is turned into * a pointer to the base of the array. */struct tnode *disarray(ap)struct tnode *ap;{	register int t;	register struct tnode *p;	p = ap;	/* check array & not MOS */	if (((t = p->type)&XTYPE)!=ARRAY || p->op==NAME&&p->class==MOS)		return(p);	p->ssp++;	*cp++ = p;	setype(p, decref(t), -1);	build(AMPER);	return(*--cp);}/* * make sure that p is a ptr to a node * with type int or char or 'okt.' * okt might be nonexistent or 'long' * (e.g. for <<). */chkw(p, okt)struct tnode *p;{	register int t;	if ((t=p->type)>CHAR && t<PTR && t!=okt)		error("Integer operand required");	return;}/* *'linearize' a type for looking up in the * conversion table */lintyp(t){	switch(t) {	case INT:	case CHAR:		return(0);	case FLOAT:	case DOUBLE:		return(1);	case LONG:		return(2);	default:		return(3);	}}/* * Report an error. */error(s, p1, p2, p3, p4, p5, p6){	nerror++;	printf("%d: ", line);	printf(s, p1, p2, p3, p4, p5, p6);	printf("\n");}/* * Generate a node in an expression tree, * setting the operator, type, degree (unused in this pass) * and the operands. */block(an, op, t, d, p1,p2,p3)int *p1, *p2, *p3;{	register int *ap, *p, n;	int *oldp;	n = an+3;	p = gblock(n);	oldp = p;	ap = &op;	do {		*p++ = *ap++;	} while (--n);	return(oldp);}/* * Assign an unitialized block for use in the * expression tree. */gblock(n){	register int *p;	p = space;	if ((space =+ n) >= &osspace[OSSIZ]) {		error("Expression overflow");		exit(1);	}	return(p);}/* * Check that a tree can be used as an lvalue. */chklval(ap)struct tnode *ap;{	register struct tnode *p;	p = ap;	if (p->op!=NAME && p->op!=STAR)		error("Lvalue required");}/* * reduce some forms of `constant op constant' * to a constant.  More of this is done in the next pass * but this is used to allow constant expressions * to be used in switches and array bounds. */fold(op, ap1, ap2)struct tnode *ap1, *ap2;{	register struct tnode *p1;	register int v1, v2;	p1 = ap1;	if (p1->op!=CON || (ap2!=0 && ap2->op!=CON))		return(0);	v1 = p1->value;	v2 = ap2->value;	switch (op) {	case PLUS:		v1 =+ v2;		break;	case MINUS:		v1 =- v2;		break;	case TIMES:		v1 =* v2;		break;	case DIVIDE:		v1 =/ v2;		break;	case MOD:		v1 =% v2;		break;	case AND:		v1 =& v2;		break;	case OR:		v1 =| v2;		break;	case EXOR:		v1 =^ v2;		break;	case NEG:		v1 = - v1;		break;	case COMPL:		v1 = ~ v1;		break;	case LSHIFT:		v1 =<< v2;		break;	case RSHIFT:		v1 =>> v2;		break;	default:		return(0);	}	p1->value = v1;	*cp++ = p1;	return(1);}/* * Compile an expression expected to have constant value, * for example an array bound or a case value. */conexp(){	register struct tnode *t;	initflg++;	if (t = tree())		if (t->op != CON)			error("Constant required");	initflg--;	return(t->value);}

⌨️ 快捷键说明

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