# 2.11BSD#431 - /usr/src/lib/mip/trees.c

##### Functions

    bcon              X
    block             X
    bpsize            X
    buildtree         X
    chkpun            X
    chkstr            X
    conval            X
    convert           X
    doszof            X
    ecomp             X
    econvert          X
    eprint            X
    fixargs           X
    fpe               X
    icons             X
    makety            X
    moditype          X
    notlval           X
    oconvert          X
    opact             X
    p2tree            X
    pconvert          X
    printact          X
    prtdcon           X
    prtree            X
    psize             X
    ptmatch           X
    stref             X
    tymatch           X

##### Variables

    adebug            X
    bdebug            X
    edebug            X
    fpe_count         X
    gotfpe            X
    tdebug            X

##### Macros

    CVTL              X
    CVTO              X
    CVTR              X
    LVAL              X
    MDBI              X
    MENU              X
    MINT              X
    MPTI              X
    MPTR              X
    MSTR              X
    MVOID             X
    NCVT              X
    NCVTR             X
    OTHER             X
    PTMATCH           X
    PUN               X
    TYMATCH           X
    TYPL              X
    TYPR              X

##### struct's

    actions           X

       1: #if !defined(lint) && defined(DOSCCS)
       2: static char *sccsid ="@(#)trees.c	4.10.1 (2.11BSD GTE) 1/17/95";
       3: #endif
       4:
       5: # include "pass1.h"
       6:
       7: # include <setjmp.h>
       8:
       9: int bdebug = 0;
      10: int adebug = 0;
      11: extern ddebug;
      12: extern eprint();
      13:
      14:         /* corrections when in violation of lint */
      15:
      16: /*	some special actions, used in finding the type of nodes */
      17: # define NCVT 01
      18: # define PUN 02
      19: # define TYPL 04
      20: # define TYPR 010
      21: # define TYMATCH 040
      22: # define LVAL 0100
      23: # define CVTO 0200
      24: # define CVTL 0400
      25: # define CVTR 01000
      26: # define PTMATCH 02000
      27: # define OTHER 04000
      28: # define NCVTR 010000
      29:
      30: #ifndef BUG1
      31: printact(t, acts)
      32:     NODE *t;
      33:     int acts;
      34: {
      35:     static struct actions {
      36:         int a_bit;
      37:         char    *a_name;
      38:     } actions[] = {
      39:         { PUN,      "PUN" },
      40:         { CVTL,     "CVTL" },
      41:         { CVTR,     "CVTR" },
      42:         { TYPL,     "TYPL" },
      43:         { TYPR,     "TYPR" },
      44:         { TYMATCH,  "TYMATCH" },
      45:         { PTMATCH,  "PTMATCH" },
      46:         { LVAL,     "LVAL" },
      47:         { CVTO,     "CVTO" },
      48:         { NCVT,     "NCVT" },
      49:         { OTHER,    "OTHER" },
      50:         { NCVTR,    "NCVTR" },
      51:         { 0 }
      52:     };
      53:     register struct actions *p;
      54:     char *sep = " ";
      55:
      56:     printf("actions");
      57:     for (p = actions; p->a_name; p++)
      58:         if (p->a_bit & acts) {
      59:             printf("%s%s", sep, p->a_name);
      60:             sep = "|";
      61:         }
      62:     if (!bdebug) {
      63:         printf(" for:\n");
      64:         fwalk(t, eprint, 0);
      65:     } else
      66:         putchar('\n');
      67: }
      68: #endif
      69:
      70: /* node conventions:
      71:
      72: 	NAME:	rval>0 is stab index for external
      73: 		rval<0 is -inlabel number
      74: 		lval is offset in bits
      75: 	ICON:	lval has the value
      76: 		rval has the STAB index, or - label number,
      77: 			if a name whose address is in the constant
      78: 		rval = NONAME means no name
      79: 	REG:	rval is reg. identification cookie
      80:
      81: 	*/
      82:
      83: NODE *
      84: buildtree( o, l, r ) register NODE *l, *r; {
      85:     register NODE *p, *q;
      86:     register actions;
      87:     register opty;
      88:     register struct symtab *sp;
      89:     register NODE *lr, *ll;
      90:     NODE *fixargs();
      91:     int i;
      92:
      93: # ifndef BUG1
      94:     if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
      95: # endif
      96:     opty = optype(o);
      97:
      98:     /* check for constants */
      99:
     100:     if( opty == UTYPE && l->in.op == ICON ){
     101:
     102:         switch( o ){
     103:
     104:         case NOT:
     105:             if( hflag ) werror("constant argument to NOT" );
     106:         case UNARY MINUS:
     107:         case COMPL:
     108:             if( conval( l, o, l ) ) return(l);
     109:             break;
     110:
     111:             }
     112:         }
     113:
     114:     else if( o==UNARY MINUS && l->in.op==FCON ){
     115:         l->fpn.fval = -l->fpn.fval;
     116:         return(l);
     117:         }
     118:
     119:     else if( o==UNARY MINUS && l->in.op==DCON ){
     120:         l->dpn.dval = -l->dpn.dval;
     121:         return(l);
     122:         }
     123:
     124:     else if( o==QUEST && l->in.op==ICON ) {
     125:         l->in.op = FREE;
     126:         r->in.op = FREE;
     127:         if( l->tn.lval ){
     128:             tfree( r->in.right );
     129:             return( r->in.left );
     130:             }
     131:         else {
     132:             tfree( r->in.left );
     133:             return( r->in.right );
     134:             }
     135:         }
     136:
     137:     else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
     138:
     139:     else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
     140:
     141:         switch( o ){
     142:
     143:         case ULT:
     144:         case UGT:
     145:         case ULE:
     146:         case UGE:
     147:         case LT:
     148:         case GT:
     149:         case LE:
     150:         case GE:
     151:         case EQ:
     152:         case NE:
     153:         case ANDAND:
     154:         case OROR:
     155:         case CBRANCH:
     156:
     157:         ccwarn:
     158:             if( hflag ) werror("constant in conditional context" );
     159:
     160:         case PLUS:
     161:         case MINUS:
     162:         case MUL:
     163:         case DIV:
     164:         case MOD:
     165:         case AND:
     166:         case OR:
     167:         case ER:
     168:         case LS:
     169:         case RS:
     170:             if( conval( l, o, r ) ) {
     171:                 r->in.op = FREE;
     172:                 return(l);
     173:                 }
     174:             break;
     175:             }
     176:         }
     177:     else if (opty == BITYPE &&
     178:         (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
     179:         (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
     180:             if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
     181:                 extern int fpe_count;
     182:                 extern jmp_buf gotfpe;
     183:
     184:                 fpe_count = 0;
     185:                 if (setjmp(gotfpe))
     186:                     goto treatfpe;
     187:                 if (l->in.op == ICON)
     188:                     l->dpn.dval = l->tn.lval;
     189:                 else if (l->in.op == FCON)
     190:                     l->dpn.dval = l->fpn.fval;
     191:                 if (r->in.op == ICON)
     192:                     r->dpn.dval = r->tn.lval;
     193:                 else if (r->in.op == FCON)
     194:                     r->dpn.dval = r->fpn.fval;
     195:                 switch (o) {
     196:
     197:                 case PLUS:
     198:                     l->dpn.dval += r->dpn.dval;
     199:                     break;
     200:
     201:                 case MINUS:
     202:                     l->dpn.dval -= r->dpn.dval;
     203:                     break;
     204:
     205:                 case MUL:
     206:                     l->dpn.dval *= r->dpn.dval;
     207:                     break;
     208:
     209:                 case DIV:
     210:                     if (r->dpn.dval == 0)
     211:                         uerror("division by 0.");
     212:                     else
     213:                         l->dpn.dval /= r->dpn.dval;
     214:                     break;
     215:                     }
     216:             treatfpe:
     217:                 if (fpe_count > 0) {
     218:                     uerror("floating point exception in constant expression");
     219:                     l->dpn.dval = 1.0; /* Fairly harmless */
     220:                     }
     221:                 fpe_count = -1;
     222:                 l->in.op = DCON;
     223:                 l->in.type = l->fn.csiz = DOUBLE;
     224:                 r->in.op = FREE;
     225:                 return (l);
     226:             }
     227:         }
     228:
     229:     /* it's real; we must make a new node */
     230:
     231:     p = block( o, l, r, INT, 0, INT );
     232:
     233:     actions = opact(p);
     234: #ifndef BUG1
     235:     if (adebug)
     236:         printact(p, actions);
     237: #endif
     238:
     239:     if( actions&LVAL ){ /* check left descendent */
     240:         if( notlval(p->in.left) ) {
     241:             uerror("illegal lhs of assignment operator" );
     242:             }
     243:         }
     244:
     245:     if( actions & NCVTR ){
     246:         p->in.left = pconvert( p->in.left );
     247:         }
     248:     else if( !(actions & NCVT ) ){
     249:         switch( opty ){
     250:
     251:         case BITYPE:
     252:             p->in.right = pconvert( p->in.right );
     253:         case UTYPE:
     254:             p->in.left = pconvert( p->in.left );
     255:
     256:             }
     257:         }
     258:
     259:     if( (actions&PUN) && (o!=CAST||cflag) ){
     260:         chkpun(p);
     261:         }
     262:
     263:     if( actions & (TYPL|TYPR) ){
     264:
     265:         q = (actions&TYPL) ? p->in.left : p->in.right;
     266:
     267:         p->in.type = q->in.type;
     268:         p->fn.cdim = q->fn.cdim;
     269:         p->fn.csiz = q->fn.csiz;
     270:         }
     271:
     272:     if( actions & CVTL ) p = convert( p, CVTL );
     273:     if( actions & CVTR ) p = convert( p, CVTR );
     274:     if( actions & TYMATCH ) p = tymatch(p);
     275:     if( actions & PTMATCH ) p = ptmatch(p);
     276:
     277:     if( actions & OTHER ){
     278:         l = p->in.left;
     279:         r = p->in.right;
     280:
     281:         switch(o){
     282:
     283:         case NAME:
     284:             sp = &stab[idname];
     285:             if( sp->stype == UNDEF ){
     286: #ifndef FLEXNAMES
     287:                 uerror("%.8s undefined", sp->sname );
     288: #else
     289:                 uerror("%s undefined", sp->sname );
     290: #endif
     291:                 /* make p look reasonable */
     292:                 p->in.type = p->fn.cdim = p->fn.csiz = INT;
     293:                 p->tn.rval = idname;
     294:                 p->tn.lval = 0;
     295:                 defid( p, SNULL );
     296:                 break;
     297:                 }
     298:             p->in.type = sp->stype;
     299:             p->fn.cdim = sp->dimoff;
     300:             p->fn.csiz = sp->sizoff;
     301:             p->tn.lval = 0;
     302:             p->tn.rval = idname;
     303:             /* special case: MOETY is really an ICON... */
     304:             if( p->in.type == MOETY ){
     305:                 p->tn.rval = NONAME;
     306:                 p->tn.lval = sp->offset;
     307:                 p->fn.cdim = 0;
     308:                 p->in.type = ENUMTY;
     309:                 p->in.op = ICON;
     310:                 }
     311:             break;
     312:
     313:         case ICON:
     314:             p->in.type = INT;
     315:             p->fn.cdim = 0;
     316:             p->fn.csiz = INT;
     317:             break;
     318:
     319:         case STRING:
     320:             p->in.op = NAME;
     321:             p->in.type = CHAR+ARY;
     322:             p->tn.lval = 0;
     323:             p->tn.rval = NOLAB;
     324:             p->fn.cdim = curdim;
     325:             p->fn.csiz = CHAR;
     326:             break;
     327:
     328:         case FCON:
     329:             p->tn.lval = 0;
     330:             p->tn.rval = 0;
     331:             p->in.type = FLOAT;
     332:             p->fn.cdim = 0;
     333:             p->fn.csiz = FLOAT;
     334:             break;
     335:
     336:         case DCON:
     337:             p->tn.lval = 0;
     338:             p->tn.rval = 0;
     339:             p->in.type = DOUBLE;
     340:             p->fn.cdim = 0;
     341:             p->fn.csiz = DOUBLE;
     342:             break;
     343:
     344:         case STREF:
     345:             /* p->x turned into *(p+offset) */
     346:             /* rhs must be a name; check correctness */
     347:
     348:             i = r->tn.rval;
     349:             if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
     350:                 uerror("member of structure or union required" );
     351:                 }else
     352:             /* if this name is non-unique, find right one */
     353:             if( stab[i].sflags & SNONUNIQ &&
     354:                 (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
     355:                 (l->fn.csiz +1) >= 0 ){
     356:                 /* nonunique name && structure defined */
     357:                 char * memnam, * tabnam;
     358:                 register k;
     359:                 int j;
     360:                 int memi;
     361:                 j=dimtab[l->fn.csiz+1];
     362:                 for( ; (memi=dimtab[j]) >= 0; ++j ){
     363:                     tabnam = stab[memi].sname;
     364:                     memnam = stab[i].sname;
     365: # ifndef BUG1
     366:                     if( ddebug>1 ){
     367: #ifndef FLEXNAMES
     368:                         printf("member %.8s==%.8s?\n",
     369: #else
     370:                         printf("member %s==%s?\n",
     371: #endif
     372:                             memnam, tabnam);
     373:                         }
     374: # endif
     375:                     if( stab[memi].sflags & SNONUNIQ ){
     376: #ifndef FLEXNAMES
     377:                         for( k=0; k<NCHNAM; ++k ){
     378:                             if(*memnam++!=*tabnam)
     379:                                 goto next;
     380:                             if(!*tabnam++) break;
     381:                             }
     382: #else
     383:                         if (memnam != tabnam)
     384:                             goto next;
     385: #endif
     386:                         r->tn.rval = i = memi;
     387:                         break;
     388:                         }
     389:                     next: continue;
     390:                     }
     391:                 if( memi < 0 )
     392: #ifndef FLEXNAMES
     393:                     uerror("illegal member use: %.8s",
     394: #else
     395:                     uerror("illegal member use: %s",
     396: #endif
     397:                         stab[i].sname);
     398:                 }
     399:             else {
     400:                 register j;
     401:                 if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
     402:                     if( stab[i].sflags & SNONUNIQ ){
     403:                         uerror("nonunique name demands struct/union or struct/union pointer" );
     404:                         }
     405:                     else werror("struct/union or struct/union pointer required" );
     406:                     }
     407:                 else if( (j=l->fn.csiz+1)<0 ) cerror("undefined structure or union" );
     408:                 else if( !chkstr( i, (int)dimtab[j], DECREF(l->in.type) ) ){
     409: #ifndef FLEXNAMES
     410:                     werror("illegal member use: %.8s", stab[i].sname );
     411: #else
     412:                     werror("illegal member use: %s", stab[i].sname );
     413: #endif
     414:                     }
     415:                 }
     416:
     417:             p = stref( p );
     418:             break;
     419:
     420:         case UNARY MUL:
     421:             if( l->in.op == UNARY AND ){
     422:                 p->in.op = l->in.op = FREE;
     423:                 p = l->in.left;
     424:                 }
     425:             if( !ISPTR(l->in.type))uerror("illegal indirection");
     426:             p->in.type = DECREF(l->in.type);
     427:             p->fn.cdim = l->fn.cdim;
     428:             p->fn.csiz = l->fn.csiz;
     429:             break;
     430:
     431:         case UNARY AND:
     432:             switch( l->in.op ){
     433:
     434:             case UNARY MUL:
     435:                 p->in.op = l->in.op = FREE;
     436:                 p = l->in.left;
     437:             case NAME:
     438:                 p->in.type = INCREF( l->in.type );
     439:                 p->fn.cdim = l->fn.cdim;
     440:                 p->fn.csiz = l->fn.csiz;
     441:                 break;
     442:
     443:             case COMOP:
     444:                 lr = buildtree( UNARY AND, l->in.right, NIL );
     445:                 p->in.op = l->in.op = FREE;
     446:                 p = buildtree( COMOP, l->in.left, lr );
     447:                 break;
     448:
     449:             case QUEST:
     450:                 lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
     451:                 ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
     452:                 p->in.op = l->in.op = l->in.right->in.op = FREE;
     453:                 p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
     454:                 break;
     455:
     456: # ifdef ADDROREG
     457:             case OREG:
     458:                 /* OREG was built in clocal()
     459: 				 * for an auto or formal parameter
     460: 				 * now its address is being taken
     461: 				 * local code must unwind it
     462: 				 * back to PLUS/MINUS REG ICON
     463: 				 * according to local conventions
     464: 				 */
     465:                 {
     466:                 extern NODE * addroreg();
     467:                 p->in.op = FREE;
     468:                 p = addroreg( l );
     469:                 }
     470:                 break;
     471:
     472: # endif
     473:             default:
     474:                 uerror("unacceptable operand of &" );
     475:                 break;
     476:                 }
     477:             break;
     478:
     479:         case LS:
     480:         case RS:
     481:         case ASG LS:
     482:         case ASG RS:
     483:             if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
     484:                 p->in.right = makety(p->in.right, INT, 0, INT );
     485:             break;
     486:
     487:         case RETURN:
     488:         case ASSIGN:
     489:         case CAST:
     490:             /* structure assignment */
     491:             /* take the addresses of the two sides; then make an
     492: 			/* operator using STASG and
     493: 			/* the addresses of left and right */
     494:
     495:             {
     496:                 register TWORD t;
     497:                 register d, s;
     498:
     499:                 if( l->fn.csiz != r->fn.csiz ) uerror("assignment of different structures" );
     500:
     501:                 r = buildtree( UNARY AND, r, NIL );
     502:                 t = r->in.type;
     503:                 d = r->fn.cdim;
     504:                 s = r->fn.csiz;
     505:
     506:                 l = block( STASG, l, r, t, d, s );
     507:
     508:                 if( o == RETURN ){
     509:                     p->in.op = FREE;
     510:                     p = l;
     511:                     break;
     512:                     }
     513:
     514:                 p->in.op = UNARY MUL;
     515:                 p->in.left = l;
     516:                 p->in.right = NIL;
     517:                 break;
     518:                 }
     519:         case COLON:
     520:             /* structure colon */
     521:
     522:             if( l->fn.csiz != r->fn.csiz ) uerror("type clash in conditional" );
     523:             break;
     524:
     525:         case CALL:
     526:             p->in.right = r = fixargs( p->in.right );
     527:         case UNARY CALL:
     528:             if( !ISPTR(l->in.type)) uerror("illegal function");
     529:             p->in.type = DECREF(l->in.type);
     530:             if( !ISFTN(p->in.type)) uerror("illegal function");
     531:             p->in.type = DECREF( p->in.type );
     532:             p->fn.cdim = l->fn.cdim;
     533:             p->fn.csiz = l->fn.csiz;
     534:             if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
     535:                 l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
     536:                 ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
     537:                 p->in.op += (FORTCALL-CALL);
     538:                 }
     539:             if( p->in.type == STRTY || p->in.type == UNIONTY ){
     540:                 /* function returning structure */
     541:                 /*  make function really return ptr to str., with * */
     542:
     543:                 p->in.op += STCALL-CALL;
     544:                 p->in.type = INCREF( p->in.type );
     545:                 p = buildtree( UNARY MUL, p, NIL );
     546:
     547:                 }
     548:             break;
     549:
     550:         default:
     551:             cerror("other code %d", o );
     552:             }
     553:
     554:         }
     555:
     556:     if( actions & CVTO ) p = oconvert(p);
     557:     p = clocal(p);
     558:
     559: # ifndef BUG1
     560:     if( bdebug ) fwalk( p, eprint, 0 );
     561: # endif
     562:
     563:     return(p);
     564:
     565:     }
     566:
     567: int fpe_count = -1;
     568: jmp_buf gotfpe;
     569:
     570: fpe() {
     571:     if (fpe_count < 0)
     572:         cerror("floating point exception");
     573:     ++fpe_count;
     574:     longjmp(gotfpe, 1);
     575:     }
     576:
     577: /*
     578:  * Rewrite arguments in a function call.
     579:  * Structure arguments are massaged, single
     580:  * precision floating point constants are
     581:  * cast to double (to eliminate convert code).
     582:  */
     583: NODE *
     584: fixargs( p ) register NODE *p;  {
     585:     int o = p->in.op;
     586:
     587:     if( o == CM ){
     588:         p->in.left = fixargs( p->in.left );
     589:         p->in.right = fixargs( p->in.right );
     590:         return( p );
     591:         }
     592:
     593:     if( p->in.type == STRTY || p->in.type == UNIONTY ){
     594:         p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
     595:         p->in.left = buildtree( UNARY AND, p->in.left, NIL );
     596:         p = clocal(p);
     597:         }
     598:     else if( o == FCON )
     599:         p = makety(p, DOUBLE, 0, 0);
     600:     return( p );
     601:     }
     602:
     603: chkstr( i, j, type ) TWORD type; {
     604:     /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
     605:     /* i has been checked to contain a MOS or MOU */
     606:     /* j is the index in dimtab of the members... */
     607:     int k, kk;
     608:
     609:     extern int ddebug;
     610:
     611: # ifndef BUG1
     612: #ifndef FLEXNAMES
     613:     if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
     614: #else
     615:     if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
     616: #endif
     617: # endif
     618:     if( (k = j) < 0 ) uerror("undefined structure or union" );
     619:     else {
     620:         for( ; (kk = (int)dimtab[k] ) >= 0; ++k ){
     621:             if( kk >= SYMTSZ ){
     622:                 cerror("gummy structure" );
     623:                 return(1);
     624:                 }
     625:             if( kk == i ) return( 1 );
     626:             switch( stab[kk].stype ){
     627:
     628:             case STRTY:
     629:             case UNIONTY:
     630:                 if( type == STRTY ) continue;  /* no recursive looking for strs */
     631:                 if( hflag && chkstr( i, (int)dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
     632:                     if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
     633:                     werror(
     634: #ifndef FLEXNAMES
     635:                     "illegal member use: perhaps %.8s.%.8s?",
     636: #else
     637:                     "illegal member use: perhaps %s.%s?",
     638: #endif
     639:                     stab[kk].sname, stab[i].sname );
     640:                     return(1);
     641:                     }
     642:                 }
     643:             }
     644:         }
     645:     return( 0 );
     646:     }
     647:
     648: conval( p, o, q ) register NODE *p, *q; {
     649:     /* apply the op o to the lval part of p; if binary, rhs is val */
     650:     int i, u;
     651:     CONSZ val;
     652:
     653:     val = q->tn.lval;
     654:     u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
     655:     if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
     656:
     657:     if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
     658:     if( q->tn.rval != NONAME && o!=PLUS ) return(0);
     659:     if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
     660:
     661:     switch( o ){
     662:
     663:     case PLUS:
     664:         p->tn.lval += val;
     665:         if( p->tn.rval == NONAME ){
     666:             p->tn.rval = q->tn.rval;
     667:             p->in.type = q->in.type;
     668:             }
     669:         break;
     670:     case MINUS:
     671:         p->tn.lval -= val;
     672:         break;
     673:     case MUL:
     674:         p->tn.lval *= val;
     675:         break;
     676:     case DIV:
     677:         if( val == 0 ) uerror("division by 0" );
     678:         else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
     679:         else p->tn.lval /= val;
     680:         break;
     681:     case MOD:
     682:         if( val == 0 ) uerror("division by 0" );
     683:         else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
     684:         else p->tn.lval %= val;
     685:         break;
     686:     case AND:
     687:         p->tn.lval &= val;
     688:         break;
     689:     case OR:
     690:         p->tn.lval |= val;
     691:         break;
     692:     case ER:
     693:         p->tn.lval ^= val;
     694:         break;
     695:     case LS:
     696:         i = val;
     697:         p->tn.lval = p->tn.lval << i;
     698:         break;
     699:     case RS:
     700:         i = val;
     701:         if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
     702:         else p->tn.lval = p->tn.lval >> i;
     703:         break;
     704:
     705:     case UNARY MINUS:
     706:         p->tn.lval = - p->tn.lval;
     707:         break;
     708:     case COMPL:
     709:         p->tn.lval = ~p->tn.lval;
     710:         break;
     711:     case NOT:
     712:         p->tn.lval = !p->tn.lval;
     713:         break;
     714:     case LT:
     715:         p->tn.lval = p->tn.lval < val;
     716:         break;
     717:     case LE:
     718:         p->tn.lval = p->tn.lval <= val;
     719:         break;
     720:     case GT:
     721:         p->tn.lval = p->tn.lval > val;
     722:         break;
     723:     case GE:
     724:         p->tn.lval = p->tn.lval >= val;
     725:         break;
     726:     case ULT:
     727:         p->tn.lval = (p->tn.lval-val)<0;
     728:         break;
     729:     case ULE:
     730:         p->tn.lval = (p->tn.lval-val)<=0;
     731:         break;
     732:     case UGE:
     733:         p->tn.lval = (p->tn.lval-val)>=0;
     734:         break;
     735:     case UGT:
     736:         p->tn.lval = (p->tn.lval-val)>0;
     737:         break;
     738:     case EQ:
     739:         p->tn.lval = p->tn.lval == val;
     740:         break;
     741:     case NE:
     742:         p->tn.lval = p->tn.lval != val;
     743:         break;
     744:     default:
     745:         return(0);
     746:         }
     747:     return(1);
     748:     }
     749:
     750: chkpun(p) register NODE *p; {
     751:
     752:     /* checks p for the existance of a pun */
     753:
     754:     /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
     755:
     756:     /* one case is when enumerations are used: this applies only to lint */
     757:     /* in the other case, one operand is a pointer, the other integer type */
     758:     /* we check that this integer is in fact a constant zero... */
     759:
     760:     /* in the case of ASSIGN, any assignment of pointer to integer is illegal */
     761:     /* this falls out, because the LHS is never 0 */
     762:
     763:     register NODE *q;
     764:     register t1, t2;
     765:     register d1, d2;
     766:
     767:     t1 = p->in.left->in.type;
     768:     t2 = p->in.right->in.type;
     769:
     770:     if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
     771:         if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) {
     772:             uerror("illegal comparison of enums" );
     773:             return;
     774:             }
     775:         if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return;
     776:         werror("enumeration type clash, operator %s", opst[p->in.op] );
     777:         return;
     778:         }
     779:
     780:     if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;
     781:     else q = p->in.left;
     782:
     783:     if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){
     784:         if( q->in.op != ICON || q->tn.lval != 0 ){
     785:             werror("illegal combination of pointer and integer, op %s",
     786:                 opst[p->in.op] );
     787:             }
     788:         }
     789:     else {
     790:         d1 = p->in.left->fn.cdim;
     791:         d2 = p->in.right->fn.cdim;
     792:         for( ;; ){
     793:             if( t1 == t2 ) {;
     794:                 if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
     795:                     werror("illegal structure pointer combination" );
     796:                     }
     797:                 return;
     798:                 }
     799:             if( ISARY(t1) || ISPTR(t1) ){
     800:                 if( !ISARY(t2) && !ISPTR(t2) ) break;
     801:                 if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){
     802:                     werror("illegal array size combination" );
     803:                     return;
     804:                     }
     805:                 if( ISARY(t1) ) ++d1;
     806:                 if( ISARY(t2) ) ++d2;
     807:                 }
     808:             else break;
     809:             t1 = DECREF(t1);
     810:             t2 = DECREF(t2);
     811:             }
     812:         werror("illegal pointer combination" );
     813:         }
     814:
     815:     }
     816:
     817: NODE *
     818: stref( p ) register NODE *p; {
     819:
     820:     TWORD t;
     821:     int d, s, dsc, align;
     822:     OFFSZ off;
     823:     register struct symtab *q;
     824:
     825:     /* make p->x */
     826:     /* this is also used to reference automatic variables */
     827:
     828:     q = &stab[p->in.right->tn.rval];
     829:     p->in.right->in.op = FREE;
     830:     p->in.op = FREE;
     831:     p = pconvert( p->in.left );
     832:
     833:     /* make p look like ptr to x */
     834:
     835:     if( !ISPTR(p->in.type)){
     836:         p->in.type = PTR+UNIONTY;
     837:         }
     838:
     839:     t = INCREF( q->stype );
     840:     d = q->dimoff;
     841:     s = q->sizoff;
     842:
     843:     p = makety( p, t, d, s );
     844:
     845:     /* compute the offset to be added */
     846:
     847:     off = q->offset;
     848:     dsc = q->sclass;
     849:
     850:     if( dsc & FIELD ) {  /* normalize offset */
     851:         align = ALINT;
     852:         s = INT;
     853:         off = (off/align)*align;
     854:         }
     855:     if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
     856:
     857:     p = buildtree( UNARY MUL, p, NIL );
     858:
     859:     /* if field, build field info */
     860:
     861:     if( dsc & FIELD ){
     862:         p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
     863:         p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
     864:         }
     865:
     866:     return( clocal(p) );
     867:     }
     868:
     869: notlval(p) register NODE *p; {
     870:
     871:     /* return 0 if p an lvalue, 1 otherwise */
     872:
     873:     again:
     874:
     875:     switch( p->in.op ){
     876:
     877:     case FLD:
     878:         p = p->in.left;
     879:         goto again;
     880:
     881:     case UNARY MUL:
     882:         /* fix the &(a=b) bug, given that a and b are structures */
     883:         if( p->in.left->in.op == STASG ) return( 1 );
     884:         /* and the f().a bug, given that f returns a structure */
     885:         if( p->in.left->in.op == UNARY STCALL ||
     886:             p->in.left->in.op == STCALL ) return( 1 );
     887:     case NAME:
     888:     case OREG:
     889:         if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
     890:     case REG:
     891:         return(0);
     892:
     893:     default:
     894:         return(1);
     895:
     896:         }
     897:
     898:     }
     899:
     900: NODE *
     901: bcon( i ) int i;{ /* make a constant node with value i */
     902:     register NODE *p;
     903:
     904:     p = block( ICON, NIL, NIL, INT, 0, INT );
     905:     p->tn.lval = i;
     906:     p->tn.rval = NONAME;
     907:     return( clocal(p) );
     908:     }
     909:
     910: NODE *
     911: bpsize(p) register NODE *p; {
     912:     return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
     913:     }
     914:
     915: OFFSZ
     916: psize( p ) NODE *p; {
     917:     /* p is a node of type pointer; psize returns the
     918: 	   size of the thing pointed to */
     919:
     920:     if( !ISPTR(p->in.type) ){
     921:         uerror("pointer required");
     922:         return( SZINT );
     923:         }
     924:     /* note: no pointers to fields */
     925:     return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
     926:     }
     927:
     928: NODE *
     929: convert( p, f )  register NODE *p; {
     930:     /*  convert an operand of p
     931: 	    f is either CVTL or CVTR
     932: 	    operand has type int, and is converted by the size of the other side
     933: 	    */
     934:
     935:     register NODE *q, *r;
     936:
     937:     q = (f==CVTL)?p->in.left:p->in.right;
     938:
     939:     r = block( PMCONV,
     940:         q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
     941:     r = clocal(r);
     942:     if( f == CVTL )
     943:         p->in.left = r;
     944:     else
     945:         p->in.right = r;
     946:     return(p);
     947:
     948:     }
     949:
     950: #ifndef econvert
     951: econvert( p ) register NODE *p; {
     952:
     953:     /* change enums to ints, or appropriate types */
     954:
     955:     register TWORD ty;
     956:
     957:     if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
     958:         if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
     959:         else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
     960:         else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
     961:         else ty = LONG;
     962:         ty = ctype( ty );
     963:         p->fn.csiz = ty;
     964:         MODTYPE(p->in.type,ty);
     965:         if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
     966:         }
     967:     }
     968: #endif
     969:
     970: NODE *
     971: pconvert( p ) register NODE *p; {
     972:
     973:     /* if p should be changed into a pointer, do so */
     974:
     975:     if( ISARY( p->in.type) ){
     976:         p->in.type = DECREF( p->in.type );
     977:         ++p->fn.cdim;
     978:         return( buildtree( UNARY AND, p, NIL ) );
     979:         }
     980:     if( ISFTN( p->in.type) )
     981:         return( buildtree( UNARY AND, p, NIL ) );
     982:
     983:     return( p );
     984:     }
     985:
     986: NODE *
     987: oconvert(p) register NODE *p; {
     988:     /* convert the result itself: used for pointer and unsigned */
     989:
     990:     switch(p->in.op) {
     991:
     992:     case LE:
     993:     case LT:
     994:     case GE:
     995:     case GT:
     996:         if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
     997:     case EQ:
     998:     case NE:
     999:         return( p );
    1000:
    1001:     case MINUS:
    1002:         return(  clocal( block( PVCONV,
    1003:             p, bpsize(p->in.left), INT, 0, INT ) ) );
    1004:         }
    1005:
    1006:     cerror("illegal oconvert: %d", p->in.op );
    1007:
    1008:     return(p);
    1009:     }
    1010:
    1011: NODE *
    1012: ptmatch(p)  register NODE *p; {
    1013:
    1014:     /* makes the operands of p agree; they are
    1015: 	   either pointers or integers, by this time */
    1016:     /* with MINUS, the sizes must be the same */
    1017:     /* with COLON, the types must be the same */
    1018:
    1019:     TWORD t1, t2, t;
    1020:     int o, d2, d, s2, s;
    1021:
    1022:     o = p->in.op;
    1023:     t = t1 = p->in.left->in.type;
    1024:     t2 = p->in.right->in.type;
    1025:     d = p->in.left->fn.cdim;
    1026:     d2 = p->in.right->fn.cdim;
    1027:     s = p->in.left->fn.csiz;
    1028:     s2 = p->in.right->fn.csiz;
    1029:
    1030:     switch( o ){
    1031:
    1032:     case ASSIGN:
    1033:     case RETURN:
    1034:     case CAST:
    1035:         {  break; }
    1036:
    1037:     case MINUS:
    1038:         {  if( psize(p->in.left) != psize(p->in.right) ){
    1039:             uerror("illegal pointer subtraction");
    1040:             }
    1041:            break;
    1042:            }
    1043:     case COLON:
    1044:         {  if( t1 != t2 ) uerror("illegal types in :");
    1045:            break;
    1046:            }
    1047:     default:  /* must work harder: relationals or comparisons */
    1048:
    1049:         if( !ISPTR(t1) ){
    1050:             t = t2;
    1051:             d = d2;
    1052:             s = s2;
    1053:             break;
    1054:             }
    1055:         if( !ISPTR(t2) ){
    1056:             break;
    1057:             }
    1058:
    1059:         /* both are pointers */
    1060:         if( talign(t2,s2) < talign(t,s) ){
    1061:             t = t2;
    1062:             s = s2;
    1063:             }
    1064:         break;
    1065:         }
    1066:
    1067:     p->in.left = makety( p->in.left, t, d, s );
    1068:     p->in.right = makety( p->in.right, t, d, s );
    1069:     if( o!=MINUS && !logop(o) ){
    1070:
    1071:         p->in.type = t;
    1072:         p->fn.cdim = d;
    1073:         p->fn.csiz = s;
    1074:         }
    1075:
    1076:     return(clocal(p));
    1077:     }
    1078:
    1079: int tdebug = 0;
    1080:
    1081: NODE *
    1082: tymatch(p)  register NODE *p; {
    1083:
    1084:     /* satisfy the types of various arithmetic binary ops */
    1085:
    1086:     /* rules are:
    1087: 		if assignment, type of LHS
    1088: 		if any float or doubles, make double
    1089: 		if any longs, make long
    1090: 		otherwise, make int
    1091: 		if either operand is unsigned, the result is...
    1092: 	*/
    1093:
    1094:     register TWORD t1, t2, t, tu;
    1095:     register o, u;
    1096:
    1097:     o = p->in.op;
    1098:
    1099:     t1 = p->in.left->in.type;
    1100:     t2 = p->in.right->in.type;
    1101:     if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
    1102:         uerror("void type illegal in expression");
    1103:
    1104:     u = 0;
    1105:     if( ISUNSIGNED(t1) ){
    1106:         u = 1;
    1107:         t1 = DEUNSIGN(t1);
    1108:         }
    1109:     if( ISUNSIGNED(t2) ){
    1110:         u = 1;
    1111:         t2 = DEUNSIGN(t2);
    1112:         }
    1113:
    1114:     if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
    1115:     if( t2 == CHAR || t2 == SHORT ) t2 = INT;
    1116:
    1117: #ifdef SPRECC
    1118:     if( t1 == DOUBLE || t2 == DOUBLE )
    1119:         t = DOUBLE;
    1120:     else if( t1 == FLOAT || t2 == FLOAT )
    1121:         t = FLOAT;
    1122: #else
    1123:     if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
    1124:         t = DOUBLE;
    1125: #endif
    1126:     else if( t1==LONG || t2==LONG ) t = LONG;
    1127:     else t = INT;
    1128:
    1129:     if( o == ASSIGN || o == CAST || o == RETURN ){
    1130:         tu = p->in.left->in.type;
    1131:         t = t1;
    1132:         }
    1133:     else {
    1134:         tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
    1135:         }
    1136:
    1137:     /* because expressions have values that are at least as wide
    1138: 	   as INT or UNSIGNED, the only conversions needed
    1139: 	   are those involving FLOAT/DOUBLE, and those
    1140: 	   from LONG to INT and ULONG to UNSIGNED */
    1141:
    1142:     if( t != t1 && ! asgop(o) )
    1143:         p->in.left = makety( p->in.left, tu, 0, (int)tu );
    1144:
    1145:     if( t != t2 || o==CAST )
    1146:         p->in.right = makety( p->in.right, tu, 0, (int)tu );
    1147:
    1148:     if( asgop(o) ){
    1149:         p->in.type = p->in.left->in.type;
    1150:         p->fn.cdim = p->in.left->fn.cdim;
    1151:         p->fn.csiz = p->in.left->fn.csiz;
    1152:         }
    1153:     else if( !logop(o) ){
    1154:         p->in.type = tu;
    1155:         p->fn.cdim = 0;
    1156:         p->fn.csiz = t;
    1157:         }
    1158:
    1159: # ifndef BUG1
    1160:     if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
    1161: # endif
    1162:
    1163:     return(p);
    1164:     }
    1165:
    1166: NODE *
    1167: makety( p, t, d, s ) register NODE *p; TWORD t; {
    1168:     /* make p into type t by inserting a conversion */
    1169:
    1170:     if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
    1171:     if( t == p->in.type ){
    1172:         p->fn.cdim = d;
    1173:         p->fn.csiz = s;
    1174:         return( p );
    1175:         }
    1176:
    1177:     if( t & TMASK ){
    1178:         /* non-simple type */
    1179:         return( block( PCONV, p, NIL, t, d, s ) );
    1180:         }
    1181:
    1182:     if( p->in.op == ICON ){
    1183:         if (t == DOUBLE) {
    1184:             p->in.op = DCON;
    1185:             if (ISUNSIGNED(p->in.type))
    1186:                 p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval;
    1187:             else
    1188:                 p->dpn.dval = p->tn.lval;
    1189:             p->in.type = p->fn.csiz = t;
    1190:             return (clocal(p));
    1191:         }
    1192:         if (t == FLOAT) {
    1193:             p->in.op = FCON;
    1194:             if( ISUNSIGNED(p->in.type) ){
    1195:                 p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval;
    1196:                 }
    1197:             else {
    1198:                 p->fpn.fval = p->tn.lval;
    1199:                 }
    1200:
    1201:             p->in.type = p->fn.csiz = t;
    1202:             return( clocal(p) );
    1203:             }
    1204:         }
    1205:     else if (p->in.op == FCON && t == DOUBLE) {
    1206:         double db;
    1207:
    1208:         p->in.op = DCON;
    1209:         db = p->fpn.fval;
    1210:         p->dpn.dval = db;
    1211:         p->in.type = p->fn.csiz = t;
    1212:         return (clocal(p));
    1213:     } else if (p->in.op == DCON && t == FLOAT) {
    1214:         float fl;
    1215:
    1216:         p->in.op = FCON;
    1217:         fl = p->dpn.dval;
    1218: #ifdef notdef
    1219:         if (fl != p->dpn.dval)
    1220:             werror("float conversion loses precision");
    1221: #endif
    1222:         p->fpn.fval = fl;
    1223:         p->in.type = p->fn.csiz = t;
    1224:         return (clocal(p));
    1225:     }
    1226:
    1227:     return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
    1228:
    1229:     }
    1230:
    1231: NODE *
    1232: block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
    1233:
    1234:     register NODE *p;
    1235:
    1236:     p = talloc();
    1237:     p->in.op = o;
    1238:     p->in.left = l;
    1239:     p->in.right = r;
    1240:     p->in.type = t;
    1241:     p->fn.cdim = d;
    1242:     p->fn.csiz = s;
    1243:     return(p);
    1244:     }
    1245:
    1246: icons(p) register NODE *p; {
    1247:     /* if p is an integer constant, return its value */
    1248:     int val;
    1249:
    1250:     if( p->in.op != ICON ){
    1251:         uerror("constant expected");
    1252:         val = 1;
    1253:         }
    1254:     else {
    1255:         val = p->tn.lval;
    1256:         if( val != p->tn.lval ) uerror("constant too big for cross-compiler" );
    1257:         }
    1258:     tfree( p );
    1259:     return(val);
    1260:     }
    1261:
    1262: /* 	the intent of this table is to examine the
    1263: 	operators, and to check them for
    1264: 	correctness.
    1265:
    1266: 	The table is searched for the op and the
    1267: 	modified type (where this is one of the
    1268: 	types INT (includes char and short), LONG,
    1269: 	DOUBLE (includes FLOAT), and POINTER
    1270:
    1271: 	The default action is to make the node type integer
    1272:
    1273: 	The actions taken include:
    1274: 		PUN	  check for puns
    1275: 		CVTL	  convert the left operand
    1276: 		CVTR	  convert the right operand
    1277: 		TYPL	  the type is determined by the left operand
    1278: 		TYPR	  the type is determined by the right operand
    1279: 		TYMATCH	  force type of left and right to match, by inserting conversions
    1280: 		PTMATCH	  like TYMATCH, but for pointers
    1281: 		LVAL	  left operand must be lval
    1282: 		CVTO	  convert the op
    1283: 		NCVT	  do not convert the operands
    1284: 		OTHER	  handled by code
    1285: 		NCVTR	  convert the left operand, not the right...
    1286:
    1287: 	*/
    1288:
    1289: # define MINT 01  /* integer */
    1290: # define MDBI 02   /* integer or double */
    1291: # define MSTR 04  /* structure */
    1292: # define MPTR 010  /* pointer */
    1293: # define MPTI 020  /* pointer or integer */
    1294: # define MENU 040 /* enumeration variable or member */
    1295: # define MVOID 0100000 /* void type */
    1296:
    1297: opact( p )  NODE *p; {
    1298:
    1299:     register mt12, mt1, mt2, o;
    1300:
    1301:     mt1 = mt2 = mt12 = 0;
    1302:
    1303:     switch( optype(o=p->in.op) ){
    1304:
    1305:     case BITYPE:
    1306:         mt2 = moditype( p->in.right->in.type );
    1307:     case UTYPE:
    1308:         mt1 = moditype( p->in.left->in.type );
    1309:         break;
    1310:
    1311:         }
    1312:
    1313:     if( ((mt1 | mt2) & MVOID) &&
    1314:         o != COMOP &&
    1315:         !(o == CAST && (mt1 & MVOID)) ){
    1316:         /* if lhs of RETURN is void, grammar will complain */
    1317:         if( o != RETURN )
    1318:             uerror("value of void expression used" );
    1319:         return( NCVT );
    1320:         }
    1321:     mt1 &= ~MVOID;
    1322:     mt2 &= ~MVOID;
    1323:     mt12 = mt1 & mt2;
    1324:
    1325:     switch( o ){
    1326:
    1327:     case NAME :
    1328:     case STRING :
    1329:     case ICON :
    1330:     case FCON :
    1331:     case DCON :
    1332:     case CALL :
    1333:     case UNARY CALL:
    1334:     case UNARY MUL:
    1335:         {  return( OTHER ); }
    1336:     case UNARY MINUS:
    1337:         if( mt1 & MDBI ) return( TYPL );
    1338:         break;
    1339:
    1340:     case COMPL:
    1341:         if( mt1 & MINT ) return( TYPL );
    1342:         break;
    1343:
    1344:     case UNARY AND:
    1345:         {  return( NCVT+OTHER ); }
    1346:     case INIT:
    1347:     case CM:
    1348:         return( 0 );
    1349:
    1350:     case NOT:
    1351:     case CBRANCH:
    1352:         if( mt1 & MSTR ) break;
    1353:         return( 0 );
    1354:
    1355:     case ANDAND:
    1356:     case OROR:
    1357:         if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
    1358:         return( 0 );
    1359:
    1360:     case MUL:
    1361:     case DIV:
    1362:         if( mt12 & MDBI ) return( TYMATCH );
    1363:         break;
    1364:
    1365:     case MOD:
    1366:     case AND:
    1367:     case OR:
    1368:     case ER:
    1369:         if( mt12 & MINT ) return( TYMATCH );
    1370:         break;
    1371:
    1372:     case LS:
    1373:     case RS:
    1374:         if( mt12 & MINT ) return( TYMATCH+OTHER );
    1375:         break;
    1376:
    1377:     case EQ:
    1378:     case NE:
    1379:     case LT:
    1380:     case LE:
    1381:     case GT:
    1382:     case GE:
    1383:         if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT );
    1384:         if( mt12 & MDBI ) return( TYMATCH+CVTO );
    1385:         else if( mt12 & MPTR ) return( PTMATCH+PUN );
    1386:         else if( mt12 & MPTI ) return( PTMATCH+PUN );
    1387:         else break;
    1388:
    1389:     case QUEST:
    1390:     case COMOP:
    1391:         if( mt2&MENU ) return( TYPR+NCVTR );
    1392:         return( TYPR );
    1393:
    1394:     case STREF:
    1395:         return( NCVTR+OTHER );
    1396:
    1397:     case FORCE:
    1398:         return( TYPL );
    1399:
    1400:     case COLON:
    1401:         if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
    1402:         else if( mt12 & MDBI ) return( TYMATCH );
    1403:         else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
    1404:         else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
    1405:         else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
    1406:         else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
    1407:         break;
    1408:
    1409:     case ASSIGN:
    1410:     case RETURN:
    1411:         if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
    1412:     case CAST:
    1413:         if(o==CAST && mt1==0)return(TYPL+TYMATCH);
    1414:         if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
    1415:         else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
    1416:         else if( mt2 == 0 &&
    1417:                 ( p->in.right->in.op == CALL ||
    1418:               p->in.right->in.op == UNARY CALL)) break;
    1419:         else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
    1420:         else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
    1421:         break;
    1422:
    1423:     case ASG LS:
    1424:     case ASG RS:
    1425:         if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
    1426:         break;
    1427:
    1428:     case ASG MUL:
    1429:     case ASG DIV:
    1430:         if( mt12 & MDBI ) return( LVAL+TYMATCH );
    1431:         break;
    1432:
    1433:     case ASG MOD:
    1434:     case ASG AND:
    1435:     case ASG OR:
    1436:     case ASG ER:
    1437:         if( mt12 & MINT ) return( LVAL+TYMATCH );
    1438:         break;
    1439:
    1440:     case ASG PLUS:
    1441:     case ASG MINUS:
    1442:     case INCR:
    1443:     case DECR:
    1444:         if( mt12 & MDBI ) return( TYMATCH+LVAL );
    1445:         else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
    1446:         break;
    1447:
    1448:     case MINUS:
    1449:         if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
    1450:         if( mt2 & MPTR ) break;
    1451:     case PLUS:
    1452:         if( mt12 & MDBI ) return( TYMATCH );
    1453:         else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
    1454:         else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
    1455:
    1456:         }
    1457:     if( mt12 == MSTR )
    1458:         uerror("%s is not a permitted struct/union operation", opst[o] );
    1459:     else
    1460:         uerror("operands of %s have incompatible types", opst[o] );
    1461:     return( NCVT );
    1462:     }
    1463:
    1464: moditype( ty ) TWORD ty; {
    1465:
    1466:     switch( ty ){
    1467:
    1468:     case UNDEF:
    1469:         return( MVOID );
    1470:     case ENUMTY:
    1471:     case MOETY:
    1472:         return( MENU );
    1473:
    1474:     case STRTY:
    1475:     case UNIONTY:
    1476:         return( MSTR );
    1477:
    1478:     case CHAR:
    1479:     case SHORT:
    1480:     case UCHAR:
    1481:     case USHORT:
    1482:         return( MINT|MPTI|MDBI );
    1483:     case UNSIGNED:
    1484:     case ULONG:
    1485:     case INT:
    1486:     case LONG:
    1487:         return( MINT|MDBI|MPTI );
    1488:     case FLOAT:
    1489:     case DOUBLE:
    1490:         return( MDBI );
    1491:     default:
    1492:         return( MPTR|MPTI );
    1493:
    1494:         }
    1495:     }
    1496:
    1497: NODE *
    1498: doszof( p )  register NODE *p; {
    1499:     /* do sizeof p */
    1500:     int i;
    1501:
    1502:     /* whatever is the meaning of this if it is a bitfield? */
    1503:     i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
    1504:
    1505:     tfree(p);
    1506:     if( i <= 0 ) werror("sizeof returns 0" );
    1507:     return( bcon( i ) );
    1508:     }
    1509:
    1510: # ifndef BUG2
    1511: eprint( p, down, a, b ) register NODE *p; int *a, *b; {
    1512:     register ty;
    1513:
    1514:     *a = *b = down+1;
    1515:     while( down > 1 ){
    1516:         printf( "\t" );
    1517:         down -= 2;
    1518:         }
    1519:     if( down ) printf( "    " );
    1520:
    1521:     ty = optype( p->in.op );
    1522:
    1523:     printf("%o) %s, ", p, opst[p->in.op] );
    1524:     if( ty == LTYPE ){
    1525:         printf( CONFMT, p->tn.lval );
    1526:         printf( ", %d, ", p->tn.rval );
    1527:         }
    1528:     tprint( p->in.type );
    1529:     printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
    1530:     }
    1531: # endif
    1532:
    1533: prtdcon( p ) register NODE *p; {
    1534:     int o = p->in.op, i;
    1535:
    1536:     if( o == DCON || o == FCON ){
    1537:         locctr( DATA );
    1538:         defalign( o == DCON ? ALDOUBLE : ALFLOAT );
    1539:         deflab( i = getlab() );
    1540:         if( o == FCON )
    1541:             fincode( p->fpn.fval, SZFLOAT );
    1542:         else
    1543:             fincode( p->dpn.dval, SZDOUBLE );
    1544:         p->tn.lval = 0;
    1545:         p->tn.rval = -i;
    1546:         p->in.type = (o == DCON ? DOUBLE : FLOAT);
    1547:         p->in.op = NAME;
    1548:         }
    1549:     }
    1550:
    1551:
    1552: int edebug = 0;
    1553: ecomp( p ) register NODE *p; {
    1554: # ifndef BUG2
    1555:     if( edebug ) fwalk( p, eprint, 0 );
    1556: # endif
    1557:     if( !reached ){
    1558:         werror("statement not reached" );
    1559:         reached = 1;
    1560:         }
    1561:     p = optim(p);
    1562:     walkf( p, prtdcon );
    1563:     locctr( PROG );
    1564:     ecode( p );
    1565:     tfree(p);
    1566:     }
    1567:
    1568: # ifdef STDPRTREE
    1569: # ifndef ONEPASS
    1570:
    1571: prtree(p) register NODE *p; {
    1572:
    1573:     register struct symtab *q;
    1574:     register ty;
    1575:
    1576: # ifdef MYPRTREE
    1577:     MYPRTREE(p);  /* local action can be taken here; then return... */
    1578: #endif
    1579:
    1580:     ty = optype(p->in.op);
    1581:
    1582:     printf( "%d\t", p->in.op );
    1583:
    1584:     if( ty == LTYPE ) {
    1585:         printf( CONFMT, p->tn.lval );
    1586:         printf( "\t" );
    1587:         }
    1588:     if( ty != BITYPE ) {
    1589:         if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
    1590:         else printf( "%d\t", p->tn.rval );
    1591:         }
    1592:
    1593:     printf( "%o\t", p->in.type );
    1594:
    1595:     /* handle special cases */
    1596:
    1597:     switch( p->in.op ){
    1598:
    1599:     case NAME:
    1600:     case ICON:
    1601:         /* print external name */
    1602:         if( p->tn.rval == NONAME ) printf( "\n" );
    1603:         else if( p->tn.rval >= 0 ){
    1604:             q = &stab[p->tn.rval];
    1605:             printf(  "%s\n", exname(q->sname) );
    1606:             }
    1607:         else { /* label */
    1608:             printf( LABFMT, -p->tn.rval );
    1609:             }
    1610:         break;
    1611:
    1612:     case STARG:
    1613:     case STASG:
    1614:     case STCALL:
    1615:     case UNARY STCALL:
    1616:         /* print out size */
    1617:         /* use lhs size, in order to avoid hassles with the structure `.' operator */
    1618:
    1619:         /* note: p->in.left not a field... */
    1620:         printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
    1621:         printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
    1622:         break;
    1623:
    1624:     default:
    1625:         printf(  "\n" );
    1626:         }
    1627:
    1628:     if( ty != LTYPE ) prtree( p->in.left );
    1629:     if( ty == BITYPE ) prtree( p->in.right );
    1630:
    1631:     }
    1632:
    1633: # else
    1634:
    1635: p2tree(p) register NODE *p; {
    1636:     register ty;
    1637:
    1638: # ifdef MYP2TREE
    1639:     MYP2TREE(p);  /* local action can be taken here; then return... */
    1640: # endif
    1641:
    1642:     ty = optype(p->in.op);
    1643:
    1644:     switch( p->in.op ){
    1645:
    1646:     case NAME:
    1647:     case ICON:
    1648: #ifndef FLEXNAMES
    1649:         if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
    1650: #else
    1651:         if( p->tn.rval == NONAME ) p->in.name = "";
    1652: #endif
    1653:         else if( p->tn.rval >= 0 ){ /* copy name from exname */
    1654:             register char *cp;
    1655:             register i;
    1656:             cp = exname( stab[p->tn.rval].sname );
    1657: #ifndef FLEXNAMES
    1658:             for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
    1659: #else
    1660:             p->in.name = tstr(cp);
    1661: #endif
    1662:             }
    1663: #ifndef FLEXNAMES
    1664:         else sprintf( p->in.name, LABFMT, -p->tn.rval );
    1665: #else
    1666:         else {
    1667:             char temp[32];
    1668:             sprintf( temp, LABFMT, -p->tn.rval );
    1669:             p->in.name = tstr(temp);
    1670:         }
    1671: #endif
    1672:         break;
    1673:
    1674:     case STARG:
    1675:     case STASG:
    1676:     case STCALL:
    1677:     case UNARY STCALL:
    1678:         /* set up size parameters */
    1679:         p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim, (OFFSZ)p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
    1680:         p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
    1681:         break;
    1682:
    1683:     case REG:
    1684:         rbusy( p->tn.rval, p->in.type );
    1685:     default:
    1686: #ifndef FLEXNAMES
    1687:         p->in.name[0] = '\0';
    1688: #else
    1689:         p->in.name = "";
    1690: #endif
    1691:         }
    1692:
    1693:     p->in.rall = NOPREF;
    1694:
    1695:     if( ty != LTYPE ) p2tree( p->in.left );
    1696:     if( ty == BITYPE ) p2tree( p->in.right );
    1697:     }
    1698:
    1699: # endif
    1700: # endif

#### Defined functions

bcon defined in line 900; used 11 times

- in line 1507
- in /usr/src/lib/mip/cgram.y line 430, 531, 551, 562, 667, 688, 732, 808
- in /usr/src/lib/mip/pass1.h line 181
- in /usr/src/lib/mip/pftn.c line 979

block defined in line 1231; used 22 times

- in line 231, 506, 594, 855, 862, 904, 939, 1002, 1179, 1227
- in /usr/src/lib/mip/cgram.y line 492, 506, 724, 778, 792, 799
- in /usr/src/lib/mip/pass1.h line 189
- in /usr/src/lib/mip/pftn.c line 450, 474, 500, 513, 1099

bpsize defined in line 910; used 3 times

- in line 940, 1003
- in /usr/src/lib/mip/pass1.h line 182

buildtree defined in line 83; used 47 times

- in line 444-453(6), 501, 545, 595, 857, 978-981(2)
- in /usr/src/lib/mip/cgram.y line 430(2), 476-485(3), 531, 551, 562, 582, 611, 641, 658(2), 667-670(2), 683-686(2), 693, 701-712(7), 728, 738-742(2), 783
- in /usr/src/lib/mip/optim.c line 31
- in /usr/src/lib/mip/pass1.h line 172
- in /usr/src/lib/mip/pftn.c line 971, 1066(2), 1099

chkpun defined in line 750; used 1 times

- in line 260

chkstr defined in line 603; used 2 times

- in line 408, 631

conval defined in line 648; used 5 times

- in line 108, 170
- in /usr/src/lib/mip/optim.c line 112, 119-123(2)

convert defined in line 928; used 3 times

- in line 272-273(2)
- in /usr/src/lib/mip/pass1.h line 183

doszof defined in line 1497; used 3 times

- in /usr/src/lib/mip/cgram.y line 691, 699
- in /usr/src/lib/mip/pass1.h line 190

ecomp defined in line 1553; used 10 times

- in /usr/src/lib/mip/cgram.y line 408, 430, 438, 485, 531, 551-555(2), 562, 582
- in /usr/src/lib/mip/pftn.c line 1067

econvert defined in line 951; used 3 times

- in line 950, 1170
- in /usr/src/lib/mip/optim.c line 47

eprint defined in line 1511; never used
fixargs defined in line 583; used 5 times

- in line 90, 526, 588-589(2)
- in /usr/src/lib/mip/pass1.h line 193

fpe defined in line 570; used 2 times

- in /usr/src/lib/mip/scan.c line 66, 179

icons defined in line 1246; used 1 times

- in /usr/src/lib/mip/cgram.y line 591

makety defined in line 1166; used 10 times

- in line 484, 599, 843, 1067-1068(2), 1143-1146(2)
- in /usr/src/lib/mip/cgram.y line 580
- in /usr/src/lib/mip/optim.c line 126
- in /usr/src/lib/mip/pass1.h line 188

moditype defined in line 1464; used 2 times

- in line 1306-1308(2)

notlval defined in line 869; used 2 times

- in line 240
- in /usr/src/lib/mip/cgram.y line 708

oconvert defined in line 986; used 2 times

- in line 556
- in /usr/src/lib/mip/pass1.h line 185

opact defined in line 1297; used 1 times

- in line 233

p2tree defined in line 1635; used 2 times

- in line 1695-1696(2)

pconvert defined in line 970; used 5 times

- in line 246, 252-254(2), 831
- in /usr/src/lib/mip/pass1.h line 184

printact defined in line 31; used 1 times

- in line 236

prtdcon defined in line 1533; used 1 times

- in line 1562

prtree defined in line 1571; used 2 times

- in line 1628-1629(2)

psize defined in line 915; used 4 times

- in line 912, 1038(2)
- in /usr/src/lib/mip/pass1.h line 196

ptmatch defined in line 1011; used 2 times

- in line 275
- in /usr/src/lib/mip/pass1.h line 186

stref defined in line 817; used 2 times

