122188Sdist /* 222188Sdist * Copyright (c) 1980 Regents of the University of California. 322188Sdist * All rights reserved. The Berkeley software License Agreement 422188Sdist * specifies the terms and conditions for redistribution. 522188Sdist */ 6771Speter 715945Speter #ifndef lint 8*30839Smckusick static char sccsid[] = "@(#)rval.c 5.2 (Berkeley) 04/07/87"; 922188Sdist #endif not lint 10771Speter 11771Speter #include "whoami.h" 12771Speter #include "0.h" 13771Speter #include "tree.h" 14771Speter #include "opcode.h" 15771Speter #include "objfmt.h" 16771Speter #ifdef PC 17771Speter # include "pc.h" 1818468Sralph # include <pcc.h> 19771Speter #endif PC 2011328Speter #include "tmps.h" 2115931Smckusick #include "tree_ty.h" 22771Speter 23771Speter extern char *opnames[]; 24771Speter 251627Speter /* line number of the last record comparison warning */ 261627Speter short reccompline = 0; 273397Speter /* line number of the last non-standard set comparison */ 283397Speter short nssetline = 0; 291627Speter 30771Speter #ifdef PC 31771Speter char *relts[] = { 32771Speter "_RELEQ" , "_RELNE" , 33771Speter "_RELTLT" , "_RELTGT" , 34771Speter "_RELTLE" , "_RELTGE" 35771Speter }; 36771Speter char *relss[] = { 37771Speter "_RELEQ" , "_RELNE" , 38771Speter "_RELSLT" , "_RELSGT" , 39771Speter "_RELSLE" , "_RELSGE" 40771Speter }; 41771Speter long relops[] = { 4218468Sralph PCC_EQ , PCC_NE , 4318468Sralph PCC_LT , PCC_GT , 4418468Sralph PCC_LE , PCC_GE 45771Speter }; 4618468Sralph long mathop[] = { PCC_MUL , PCC_PLUS , PCC_MINUS }; 47771Speter char *setop[] = { "_MULT" , "_ADDT" , "_SUBT" }; 48771Speter #endif PC 49771Speter /* 50771Speter * Rvalue - an expression. 51771Speter * 52771Speter * Contype is the type that the caller would prefer, nand is important 5316273Speter * if constant strings are involved, because of string padding. 54771Speter * required is a flag whether an lvalue or an rvalue is required. 55771Speter * only VARs and structured things can have gt their lvalue this way. 56771Speter */ 5715931Smckusick /*ARGSUSED*/ 58771Speter struct nl * 59771Speter rvalue(r, contype , required ) 6015931Smckusick struct tnode *r; 61771Speter struct nl *contype; 62771Speter int required; 63771Speter { 64771Speter register struct nl *p, *p1; 65771Speter register struct nl *q; 6615931Smckusick int c, c1, w; 6715931Smckusick #ifdef OBJ 6815931Smckusick int g; 6915931Smckusick #endif 7015931Smckusick struct tnode *rt; 71771Speter char *cp, *cp1, *opname; 72771Speter long l; 7315931Smckusick union 7415931Smckusick { 7515931Smckusick long plong[2]; 7615931Smckusick double pdouble; 7715931Smckusick }f; 78771Speter extern int flagwas; 79771Speter struct csetstr csetd; 80771Speter # ifdef PC 81771Speter struct nl *rettype; 82771Speter long ctype; 833834Speter struct nl *tempnlp; 84771Speter # endif PC 85771Speter 8615931Smckusick if (r == TR_NIL) 8715931Smckusick return (NLNIL); 88771Speter if (nowexp(r)) 8915931Smckusick return (NLNIL); 90771Speter /* 91771Speter * Pick up the name of the operation 92771Speter * for future error messages. 93771Speter */ 9415931Smckusick if (r->tag <= T_IN) 9515931Smckusick opname = opnames[r->tag]; 96771Speter 97771Speter /* 98771Speter * The root of the tree tells us what sort of expression we have. 99771Speter */ 10015931Smckusick switch (r->tag) { 101771Speter 102771Speter /* 103771Speter * The constant nil 104771Speter */ 105771Speter case T_NIL: 106771Speter # ifdef OBJ 10715931Smckusick (void) put(2, O_CON2, 0); 108771Speter # endif OBJ 109771Speter # ifdef PC 11018468Sralph putleaf( PCC_ICON , 0 , 0 , PCCTM_PTR|PCCT_UNDEF , (char *) 0 ); 111771Speter # endif PC 112771Speter return (nl+TNIL); 113771Speter 114771Speter /* 115771Speter * Function call with arguments. 116771Speter */ 117771Speter case T_FCALL: 118771Speter # ifdef OBJ 119771Speter return (funccod(r)); 120771Speter # endif OBJ 121771Speter # ifdef PC 122771Speter return (pcfunccod( r )); 123771Speter # endif PC 124771Speter 125771Speter case T_VAR: 12615931Smckusick p = lookup(r->var_node.cptr); 12715931Smckusick if (p == NLNIL || p->class == BADUSE) 12815931Smckusick return (NLNIL); 129771Speter switch (p->class) { 130771Speter case VAR: 131771Speter /* 132771Speter * If a variable is 133771Speter * qualified then get 134771Speter * the rvalue by a 135771Speter * lvalue and an ind. 136771Speter */ 13715931Smckusick if (r->var_node.qual != TR_NIL) 138771Speter goto ind; 139771Speter q = p->type; 140771Speter if (q == NIL) 14115931Smckusick return (NLNIL); 142771Speter # ifdef OBJ 143771Speter w = width(q); 144771Speter switch (w) { 145771Speter case 8: 14615931Smckusick (void) put(2, O_RV8 | bn << 8+INDX, 1473078Smckusic (int)p->value[0]); 148771Speter break; 149771Speter case 4: 15015931Smckusick (void) put(2, O_RV4 | bn << 8+INDX, 1513078Smckusic (int)p->value[0]); 152771Speter break; 153771Speter case 2: 15415931Smckusick (void) put(2, O_RV2 | bn << 8+INDX, 1553078Smckusic (int)p->value[0]); 156771Speter break; 157771Speter case 1: 15815931Smckusick (void) put(2, O_RV1 | bn << 8+INDX, 1593078Smckusic (int)p->value[0]); 160771Speter break; 161771Speter default: 16215931Smckusick (void) put(3, O_RV | bn << 8+INDX, 1633078Smckusic (int)p->value[0], w); 164771Speter } 165771Speter # endif OBJ 166771Speter # ifdef PC 167771Speter if ( required == RREQ ) { 1683834Speter putRV( p -> symbol , bn , p -> value[0] , 1693834Speter p -> extra_flags , p2type( q ) ); 170771Speter } else { 1713834Speter putLV( p -> symbol , bn , p -> value[0] , 1723834Speter p -> extra_flags , p2type( q ) ); 173771Speter } 174771Speter # endif PC 175771Speter return (q); 176771Speter 177771Speter case WITHPTR: 178771Speter case REF: 179771Speter /* 180771Speter * A lvalue for these 181771Speter * is actually what one 182771Speter * might consider a rvalue. 183771Speter */ 184771Speter ind: 185771Speter q = lvalue(r, NOFLAGS , LREQ ); 186771Speter if (q == NIL) 18715931Smckusick return (NLNIL); 188771Speter # ifdef OBJ 189771Speter w = width(q); 190771Speter switch (w) { 191771Speter case 8: 19215931Smckusick (void) put(1, O_IND8); 193771Speter break; 194771Speter case 4: 19515931Smckusick (void) put(1, O_IND4); 196771Speter break; 197771Speter case 2: 19815931Smckusick (void) put(1, O_IND2); 199771Speter break; 200771Speter case 1: 20115931Smckusick (void) put(1, O_IND1); 202771Speter break; 203771Speter default: 20415931Smckusick (void) put(2, O_IND, w); 205771Speter } 206771Speter # endif OBJ 207771Speter # ifdef PC 208771Speter if ( required == RREQ ) { 20918468Sralph putop( PCCOM_UNARY PCC_MUL , p2type( q ) ); 210771Speter } 211771Speter # endif PC 212771Speter return (q); 213771Speter 214771Speter case CONST: 21515931Smckusick if (r->var_node.qual != TR_NIL) { 21615931Smckusick error("%s is a constant and cannot be qualified", r->var_node.cptr); 21715931Smckusick return (NLNIL); 218771Speter } 219771Speter q = p->type; 22015931Smckusick if (q == NLNIL) 22115931Smckusick return (NLNIL); 222771Speter if (q == nl+TSTR) { 223771Speter /* 224771Speter * Find the size of the string 225771Speter * constant if needed. 226771Speter */ 22715931Smckusick cp = (char *) p->ptr[0]; 228771Speter cstrng: 229771Speter cp1 = cp; 230771Speter for (c = 0; *cp++; c++) 231771Speter continue; 2323078Smckusic w = c; 233771Speter if (contype != NIL && !opt('s')) { 234771Speter if (width(contype) < c && classify(contype) == TSTR) { 235771Speter error("Constant string too long"); 23615931Smckusick return (NLNIL); 237771Speter } 2383078Smckusic w = width(contype); 239771Speter } 240771Speter # ifdef OBJ 24115931Smckusick (void) put(2, O_CONG, w); 2423078Smckusic putstr(cp1, w - c); 243771Speter # endif OBJ 244771Speter # ifdef PC 2453155Smckusic putCONG( cp1 , w , required ); 246771Speter # endif PC 247771Speter /* 248771Speter * Define the string temporarily 249771Speter * so later people can know its 250771Speter * width. 251771Speter * cleaned out by stat. 252771Speter */ 25315931Smckusick q = defnl((char *) 0, STR, NLNIL, w); 254771Speter q->type = q; 255771Speter return (q); 256771Speter } 257771Speter if (q == nl+T1CHAR) { 258771Speter # ifdef OBJ 25915931Smckusick (void) put(2, O_CONC, (int)p->value[0]); 260771Speter # endif OBJ 261771Speter # ifdef PC 26218468Sralph putleaf( PCC_ICON , p -> value[0] , 0 26318468Sralph , PCCT_CHAR , (char *) 0 ); 264771Speter # endif PC 265771Speter return (q); 266771Speter } 267771Speter /* 268771Speter * Every other kind of constant here 269771Speter */ 270771Speter switch (width(q)) { 271771Speter case 8: 272771Speter #ifndef DEBUG 273771Speter # ifdef OBJ 27415931Smckusick (void) put(2, O_CON8, p->real); 275771Speter # endif OBJ 276771Speter # ifdef PC 277771Speter putCON8( p -> real ); 278771Speter # endif PC 279771Speter #else 280771Speter if (hp21mx) { 28115931Smckusick f.pdouble = p->real; 28215931Smckusick conv((int *) (&f.pdouble)); 28315931Smckusick l = f.plong[1]; 28415931Smckusick (void) put(2, O_CON4, l); 285771Speter } else 286771Speter # ifdef OBJ 28715931Smckusick (void) put(2, O_CON8, p->real); 288771Speter # endif OBJ 289771Speter # ifdef PC 290771Speter putCON8( p -> real ); 291771Speter # endif PC 292771Speter #endif 293771Speter break; 294771Speter case 4: 295771Speter # ifdef OBJ 29615931Smckusick (void) put(2, O_CON4, p->range[0]); 297771Speter # endif OBJ 298771Speter # ifdef PC 29918468Sralph putleaf( PCC_ICON , (int) p->range[0] , 0 30018468Sralph , PCCT_INT , (char *) 0 ); 301771Speter # endif PC 302771Speter break; 303771Speter case 2: 304771Speter # ifdef OBJ 30515931Smckusick (void) put(2, O_CON2, (short)p->range[0]); 306771Speter # endif OBJ 307771Speter # ifdef PC 30818468Sralph putleaf( PCC_ICON , (short) p -> range[0] 30918468Sralph , 0 , PCCT_SHORT , (char *) 0 ); 310771Speter # endif PC 311771Speter break; 312771Speter case 1: 313771Speter # ifdef OBJ 31415931Smckusick (void) put(2, O_CON1, p->value[0]); 315771Speter # endif OBJ 316771Speter # ifdef PC 31718468Sralph putleaf( PCC_ICON , p -> value[0] , 0 31818468Sralph , PCCT_CHAR , (char *) 0 ); 319771Speter # endif PC 320771Speter break; 321771Speter default: 322771Speter panic("rval"); 323771Speter } 324771Speter return (q); 325771Speter 326771Speter case FUNC: 3271200Speter case FFUNC: 328771Speter /* 329771Speter * Function call with no arguments. 330771Speter */ 33115931Smckusick if (r->var_node.qual != TR_NIL) { 332771Speter error("Can't qualify a function result value"); 33315931Smckusick return (NLNIL); 334771Speter } 335771Speter # ifdef OBJ 33615931Smckusick return (funccod(r)); 337771Speter # endif OBJ 338771Speter # ifdef PC 339771Speter return (pcfunccod( r )); 340771Speter # endif PC 341771Speter 342771Speter case TYPE: 343771Speter error("Type names (e.g. %s) allowed only in declarations", p->symbol); 34415931Smckusick return (NLNIL); 345771Speter 346771Speter case PROC: 3471200Speter case FPROC: 348771Speter error("Procedure %s found where expression required", p->symbol); 34915931Smckusick return (NLNIL); 350771Speter default: 351771Speter panic("rvid"); 352771Speter } 353771Speter /* 354771Speter * Constant sets 355771Speter */ 356771Speter case T_CSET: 357771Speter # ifdef OBJ 358771Speter if ( precset( r , contype , &csetd ) ) { 359771Speter if ( csetd.csettype == NIL ) { 36015931Smckusick return (NLNIL); 361771Speter } 362771Speter postcset( r , &csetd ); 363771Speter } else { 36415931Smckusick (void) put( 2, O_PUSH, -lwidth(csetd.csettype)); 365771Speter postcset( r , &csetd ); 366771Speter setran( ( csetd.csettype ) -> type ); 36715931Smckusick (void) put( 2, O_CON24, set.uprbp); 36815931Smckusick (void) put( 2, O_CON24, set.lwrb); 36915931Smckusick (void) put( 2, O_CTTOT, 3703078Smckusic (int)(4 + csetd.singcnt + 2 * csetd.paircnt)); 371771Speter } 372771Speter return csetd.csettype; 373771Speter # endif OBJ 374771Speter # ifdef PC 375771Speter if ( precset( r , contype , &csetd ) ) { 376771Speter if ( csetd.csettype == NIL ) { 37715931Smckusick return (NLNIL); 378771Speter } 379771Speter postcset( r , &csetd ); 380771Speter } else { 38118468Sralph putleaf( PCC_ICON , 0 , 0 38218468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 383771Speter , "_CTTOT" ); 384771Speter /* 385771Speter * allocate a temporary and use it 386771Speter */ 3873834Speter tempnlp = tmpalloc(lwidth(csetd.csettype), 3883227Smckusic csetd.csettype, NOREG); 38915931Smckusick putLV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 39018468Sralph tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 391771Speter setran( ( csetd.csettype ) -> type ); 39218468Sralph putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 ); 39318468Sralph putop( PCC_CM , PCCT_INT ); 39418468Sralph putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 ); 39518468Sralph putop( PCC_CM , PCCT_INT ); 396771Speter postcset( r , &csetd ); 39718468Sralph putop( PCC_CALL , PCCT_INT ); 398771Speter } 399771Speter return csetd.csettype; 400771Speter # endif PC 401771Speter 402771Speter /* 403771Speter * Unary plus and minus 404771Speter */ 405771Speter case T_PLUS: 406771Speter case T_MINUS: 40715931Smckusick q = rvalue(r->un_expr.expr, NLNIL , RREQ ); 40815931Smckusick if (q == NLNIL) 40915931Smckusick return (NLNIL); 410771Speter if (isnta(q, "id")) { 411771Speter error("Operand of %s must be integer or real, not %s", opname, nameof(q)); 41215931Smckusick return (NLNIL); 413771Speter } 41415931Smckusick if (r->tag == T_MINUS) { 415771Speter # ifdef OBJ 41615931Smckusick (void) put(1, O_NEG2 + (width(q) >> 2)); 41710670Speter return (isa(q, "d") ? q : nl+T4INT); 418771Speter # endif OBJ 419771Speter # ifdef PC 42010670Speter if (isa(q, "i")) { 42118468Sralph sconv(p2type(q), PCCT_INT); 42218468Sralph putop( PCCOM_UNARY PCC_MINUS, PCCT_INT); 42310670Speter return nl+T4INT; 42410670Speter } 42518468Sralph putop( PCCOM_UNARY PCC_MINUS, PCCT_DOUBLE); 42610670Speter return nl+TDOUBLE; 427771Speter # endif PC 428771Speter } 429771Speter return (q); 430771Speter 431771Speter case T_NOT: 43215931Smckusick q = rvalue(r->un_expr.expr, NLNIL , RREQ ); 43315931Smckusick if (q == NLNIL) 43415931Smckusick return (NLNIL); 435771Speter if (isnta(q, "b")) { 436771Speter error("not must operate on a Boolean, not %s", nameof(q)); 43715931Smckusick return (NLNIL); 438771Speter } 439771Speter # ifdef OBJ 44015931Smckusick (void) put(1, O_NOT); 441771Speter # endif OBJ 442771Speter # ifdef PC 44318468Sralph sconv(p2type(q), PCCT_INT); 44418468Sralph putop( PCC_NOT , PCCT_INT); 44518468Sralph sconv(PCCT_INT, p2type(q)); 446771Speter # endif PC 447771Speter return (nl+T1BOOL); 448771Speter 449771Speter case T_AND: 450771Speter case T_OR: 45115931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 45210364Smckusick # ifdef PC 45318468Sralph sconv(p2type(p),PCCT_INT); 45410364Smckusick # endif PC 45515931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 45610364Smckusick # ifdef PC 45718468Sralph sconv(p2type(p1),PCCT_INT); 45810364Smckusick # endif PC 45915931Smckusick if (p == NLNIL || p1 == NLNIL) 46015931Smckusick return (NLNIL); 461771Speter if (isnta(p, "b")) { 462771Speter error("Left operand of %s must be Boolean, not %s", opname, nameof(p)); 46315931Smckusick return (NLNIL); 464771Speter } 465771Speter if (isnta(p1, "b")) { 466771Speter error("Right operand of %s must be Boolean, not %s", opname, nameof(p1)); 46715931Smckusick return (NLNIL); 468771Speter } 469771Speter # ifdef OBJ 47015931Smckusick (void) put(1, r->tag == T_AND ? O_AND : O_OR); 471771Speter # endif OBJ 472771Speter # ifdef PC 473771Speter /* 474771Speter * note the use of & and | rather than && and || 475771Speter * to force evaluation of all the expressions. 476771Speter */ 47718468Sralph putop( r->tag == T_AND ? PCC_AND : PCC_OR , PCCT_INT ); 47818468Sralph sconv(PCCT_INT, p2type(p)); 479771Speter # endif PC 480771Speter return (nl+T1BOOL); 481771Speter 482771Speter case T_DIVD: 483771Speter # ifdef OBJ 48415931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 48515931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 486771Speter # endif OBJ 487771Speter # ifdef PC 488771Speter /* 489771Speter * force these to be doubles for the divide 490771Speter */ 49115931Smckusick p = rvalue( r->expr_node.lhs , NLNIL , RREQ ); 49218468Sralph sconv(p2type(p), PCCT_DOUBLE); 49315931Smckusick p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ ); 49418468Sralph sconv(p2type(p1), PCCT_DOUBLE); 495771Speter # endif PC 49615931Smckusick if (p == NLNIL || p1 == NLNIL) 49715931Smckusick return (NLNIL); 498771Speter if (isnta(p, "id")) { 499771Speter error("Left operand of / must be integer or real, not %s", nameof(p)); 50015931Smckusick return (NLNIL); 501771Speter } 502771Speter if (isnta(p1, "id")) { 503771Speter error("Right operand of / must be integer or real, not %s", nameof(p1)); 50415931Smckusick return (NLNIL); 505771Speter } 506771Speter # ifdef OBJ 50715931Smckusick return gen(NIL, r->tag, width(p), width(p1)); 508771Speter # endif OBJ 509771Speter # ifdef PC 51018468Sralph putop( PCC_DIV , PCCT_DOUBLE ); 511771Speter return nl + TDOUBLE; 512771Speter # endif PC 513771Speter 514771Speter case T_MULT: 515771Speter case T_ADD: 516771Speter case T_SUB: 517771Speter # ifdef OBJ 518771Speter /* 51916273Speter * get the type of the right hand side. 52016273Speter * if it turns out to be a set, 52116273Speter * use that type when getting 52216273Speter * the type of the left hand side. 52316273Speter * and then use the type of the left hand side 52416273Speter * when generating code. 52516273Speter * this will correctly decide the type of any 52616273Speter * empty sets in the tree, since if the empty set 52716273Speter * is on the left hand side it will inherit 52816273Speter * the type of the right hand side, 52916273Speter * and if it's on the right hand side, its type (intset) 53016273Speter * will be overridden by the type of the left hand side. 53116273Speter * this is an awful lot of tree traversing, 53216273Speter * but it works. 533771Speter */ 53416273Speter codeoff(); 53516273Speter p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ ); 53616273Speter codeon(); 53716273Speter if ( p1 == NLNIL ) { 53815931Smckusick return NLNIL; 5391555Speter } 54016273Speter if (isa(p1, "t")) { 54116273Speter codeoff(); 54216273Speter contype = rvalue(r->expr_node.lhs, p1, RREQ); 54316273Speter codeon(); 54416273Speter if (contype == NLNIL) { 54516273Speter return NLNIL; 54616273Speter } 54716273Speter } 54815931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 54915931Smckusick p1 = rvalue( r->expr_node.rhs , p , RREQ ); 55015937Smckusick if ( p == NLNIL || p1 == NLNIL ) 55115931Smckusick return NLNIL; 552771Speter if (isa(p, "id") && isa(p1, "id")) 55315931Smckusick return (gen(NIL, r->tag, width(p), width(p1))); 554771Speter if (isa(p, "t") && isa(p1, "t")) { 555771Speter if (p != p1) { 556771Speter error("Set types of operands of %s must be identical", opname); 55715931Smckusick return (NLNIL); 558771Speter } 55915931Smckusick (void) gen(TSET, r->tag, width(p), 0); 560771Speter return (p); 561771Speter } 562771Speter # endif OBJ 563771Speter # ifdef PC 564771Speter /* 565771Speter * the second pass can't do 566771Speter * long op double or double op long 56716273Speter * so we have to know the type of both operands. 56816273Speter * also, see the note for obj above on determining 56916273Speter * the type of empty sets. 570771Speter */ 571771Speter codeoff(); 57216273Speter p1 = rvalue(r->expr_node.rhs, NLNIL, RREQ); 573771Speter codeon(); 574771Speter if ( isa( p1 , "id" ) ) { 57515931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 57615937Smckusick if ( ( p == NLNIL ) || ( p1 == NLNIL ) ) { 57715931Smckusick return NLNIL; 578771Speter } 57915931Smckusick tuac(p, p1, &rettype, (int *) (&ctype)); 58015931Smckusick p1 = rvalue( r->expr_node.rhs , contype , RREQ ); 58115931Smckusick tuac(p1, p, &rettype, (int *) (&ctype)); 582771Speter if ( isa( p , "id" ) ) { 58315931Smckusick putop( (int) mathop[r->tag - T_MULT], (int) ctype); 584771Speter return rettype; 585771Speter } 586771Speter } 587771Speter if ( isa( p1 , "t" ) ) { 58818468Sralph putleaf( PCC_ICON , 0 , 0 58918468Sralph , PCCM_ADDTYPE( PCCM_ADDTYPE( PCCTM_PTR | PCCT_STRTY , PCCTM_FTN ) 59018468Sralph , PCCTM_PTR ) 59115931Smckusick , setop[ r->tag - T_MULT ] ); 59216273Speter codeoff(); 59316273Speter contype = rvalue( r->expr_node.lhs, p1 , LREQ ); 59416273Speter codeon(); 59515937Smckusick if ( contype == NLNIL ) { 59615931Smckusick return NLNIL; 5971555Speter } 5981555Speter /* 5991555Speter * allocate a temporary and use it 6001555Speter */ 6013834Speter tempnlp = tmpalloc(lwidth(contype), contype, NOREG); 60215931Smckusick putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 60318468Sralph tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 60415931Smckusick p = rvalue( r->expr_node.lhs , contype , LREQ ); 605771Speter if ( isa( p , "t" ) ) { 60618468Sralph putop( PCC_CM , PCCT_INT ); 60715937Smckusick if ( p == NLNIL || p1 == NLNIL ) { 60815931Smckusick return NLNIL; 609771Speter } 61015931Smckusick p1 = rvalue( r->expr_node.rhs , p , LREQ ); 611771Speter if ( p != p1 ) { 612771Speter error("Set types of operands of %s must be identical", opname); 61315931Smckusick return NLNIL; 614771Speter } 61518468Sralph putop( PCC_CM , PCCT_INT ); 61618468Sralph putleaf( PCC_ICON , (int) (lwidth(p1)) / sizeof( long ) , 0 61718468Sralph , PCCT_INT , (char *) 0 ); 61818468Sralph putop( PCC_CM , PCCT_INT ); 61918468Sralph putop( PCC_CALL , PCCTM_PTR | PCCT_STRTY ); 620771Speter return p; 621771Speter } 622771Speter } 623771Speter if ( isnta( p1 , "idt" ) ) { 624771Speter /* 625771Speter * find type of left operand for error message. 626771Speter */ 62715931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 628771Speter } 629771Speter /* 630771Speter * don't give spurious error messages. 631771Speter */ 63215937Smckusick if ( p == NLNIL || p1 == NLNIL ) { 63315931Smckusick return NLNIL; 634771Speter } 635771Speter # endif PC 636771Speter if (isnta(p, "idt")) { 637771Speter error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p)); 63815931Smckusick return (NLNIL); 639771Speter } 640771Speter if (isnta(p1, "idt")) { 641771Speter error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1)); 64215931Smckusick return (NLNIL); 643771Speter } 644771Speter error("Cannot mix sets with integers and reals as operands of %s", opname); 64515931Smckusick return (NLNIL); 646771Speter 647771Speter case T_MOD: 648771Speter case T_DIV: 64915931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 65010364Smckusick # ifdef PC 65118468Sralph sconv(p2type(p), PCCT_INT); 652*30839Smckusick # ifdef tahoe 653*30839Smckusick /* prepare for ediv workaround, see below. */ 654*30839Smckusick if (r->tag == T_MOD) { 655*30839Smckusick (void) rvalue(r->expr_node.lhs, NLNIL, RREQ); 656*30839Smckusick sconv(p2type(p), PCCT_INT); 657*30839Smckusick } 658*30839Smckusick # endif tahoe 65910364Smckusick # endif PC 66015931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 66110364Smckusick # ifdef PC 66218468Sralph sconv(p2type(p1), PCCT_INT); 66310364Smckusick # endif PC 66415937Smckusick if (p == NLNIL || p1 == NLNIL) 66515931Smckusick return (NLNIL); 666771Speter if (isnta(p, "i")) { 667771Speter error("Left operand of %s must be integer, not %s", opname, nameof(p)); 66815931Smckusick return (NLNIL); 669771Speter } 670771Speter if (isnta(p1, "i")) { 671771Speter error("Right operand of %s must be integer, not %s", opname, nameof(p1)); 67215931Smckusick return (NLNIL); 673771Speter } 674771Speter # ifdef OBJ 67515931Smckusick return (gen(NIL, r->tag, width(p), width(p1))); 676771Speter # endif OBJ 677771Speter # ifdef PC 678*30839Smckusick # ifndef tahoe 67918468Sralph putop( r->tag == T_DIV ? PCC_DIV : PCC_MOD , PCCT_INT ); 680771Speter return ( nl + T4INT ); 681*30839Smckusick # else tahoe 682*30839Smckusick putop( PCC_DIV , PCCT_INT ); 683*30839Smckusick if (r->tag == T_MOD) { 684*30839Smckusick /* 685*30839Smckusick * avoid f1 bug: PCC_MOD would generate an 'ediv', 686*30839Smckusick * which would reuire too many registers to evaluate 687*30839Smckusick * things like 688*30839Smckusick * var i:boolean;j:integer; i := (j+1) = (j mod 2); 689*30839Smckusick * so, instead of 690*30839Smckusick * PCC_MOD 691*30839Smckusick * / \ 692*30839Smckusick * p p1 693*30839Smckusick * we put 694*30839Smckusick * PCC_MINUS 695*30839Smckusick * / \ 696*30839Smckusick * p PCC_MUL 697*30839Smckusick * / \ 698*30839Smckusick * PCC_DIV p1 699*30839Smckusick * / \ 700*30839Smckusick * p p1 701*30839Smckusick * 702*30839Smckusick * we already have put p, p, p1, PCC_DIV. and now... 703*30839Smckusick */ 704*30839Smckusick rvalue(r->expr_node.rhs, NLNIL , RREQ ); 705*30839Smckusick sconv(p2type(p1), PCCT_INT); 706*30839Smckusick putop( PCC_MUL, PCCT_INT ); 707*30839Smckusick putop( PCC_MINUS, PCCT_INT ); 708*30839Smckusick } 709*30839Smckusick return ( nl + T4INT ); 710*30839Smckusick # endif tahoe 711771Speter # endif PC 712771Speter 713771Speter case T_EQ: 714771Speter case T_NE: 715771Speter case T_LT: 716771Speter case T_GT: 717771Speter case T_LE: 718771Speter case T_GE: 719771Speter /* 720771Speter * Since there can be no, a priori, knowledge 721771Speter * of the context type should a constant string 722771Speter * or set arise, we must poke around to find such 723771Speter * a type if possible. Since constant strings can 724771Speter * always masquerade as identifiers, this is always 725771Speter * necessary. 72616273Speter * see the note in the obj section of case T_MULT above 72716273Speter * for the determination of the base type of empty sets. 728771Speter */ 729771Speter codeoff(); 73015931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 731771Speter codeon(); 73215931Smckusick if (p1 == NLNIL) 73315931Smckusick return (NLNIL); 734771Speter contype = p1; 735771Speter # ifdef OBJ 7361555Speter if (p1->class == STR) { 737771Speter /* 738771Speter * For constant strings we want 739771Speter * the longest type so as to be 740771Speter * able to do padding (more importantly 741771Speter * avoiding truncation). For clarity, 742771Speter * we get this length here. 743771Speter */ 744771Speter codeoff(); 74515931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 746771Speter codeon(); 74715931Smckusick if (p == NLNIL) 74815931Smckusick return (NLNIL); 7491555Speter if (width(p) > width(p1)) 750771Speter contype = p; 751771Speter } 75216273Speter if (isa(p1, "t")) { 75316273Speter codeoff(); 75416273Speter contype = rvalue(r->expr_node.lhs, p1, RREQ); 75516273Speter codeon(); 75616273Speter if (contype == NLNIL) { 75716273Speter return NLNIL; 75816273Speter } 75916273Speter } 760771Speter /* 761771Speter * Now we generate code for 762771Speter * the operands of the relational 763771Speter * operation. 764771Speter */ 76515931Smckusick p = rvalue(r->expr_node.lhs, contype , RREQ ); 76615931Smckusick if (p == NLNIL) 76715931Smckusick return (NLNIL); 76815931Smckusick p1 = rvalue(r->expr_node.rhs, p , RREQ ); 76915931Smckusick if (p1 == NLNIL) 77015931Smckusick return (NLNIL); 771771Speter # endif OBJ 772771Speter # ifdef PC 773771Speter c1 = classify( p1 ); 774771Speter if ( c1 == TSET || c1 == TSTR || c1 == TREC ) { 77518468Sralph putleaf( PCC_ICON , 0 , 0 77618468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 77715931Smckusick , c1 == TSET ? relts[ r->tag - T_EQ ] 77815931Smckusick : relss[ r->tag - T_EQ ] ); 779771Speter /* 780771Speter * for [] and strings, comparisons are done on 781771Speter * the maximum width of the two sides. 782771Speter * for other sets, we have to ask the left side 783771Speter * what type it is based on the type of the right. 784771Speter * (this matters for intsets). 785771Speter */ 7861555Speter if ( c1 == TSTR ) { 787771Speter codeoff(); 78815931Smckusick p = rvalue( r->expr_node.lhs , NLNIL , LREQ ); 789771Speter codeon(); 79015931Smckusick if ( p == NLNIL ) { 79115931Smckusick return NLNIL; 7921555Speter } 7931555Speter if ( lwidth( p ) > lwidth( p1 ) ) { 794771Speter contype = p; 795771Speter } 7961555Speter } else if ( c1 == TSET ) { 79715937Smckusick codeoff(); 79816273Speter contype = rvalue(r->expr_node.lhs, p1, LREQ); 79915937Smckusick codeon(); 80016273Speter if (contype == NLNIL) { 80115937Smckusick return NLNIL; 8021555Speter } 8031627Speter } 804771Speter /* 805771Speter * put out the width of the comparison. 806771Speter */ 80718468Sralph putleaf(PCC_ICON, (int) lwidth(contype), 0, PCCT_INT, (char *) 0); 808771Speter /* 809771Speter * and the left hand side, 810771Speter * for sets, strings, records 811771Speter */ 81215931Smckusick p = rvalue( r->expr_node.lhs , contype , LREQ ); 81315931Smckusick if ( p == NLNIL ) { 81415931Smckusick return NLNIL; 8155413Speter } 81618468Sralph putop( PCC_CM , PCCT_INT ); 81715931Smckusick p1 = rvalue( r->expr_node.rhs , p , LREQ ); 81815931Smckusick if ( p1 == NLNIL ) { 81915931Smckusick return NLNIL; 8205413Speter } 82118468Sralph putop( PCC_CM , PCCT_INT ); 82218468Sralph putop( PCC_CALL , PCCT_INT ); 823771Speter } else { 824771Speter /* 825771Speter * the easy (scalar or error) case 826771Speter */ 82715931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 82815931Smckusick if ( p == NLNIL ) { 82915931Smckusick return NLNIL; 8302056Speter } 831771Speter /* 832771Speter * since the second pass can't do 833771Speter * long op double or double op long 834771Speter * we may have to do some coercing. 835771Speter */ 83615931Smckusick tuac(p, p1, &rettype, (int *) (&ctype)); 83715931Smckusick p1 = rvalue( r->expr_node.rhs , p , RREQ ); 83815931Smckusick if ( p1 == NLNIL ) { 83915931Smckusick return NLNIL; 8405413Speter } 84115931Smckusick tuac(p1, p, &rettype, (int *) (&ctype)); 84218468Sralph putop((int) relops[ r->tag - T_EQ ] , PCCT_INT ); 84318468Sralph sconv(PCCT_INT, PCCT_CHAR); 844771Speter } 845771Speter # endif PC 846771Speter c = classify(p); 847771Speter c1 = classify(p1); 848771Speter if (nocomp(c) || nocomp(c1)) 84915931Smckusick return (NLNIL); 85015931Smckusick # ifdef OBJ 85115931Smckusick g = NIL; 85215931Smckusick # endif 853771Speter switch (c) { 854771Speter case TBOOL: 855771Speter case TCHAR: 856771Speter if (c != c1) 857771Speter goto clash; 858771Speter break; 859771Speter case TINT: 860771Speter case TDOUBLE: 861771Speter if (c1 != TINT && c1 != TDOUBLE) 862771Speter goto clash; 863771Speter break; 864771Speter case TSCAL: 865771Speter if (c1 != TSCAL) 866771Speter goto clash; 867771Speter if (scalar(p) != scalar(p1)) 868771Speter goto nonident; 869771Speter break; 870771Speter case TSET: 871771Speter if (c1 != TSET) 872771Speter goto clash; 8733397Speter if ( opt( 's' ) && 87415931Smckusick ( ( r->tag == T_LT) || (r->tag == T_GT) ) && 8753397Speter ( line != nssetline ) ) { 8763397Speter nssetline = line; 8773397Speter standard(); 8783397Speter error("%s comparison on sets is non-standard" , opname ); 8793397Speter } 880771Speter if (p != p1) 881771Speter goto nonident; 88215931Smckusick # ifdef OBJ 88315931Smckusick g = TSET; 88415931Smckusick # endif 885771Speter break; 886771Speter case TREC: 887771Speter if ( c1 != TREC ) { 888771Speter goto clash; 889771Speter } 890771Speter if ( p != p1 ) { 891771Speter goto nonident; 892771Speter } 89315931Smckusick if (r->tag != T_EQ && r->tag != T_NE) { 894771Speter error("%s not allowed on records - only allow = and <>" , opname ); 89515931Smckusick return (NLNIL); 896771Speter } 89715931Smckusick # ifdef OBJ 89815931Smckusick g = TREC; 89915931Smckusick # endif 900771Speter break; 901771Speter case TPTR: 902771Speter case TNIL: 903771Speter if (c1 != TPTR && c1 != TNIL) 904771Speter goto clash; 90515931Smckusick if (r->tag != T_EQ && r->tag != T_NE) { 906771Speter error("%s not allowed on pointers - only allow = and <>" , opname ); 90715931Smckusick return (NLNIL); 908771Speter } 90915937Smckusick if (p != nl+TNIL && p1 != nl+TNIL && p != p1) 91015937Smckusick goto nonident; 911771Speter break; 912771Speter case TSTR: 913771Speter if (c1 != TSTR) 914771Speter goto clash; 915771Speter if (width(p) != width(p1)) { 916771Speter error("Strings not same length in %s comparison", opname); 91715931Smckusick return (NLNIL); 918771Speter } 91915931Smckusick # ifdef OBJ 92015931Smckusick g = TSTR; 92115931Smckusick # endif OBJ 922771Speter break; 923771Speter default: 924771Speter panic("rval2"); 925771Speter } 926771Speter # ifdef OBJ 92715931Smckusick return (gen(g, r->tag, width(p), width(p1))); 928771Speter # endif OBJ 929771Speter # ifdef PC 930771Speter return nl + TBOOL; 931771Speter # endif PC 932771Speter clash: 933771Speter error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname); 93415931Smckusick return (NLNIL); 935771Speter nonident: 936771Speter error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname); 93715931Smckusick return (NLNIL); 938771Speter 939771Speter case T_IN: 94015931Smckusick rt = r->expr_node.rhs; 941771Speter # ifdef OBJ 94215931Smckusick if (rt != TR_NIL && rt->tag == T_CSET) { 94315931Smckusick (void) precset( rt , NLNIL , &csetd ); 944771Speter p1 = csetd.csettype; 94515931Smckusick if (p1 == NLNIL) 94615931Smckusick return NLNIL; 947771Speter postcset( rt, &csetd); 948771Speter } else { 94915931Smckusick p1 = stkrval(r->expr_node.rhs, NLNIL , (long) RREQ ); 95015931Smckusick rt = TR_NIL; 951771Speter } 952771Speter # endif OBJ 953771Speter # ifdef PC 95415931Smckusick if (rt != TR_NIL && rt->tag == T_CSET) { 95515931Smckusick if ( precset( rt , NLNIL , &csetd ) ) { 95618468Sralph putleaf( PCC_ICON , 0 , 0 95718468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 9581555Speter , "_IN" ); 959771Speter } else { 96018468Sralph putleaf( PCC_ICON , 0 , 0 96118468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 962771Speter , "_INCT" ); 963771Speter } 964771Speter p1 = csetd.csettype; 965771Speter if (p1 == NIL) 96615931Smckusick return NLNIL; 967771Speter } else { 96818468Sralph putleaf( PCC_ICON , 0 , 0 96918468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 970771Speter , "_IN" ); 971771Speter codeoff(); 97215931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , LREQ ); 973771Speter codeon(); 974771Speter } 975771Speter # endif PC 97615931Smckusick p = stkrval(r->expr_node.lhs, NLNIL , (long) RREQ ); 977771Speter if (p == NIL || p1 == NIL) 97815931Smckusick return (NLNIL); 97915931Smckusick if (p1->class != (char) SET) { 980771Speter error("Right operand of 'in' must be a set, not %s", nameof(p1)); 98115931Smckusick return (NLNIL); 982771Speter } 98315931Smckusick if (incompat(p, p1->type, r->expr_node.lhs)) { 984771Speter cerror("Index type clashed with set component type for 'in'"); 98515931Smckusick return (NLNIL); 986771Speter } 987771Speter setran(p1->type); 988771Speter # ifdef OBJ 98915931Smckusick if (rt == TR_NIL || csetd.comptime) 99015931Smckusick (void) put(4, O_IN, width(p1), set.lwrb, set.uprbp); 991771Speter else 99215931Smckusick (void) put(2, O_INCT, 9933078Smckusic (int)(3 + csetd.singcnt + 2*csetd.paircnt)); 994771Speter # endif OBJ 995771Speter # ifdef PC 99615931Smckusick if ( rt == TR_NIL || rt->tag != T_CSET ) { 99718468Sralph putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 ); 99818468Sralph putop( PCC_CM , PCCT_INT ); 99918468Sralph putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 ); 100018468Sralph putop( PCC_CM , PCCT_INT ); 100115931Smckusick p1 = rvalue( r->expr_node.rhs , NLNIL , LREQ ); 100215931Smckusick if ( p1 == NLNIL ) { 100315931Smckusick return NLNIL; 10045413Speter } 100518468Sralph putop( PCC_CM , PCCT_INT ); 1006771Speter } else if ( csetd.comptime ) { 100718468Sralph putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 ); 100818468Sralph putop( PCC_CM , PCCT_INT ); 100918468Sralph putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 ); 101018468Sralph putop( PCC_CM , PCCT_INT ); 101115931Smckusick postcset( r->expr_node.rhs , &csetd ); 101218468Sralph putop( PCC_CM , PCCT_INT ); 1013771Speter } else { 101415931Smckusick postcset( r->expr_node.rhs , &csetd ); 1015771Speter } 101618468Sralph putop( PCC_CALL , PCCT_INT ); 101718468Sralph sconv(PCCT_INT, PCCT_CHAR); 1018771Speter # endif PC 1019771Speter return (nl+T1BOOL); 1020771Speter default: 102115931Smckusick if (r->expr_node.lhs == TR_NIL) 102215931Smckusick return (NLNIL); 102315931Smckusick switch (r->tag) { 1024771Speter default: 1025771Speter panic("rval3"); 1026771Speter 1027771Speter 1028771Speter /* 1029771Speter * An octal number 1030771Speter */ 1031771Speter case T_BINT: 103215931Smckusick f.pdouble = a8tol(r->const_node.cptr); 1033771Speter goto conint; 1034771Speter 1035771Speter /* 1036771Speter * A decimal number 1037771Speter */ 1038771Speter case T_INT: 103915931Smckusick f.pdouble = atof(r->const_node.cptr); 1040771Speter conint: 104115931Smckusick if (f.pdouble > MAXINT || f.pdouble < MININT) { 1042771Speter error("Constant too large for this implementation"); 104315931Smckusick return (NLNIL); 1044771Speter } 104515931Smckusick l = f.pdouble; 104610364Smckusick # ifdef OBJ 104710364Smckusick if (bytes(l, l) <= 2) { 104815931Smckusick (void) put(2, O_CON2, ( short ) l); 104910364Smckusick return (nl+T2INT); 105010364Smckusick } 105115931Smckusick (void) put(2, O_CON4, l); 105210364Smckusick return (nl+T4INT); 1053771Speter # endif OBJ 1054771Speter # ifdef PC 105510364Smckusick switch (bytes(l, l)) { 105610364Smckusick case 1: 105718468Sralph putleaf(PCC_ICON, (int) l, 0, PCCT_CHAR, 105815931Smckusick (char *) 0); 105910364Smckusick return nl+T1INT; 106010364Smckusick case 2: 106118468Sralph putleaf(PCC_ICON, (int) l, 0, PCCT_SHORT, 106215931Smckusick (char *) 0); 106310364Smckusick return nl+T2INT; 106410364Smckusick case 4: 106518468Sralph putleaf(PCC_ICON, (int) l, 0, PCCT_INT, 106615931Smckusick (char *) 0); 106710364Smckusick return nl+T4INT; 106810364Smckusick } 1069771Speter # endif PC 1070771Speter 1071771Speter /* 1072771Speter * A floating point number 1073771Speter */ 1074771Speter case T_FINT: 1075771Speter # ifdef OBJ 107615931Smckusick (void) put(2, O_CON8, atof(r->const_node.cptr)); 1077771Speter # endif OBJ 1078771Speter # ifdef PC 107915931Smckusick putCON8( atof( r->const_node.cptr ) ); 1080771Speter # endif PC 1081771Speter return (nl+TDOUBLE); 1082771Speter 1083771Speter /* 1084771Speter * Constant strings. Note that constant characters 1085771Speter * are constant strings of length one; there is 1086771Speter * no constant string of length one. 1087771Speter */ 1088771Speter case T_STRNG: 108915931Smckusick cp = r->const_node.cptr; 1090771Speter if (cp[1] == 0) { 1091771Speter # ifdef OBJ 109215931Smckusick (void) put(2, O_CONC, cp[0]); 1093771Speter # endif OBJ 1094771Speter # ifdef PC 109518468Sralph putleaf( PCC_ICON , cp[0] , 0 , PCCT_CHAR , 109615931Smckusick (char *) 0 ); 1097771Speter # endif PC 1098771Speter return (nl+T1CHAR); 1099771Speter } 1100771Speter goto cstrng; 1101771Speter } 1102771Speter 1103771Speter } 1104771Speter } 1105771Speter 1106771Speter /* 1107771Speter * Can a class appear 1108771Speter * in a comparison ? 1109771Speter */ 1110771Speter nocomp(c) 1111771Speter int c; 1112771Speter { 1113771Speter 1114771Speter switch (c) { 1115771Speter case TREC: 11161627Speter if ( line != reccompline ) { 11171627Speter reccompline = line; 11181627Speter warning(); 11191627Speter if ( opt( 's' ) ) { 11201627Speter standard(); 11211627Speter } 1122771Speter error("record comparison is non-standard"); 1123771Speter } 1124771Speter break; 1125771Speter case TFILE: 1126771Speter case TARY: 1127771Speter error("%ss may not participate in comparisons", clnames[c]); 1128771Speter return (1); 1129771Speter } 1130771Speter return (NIL); 1131771Speter } 1132771Speter 1133771Speter /* 1134771Speter * this is sort of like gconst, except it works on expression trees 1135771Speter * rather than declaration trees, and doesn't give error messages for 1136771Speter * non-constant things. 1137771Speter * as a side effect this fills in the con structure that gconst uses. 1138771Speter * this returns TRUE or FALSE. 1139771Speter */ 114015931Smckusick 114115931Smckusick bool 1142771Speter constval(r) 114315931Smckusick register struct tnode *r; 1144771Speter { 1145771Speter register struct nl *np; 114615931Smckusick register struct tnode *cn; 1147771Speter char *cp; 1148771Speter int negd, sgnd; 1149771Speter long ci; 1150771Speter 1151771Speter con.ctype = NIL; 1152771Speter cn = r; 1153771Speter negd = sgnd = 0; 1154771Speter loop: 1155771Speter /* 1156771Speter * cn[2] is nil if error recovery generated a T_STRNG 1157771Speter */ 115815931Smckusick if (cn == TR_NIL || cn->expr_node.lhs == TR_NIL) 1159771Speter return FALSE; 116015931Smckusick switch (cn->tag) { 1161771Speter default: 1162771Speter return FALSE; 1163771Speter case T_MINUS: 1164771Speter negd = 1 - negd; 1165771Speter /* and fall through */ 1166771Speter case T_PLUS: 1167771Speter sgnd++; 116815931Smckusick cn = cn->un_expr.expr; 1169771Speter goto loop; 1170771Speter case T_NIL: 1171771Speter con.cpval = NIL; 1172771Speter con.cival = 0; 1173771Speter con.crval = con.cival; 1174771Speter con.ctype = nl + TNIL; 1175771Speter break; 1176771Speter case T_VAR: 117715931Smckusick np = lookup(cn->var_node.cptr); 117815931Smckusick if (np == NLNIL || np->class != CONST) { 1179771Speter return FALSE; 1180771Speter } 118115931Smckusick if ( cn->var_node.qual != TR_NIL ) { 1182771Speter return FALSE; 1183771Speter } 1184771Speter con.ctype = np->type; 1185771Speter switch (classify(np->type)) { 1186771Speter case TINT: 1187771Speter con.crval = np->range[0]; 1188771Speter break; 1189771Speter case TDOUBLE: 1190771Speter con.crval = np->real; 1191771Speter break; 1192771Speter case TBOOL: 1193771Speter case TCHAR: 1194771Speter case TSCAL: 1195771Speter con.cival = np->value[0]; 1196771Speter con.crval = con.cival; 1197771Speter break; 1198771Speter case TSTR: 119915931Smckusick con.cpval = (char *) np->ptr[0]; 1200771Speter break; 1201771Speter default: 1202771Speter con.ctype = NIL; 1203771Speter return FALSE; 1204771Speter } 1205771Speter break; 1206771Speter case T_BINT: 120715931Smckusick con.crval = a8tol(cn->const_node.cptr); 1208771Speter goto restcon; 1209771Speter case T_INT: 121015931Smckusick con.crval = atof(cn->const_node.cptr); 1211771Speter if (con.crval > MAXINT || con.crval < MININT) { 1212771Speter derror("Constant too large for this implementation"); 1213771Speter con.crval = 0; 1214771Speter } 1215771Speter restcon: 1216771Speter ci = con.crval; 1217771Speter #ifndef PI0 1218771Speter if (bytes(ci, ci) <= 2) 1219771Speter con.ctype = nl+T2INT; 1220771Speter else 1221771Speter #endif 1222771Speter con.ctype = nl+T4INT; 1223771Speter break; 1224771Speter case T_FINT: 1225771Speter con.ctype = nl+TDOUBLE; 122615931Smckusick con.crval = atof(cn->const_node.cptr); 1227771Speter break; 1228771Speter case T_STRNG: 122915931Smckusick cp = cn->const_node.cptr; 1230771Speter if (cp[1] == 0) { 1231771Speter con.ctype = nl+T1CHAR; 1232771Speter con.cival = cp[0]; 1233771Speter con.crval = con.cival; 1234771Speter break; 1235771Speter } 1236771Speter con.ctype = nl+TSTR; 1237771Speter con.cpval = cp; 1238771Speter break; 1239771Speter } 1240771Speter if (sgnd) { 1241771Speter if (isnta(con.ctype, "id")) { 1242771Speter derror("%s constants cannot be signed", nameof(con.ctype)); 1243771Speter return FALSE; 1244771Speter } else if (negd) 1245771Speter con.crval = -con.crval; 1246771Speter } 1247771Speter return TRUE; 1248771Speter } 1249