xref: /csrg-svn/usr.bin/pascal/src/rval.c (revision 11328)
1771Speter /* Copyright (c) 1979 Regents of the University of California */
2771Speter 
3*11328Speter static char sccsid[] = "@(#)rval.c 1.16 02/28/83";
4771Speter 
5771Speter #include "whoami.h"
6771Speter #include "0.h"
7771Speter #include "tree.h"
8771Speter #include "opcode.h"
9771Speter #include "objfmt.h"
10771Speter #ifdef PC
11771Speter #   include	"pc.h"
12771Speter #   include "pcops.h"
13771Speter #endif PC
14*11328Speter #include "tmps.h"
15771Speter 
16771Speter extern	char *opnames[];
17771Speter 
181627Speter     /* line number of the last record comparison warning */
191627Speter short reccompline = 0;
203397Speter     /* line number of the last non-standard set comparison */
213397Speter short nssetline = 0;
221627Speter 
23771Speter #ifdef PC
24771Speter     char	*relts[] =  {
25771Speter 				"_RELEQ" , "_RELNE" ,
26771Speter 				"_RELTLT" , "_RELTGT" ,
27771Speter 				"_RELTLE" , "_RELTGE"
28771Speter 			    };
29771Speter     char	*relss[] =  {
30771Speter 				"_RELEQ" , "_RELNE" ,
31771Speter 				"_RELSLT" , "_RELSGT" ,
32771Speter 				"_RELSLE" , "_RELSGE"
33771Speter 			    };
34771Speter     long	relops[] =  {
35771Speter 				P2EQ , P2NE ,
36771Speter 				P2LT , P2GT ,
37771Speter 				P2LE , P2GE
38771Speter 			    };
39771Speter     long	mathop[] =  {	P2MUL , P2PLUS , P2MINUS };
40771Speter     char	*setop[] =  {	"_MULT" , "_ADDT" , "_SUBT" };
41771Speter #endif PC
42771Speter /*
43771Speter  * Rvalue - an expression.
44771Speter  *
45771Speter  * Contype is the type that the caller would prefer, nand is important
46771Speter  * if constant sets or constant strings are involved, the latter
47771Speter  * because of string padding.
48771Speter  * required is a flag whether an lvalue or an rvalue is required.
49771Speter  * only VARs and structured things can have gt their lvalue this way.
50771Speter  */
51771Speter struct nl *
52771Speter rvalue(r, contype , required )
53771Speter 	int *r;
54771Speter 	struct nl *contype;
55771Speter 	int	required;
56771Speter {
57771Speter 	register struct nl *p, *p1;
58771Speter 	register struct nl *q;
59771Speter 	int c, c1, *rt, w, g;
60771Speter 	char *cp, *cp1, *opname;
61771Speter 	long l;
62771Speter 	double f;
63771Speter 	extern int	flagwas;
64771Speter 	struct csetstr	csetd;
65771Speter #	ifdef PC
66771Speter 	    struct nl	*rettype;
67771Speter 	    long	ctype;
683834Speter 	    struct nl	*tempnlp;
69771Speter #	endif PC
70771Speter 
71771Speter 	if (r == NIL)
72771Speter 		return (NIL);
73771Speter 	if (nowexp(r))
74771Speter 		return (NIL);
75771Speter 	/*
76771Speter 	 * Pick up the name of the operation
77771Speter 	 * for future error messages.
78771Speter 	 */
79771Speter 	if (r[0] <= T_IN)
80771Speter 		opname = opnames[r[0]];
81771Speter 
82771Speter 	/*
83771Speter 	 * The root of the tree tells us what sort of expression we have.
84771Speter 	 */
85771Speter 	switch (r[0]) {
86771Speter 
87771Speter 	/*
88771Speter 	 * The constant nil
89771Speter 	 */
90771Speter 	case T_NIL:
91771Speter #		ifdef OBJ
92771Speter 		    put(2, O_CON2, 0);
93771Speter #		endif OBJ
94771Speter #		ifdef PC
951477Speter 		    putleaf( P2ICON , 0 , 0 , P2PTR|P2UNDEF , 0 );
96771Speter #		endif PC
97771Speter 		return (nl+TNIL);
98771Speter 
99771Speter 	/*
100771Speter 	 * Function call with arguments.
101771Speter 	 */
102771Speter 	case T_FCALL:
103771Speter #	    ifdef OBJ
104771Speter 		return (funccod(r));
105771Speter #	    endif OBJ
106771Speter #	    ifdef PC
107771Speter 		return (pcfunccod( r ));
108771Speter #	    endif PC
109771Speter 
110771Speter 	case T_VAR:
111771Speter 		p = lookup(r[2]);
112771Speter 		if (p == NIL || p->class == BADUSE)
113771Speter 			return (NIL);
114771Speter 		switch (p->class) {
115771Speter 		    case VAR:
116771Speter 			    /*
117771Speter 			     * If a variable is
118771Speter 			     * qualified then get
119771Speter 			     * the rvalue by a
120771Speter 			     * lvalue and an ind.
121771Speter 			     */
122771Speter 			    if (r[3] != NIL)
123771Speter 				    goto ind;
124771Speter 			    q = p->type;
125771Speter 			    if (q == NIL)
126771Speter 				    return (NIL);
127771Speter #			    ifdef OBJ
128771Speter 				w = width(q);
129771Speter 				switch (w) {
130771Speter 				    case 8:
1313078Smckusic 					put(2, O_RV8 | bn << 8+INDX,
1323078Smckusic 						(int)p->value[0]);
133771Speter 					break;
134771Speter 				    case 4:
1353078Smckusic 					put(2, O_RV4 | bn << 8+INDX,
1363078Smckusic 						(int)p->value[0]);
137771Speter 					break;
138771Speter 				    case 2:
1393078Smckusic 					put(2, O_RV2 | bn << 8+INDX,
1403078Smckusic 						(int)p->value[0]);
141771Speter 					break;
142771Speter 				    case 1:
1433078Smckusic 					put(2, O_RV1 | bn << 8+INDX,
1443078Smckusic 						(int)p->value[0]);
145771Speter 					break;
146771Speter 				    default:
1473078Smckusic 					put(3, O_RV | bn << 8+INDX,
1483078Smckusic 						(int)p->value[0], w);
149771Speter 				}
150771Speter #			   endif OBJ
151771Speter #			   ifdef PC
152771Speter 				if ( required == RREQ ) {
1533834Speter 				    putRV( p -> symbol , bn , p -> value[0] ,
1543834Speter 					    p -> extra_flags , p2type( q ) );
155771Speter 				} else {
1563834Speter 				    putLV( p -> symbol , bn , p -> value[0] ,
1573834Speter 					    p -> extra_flags , p2type( q ) );
158771Speter 				}
159771Speter #			   endif PC
160771Speter 			   return (q);
161771Speter 
162771Speter 		    case WITHPTR:
163771Speter 		    case REF:
164771Speter 			    /*
165771Speter 			     * A lvalue for these
166771Speter 			     * is actually what one
167771Speter 			     * might consider a rvalue.
168771Speter 			     */
169771Speter ind:
170771Speter 			    q = lvalue(r, NOFLAGS , LREQ );
171771Speter 			    if (q == NIL)
172771Speter 				    return (NIL);
173771Speter #			    ifdef OBJ
174771Speter 				w = width(q);
175771Speter 				switch (w) {
176771Speter 				    case 8:
177771Speter 					    put(1, O_IND8);
178771Speter 					    break;
179771Speter 				    case 4:
180771Speter 					    put(1, O_IND4);
181771Speter 					    break;
182771Speter 				    case 2:
183771Speter 					    put(1, O_IND2);
184771Speter 					    break;
185771Speter 				    case 1:
186771Speter 					    put(1, O_IND1);
187771Speter 					    break;
188771Speter 				    default:
189771Speter 					    put(2, O_IND, w);
190771Speter 				}
191771Speter #			    endif OBJ
192771Speter #			    ifdef PC
193771Speter 				if ( required == RREQ ) {
194771Speter 				    putop( P2UNARY P2MUL , p2type( q ) );
195771Speter 				}
196771Speter #			    endif PC
197771Speter 			    return (q);
198771Speter 
199771Speter 		    case CONST:
200771Speter 			    if (r[3] != NIL) {
201771Speter 				error("%s is a constant and cannot be qualified", r[2]);
202771Speter 				return (NIL);
203771Speter 			    }
204771Speter 			    q = p->type;
205771Speter 			    if (q == NIL)
206771Speter 				    return (NIL);
207771Speter 			    if (q == nl+TSTR) {
208771Speter 				    /*
209771Speter 				     * Find the size of the string
210771Speter 				     * constant if needed.
211771Speter 				     */
212771Speter 				    cp = p->ptr[0];
213771Speter cstrng:
214771Speter 				    cp1 = cp;
215771Speter 				    for (c = 0; *cp++; c++)
216771Speter 					    continue;
2173078Smckusic 				    w = c;
218771Speter 				    if (contype != NIL && !opt('s')) {
219771Speter 					    if (width(contype) < c && classify(contype) == TSTR) {
220771Speter 						    error("Constant string too long");
221771Speter 						    return (NIL);
222771Speter 					    }
2233078Smckusic 					    w = width(contype);
224771Speter 				    }
225771Speter #				    ifdef OBJ
2263078Smckusic 					put(2, O_CONG, w);
2273078Smckusic 					putstr(cp1, w - c);
228771Speter #				    endif OBJ
229771Speter #				    ifdef PC
2303155Smckusic 					putCONG( cp1 , w , required );
231771Speter #				    endif PC
232771Speter 				    /*
233771Speter 				     * Define the string temporarily
234771Speter 				     * so later people can know its
235771Speter 				     * width.
236771Speter 				     * cleaned out by stat.
237771Speter 				     */
2383078Smckusic 				    q = defnl(0, STR, 0, w);
239771Speter 				    q->type = q;
240771Speter 				    return (q);
241771Speter 			    }
242771Speter 			    if (q == nl+T1CHAR) {
243771Speter #				    ifdef OBJ
2443078Smckusic 					put(2, O_CONC, (int)p->value[0]);
245771Speter #				    endif OBJ
246771Speter #				    ifdef PC
247771Speter 					putleaf( P2ICON , p -> value[0] , 0
248771Speter 						, P2CHAR , 0 );
249771Speter #				    endif PC
250771Speter 				    return (q);
251771Speter 			    }
252771Speter 			    /*
253771Speter 			     * Every other kind of constant here
254771Speter 			     */
255771Speter 			    switch (width(q)) {
256771Speter 			    case 8:
257771Speter #ifndef DEBUG
258771Speter #				    ifdef OBJ
259771Speter 					put(2, O_CON8, p->real);
260771Speter #				    endif OBJ
261771Speter #				    ifdef PC
262771Speter 					putCON8( p -> real );
263771Speter #				    endif PC
264771Speter #else
265771Speter 				    if (hp21mx) {
266771Speter 					    f = p->real;
267771Speter 					    conv(&f);
268771Speter 					    l = f.plong;
269771Speter 					    put(2, O_CON4, l);
270771Speter 				    } else
271771Speter #					    ifdef OBJ
272771Speter 						put(2, O_CON8, p->real);
273771Speter #					    endif OBJ
274771Speter #					    ifdef PC
275771Speter 						putCON8( p -> real );
276771Speter #					    endif PC
277771Speter #endif
278771Speter 				    break;
279771Speter 			    case 4:
280771Speter #				    ifdef OBJ
281771Speter 					put(2, O_CON4, p->range[0]);
282771Speter #				    endif OBJ
283771Speter #				    ifdef PC
284771Speter 					putleaf( P2ICON , p -> range[0] , 0
285771Speter 						, P2INT , 0 );
286771Speter #				    endif PC
287771Speter 				    break;
288771Speter 			    case 2:
289771Speter #				    ifdef OBJ
2903078Smckusic 					put(2, O_CON2, (short)p->range[0]);
291771Speter #				    endif OBJ
292771Speter #				    ifdef PC
293771Speter 					putleaf( P2ICON , (short) p -> range[0]
29410364Smckusick 						, 0 , P2SHORT , 0 );
295771Speter #				    endif PC
296771Speter 				    break;
297771Speter 			    case 1:
298771Speter #				    ifdef OBJ
299771Speter 					put(2, O_CON1, p->value[0]);
300771Speter #				    endif OBJ
301771Speter #				    ifdef PC
302771Speter 					putleaf( P2ICON , p -> value[0] , 0
30310364Smckusick 						, P2CHAR , 0 );
304771Speter #				    endif PC
305771Speter 				    break;
306771Speter 			    default:
307771Speter 				    panic("rval");
308771Speter 			    }
309771Speter 			    return (q);
310771Speter 
311771Speter 		    case FUNC:
3121200Speter 		    case FFUNC:
313771Speter 			    /*
314771Speter 			     * Function call with no arguments.
315771Speter 			     */
316771Speter 			    if (r[3]) {
317771Speter 				    error("Can't qualify a function result value");
318771Speter 				    return (NIL);
319771Speter 			    }
320771Speter #			    ifdef OBJ
321771Speter 				return (funccod((int *) r));
322771Speter #			    endif OBJ
323771Speter #			    ifdef PC
324771Speter 				return (pcfunccod( r ));
325771Speter #			    endif PC
326771Speter 
327771Speter 		    case TYPE:
328771Speter 			    error("Type names (e.g. %s) allowed only in declarations", p->symbol);
329771Speter 			    return (NIL);
330771Speter 
331771Speter 		    case PROC:
3321200Speter 		    case FPROC:
333771Speter 			    error("Procedure %s found where expression required", p->symbol);
334771Speter 			    return (NIL);
335771Speter 		    default:
336771Speter 			    panic("rvid");
337771Speter 		}
338771Speter 	/*
339771Speter 	 * Constant sets
340771Speter 	 */
341771Speter 	case T_CSET:
342771Speter #		ifdef OBJ
343771Speter 		    if ( precset( r , contype , &csetd ) ) {
344771Speter 			if ( csetd.csettype == NIL ) {
345771Speter 			    return NIL;
346771Speter 			}
347771Speter 			postcset( r , &csetd );
348771Speter 		    } else {
3493078Smckusic 			put( 2, O_PUSH, -lwidth(csetd.csettype));
350771Speter 			postcset( r , &csetd );
351771Speter 			setran( ( csetd.csettype ) -> type );
352771Speter 			put( 2, O_CON24, set.uprbp);
353771Speter 			put( 2, O_CON24, set.lwrb);
3543078Smckusic 			put( 2, O_CTTOT,
3553078Smckusic 				(int)(4 + csetd.singcnt + 2 * csetd.paircnt));
356771Speter 		    }
357771Speter 		    return csetd.csettype;
358771Speter #		endif OBJ
359771Speter #		ifdef PC
360771Speter 		    if ( precset( r , contype , &csetd ) ) {
361771Speter 			if ( csetd.csettype == NIL ) {
362771Speter 			    return NIL;
363771Speter 			}
364771Speter 			postcset( r , &csetd );
365771Speter 		    } else {
366771Speter 			putleaf( P2ICON , 0 , 0
367771Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR )
368771Speter 				, "_CTTOT" );
369771Speter 			/*
370771Speter 			 *	allocate a temporary and use it
371771Speter 			 */
3723834Speter 			tempnlp = tmpalloc(lwidth(csetd.csettype),
3733227Smckusic 				csetd.csettype, NOREG);
3743834Speter 			putLV( 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
3753834Speter 				tempnlp -> extra_flags , P2PTR|P2STRTY );
376771Speter 			setran( ( csetd.csettype ) -> type );
377771Speter 			putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 );
378771Speter 			putop( P2LISTOP , P2INT );
379771Speter 			putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 );
380771Speter 			putop( P2LISTOP , P2INT );
381771Speter 			postcset( r , &csetd );
382771Speter 			putop( P2CALL , P2INT );
383771Speter 		    }
384771Speter 		    return csetd.csettype;
385771Speter #		endif PC
386771Speter 
387771Speter 	/*
388771Speter 	 * Unary plus and minus
389771Speter 	 */
390771Speter 	case T_PLUS:
391771Speter 	case T_MINUS:
392771Speter 		q = rvalue(r[2], NIL , RREQ );
393771Speter 		if (q == NIL)
394771Speter 			return (NIL);
395771Speter 		if (isnta(q, "id")) {
396771Speter 			error("Operand of %s must be integer or real, not %s", opname, nameof(q));
397771Speter 			return (NIL);
398771Speter 		}
399771Speter 		if (r[0] == T_MINUS) {
400771Speter #		    ifdef OBJ
401771Speter 			put(1, O_NEG2 + (width(q) >> 2));
40210670Speter 			return (isa(q, "d") ? q : nl+T4INT);
403771Speter #		    endif OBJ
404771Speter #		    ifdef PC
40510670Speter 			if (isa(q, "i")) {
40610670Speter 			    sconv(p2type(q), P2INT);
40710670Speter 			    putop( P2UNARY P2MINUS, P2INT);
40810670Speter 			    return nl+T4INT;
40910670Speter 			}
41010670Speter 			putop( P2UNARY P2MINUS, P2DOUBLE);
41110670Speter 			return nl+TDOUBLE;
412771Speter #		    endif PC
413771Speter 		}
414771Speter 		return (q);
415771Speter 
416771Speter 	case T_NOT:
417771Speter 		q = rvalue(r[2], NIL , RREQ );
418771Speter 		if (q == NIL)
419771Speter 			return (NIL);
420771Speter 		if (isnta(q, "b")) {
421771Speter 			error("not must operate on a Boolean, not %s", nameof(q));
422771Speter 			return (NIL);
423771Speter 		}
424771Speter #		ifdef OBJ
425771Speter 		    put(1, O_NOT);
426771Speter #		endif OBJ
427771Speter #		ifdef PC
42810364Smckusick 		    sconv(p2type(q), P2INT);
42910364Smckusick 		    putop( P2NOT , P2INT);
43010364Smckusick 		    sconv(P2INT, p2type(q));
431771Speter #		endif PC
432771Speter 		return (nl+T1BOOL);
433771Speter 
434771Speter 	case T_AND:
435771Speter 	case T_OR:
436771Speter 		p = rvalue(r[2], NIL , RREQ );
43710364Smckusick #		ifdef PC
43810364Smckusick 		    sconv(p2type(p),P2INT);
43910364Smckusick #		endif PC
440771Speter 		p1 = rvalue(r[3], NIL , RREQ );
44110364Smckusick #		ifdef PC
44210364Smckusick 		    sconv(p2type(p1),P2INT);
44310364Smckusick #		endif PC
444771Speter 		if (p == NIL || p1 == NIL)
445771Speter 			return (NIL);
446771Speter 		if (isnta(p, "b")) {
447771Speter 			error("Left operand of %s must be Boolean, not %s", opname, nameof(p));
448771Speter 			return (NIL);
449771Speter 		}
450771Speter 		if (isnta(p1, "b")) {
451771Speter 			error("Right operand of %s must be Boolean, not %s", opname, nameof(p1));
452771Speter 			return (NIL);
453771Speter 		}
454771Speter #		ifdef OBJ
455771Speter 		    put(1, r[0] == T_AND ? O_AND : O_OR);
456771Speter #		endif OBJ
457771Speter #		ifdef PC
458771Speter 			/*
459771Speter 			 * note the use of & and | rather than && and ||
460771Speter 			 * to force evaluation of all the expressions.
461771Speter 			 */
462771Speter 		    putop( r[ 0 ] == T_AND ? P2AND : P2OR , P2INT );
46310364Smckusick 		    sconv(P2INT, p2type(p));
464771Speter #		endif PC
465771Speter 		return (nl+T1BOOL);
466771Speter 
467771Speter 	case T_DIVD:
468771Speter #		ifdef OBJ
469771Speter 		    p = rvalue(r[2], NIL , RREQ );
470771Speter 		    p1 = rvalue(r[3], NIL , RREQ );
471771Speter #		endif OBJ
472771Speter #		ifdef PC
473771Speter 			/*
474771Speter 			 *	force these to be doubles for the divide
475771Speter 			 */
476771Speter 		    p = rvalue( r[ 2 ] , NIL , RREQ );
47710364Smckusick 		    sconv(p2type(p), P2DOUBLE);
478771Speter 		    p1 = rvalue( r[ 3 ] , NIL , RREQ );
47910364Smckusick 		    sconv(p2type(p1), P2DOUBLE);
480771Speter #		endif PC
481771Speter 		if (p == NIL || p1 == NIL)
482771Speter 			return (NIL);
483771Speter 		if (isnta(p, "id")) {
484771Speter 			error("Left operand of / must be integer or real, not %s", nameof(p));
485771Speter 			return (NIL);
486771Speter 		}
487771Speter 		if (isnta(p1, "id")) {
488771Speter 			error("Right operand of / must be integer or real, not %s", nameof(p1));
489771Speter 			return (NIL);
490771Speter 		}
491771Speter #		ifdef OBJ
492771Speter 		    return gen(NIL, r[0], width(p), width(p1));
493771Speter #		endif OBJ
494771Speter #		ifdef PC
495771Speter 		    putop( P2DIV , P2DOUBLE );
496771Speter 		    return nl + TDOUBLE;
497771Speter #		endif PC
498771Speter 
499771Speter 	case T_MULT:
500771Speter 	case T_ADD:
501771Speter 	case T_SUB:
502771Speter #		ifdef OBJ
503771Speter 		    /*
5041555Speter 		     * If the context hasn't told us the type
5051555Speter 		     * and a constant set is present
5061555Speter 		     * we need to infer the type
5071555Speter 		     * before generating code.
508771Speter 		     */
5091555Speter 		    if ( contype == NIL ) {
510771Speter 			    codeoff();
5111555Speter 			    contype = rvalue( r[3] , NIL , RREQ );
512771Speter 			    codeon();
5131555Speter 			    if ( contype == lookup( intset ) -> type ) {
5141555Speter 				codeoff();
5151555Speter 				contype = rvalue( r[2] , NIL , RREQ );
5161555Speter 				codeon();
5171555Speter 			    }
518771Speter 		    }
5191555Speter 		    if ( contype == NIL ) {
5201555Speter 			return NIL;
5211555Speter 		    }
5221555Speter 		    p = rvalue( r[2] , contype , RREQ );
5231555Speter 		    p1 = rvalue( r[3] , p , RREQ );
5241555Speter 		    if ( p == NIL || p1 == NIL )
5251555Speter 			    return NIL;
526771Speter 		    if (isa(p, "id") && isa(p1, "id"))
527771Speter 			return (gen(NIL, r[0], width(p), width(p1)));
528771Speter 		    if (isa(p, "t") && isa(p1, "t")) {
529771Speter 			    if (p != p1) {
530771Speter 				    error("Set types of operands of %s must be identical", opname);
531771Speter 				    return (NIL);
532771Speter 			    }
533771Speter 			    gen(TSET, r[0], width(p), 0);
534771Speter 			    return (p);
535771Speter 		    }
536771Speter #		endif OBJ
537771Speter #		ifdef PC
538771Speter 			/*
539771Speter 			 * the second pass can't do
540771Speter 			 *	long op double  or  double op long
541771Speter 			 * so we have to know the type of both operands
542771Speter 			 * also, it gets tricky for sets, which are done
543771Speter 			 * by function calls.
544771Speter 			 */
545771Speter 		    codeoff();
546771Speter 		    p1 = rvalue( r[ 3 ] , contype , RREQ );
547771Speter 		    codeon();
548771Speter 		    if ( isa( p1 , "id" ) ) {
549771Speter 			p = rvalue( r[ 2 ] , contype , RREQ );
550771Speter 			if ( ( p == NIL ) || ( p1 == NIL ) ) {
551771Speter 			    return NIL;
552771Speter 			}
55310364Smckusick 			tuac(p, p1, &rettype, &ctype);
554771Speter 			p1 = rvalue( r[ 3 ] , contype , RREQ );
55510364Smckusick 			tuac(p1, p, &rettype, &ctype);
556771Speter 			if ( isa( p , "id" ) ) {
557771Speter 			    putop( mathop[ r[0] - T_MULT ] , ctype );
558771Speter 			    return rettype;
559771Speter 			}
560771Speter 		    }
561771Speter 		    if ( isa( p1 , "t" ) ) {
562771Speter 			putleaf( P2ICON , 0 , 0
563771Speter 			    , ADDTYPE( ADDTYPE( P2PTR | P2STRTY , P2FTN )
564771Speter 					, P2PTR )
565771Speter 			    , setop[ r[0] - T_MULT ] );
5661555Speter 			if ( contype == NIL ) {
5671555Speter 			    contype = p1;
5681555Speter 			    if ( contype == lookup( intset ) -> type ) {
5691555Speter 				codeoff();
5701555Speter 				contype = rvalue( r[2] , NIL , LREQ );
5711555Speter 				codeon();
5721555Speter 			    }
5731555Speter 			}
5741555Speter 			if ( contype == NIL ) {
5751555Speter 			    return NIL;
5761555Speter 			}
5771555Speter 			    /*
5781555Speter 			     *	allocate a temporary and use it
5791555Speter 			     */
5803834Speter 			tempnlp = tmpalloc(lwidth(contype), contype, NOREG);
5813834Speter 			putLV( 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
5823834Speter 				tempnlp -> extra_flags , P2PTR|P2STRTY );
5831555Speter 			p = rvalue( r[2] , contype , LREQ );
584771Speter 			if ( isa( p , "t" ) ) {
585771Speter 			    putop( P2LISTOP , P2INT );
586771Speter 			    if ( p == NIL || p1 == NIL ) {
587771Speter 				return NIL;
588771Speter 			    }
589771Speter 			    p1 = rvalue( r[3] , p , LREQ );
590771Speter 			    if ( p != p1 ) {
591771Speter 				error("Set types of operands of %s must be identical", opname);
592771Speter 				return NIL;
593771Speter 			    }
594771Speter 			    putop( P2LISTOP , P2INT );
595771Speter 			    putleaf( P2ICON , lwidth( p1 ) / sizeof( long ) , 0
596771Speter 				    , P2INT , 0 );
597771Speter 			    putop( P2LISTOP , P2INT );
598771Speter 			    putop( P2CALL , P2PTR | P2STRTY );
599771Speter 			    return p;
600771Speter 			}
601771Speter 		    }
602771Speter 		    if ( isnta( p1 , "idt" ) ) {
603771Speter 			    /*
604771Speter 			     *	find type of left operand for error message.
605771Speter 			     */
606771Speter 			p = rvalue( r[2] , contype , RREQ );
607771Speter 		    }
608771Speter 			/*
609771Speter 			 *	don't give spurious error messages.
610771Speter 			 */
611771Speter 		    if ( p == NIL || p1 == NIL ) {
612771Speter 			return NIL;
613771Speter 		    }
614771Speter #		endif PC
615771Speter 		if (isnta(p, "idt")) {
616771Speter 			error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p));
617771Speter 			return (NIL);
618771Speter 		}
619771Speter 		if (isnta(p1, "idt")) {
620771Speter 			error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1));
621771Speter 			return (NIL);
622771Speter 		}
623771Speter 		error("Cannot mix sets with integers and reals as operands of %s", opname);
624771Speter 		return (NIL);
625771Speter 
626771Speter 	case T_MOD:
627771Speter 	case T_DIV:
628771Speter 		p = rvalue(r[2], NIL , RREQ );
62910364Smckusick #		ifdef PC
63010364Smckusick 		    sconv(p2type(p), P2INT);
63110364Smckusick #		endif PC
632771Speter 		p1 = rvalue(r[3], NIL , RREQ );
63310364Smckusick #		ifdef PC
63410364Smckusick 		    sconv(p2type(p1), P2INT);
63510364Smckusick #		endif PC
636771Speter 		if (p == NIL || p1 == NIL)
637771Speter 			return (NIL);
638771Speter 		if (isnta(p, "i")) {
639771Speter 			error("Left operand of %s must be integer, not %s", opname, nameof(p));
640771Speter 			return (NIL);
641771Speter 		}
642771Speter 		if (isnta(p1, "i")) {
643771Speter 			error("Right operand of %s must be integer, not %s", opname, nameof(p1));
644771Speter 			return (NIL);
645771Speter 		}
646771Speter #		ifdef OBJ
647771Speter 		    return (gen(NIL, r[0], width(p), width(p1)));
648771Speter #		endif OBJ
649771Speter #		ifdef PC
650771Speter 		    putop( r[ 0 ] == T_DIV ? P2DIV : P2MOD , P2INT );
651771Speter 		    return ( nl + T4INT );
652771Speter #		endif PC
653771Speter 
654771Speter 	case T_EQ:
655771Speter 	case T_NE:
656771Speter 	case T_LT:
657771Speter 	case T_GT:
658771Speter 	case T_LE:
659771Speter 	case T_GE:
660771Speter 		/*
661771Speter 		 * Since there can be no, a priori, knowledge
662771Speter 		 * of the context type should a constant string
663771Speter 		 * or set arise, we must poke around to find such
664771Speter 		 * a type if possible.  Since constant strings can
665771Speter 		 * always masquerade as identifiers, this is always
666771Speter 		 * necessary.
667771Speter 		 */
668771Speter 		codeoff();
669771Speter 		p1 = rvalue(r[3], NIL , RREQ );
670771Speter 		codeon();
671771Speter 		if (p1 == NIL)
672771Speter 			return (NIL);
673771Speter 		contype = p1;
674771Speter #		ifdef OBJ
6751555Speter 		    if (p1->class == STR) {
676771Speter 			    /*
677771Speter 			     * For constant strings we want
678771Speter 			     * the longest type so as to be
679771Speter 			     * able to do padding (more importantly
680771Speter 			     * avoiding truncation). For clarity,
681771Speter 			     * we get this length here.
682771Speter 			     */
683771Speter 			    codeoff();
684771Speter 			    p = rvalue(r[2], NIL , RREQ );
685771Speter 			    codeon();
686771Speter 			    if (p == NIL)
687771Speter 				    return (NIL);
6881555Speter 			    if (width(p) > width(p1))
689771Speter 				    contype = p;
6901555Speter 		    } else if ( isa( p1 , "t" ) ) {
6911555Speter 			if ( contype == lookup( intset ) -> type ) {
6921555Speter 			    codeoff();
6931555Speter 			    contype = rvalue( r[2] , NIL , RREQ );
6941555Speter 			    codeon();
6951555Speter 			    if ( contype == NIL ) {
6961555Speter 				return NIL;
6971555Speter 			    }
6981555Speter 			}
699771Speter 		    }
700771Speter 		    /*
701771Speter 		     * Now we generate code for
702771Speter 		     * the operands of the relational
703771Speter 		     * operation.
704771Speter 		     */
705771Speter 		    p = rvalue(r[2], contype , RREQ );
706771Speter 		    if (p == NIL)
707771Speter 			    return (NIL);
708771Speter 		    p1 = rvalue(r[3], p , RREQ );
709771Speter 		    if (p1 == NIL)
710771Speter 			    return (NIL);
711771Speter #		endif OBJ
712771Speter #		ifdef PC
713771Speter 		    c1 = classify( p1 );
714771Speter 		    if ( c1 == TSET || c1 == TSTR || c1 == TREC ) {
715771Speter 			putleaf( P2ICON , 0 , 0
716771Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR )
717771Speter 				, c1 == TSET  ? relts[ r[0] - T_EQ ]
718771Speter 					      : relss[ r[0] - T_EQ ] );
719771Speter 			    /*
720771Speter 			     *	for [] and strings, comparisons are done on
721771Speter 			     *	the maximum width of the two sides.
722771Speter 			     *	for other sets, we have to ask the left side
723771Speter 			     *	what type it is based on the type of the right.
724771Speter 			     *	(this matters for intsets).
725771Speter 			     */
7261555Speter 			if ( c1 == TSTR ) {
727771Speter 			    codeoff();
728771Speter 			    p = rvalue( r[ 2 ] , NIL , LREQ );
729771Speter 			    codeon();
7301555Speter 			    if ( p == NIL ) {
7311555Speter 				return NIL;
7321555Speter 			    }
7331555Speter 			    if ( lwidth( p ) > lwidth( p1 ) ) {
734771Speter 				contype = p;
735771Speter 			    }
7361555Speter 			} else if ( c1 == TSET ) {
7371555Speter 			    if ( contype == lookup( intset ) -> type ) {
7381555Speter 				codeoff();
7391555Speter 				p = rvalue( r[ 2 ] , NIL , LREQ );
7401555Speter 				codeon();
7411555Speter 				if ( p == NIL ) {
7421555Speter 				    return NIL;
7431555Speter 				}
7441555Speter 				contype = p;
7451555Speter 			    }
7461627Speter 			}
747771Speter 			    /*
748771Speter 			     *	put out the width of the comparison.
749771Speter 			     */
750771Speter 			putleaf( P2ICON , lwidth( contype ) , 0 , P2INT , 0 );
751771Speter 			    /*
752771Speter 			     *	and the left hand side,
753771Speter 			     *	for sets, strings, records
754771Speter 			     */
755771Speter 			p = rvalue( r[ 2 ] , contype , LREQ );
7565413Speter 			if ( p == NIL ) {
7575413Speter 			    return NIL;
7585413Speter 			}
759771Speter 			putop( P2LISTOP , P2INT );
760771Speter 			p1 = rvalue( r[ 3 ] , p , LREQ );
7615413Speter 			if ( p1 == NIL ) {
7625413Speter 			    return NIL;
7635413Speter 			}
764771Speter 			putop( P2LISTOP , P2INT );
765771Speter 			putop( P2CALL , P2INT );
766771Speter 		    } else {
767771Speter 			    /*
768771Speter 			     *	the easy (scalar or error) case
769771Speter 			     */
770771Speter 			p = rvalue( r[ 2 ] , contype , RREQ );
771771Speter 			if ( p == NIL ) {
772771Speter 			    return NIL;
7732056Speter 			}
774771Speter 			    /*
775771Speter 			     * since the second pass can't do
776771Speter 			     *	long op double  or  double op long
777771Speter 			     * we may have to do some coercing.
778771Speter 			     */
77910364Smckusick 			tuac(p, p1, &rettype, &ctype);
780771Speter 			p1 = rvalue( r[ 3 ] , p , RREQ );
7815413Speter 			if ( p1 == NIL ) {
7825413Speter 			    return NIL;
7835413Speter 			}
78410364Smckusick 			tuac(p1, p, &rettype, &ctype);
785771Speter 			putop( relops[ r[0] - T_EQ ] , P2INT );
78610364Smckusick 			sconv(P2INT, P2CHAR);
787771Speter 		    }
788771Speter #		endif PC
789771Speter 		c = classify(p);
790771Speter 		c1 = classify(p1);
791771Speter 		if (nocomp(c) || nocomp(c1))
792771Speter 			return (NIL);
793771Speter 		g = NIL;
794771Speter 		switch (c) {
795771Speter 			case TBOOL:
796771Speter 			case TCHAR:
797771Speter 				if (c != c1)
798771Speter 					goto clash;
799771Speter 				break;
800771Speter 			case TINT:
801771Speter 			case TDOUBLE:
802771Speter 				if (c1 != TINT && c1 != TDOUBLE)
803771Speter 					goto clash;
804771Speter 				break;
805771Speter 			case TSCAL:
806771Speter 				if (c1 != TSCAL)
807771Speter 					goto clash;
808771Speter 				if (scalar(p) != scalar(p1))
809771Speter 					goto nonident;
810771Speter 				break;
811771Speter 			case TSET:
812771Speter 				if (c1 != TSET)
813771Speter 					goto clash;
8143397Speter 				if ( opt( 's' ) &&
8153397Speter 				    ( ( r[0] == T_LT ) || ( r[0] == T_GT ) ) &&
8163397Speter 				    ( line != nssetline ) ) {
8173397Speter 				    nssetline = line;
8183397Speter 				    standard();
8193397Speter 				    error("%s comparison on sets is non-standard" , opname );
8203397Speter 				}
821771Speter 				if (p != p1)
822771Speter 					goto nonident;
823771Speter 				g = TSET;
824771Speter 				break;
825771Speter 			case TREC:
826771Speter 				if ( c1 != TREC ) {
827771Speter 				    goto clash;
828771Speter 				}
829771Speter 				if ( p != p1 ) {
830771Speter 				    goto nonident;
831771Speter 				}
832771Speter 				if (r[0] != T_EQ && r[0] != T_NE) {
833771Speter 					error("%s not allowed on records - only allow = and <>" , opname );
834771Speter 					return (NIL);
835771Speter 				}
836771Speter 				g = TREC;
837771Speter 				break;
838771Speter 			case TPTR:
839771Speter 			case TNIL:
840771Speter 				if (c1 != TPTR && c1 != TNIL)
841771Speter 					goto clash;
842771Speter 				if (r[0] != T_EQ && r[0] != T_NE) {
843771Speter 					error("%s not allowed on pointers - only allow = and <>" , opname );
844771Speter 					return (NIL);
845771Speter 				}
846771Speter 				break;
847771Speter 			case TSTR:
848771Speter 				if (c1 != TSTR)
849771Speter 					goto clash;
850771Speter 				if (width(p) != width(p1)) {
851771Speter 					error("Strings not same length in %s comparison", opname);
852771Speter 					return (NIL);
853771Speter 				}
854771Speter 				g = TSTR;
855771Speter 				break;
856771Speter 			default:
857771Speter 				panic("rval2");
858771Speter 		}
859771Speter #		ifdef OBJ
860771Speter 		    return (gen(g, r[0], width(p), width(p1)));
861771Speter #		endif OBJ
862771Speter #		ifdef PC
863771Speter 		    return nl + TBOOL;
864771Speter #		endif PC
865771Speter clash:
866771Speter 		error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname);
867771Speter 		return (NIL);
868771Speter nonident:
869771Speter 		error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname);
870771Speter 		return (NIL);
871771Speter 
872771Speter 	case T_IN:
873771Speter 	    rt = r[3];
874771Speter #	    ifdef OBJ
875771Speter 		if (rt != NIL && rt[0] == T_CSET) {
876771Speter 			precset( rt , NIL , &csetd );
877771Speter 			p1 = csetd.csettype;
878771Speter 			if (p1 == NIL)
879771Speter 			    return NIL;
880771Speter 			postcset( rt, &csetd);
881771Speter 		    } else {
882771Speter 			p1 = stkrval(r[3], NIL , RREQ );
883771Speter 			rt = NIL;
884771Speter 		    }
885771Speter #		endif OBJ
886771Speter #		ifdef PC
887771Speter 		    if (rt != NIL && rt[0] == T_CSET) {
888771Speter 			if ( precset( rt , NIL , &csetd ) ) {
8891555Speter 			    putleaf( P2ICON , 0 , 0
8901555Speter 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
8911555Speter 				    , "_IN" );
892771Speter 			} else {
893771Speter 			    putleaf( P2ICON , 0 , 0
894771Speter 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
895771Speter 				    , "_INCT" );
896771Speter 			}
897771Speter 			p1 = csetd.csettype;
898771Speter 			if (p1 == NIL)
899771Speter 			    return NIL;
900771Speter 		    } else {
901771Speter 			putleaf( P2ICON , 0 , 0
902771Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR )
903771Speter 				, "_IN" );
904771Speter 			codeoff();
905771Speter 			p1 = rvalue(r[3], NIL , LREQ );
906771Speter 			codeon();
907771Speter 		    }
908771Speter #		endif PC
909771Speter 		p = stkrval(r[2], NIL , RREQ );
910771Speter 		if (p == NIL || p1 == NIL)
911771Speter 			return (NIL);
912771Speter 		if (p1->class != SET) {
913771Speter 			error("Right operand of 'in' must be a set, not %s", nameof(p1));
914771Speter 			return (NIL);
915771Speter 		}
916771Speter 		if (incompat(p, p1->type, r[2])) {
917771Speter 			cerror("Index type clashed with set component type for 'in'");
918771Speter 			return (NIL);
919771Speter 		}
920771Speter 		setran(p1->type);
921771Speter #		ifdef OBJ
922771Speter 		    if (rt == NIL || csetd.comptime)
923771Speter 			    put(4, O_IN, width(p1), set.lwrb, set.uprbp);
924771Speter 		    else
9253078Smckusic 			    put(2, O_INCT,
9263078Smckusic 				(int)(3 + csetd.singcnt + 2*csetd.paircnt));
927771Speter #		endif OBJ
928771Speter #		ifdef PC
929771Speter 		    if ( rt == NIL || rt[0] != T_CSET ) {
930771Speter 			putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 );
931771Speter 			putop( P2LISTOP , P2INT );
932771Speter 			putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 );
933771Speter 			putop( P2LISTOP , P2INT );
934771Speter 			p1 = rvalue( r[3] , NIL , LREQ );
9355413Speter 			if ( p1 == NIL ) {
9365413Speter 			    return NIL;
9375413Speter 			}
938771Speter 			putop( P2LISTOP , P2INT );
939771Speter 		    } else if ( csetd.comptime ) {
940771Speter 			putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 );
941771Speter 			putop( P2LISTOP , P2INT );
942771Speter 			putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 );
943771Speter 			putop( P2LISTOP , P2INT );
944771Speter 			postcset( r[3] , &csetd );
945771Speter 			putop( P2LISTOP , P2INT );
946771Speter 		    } else {
947771Speter 			postcset( r[3] , &csetd );
948771Speter 		    }
949771Speter 		    putop( P2CALL , P2INT );
95010364Smckusick 		    sconv(P2INT, P2CHAR);
951771Speter #		endif PC
952771Speter 		return (nl+T1BOOL);
953771Speter 	default:
954771Speter 		if (r[2] == NIL)
955771Speter 			return (NIL);
956771Speter 		switch (r[0]) {
957771Speter 		default:
958771Speter 			panic("rval3");
959771Speter 
960771Speter 
961771Speter 		/*
962771Speter 		 * An octal number
963771Speter 		 */
964771Speter 		case T_BINT:
965771Speter 			f = a8tol(r[2]);
966771Speter 			goto conint;
967771Speter 
968771Speter 		/*
969771Speter 		 * A decimal number
970771Speter 		 */
971771Speter 		case T_INT:
972771Speter 			f = atof(r[2]);
973771Speter conint:
974771Speter 			if (f > MAXINT || f < MININT) {
975771Speter 				error("Constant too large for this implementation");
976771Speter 				return (NIL);
977771Speter 			}
978771Speter 			l = f;
97910364Smckusick #			ifdef OBJ
98010364Smckusick 			    if (bytes(l, l) <= 2) {
981771Speter 				    put(2, O_CON2, ( short ) l);
98210364Smckusick 				    return (nl+T2INT);
98310364Smckusick 			    }
984771Speter 			    put(2, O_CON4, l);
98510364Smckusick 			    return (nl+T4INT);
986771Speter #			endif OBJ
987771Speter #			ifdef PC
98810364Smckusick 			    switch (bytes(l, l)) {
98910364Smckusick 				case 1:
99010364Smckusick 				    putleaf(P2ICON, l, 0, P2CHAR, 0);
99110364Smckusick 				    return nl+T1INT;
99210364Smckusick 				case 2:
99310364Smckusick 				    putleaf(P2ICON, l, 0, P2SHORT, 0);
99410364Smckusick 				    return nl+T2INT;
99510364Smckusick 				case 4:
99610364Smckusick 				    putleaf(P2ICON, l, 0, P2INT, 0);
99710364Smckusick 				    return nl+T4INT;
99810364Smckusick 			    }
999771Speter #			endif PC
1000771Speter 
1001771Speter 		/*
1002771Speter 		 * A floating point number
1003771Speter 		 */
1004771Speter 		case T_FINT:
1005771Speter #			ifdef OBJ
1006771Speter 			    put(2, O_CON8, atof(r[2]));
1007771Speter #			endif OBJ
1008771Speter #			ifdef PC
1009771Speter 			    putCON8( atof( r[2] ) );
1010771Speter #			endif PC
1011771Speter 			return (nl+TDOUBLE);
1012771Speter 
1013771Speter 		/*
1014771Speter 		 * Constant strings.  Note that constant characters
1015771Speter 		 * are constant strings of length one; there is
1016771Speter 		 * no constant string of length one.
1017771Speter 		 */
1018771Speter 		case T_STRNG:
1019771Speter 			cp = r[2];
1020771Speter 			if (cp[1] == 0) {
1021771Speter #				ifdef OBJ
1022771Speter 				    put(2, O_CONC, cp[0]);
1023771Speter #				endif OBJ
1024771Speter #				ifdef PC
1025771Speter 				    putleaf( P2ICON , cp[0] , 0 , P2CHAR , 0 );
1026771Speter #				endif PC
1027771Speter 				return (nl+T1CHAR);
1028771Speter 			}
1029771Speter 			goto cstrng;
1030771Speter 		}
1031771Speter 
1032771Speter 	}
1033771Speter }
1034771Speter 
1035771Speter /*
1036771Speter  * Can a class appear
1037771Speter  * in a comparison ?
1038771Speter  */
1039771Speter nocomp(c)
1040771Speter 	int c;
1041771Speter {
1042771Speter 
1043771Speter 	switch (c) {
1044771Speter 		case TREC:
10451627Speter 			if ( line != reccompline ) {
10461627Speter 			    reccompline = line;
10471627Speter 			    warning();
10481627Speter 			    if ( opt( 's' ) ) {
10491627Speter 				standard();
10501627Speter 			    }
1051771Speter 			    error("record comparison is non-standard");
1052771Speter 			}
1053771Speter 			break;
1054771Speter 		case TFILE:
1055771Speter 		case TARY:
1056771Speter 			error("%ss may not participate in comparisons", clnames[c]);
1057771Speter 			return (1);
1058771Speter 	}
1059771Speter 	return (NIL);
1060771Speter }
1061771Speter 
1062771Speter     /*
1063771Speter      *	this is sort of like gconst, except it works on expression trees
1064771Speter      *	rather than declaration trees, and doesn't give error messages for
1065771Speter      *	non-constant things.
1066771Speter      *	as a side effect this fills in the con structure that gconst uses.
1067771Speter      *	this returns TRUE or FALSE.
1068771Speter      */
1069771Speter constval(r)
1070771Speter 	register int *r;
1071771Speter {
1072771Speter 	register struct nl *np;
1073771Speter 	register *cn;
1074771Speter 	char *cp;
1075771Speter 	int negd, sgnd;
1076771Speter 	long ci;
1077771Speter 
1078771Speter 	con.ctype = NIL;
1079771Speter 	cn = r;
1080771Speter 	negd = sgnd = 0;
1081771Speter loop:
1082771Speter 	    /*
1083771Speter 	     *	cn[2] is nil if error recovery generated a T_STRNG
1084771Speter 	     */
1085771Speter 	if (cn == NIL || cn[2] == NIL)
1086771Speter 		return FALSE;
1087771Speter 	switch (cn[0]) {
1088771Speter 		default:
1089771Speter 			return FALSE;
1090771Speter 		case T_MINUS:
1091771Speter 			negd = 1 - negd;
1092771Speter 			/* and fall through */
1093771Speter 		case T_PLUS:
1094771Speter 			sgnd++;
1095771Speter 			cn = cn[2];
1096771Speter 			goto loop;
1097771Speter 		case T_NIL:
1098771Speter 			con.cpval = NIL;
1099771Speter 			con.cival = 0;
1100771Speter 			con.crval = con.cival;
1101771Speter 			con.ctype = nl + TNIL;
1102771Speter 			break;
1103771Speter 		case T_VAR:
1104771Speter 			np = lookup(cn[2]);
1105771Speter 			if (np == NIL || np->class != CONST) {
1106771Speter 				return FALSE;
1107771Speter 			}
1108771Speter 			if ( cn[3] != NIL ) {
1109771Speter 				return FALSE;
1110771Speter 			}
1111771Speter 			con.ctype = np->type;
1112771Speter 			switch (classify(np->type)) {
1113771Speter 				case TINT:
1114771Speter 					con.crval = np->range[0];
1115771Speter 					break;
1116771Speter 				case TDOUBLE:
1117771Speter 					con.crval = np->real;
1118771Speter 					break;
1119771Speter 				case TBOOL:
1120771Speter 				case TCHAR:
1121771Speter 				case TSCAL:
1122771Speter 					con.cival = np->value[0];
1123771Speter 					con.crval = con.cival;
1124771Speter 					break;
1125771Speter 				case TSTR:
1126771Speter 					con.cpval = np->ptr[0];
1127771Speter 					break;
1128771Speter 				default:
1129771Speter 					con.ctype = NIL;
1130771Speter 					return FALSE;
1131771Speter 			}
1132771Speter 			break;
1133771Speter 		case T_BINT:
1134771Speter 			con.crval = a8tol(cn[2]);
1135771Speter 			goto restcon;
1136771Speter 		case T_INT:
1137771Speter 			con.crval = atof(cn[2]);
1138771Speter 			if (con.crval > MAXINT || con.crval < MININT) {
1139771Speter 				derror("Constant too large for this implementation");
1140771Speter 				con.crval = 0;
1141771Speter 			}
1142771Speter restcon:
1143771Speter 			ci = con.crval;
1144771Speter #ifndef PI0
1145771Speter 			if (bytes(ci, ci) <= 2)
1146771Speter 				con.ctype = nl+T2INT;
1147771Speter 			else
1148771Speter #endif
1149771Speter 				con.ctype = nl+T4INT;
1150771Speter 			break;
1151771Speter 		case T_FINT:
1152771Speter 			con.ctype = nl+TDOUBLE;
1153771Speter 			con.crval = atof(cn[2]);
1154771Speter 			break;
1155771Speter 		case T_STRNG:
1156771Speter 			cp = cn[2];
1157771Speter 			if (cp[1] == 0) {
1158771Speter 				con.ctype = nl+T1CHAR;
1159771Speter 				con.cival = cp[0];
1160771Speter 				con.crval = con.cival;
1161771Speter 				break;
1162771Speter 			}
1163771Speter 			con.ctype = nl+TSTR;
1164771Speter 			con.cpval = cp;
1165771Speter 			break;
1166771Speter 	}
1167771Speter 	if (sgnd) {
1168771Speter 		if (isnta(con.ctype, "id")) {
1169771Speter 			derror("%s constants cannot be signed", nameof(con.ctype));
1170771Speter 			return FALSE;
1171771Speter 		} else if (negd)
1172771Speter 			con.crval = -con.crval;
1173771Speter 	}
1174771Speter 	return TRUE;
1175771Speter }
1176