1: #ifndef lint
   2: static char *sccsid ="@(#)trees.c	4.10 (Berkeley) 1/8/86";
   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, 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 = 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, 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 ){ /* 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 TVOID:
1469:         return( MPTR );
1470:     case UNDEF:
1471:         return( MVOID );
1472:     case ENUMTY:
1473:     case MOETY:
1474:         return( MENU );
1475: 
1476:     case STRTY:
1477:     case UNIONTY:
1478:         return( MSTR );
1479: 
1480:     case CHAR:
1481:     case SHORT:
1482:     case UCHAR:
1483:     case USHORT:
1484:         return( MINT|MPTI|MDBI );
1485:     case UNSIGNED:
1486:     case ULONG:
1487:     case INT:
1488:     case LONG:
1489:         return( MINT|MDBI|MPTI );
1490:     case FLOAT:
1491:     case DOUBLE:
1492:         return( MDBI );
1493:     default:
1494:         return( MPTR|MPTI );
1495: 
1496:         }
1497:     }
1498: 
1499: NODE *
1500: doszof( p )  register NODE *p; {
1501:     /* do sizeof p */
1502:     int i;
1503: 
1504:     /* whatever is the meaning of this if it is a bitfield? */
1505:     i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
1506: 
1507:     tfree(p);
1508:     if( i <= 0 ) werror( "sizeof returns 0" );
1509:     return( bcon( i ) );
1510:     }
1511: 
1512: # ifndef BUG2
1513: eprint( p, down, a, b ) register NODE *p; int *a, *b; {
1514:     register ty;
1515: 
1516:     *a = *b = down+1;
1517:     while( down > 1 ){
1518:         printf( "\t" );
1519:         down -= 2;
1520:         }
1521:     if( down ) printf( "    " );
1522: 
1523:     ty = optype( p->in.op );
1524: 
1525:     printf("%o) %s, ", p, opst[p->in.op] );
1526:     if( ty == LTYPE ){
1527:         printf( CONFMT, p->tn.lval );
1528:         printf( ", %d, ", p->tn.rval );
1529:         }
1530:     tprint( p->in.type );
1531:     printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
1532:     }
1533: # endif
1534: 
1535: prtdcon( p ) register NODE *p; {
1536:     int o = p->in.op, i;
1537: 
1538:     if( o == DCON || o == FCON ){
1539:         locctr( DATA );
1540:         defalign( o == DCON ? ALDOUBLE : ALFLOAT );
1541:         deflab( i = getlab() );
1542:         if( o == FCON )
1543:             fincode( p->fpn.fval, SZFLOAT );
1544:         else
1545:             fincode( p->dpn.dval, SZDOUBLE );
1546:         p->tn.lval = 0;
1547:         p->tn.rval = -i;
1548:         p->in.type = (o == DCON ? DOUBLE : FLOAT);
1549:         p->in.op = NAME;
1550:         }
1551:     }
1552: 
1553: 
1554: int edebug = 0;
1555: ecomp( p ) register NODE *p; {
1556: # ifndef BUG2
1557:     if( edebug ) fwalk( p, eprint, 0 );
1558: # endif
1559:     if( !reached ){
1560:         werror( "statement not reached" );
1561:         reached = 1;
1562:         }
1563:     p = optim(p);
1564:     walkf( p, prtdcon );
1565:     locctr( PROG );
1566:     ecode( p );
1567:     tfree(p);
1568:     }
1569: 
1570: # ifdef STDPRTREE
1571: # ifndef ONEPASS
1572: 
1573: prtree(p) register NODE *p; {
1574: 
1575:     register struct symtab *q;
1576:     register ty;
1577: 
1578: # ifdef MYPRTREE
1579:     MYPRTREE(p);  /* local action can be taken here; then return... */
1580: #endif
1581: 
1582:     ty = optype(p->in.op);
1583: 
1584:     printf( "%d\t", p->in.op );
1585: 
1586:     if( ty == LTYPE ) {
1587:         printf( CONFMT, p->tn.lval );
1588:         printf( "\t" );
1589:         }
1590:     if( ty != BITYPE ) {
1591:         if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
1592:         else printf( "%d\t", p->tn.rval );
1593:         }
1594: 
1595:     printf( "%o\t", p->in.type );
1596: 
1597:     /* handle special cases */
1598: 
1599:     switch( p->in.op ){
1600: 
1601:     case NAME:
1602:     case ICON:
1603:         /* print external name */
1604:         if( p->tn.rval == NONAME ) printf( "\n" );
1605:         else if( p->tn.rval >= 0 ){
1606:             q = &stab[p->tn.rval];
1607:             printf(  "%s\n", exname(q->sname) );
1608:             }
1609:         else { /* label */
1610:             printf( LABFMT, -p->tn.rval );
1611:             }
1612:         break;
1613: 
1614:     case STARG:
1615:     case STASG:
1616:     case STCALL:
1617:     case UNARY STCALL:
1618:         /* print out size */
1619:         /* use lhs size, in order to avoid hassles with the structure `.' operator */
1620: 
1621:         /* note: p->in.left not a field... */
1622:         printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
1623:         printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
1624:         break;
1625: 
1626:     default:
1627:         printf(  "\n" );
1628:         }
1629: 
1630:     if( ty != LTYPE ) prtree( p->in.left );
1631:     if( ty == BITYPE ) prtree( p->in.right );
1632: 
1633:     }
1634: 
1635: # else
1636: 
1637: p2tree(p) register NODE *p; {
1638:     register ty;
1639: 
1640: # ifdef MYP2TREE
1641:     MYP2TREE(p);  /* local action can be taken here; then return... */
1642: # endif
1643: 
1644:     ty = optype(p->in.op);
1645: 
1646:     switch( p->in.op ){
1647: 
1648:     case NAME:
1649:     case ICON:
1650: #ifndef FLEXNAMES
1651:         if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
1652: #else
1653:         if( p->tn.rval == NONAME ) p->in.name = "";
1654: #endif
1655:         else if( p->tn.rval >= 0 ){ /* copy name from exname */
1656:             register char *cp;
1657:             register i;
1658:             cp = exname( stab[p->tn.rval].sname );
1659: #ifndef FLEXNAMES
1660:             for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
1661: #else
1662:             p->in.name = tstr(cp);
1663: #endif
1664:             }
1665: #ifndef FLEXNAMES
1666:         else sprintf( p->in.name, LABFMT, -p->tn.rval );
1667: #else
1668:         else {
1669:             char temp[32];
1670:             sprintf( temp, LABFMT, -p->tn.rval );
1671:             p->in.name = tstr(temp);
1672:         }
1673: #endif
1674:         break;
1675: 
1676:     case STARG:
1677:     case STASG:
1678:     case STCALL:
1679:     case UNARY STCALL:
1680:         /* set up size parameters */
1681:         p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
1682:         p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
1683:         break;
1684: 
1685:     case REG:
1686:         rbusy( p->tn.rval, p->in.type );
1687:     default:
1688: #ifndef FLEXNAMES
1689:         p->in.name[0] = '\0';
1690: #else
1691:         p->in.name = "";
1692: #endif
1693:         }
1694: 
1695:     p->in.rall = NOPREF;
1696: 
1697:     if( ty != LTYPE ) p2tree( p->in.left );
1698:     if( ty == BITYPE ) p2tree( p->in.right );
1699:     }
1700: 
1701: # endif
1702: # endif

