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

Defined functions

bcon defined in line 691; used 11 times
block defined in line 976; used 26 times
bpsize defined in line 701; used 2 times
buildtree defined in line 32; used 49 times
chkpun defined in line 548; used 1 times
chkstr defined in line 420; used 2 times
conval defined in line 449; used 5 times
convert defined in line 719; used 2 times
doszof defined in line 1212; used 2 times
ecomp defined in line 1263; used 11 times
econvert defined in line 741; used 2 times
eprint defined in line 1225; used 3 times
icons defined in line 991; used 1 times
makety defined in line 941; used 7 times
moditype defined in line 1181; used 2 times
notlval defined in line 665; used 1 times
oconvert defined in line 775; used 1 times
opact defined in line 1041; used 1 times
p2tree defined in line 1343; used 2 times
pconvert defined in line 759; used 4 times
prtdcon defined in line 1246; used 1 times
prtree defined in line 1279; used 2 times
psize defined in line 706; used 3 times
ptmatch defined in line 800; used 1 times
strargs defined in line 403; used 3 times
stref defined in line 614; used 1 times
tymatch defined in line 870; used 1 times

Defined variables

bdebug defined in line 30; used 2 times
edebug defined in line 1262; used 1 times
tdebug defined in line 868; used 1 times

Defined macros

CVTL defined in line 11; used 6 times
CVTO defined in line 10; used 3 times
CVTR defined in line 12; used 4 times
LVAL defined in line 9; used 11 times
MDBI defined in line 1035; used 11 times
MENU defined in line 1039; used 7 times
MINT defined in line 1034; used 12 times
MPTI defined in line 1038; used 4 times
MPTR defined in line 1037; used 11 times
MSTR defined in line 1036; used 3 times
NCVT defined in line 4; used 9 times
NCVTR defined in line 15; used 2 times
OTHER defined in line 14; used 8 times
PTMATCH defined in line 13; used 9 times
PUN defined in line 5; used 12 times
TYMATCH defined in line 8; used 11 times
TYPL defined in line 6; used 16 times
TYPR defined in line 7; used 5 times
Last modified: 1982-08-28
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1509
Valid CSS Valid XHTML 1.0 Strict