1771Speter /* Copyright (c) 1979 Regents of the University of California */ 2771Speter 3*15931Smckusick ifndef lint 4*15931Smckusick static char sccsid[] = "@(#)rval.c 1.16.1.1 02/04/84"; 5*15931Smckusick #endif 6771Speter 7771Speter #include "whoami.h" 8771Speter #include "0.h" 9771Speter #include "tree.h" 10771Speter #include "opcode.h" 11771Speter #include "objfmt.h" 12771Speter #ifdef PC 13771Speter # include "pc.h" 14771Speter # include "pcops.h" 15771Speter #endif PC 1611328Speter #include "tmps.h" 17*15931Smckusick #include "tree_ty.h" 18771Speter 19771Speter extern char *opnames[]; 20771Speter 211627Speter /* line number of the last record comparison warning */ 221627Speter short reccompline = 0; 233397Speter /* line number of the last non-standard set comparison */ 243397Speter short nssetline = 0; 251627Speter 26771Speter #ifdef PC 27771Speter char *relts[] = { 28771Speter "_RELEQ" , "_RELNE" , 29771Speter "_RELTLT" , "_RELTGT" , 30771Speter "_RELTLE" , "_RELTGE" 31771Speter }; 32771Speter char *relss[] = { 33771Speter "_RELEQ" , "_RELNE" , 34771Speter "_RELSLT" , "_RELSGT" , 35771Speter "_RELSLE" , "_RELSGE" 36771Speter }; 37771Speter long relops[] = { 38771Speter P2EQ , P2NE , 39771Speter P2LT , P2GT , 40771Speter P2LE , P2GE 41771Speter }; 42771Speter long mathop[] = { P2MUL , P2PLUS , P2MINUS }; 43771Speter char *setop[] = { "_MULT" , "_ADDT" , "_SUBT" }; 44771Speter #endif PC 45771Speter /* 46771Speter * Rvalue - an expression. 47771Speter * 48771Speter * Contype is the type that the caller would prefer, nand is important 49771Speter * if constant sets or constant strings are involved, the latter 50771Speter * because of string padding. 51771Speter * required is a flag whether an lvalue or an rvalue is required. 52771Speter * only VARs and structured things can have gt their lvalue this way. 53771Speter */ 54*15931Smckusick /*ARGSUSED*/ 55771Speter struct nl * 56771Speter rvalue(r, contype , required ) 57*15931Smckusick struct tnode *r; 58771Speter struct nl *contype; 59771Speter int required; 60771Speter { 61771Speter register struct nl *p, *p1; 62771Speter register struct nl *q; 63*15931Smckusick int c, c1, w; 64*15931Smckusick #ifdef OBJ 65*15931Smckusick int g; 66*15931Smckusick #endif 67*15931Smckusick struct tnode *rt; 68771Speter char *cp, *cp1, *opname; 69771Speter long l; 70*15931Smckusick union 71*15931Smckusick { 72*15931Smckusick long plong[2]; 73*15931Smckusick double pdouble; 74*15931Smckusick }f; 75771Speter extern int flagwas; 76771Speter struct csetstr csetd; 77771Speter # ifdef PC 78771Speter struct nl *rettype; 79771Speter long ctype; 803834Speter struct nl *tempnlp; 81771Speter # endif PC 82771Speter 83*15931Smckusick if (r == TR_NIL) 84*15931Smckusick return (NLNIL); 85771Speter if (nowexp(r)) 86*15931Smckusick return (NLNIL); 87771Speter /* 88771Speter * Pick up the name of the operation 89771Speter * for future error messages. 90771Speter */ 91*15931Smckusick if (r->tag <= T_IN) 92*15931Smckusick opname = opnames[r->tag]; 93771Speter 94771Speter /* 95771Speter * The root of the tree tells us what sort of expression we have. 96771Speter */ 97*15931Smckusick switch (r->tag) { 98771Speter 99771Speter /* 100771Speter * The constant nil 101771Speter */ 102771Speter case T_NIL: 103771Speter # ifdef OBJ 104*15931Smckusick (void) put(2, O_CON2, 0); 105771Speter # endif OBJ 106771Speter # ifdef PC 107*15931Smckusick putleaf( P2ICON , 0 , 0 , P2PTR|P2UNDEF , (char *) 0 ); 108771Speter # endif PC 109771Speter return (nl+TNIL); 110771Speter 111771Speter /* 112771Speter * Function call with arguments. 113771Speter */ 114771Speter case T_FCALL: 115771Speter # ifdef OBJ 116771Speter return (funccod(r)); 117771Speter # endif OBJ 118771Speter # ifdef PC 119771Speter return (pcfunccod( r )); 120771Speter # endif PC 121771Speter 122771Speter case T_VAR: 123*15931Smckusick p = lookup(r->var_node.cptr); 124*15931Smckusick if (p == NLNIL || p->class == BADUSE) 125*15931Smckusick return (NLNIL); 126771Speter switch (p->class) { 127771Speter case VAR: 128771Speter /* 129771Speter * If a variable is 130771Speter * qualified then get 131771Speter * the rvalue by a 132771Speter * lvalue and an ind. 133771Speter */ 134*15931Smckusick if (r->var_node.qual != TR_NIL) 135771Speter goto ind; 136771Speter q = p->type; 137771Speter if (q == NIL) 138*15931Smckusick return (NLNIL); 139771Speter # ifdef OBJ 140771Speter w = width(q); 141771Speter switch (w) { 142771Speter case 8: 143*15931Smckusick (void) put(2, O_RV8 | bn << 8+INDX, 1443078Smckusic (int)p->value[0]); 145771Speter break; 146771Speter case 4: 147*15931Smckusick (void) put(2, O_RV4 | bn << 8+INDX, 1483078Smckusic (int)p->value[0]); 149771Speter break; 150771Speter case 2: 151*15931Smckusick (void) put(2, O_RV2 | bn << 8+INDX, 1523078Smckusic (int)p->value[0]); 153771Speter break; 154771Speter case 1: 155*15931Smckusick (void) put(2, O_RV1 | bn << 8+INDX, 1563078Smckusic (int)p->value[0]); 157771Speter break; 158771Speter default: 159*15931Smckusick (void) put(3, O_RV | bn << 8+INDX, 1603078Smckusic (int)p->value[0], w); 161771Speter } 162771Speter # endif OBJ 163771Speter # ifdef PC 164771Speter if ( required == RREQ ) { 1653834Speter putRV( p -> symbol , bn , p -> value[0] , 1663834Speter p -> extra_flags , p2type( q ) ); 167771Speter } else { 1683834Speter putLV( p -> symbol , bn , p -> value[0] , 1693834Speter p -> extra_flags , p2type( q ) ); 170771Speter } 171771Speter # endif PC 172771Speter return (q); 173771Speter 174771Speter case WITHPTR: 175771Speter case REF: 176771Speter /* 177771Speter * A lvalue for these 178771Speter * is actually what one 179771Speter * might consider a rvalue. 180771Speter */ 181771Speter ind: 182771Speter q = lvalue(r, NOFLAGS , LREQ ); 183771Speter if (q == NIL) 184*15931Smckusick return (NLNIL); 185771Speter # ifdef OBJ 186771Speter w = width(q); 187771Speter switch (w) { 188771Speter case 8: 189*15931Smckusick (void) put(1, O_IND8); 190771Speter break; 191771Speter case 4: 192*15931Smckusick (void) put(1, O_IND4); 193771Speter break; 194771Speter case 2: 195*15931Smckusick (void) put(1, O_IND2); 196771Speter break; 197771Speter case 1: 198*15931Smckusick (void) put(1, O_IND1); 199771Speter break; 200771Speter default: 201*15931Smckusick (void) put(2, O_IND, w); 202771Speter } 203771Speter # endif OBJ 204771Speter # ifdef PC 205771Speter if ( required == RREQ ) { 206771Speter putop( P2UNARY P2MUL , p2type( q ) ); 207771Speter } 208771Speter # endif PC 209771Speter return (q); 210771Speter 211771Speter case CONST: 212*15931Smckusick if (r->var_node.qual != TR_NIL) { 213*15931Smckusick error("%s is a constant and cannot be qualified", r->var_node.cptr); 214*15931Smckusick return (NLNIL); 215771Speter } 216771Speter q = p->type; 217*15931Smckusick if (q == NLNIL) 218*15931Smckusick return (NLNIL); 219771Speter if (q == nl+TSTR) { 220771Speter /* 221771Speter * Find the size of the string 222771Speter * constant if needed. 223771Speter */ 224*15931Smckusick cp = (char *) p->ptr[0]; 225771Speter cstrng: 226771Speter cp1 = cp; 227771Speter for (c = 0; *cp++; c++) 228771Speter continue; 2293078Smckusic w = c; 230771Speter if (contype != NIL && !opt('s')) { 231771Speter if (width(contype) < c && classify(contype) == TSTR) { 232771Speter error("Constant string too long"); 233*15931Smckusick return (NLNIL); 234771Speter } 2353078Smckusic w = width(contype); 236771Speter } 237771Speter # ifdef OBJ 238*15931Smckusick (void) put(2, O_CONG, w); 2393078Smckusic putstr(cp1, w - c); 240771Speter # endif OBJ 241771Speter # ifdef PC 2423155Smckusic putCONG( cp1 , w , required ); 243771Speter # endif PC 244771Speter /* 245771Speter * Define the string temporarily 246771Speter * so later people can know its 247771Speter * width. 248771Speter * cleaned out by stat. 249771Speter */ 250*15931Smckusick q = defnl((char *) 0, STR, NLNIL, w); 251771Speter q->type = q; 252771Speter return (q); 253771Speter } 254771Speter if (q == nl+T1CHAR) { 255771Speter # ifdef OBJ 256*15931Smckusick (void) put(2, O_CONC, (int)p->value[0]); 257771Speter # endif OBJ 258771Speter # ifdef PC 259771Speter putleaf( P2ICON , p -> value[0] , 0 260*15931Smckusick , P2CHAR , (char *) 0 ); 261771Speter # endif PC 262771Speter return (q); 263771Speter } 264771Speter /* 265771Speter * Every other kind of constant here 266771Speter */ 267771Speter switch (width(q)) { 268771Speter case 8: 269771Speter #ifndef DEBUG 270771Speter # ifdef OBJ 271*15931Smckusick (void) put(2, O_CON8, p->real); 272771Speter # endif OBJ 273771Speter # ifdef PC 274771Speter putCON8( p -> real ); 275771Speter # endif PC 276771Speter #else 277771Speter if (hp21mx) { 278*15931Smckusick f.pdouble = p->real; 279*15931Smckusick conv((int *) (&f.pdouble)); 280*15931Smckusick l = f.plong[1]; 281*15931Smckusick (void) put(2, O_CON4, l); 282771Speter } else 283771Speter # ifdef OBJ 284*15931Smckusick (void) put(2, O_CON8, p->real); 285771Speter # endif OBJ 286771Speter # ifdef PC 287771Speter putCON8( p -> real ); 288771Speter # endif PC 289771Speter #endif 290771Speter break; 291771Speter case 4: 292771Speter # ifdef OBJ 293*15931Smckusick (void) put(2, O_CON4, p->range[0]); 294771Speter # endif OBJ 295771Speter # ifdef PC 296*15931Smckusick putleaf( P2ICON , (int) p->range[0] , 0 297*15931Smckusick , P2INT , (char *) 0 ); 298771Speter # endif PC 299771Speter break; 300771Speter case 2: 301771Speter # ifdef OBJ 302*15931Smckusick (void) put(2, O_CON2, (short)p->range[0]); 303771Speter # endif OBJ 304771Speter # ifdef PC 305771Speter putleaf( P2ICON , (short) p -> range[0] 306*15931Smckusick , 0 , P2SHORT , (char *) 0 ); 307771Speter # endif PC 308771Speter break; 309771Speter case 1: 310771Speter # ifdef OBJ 311*15931Smckusick (void) put(2, O_CON1, p->value[0]); 312771Speter # endif OBJ 313771Speter # ifdef PC 314771Speter putleaf( P2ICON , p -> value[0] , 0 315*15931Smckusick , P2CHAR , (char *) 0 ); 316771Speter # endif PC 317771Speter break; 318771Speter default: 319771Speter panic("rval"); 320771Speter } 321771Speter return (q); 322771Speter 323771Speter case FUNC: 3241200Speter case FFUNC: 325771Speter /* 326771Speter * Function call with no arguments. 327771Speter */ 328*15931Smckusick if (r->var_node.qual != TR_NIL) { 329771Speter error("Can't qualify a function result value"); 330*15931Smckusick return (NLNIL); 331771Speter } 332771Speter # ifdef OBJ 333*15931Smckusick return (funccod(r)); 334771Speter # endif OBJ 335771Speter # ifdef PC 336771Speter return (pcfunccod( r )); 337771Speter # endif PC 338771Speter 339771Speter case TYPE: 340771Speter error("Type names (e.g. %s) allowed only in declarations", p->symbol); 341*15931Smckusick return (NLNIL); 342771Speter 343771Speter case PROC: 3441200Speter case FPROC: 345771Speter error("Procedure %s found where expression required", p->symbol); 346*15931Smckusick return (NLNIL); 347771Speter default: 348771Speter panic("rvid"); 349771Speter } 350771Speter /* 351771Speter * Constant sets 352771Speter */ 353771Speter case T_CSET: 354771Speter # ifdef OBJ 355771Speter if ( precset( r , contype , &csetd ) ) { 356771Speter if ( csetd.csettype == NIL ) { 357*15931Smckusick return (NLNIL); 358771Speter } 359771Speter postcset( r , &csetd ); 360771Speter } else { 361*15931Smckusick (void) put( 2, O_PUSH, -lwidth(csetd.csettype)); 362771Speter postcset( r , &csetd ); 363771Speter setran( ( csetd.csettype ) -> type ); 364*15931Smckusick (void) put( 2, O_CON24, set.uprbp); 365*15931Smckusick (void) put( 2, O_CON24, set.lwrb); 366*15931Smckusick (void) put( 2, O_CTTOT, 3673078Smckusic (int)(4 + csetd.singcnt + 2 * csetd.paircnt)); 368771Speter } 369771Speter return csetd.csettype; 370771Speter # endif OBJ 371771Speter # ifdef PC 372771Speter if ( precset( r , contype , &csetd ) ) { 373771Speter if ( csetd.csettype == NIL ) { 374*15931Smckusick return (NLNIL); 375771Speter } 376771Speter postcset( r , &csetd ); 377771Speter } else { 378771Speter putleaf( P2ICON , 0 , 0 379771Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 380771Speter , "_CTTOT" ); 381771Speter /* 382771Speter * allocate a temporary and use it 383771Speter */ 3843834Speter tempnlp = tmpalloc(lwidth(csetd.csettype), 3853227Smckusic csetd.csettype, NOREG); 386*15931Smckusick putLV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 3873834Speter tempnlp -> extra_flags , P2PTR|P2STRTY ); 388771Speter setran( ( csetd.csettype ) -> type ); 389*15931Smckusick putleaf( P2ICON , set.lwrb , 0 , P2INT , (char *) 0 ); 390771Speter putop( P2LISTOP , P2INT ); 391*15931Smckusick putleaf( P2ICON , set.uprbp , 0 , P2INT , (char *) 0 ); 392771Speter putop( P2LISTOP , P2INT ); 393771Speter postcset( r , &csetd ); 394771Speter putop( P2CALL , P2INT ); 395771Speter } 396771Speter return csetd.csettype; 397771Speter # endif PC 398771Speter 399771Speter /* 400771Speter * Unary plus and minus 401771Speter */ 402771Speter case T_PLUS: 403771Speter case T_MINUS: 404*15931Smckusick q = rvalue(r->un_expr.expr, NLNIL , RREQ ); 405*15931Smckusick if (q == NLNIL) 406*15931Smckusick return (NLNIL); 407771Speter if (isnta(q, "id")) { 408771Speter error("Operand of %s must be integer or real, not %s", opname, nameof(q)); 409*15931Smckusick return (NLNIL); 410771Speter } 411*15931Smckusick if (r->tag == T_MINUS) { 412771Speter # ifdef OBJ 413*15931Smckusick (void) put(1, O_NEG2 + (width(q) >> 2)); 41410670Speter return (isa(q, "d") ? q : nl+T4INT); 415771Speter # endif OBJ 416771Speter # ifdef PC 41710670Speter if (isa(q, "i")) { 41810670Speter sconv(p2type(q), P2INT); 41910670Speter putop( P2UNARY P2MINUS, P2INT); 42010670Speter return nl+T4INT; 42110670Speter } 42210670Speter putop( P2UNARY P2MINUS, P2DOUBLE); 42310670Speter return nl+TDOUBLE; 424771Speter # endif PC 425771Speter } 426771Speter return (q); 427771Speter 428771Speter case T_NOT: 429*15931Smckusick q = rvalue(r->un_expr.expr, NLNIL , RREQ ); 430*15931Smckusick if (q == NLNIL) 431*15931Smckusick return (NLNIL); 432771Speter if (isnta(q, "b")) { 433771Speter error("not must operate on a Boolean, not %s", nameof(q)); 434*15931Smckusick return (NLNIL); 435771Speter } 436771Speter # ifdef OBJ 437*15931Smckusick (void) put(1, O_NOT); 438771Speter # endif OBJ 439771Speter # ifdef PC 44010364Smckusick sconv(p2type(q), P2INT); 44110364Smckusick putop( P2NOT , P2INT); 44210364Smckusick sconv(P2INT, p2type(q)); 443771Speter # endif PC 444771Speter return (nl+T1BOOL); 445771Speter 446771Speter case T_AND: 447771Speter case T_OR: 448*15931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 44910364Smckusick # ifdef PC 45010364Smckusick sconv(p2type(p),P2INT); 45110364Smckusick # endif PC 452*15931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 45310364Smckusick # ifdef PC 45410364Smckusick sconv(p2type(p1),P2INT); 45510364Smckusick # endif PC 456*15931Smckusick if (p == NLNIL || p1 == NLNIL) 457*15931Smckusick return (NLNIL); 458771Speter if (isnta(p, "b")) { 459771Speter error("Left operand of %s must be Boolean, not %s", opname, nameof(p)); 460*15931Smckusick return (NLNIL); 461771Speter } 462771Speter if (isnta(p1, "b")) { 463771Speter error("Right operand of %s must be Boolean, not %s", opname, nameof(p1)); 464*15931Smckusick return (NLNIL); 465771Speter } 466771Speter # ifdef OBJ 467*15931Smckusick (void) put(1, r->tag == T_AND ? O_AND : O_OR); 468771Speter # endif OBJ 469771Speter # ifdef PC 470771Speter /* 471771Speter * note the use of & and | rather than && and || 472771Speter * to force evaluation of all the expressions. 473771Speter */ 474*15931Smckusick putop( r->tag == T_AND ? P2AND : P2OR , P2INT ); 47510364Smckusick sconv(P2INT, p2type(p)); 476771Speter # endif PC 477771Speter return (nl+T1BOOL); 478771Speter 479771Speter case T_DIVD: 480771Speter # ifdef OBJ 481*15931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 482*15931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 483771Speter # endif OBJ 484771Speter # ifdef PC 485771Speter /* 486771Speter * force these to be doubles for the divide 487771Speter */ 488*15931Smckusick p = rvalue( r->expr_node.lhs , NLNIL , RREQ ); 48910364Smckusick sconv(p2type(p), P2DOUBLE); 490*15931Smckusick p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ ); 49110364Smckusick sconv(p2type(p1), P2DOUBLE); 492771Speter # endif PC 493*15931Smckusick if (p == NLNIL || p1 == NLNIL) 494*15931Smckusick return (NLNIL); 495771Speter if (isnta(p, "id")) { 496771Speter error("Left operand of / must be integer or real, not %s", nameof(p)); 497*15931Smckusick return (NLNIL); 498771Speter } 499771Speter if (isnta(p1, "id")) { 500771Speter error("Right operand of / must be integer or real, not %s", nameof(p1)); 501*15931Smckusick return (NLNIL); 502771Speter } 503771Speter # ifdef OBJ 504*15931Smckusick return gen(NIL, r->tag, width(p), width(p1)); 505771Speter # endif OBJ 506771Speter # ifdef PC 507771Speter putop( P2DIV , P2DOUBLE ); 508771Speter return nl + TDOUBLE; 509771Speter # endif PC 510771Speter 511771Speter case T_MULT: 512771Speter case T_ADD: 513771Speter case T_SUB: 514771Speter # ifdef OBJ 515771Speter /* 5161555Speter * If the context hasn't told us the type 5171555Speter * and a constant set is present 5181555Speter * we need to infer the type 5191555Speter * before generating code. 520771Speter */ 5211555Speter if ( contype == NIL ) { 522771Speter codeoff(); 523*15931Smckusick contype = rvalue( r->expr_node.rhs , NLNIL , RREQ ); 524771Speter codeon(); 525*15931Smckusick if ( contype == lookup((char *) intset ) -> type ) { 526*15931Smckusick codeoff(); 527*15931Smckusick contype = rvalue( r->expr_node.lhs , NLNIL , 528*15931Smckusick RREQ ); 529*15931Smckusick codeon(); 530*15931Smckusick } 531771Speter } 5321555Speter if ( contype == NIL ) { 533*15931Smckusick return NLNIL; 5341555Speter } 535*15931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 536*15931Smckusick p1 = rvalue( r->expr_node.rhs , p , RREQ ); 5371555Speter if ( p == NIL || p1 == NIL ) 538*15931Smckusick return NLNIL; 539771Speter if (isa(p, "id") && isa(p1, "id")) 540*15931Smckusick return (gen(NIL, r->tag, width(p), width(p1))); 541771Speter if (isa(p, "t") && isa(p1, "t")) { 542771Speter if (p != p1) { 543771Speter error("Set types of operands of %s must be identical", opname); 544*15931Smckusick return (NLNIL); 545771Speter } 546*15931Smckusick (void) gen(TSET, r->tag, width(p), 0); 547771Speter return (p); 548771Speter } 549771Speter # endif OBJ 550771Speter # ifdef PC 551771Speter /* 552771Speter * the second pass can't do 553771Speter * long op double or double op long 554771Speter * so we have to know the type of both operands 555771Speter * also, it gets tricky for sets, which are done 556771Speter * by function calls. 557771Speter */ 558771Speter codeoff(); 559*15931Smckusick p1 = rvalue( r->expr_node.rhs , contype , RREQ ); 560771Speter codeon(); 561771Speter if ( isa( p1 , "id" ) ) { 562*15931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 563771Speter if ( ( p == NIL ) || ( p1 == NIL ) ) { 564*15931Smckusick return NLNIL; 565771Speter } 566*15931Smckusick tuac(p, p1, &rettype, (int *) (&ctype)); 567*15931Smckusick p1 = rvalue( r->expr_node.rhs , contype , RREQ ); 568*15931Smckusick tuac(p1, p, &rettype, (int *) (&ctype)); 569771Speter if ( isa( p , "id" ) ) { 570*15931Smckusick putop( (int) mathop[r->tag - T_MULT], (int) ctype); 571771Speter return rettype; 572771Speter } 573771Speter } 574771Speter if ( isa( p1 , "t" ) ) { 575771Speter putleaf( P2ICON , 0 , 0 576771Speter , ADDTYPE( ADDTYPE( P2PTR | P2STRTY , P2FTN ) 577771Speter , P2PTR ) 578*15931Smckusick , setop[ r->tag - T_MULT ] ); 5791555Speter if ( contype == NIL ) { 580*15931Smckusick contype = p1; 581*15931Smckusick if ( contype == lookup((char *) intset ) -> type ) { 582*15931Smckusick codeoff(); 583*15931Smckusick contype = rvalue( r->expr_node.lhs, NLNIL , 584*15931Smckusick LREQ ); 585*15931Smckusick codeon(); 586*15931Smckusick } 5871555Speter } 5881555Speter if ( contype == NIL ) { 589*15931Smckusick return NLNIL; 5901555Speter } 5911555Speter /* 5921555Speter * allocate a temporary and use it 5931555Speter */ 5943834Speter tempnlp = tmpalloc(lwidth(contype), contype, NOREG); 595*15931Smckusick putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 5963834Speter tempnlp -> extra_flags , P2PTR|P2STRTY ); 597*15931Smckusick p = rvalue( r->expr_node.lhs , contype , LREQ ); 598771Speter if ( isa( p , "t" ) ) { 599771Speter putop( P2LISTOP , P2INT ); 600771Speter if ( p == NIL || p1 == NIL ) { 601*15931Smckusick return NLNIL; 602771Speter } 603*15931Smckusick p1 = rvalue( r->expr_node.rhs , p , LREQ ); 604771Speter if ( p != p1 ) { 605771Speter error("Set types of operands of %s must be identical", opname); 606*15931Smckusick return NLNIL; 607771Speter } 608771Speter putop( P2LISTOP , P2INT ); 609*15931Smckusick putleaf( P2ICON , (int) (lwidth(p1)) / sizeof( long ) , 0 610*15931Smckusick , P2INT , (char *) 0 ); 611771Speter putop( P2LISTOP , P2INT ); 612771Speter putop( P2CALL , P2PTR | P2STRTY ); 613771Speter return p; 614771Speter } 615771Speter } 616771Speter if ( isnta( p1 , "idt" ) ) { 617771Speter /* 618771Speter * find type of left operand for error message. 619771Speter */ 620*15931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 621771Speter } 622771Speter /* 623771Speter * don't give spurious error messages. 624771Speter */ 625771Speter if ( p == NIL || p1 == NIL ) { 626*15931Smckusick return NLNIL; 627771Speter } 628771Speter # endif PC 629771Speter if (isnta(p, "idt")) { 630771Speter error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p)); 631*15931Smckusick return (NLNIL); 632771Speter } 633771Speter if (isnta(p1, "idt")) { 634771Speter error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1)); 635*15931Smckusick return (NLNIL); 636771Speter } 637771Speter error("Cannot mix sets with integers and reals as operands of %s", opname); 638*15931Smckusick return (NLNIL); 639771Speter 640771Speter case T_MOD: 641771Speter case T_DIV: 642*15931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 64310364Smckusick # ifdef PC 64410364Smckusick sconv(p2type(p), P2INT); 64510364Smckusick # endif PC 646*15931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 64710364Smckusick # ifdef PC 64810364Smckusick sconv(p2type(p1), P2INT); 64910364Smckusick # endif PC 650771Speter if (p == NIL || p1 == NIL) 651*15931Smckusick return (NLNIL); 652771Speter if (isnta(p, "i")) { 653771Speter error("Left operand of %s must be integer, not %s", opname, nameof(p)); 654*15931Smckusick return (NLNIL); 655771Speter } 656771Speter if (isnta(p1, "i")) { 657771Speter error("Right operand of %s must be integer, not %s", opname, nameof(p1)); 658*15931Smckusick return (NLNIL); 659771Speter } 660771Speter # ifdef OBJ 661*15931Smckusick return (gen(NIL, r->tag, width(p), width(p1))); 662771Speter # endif OBJ 663771Speter # ifdef PC 664*15931Smckusick putop( r->tag == T_DIV ? P2DIV : P2MOD , P2INT ); 665771Speter return ( nl + T4INT ); 666771Speter # endif PC 667771Speter 668771Speter case T_EQ: 669771Speter case T_NE: 670771Speter case T_LT: 671771Speter case T_GT: 672771Speter case T_LE: 673771Speter case T_GE: 674771Speter /* 675771Speter * Since there can be no, a priori, knowledge 676771Speter * of the context type should a constant string 677771Speter * or set arise, we must poke around to find such 678771Speter * a type if possible. Since constant strings can 679771Speter * always masquerade as identifiers, this is always 680771Speter * necessary. 681771Speter */ 682771Speter codeoff(); 683*15931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 684771Speter codeon(); 685*15931Smckusick if (p1 == NLNIL) 686*15931Smckusick return (NLNIL); 687771Speter contype = p1; 688771Speter # ifdef OBJ 6891555Speter if (p1->class == STR) { 690771Speter /* 691771Speter * For constant strings we want 692771Speter * the longest type so as to be 693771Speter * able to do padding (more importantly 694771Speter * avoiding truncation). For clarity, 695771Speter * we get this length here. 696771Speter */ 697771Speter codeoff(); 698*15931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 699771Speter codeon(); 700*15931Smckusick if (p == NLNIL) 701*15931Smckusick return (NLNIL); 7021555Speter if (width(p) > width(p1)) 703771Speter contype = p; 704*15931Smckusick } else if ( isa( p1 , "t" ) ) { 705*15931Smckusick if ( contype == lookup((char *) intset ) -> type ) { 706*15931Smckusick codeoff(); 707*15931Smckusick contype = rvalue( r->expr_node.lhs , NLNIL , RREQ ); 708*15931Smckusick codeon(); 709*15931Smckusick if ( contype == NIL ) { 710*15931Smckusick return NLNIL; 711*15931Smckusick } 712*15931Smckusick } 713771Speter } 714771Speter /* 715771Speter * Now we generate code for 716771Speter * the operands of the relational 717771Speter * operation. 718771Speter */ 719*15931Smckusick p = rvalue(r->expr_node.lhs, contype , RREQ ); 720*15931Smckusick if (p == NLNIL) 721*15931Smckusick return (NLNIL); 722*15931Smckusick p1 = rvalue(r->expr_node.rhs, p , RREQ ); 723*15931Smckusick if (p1 == NLNIL) 724*15931Smckusick return (NLNIL); 725771Speter # endif OBJ 726771Speter # ifdef PC 727771Speter c1 = classify( p1 ); 728771Speter if ( c1 == TSET || c1 == TSTR || c1 == TREC ) { 729771Speter putleaf( P2ICON , 0 , 0 730771Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 731*15931Smckusick , c1 == TSET ? relts[ r->tag - T_EQ ] 732*15931Smckusick : relss[ r->tag - T_EQ ] ); 733771Speter /* 734771Speter * for [] and strings, comparisons are done on 735771Speter * the maximum width of the two sides. 736771Speter * for other sets, we have to ask the left side 737771Speter * what type it is based on the type of the right. 738771Speter * (this matters for intsets). 739771Speter */ 7401555Speter if ( c1 == TSTR ) { 741771Speter codeoff(); 742*15931Smckusick p = rvalue( r->expr_node.lhs , NLNIL , LREQ ); 743771Speter codeon(); 744*15931Smckusick if ( p == NLNIL ) { 745*15931Smckusick return NLNIL; 7461555Speter } 7471555Speter if ( lwidth( p ) > lwidth( p1 ) ) { 748771Speter contype = p; 749771Speter } 7501555Speter } else if ( c1 == TSET ) { 751*15931Smckusick if ( contype == lookup((char *) intset ) -> type ) { 752*15931Smckusick codeoff(); 753*15931Smckusick p = rvalue( r->expr_node.lhs , NLNIL , LREQ ); 754*15931Smckusick codeon(); 755*15931Smckusick if ( p == NLNIL ) { 756*15931Smckusick return NLNIL; 757*15931Smckusick } 758*15931Smckusick contype = p; 7591555Speter } 7601627Speter } 761771Speter /* 762771Speter * put out the width of the comparison. 763771Speter */ 764*15931Smckusick putleaf(P2ICON, (int) lwidth(contype), 0, P2INT, (char *) 0); 765771Speter /* 766771Speter * and the left hand side, 767771Speter * for sets, strings, records 768771Speter */ 769*15931Smckusick p = rvalue( r->expr_node.lhs , contype , LREQ ); 770*15931Smckusick if ( p == NLNIL ) { 771*15931Smckusick return NLNIL; 7725413Speter } 773771Speter putop( P2LISTOP , P2INT ); 774*15931Smckusick p1 = rvalue( r->expr_node.rhs , p , LREQ ); 775*15931Smckusick if ( p1 == NLNIL ) { 776*15931Smckusick return NLNIL; 7775413Speter } 778771Speter putop( P2LISTOP , P2INT ); 779771Speter putop( P2CALL , P2INT ); 780771Speter } else { 781771Speter /* 782771Speter * the easy (scalar or error) case 783771Speter */ 784*15931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 785*15931Smckusick if ( p == NLNIL ) { 786*15931Smckusick return NLNIL; 7872056Speter } 788771Speter /* 789771Speter * since the second pass can't do 790771Speter * long op double or double op long 791771Speter * we may have to do some coercing. 792771Speter */ 793*15931Smckusick tuac(p, p1, &rettype, (int *) (&ctype)); 794*15931Smckusick p1 = rvalue( r->expr_node.rhs , p , RREQ ); 795*15931Smckusick if ( p1 == NLNIL ) { 796*15931Smckusick return NLNIL; 7975413Speter } 798*15931Smckusick tuac(p1, p, &rettype, (int *) (&ctype)); 799*15931Smckusick putop((int) relops[ r->tag - T_EQ ] , P2INT ); 80010364Smckusick sconv(P2INT, P2CHAR); 801771Speter } 802771Speter # endif PC 803771Speter c = classify(p); 804771Speter c1 = classify(p1); 805771Speter if (nocomp(c) || nocomp(c1)) 806*15931Smckusick return (NLNIL); 807*15931Smckusick # ifdef OBJ 808*15931Smckusick g = NIL; 809*15931Smckusick # endif 810771Speter switch (c) { 811771Speter case TBOOL: 812771Speter case TCHAR: 813771Speter if (c != c1) 814771Speter goto clash; 815771Speter break; 816771Speter case TINT: 817771Speter case TDOUBLE: 818771Speter if (c1 != TINT && c1 != TDOUBLE) 819771Speter goto clash; 820771Speter break; 821771Speter case TSCAL: 822771Speter if (c1 != TSCAL) 823771Speter goto clash; 824771Speter if (scalar(p) != scalar(p1)) 825771Speter goto nonident; 826771Speter break; 827771Speter case TSET: 828771Speter if (c1 != TSET) 829771Speter goto clash; 8303397Speter if ( opt( 's' ) && 831*15931Smckusick ( ( r->tag == T_LT) || (r->tag == T_GT) ) && 8323397Speter ( line != nssetline ) ) { 8333397Speter nssetline = line; 8343397Speter standard(); 8353397Speter error("%s comparison on sets is non-standard" , opname ); 8363397Speter } 837771Speter if (p != p1) 838771Speter goto nonident; 839*15931Smckusick # ifdef OBJ 840*15931Smckusick g = TSET; 841*15931Smckusick # endif 842771Speter break; 843771Speter case TREC: 844771Speter if ( c1 != TREC ) { 845771Speter goto clash; 846771Speter } 847771Speter if ( p != p1 ) { 848771Speter goto nonident; 849771Speter } 850*15931Smckusick if (r->tag != T_EQ && r->tag != T_NE) { 851771Speter error("%s not allowed on records - only allow = and <>" , opname ); 852*15931Smckusick return (NLNIL); 853771Speter } 854*15931Smckusick # ifdef OBJ 855*15931Smckusick g = TREC; 856*15931Smckusick # endif 857771Speter break; 858771Speter case TPTR: 859771Speter case TNIL: 860771Speter if (c1 != TPTR && c1 != TNIL) 861771Speter goto clash; 862*15931Smckusick if (r->tag != T_EQ && r->tag != T_NE) { 863771Speter error("%s not allowed on pointers - only allow = and <>" , opname ); 864*15931Smckusick return (NLNIL); 865771Speter } 866771Speter break; 867771Speter case TSTR: 868771Speter if (c1 != TSTR) 869771Speter goto clash; 870771Speter if (width(p) != width(p1)) { 871771Speter error("Strings not same length in %s comparison", opname); 872*15931Smckusick return (NLNIL); 873771Speter } 874*15931Smckusick # ifdef OBJ 875*15931Smckusick g = TSTR; 876*15931Smckusick # endif OBJ 877771Speter break; 878771Speter default: 879771Speter panic("rval2"); 880771Speter } 881771Speter # ifdef OBJ 882*15931Smckusick return (gen(g, r->tag, width(p), width(p1))); 883771Speter # endif OBJ 884771Speter # ifdef PC 885771Speter return nl + TBOOL; 886771Speter # endif PC 887771Speter clash: 888771Speter error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname); 889*15931Smckusick return (NLNIL); 890771Speter nonident: 891771Speter error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname); 892*15931Smckusick return (NLNIL); 893771Speter 894771Speter case T_IN: 895*15931Smckusick rt = r->expr_node.rhs; 896771Speter # ifdef OBJ 897*15931Smckusick if (rt != TR_NIL && rt->tag == T_CSET) { 898*15931Smckusick (void) precset( rt , NLNIL , &csetd ); 899771Speter p1 = csetd.csettype; 900*15931Smckusick if (p1 == NLNIL) 901*15931Smckusick return NLNIL; 902771Speter postcset( rt, &csetd); 903771Speter } else { 904*15931Smckusick p1 = stkrval(r->expr_node.rhs, NLNIL , (long) RREQ ); 905*15931Smckusick rt = TR_NIL; 906771Speter } 907771Speter # endif OBJ 908771Speter # ifdef PC 909*15931Smckusick if (rt != TR_NIL && rt->tag == T_CSET) { 910*15931Smckusick if ( precset( rt , NLNIL , &csetd ) ) { 9111555Speter putleaf( P2ICON , 0 , 0 9121555Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 9131555Speter , "_IN" ); 914771Speter } else { 915771Speter putleaf( P2ICON , 0 , 0 916771Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 917771Speter , "_INCT" ); 918771Speter } 919771Speter p1 = csetd.csettype; 920771Speter if (p1 == NIL) 921*15931Smckusick return NLNIL; 922771Speter } else { 923771Speter putleaf( P2ICON , 0 , 0 924771Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 925771Speter , "_IN" ); 926771Speter codeoff(); 927*15931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , LREQ ); 928771Speter codeon(); 929771Speter } 930771Speter # endif PC 931*15931Smckusick p = stkrval(r->expr_node.lhs, NLNIL , (long) RREQ ); 932771Speter if (p == NIL || p1 == NIL) 933*15931Smckusick return (NLNIL); 934*15931Smckusick if (p1->class != (char) SET) { 935771Speter error("Right operand of 'in' must be a set, not %s", nameof(p1)); 936*15931Smckusick return (NLNIL); 937771Speter } 938*15931Smckusick if (incompat(p, p1->type, r->expr_node.lhs)) { 939771Speter cerror("Index type clashed with set component type for 'in'"); 940*15931Smckusick return (NLNIL); 941771Speter } 942771Speter setran(p1->type); 943771Speter # ifdef OBJ 944*15931Smckusick if (rt == TR_NIL || csetd.comptime) 945*15931Smckusick (void) put(4, O_IN, width(p1), set.lwrb, set.uprbp); 946771Speter else 947*15931Smckusick (void) put(2, O_INCT, 9483078Smckusic (int)(3 + csetd.singcnt + 2*csetd.paircnt)); 949771Speter # endif OBJ 950771Speter # ifdef PC 951*15931Smckusick if ( rt == TR_NIL || rt->tag != T_CSET ) { 952*15931Smckusick putleaf( P2ICON , set.lwrb , 0 , P2INT , (char *) 0 ); 953771Speter putop( P2LISTOP , P2INT ); 954*15931Smckusick putleaf( P2ICON , set.uprbp , 0 , P2INT , (char *) 0 ); 955771Speter putop( P2LISTOP , P2INT ); 956*15931Smckusick p1 = rvalue( r->expr_node.rhs , NLNIL , LREQ ); 957*15931Smckusick if ( p1 == NLNIL ) { 958*15931Smckusick return NLNIL; 9595413Speter } 960771Speter putop( P2LISTOP , P2INT ); 961771Speter } else if ( csetd.comptime ) { 962*15931Smckusick putleaf( P2ICON , set.lwrb , 0 , P2INT , (char *) 0 ); 963771Speter putop( P2LISTOP , P2INT ); 964*15931Smckusick putleaf( P2ICON , set.uprbp , 0 , P2INT , (char *) 0 ); 965771Speter putop( P2LISTOP , P2INT ); 966*15931Smckusick postcset( r->expr_node.rhs , &csetd ); 967771Speter putop( P2LISTOP , P2INT ); 968771Speter } else { 969*15931Smckusick postcset( r->expr_node.rhs , &csetd ); 970771Speter } 971771Speter putop( P2CALL , P2INT ); 97210364Smckusick sconv(P2INT, P2CHAR); 973771Speter # endif PC 974771Speter return (nl+T1BOOL); 975771Speter default: 976*15931Smckusick if (r->expr_node.lhs == TR_NIL) 977*15931Smckusick return (NLNIL); 978*15931Smckusick switch (r->tag) { 979771Speter default: 980771Speter panic("rval3"); 981771Speter 982771Speter 983771Speter /* 984771Speter * An octal number 985771Speter */ 986771Speter case T_BINT: 987*15931Smckusick f.pdouble = a8tol(r->const_node.cptr); 988771Speter goto conint; 989771Speter 990771Speter /* 991771Speter * A decimal number 992771Speter */ 993771Speter case T_INT: 994*15931Smckusick f.pdouble = atof(r->const_node.cptr); 995771Speter conint: 996*15931Smckusick if (f.pdouble > MAXINT || f.pdouble < MININT) { 997771Speter error("Constant too large for this implementation"); 998*15931Smckusick return (NLNIL); 999771Speter } 1000*15931Smckusick l = f.pdouble; 100110364Smckusick # ifdef OBJ 100210364Smckusick if (bytes(l, l) <= 2) { 1003*15931Smckusick (void) put(2, O_CON2, ( short ) l); 100410364Smckusick return (nl+T2INT); 100510364Smckusick } 1006*15931Smckusick (void) put(2, O_CON4, l); 100710364Smckusick return (nl+T4INT); 1008771Speter # endif OBJ 1009771Speter # ifdef PC 101010364Smckusick switch (bytes(l, l)) { 101110364Smckusick case 1: 1012*15931Smckusick putleaf(P2ICON, (int) l, 0, P2CHAR, 1013*15931Smckusick (char *) 0); 101410364Smckusick return nl+T1INT; 101510364Smckusick case 2: 1016*15931Smckusick putleaf(P2ICON, (int) l, 0, P2SHORT, 1017*15931Smckusick (char *) 0); 101810364Smckusick return nl+T2INT; 101910364Smckusick case 4: 1020*15931Smckusick putleaf(P2ICON, (int) l, 0, P2INT, 1021*15931Smckusick (char *) 0); 102210364Smckusick return nl+T4INT; 102310364Smckusick } 1024771Speter # endif PC 1025771Speter 1026771Speter /* 1027771Speter * A floating point number 1028771Speter */ 1029771Speter case T_FINT: 1030771Speter # ifdef OBJ 1031*15931Smckusick (void) put(2, O_CON8, atof(r->const_node.cptr)); 1032771Speter # endif OBJ 1033771Speter # ifdef PC 1034*15931Smckusick putCON8( atof( r->const_node.cptr ) ); 1035771Speter # endif PC 1036771Speter return (nl+TDOUBLE); 1037771Speter 1038771Speter /* 1039771Speter * Constant strings. Note that constant characters 1040771Speter * are constant strings of length one; there is 1041771Speter * no constant string of length one. 1042771Speter */ 1043771Speter case T_STRNG: 1044*15931Smckusick cp = r->const_node.cptr; 1045771Speter if (cp[1] == 0) { 1046771Speter # ifdef OBJ 1047*15931Smckusick (void) put(2, O_CONC, cp[0]); 1048771Speter # endif OBJ 1049771Speter # ifdef PC 1050*15931Smckusick putleaf( P2ICON , cp[0] , 0 , P2CHAR , 1051*15931Smckusick (char *) 0 ); 1052771Speter # endif PC 1053771Speter return (nl+T1CHAR); 1054771Speter } 1055771Speter goto cstrng; 1056771Speter } 1057771Speter 1058771Speter } 1059771Speter } 1060771Speter 1061771Speter /* 1062771Speter * Can a class appear 1063771Speter * in a comparison ? 1064771Speter */ 1065771Speter nocomp(c) 1066771Speter int c; 1067771Speter { 1068771Speter 1069771Speter switch (c) { 1070771Speter case TREC: 10711627Speter if ( line != reccompline ) { 10721627Speter reccompline = line; 10731627Speter warning(); 10741627Speter if ( opt( 's' ) ) { 10751627Speter standard(); 10761627Speter } 1077771Speter error("record comparison is non-standard"); 1078771Speter } 1079771Speter break; 1080771Speter case TFILE: 1081771Speter case TARY: 1082771Speter error("%ss may not participate in comparisons", clnames[c]); 1083771Speter return (1); 1084771Speter } 1085771Speter return (NIL); 1086771Speter } 1087771Speter 1088771Speter /* 1089771Speter * this is sort of like gconst, except it works on expression trees 1090771Speter * rather than declaration trees, and doesn't give error messages for 1091771Speter * non-constant things. 1092771Speter * as a side effect this fills in the con structure that gconst uses. 1093771Speter * this returns TRUE or FALSE. 1094771Speter */ 1095*15931Smckusick 1096*15931Smckusick bool 1097771Speter constval(r) 1098*15931Smckusick register struct tnode *r; 1099771Speter { 1100771Speter register struct nl *np; 1101*15931Smckusick register struct tnode *cn; 1102771Speter char *cp; 1103771Speter int negd, sgnd; 1104771Speter long ci; 1105771Speter 1106771Speter con.ctype = NIL; 1107771Speter cn = r; 1108771Speter negd = sgnd = 0; 1109771Speter loop: 1110771Speter /* 1111771Speter * cn[2] is nil if error recovery generated a T_STRNG 1112771Speter */ 1113*15931Smckusick if (cn == TR_NIL || cn->expr_node.lhs == TR_NIL) 1114771Speter return FALSE; 1115*15931Smckusick switch (cn->tag) { 1116771Speter default: 1117771Speter return FALSE; 1118771Speter case T_MINUS: 1119771Speter negd = 1 - negd; 1120771Speter /* and fall through */ 1121771Speter case T_PLUS: 1122771Speter sgnd++; 1123*15931Smckusick cn = cn->un_expr.expr; 1124771Speter goto loop; 1125771Speter case T_NIL: 1126771Speter con.cpval = NIL; 1127771Speter con.cival = 0; 1128771Speter con.crval = con.cival; 1129771Speter con.ctype = nl + TNIL; 1130771Speter break; 1131771Speter case T_VAR: 1132*15931Smckusick np = lookup(cn->var_node.cptr); 1133*15931Smckusick if (np == NLNIL || np->class != CONST) { 1134771Speter return FALSE; 1135771Speter } 1136*15931Smckusick if ( cn->var_node.qual != TR_NIL ) { 1137771Speter return FALSE; 1138771Speter } 1139771Speter con.ctype = np->type; 1140771Speter switch (classify(np->type)) { 1141771Speter case TINT: 1142771Speter con.crval = np->range[0]; 1143771Speter break; 1144771Speter case TDOUBLE: 1145771Speter con.crval = np->real; 1146771Speter break; 1147771Speter case TBOOL: 1148771Speter case TCHAR: 1149771Speter case TSCAL: 1150771Speter con.cival = np->value[0]; 1151771Speter con.crval = con.cival; 1152771Speter break; 1153771Speter case TSTR: 1154*15931Smckusick con.cpval = (char *) np->ptr[0]; 1155771Speter break; 1156771Speter default: 1157771Speter con.ctype = NIL; 1158771Speter return FALSE; 1159771Speter } 1160771Speter break; 1161771Speter case T_BINT: 1162*15931Smckusick con.crval = a8tol(cn->const_node.cptr); 1163771Speter goto restcon; 1164771Speter case T_INT: 1165*15931Smckusick con.crval = atof(cn->const_node.cptr); 1166771Speter if (con.crval > MAXINT || con.crval < MININT) { 1167771Speter derror("Constant too large for this implementation"); 1168771Speter con.crval = 0; 1169771Speter } 1170771Speter restcon: 1171771Speter ci = con.crval; 1172771Speter #ifndef PI0 1173771Speter if (bytes(ci, ci) <= 2) 1174771Speter con.ctype = nl+T2INT; 1175771Speter else 1176771Speter #endif 1177771Speter con.ctype = nl+T4INT; 1178771Speter break; 1179771Speter case T_FINT: 1180771Speter con.ctype = nl+TDOUBLE; 1181*15931Smckusick con.crval = atof(cn->const_node.cptr); 1182771Speter break; 1183771Speter case T_STRNG: 1184*15931Smckusick cp = cn->const_node.cptr; 1185771Speter if (cp[1] == 0) { 1186771Speter con.ctype = nl+T1CHAR; 1187771Speter con.cival = cp[0]; 1188771Speter con.crval = con.cival; 1189771Speter break; 1190771Speter } 1191771Speter con.ctype = nl+TSTR; 1192771Speter con.cpval = cp; 1193771Speter break; 1194771Speter } 1195771Speter if (sgnd) { 1196771Speter if (isnta(con.ctype, "id")) { 1197771Speter derror("%s constants cannot be signed", nameof(con.ctype)); 1198771Speter return FALSE; 1199771Speter } else if (negd) 1200771Speter con.crval = -con.crval; 1201771Speter } 1202771Speter return TRUE; 1203771Speter } 1204