Defined functions

bcon defined in line 900; used 11 times
block defined in line 1231; used 22 times
bpsize defined in line 910; used 3 times
buildtree defined in line 83; used 47 times
chkpun defined in line 750; used 1 times
chkstr defined in line 603; used 2 times
conval defined in line 648; used 5 times
convert defined in line 928; used 3 times
doszof defined in line 1499; used 3 times
ecomp defined in line 1555; used 10 times
econvert defined in line 951; used 3 times
eprint defined in line 1513; never used
fixargs defined in line 583; used 5 times
fpe defined in line 570; used 2 times
icons defined in line 1246; used 1 times
makety defined in line 1166; used 10 times
moditype defined in line 1464; used 2 times
notlval defined in line 869; used 2 times
oconvert defined in line 986; used 2 times
opact defined in line 1297; used 1 times
p2tree defined in line 1637; used 2 times
pconvert defined in line 970; used 5 times
printact defined in line 31; used 1 times
prtdcon defined in line 1535; used 1 times
prtree defined in line 1573; used 2 times
psize defined in line 915; used 4 times
ptmatch defined in line 1011; used 2 times
stref defined in line 817; used 2 times
tymatch defined in line 1081; used 2 times

Defined variables

adebug defined in line 10; used 1 times
bdebug defined in line 9; used 3 times
edebug defined in line 1554; never used
fpe_count defined in line 567; used 6 times
gotfpe defined in line 568; used 3 times
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
CVTO defined in line 23; used 4 times
CVTR defined in line 25; used 5 times
LVAL defined in line 22; used 12 times
MDBI defined in line 1290; used 11 times
MENU defined in line 1294; used 7 times
MINT defined in line 1289; used 12 times
MPTI defined in line 1293; used 5 times
MPTR defined in line 1292; used 12 times
MSTR defined in line 1291; used 7 times
MVOID defined in line 1295; used 5 times
NCVT defined in line 17; used 10 times
NCVTR defined in line 28; used 4 times
OTHER defined in line 27; used 9 times
PTMATCH defined in line 26; used 10 times
PUN defined in line 18; used 13 times
TYMATCH defined in line 21; used 14 times
TYPL defined in line 19; used 17 times
TYPR defined in line 20; used 6 times
Last modified: 1986-01-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3617
Valid CSS Valid XHTML 1.0 Strict