📄 trees.c
字号:
l = block( STASG, l, r, t, d, s ); if( o == RETURN ){ p->in.op = FREE; p = l; break; } p->in.op = UNARY MUL; p->in.left = l; p->in.right = NIL; break; } case COLON: /* structure colon */ if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" ); break; case CALL: p->in.right = r = strargs( p->in.right ); case UNARY CALL: if( !ISPTR(l->in.type)) uerror("illegal function"); p->in.type = DECREF(l->in.type); if( !ISFTN(p->in.type)) uerror("illegal function"); p->in.type = DECREF( p->in.type ); p->fn.cdim = l->fn.cdim; p->fn.csiz = l->fn.csiz; if( l->in.op == UNARY AND && l->in.left->in.op == NAME && l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME && ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){ p->in.op += (FORTCALL-CALL); } if( p->in.type == STRTY || p->in.type == UNIONTY ){ /* function returning structure */ /* make function really return ptr to str., with * */ p->in.op += STCALL-CALL; p->in.type = INCREF( p->in.type ); p = buildtree( UNARY MUL, p, NIL ); } break; default: cerror( "other code %d", o ); } } if( actions & CVTO ) p = oconvert(p); p = clocal(p);# ifndef BUG1 if( bdebug ) fwalk( p, eprint, 0 );# endif return(p); }/* vdp012 report floating point exception. * If fpe_count is not less then 0 then * the floating point signal occured when * we were combining constants in buildtree * (see call to setjmp) */int fpe_count = -1;jmp_buf gotfpe;voidfpe() { if (fpe_count < 0) cerror("floating point exception"); ++fpe_count; longjmp(gotfpe, 1); }NODE *strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */ if( p->in.op == CM ){ p->in.left = strargs( p->in.left ); p->in.right = strargs( p->in.right ); return( p ); } /*RAP005 Catch use of functions that don't return values used as arguements. */ if ((p->in.op==UNARY CALL || p->in.op==CALL ) && p->in.type==UNDEF) uerror("void or undef used in value required context"); 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); } /* vdp Single (e.g. 34.56f ) * precision floating point constants are * cast to double (to eliminate convert code). */ else if( p->in.op == FCON ) p = makety(p, DOUBLE, 0, 0); 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 if (u) p->tn.lval /= (unsigned)val; else p->tn.lval /= val; break; case MOD: if( val == 0 ) uerror( "division by 0" ); else if (u) p->tn.lval %= (unsigned)val; 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; if (u) p->tn.lval = (unsigned)p->tn.lval << i; else p->tn.lval = p->tn.lval << i; break; case RS: i = val; if (u) p->tn.lval = (unsigned)p->tn.lval >> i; else 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 ); p->in.typattr = INCATTR(q->stypattr); /* 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); }#ifndef econverteconvert( 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; } }#endifNODE *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 ta, 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; ta = p->in.left->in.typattr; 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; } if (o == CAST) p->in.right->in.typattr = ta; 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; /* vdp009 - if floating point is not to be promoted * up to double (fflag) we check for that here */ if ((fflag) && (t1==DOUBLE || t2==DOUBLE)) t = DOUBLE; else if ((fflag) && (t1==FLOAT || t2==FLOAT)) t = FLOAT; else 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -