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