📄 trees.c
字号:
#ifndef lintstatic char *sccsid = "@(#)trees.c 4.3 ULTRIX 2/4/91";#endif lint/************************************************************************ * * * Copyright (c) 1985 - 1989 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * Modification History * * * 018 Jon Reeves, 10-May-1989 * Signal handler now returns void. * * 017 Jon Reeves, 03-May-1989 for Sid Maxwell * Clean up handling of void * in : expressions. * * 016 Jon Reeves, 11-Apr-1988 * Add ifndef econvert/endif so lint builds cleanly. * * 015 David L Ballenger, 22-Mar-1987 * Fix problem with SUN fixes added in 010 that caused the following: * if ((unsigned)char_variable <= 127) * to generate a signed comparison and branch rather than unsigned. * * 014 Lu Anne Van de Pas, 14-Aug-86 * Fixed bug with asgop; ie. if (int < (int= float * double / float)). * The intermediate results of the compuations are used again for the * comparsion so we can't optimize it. * * 013 Victoria Holt, 14-Apr-86 * Bug fix for constant pointers. * * 012 Lu Anne Van de Pas, 1-April-86 * Added floating point exception handler from 4.3, to report * floating point overflow and underflow faults when folding constants * together. * * David L Ballenger, 18-Mar-1986 * 011 Add fix for casts of enumeration variables which was broken by * the SUN fixes. * * David L Ballenger, 16-Mar-1986 * 010 Add bug fixes from SUN for NFS code. * * Lu Anne Van de Pas, 02-Mar-86 * 009 Added support for single precision arithmetic to be done in * singleprec if fflag is set * * Victoria Holt, 26-Feb-86 * 008 Added support for const and volatile. * * David L Ballenger, 28-May-1985 * 007 Fix bug that prevented assignments between variables defined as * void (*)(), i.e. pointer to function returning void. * * Rich Phillips, 13-Sept-84 * 006- Back out of 003, see local.c for reason (in mod history) * * Rich Phillips, 21-Aug-84 * 005- Issue an error when functions that do not return a value are * used in a value required context. * * Rich Phillips, 01-Aug-84 * 004- Issue an error if a structure or union type was specified in a * condition, like "if (a)" where "a" is a union or structure. * * Rich Phillips, 20-July-84 * 003- Issue an error if unary & operator applies to a unary * with * NWASREG set. * * Stephen Reilly, 13-Feb-84 * 002- Fix a coding bug from ( 001 ). The problem was I thought asgop * only was true for assign type operations. Not true the RETURN * CAST are considered assign typea which causes conversion problems. * * Stephen Reilly, 20-Jan-84 * 001- Fix the problem with ( int op= real ). The bug was that the * real was converted to the int rather than the int being * converted to real. * ***********************************************************************/# include "mfile1"# include <setjmp.h> /* corrections when in violation of lint *//* some special actions, used in finding the type of nodes */# define NCVT 01# define PUN 02# define TYPL 04# define TYPR 010# define TYMATCH 040# define LVAL 0100# define CVTO 0200# define CVTL 0400# define CVTR 01000# define PTMATCH 02000# define OTHER 04000# define NCVTR 010000/* node conventions: NAME: rval>0 is stab index for external rval<0 is -inlabel number lval is offset in bits ICON: lval has the value rval has the STAB index, or - label number, if a name whose address is in the constant rval = NONAME means no name REG: rval is reg. identification cookie */int bdebug = 0;extern ddebug;extern fflag; /*vdp009*/ extern int adebug; extern int eprint();#ifndef BUG1/* vdp009 - adebug flag. Print out actions or conversions that * need to be done to the tree */ printact(t, acts) NODE *t; int acts;{ static struct actions { int a_bit; char *a_name; } actions[] = { { PUN, "PUN" }, { CVTL, "CVTL" }, { CVTR, "CVTR" }, { TYPL, "TYPL" }, { TYPR, "TYPR" }, { TYMATCH, "TYMATCH" }, { PTMATCH, "PTMATCH" }, { LVAL, "LVAL" }, { CVTO, "CVTO" }, { NCVT, "NCVT" }, { OTHER, "OTHER" }, { NCVTR, "NCVTR" }, { 0 } }; register struct actions *p; char *sep = " "; printf("actions"); for (p = actions; p->a_name; p++) if (p->a_bit & acts) { printf("%s%s", sep, p->a_name); sep = "|"; } if (!bdebug) { printf(" for:\n"); fwalk(t, eprint, 0); } else putchar('\n');}#endifNODE *buildtree( o, l, r ) register NODE *l, *r; { register NODE *p, *q; register actions; register opty; register struct symtab *sp; register NODE *lr, *ll; int i;# ifndef BUG1 if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );# endif opty = optype(o); /* check for constants */ if( opty == UTYPE && l->in.op == ICON ){ switch( o ){ case NOT: if( hflag ) werror( "constant argument to NOT" ); case UNARY MINUS: case COMPL: if( conval( l, o, l ) ) return(l); break; } } /* lvdp009 check for both Floating constant and double * constant; combine unary minus node and constant node */ else if( o==UNARY MINUS && l->in.op==FCON ){ l->fpn.fval = -l->fpn.fval; return(l); } else if( o==UNARY MINUS && l->in.op==DCON ){ l->dpn.dval = -l->dpn.dval; return(l); } /* lvdp009 end */ else if( o==QUEST && l->in.op==ICON ) { l->in.op = FREE; r->in.op = FREE; if( l->tn.lval ){ tfree( r->in.right ); return( r->in.left ); } else { tfree( r->in.left ); return( r->in.right ); } } else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn; else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){ switch( o ){ case ULT: case UGT: case ULE: case UGE: case LT: case GT: case LE: case GE: case EQ: case NE: case ANDAND: case OROR: case CBRANCH: ccwarn: if( hflag ) werror( "constant in conditional context" ); case PLUS: case MINUS: case MUL: case DIV: case MOD: case AND: case OR: case ER: case LS: case RS: if( conval( l, o, r ) ) { r->in.op = FREE; return(l); } break; } } /*vdp009 add test for double constant*/ else if( opty == BITYPE && (l->in.op==FCON || l->in.op==DCON || l->in.op==ICON) && (r->in.op==FCON || r->in.op==DCON || r->in.op==ICON) ){ if (o == PLUS || o == MINUS || o == MUL || o == DIV) { /* vdp012 set up to handle floating * point exception */ extern int fpe_count; extern jmp_buf gotfpe; fpe_count = 0; if (setjmp(gotfpe)) goto treatfpe; if( l->in.op == ICON ) l->dpn.dval = l->tn.lval; else if (l->in.op == FCON ) /*vdp009 */ l->dpn.dval = l->fpn.fval; if( r->in.op == ICON ) r->dpn.dval = r->tn.lval; else if (r->in.op == FCON ) /*vdp009*/ r->dpn.dval = r->fpn.fval; switch(o){ /*vdp009 conbine constants together*/ case PLUS: l->dpn.dval += r->dpn.dval; break; case MINUS: l->dpn.dval -= r->dpn.dval; break; case MUL: l->dpn.dval *= r->dpn.dval; break; case DIV: if( r->dpn.dval == 0 ) uerror( "division by 0." ); else l->dpn.dval /= r->dpn.dval; break; } treatfpe: if (fpe_count > 0) { uerror("floating point exception in constant expression"); l->dpn.dval = 1.0; /* Fairly harmless */ } fpe_count = -1; l->in.op = DCON; l->in.type = l->fn.csiz = DOUBLE; r->in.op = FREE; return (l); } } if (asgop(o) && o != CAST) { if (ISRODATA(l->in.typattr, l->in.type)) { uerror("cannot assign to a const"); } else { if (ISPTR(l->in.type) && ISPTR(r->in.type) && ISCONST(r->in.typattr)) { uerror("cannot assign const address to non-const pointer"); } } } if (o == INITASSIGN) o = ASSIGN; /* its real; we must make a new node */ p = block( o, l, r, INT, 0, INT ); actions = opact(p);#ifndef BUG1 if (adebug) /*vdp009*/ printact(p, actions);#endif if( actions&LVAL ){ /* check left descendent */ if( notlval(p->in.left) ) { uerror( "illegal lhs of assignment operator" ); } } if( actions & NCVTR ){ p->in.left = pconvert( p->in.left ); } else if( !(actions & NCVT ) ){ switch( opty ){ case BITYPE: p->in.right = pconvert( p->in.right ); case UTYPE: p->in.left = pconvert( p->in.left ); } } if( (actions&PUN) && (o!=CAST||cflag) ){ chkpun(p); } if( actions & (TYPL|TYPR) ){ /* make type equal to the left (TYPL) or make type equal to the right (TYPR) */ q = (actions&TYPL) ? p->in.left : p->in.right; p->in.type = q->in.type; p->fn.cdim = q->fn.cdim; p->fn.csiz = q->fn.csiz; } if( actions & CVTL ) p = convert( p, CVTL ); if( actions & CVTR ) p = convert( p, CVTR ); if( actions & TYMATCH ) p = tymatch(p); if( actions & PTMATCH ) p = ptmatch(p); if( actions & OTHER ){ l = p->in.left; r = p->in.right; switch(o){ case NAME: sp = &stab[idname]; if( sp->stype == UNDEF ){#ifndef FLEXNAMES uerror( "%.8s undefined", sp->sname );#else uerror( "%s undefined", sp->sname );#endif /* make p look reasonable */ p->in.type = p->fn.cdim = p->fn.csiz = INT; p->in.typattr = 0; p->tn.rval = idname; p->tn.lval = 0; defid( p, SNULL ); break; } p->in.type = sp->stype; p->in.typattr = sp->stypattr; p->fn.cdim = sp->dimoff; p->fn.csiz = sp->sizoff; p->tn.lval = 0; p->tn.rval = idname; /* special case: MOETY is really an ICON... */ if( p->in.type == MOETY ){ p->tn.rval = NONAME; p->tn.lval = sp->offset; p->fn.cdim = 0; p->in.type = ENUMTY; p->in.op = ICON; } break; case ICON: p->in.type = INT; p->fn.cdim = 0; p->fn.csiz = INT; break; case STRING: p->in.op = NAME; p->in.type = CHAR+ARY; p->tn.lval = 0; p->tn.rval = NOLAB; p->fn.cdim = curdim; p->fn.csiz = CHAR; break; /* vdp009 - distinguish between Floating constant and * double constant */ case FCON: p->tn.lval = 0; p->tn.rval = 0; p->in.type = FLOAT; p->fn.cdim = 0; p->fn.csiz = FLOAT; break; case DCON: p->tn.lval = 0; p->tn.rval = 0; p->in.type = DOUBLE; p->fn.cdim = 0; p->fn.csiz = DOUBLE; break; case STREF: /* p->x turned into *(p+offset) */ /* rhs must be a name; check correctness */ i = r->tn.rval; if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){ uerror( "member of structure or union required" ); }else /* if this name is non-unique, find right one */ if( stab[i].sflags & SNONUNIQ && (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) && (l->fn.csiz +1) >= 0 ){ /* nonunique name && structure defined */ char * memnam, * tabnam; register k; int j; int memi; j=dimtab[l->fn.csiz+1]; for( ; (memi=dimtab[j]) >= 0; ++j ){ tabnam = stab[memi].sname; memnam = stab[i].sname;# ifndef BUG1 if( ddebug>1 ){#ifndef FLEXNAMES printf("member %.8s==%.8s?\n",#else printf("member %s==%s?\n",#endif memnam, tabnam); }# endif if( stab[memi].sflags & SNONUNIQ ){#ifndef FLEXNAMES for( k=0; k<NCHNAM; ++k ){ if(*memnam++!=*tabnam) goto next; if(!*tabnam++) break; }#else if (memnam != tabnam) goto next;#endif r->tn.rval = i = memi; break; } next: continue; } if( memi < 0 )#ifndef FLEXNAMES uerror("illegal member use: %.8s",#else uerror("illegal member use: %s",#endif stab[i].sname); } else { register j; if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){ if( stab[i].sflags & SNONUNIQ ){ uerror( "nonunique name demands struct/union or struct/union pointer" ); } else werror( "struct/union or struct/union pointer required" ); } else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" ); else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){#ifndef FLEXNAMES werror( "illegal member use: %.8s", stab[i].sname );#else werror( "illegal member use: %s", stab[i].sname );#endif } } p = stref( p ); p->in.typattr = stab[r->tn.rval].stypattr; break; case UNARY MUL: if( l->in.op == UNARY AND ){ p->in.op = l->in.op = FREE; p = l->in.left; } if( !ISPTR(l->in.type))uerror("illegal indirection"); p->in.type = DECREF(l->in.type); p->in.typattr = DECATTR(l->in.typattr); p->fn.cdim = l->fn.cdim; p->fn.csiz = l->fn.csiz; break; case UNARY AND: switch( l->in.op ){ case UNARY MUL: p->in.op = l->in.op = FREE; p = l->in.left; case NAME: p->in.type = INCREF( l->in.type ); p->in.typattr = INCATTR(l->in.typattr); p->fn.cdim = l->fn.cdim; p->fn.csiz = l->fn.csiz; break; case COMOP: lr = buildtree( UNARY AND, l->in.right, NIL ); p->in.op = l->in.op = FREE; p = buildtree( COMOP, l->in.left, lr ); break; case QUEST: lr = buildtree( UNARY AND, l->in.right->in.right, NIL ); ll = buildtree( UNARY AND, l->in.right->in.left, NIL ); p->in.op = l->in.op = l->in.right->in.op = FREE; p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) ); break;# ifdef ADDROREG case OREG: /* OREG was built in clocal() * for an auto or formal parameter * now its address is being taken * local code must unwind it * back to PLUS/MINUS REG ICON * according to local conventions */ { extern NODE * addroreg(); p->in.op = FREE; p = addroreg( l ); } break;# endif default: uerror( "unacceptable operand of &" ); break; } break; case LS: case RS: case ASG LS: case ASG RS: if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT) p->in.right = makety(p->in.right, INT, 0, INT ); break; case RETURN: case ASSIGN: case CAST: /* structure assignment */ /* take the addresses of the two sides; then make an /* operator using STASG and /* the addresses of left and right */ { register TWORD t; register d, s; if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" ); r = buildtree( UNARY AND, r, NIL ); t = r->in.type; d = r->fn.cdim; s = r->fn.csiz;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -