1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622188Sdist */ 7771Speter 815945Speter #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)rval.c 5.3 (Berkeley) 04/16/91"; 10*48116Sbostic #endif /* not lint */ 11771Speter 12771Speter #include "whoami.h" 13771Speter #include "0.h" 14771Speter #include "tree.h" 15771Speter #include "opcode.h" 16771Speter #include "objfmt.h" 17771Speter #ifdef PC 18771Speter # include "pc.h" 1918468Sralph # include <pcc.h> 20771Speter #endif PC 2111328Speter #include "tmps.h" 2215931Smckusick #include "tree_ty.h" 23771Speter 24771Speter extern char *opnames[]; 25771Speter 261627Speter /* line number of the last record comparison warning */ 271627Speter short reccompline = 0; 283397Speter /* line number of the last non-standard set comparison */ 293397Speter short nssetline = 0; 301627Speter 31771Speter #ifdef PC 32771Speter char *relts[] = { 33771Speter "_RELEQ" , "_RELNE" , 34771Speter "_RELTLT" , "_RELTGT" , 35771Speter "_RELTLE" , "_RELTGE" 36771Speter }; 37771Speter char *relss[] = { 38771Speter "_RELEQ" , "_RELNE" , 39771Speter "_RELSLT" , "_RELSGT" , 40771Speter "_RELSLE" , "_RELSGE" 41771Speter }; 42771Speter long relops[] = { 4318468Sralph PCC_EQ , PCC_NE , 4418468Sralph PCC_LT , PCC_GT , 4518468Sralph PCC_LE , PCC_GE 46771Speter }; 4718468Sralph long mathop[] = { PCC_MUL , PCC_PLUS , PCC_MINUS }; 48771Speter char *setop[] = { "_MULT" , "_ADDT" , "_SUBT" }; 49771Speter #endif PC 50771Speter /* 51771Speter * Rvalue - an expression. 52771Speter * 53771Speter * Contype is the type that the caller would prefer, nand is important 5416273Speter * if constant strings are involved, because of string padding. 55771Speter * required is a flag whether an lvalue or an rvalue is required. 56771Speter * only VARs and structured things can have gt their lvalue this way. 57771Speter */ 5815931Smckusick /*ARGSUSED*/ 59771Speter struct nl * 60771Speter rvalue(r, contype , required ) 6115931Smckusick struct tnode *r; 62771Speter struct nl *contype; 63771Speter int required; 64771Speter { 65771Speter register struct nl *p, *p1; 66771Speter register struct nl *q; 6715931Smckusick int c, c1, w; 6815931Smckusick #ifdef OBJ 6915931Smckusick int g; 7015931Smckusick #endif 7115931Smckusick struct tnode *rt; 72771Speter char *cp, *cp1, *opname; 73771Speter long l; 7415931Smckusick union 7515931Smckusick { 7615931Smckusick long plong[2]; 7715931Smckusick double pdouble; 7815931Smckusick }f; 79771Speter extern int flagwas; 80771Speter struct csetstr csetd; 81771Speter # ifdef PC 82771Speter struct nl *rettype; 83771Speter long ctype; 843834Speter struct nl *tempnlp; 85771Speter # endif PC 86771Speter 8715931Smckusick if (r == TR_NIL) 8815931Smckusick return (NLNIL); 89771Speter if (nowexp(r)) 9015931Smckusick return (NLNIL); 91771Speter /* 92771Speter * Pick up the name of the operation 93771Speter * for future error messages. 94771Speter */ 9515931Smckusick if (r->tag <= T_IN) 9615931Smckusick opname = opnames[r->tag]; 97771Speter 98771Speter /* 99771Speter * The root of the tree tells us what sort of expression we have. 100771Speter */ 10115931Smckusick switch (r->tag) { 102771Speter 103771Speter /* 104771Speter * The constant nil 105771Speter */ 106771Speter case T_NIL: 107771Speter # ifdef OBJ 10815931Smckusick (void) put(2, O_CON2, 0); 109771Speter # endif OBJ 110771Speter # ifdef PC 11118468Sralph putleaf( PCC_ICON , 0 , 0 , PCCTM_PTR|PCCT_UNDEF , (char *) 0 ); 112771Speter # endif PC 113771Speter return (nl+TNIL); 114771Speter 115771Speter /* 116771Speter * Function call with arguments. 117771Speter */ 118771Speter case T_FCALL: 119771Speter # ifdef OBJ 120771Speter return (funccod(r)); 121771Speter # endif OBJ 122771Speter # ifdef PC 123771Speter return (pcfunccod( r )); 124771Speter # endif PC 125771Speter 126771Speter case T_VAR: 12715931Smckusick p = lookup(r->var_node.cptr); 12815931Smckusick if (p == NLNIL || p->class == BADUSE) 12915931Smckusick return (NLNIL); 130771Speter switch (p->class) { 131771Speter case VAR: 132771Speter /* 133771Speter * If a variable is 134771Speter * qualified then get 135771Speter * the rvalue by a 136771Speter * lvalue and an ind. 137771Speter */ 13815931Smckusick if (r->var_node.qual != TR_NIL) 139771Speter goto ind; 140771Speter q = p->type; 141771Speter if (q == NIL) 14215931Smckusick return (NLNIL); 143771Speter # ifdef OBJ 144771Speter w = width(q); 145771Speter switch (w) { 146771Speter case 8: 14715931Smckusick (void) put(2, O_RV8 | bn << 8+INDX, 1483078Smckusic (int)p->value[0]); 149771Speter break; 150771Speter case 4: 15115931Smckusick (void) put(2, O_RV4 | bn << 8+INDX, 1523078Smckusic (int)p->value[0]); 153771Speter break; 154771Speter case 2: 15515931Smckusick (void) put(2, O_RV2 | bn << 8+INDX, 1563078Smckusic (int)p->value[0]); 157771Speter break; 158771Speter case 1: 15915931Smckusick (void) put(2, O_RV1 | bn << 8+INDX, 1603078Smckusic (int)p->value[0]); 161771Speter break; 162771Speter default: 16315931Smckusick (void) put(3, O_RV | bn << 8+INDX, 1643078Smckusic (int)p->value[0], w); 165771Speter } 166771Speter # endif OBJ 167771Speter # ifdef PC 168771Speter if ( required == RREQ ) { 1693834Speter putRV( p -> symbol , bn , p -> value[0] , 1703834Speter p -> extra_flags , p2type( q ) ); 171771Speter } else { 1723834Speter putLV( p -> symbol , bn , p -> value[0] , 1733834Speter p -> extra_flags , p2type( q ) ); 174771Speter } 175771Speter # endif PC 176771Speter return (q); 177771Speter 178771Speter case WITHPTR: 179771Speter case REF: 180771Speter /* 181771Speter * A lvalue for these 182771Speter * is actually what one 183771Speter * might consider a rvalue. 184771Speter */ 185771Speter ind: 186771Speter q = lvalue(r, NOFLAGS , LREQ ); 187771Speter if (q == NIL) 18815931Smckusick return (NLNIL); 189771Speter # ifdef OBJ 190771Speter w = width(q); 191771Speter switch (w) { 192771Speter case 8: 19315931Smckusick (void) put(1, O_IND8); 194771Speter break; 195771Speter case 4: 19615931Smckusick (void) put(1, O_IND4); 197771Speter break; 198771Speter case 2: 19915931Smckusick (void) put(1, O_IND2); 200771Speter break; 201771Speter case 1: 20215931Smckusick (void) put(1, O_IND1); 203771Speter break; 204771Speter default: 20515931Smckusick (void) put(2, O_IND, w); 206771Speter } 207771Speter # endif OBJ 208771Speter # ifdef PC 209771Speter if ( required == RREQ ) { 21018468Sralph putop( PCCOM_UNARY PCC_MUL , p2type( q ) ); 211771Speter } 212771Speter # endif PC 213771Speter return (q); 214771Speter 215771Speter case CONST: 21615931Smckusick if (r->var_node.qual != TR_NIL) { 21715931Smckusick error("%s is a constant and cannot be qualified", r->var_node.cptr); 21815931Smckusick return (NLNIL); 219771Speter } 220771Speter q = p->type; 22115931Smckusick if (q == NLNIL) 22215931Smckusick return (NLNIL); 223771Speter if (q == nl+TSTR) { 224771Speter /* 225771Speter * Find the size of the string 226771Speter * constant if needed. 227771Speter */ 22815931Smckusick cp = (char *) p->ptr[0]; 229771Speter cstrng: 230771Speter cp1 = cp; 231771Speter for (c = 0; *cp++; c++) 232771Speter continue; 2333078Smckusic w = c; 234771Speter if (contype != NIL && !opt('s')) { 235771Speter if (width(contype) < c && classify(contype) == TSTR) { 236771Speter error("Constant string too long"); 23715931Smckusick return (NLNIL); 238771Speter } 2393078Smckusic w = width(contype); 240771Speter } 241771Speter # ifdef OBJ 24215931Smckusick (void) put(2, O_CONG, w); 2433078Smckusic putstr(cp1, w - c); 244771Speter # endif OBJ 245771Speter # ifdef PC 2463155Smckusic putCONG( cp1 , w , required ); 247771Speter # endif PC 248771Speter /* 249771Speter * Define the string temporarily 250771Speter * so later people can know its 251771Speter * width. 252771Speter * cleaned out by stat. 253771Speter */ 25415931Smckusick q = defnl((char *) 0, STR, NLNIL, w); 255771Speter q->type = q; 256771Speter return (q); 257771Speter } 258771Speter if (q == nl+T1CHAR) { 259771Speter # ifdef OBJ 26015931Smckusick (void) put(2, O_CONC, (int)p->value[0]); 261771Speter # endif OBJ 262771Speter # ifdef PC 26318468Sralph putleaf( PCC_ICON , p -> value[0] , 0 26418468Sralph , PCCT_CHAR , (char *) 0 ); 265771Speter # endif PC 266771Speter return (q); 267771Speter } 268771Speter /* 269771Speter * Every other kind of constant here 270771Speter */ 271771Speter switch (width(q)) { 272771Speter case 8: 273771Speter #ifndef DEBUG 274771Speter # ifdef OBJ 27515931Smckusick (void) put(2, O_CON8, p->real); 276771Speter # endif OBJ 277771Speter # ifdef PC 278771Speter putCON8( p -> real ); 279771Speter # endif PC 280771Speter #else 281771Speter if (hp21mx) { 28215931Smckusick f.pdouble = p->real; 28315931Smckusick conv((int *) (&f.pdouble)); 28415931Smckusick l = f.plong[1]; 28515931Smckusick (void) put(2, O_CON4, l); 286771Speter } else 287771Speter # ifdef OBJ 28815931Smckusick (void) put(2, O_CON8, p->real); 289771Speter # endif OBJ 290771Speter # ifdef PC 291771Speter putCON8( p -> real ); 292771Speter # endif PC 293771Speter #endif 294771Speter break; 295771Speter case 4: 296771Speter # ifdef OBJ 29715931Smckusick (void) put(2, O_CON4, p->range[0]); 298771Speter # endif OBJ 299771Speter # ifdef PC 30018468Sralph putleaf( PCC_ICON , (int) p->range[0] , 0 30118468Sralph , PCCT_INT , (char *) 0 ); 302771Speter # endif PC 303771Speter break; 304771Speter case 2: 305771Speter # ifdef OBJ 30615931Smckusick (void) put(2, O_CON2, (short)p->range[0]); 307771Speter # endif OBJ 308771Speter # ifdef PC 30918468Sralph putleaf( PCC_ICON , (short) p -> range[0] 31018468Sralph , 0 , PCCT_SHORT , (char *) 0 ); 311771Speter # endif PC 312771Speter break; 313771Speter case 1: 314771Speter # ifdef OBJ 31515931Smckusick (void) put(2, O_CON1, p->value[0]); 316771Speter # endif OBJ 317771Speter # ifdef PC 31818468Sralph putleaf( PCC_ICON , p -> value[0] , 0 31918468Sralph , PCCT_CHAR , (char *) 0 ); 320771Speter # endif PC 321771Speter break; 322771Speter default: 323771Speter panic("rval"); 324771Speter } 325771Speter return (q); 326771Speter 327771Speter case FUNC: 3281200Speter case FFUNC: 329771Speter /* 330771Speter * Function call with no arguments. 331771Speter */ 33215931Smckusick if (r->var_node.qual != TR_NIL) { 333771Speter error("Can't qualify a function result value"); 33415931Smckusick return (NLNIL); 335771Speter } 336771Speter # ifdef OBJ 33715931Smckusick return (funccod(r)); 338771Speter # endif OBJ 339771Speter # ifdef PC 340771Speter return (pcfunccod( r )); 341771Speter # endif PC 342771Speter 343771Speter case TYPE: 344771Speter error("Type names (e.g. %s) allowed only in declarations", p->symbol); 34515931Smckusick return (NLNIL); 346771Speter 347771Speter case PROC: 3481200Speter case FPROC: 349771Speter error("Procedure %s found where expression required", p->symbol); 35015931Smckusick return (NLNIL); 351771Speter default: 352771Speter panic("rvid"); 353771Speter } 354771Speter /* 355771Speter * Constant sets 356771Speter */ 357771Speter case T_CSET: 358771Speter # ifdef OBJ 359771Speter if ( precset( r , contype , &csetd ) ) { 360771Speter if ( csetd.csettype == NIL ) { 36115931Smckusick return (NLNIL); 362771Speter } 363771Speter postcset( r , &csetd ); 364771Speter } else { 36515931Smckusick (void) put( 2, O_PUSH, -lwidth(csetd.csettype)); 366771Speter postcset( r , &csetd ); 367771Speter setran( ( csetd.csettype ) -> type ); 36815931Smckusick (void) put( 2, O_CON24, set.uprbp); 36915931Smckusick (void) put( 2, O_CON24, set.lwrb); 37015931Smckusick (void) put( 2, O_CTTOT, 3713078Smckusic (int)(4 + csetd.singcnt + 2 * csetd.paircnt)); 372771Speter } 373771Speter return csetd.csettype; 374771Speter # endif OBJ 375771Speter # ifdef PC 376771Speter if ( precset( r , contype , &csetd ) ) { 377771Speter if ( csetd.csettype == NIL ) { 37815931Smckusick return (NLNIL); 379771Speter } 380771Speter postcset( r , &csetd ); 381771Speter } else { 38218468Sralph putleaf( PCC_ICON , 0 , 0 38318468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 384771Speter , "_CTTOT" ); 385771Speter /* 386771Speter * allocate a temporary and use it 387771Speter */ 3883834Speter tempnlp = tmpalloc(lwidth(csetd.csettype), 3893227Smckusic csetd.csettype, NOREG); 39015931Smckusick putLV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 39118468Sralph tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 392771Speter setran( ( csetd.csettype ) -> type ); 39318468Sralph putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 ); 39418468Sralph putop( PCC_CM , PCCT_INT ); 39518468Sralph putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 ); 39618468Sralph putop( PCC_CM , PCCT_INT ); 397771Speter postcset( r , &csetd ); 39818468Sralph putop( PCC_CALL , PCCT_INT ); 399771Speter } 400771Speter return csetd.csettype; 401771Speter # endif PC 402771Speter 403771Speter /* 404771Speter * Unary plus and minus 405771Speter */ 406771Speter case T_PLUS: 407771Speter case T_MINUS: 40815931Smckusick q = rvalue(r->un_expr.expr, NLNIL , RREQ ); 40915931Smckusick if (q == NLNIL) 41015931Smckusick return (NLNIL); 411771Speter if (isnta(q, "id")) { 412771Speter error("Operand of %s must be integer or real, not %s", opname, nameof(q)); 41315931Smckusick return (NLNIL); 414771Speter } 41515931Smckusick if (r->tag == T_MINUS) { 416771Speter # ifdef OBJ 41715931Smckusick (void) put(1, O_NEG2 + (width(q) >> 2)); 41810670Speter return (isa(q, "d") ? q : nl+T4INT); 419771Speter # endif OBJ 420771Speter # ifdef PC 42110670Speter if (isa(q, "i")) { 42218468Sralph sconv(p2type(q), PCCT_INT); 42318468Sralph putop( PCCOM_UNARY PCC_MINUS, PCCT_INT); 42410670Speter return nl+T4INT; 42510670Speter } 42618468Sralph putop( PCCOM_UNARY PCC_MINUS, PCCT_DOUBLE); 42710670Speter return nl+TDOUBLE; 428771Speter # endif PC 429771Speter } 430771Speter return (q); 431771Speter 432771Speter case T_NOT: 43315931Smckusick q = rvalue(r->un_expr.expr, NLNIL , RREQ ); 43415931Smckusick if (q == NLNIL) 43515931Smckusick return (NLNIL); 436771Speter if (isnta(q, "b")) { 437771Speter error("not must operate on a Boolean, not %s", nameof(q)); 43815931Smckusick return (NLNIL); 439771Speter } 440771Speter # ifdef OBJ 44115931Smckusick (void) put(1, O_NOT); 442771Speter # endif OBJ 443771Speter # ifdef PC 44418468Sralph sconv(p2type(q), PCCT_INT); 44518468Sralph putop( PCC_NOT , PCCT_INT); 44618468Sralph sconv(PCCT_INT, p2type(q)); 447771Speter # endif PC 448771Speter return (nl+T1BOOL); 449771Speter 450771Speter case T_AND: 451771Speter case T_OR: 45215931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 45310364Smckusick # ifdef PC 45418468Sralph sconv(p2type(p),PCCT_INT); 45510364Smckusick # endif PC 45615931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 45710364Smckusick # ifdef PC 45818468Sralph sconv(p2type(p1),PCCT_INT); 45910364Smckusick # endif PC 46015931Smckusick if (p == NLNIL || p1 == NLNIL) 46115931Smckusick return (NLNIL); 462771Speter if (isnta(p, "b")) { 463771Speter error("Left operand of %s must be Boolean, not %s", opname, nameof(p)); 46415931Smckusick return (NLNIL); 465771Speter } 466771Speter if (isnta(p1, "b")) { 467771Speter error("Right operand of %s must be Boolean, not %s", opname, nameof(p1)); 46815931Smckusick return (NLNIL); 469771Speter } 470771Speter # ifdef OBJ 47115931Smckusick (void) put(1, r->tag == T_AND ? O_AND : O_OR); 472771Speter # endif OBJ 473771Speter # ifdef PC 474771Speter /* 475771Speter * note the use of & and | rather than && and || 476771Speter * to force evaluation of all the expressions. 477771Speter */ 47818468Sralph putop( r->tag == T_AND ? PCC_AND : PCC_OR , PCCT_INT ); 47918468Sralph sconv(PCCT_INT, p2type(p)); 480771Speter # endif PC 481771Speter return (nl+T1BOOL); 482771Speter 483771Speter case T_DIVD: 484771Speter # ifdef OBJ 48515931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 48615931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 487771Speter # endif OBJ 488771Speter # ifdef PC 489771Speter /* 490771Speter * force these to be doubles for the divide 491771Speter */ 49215931Smckusick p = rvalue( r->expr_node.lhs , NLNIL , RREQ ); 49318468Sralph sconv(p2type(p), PCCT_DOUBLE); 49415931Smckusick p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ ); 49518468Sralph sconv(p2type(p1), PCCT_DOUBLE); 496771Speter # endif PC 49715931Smckusick if (p == NLNIL || p1 == NLNIL) 49815931Smckusick return (NLNIL); 499771Speter if (isnta(p, "id")) { 500771Speter error("Left operand of / must be integer or real, not %s", nameof(p)); 50115931Smckusick return (NLNIL); 502771Speter } 503771Speter if (isnta(p1, "id")) { 504771Speter error("Right operand of / must be integer or real, not %s", nameof(p1)); 50515931Smckusick return (NLNIL); 506771Speter } 507771Speter # ifdef OBJ 50815931Smckusick return gen(NIL, r->tag, width(p), width(p1)); 509771Speter # endif OBJ 510771Speter # ifdef PC 51118468Sralph putop( PCC_DIV , PCCT_DOUBLE ); 512771Speter return nl + TDOUBLE; 513771Speter # endif PC 514771Speter 515771Speter case T_MULT: 516771Speter case T_ADD: 517771Speter case T_SUB: 518771Speter # ifdef OBJ 519771Speter /* 52016273Speter * get the type of the right hand side. 52116273Speter * if it turns out to be a set, 52216273Speter * use that type when getting 52316273Speter * the type of the left hand side. 52416273Speter * and then use the type of the left hand side 52516273Speter * when generating code. 52616273Speter * this will correctly decide the type of any 52716273Speter * empty sets in the tree, since if the empty set 52816273Speter * is on the left hand side it will inherit 52916273Speter * the type of the right hand side, 53016273Speter * and if it's on the right hand side, its type (intset) 53116273Speter * will be overridden by the type of the left hand side. 53216273Speter * this is an awful lot of tree traversing, 53316273Speter * but it works. 534771Speter */ 53516273Speter codeoff(); 53616273Speter p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ ); 53716273Speter codeon(); 53816273Speter if ( p1 == NLNIL ) { 53915931Smckusick return NLNIL; 5401555Speter } 54116273Speter if (isa(p1, "t")) { 54216273Speter codeoff(); 54316273Speter contype = rvalue(r->expr_node.lhs, p1, RREQ); 54416273Speter codeon(); 54516273Speter if (contype == NLNIL) { 54616273Speter return NLNIL; 54716273Speter } 54816273Speter } 54915931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 55015931Smckusick p1 = rvalue( r->expr_node.rhs , p , RREQ ); 55115937Smckusick if ( p == NLNIL || p1 == NLNIL ) 55215931Smckusick return NLNIL; 553771Speter if (isa(p, "id") && isa(p1, "id")) 55415931Smckusick return (gen(NIL, r->tag, width(p), width(p1))); 555771Speter if (isa(p, "t") && isa(p1, "t")) { 556771Speter if (p != p1) { 557771Speter error("Set types of operands of %s must be identical", opname); 55815931Smckusick return (NLNIL); 559771Speter } 56015931Smckusick (void) gen(TSET, r->tag, width(p), 0); 561771Speter return (p); 562771Speter } 563771Speter # endif OBJ 564771Speter # ifdef PC 565771Speter /* 566771Speter * the second pass can't do 567771Speter * long op double or double op long 56816273Speter * so we have to know the type of both operands. 56916273Speter * also, see the note for obj above on determining 57016273Speter * the type of empty sets. 571771Speter */ 572771Speter codeoff(); 57316273Speter p1 = rvalue(r->expr_node.rhs, NLNIL, RREQ); 574771Speter codeon(); 575771Speter if ( isa( p1 , "id" ) ) { 57615931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 57715937Smckusick if ( ( p == NLNIL ) || ( p1 == NLNIL ) ) { 57815931Smckusick return NLNIL; 579771Speter } 58015931Smckusick tuac(p, p1, &rettype, (int *) (&ctype)); 58115931Smckusick p1 = rvalue( r->expr_node.rhs , contype , RREQ ); 58215931Smckusick tuac(p1, p, &rettype, (int *) (&ctype)); 583771Speter if ( isa( p , "id" ) ) { 58415931Smckusick putop( (int) mathop[r->tag - T_MULT], (int) ctype); 585771Speter return rettype; 586771Speter } 587771Speter } 588771Speter if ( isa( p1 , "t" ) ) { 58918468Sralph putleaf( PCC_ICON , 0 , 0 59018468Sralph , PCCM_ADDTYPE( PCCM_ADDTYPE( PCCTM_PTR | PCCT_STRTY , PCCTM_FTN ) 59118468Sralph , PCCTM_PTR ) 59215931Smckusick , setop[ r->tag - T_MULT ] ); 59316273Speter codeoff(); 59416273Speter contype = rvalue( r->expr_node.lhs, p1 , LREQ ); 59516273Speter codeon(); 59615937Smckusick if ( contype == NLNIL ) { 59715931Smckusick return NLNIL; 5981555Speter } 5991555Speter /* 6001555Speter * allocate a temporary and use it 6011555Speter */ 6023834Speter tempnlp = tmpalloc(lwidth(contype), contype, NOREG); 60315931Smckusick putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 60418468Sralph tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 60515931Smckusick p = rvalue( r->expr_node.lhs , contype , LREQ ); 606771Speter if ( isa( p , "t" ) ) { 60718468Sralph putop( PCC_CM , PCCT_INT ); 60815937Smckusick if ( p == NLNIL || p1 == NLNIL ) { 60915931Smckusick return NLNIL; 610771Speter } 61115931Smckusick p1 = rvalue( r->expr_node.rhs , p , LREQ ); 612771Speter if ( p != p1 ) { 613771Speter error("Set types of operands of %s must be identical", opname); 61415931Smckusick return NLNIL; 615771Speter } 61618468Sralph putop( PCC_CM , PCCT_INT ); 61718468Sralph putleaf( PCC_ICON , (int) (lwidth(p1)) / sizeof( long ) , 0 61818468Sralph , PCCT_INT , (char *) 0 ); 61918468Sralph putop( PCC_CM , PCCT_INT ); 62018468Sralph putop( PCC_CALL , PCCTM_PTR | PCCT_STRTY ); 621771Speter return p; 622771Speter } 623771Speter } 624771Speter if ( isnta( p1 , "idt" ) ) { 625771Speter /* 626771Speter * find type of left operand for error message. 627771Speter */ 62815931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 629771Speter } 630771Speter /* 631771Speter * don't give spurious error messages. 632771Speter */ 63315937Smckusick if ( p == NLNIL || p1 == NLNIL ) { 63415931Smckusick return NLNIL; 635771Speter } 636771Speter # endif PC 637771Speter if (isnta(p, "idt")) { 638771Speter error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p)); 63915931Smckusick return (NLNIL); 640771Speter } 641771Speter if (isnta(p1, "idt")) { 642771Speter error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1)); 64315931Smckusick return (NLNIL); 644771Speter } 645771Speter error("Cannot mix sets with integers and reals as operands of %s", opname); 64615931Smckusick return (NLNIL); 647771Speter 648771Speter case T_MOD: 649771Speter case T_DIV: 65015931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 65110364Smckusick # ifdef PC 65218468Sralph sconv(p2type(p), PCCT_INT); 65330839Smckusick # ifdef tahoe 65430839Smckusick /* prepare for ediv workaround, see below. */ 65530839Smckusick if (r->tag == T_MOD) { 65630839Smckusick (void) rvalue(r->expr_node.lhs, NLNIL, RREQ); 65730839Smckusick sconv(p2type(p), PCCT_INT); 65830839Smckusick } 65930839Smckusick # endif tahoe 66010364Smckusick # endif PC 66115931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 66210364Smckusick # ifdef PC 66318468Sralph sconv(p2type(p1), PCCT_INT); 66410364Smckusick # endif PC 66515937Smckusick if (p == NLNIL || p1 == NLNIL) 66615931Smckusick return (NLNIL); 667771Speter if (isnta(p, "i")) { 668771Speter error("Left operand of %s must be integer, not %s", opname, nameof(p)); 66915931Smckusick return (NLNIL); 670771Speter } 671771Speter if (isnta(p1, "i")) { 672771Speter error("Right operand of %s must be integer, not %s", opname, nameof(p1)); 67315931Smckusick return (NLNIL); 674771Speter } 675771Speter # ifdef OBJ 67615931Smckusick return (gen(NIL, r->tag, width(p), width(p1))); 677771Speter # endif OBJ 678771Speter # ifdef PC 67930839Smckusick # ifndef tahoe 68018468Sralph putop( r->tag == T_DIV ? PCC_DIV : PCC_MOD , PCCT_INT ); 681771Speter return ( nl + T4INT ); 68230839Smckusick # else tahoe 68330839Smckusick putop( PCC_DIV , PCCT_INT ); 68430839Smckusick if (r->tag == T_MOD) { 68530839Smckusick /* 68630839Smckusick * avoid f1 bug: PCC_MOD would generate an 'ediv', 68730839Smckusick * which would reuire too many registers to evaluate 68830839Smckusick * things like 68930839Smckusick * var i:boolean;j:integer; i := (j+1) = (j mod 2); 69030839Smckusick * so, instead of 69130839Smckusick * PCC_MOD 69230839Smckusick * / \ 69330839Smckusick * p p1 69430839Smckusick * we put 69530839Smckusick * PCC_MINUS 69630839Smckusick * / \ 69730839Smckusick * p PCC_MUL 69830839Smckusick * / \ 69930839Smckusick * PCC_DIV p1 70030839Smckusick * / \ 70130839Smckusick * p p1 70230839Smckusick * 70330839Smckusick * we already have put p, p, p1, PCC_DIV. and now... 70430839Smckusick */ 70530839Smckusick rvalue(r->expr_node.rhs, NLNIL , RREQ ); 70630839Smckusick sconv(p2type(p1), PCCT_INT); 70730839Smckusick putop( PCC_MUL, PCCT_INT ); 70830839Smckusick putop( PCC_MINUS, PCCT_INT ); 70930839Smckusick } 71030839Smckusick return ( nl + T4INT ); 71130839Smckusick # endif tahoe 712771Speter # endif PC 713771Speter 714771Speter case T_EQ: 715771Speter case T_NE: 716771Speter case T_LT: 717771Speter case T_GT: 718771Speter case T_LE: 719771Speter case T_GE: 720771Speter /* 721771Speter * Since there can be no, a priori, knowledge 722771Speter * of the context type should a constant string 723771Speter * or set arise, we must poke around to find such 724771Speter * a type if possible. Since constant strings can 725771Speter * always masquerade as identifiers, this is always 726771Speter * necessary. 72716273Speter * see the note in the obj section of case T_MULT above 72816273Speter * for the determination of the base type of empty sets. 729771Speter */ 730771Speter codeoff(); 73115931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 732771Speter codeon(); 73315931Smckusick if (p1 == NLNIL) 73415931Smckusick return (NLNIL); 735771Speter contype = p1; 736771Speter # ifdef OBJ 7371555Speter if (p1->class == STR) { 738771Speter /* 739771Speter * For constant strings we want 740771Speter * the longest type so as to be 741771Speter * able to do padding (more importantly 742771Speter * avoiding truncation). For clarity, 743771Speter * we get this length here. 744771Speter */ 745771Speter codeoff(); 74615931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 747771Speter codeon(); 74815931Smckusick if (p == NLNIL) 74915931Smckusick return (NLNIL); 7501555Speter if (width(p) > width(p1)) 751771Speter contype = p; 752771Speter } 75316273Speter if (isa(p1, "t")) { 75416273Speter codeoff(); 75516273Speter contype = rvalue(r->expr_node.lhs, p1, RREQ); 75616273Speter codeon(); 75716273Speter if (contype == NLNIL) { 75816273Speter return NLNIL; 75916273Speter } 76016273Speter } 761771Speter /* 762771Speter * Now we generate code for 763771Speter * the operands of the relational 764771Speter * operation. 765771Speter */ 76615931Smckusick p = rvalue(r->expr_node.lhs, contype , RREQ ); 76715931Smckusick if (p == NLNIL) 76815931Smckusick return (NLNIL); 76915931Smckusick p1 = rvalue(r->expr_node.rhs, p , RREQ ); 77015931Smckusick if (p1 == NLNIL) 77115931Smckusick return (NLNIL); 772771Speter # endif OBJ 773771Speter # ifdef PC 774771Speter c1 = classify( p1 ); 775771Speter if ( c1 == TSET || c1 == TSTR || c1 == TREC ) { 77618468Sralph putleaf( PCC_ICON , 0 , 0 77718468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 77815931Smckusick , c1 == TSET ? relts[ r->tag - T_EQ ] 77915931Smckusick : relss[ r->tag - T_EQ ] ); 780771Speter /* 781771Speter * for [] and strings, comparisons are done on 782771Speter * the maximum width of the two sides. 783771Speter * for other sets, we have to ask the left side 784771Speter * what type it is based on the type of the right. 785771Speter * (this matters for intsets). 786771Speter */ 7871555Speter if ( c1 == TSTR ) { 788771Speter codeoff(); 78915931Smckusick p = rvalue( r->expr_node.lhs , NLNIL , LREQ ); 790771Speter codeon(); 79115931Smckusick if ( p == NLNIL ) { 79215931Smckusick return NLNIL; 7931555Speter } 7941555Speter if ( lwidth( p ) > lwidth( p1 ) ) { 795771Speter contype = p; 796771Speter } 7971555Speter } else if ( c1 == TSET ) { 79815937Smckusick codeoff(); 79916273Speter contype = rvalue(r->expr_node.lhs, p1, LREQ); 80015937Smckusick codeon(); 80116273Speter if (contype == NLNIL) { 80215937Smckusick return NLNIL; 8031555Speter } 8041627Speter } 805771Speter /* 806771Speter * put out the width of the comparison. 807771Speter */ 80818468Sralph putleaf(PCC_ICON, (int) lwidth(contype), 0, PCCT_INT, (char *) 0); 809771Speter /* 810771Speter * and the left hand side, 811771Speter * for sets, strings, records 812771Speter */ 81315931Smckusick p = rvalue( r->expr_node.lhs , contype , LREQ ); 81415931Smckusick if ( p == NLNIL ) { 81515931Smckusick return NLNIL; 8165413Speter } 81718468Sralph putop( PCC_CM , PCCT_INT ); 81815931Smckusick p1 = rvalue( r->expr_node.rhs , p , LREQ ); 81915931Smckusick if ( p1 == NLNIL ) { 82015931Smckusick return NLNIL; 8215413Speter } 82218468Sralph putop( PCC_CM , PCCT_INT ); 82318468Sralph putop( PCC_CALL , PCCT_INT ); 824771Speter } else { 825771Speter /* 826771Speter * the easy (scalar or error) case 827771Speter */ 82815931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 82915931Smckusick if ( p == NLNIL ) { 83015931Smckusick return NLNIL; 8312056Speter } 832771Speter /* 833771Speter * since the second pass can't do 834771Speter * long op double or double op long 835771Speter * we may have to do some coercing. 836771Speter */ 83715931Smckusick tuac(p, p1, &rettype, (int *) (&ctype)); 83815931Smckusick p1 = rvalue( r->expr_node.rhs , p , RREQ ); 83915931Smckusick if ( p1 == NLNIL ) { 84015931Smckusick return NLNIL; 8415413Speter } 84215931Smckusick tuac(p1, p, &rettype, (int *) (&ctype)); 84318468Sralph putop((int) relops[ r->tag - T_EQ ] , PCCT_INT ); 84418468Sralph sconv(PCCT_INT, PCCT_CHAR); 845771Speter } 846771Speter # endif PC 847771Speter c = classify(p); 848771Speter c1 = classify(p1); 849771Speter if (nocomp(c) || nocomp(c1)) 85015931Smckusick return (NLNIL); 85115931Smckusick # ifdef OBJ 85215931Smckusick g = NIL; 85315931Smckusick # endif 854771Speter switch (c) { 855771Speter case TBOOL: 856771Speter case TCHAR: 857771Speter if (c != c1) 858771Speter goto clash; 859771Speter break; 860771Speter case TINT: 861771Speter case TDOUBLE: 862771Speter if (c1 != TINT && c1 != TDOUBLE) 863771Speter goto clash; 864771Speter break; 865771Speter case TSCAL: 866771Speter if (c1 != TSCAL) 867771Speter goto clash; 868771Speter if (scalar(p) != scalar(p1)) 869771Speter goto nonident; 870771Speter break; 871771Speter case TSET: 872771Speter if (c1 != TSET) 873771Speter goto clash; 8743397Speter if ( opt( 's' ) && 87515931Smckusick ( ( r->tag == T_LT) || (r->tag == T_GT) ) && 8763397Speter ( line != nssetline ) ) { 8773397Speter nssetline = line; 8783397Speter standard(); 8793397Speter error("%s comparison on sets is non-standard" , opname ); 8803397Speter } 881771Speter if (p != p1) 882771Speter goto nonident; 88315931Smckusick # ifdef OBJ 88415931Smckusick g = TSET; 88515931Smckusick # endif 886771Speter break; 887771Speter case TREC: 888771Speter if ( c1 != TREC ) { 889771Speter goto clash; 890771Speter } 891771Speter if ( p != p1 ) { 892771Speter goto nonident; 893771Speter } 89415931Smckusick if (r->tag != T_EQ && r->tag != T_NE) { 895771Speter error("%s not allowed on records - only allow = and <>" , opname ); 89615931Smckusick return (NLNIL); 897771Speter } 89815931Smckusick # ifdef OBJ 89915931Smckusick g = TREC; 90015931Smckusick # endif 901771Speter break; 902771Speter case TPTR: 903771Speter case TNIL: 904771Speter if (c1 != TPTR && c1 != TNIL) 905771Speter goto clash; 90615931Smckusick if (r->tag != T_EQ && r->tag != T_NE) { 907771Speter error("%s not allowed on pointers - only allow = and <>" , opname ); 90815931Smckusick return (NLNIL); 909771Speter } 91015937Smckusick if (p != nl+TNIL && p1 != nl+TNIL && p != p1) 91115937Smckusick goto nonident; 912771Speter break; 913771Speter case TSTR: 914771Speter if (c1 != TSTR) 915771Speter goto clash; 916771Speter if (width(p) != width(p1)) { 917771Speter error("Strings not same length in %s comparison", opname); 91815931Smckusick return (NLNIL); 919771Speter } 92015931Smckusick # ifdef OBJ 92115931Smckusick g = TSTR; 92215931Smckusick # endif OBJ 923771Speter break; 924771Speter default: 925771Speter panic("rval2"); 926771Speter } 927771Speter # ifdef OBJ 92815931Smckusick return (gen(g, r->tag, width(p), width(p1))); 929771Speter # endif OBJ 930771Speter # ifdef PC 931771Speter return nl + TBOOL; 932771Speter # endif PC 933771Speter clash: 934771Speter error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname); 93515931Smckusick return (NLNIL); 936771Speter nonident: 937771Speter error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname); 93815931Smckusick return (NLNIL); 939771Speter 940771Speter case T_IN: 94115931Smckusick rt = r->expr_node.rhs; 942771Speter # ifdef OBJ 94315931Smckusick if (rt != TR_NIL && rt->tag == T_CSET) { 94415931Smckusick (void) precset( rt , NLNIL , &csetd ); 945771Speter p1 = csetd.csettype; 94615931Smckusick if (p1 == NLNIL) 94715931Smckusick return NLNIL; 948771Speter postcset( rt, &csetd); 949771Speter } else { 95015931Smckusick p1 = stkrval(r->expr_node.rhs, NLNIL , (long) RREQ ); 95115931Smckusick rt = TR_NIL; 952771Speter } 953771Speter # endif OBJ 954771Speter # ifdef PC 95515931Smckusick if (rt != TR_NIL && rt->tag == T_CSET) { 95615931Smckusick if ( precset( rt , NLNIL , &csetd ) ) { 95718468Sralph putleaf( PCC_ICON , 0 , 0 95818468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 9591555Speter , "_IN" ); 960771Speter } else { 96118468Sralph putleaf( PCC_ICON , 0 , 0 96218468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 963771Speter , "_INCT" ); 964771Speter } 965771Speter p1 = csetd.csettype; 966771Speter if (p1 == NIL) 96715931Smckusick return NLNIL; 968771Speter } else { 96918468Sralph putleaf( PCC_ICON , 0 , 0 97018468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 971771Speter , "_IN" ); 972771Speter codeoff(); 97315931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , LREQ ); 974771Speter codeon(); 975771Speter } 976771Speter # endif PC 97715931Smckusick p = stkrval(r->expr_node.lhs, NLNIL , (long) RREQ ); 978771Speter if (p == NIL || p1 == NIL) 97915931Smckusick return (NLNIL); 98015931Smckusick if (p1->class != (char) SET) { 981771Speter error("Right operand of 'in' must be a set, not %s", nameof(p1)); 98215931Smckusick return (NLNIL); 983771Speter } 98415931Smckusick if (incompat(p, p1->type, r->expr_node.lhs)) { 985771Speter cerror("Index type clashed with set component type for 'in'"); 98615931Smckusick return (NLNIL); 987771Speter } 988771Speter setran(p1->type); 989771Speter # ifdef OBJ 99015931Smckusick if (rt == TR_NIL || csetd.comptime) 99115931Smckusick (void) put(4, O_IN, width(p1), set.lwrb, set.uprbp); 992771Speter else 99315931Smckusick (void) put(2, O_INCT, 9943078Smckusic (int)(3 + csetd.singcnt + 2*csetd.paircnt)); 995771Speter # endif OBJ 996771Speter # ifdef PC 99715931Smckusick if ( rt == TR_NIL || rt->tag != T_CSET ) { 99818468Sralph putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 ); 99918468Sralph putop( PCC_CM , PCCT_INT ); 100018468Sralph putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 ); 100118468Sralph putop( PCC_CM , PCCT_INT ); 100215931Smckusick p1 = rvalue( r->expr_node.rhs , NLNIL , LREQ ); 100315931Smckusick if ( p1 == NLNIL ) { 100415931Smckusick return NLNIL; 10055413Speter } 100618468Sralph putop( PCC_CM , PCCT_INT ); 1007771Speter } else if ( csetd.comptime ) { 100818468Sralph putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 ); 100918468Sralph putop( PCC_CM , PCCT_INT ); 101018468Sralph putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 ); 101118468Sralph putop( PCC_CM , PCCT_INT ); 101215931Smckusick postcset( r->expr_node.rhs , &csetd ); 101318468Sralph putop( PCC_CM , PCCT_INT ); 1014771Speter } else { 101515931Smckusick postcset( r->expr_node.rhs , &csetd ); 1016771Speter } 101718468Sralph putop( PCC_CALL , PCCT_INT ); 101818468Sralph sconv(PCCT_INT, PCCT_CHAR); 1019771Speter # endif PC 1020771Speter return (nl+T1BOOL); 1021771Speter default: 102215931Smckusick if (r->expr_node.lhs == TR_NIL) 102315931Smckusick return (NLNIL); 102415931Smckusick switch (r->tag) { 1025771Speter default: 1026771Speter panic("rval3"); 1027771Speter 1028771Speter 1029771Speter /* 1030771Speter * An octal number 1031771Speter */ 1032771Speter case T_BINT: 103315931Smckusick f.pdouble = a8tol(r->const_node.cptr); 1034771Speter goto conint; 1035771Speter 1036771Speter /* 1037771Speter * A decimal number 1038771Speter */ 1039771Speter case T_INT: 104015931Smckusick f.pdouble = atof(r->const_node.cptr); 1041771Speter conint: 104215931Smckusick if (f.pdouble > MAXINT || f.pdouble < MININT) { 1043771Speter error("Constant too large for this implementation"); 104415931Smckusick return (NLNIL); 1045771Speter } 104615931Smckusick l = f.pdouble; 104710364Smckusick # ifdef OBJ 104810364Smckusick if (bytes(l, l) <= 2) { 104915931Smckusick (void) put(2, O_CON2, ( short ) l); 105010364Smckusick return (nl+T2INT); 105110364Smckusick } 105215931Smckusick (void) put(2, O_CON4, l); 105310364Smckusick return (nl+T4INT); 1054771Speter # endif OBJ 1055771Speter # ifdef PC 105610364Smckusick switch (bytes(l, l)) { 105710364Smckusick case 1: 105818468Sralph putleaf(PCC_ICON, (int) l, 0, PCCT_CHAR, 105915931Smckusick (char *) 0); 106010364Smckusick return nl+T1INT; 106110364Smckusick case 2: 106218468Sralph putleaf(PCC_ICON, (int) l, 0, PCCT_SHORT, 106315931Smckusick (char *) 0); 106410364Smckusick return nl+T2INT; 106510364Smckusick case 4: 106618468Sralph putleaf(PCC_ICON, (int) l, 0, PCCT_INT, 106715931Smckusick (char *) 0); 106810364Smckusick return nl+T4INT; 106910364Smckusick } 1070771Speter # endif PC 1071771Speter 1072771Speter /* 1073771Speter * A floating point number 1074771Speter */ 1075771Speter case T_FINT: 1076771Speter # ifdef OBJ 107715931Smckusick (void) put(2, O_CON8, atof(r->const_node.cptr)); 1078771Speter # endif OBJ 1079771Speter # ifdef PC 108015931Smckusick putCON8( atof( r->const_node.cptr ) ); 1081771Speter # endif PC 1082771Speter return (nl+TDOUBLE); 1083771Speter 1084771Speter /* 1085771Speter * Constant strings. Note that constant characters 1086771Speter * are constant strings of length one; there is 1087771Speter * no constant string of length one. 1088771Speter */ 1089771Speter case T_STRNG: 109015931Smckusick cp = r->const_node.cptr; 1091771Speter if (cp[1] == 0) { 1092771Speter # ifdef OBJ 109315931Smckusick (void) put(2, O_CONC, cp[0]); 1094771Speter # endif OBJ 1095771Speter # ifdef PC 109618468Sralph putleaf( PCC_ICON , cp[0] , 0 , PCCT_CHAR , 109715931Smckusick (char *) 0 ); 1098771Speter # endif PC 1099771Speter return (nl+T1CHAR); 1100771Speter } 1101771Speter goto cstrng; 1102771Speter } 1103771Speter 1104771Speter } 1105771Speter } 1106771Speter 1107771Speter /* 1108771Speter * Can a class appear 1109771Speter * in a comparison ? 1110771Speter */ 1111771Speter nocomp(c) 1112771Speter int c; 1113771Speter { 1114771Speter 1115771Speter switch (c) { 1116771Speter case TREC: 11171627Speter if ( line != reccompline ) { 11181627Speter reccompline = line; 11191627Speter warning(); 11201627Speter if ( opt( 's' ) ) { 11211627Speter standard(); 11221627Speter } 1123771Speter error("record comparison is non-standard"); 1124771Speter } 1125771Speter break; 1126771Speter case TFILE: 1127771Speter case TARY: 1128771Speter error("%ss may not participate in comparisons", clnames[c]); 1129771Speter return (1); 1130771Speter } 1131771Speter return (NIL); 1132771Speter } 1133771Speter 1134771Speter /* 1135771Speter * this is sort of like gconst, except it works on expression trees 1136771Speter * rather than declaration trees, and doesn't give error messages for 1137771Speter * non-constant things. 1138771Speter * as a side effect this fills in the con structure that gconst uses. 1139771Speter * this returns TRUE or FALSE. 1140771Speter */ 114115931Smckusick 114215931Smckusick bool 1143771Speter constval(r) 114415931Smckusick register struct tnode *r; 1145771Speter { 1146771Speter register struct nl *np; 114715931Smckusick register struct tnode *cn; 1148771Speter char *cp; 1149771Speter int negd, sgnd; 1150771Speter long ci; 1151771Speter 1152771Speter con.ctype = NIL; 1153771Speter cn = r; 1154771Speter negd = sgnd = 0; 1155771Speter loop: 1156771Speter /* 1157771Speter * cn[2] is nil if error recovery generated a T_STRNG 1158771Speter */ 115915931Smckusick if (cn == TR_NIL || cn->expr_node.lhs == TR_NIL) 1160771Speter return FALSE; 116115931Smckusick switch (cn->tag) { 1162771Speter default: 1163771Speter return FALSE; 1164771Speter case T_MINUS: 1165771Speter negd = 1 - negd; 1166771Speter /* and fall through */ 1167771Speter case T_PLUS: 1168771Speter sgnd++; 116915931Smckusick cn = cn->un_expr.expr; 1170771Speter goto loop; 1171771Speter case T_NIL: 1172771Speter con.cpval = NIL; 1173771Speter con.cival = 0; 1174771Speter con.crval = con.cival; 1175771Speter con.ctype = nl + TNIL; 1176771Speter break; 1177771Speter case T_VAR: 117815931Smckusick np = lookup(cn->var_node.cptr); 117915931Smckusick if (np == NLNIL || np->class != CONST) { 1180771Speter return FALSE; 1181771Speter } 118215931Smckusick if ( cn->var_node.qual != TR_NIL ) { 1183771Speter return FALSE; 1184771Speter } 1185771Speter con.ctype = np->type; 1186771Speter switch (classify(np->type)) { 1187771Speter case TINT: 1188771Speter con.crval = np->range[0]; 1189771Speter break; 1190771Speter case TDOUBLE: 1191771Speter con.crval = np->real; 1192771Speter break; 1193771Speter case TBOOL: 1194771Speter case TCHAR: 1195771Speter case TSCAL: 1196771Speter con.cival = np->value[0]; 1197771Speter con.crval = con.cival; 1198771Speter break; 1199771Speter case TSTR: 120015931Smckusick con.cpval = (char *) np->ptr[0]; 1201771Speter break; 1202771Speter default: 1203771Speter con.ctype = NIL; 1204771Speter return FALSE; 1205771Speter } 1206771Speter break; 1207771Speter case T_BINT: 120815931Smckusick con.crval = a8tol(cn->const_node.cptr); 1209771Speter goto restcon; 1210771Speter case T_INT: 121115931Smckusick con.crval = atof(cn->const_node.cptr); 1212771Speter if (con.crval > MAXINT || con.crval < MININT) { 1213771Speter derror("Constant too large for this implementation"); 1214771Speter con.crval = 0; 1215771Speter } 1216771Speter restcon: 1217771Speter ci = con.crval; 1218771Speter #ifndef PI0 1219771Speter if (bytes(ci, ci) <= 2) 1220771Speter con.ctype = nl+T2INT; 1221771Speter else 1222771Speter #endif 1223771Speter con.ctype = nl+T4INT; 1224771Speter break; 1225771Speter case T_FINT: 1226771Speter con.ctype = nl+TDOUBLE; 122715931Smckusick con.crval = atof(cn->const_node.cptr); 1228771Speter break; 1229771Speter case T_STRNG: 123015931Smckusick cp = cn->const_node.cptr; 1231771Speter if (cp[1] == 0) { 1232771Speter con.ctype = nl+T1CHAR; 1233771Speter con.cival = cp[0]; 1234771Speter con.crval = con.cival; 1235771Speter break; 1236771Speter } 1237771Speter con.ctype = nl+TSTR; 1238771Speter con.cpval = cp; 1239771Speter break; 1240771Speter } 1241771Speter if (sgnd) { 1242771Speter if (isnta(con.ctype, "id")) { 1243771Speter derror("%s constants cannot be signed", nameof(con.ctype)); 1244771Speter return FALSE; 1245771Speter } else if (negd) 1246771Speter con.crval = -con.crval; 1247771Speter } 1248771Speter return TRUE; 1249771Speter } 1250