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