148116Sbostic /*-
2*62215Sbostic * Copyright (c) 1980, 1993
3*62215Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622188Sdist */
7771Speter
815945Speter #ifndef lint
9*62215Sbostic static char sccsid[] = "@(#)rval.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #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 *
rvalue(r,contype,required)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 */
nocomp(c)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
constval(r)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