1 #ifndef lint 2 static char *sccsid ="@(#)trees.c 4.10 (Berkeley) 01/08/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 1703