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