trees.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,611 行 · 第 1/3 页

C
1,611
字号
		p->in.left = strargs( p->in.left );		p->in.right = strargs( p->in.right );		return( p );		}	if( p->in.type == STRTY || p->in.type == UNIONTY ){		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );		p->in.left = buildtree( UNARY AND, p->in.left, NIL );		p = clocal(p);		}	return( p );	}chkstr( i, j, type ) TWORD type; {	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */	/* i has been checked to contain a MOS or MOU */	/* j is the index in dimtab of the members... */	int k, kk;	extern int ddebug;# ifndef BUG1#ifndef FLEXNAMES	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );#else	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );#endif# endif	if( (k = j) < 0 ) uerror( "undefined structure or union" );	else {		for( ; (kk = dimtab[k] ) >= 0; ++k ){			if( kk >= SYMTSZ ){				cerror( "gummy structure" );				return(1);				}			if( kk == i ) return( 1 );			switch( stab[kk].stype ){			case STRTY:			case UNIONTY:				if( type == STRTY ) continue;  /* no recursive looking for strs */				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */					werror(#ifndef FLEXNAMES					"illegal member use: perhaps %.8s.%.8s?",#else					"illegal member use: perhaps %s.%s?",#endif					stab[kk].sname, stab[i].sname );					return(1);					}				}			}		}	return( 0 );	}conval( p, o, q ) register NODE *p, *q; {	/* apply the op o to the lval part of p; if binary, rhs is val */	int i, u;	CONSZ val;	val = q->tn.lval;	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);	if( q->tn.rval != NONAME && o!=PLUS ) return(0);	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);	switch( o ){	case PLUS:		p->tn.lval += val;		if( p->tn.rval == NONAME ){			p->tn.rval = q->tn.rval;			p->in.type = q->in.type;			}		break;	case MINUS:		p->tn.lval -= val;		break;	case MUL:		p->tn.lval *= val;		break;	case DIV:		if( val == 0 ) uerror( "division by 0" );		else p->tn.lval /= val;		break;	case MOD:		if( val == 0 ) uerror( "division by 0" );		else p->tn.lval %= val;		break;	case AND:		p->tn.lval &= val;		break;	case OR:		p->tn.lval |= val;		break;	case ER:		p->tn.lval ^=  val;		break;	case LS:		i = val;		p->tn.lval = p->tn.lval << i;		break;	case RS:		i = val;		p->tn.lval = p->tn.lval >> i;		break;	case UNARY MINUS:		p->tn.lval = - p->tn.lval;		break;	case COMPL:		p->tn.lval = ~p->tn.lval;		break;	case NOT:		p->tn.lval = !p->tn.lval;		break;	case LT:		p->tn.lval = p->tn.lval < val;		break;	case LE:		p->tn.lval = p->tn.lval <= val;		break;	case GT:		p->tn.lval = p->tn.lval > val;		break;	case GE:		p->tn.lval = p->tn.lval >= val;		break;	case ULT:		p->tn.lval = (p->tn.lval-val)<0;		break;	case ULE:		p->tn.lval = (p->tn.lval-val)<=0;		break;	case UGE:		p->tn.lval = (p->tn.lval-val)>=0;		break;	case UGT:		p->tn.lval = (p->tn.lval-val)>0;		break;	case EQ:		p->tn.lval = p->tn.lval == val;		break;	case NE:		p->tn.lval = p->tn.lval != val;		break;	default:		return(0);		}	return(1);	}chkpun(p) register NODE *p; {	/* checks p for the existance of a pun */	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */	/* one case is when enumerations are used: this applies only to lint */	/* in the other case, one operand is a pointer, the other integer type */	/* we check that this integer is in fact a constant zero... */	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */	/* this falls out, because the LHS is never 0 */	register NODE *q;	register t1, t2;	register d1, d2;	t1 = p->in.left->in.type;	t2 = p->in.right->in.type;	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) {			uerror( "illegal comparison of enums" );			return;			}		if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return;		werror( "enumeration type clash, operator %s", opst[p->in.op] );		return;		}	if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;	else q = p->in.left;	if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){		if( q->in.op != ICON || q->tn.lval != 0 ){			werror( "illegal combination of pointer and integer, op %s",				opst[p->in.op] );			}		}	else {		d1 = p->in.left->fn.cdim;		d2 = p->in.right->fn.cdim;		for( ;; ){			if( t1 == t2 ) {;				if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {					werror( "illegal structure pointer combination" );					}				return;				}			if( ISARY(t1) || ISPTR(t1) ){				if( !ISARY(t2) && !ISPTR(t2) ) break;				if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){					werror( "illegal array size combination" );					return;					}				if( ISARY(t1) ) ++d1;				if( ISARY(t2) ) ++d2;				}			else break;			t1 = DECREF(t1);			t2 = DECREF(t2);			}		werror( "illegal pointer combination" );		}	}NODE *stref( p ) register NODE *p; {	TWORD t;	int d, s, dsc, align;	OFFSZ off;	register struct symtab *q;	/* make p->x */	/* this is also used to reference automatic variables */	q = &stab[p->in.right->tn.rval];	p->in.right->in.op = FREE;	p->in.op = FREE;	p = pconvert( p->in.left );	/* make p look like ptr to x */	if( !ISPTR(p->in.type)){		p->in.type = PTR+UNIONTY;		}	t = INCREF( q->stype );	d = q->dimoff;	s = q->sizoff;	p = makety( p, t, d, s );	/* compute the offset to be added */	off = q->offset;	dsc = q->sclass;	if( dsc & FIELD ) {  /* normalize offset */		align = ALINT;		s = INT;		off = (off/align)*align;		}	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );	p = buildtree( UNARY MUL, p, NIL );	/* if field, build field info */	if( dsc & FIELD ){		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );		}	return( clocal(p) );	}notlval(p) register NODE *p; {	/* return 0 if p an lvalue, 1 otherwise */	again:	switch( p->in.op ){	case FLD:		p = p->in.left;		goto again;	case UNARY MUL:		/* fix the &(a=b) bug, given that a and b are structures */		if( p->in.left->in.op == STASG ) return( 1 );		/* and the f().a bug, given that f returns a structure */		if( p->in.left->in.op == UNARY STCALL ||		    p->in.left->in.op == STCALL ) return( 1 );	case NAME:	case OREG:		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);	case REG:		return(0);	default:		return(1);		}	}NODE *bcon( i ){ /* make a constant node with value i */	register NODE *p;	p = block( ICON, NIL, NIL, INT, 0, INT );	p->tn.lval = i;	p->tn.rval = NONAME;	return( clocal(p) );	}NODE *bpsize(p) register NODE *p; {	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );	}OFFSZpsize( p ) NODE *p; {	/* p is a node of type pointer; psize returns the	   size of the thing pointed to */	if( !ISPTR(p->in.type) ){		uerror( "pointer required");		return( SZINT );		}	/* note: no pointers to fields */	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );	}NODE *convert( p, f )  register NODE *p; {	/*  convert an operand of p	    f is either CVTL or CVTR	    operand has type int, and is converted by the size of the other side	    */	register NODE *q, *r;	q = (f==CVTL)?p->in.left:p->in.right;	r = block( PMCONV,		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );	r = clocal(r);	if( f == CVTL )		p->in.left = r;	else		p->in.right = r;	return(p);	}econvert( p ) register NODE *p; {	/* change enums to ints, or appropriate types */	register TWORD ty;	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;		else ty = LONG;		ty = ctype( ty );		p->fn.csiz = ty;		MODTYPE(p->in.type,ty);		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;		}	}NODE *pconvert( p ) register NODE *p; {	/* if p should be changed into a pointer, do so */	if( ISARY( p->in.type) ){		p->in.type = DECREF( p->in.type );		++p->fn.cdim;		return( buildtree( UNARY AND, p, NIL ) );		}	if( ISFTN( p->in.type) )		return( buildtree( UNARY AND, p, NIL ) );	return( p );	}NODE *oconvert(p) register NODE *p; {	/* convert the result itself: used for pointer and unsigned */	switch(p->in.op) {	case LE:	case LT:	case GE:	case GT:		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);	case EQ:	case NE:		return( p );	case MINUS:		return(  clocal( block( PVCONV,			p, bpsize(p->in.left), INT, 0, INT ) ) );		}	cerror( "illegal oconvert: %d", p->in.op );	return(p);	}NODE *ptmatch(p)  register NODE *p; {	/* makes the operands of p agree; they are	   either pointers or integers, by this time */	/* with MINUS, the sizes must be the same */	/* with COLON, the types must be the same */	TWORD t1, t2, t;	int o, d2, d, s2, s;	o = p->in.op;	t = t1 = p->in.left->in.type;	t2 = p->in.right->in.type;	d = p->in.left->fn.cdim;	d2 = p->in.right->fn.cdim;	s = p->in.left->fn.csiz;	s2 = p->in.right->fn.csiz;	switch( o ){	case ASSIGN:	case RETURN:	case CAST:		{  break; }	case MINUS:		{  if( psize(p->in.left) != psize(p->in.right) ){			uerror( "illegal pointer subtraction");			}		   break;		   }	case COLON:		{  if( t1 != t2 ) uerror( "illegal types in :");		   break;		   }	default:  /* must work harder: relationals or comparisons */		if( !ISPTR(t1) ){			t = t2;			d = d2;			s = s2;			break;			}		if( !ISPTR(t2) ){			break;			}		/* both are pointers */		if( talign(t2,s2) < talign(t,s) ){			t = t2;			s = s2;			}		break;		}	p->in.left = makety( p->in.left, t, d, s );	p->in.right = makety( p->in.right, t, d, s );	if( o!=MINUS && !logop(o) ){		p->in.type = t;		p->fn.cdim = d;		p->fn.csiz = s;		}	return(clocal(p));	}int tdebug = 0;NODE *tymatch(p)  register NODE *p; {	/* satisfy the types of various arithmetic binary ops */	/* rules are:		if assignment, op, type of LHS		if any float or doubles, make double		if any longs, make long		otherwise, make int		if either operand is unsigned, the result is...	*/	register TWORD t1, t2, t, tu;	register o, u;	o = p->in.op;	t1 = p->in.left->in.type;	t2 = p->in.right->in.type;	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )		uerror("void type illegal in expression");	u = 0;	if( ISUNSIGNED(t1) ){		u = 1;		t1 = DEUNSIGN(t1);		}	if( ISUNSIGNED(t2) ){		u = 1;		t2 = DEUNSIGN(t2);		}	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;	if( t2 == CHAR || t2 == SHORT ) t2 = INT;	if( t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE;	else if( t1==LONG || t2==LONG ) t = LONG;	else t = INT;	if( asgop(o) ){		/*		 *  We use the right hand side to determine which operand		 *  must be converted.  This fixes the problem of		 *  (int op= real) where the real is getting converted where		 *  it should not. The ASSIGN is unchanged by this fix.  Only		 *  the op= is effected.		 */		if ( ( (dope[o]&ASGOPFLG) && o != CAST && o != RETURN) && 		     ( t == DOUBLE ) )			/* slr002 slr001 */

⌨️ 快捷键说明

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