- in line 417
- in /usr/src/lib/mip/pass1.h line 179

tymatch defined in line 1081; used 2 times

- in line 274
- in /usr/src/lib/mip/pass1.h line 187

#### Defined variables

adebug defined in line 10; used 1 times

- in line 235

bdebug defined in line 9; used 3 times

- in line 62, 94, 560

edebug defined in line 1552; never used
fpe_count defined in line 567; used 6 times

- in line 181-184(2), 217-221(2), 571-573(2)

gotfpe defined in line 568; used 3 times

- in line 182-185(2), 574

sccsid defined in line 2; never used
tdebug defined in line 1079; never used

#### Defined struct's

actions defined in line 35; used 2 times

- in line 53(2)

#### Defined macros

CVTL defined in line 24; used 7 times

- in line 40, 272(2), 937-942(3), 1454

CVTO defined in line 23; used 4 times

- in line 47, 556, 1384, 1449

CVTR defined in line 25; used 5 times

- in line 41, 273(2), 1445, 1453

LVAL defined in line 22; used 12 times

- in line 46, 239, 1411-1430(7), 1437, 1444-1445(2)

MDBI defined in line 1290; used 11 times

- in line 1337, 1362, 1384, 1402, 1414, 1430, 1444, 1452, 1482-1490(3)

