1*22188Sdist /* 2*22188Sdist * Copyright (c) 1980 Regents of the University of California. 3*22188Sdist * All rights reserved. The Berkeley software License Agreement 4*22188Sdist * specifies the terms and conditions for redistribution. 5*22188Sdist */ 6771Speter 715945Speter #ifndef lint 8*22188Sdist static char sccsid[] = "@(#)rval.c 5.1 (Berkeley) 06/05/85"; 9*22188Sdist #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); 65210364Smckusick # endif PC 65315931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 65410364Smckusick # ifdef PC 65518468Sralph sconv(p2type(p1), PCCT_INT); 65610364Smckusick # endif PC 65715937Smckusick if (p == NLNIL || p1 == NLNIL) 65815931Smckusick return (NLNIL); 659771Speter if (isnta(p, "i")) { 660771Speter error("Left operand of %s must be integer, not %s", opname, nameof(p)); 66115931Smckusick return (NLNIL); 662771Speter } 663771Speter if (isnta(p1, "i")) { 664771Speter error("Right operand of %s must be integer, not %s", opname, nameof(p1)); 66515931Smckusick return (NLNIL); 666771Speter } 667771Speter # ifdef OBJ 66815931Smckusick return (gen(NIL, r->tag, width(p), width(p1))); 669771Speter # endif OBJ 670771Speter # ifdef PC 67118468Sralph putop( r->tag == T_DIV ? PCC_DIV : PCC_MOD , PCCT_INT ); 672771Speter return ( nl + T4INT ); 673771Speter # endif PC 674771Speter 675771Speter case T_EQ: 676771Speter case T_NE: 677771Speter case T_LT: 678771Speter case T_GT: 679771Speter case T_LE: 680771Speter case T_GE: 681771Speter /* 682771Speter * Since there can be no, a priori, knowledge 683771Speter * of the context type should a constant string 684771Speter * or set arise, we must poke around to find such 685771Speter * a type if possible. Since constant strings can 686771Speter * always masquerade as identifiers, this is always 687771Speter * necessary. 68816273Speter * see the note in the obj section of case T_MULT above 68916273Speter * for the determination of the base type of empty sets. 690771Speter */ 691771Speter codeoff(); 69215931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 693771Speter codeon(); 69415931Smckusick if (p1 == NLNIL) 69515931Smckusick return (NLNIL); 696771Speter contype = p1; 697771Speter # ifdef OBJ 6981555Speter if (p1->class == STR) { 699771Speter /* 700771Speter * For constant strings we want 701771Speter * the longest type so as to be 702771Speter * able to do padding (more importantly 703771Speter * avoiding truncation). For clarity, 704771Speter * we get this length here. 705771Speter */ 706771Speter codeoff(); 70715931Smckusick p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 708771Speter codeon(); 70915931Smckusick if (p == NLNIL) 71015931Smckusick return (NLNIL); 7111555Speter if (width(p) > width(p1)) 712771Speter contype = p; 713771Speter } 71416273Speter if (isa(p1, "t")) { 71516273Speter codeoff(); 71616273Speter contype = rvalue(r->expr_node.lhs, p1, RREQ); 71716273Speter codeon(); 71816273Speter if (contype == NLNIL) { 71916273Speter return NLNIL; 72016273Speter } 72116273Speter } 722771Speter /* 723771Speter * Now we generate code for 724771Speter * the operands of the relational 725771Speter * operation. 726771Speter */ 72715931Smckusick p = rvalue(r->expr_node.lhs, contype , RREQ ); 72815931Smckusick if (p == NLNIL) 72915931Smckusick return (NLNIL); 73015931Smckusick p1 = rvalue(r->expr_node.rhs, p , RREQ ); 73115931Smckusick if (p1 == NLNIL) 73215931Smckusick return (NLNIL); 733771Speter # endif OBJ 734771Speter # ifdef PC 735771Speter c1 = classify( p1 ); 736771Speter if ( c1 == TSET || c1 == TSTR || c1 == TREC ) { 73718468Sralph putleaf( PCC_ICON , 0 , 0 73818468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 73915931Smckusick , c1 == TSET ? relts[ r->tag - T_EQ ] 74015931Smckusick : relss[ r->tag - T_EQ ] ); 741771Speter /* 742771Speter * for [] and strings, comparisons are done on 743771Speter * the maximum width of the two sides. 744771Speter * for other sets, we have to ask the left side 745771Speter * what type it is based on the type of the right. 746771Speter * (this matters for intsets). 747771Speter */ 7481555Speter if ( c1 == TSTR ) { 749771Speter codeoff(); 75015931Smckusick p = rvalue( r->expr_node.lhs , NLNIL , LREQ ); 751771Speter codeon(); 75215931Smckusick if ( p == NLNIL ) { 75315931Smckusick return NLNIL; 7541555Speter } 7551555Speter if ( lwidth( p ) > lwidth( p1 ) ) { 756771Speter contype = p; 757771Speter } 7581555Speter } else if ( c1 == TSET ) { 75915937Smckusick codeoff(); 76016273Speter contype = rvalue(r->expr_node.lhs, p1, LREQ); 76115937Smckusick codeon(); 76216273Speter if (contype == NLNIL) { 76315937Smckusick return NLNIL; 7641555Speter } 7651627Speter } 766771Speter /* 767771Speter * put out the width of the comparison. 768771Speter */ 76918468Sralph putleaf(PCC_ICON, (int) lwidth(contype), 0, PCCT_INT, (char *) 0); 770771Speter /* 771771Speter * and the left hand side, 772771Speter * for sets, strings, records 773771Speter */ 77415931Smckusick p = rvalue( r->expr_node.lhs , contype , LREQ ); 77515931Smckusick if ( p == NLNIL ) { 77615931Smckusick return NLNIL; 7775413Speter } 77818468Sralph putop( PCC_CM , PCCT_INT ); 77915931Smckusick p1 = rvalue( r->expr_node.rhs , p , LREQ ); 78015931Smckusick if ( p1 == NLNIL ) { 78115931Smckusick return NLNIL; 7825413Speter } 78318468Sralph putop( PCC_CM , PCCT_INT ); 78418468Sralph putop( PCC_CALL , PCCT_INT ); 785771Speter } else { 786771Speter /* 787771Speter * the easy (scalar or error) case 788771Speter */ 78915931Smckusick p = rvalue( r->expr_node.lhs , contype , RREQ ); 79015931Smckusick if ( p == NLNIL ) { 79115931Smckusick return NLNIL; 7922056Speter } 793771Speter /* 794771Speter * since the second pass can't do 795771Speter * long op double or double op long 796771Speter * we may have to do some coercing. 797771Speter */ 79815931Smckusick tuac(p, p1, &rettype, (int *) (&ctype)); 79915931Smckusick p1 = rvalue( r->expr_node.rhs , p , RREQ ); 80015931Smckusick if ( p1 == NLNIL ) { 80115931Smckusick return NLNIL; 8025413Speter } 80315931Smckusick tuac(p1, p, &rettype, (int *) (&ctype)); 80418468Sralph putop((int) relops[ r->tag - T_EQ ] , PCCT_INT ); 80518468Sralph sconv(PCCT_INT, PCCT_CHAR); 806771Speter } 807771Speter # endif PC 808771Speter c = classify(p); 809771Speter c1 = classify(p1); 810771Speter if (nocomp(c) || nocomp(c1)) 81115931Smckusick return (NLNIL); 81215931Smckusick # ifdef OBJ 81315931Smckusick g = NIL; 81415931Smckusick # endif 815771Speter switch (c) { 816771Speter case TBOOL: 817771Speter case TCHAR: 818771Speter if (c != c1) 819771Speter goto clash; 820771Speter break; 821771Speter case TINT: 822771Speter case TDOUBLE: 823771Speter if (c1 != TINT && c1 != TDOUBLE) 824771Speter goto clash; 825771Speter break; 826771Speter case TSCAL: 827771Speter if (c1 != TSCAL) 828771Speter goto clash; 829771Speter if (scalar(p) != scalar(p1)) 830771Speter goto nonident; 831771Speter break; 832771Speter case TSET: 833771Speter if (c1 != TSET) 834771Speter goto clash; 8353397Speter if ( opt( 's' ) && 83615931Smckusick ( ( r->tag == T_LT) || (r->tag == T_GT) ) && 8373397Speter ( line != nssetline ) ) { 8383397Speter nssetline = line; 8393397Speter standard(); 8403397Speter error("%s comparison on sets is non-standard" , opname ); 8413397Speter } 842771Speter if (p != p1) 843771Speter goto nonident; 84415931Smckusick # ifdef OBJ 84515931Smckusick g = TSET; 84615931Smckusick # endif 847771Speter break; 848771Speter case TREC: 849771Speter if ( c1 != TREC ) { 850771Speter goto clash; 851771Speter } 852771Speter if ( p != p1 ) { 853771Speter goto nonident; 854771Speter } 85515931Smckusick if (r->tag != T_EQ && r->tag != T_NE) { 856771Speter error("%s not allowed on records - only allow = and <>" , opname ); 85715931Smckusick return (NLNIL); 858771Speter } 85915931Smckusick # ifdef OBJ 86015931Smckusick g = TREC; 86115931Smckusick # endif 862771Speter break; 863771Speter case TPTR: 864771Speter case TNIL: 865771Speter if (c1 != TPTR && c1 != TNIL) 866771Speter goto clash; 86715931Smckusick if (r->tag != T_EQ && r->tag != T_NE) { 868771Speter error("%s not allowed on pointers - only allow = and <>" , opname ); 86915931Smckusick return (NLNIL); 870771Speter } 87115937Smckusick if (p != nl+TNIL && p1 != nl+TNIL && p != p1) 87215937Smckusick goto nonident; 873771Speter break; 874771Speter case TSTR: 875771Speter if (c1 != TSTR) 876771Speter goto clash; 877771Speter if (width(p) != width(p1)) { 878771Speter error("Strings not same length in %s comparison", opname); 87915931Smckusick return (NLNIL); 880771Speter } 88115931Smckusick # ifdef OBJ 88215931Smckusick g = TSTR; 88315931Smckusick # endif OBJ 884771Speter break; 885771Speter default: 886771Speter panic("rval2"); 887771Speter } 888771Speter # ifdef OBJ 88915931Smckusick return (gen(g, r->tag, width(p), width(p1))); 890771Speter # endif OBJ 891771Speter # ifdef PC 892771Speter return nl + TBOOL; 893771Speter # endif PC 894771Speter clash: 895771Speter error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname); 89615931Smckusick return (NLNIL); 897771Speter nonident: 898771Speter error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname); 89915931Smckusick return (NLNIL); 900771Speter 901771Speter case T_IN: 90215931Smckusick rt = r->expr_node.rhs; 903771Speter # ifdef OBJ 90415931Smckusick if (rt != TR_NIL && rt->tag == T_CSET) { 90515931Smckusick (void) precset( rt , NLNIL , &csetd ); 906771Speter p1 = csetd.csettype; 90715931Smckusick if (p1 == NLNIL) 90815931Smckusick return NLNIL; 909771Speter postcset( rt, &csetd); 910771Speter } else { 91115931Smckusick p1 = stkrval(r->expr_node.rhs, NLNIL , (long) RREQ ); 91215931Smckusick rt = TR_NIL; 913771Speter } 914771Speter # endif OBJ 915771Speter # ifdef PC 91615931Smckusick if (rt != TR_NIL && rt->tag == T_CSET) { 91715931Smckusick if ( precset( rt , NLNIL , &csetd ) ) { 91818468Sralph putleaf( PCC_ICON , 0 , 0 91918468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 9201555Speter , "_IN" ); 921771Speter } else { 92218468Sralph putleaf( PCC_ICON , 0 , 0 92318468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 924771Speter , "_INCT" ); 925771Speter } 926771Speter p1 = csetd.csettype; 927771Speter if (p1 == NIL) 92815931Smckusick return NLNIL; 929771Speter } else { 93018468Sralph putleaf( PCC_ICON , 0 , 0 93118468Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 932771Speter , "_IN" ); 933771Speter codeoff(); 93415931Smckusick p1 = rvalue(r->expr_node.rhs, NLNIL , LREQ ); 935771Speter codeon(); 936771Speter } 937771Speter # endif PC 93815931Smckusick p = stkrval(r->expr_node.lhs, NLNIL , (long) RREQ ); 939771Speter if (p == NIL || p1 == NIL) 94015931Smckusick return (NLNIL); 94115931Smckusick if (p1->class != (char) SET) { 942771Speter error("Right operand of 'in' must be a set, not %s", nameof(p1)); 94315931Smckusick return (NLNIL); 944771Speter } 94515931Smckusick if (incompat(p, p1->type, r->expr_node.lhs)) { 946771Speter cerror("Index type clashed with set component type for 'in'"); 94715931Smckusick return (NLNIL); 948771Speter } 949771Speter setran(p1->type); 950771Speter # ifdef OBJ 95115931Smckusick if (rt == TR_NIL || csetd.comptime) 95215931Smckusick (void) put(4, O_IN, width(p1), set.lwrb, set.uprbp); 953771Speter else 95415931Smckusick (void) put(2, O_INCT, 9553078Smckusic (int)(3 + csetd.singcnt + 2*csetd.paircnt)); 956771Speter # endif OBJ 957771Speter # ifdef PC 95815931Smckusick if ( rt == TR_NIL || rt->tag != T_CSET ) { 95918468Sralph putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 ); 96018468Sralph putop( PCC_CM , PCCT_INT ); 96118468Sralph putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 ); 96218468Sralph putop( PCC_CM , PCCT_INT ); 96315931Smckusick p1 = rvalue( r->expr_node.rhs , NLNIL , LREQ ); 96415931Smckusick if ( p1 == NLNIL ) { 96515931Smckusick return NLNIL; 9665413Speter } 96718468Sralph putop( PCC_CM , PCCT_INT ); 968771Speter } else if ( csetd.comptime ) { 96918468Sralph putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 ); 97018468Sralph putop( PCC_CM , PCCT_INT ); 97118468Sralph putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 ); 97218468Sralph putop( PCC_CM , PCCT_INT ); 97315931Smckusick postcset( r->expr_node.rhs , &csetd ); 97418468Sralph putop( PCC_CM , PCCT_INT ); 975771Speter } else { 97615931Smckusick postcset( r->expr_node.rhs , &csetd ); 977771Speter } 97818468Sralph putop( PCC_CALL , PCCT_INT ); 97918468Sralph sconv(PCCT_INT, PCCT_CHAR); 980771Speter # endif PC 981771Speter return (nl+T1BOOL); 982771Speter default: 98315931Smckusick if (r->expr_node.lhs == TR_NIL) 98415931Smckusick return (NLNIL); 98515931Smckusick switch (r->tag) { 986771Speter default: 987771Speter panic("rval3"); 988771Speter 989771Speter 990771Speter /* 991771Speter * An octal number 992771Speter */ 993771Speter case T_BINT: 99415931Smckusick f.pdouble = a8tol(r->const_node.cptr); 995771Speter goto conint; 996771Speter 997771Speter /* 998771Speter * A decimal number 999771Speter */ 1000771Speter case T_INT: 100115931Smckusick f.pdouble = atof(r->const_node.cptr); 1002771Speter conint: 100315931Smckusick if (f.pdouble > MAXINT || f.pdouble < MININT) { 1004771Speter error("Constant too large for this implementation"); 100515931Smckusick return (NLNIL); 1006771Speter } 100715931Smckusick l = f.pdouble; 100810364Smckusick # ifdef OBJ 100910364Smckusick if (bytes(l, l) <= 2) { 101015931Smckusick (void) put(2, O_CON2, ( short ) l); 101110364Smckusick return (nl+T2INT); 101210364Smckusick } 101315931Smckusick (void) put(2, O_CON4, l); 101410364Smckusick return (nl+T4INT); 1015771Speter # endif OBJ 1016771Speter # ifdef PC 101710364Smckusick switch (bytes(l, l)) { 101810364Smckusick case 1: 101918468Sralph putleaf(PCC_ICON, (int) l, 0, PCCT_CHAR, 102015931Smckusick (char *) 0); 102110364Smckusick return nl+T1INT; 102210364Smckusick case 2: 102318468Sralph putleaf(PCC_ICON, (int) l, 0, PCCT_SHORT, 102415931Smckusick (char *) 0); 102510364Smckusick return nl+T2INT; 102610364Smckusick case 4: 102718468Sralph putleaf(PCC_ICON, (int) l, 0, PCCT_INT, 102815931Smckusick (char *) 0); 102910364Smckusick return nl+T4INT; 103010364Smckusick } 1031771Speter # endif PC 1032771Speter 1033771Speter /* 1034771Speter * A floating point number 1035771Speter */ 1036771Speter case T_FINT: 1037771Speter # ifdef OBJ 103815931Smckusick (void) put(2, O_CON8, atof(r->const_node.cptr)); 1039771Speter # endif OBJ 1040771Speter # ifdef PC 104115931Smckusick putCON8( atof( r->const_node.cptr ) ); 1042771Speter # endif PC 1043771Speter return (nl+TDOUBLE); 1044771Speter 1045771Speter /* 1046771Speter * Constant strings. Note that constant characters 1047771Speter * are constant strings of length one; there is 1048771Speter * no constant string of length one. 1049771Speter */ 1050771Speter case T_STRNG: 105115931Smckusick cp = r->const_node.cptr; 1052771Speter if (cp[1] == 0) { 1053771Speter # ifdef OBJ 105415931Smckusick (void) put(2, O_CONC, cp[0]); 1055771Speter # endif OBJ 1056771Speter # ifdef PC 105718468Sralph putleaf( PCC_ICON , cp[0] , 0 , PCCT_CHAR , 105815931Smckusick (char *) 0 ); 1059771Speter # endif PC 1060771Speter return (nl+T1CHAR); 1061771Speter } 1062771Speter goto cstrng; 1063771Speter } 1064771Speter 1065771Speter } 1066771Speter } 1067771Speter 1068771Speter /* 1069771Speter * Can a class appear 1070771Speter * in a comparison ? 1071771Speter */ 1072771Speter nocomp(c) 1073771Speter int c; 1074771Speter { 1075771Speter 1076771Speter switch (c) { 1077771Speter case TREC: 10781627Speter if ( line != reccompline ) { 10791627Speter reccompline = line; 10801627Speter warning(); 10811627Speter if ( opt( 's' ) ) { 10821627Speter standard(); 10831627Speter } 1084771Speter error("record comparison is non-standard"); 1085771Speter } 1086771Speter break; 1087771Speter case TFILE: 1088771Speter case TARY: 1089771Speter error("%ss may not participate in comparisons", clnames[c]); 1090771Speter return (1); 1091771Speter } 1092771Speter return (NIL); 1093771Speter } 1094771Speter 1095771Speter /* 1096771Speter * this is sort of like gconst, except it works on expression trees 1097771Speter * rather than declaration trees, and doesn't give error messages for 1098771Speter * non-constant things. 1099771Speter * as a side effect this fills in the con structure that gconst uses. 1100771Speter * this returns TRUE or FALSE. 1101771Speter */ 110215931Smckusick 110315931Smckusick bool 1104771Speter constval(r) 110515931Smckusick register struct tnode *r; 1106771Speter { 1107771Speter register struct nl *np; 110815931Smckusick register struct tnode *cn; 1109771Speter char *cp; 1110771Speter int negd, sgnd; 1111771Speter long ci; 1112771Speter 1113771Speter con.ctype = NIL; 1114771Speter cn = r; 1115771Speter negd = sgnd = 0; 1116771Speter loop: 1117771Speter /* 1118771Speter * cn[2] is nil if error recovery generated a T_STRNG 1119771Speter */ 112015931Smckusick if (cn == TR_NIL || cn->expr_node.lhs == TR_NIL) 1121771Speter return FALSE; 112215931Smckusick switch (cn->tag) { 1123771Speter default: 1124771Speter return FALSE; 1125771Speter case T_MINUS: 1126771Speter negd = 1 - negd; 1127771Speter /* and fall through */ 1128771Speter case T_PLUS: 1129771Speter sgnd++; 113015931Smckusick cn = cn->un_expr.expr; 1131771Speter goto loop; 1132771Speter case T_NIL: 1133771Speter con.cpval = NIL; 1134771Speter con.cival = 0; 1135771Speter con.crval = con.cival; 1136771Speter con.ctype = nl + TNIL; 1137771Speter break; 1138771Speter case T_VAR: 113915931Smckusick np = lookup(cn->var_node.cptr); 114015931Smckusick if (np == NLNIL || np->class != CONST) { 1141771Speter return FALSE; 1142771Speter } 114315931Smckusick if ( cn->var_node.qual != TR_NIL ) { 1144771Speter return FALSE; 1145771Speter } 1146771Speter con.ctype = np->type; 1147771Speter switch (classify(np->type)) { 1148771Speter case TINT: 1149771Speter con.crval = np->range[0]; 1150771Speter break; 1151771Speter case TDOUBLE: 1152771Speter con.crval = np->real; 1153771Speter break; 1154771Speter case TBOOL: 1155771Speter case TCHAR: 1156771Speter case TSCAL: 1157771Speter con.cival = np->value[0]; 1158771Speter con.crval = con.cival; 1159771Speter break; 1160771Speter case TSTR: 116115931Smckusick con.cpval = (char *) np->ptr[0]; 1162771Speter break; 1163771Speter default: 1164771Speter con.ctype = NIL; 1165771Speter return FALSE; 1166771Speter } 1167771Speter break; 1168771Speter case T_BINT: 116915931Smckusick con.crval = a8tol(cn->const_node.cptr); 1170771Speter goto restcon; 1171771Speter case T_INT: 117215931Smckusick con.crval = atof(cn->const_node.cptr); 1173771Speter if (con.crval > MAXINT || con.crval < MININT) { 1174771Speter derror("Constant too large for this implementation"); 1175771Speter con.crval = 0; 1176771Speter } 1177771Speter restcon: 1178771Speter ci = con.crval; 1179771Speter #ifndef PI0 1180771Speter if (bytes(ci, ci) <= 2) 1181771Speter con.ctype = nl+T2INT; 1182771Speter else 1183771Speter #endif 1184771Speter con.ctype = nl+T4INT; 1185771Speter break; 1186771Speter case T_FINT: 1187771Speter con.ctype = nl+TDOUBLE; 118815931Smckusick con.crval = atof(cn->const_node.cptr); 1189771Speter break; 1190771Speter case T_STRNG: 119115931Smckusick cp = cn->const_node.cptr; 1192771Speter if (cp[1] == 0) { 1193771Speter con.ctype = nl+T1CHAR; 1194771Speter con.cival = cp[0]; 1195771Speter con.crval = con.cival; 1196771Speter break; 1197771Speter } 1198771Speter con.ctype = nl+TSTR; 1199771Speter con.cpval = cp; 1200771Speter break; 1201771Speter } 1202771Speter if (sgnd) { 1203771Speter if (isnta(con.ctype, "id")) { 1204771Speter derror("%s constants cannot be signed", nameof(con.ctype)); 1205771Speter return FALSE; 1206771Speter } else if (negd) 1207771Speter con.crval = -con.crval; 1208771Speter } 1209771Speter return TRUE; 1210771Speter } 1211