1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)rval.c 1.7 01/02/81"; 4 5 #include "whoami.h" 6 #include "0.h" 7 #include "tree.h" 8 #include "opcode.h" 9 #include "objfmt.h" 10 #ifdef PC 11 # include "pc.h" 12 # include "pcops.h" 13 #endif PC 14 15 extern char *opnames[]; 16 17 /* line number of the last record comparison warning */ 18 short reccompline = 0; 19 20 #ifdef PC 21 char *relts[] = { 22 "_RELEQ" , "_RELNE" , 23 "_RELTLT" , "_RELTGT" , 24 "_RELTLE" , "_RELTGE" 25 }; 26 char *relss[] = { 27 "_RELEQ" , "_RELNE" , 28 "_RELSLT" , "_RELSGT" , 29 "_RELSLE" , "_RELSGE" 30 }; 31 long relops[] = { 32 P2EQ , P2NE , 33 P2LT , P2GT , 34 P2LE , P2GE 35 }; 36 long mathop[] = { P2MUL , P2PLUS , P2MINUS }; 37 char *setop[] = { "_MULT" , "_ADDT" , "_SUBT" }; 38 #endif PC 39 /* 40 * Rvalue - an expression. 41 * 42 * Contype is the type that the caller would prefer, nand is important 43 * if constant sets or constant strings are involved, the latter 44 * because of string padding. 45 * required is a flag whether an lvalue or an rvalue is required. 46 * only VARs and structured things can have gt their lvalue this way. 47 */ 48 struct nl * 49 rvalue(r, contype , required ) 50 int *r; 51 struct nl *contype; 52 int required; 53 { 54 register struct nl *p, *p1; 55 register struct nl *q; 56 int c, c1, *rt, w, g; 57 char *cp, *cp1, *opname; 58 long l; 59 double f; 60 extern int flagwas; 61 struct csetstr csetd; 62 # ifdef PC 63 struct nl *rettype; 64 long ctype; 65 long tempoff; 66 # endif PC 67 68 if (r == NIL) 69 return (NIL); 70 if (nowexp(r)) 71 return (NIL); 72 /* 73 * Pick up the name of the operation 74 * for future error messages. 75 */ 76 if (r[0] <= T_IN) 77 opname = opnames[r[0]]; 78 79 /* 80 * The root of the tree tells us what sort of expression we have. 81 */ 82 switch (r[0]) { 83 84 /* 85 * The constant nil 86 */ 87 case T_NIL: 88 # ifdef OBJ 89 put(2, O_CON2, 0); 90 # endif OBJ 91 # ifdef PC 92 putleaf( P2ICON , 0 , 0 , P2PTR|P2UNDEF , 0 ); 93 # endif PC 94 return (nl+TNIL); 95 96 /* 97 * Function call with arguments. 98 */ 99 case T_FCALL: 100 # ifdef OBJ 101 return (funccod(r)); 102 # endif OBJ 103 # ifdef PC 104 return (pcfunccod( r )); 105 # endif PC 106 107 case T_VAR: 108 p = lookup(r[2]); 109 if (p == NIL || p->class == BADUSE) 110 return (NIL); 111 switch (p->class) { 112 case VAR: 113 /* 114 * If a variable is 115 * qualified then get 116 * the rvalue by a 117 * lvalue and an ind. 118 */ 119 if (r[3] != NIL) 120 goto ind; 121 q = p->type; 122 if (q == NIL) 123 return (NIL); 124 # ifdef OBJ 125 w = width(q); 126 switch (w) { 127 case 8: 128 put(2, O_RV8 | bn << 8+INDX, p->value[0]); 129 break; 130 case 4: 131 put(2, O_RV4 | bn << 8+INDX, p->value[0]); 132 break; 133 case 2: 134 put(2, O_RV2 | bn << 8+INDX, p->value[0]); 135 break; 136 case 1: 137 put(2, O_RV1 | bn << 8+INDX, p->value[0]); 138 break; 139 default: 140 put(3, O_RV | bn << 8+INDX, p->value[0], w); 141 } 142 # endif OBJ 143 # ifdef PC 144 if ( required == RREQ ) { 145 putRV( p -> symbol , bn , p -> value[0] 146 , p2type( q ) ); 147 } else { 148 putLV( p -> symbol , bn , p -> value[0] 149 , p2type( q ) ); 150 } 151 # endif PC 152 return (q); 153 154 case WITHPTR: 155 case REF: 156 /* 157 * A lvalue for these 158 * is actually what one 159 * might consider a rvalue. 160 */ 161 ind: 162 q = lvalue(r, NOFLAGS , LREQ ); 163 if (q == NIL) 164 return (NIL); 165 # ifdef OBJ 166 w = width(q); 167 switch (w) { 168 case 8: 169 put(1, O_IND8); 170 break; 171 case 4: 172 put(1, O_IND4); 173 break; 174 case 2: 175 put(1, O_IND2); 176 break; 177 case 1: 178 put(1, O_IND1); 179 break; 180 default: 181 put(2, O_IND, w); 182 } 183 # endif OBJ 184 # ifdef PC 185 if ( required == RREQ ) { 186 putop( P2UNARY P2MUL , p2type( q ) ); 187 } 188 # endif PC 189 return (q); 190 191 case CONST: 192 if (r[3] != NIL) { 193 error("%s is a constant and cannot be qualified", r[2]); 194 return (NIL); 195 } 196 q = p->type; 197 if (q == NIL) 198 return (NIL); 199 if (q == nl+TSTR) { 200 /* 201 * Find the size of the string 202 * constant if needed. 203 */ 204 cp = p->ptr[0]; 205 cstrng: 206 cp1 = cp; 207 for (c = 0; *cp++; c++) 208 continue; 209 if (contype != NIL && !opt('s')) { 210 if (width(contype) < c && classify(contype) == TSTR) { 211 error("Constant string too long"); 212 return (NIL); 213 } 214 c = width(contype); 215 } 216 # ifdef OBJ 217 put( 2 + (sizeof(char *)/sizeof(short)) 218 , O_CONG, c, cp1); 219 # endif OBJ 220 # ifdef PC 221 putCONG( cp1 , c , required ); 222 # endif PC 223 /* 224 * Define the string temporarily 225 * so later people can know its 226 * width. 227 * cleaned out by stat. 228 */ 229 q = defnl(0, STR, 0, c); 230 q->type = q; 231 return (q); 232 } 233 if (q == nl+T1CHAR) { 234 # ifdef OBJ 235 put(2, O_CONC, p->value[0]); 236 # endif OBJ 237 # ifdef PC 238 putleaf( P2ICON , p -> value[0] , 0 239 , P2CHAR , 0 ); 240 # endif PC 241 return (q); 242 } 243 /* 244 * Every other kind of constant here 245 */ 246 switch (width(q)) { 247 case 8: 248 #ifndef DEBUG 249 # ifdef OBJ 250 put(2, O_CON8, p->real); 251 # endif OBJ 252 # ifdef PC 253 putCON8( p -> real ); 254 # endif PC 255 #else 256 if (hp21mx) { 257 f = p->real; 258 conv(&f); 259 l = f.plong; 260 put(2, O_CON4, l); 261 } else 262 # ifdef OBJ 263 put(2, O_CON8, p->real); 264 # endif OBJ 265 # ifdef PC 266 putCON8( p -> real ); 267 # endif PC 268 #endif 269 break; 270 case 4: 271 # ifdef OBJ 272 put(2, O_CON4, p->range[0]); 273 # endif OBJ 274 # ifdef PC 275 putleaf( P2ICON , p -> range[0] , 0 276 , P2INT , 0 ); 277 # endif PC 278 break; 279 case 2: 280 # ifdef OBJ 281 put(2, O_CON2, ( short ) p->range[0]); 282 # endif OBJ 283 # ifdef PC 284 /* 285 * make short constants ints 286 */ 287 putleaf( P2ICON , (short) p -> range[0] 288 , 0 , P2INT , 0 ); 289 # endif PC 290 break; 291 case 1: 292 # ifdef OBJ 293 put(2, O_CON1, p->value[0]); 294 # endif OBJ 295 # ifdef PC 296 /* 297 * make char constants ints 298 */ 299 putleaf( P2ICON , p -> value[0] , 0 300 , P2INT , 0 ); 301 # endif PC 302 break; 303 default: 304 panic("rval"); 305 } 306 return (q); 307 308 case FUNC: 309 case FFUNC: 310 /* 311 * Function call with no arguments. 312 */ 313 if (r[3]) { 314 error("Can't qualify a function result value"); 315 return (NIL); 316 } 317 # ifdef OBJ 318 return (funccod((int *) r)); 319 # endif OBJ 320 # ifdef PC 321 return (pcfunccod( r )); 322 # endif PC 323 324 case TYPE: 325 error("Type names (e.g. %s) allowed only in declarations", p->symbol); 326 return (NIL); 327 328 case PROC: 329 case FPROC: 330 error("Procedure %s found where expression required", p->symbol); 331 return (NIL); 332 default: 333 panic("rvid"); 334 } 335 /* 336 * Constant sets 337 */ 338 case T_CSET: 339 # ifdef OBJ 340 if ( precset( r , contype , &csetd ) ) { 341 if ( csetd.csettype == NIL ) { 342 return NIL; 343 } 344 postcset( r , &csetd ); 345 } else { 346 put( 2, O_PUSH, -width(csetd.csettype)); 347 postcset( r , &csetd ); 348 setran( ( csetd.csettype ) -> type ); 349 put( 2, O_CON24, set.uprbp); 350 put( 2, O_CON24, set.lwrb); 351 put( 2, O_CTTOT, 4 + csetd.singcnt + 2 * csetd.paircnt); 352 } 353 return csetd.csettype; 354 # endif OBJ 355 # ifdef PC 356 if ( precset( r , contype , &csetd ) ) { 357 if ( csetd.csettype == NIL ) { 358 return NIL; 359 } 360 postcset( r , &csetd ); 361 } else { 362 putleaf( P2ICON , 0 , 0 363 , ADDTYPE( P2FTN | P2INT , P2PTR ) 364 , "_CTTOT" ); 365 /* 366 * allocate a temporary and use it 367 */ 368 sizes[ cbn ].om_off -= lwidth( csetd.csettype ); 369 tempoff = sizes[ cbn ].om_off; 370 putlbracket( ftnno , -tempoff ); 371 if ( tempoff < sizes[ cbn ].om_max ) { 372 sizes[ cbn ].om_max = tempoff; 373 } 374 putLV( 0 , cbn , tempoff , P2PTR|P2STRTY ); 375 setran( ( csetd.csettype ) -> type ); 376 putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 ); 377 putop( P2LISTOP , P2INT ); 378 putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 ); 379 putop( P2LISTOP , P2INT ); 380 postcset( r , &csetd ); 381 putop( P2CALL , P2INT ); 382 } 383 return csetd.csettype; 384 # endif PC 385 386 /* 387 * Unary plus and minus 388 */ 389 case T_PLUS: 390 case T_MINUS: 391 q = rvalue(r[2], NIL , RREQ ); 392 if (q == NIL) 393 return (NIL); 394 if (isnta(q, "id")) { 395 error("Operand of %s must be integer or real, not %s", opname, nameof(q)); 396 return (NIL); 397 } 398 if (r[0] == T_MINUS) { 399 # ifdef OBJ 400 put(1, O_NEG2 + (width(q) >> 2)); 401 # endif OBJ 402 # ifdef PC 403 putop( P2UNARY P2MINUS , p2type( q ) ); 404 # endif PC 405 return (isa(q, "d") ? q : nl+T4INT); 406 } 407 return (q); 408 409 case T_NOT: 410 q = rvalue(r[2], NIL , RREQ ); 411 if (q == NIL) 412 return (NIL); 413 if (isnta(q, "b")) { 414 error("not must operate on a Boolean, not %s", nameof(q)); 415 return (NIL); 416 } 417 # ifdef OBJ 418 put(1, O_NOT); 419 # endif OBJ 420 # ifdef PC 421 putop( P2NOT , P2INT ); 422 # endif PC 423 return (nl+T1BOOL); 424 425 case T_AND: 426 case T_OR: 427 p = rvalue(r[2], NIL , RREQ ); 428 p1 = rvalue(r[3], NIL , RREQ ); 429 if (p == NIL || p1 == NIL) 430 return (NIL); 431 if (isnta(p, "b")) { 432 error("Left operand of %s must be Boolean, not %s", opname, nameof(p)); 433 return (NIL); 434 } 435 if (isnta(p1, "b")) { 436 error("Right operand of %s must be Boolean, not %s", opname, nameof(p1)); 437 return (NIL); 438 } 439 # ifdef OBJ 440 put(1, r[0] == T_AND ? O_AND : O_OR); 441 # endif OBJ 442 # ifdef PC 443 /* 444 * note the use of & and | rather than && and || 445 * to force evaluation of all the expressions. 446 */ 447 putop( r[ 0 ] == T_AND ? P2AND : P2OR , P2INT ); 448 # endif PC 449 return (nl+T1BOOL); 450 451 case T_DIVD: 452 # ifdef OBJ 453 p = rvalue(r[2], NIL , RREQ ); 454 p1 = rvalue(r[3], NIL , RREQ ); 455 # endif OBJ 456 # ifdef PC 457 /* 458 * force these to be doubles for the divide 459 */ 460 p = rvalue( r[ 2 ] , NIL , RREQ ); 461 if ( isnta( p , "d" ) ) { 462 putop( P2SCONV , P2DOUBLE ); 463 } 464 p1 = rvalue( r[ 3 ] , NIL , RREQ ); 465 if ( isnta( p1 , "d" ) ) { 466 putop( P2SCONV , P2DOUBLE ); 467 } 468 # endif PC 469 if (p == NIL || p1 == NIL) 470 return (NIL); 471 if (isnta(p, "id")) { 472 error("Left operand of / must be integer or real, not %s", nameof(p)); 473 return (NIL); 474 } 475 if (isnta(p1, "id")) { 476 error("Right operand of / must be integer or real, not %s", nameof(p1)); 477 return (NIL); 478 } 479 # ifdef OBJ 480 return gen(NIL, r[0], width(p), width(p1)); 481 # endif OBJ 482 # ifdef PC 483 putop( P2DIV , P2DOUBLE ); 484 return nl + TDOUBLE; 485 # endif PC 486 487 case T_MULT: 488 case T_ADD: 489 case T_SUB: 490 # ifdef OBJ 491 /* 492 * If the context hasn't told us the type 493 * and a constant set is present 494 * we need to infer the type 495 * before generating code. 496 */ 497 if ( contype == NIL ) { 498 codeoff(); 499 contype = rvalue( r[3] , NIL , RREQ ); 500 codeon(); 501 if ( contype == lookup( intset ) -> type ) { 502 codeoff(); 503 contype = rvalue( r[2] , NIL , RREQ ); 504 codeon(); 505 } 506 } 507 if ( contype == NIL ) { 508 return NIL; 509 } 510 p = rvalue( r[2] , contype , RREQ ); 511 p1 = rvalue( r[3] , p , RREQ ); 512 if ( p == NIL || p1 == NIL ) 513 return NIL; 514 if (isa(p, "id") && isa(p1, "id")) 515 return (gen(NIL, r[0], width(p), width(p1))); 516 if (isa(p, "t") && isa(p1, "t")) { 517 if (p != p1) { 518 error("Set types of operands of %s must be identical", opname); 519 return (NIL); 520 } 521 gen(TSET, r[0], width(p), 0); 522 return (p); 523 } 524 # endif OBJ 525 # ifdef PC 526 /* 527 * the second pass can't do 528 * long op double or double op long 529 * so we have to know the type of both operands 530 * also, it gets tricky for sets, which are done 531 * by function calls. 532 */ 533 codeoff(); 534 p1 = rvalue( r[ 3 ] , contype , RREQ ); 535 codeon(); 536 if ( isa( p1 , "id" ) ) { 537 p = rvalue( r[ 2 ] , contype , RREQ ); 538 if ( ( p == NIL ) || ( p1 == NIL ) ) { 539 return NIL; 540 } 541 if ( isa( p , "i" ) && isa( p1 , "d" ) ) { 542 putop( P2SCONV , P2DOUBLE ); 543 } 544 p1 = rvalue( r[ 3 ] , contype , RREQ ); 545 if ( isa( p , "d" ) && isa( p1 , "i" ) ) { 546 putop( P2SCONV , P2DOUBLE ); 547 } 548 if ( isa( p , "id" ) ) { 549 if ( isa( p , "d" ) || isa( p1 , "d" ) ) { 550 ctype = P2DOUBLE; 551 rettype = nl + TDOUBLE; 552 } else { 553 ctype = P2INT; 554 rettype = nl + T4INT; 555 } 556 putop( mathop[ r[0] - T_MULT ] , ctype ); 557 return rettype; 558 } 559 } 560 if ( isa( p1 , "t" ) ) { 561 putleaf( P2ICON , 0 , 0 562 , ADDTYPE( ADDTYPE( P2PTR | P2STRTY , P2FTN ) 563 , P2PTR ) 564 , setop[ r[0] - T_MULT ] ); 565 if ( contype == NIL ) { 566 contype = p1; 567 if ( contype == lookup( intset ) -> type ) { 568 codeoff(); 569 contype = rvalue( r[2] , NIL , LREQ ); 570 codeon(); 571 } 572 } 573 if ( contype == NIL ) { 574 return NIL; 575 } 576 /* 577 * allocate a temporary and use it 578 */ 579 sizes[ cbn ].om_off -= lwidth( contype ); 580 tempoff = sizes[ cbn ].om_off; 581 putlbracket( ftnno , -tempoff ); 582 if ( tempoff < sizes[ cbn ].om_max ) { 583 sizes[ cbn ].om_max = tempoff; 584 } 585 putLV( 0 , cbn , tempoff , P2PTR|P2STRTY ); 586 p = rvalue( r[2] , contype , LREQ ); 587 if ( isa( p , "t" ) ) { 588 putop( P2LISTOP , P2INT ); 589 if ( p == NIL || p1 == NIL ) { 590 return NIL; 591 } 592 p1 = rvalue( r[3] , p , LREQ ); 593 if ( p != p1 ) { 594 error("Set types of operands of %s must be identical", opname); 595 return NIL; 596 } 597 putop( P2LISTOP , P2INT ); 598 putleaf( P2ICON , lwidth( p1 ) / sizeof( long ) , 0 599 , P2INT , 0 ); 600 putop( P2LISTOP , P2INT ); 601 putop( P2CALL , P2PTR | P2STRTY ); 602 return p; 603 } 604 } 605 if ( isnta( p1 , "idt" ) ) { 606 /* 607 * find type of left operand for error message. 608 */ 609 p = rvalue( r[2] , contype , RREQ ); 610 } 611 /* 612 * don't give spurious error messages. 613 */ 614 if ( p == NIL || p1 == NIL ) { 615 return NIL; 616 } 617 # endif PC 618 if (isnta(p, "idt")) { 619 error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p)); 620 return (NIL); 621 } 622 if (isnta(p1, "idt")) { 623 error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1)); 624 return (NIL); 625 } 626 error("Cannot mix sets with integers and reals as operands of %s", opname); 627 return (NIL); 628 629 case T_MOD: 630 case T_DIV: 631 p = rvalue(r[2], NIL , RREQ ); 632 p1 = rvalue(r[3], NIL , RREQ ); 633 if (p == NIL || p1 == NIL) 634 return (NIL); 635 if (isnta(p, "i")) { 636 error("Left operand of %s must be integer, not %s", opname, nameof(p)); 637 return (NIL); 638 } 639 if (isnta(p1, "i")) { 640 error("Right operand of %s must be integer, not %s", opname, nameof(p1)); 641 return (NIL); 642 } 643 # ifdef OBJ 644 return (gen(NIL, r[0], width(p), width(p1))); 645 # endif OBJ 646 # ifdef PC 647 putop( r[ 0 ] == T_DIV ? P2DIV : P2MOD , P2INT ); 648 return ( nl + T4INT ); 649 # endif PC 650 651 case T_EQ: 652 case T_NE: 653 case T_LT: 654 case T_GT: 655 case T_LE: 656 case T_GE: 657 /* 658 * Since there can be no, a priori, knowledge 659 * of the context type should a constant string 660 * or set arise, we must poke around to find such 661 * a type if possible. Since constant strings can 662 * always masquerade as identifiers, this is always 663 * necessary. 664 */ 665 codeoff(); 666 p1 = rvalue(r[3], NIL , RREQ ); 667 codeon(); 668 if (p1 == NIL) 669 return (NIL); 670 contype = p1; 671 # ifdef OBJ 672 if (p1->class == STR) { 673 /* 674 * For constant strings we want 675 * the longest type so as to be 676 * able to do padding (more importantly 677 * avoiding truncation). For clarity, 678 * we get this length here. 679 */ 680 codeoff(); 681 p = rvalue(r[2], NIL , RREQ ); 682 codeon(); 683 if (p == NIL) 684 return (NIL); 685 if (width(p) > width(p1)) 686 contype = p; 687 } else if ( isa( p1 , "t" ) ) { 688 if ( contype == lookup( intset ) -> type ) { 689 codeoff(); 690 contype = rvalue( r[2] , NIL , RREQ ); 691 codeon(); 692 if ( contype == NIL ) { 693 return NIL; 694 } 695 } 696 } 697 /* 698 * Now we generate code for 699 * the operands of the relational 700 * operation. 701 */ 702 p = rvalue(r[2], contype , RREQ ); 703 if (p == NIL) 704 return (NIL); 705 p1 = rvalue(r[3], p , RREQ ); 706 if (p1 == NIL) 707 return (NIL); 708 # endif OBJ 709 # ifdef PC 710 c1 = classify( p1 ); 711 if ( c1 == TSET || c1 == TSTR || c1 == TREC ) { 712 putleaf( P2ICON , 0 , 0 713 , ADDTYPE( P2FTN | P2INT , P2PTR ) 714 , c1 == TSET ? relts[ r[0] - T_EQ ] 715 : relss[ r[0] - T_EQ ] ); 716 /* 717 * for [] and strings, comparisons are done on 718 * the maximum width of the two sides. 719 * for other sets, we have to ask the left side 720 * what type it is based on the type of the right. 721 * (this matters for intsets). 722 */ 723 if ( c1 == TSTR ) { 724 codeoff(); 725 p = rvalue( r[ 2 ] , NIL , LREQ ); 726 codeon(); 727 if ( p == NIL ) { 728 return NIL; 729 } 730 if ( lwidth( p ) > lwidth( p1 ) ) { 731 contype = p; 732 } 733 } else if ( c1 == TSET ) { 734 if ( contype == lookup( intset ) -> type ) { 735 codeoff(); 736 p = rvalue( r[ 2 ] , NIL , LREQ ); 737 codeon(); 738 if ( p == NIL ) { 739 return NIL; 740 } 741 contype = p; 742 } 743 } 744 /* 745 * put out the width of the comparison. 746 */ 747 putleaf( P2ICON , lwidth( contype ) , 0 , P2INT , 0 ); 748 /* 749 * and the left hand side, 750 * for sets, strings, records 751 */ 752 p = rvalue( r[ 2 ] , contype , LREQ ); 753 putop( P2LISTOP , P2INT ); 754 p1 = rvalue( r[ 3 ] , p , LREQ ); 755 putop( P2LISTOP , P2INT ); 756 putop( P2CALL , P2INT ); 757 } else { 758 /* 759 * the easy (scalar or error) case 760 */ 761 p = rvalue( r[ 2 ] , contype , RREQ ); 762 if ( p == NIL ) { 763 return NIL; 764 } 765 /* 766 * since the second pass can't do 767 * long op double or double op long 768 * we may have to do some coercing. 769 */ 770 if ( isa( p , "i" ) && isa( p1 , "d" ) ) { 771 putop( P2SCONV , P2DOUBLE ); 772 } 773 p1 = rvalue( r[ 3 ] , p , RREQ ); 774 if ( isa( p , "d" ) && isa( p1 , "i" ) ) 775 putop( P2SCONV , P2DOUBLE ); 776 putop( relops[ r[0] - T_EQ ] , P2INT ); 777 } 778 # endif PC 779 c = classify(p); 780 c1 = classify(p1); 781 if (nocomp(c) || nocomp(c1)) 782 return (NIL); 783 g = NIL; 784 switch (c) { 785 case TBOOL: 786 case TCHAR: 787 if (c != c1) 788 goto clash; 789 break; 790 case TINT: 791 case TDOUBLE: 792 if (c1 != TINT && c1 != TDOUBLE) 793 goto clash; 794 break; 795 case TSCAL: 796 if (c1 != TSCAL) 797 goto clash; 798 if (scalar(p) != scalar(p1)) 799 goto nonident; 800 break; 801 case TSET: 802 if (c1 != TSET) 803 goto clash; 804 if (p != p1) 805 goto nonident; 806 g = TSET; 807 break; 808 case TREC: 809 if ( c1 != TREC ) { 810 goto clash; 811 } 812 if ( p != p1 ) { 813 goto nonident; 814 } 815 if (r[0] != T_EQ && r[0] != T_NE) { 816 error("%s not allowed on records - only allow = and <>" , opname ); 817 return (NIL); 818 } 819 g = TREC; 820 break; 821 case TPTR: 822 case TNIL: 823 if (c1 != TPTR && c1 != TNIL) 824 goto clash; 825 if (r[0] != T_EQ && r[0] != T_NE) { 826 error("%s not allowed on pointers - only allow = and <>" , opname ); 827 return (NIL); 828 } 829 break; 830 case TSTR: 831 if (c1 != TSTR) 832 goto clash; 833 if (width(p) != width(p1)) { 834 error("Strings not same length in %s comparison", opname); 835 return (NIL); 836 } 837 g = TSTR; 838 break; 839 default: 840 panic("rval2"); 841 } 842 # ifdef OBJ 843 return (gen(g, r[0], width(p), width(p1))); 844 # endif OBJ 845 # ifdef PC 846 return nl + TBOOL; 847 # endif PC 848 clash: 849 error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname); 850 return (NIL); 851 nonident: 852 error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname); 853 return (NIL); 854 855 case T_IN: 856 rt = r[3]; 857 # ifdef OBJ 858 if (rt != NIL && rt[0] == T_CSET) { 859 precset( rt , NIL , &csetd ); 860 p1 = csetd.csettype; 861 if (p1 == NIL) 862 return NIL; 863 postcset( rt, &csetd); 864 } else { 865 p1 = stkrval(r[3], NIL , RREQ ); 866 rt = NIL; 867 } 868 # endif OBJ 869 # ifdef PC 870 if (rt != NIL && rt[0] == T_CSET) { 871 if ( precset( rt , NIL , &csetd ) ) { 872 putleaf( P2ICON , 0 , 0 873 , ADDTYPE( P2FTN | P2INT , P2PTR ) 874 , "_IN" ); 875 } else { 876 putleaf( P2ICON , 0 , 0 877 , ADDTYPE( P2FTN | P2INT , P2PTR ) 878 , "_INCT" ); 879 } 880 p1 = csetd.csettype; 881 if (p1 == NIL) 882 return NIL; 883 } else { 884 putleaf( P2ICON , 0 , 0 885 , ADDTYPE( P2FTN | P2INT , P2PTR ) 886 , "_IN" ); 887 codeoff(); 888 p1 = rvalue(r[3], NIL , LREQ ); 889 codeon(); 890 } 891 # endif PC 892 p = stkrval(r[2], NIL , RREQ ); 893 if (p == NIL || p1 == NIL) 894 return (NIL); 895 if (p1->class != SET) { 896 error("Right operand of 'in' must be a set, not %s", nameof(p1)); 897 return (NIL); 898 } 899 if (incompat(p, p1->type, r[2])) { 900 cerror("Index type clashed with set component type for 'in'"); 901 return (NIL); 902 } 903 setran(p1->type); 904 # ifdef OBJ 905 if (rt == NIL || csetd.comptime) 906 put(4, O_IN, width(p1), set.lwrb, set.uprbp); 907 else 908 put(2, O_INCT, 3 + csetd.singcnt + 2*csetd.paircnt); 909 # endif OBJ 910 # ifdef PC 911 if ( rt == NIL || rt[0] != T_CSET ) { 912 putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 ); 913 putop( P2LISTOP , P2INT ); 914 putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 ); 915 putop( P2LISTOP , P2INT ); 916 p1 = rvalue( r[3] , NIL , LREQ ); 917 putop( P2LISTOP , P2INT ); 918 } else if ( csetd.comptime ) { 919 putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 ); 920 putop( P2LISTOP , P2INT ); 921 putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 ); 922 putop( P2LISTOP , P2INT ); 923 postcset( r[3] , &csetd ); 924 putop( P2LISTOP , P2INT ); 925 } else { 926 postcset( r[3] , &csetd ); 927 } 928 putop( P2CALL , P2INT ); 929 # endif PC 930 return (nl+T1BOOL); 931 default: 932 if (r[2] == NIL) 933 return (NIL); 934 switch (r[0]) { 935 default: 936 panic("rval3"); 937 938 939 /* 940 * An octal number 941 */ 942 case T_BINT: 943 f = a8tol(r[2]); 944 goto conint; 945 946 /* 947 * A decimal number 948 */ 949 case T_INT: 950 f = atof(r[2]); 951 conint: 952 if (f > MAXINT || f < MININT) { 953 error("Constant too large for this implementation"); 954 return (NIL); 955 } 956 l = f; 957 if (bytes(l, l) <= 2) { 958 # ifdef OBJ 959 put(2, O_CON2, ( short ) l); 960 # endif OBJ 961 # ifdef PC 962 /* 963 * short constants are ints 964 */ 965 putleaf( P2ICON , l , 0 , P2INT , 0 ); 966 # endif PC 967 return (nl+T2INT); 968 } 969 # ifdef OBJ 970 put(2, O_CON4, l); 971 # endif OBJ 972 # ifdef PC 973 putleaf( P2ICON , l , 0 , P2INT , 0 ); 974 # endif PC 975 return (nl+T4INT); 976 977 /* 978 * A floating point number 979 */ 980 case T_FINT: 981 # ifdef OBJ 982 put(2, O_CON8, atof(r[2])); 983 # endif OBJ 984 # ifdef PC 985 putCON8( atof( r[2] ) ); 986 # endif PC 987 return (nl+TDOUBLE); 988 989 /* 990 * Constant strings. Note that constant characters 991 * are constant strings of length one; there is 992 * no constant string of length one. 993 */ 994 case T_STRNG: 995 cp = r[2]; 996 if (cp[1] == 0) { 997 # ifdef OBJ 998 put(2, O_CONC, cp[0]); 999 # endif OBJ 1000 # ifdef PC 1001 putleaf( P2ICON , cp[0] , 0 , P2CHAR , 0 ); 1002 # endif PC 1003 return (nl+T1CHAR); 1004 } 1005 goto cstrng; 1006 } 1007 1008 } 1009 } 1010 1011 /* 1012 * Can a class appear 1013 * in a comparison ? 1014 */ 1015 nocomp(c) 1016 int c; 1017 { 1018 1019 switch (c) { 1020 case TREC: 1021 if ( line != reccompline ) { 1022 reccompline = line; 1023 warning(); 1024 if ( opt( 's' ) ) { 1025 standard(); 1026 } 1027 error("record comparison is non-standard"); 1028 } 1029 break; 1030 case TFILE: 1031 case TARY: 1032 error("%ss may not participate in comparisons", clnames[c]); 1033 return (1); 1034 } 1035 return (NIL); 1036 } 1037 1038 /* 1039 * this is sort of like gconst, except it works on expression trees 1040 * rather than declaration trees, and doesn't give error messages for 1041 * non-constant things. 1042 * as a side effect this fills in the con structure that gconst uses. 1043 * this returns TRUE or FALSE. 1044 */ 1045 constval(r) 1046 register int *r; 1047 { 1048 register struct nl *np; 1049 register *cn; 1050 char *cp; 1051 int negd, sgnd; 1052 long ci; 1053 1054 con.ctype = NIL; 1055 cn = r; 1056 negd = sgnd = 0; 1057 loop: 1058 /* 1059 * cn[2] is nil if error recovery generated a T_STRNG 1060 */ 1061 if (cn == NIL || cn[2] == NIL) 1062 return FALSE; 1063 switch (cn[0]) { 1064 default: 1065 return FALSE; 1066 case T_MINUS: 1067 negd = 1 - negd; 1068 /* and fall through */ 1069 case T_PLUS: 1070 sgnd++; 1071 cn = cn[2]; 1072 goto loop; 1073 case T_NIL: 1074 con.cpval = NIL; 1075 con.cival = 0; 1076 con.crval = con.cival; 1077 con.ctype = nl + TNIL; 1078 break; 1079 case T_VAR: 1080 np = lookup(cn[2]); 1081 if (np == NIL || np->class != CONST) { 1082 return FALSE; 1083 } 1084 if ( cn[3] != NIL ) { 1085 return FALSE; 1086 } 1087 con.ctype = np->type; 1088 switch (classify(np->type)) { 1089 case TINT: 1090 con.crval = np->range[0]; 1091 break; 1092 case TDOUBLE: 1093 con.crval = np->real; 1094 break; 1095 case TBOOL: 1096 case TCHAR: 1097 case TSCAL: 1098 con.cival = np->value[0]; 1099 con.crval = con.cival; 1100 break; 1101 case TSTR: 1102 con.cpval = np->ptr[0]; 1103 break; 1104 default: 1105 con.ctype = NIL; 1106 return FALSE; 1107 } 1108 break; 1109 case T_BINT: 1110 con.crval = a8tol(cn[2]); 1111 goto restcon; 1112 case T_INT: 1113 con.crval = atof(cn[2]); 1114 if (con.crval > MAXINT || con.crval < MININT) { 1115 derror("Constant too large for this implementation"); 1116 con.crval = 0; 1117 } 1118 restcon: 1119 ci = con.crval; 1120 #ifndef PI0 1121 if (bytes(ci, ci) <= 2) 1122 con.ctype = nl+T2INT; 1123 else 1124 #endif 1125 con.ctype = nl+T4INT; 1126 break; 1127 case T_FINT: 1128 con.ctype = nl+TDOUBLE; 1129 con.crval = atof(cn[2]); 1130 break; 1131 case T_STRNG: 1132 cp = cn[2]; 1133 if (cp[1] == 0) { 1134 con.ctype = nl+T1CHAR; 1135 con.cival = cp[0]; 1136 con.crval = con.cival; 1137 break; 1138 } 1139 con.ctype = nl+TSTR; 1140 con.cpval = cp; 1141 break; 1142 } 1143 if (sgnd) { 1144 if (isnta(con.ctype, "id")) { 1145 derror("%s constants cannot be signed", nameof(con.ctype)); 1146 return FALSE; 1147 } else if (negd) 1148 con.crval = -con.crval; 1149 } 1150 return TRUE; 1151 } 1152