MENU defined in line 1294; used 7 times

- in line 1383(2), 1391, 1401, 1415(2), 1472

MINT defined in line 1289; used 12 times

- in line 1341, 1369-1374(2), 1404-1405(2), 1425, 1437, 1445, 1453-1454(2), 1482-1487(2)

MPTI defined in line 1293; used 5 times

- in line 1386, 1420, 1482-1492(3)

MPTR defined in line 1292; used 11 times

- in line 1385, 1403-1405(3), 1419, 1445-1454(5), 1492

MSTR defined in line 1291; used 7 times

- in line 1352-1357(3), 1406-1411(2), 1457, 1476

MVOID defined in line 1295; used 5 times

- in line 1313-1315(2), 1321-1322(2), 1469

NCVT defined in line 17; used 10 times

- in line 48, 248, 1319, 1345, 1383, 1401-1415(4), 1461

NCVTR defined in line 28; used 4 times

- in line 50, 245, 1391-1395(2)

OTHER defined in line 27; used 9 times

- in line 49, 277, 1335, 1345, 1374, 1395, 1406-1411(2), 1425

PTMATCH defined in line 26; used 10 times

- in line 45, 275, 1383-1386(3), 1401-1403(2), 1415-1419(2), 1449

PUN defined in line 18; used 13 times

- in line 39, 259, 1383-1386(3), 1401-1405(4), 1415-1420(3), 1449

TYMATCH defined in line 21; used 14 times

- in line 44, 274, 1362, 1369-1374(2), 1384, 1402, 1413-1414(2), 1420, 1430, 1437, 1444, 1452

TYPL defined in line 19; used 17 times

- in line 42, 263-265(2), 1337-1341(2), 1398-1425(10), 1445, 1453

TYPR defined in line 20; used 6 times

- in line 43, 263, 1391-1392(2), 1404, 1454

Last modified: 1995-01-18 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3864 |