xref: /csrg-svn/usr.bin/pascal/src/rval.c (revision 3155)
1771Speter /* Copyright (c) 1979 Regents of the University of California */
2771Speter 
3*3155Smckusic static char sccsid[] = "@(#)rval.c 1.9 03/09/81";
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
14771Speter 
15771Speter extern	char *opnames[];
16771Speter 
171627Speter     /* line number of the last record comparison warning */
181627Speter short reccompline = 0;
191627Speter 
20771Speter #ifdef PC
21771Speter     char	*relts[] =  {
22771Speter 				"_RELEQ" , "_RELNE" ,
23771Speter 				"_RELTLT" , "_RELTGT" ,
24771Speter 				"_RELTLE" , "_RELTGE"
25771Speter 			    };
26771Speter     char	*relss[] =  {
27771Speter 				"_RELEQ" , "_RELNE" ,
28771Speter 				"_RELSLT" , "_RELSGT" ,
29771Speter 				"_RELSLE" , "_RELSGE"
30771Speter 			    };
31771Speter     long	relops[] =  {
32771Speter 				P2EQ , P2NE ,
33771Speter 				P2LT , P2GT ,
34771Speter 				P2LE , P2GE
35771Speter 			    };
36771Speter     long	mathop[] =  {	P2MUL , P2PLUS , P2MINUS };
37771Speter     char	*setop[] =  {	"_MULT" , "_ADDT" , "_SUBT" };
38771Speter #endif PC
39771Speter /*
40771Speter  * Rvalue - an expression.
41771Speter  *
42771Speter  * Contype is the type that the caller would prefer, nand is important
43771Speter  * if constant sets or constant strings are involved, the latter
44771Speter  * because of string padding.
45771Speter  * required is a flag whether an lvalue or an rvalue is required.
46771Speter  * only VARs and structured things can have gt their lvalue this way.
47771Speter  */
48771Speter struct nl *
49771Speter rvalue(r, contype , required )
50771Speter 	int *r;
51771Speter 	struct nl *contype;
52771Speter 	int	required;
53771Speter {
54771Speter 	register struct nl *p, *p1;
55771Speter 	register struct nl *q;
56771Speter 	int c, c1, *rt, w, g;
57771Speter 	char *cp, *cp1, *opname;
58771Speter 	long l;
59771Speter 	double f;
60771Speter 	extern int	flagwas;
61771Speter 	struct csetstr	csetd;
62771Speter #	ifdef PC
63771Speter 	    struct nl	*rettype;
64771Speter 	    long	ctype;
65771Speter 	    long	tempoff;
66771Speter #	endif PC
67771Speter 
68771Speter 	if (r == NIL)
69771Speter 		return (NIL);
70771Speter 	if (nowexp(r))
71771Speter 		return (NIL);
72771Speter 	/*
73771Speter 	 * Pick up the name of the operation
74771Speter 	 * for future error messages.
75771Speter 	 */
76771Speter 	if (r[0] <= T_IN)
77771Speter 		opname = opnames[r[0]];
78771Speter 
79771Speter 	/*
80771Speter 	 * The root of the tree tells us what sort of expression we have.
81771Speter 	 */
82771Speter 	switch (r[0]) {
83771Speter 
84771Speter 	/*
85771Speter 	 * The constant nil
86771Speter 	 */
87771Speter 	case T_NIL:
88771Speter #		ifdef OBJ
89771Speter 		    put(2, O_CON2, 0);
90771Speter #		endif OBJ
91771Speter #		ifdef PC
921477Speter 		    putleaf( P2ICON , 0 , 0 , P2PTR|P2UNDEF , 0 );
93771Speter #		endif PC
94771Speter 		return (nl+TNIL);
95771Speter 
96771Speter 	/*
97771Speter 	 * Function call with arguments.
98771Speter 	 */
99771Speter 	case T_FCALL:
100771Speter #	    ifdef OBJ
101771Speter 		return (funccod(r));
102771Speter #	    endif OBJ
103771Speter #	    ifdef PC
104771Speter 		return (pcfunccod( r ));
105771Speter #	    endif PC
106771Speter 
107771Speter 	case T_VAR:
108771Speter 		p = lookup(r[2]);
109771Speter 		if (p == NIL || p->class == BADUSE)
110771Speter 			return (NIL);
111771Speter 		switch (p->class) {
112771Speter 		    case VAR:
113771Speter 			    /*
114771Speter 			     * If a variable is
115771Speter 			     * qualified then get
116771Speter 			     * the rvalue by a
117771Speter 			     * lvalue and an ind.
118771Speter 			     */
119771Speter 			    if (r[3] != NIL)
120771Speter 				    goto ind;
121771Speter 			    q = p->type;
122771Speter 			    if (q == NIL)
123771Speter 				    return (NIL);
124771Speter #			    ifdef OBJ
125771Speter 				w = width(q);
126771Speter 				switch (w) {
127771Speter 				    case 8:
1283078Smckusic 					put(2, O_RV8 | bn << 8+INDX,
1293078Smckusic 						(int)p->value[0]);
130771Speter 					break;
131771Speter 				    case 4:
1323078Smckusic 					put(2, O_RV4 | bn << 8+INDX,
1333078Smckusic 						(int)p->value[0]);
134771Speter 					break;
135771Speter 				    case 2:
1363078Smckusic 					put(2, O_RV2 | bn << 8+INDX,
1373078Smckusic 						(int)p->value[0]);
138771Speter 					break;
139771Speter 				    case 1:
1403078Smckusic 					put(2, O_RV1 | bn << 8+INDX,
1413078Smckusic 						(int)p->value[0]);
142771Speter 					break;
143771Speter 				    default:
1443078Smckusic 					put(3, O_RV | bn << 8+INDX,
1453078Smckusic 						(int)p->value[0], w);
146771Speter 				}
147771Speter #			   endif OBJ
148771Speter #			   ifdef PC
149771Speter 				if ( required == RREQ ) {
150771Speter 				    putRV( p -> symbol , bn , p -> value[0]
151771Speter 					    , p2type( q ) );
152771Speter 				} else {
153771Speter 				    putLV( p -> symbol , bn , p -> value[0]
154771Speter 					    , p2type( q ) );
155771Speter 				}
156771Speter #			   endif PC
157771Speter 			   return (q);
158771Speter 
159771Speter 		    case WITHPTR:
160771Speter 		    case REF:
161771Speter 			    /*
162771Speter 			     * A lvalue for these
163771Speter 			     * is actually what one
164771Speter 			     * might consider a rvalue.
165771Speter 			     */
166771Speter ind:
167771Speter 			    q = lvalue(r, NOFLAGS , LREQ );
168771Speter 			    if (q == NIL)
169771Speter 				    return (NIL);
170771Speter #			    ifdef OBJ
171771Speter 				w = width(q);
172771Speter 				switch (w) {
173771Speter 				    case 8:
174771Speter 					    put(1, O_IND8);
175771Speter 					    break;
176771Speter 				    case 4:
177771Speter 					    put(1, O_IND4);
178771Speter 					    break;
179771Speter 				    case 2:
180771Speter 					    put(1, O_IND2);
181771Speter 					    break;
182771Speter 				    case 1:
183771Speter 					    put(1, O_IND1);
184771Speter 					    break;
185771Speter 				    default:
186771Speter 					    put(2, O_IND, w);
187771Speter 				}
188771Speter #			    endif OBJ
189771Speter #			    ifdef PC
190771Speter 				if ( required == RREQ ) {
191771Speter 				    putop( P2UNARY P2MUL , p2type( q ) );
192771Speter 				}
193771Speter #			    endif PC
194771Speter 			    return (q);
195771Speter 
196771Speter 		    case CONST:
197771Speter 			    if (r[3] != NIL) {
198771Speter 				error("%s is a constant and cannot be qualified", r[2]);
199771Speter 				return (NIL);
200771Speter 			    }
201771Speter 			    q = p->type;
202771Speter 			    if (q == NIL)
203771Speter 				    return (NIL);
204771Speter 			    if (q == nl+TSTR) {
205771Speter 				    /*
206771Speter 				     * Find the size of the string
207771Speter 				     * constant if needed.
208771Speter 				     */
209771Speter 				    cp = p->ptr[0];
210771Speter cstrng:
211771Speter 				    cp1 = cp;
212771Speter 				    for (c = 0; *cp++; c++)
213771Speter 					    continue;
2143078Smckusic 				    w = c;
215771Speter 				    if (contype != NIL && !opt('s')) {
216771Speter 					    if (width(contype) < c && classify(contype) == TSTR) {
217771Speter 						    error("Constant string too long");
218771Speter 						    return (NIL);
219771Speter 					    }
2203078Smckusic 					    w = width(contype);
221771Speter 				    }
222771Speter #				    ifdef OBJ
2233078Smckusic 					put(2, O_CONG, w);
2243078Smckusic 					putstr(cp1, w - c);
225771Speter #				    endif OBJ
226771Speter #				    ifdef PC
227*3155Smckusic 					putCONG( cp1 , w , required );
228771Speter #				    endif PC
229771Speter 				    /*
230771Speter 				     * Define the string temporarily
231771Speter 				     * so later people can know its
232771Speter 				     * width.
233771Speter 				     * cleaned out by stat.
234771Speter 				     */
2353078Smckusic 				    q = defnl(0, STR, 0, w);
236771Speter 				    q->type = q;
237771Speter 				    return (q);
238771Speter 			    }
239771Speter 			    if (q == nl+T1CHAR) {
240771Speter #				    ifdef OBJ
2413078Smckusic 					put(2, O_CONC, (int)p->value[0]);
242771Speter #				    endif OBJ
243771Speter #				    ifdef PC
244771Speter 					putleaf( P2ICON , p -> value[0] , 0
245771Speter 						, P2CHAR , 0 );
246771Speter #				    endif PC
247771Speter 				    return (q);
248771Speter 			    }
249771Speter 			    /*
250771Speter 			     * Every other kind of constant here
251771Speter 			     */
252771Speter 			    switch (width(q)) {
253771Speter 			    case 8:
254771Speter #ifndef DEBUG
255771Speter #				    ifdef OBJ
256771Speter 					put(2, O_CON8, p->real);
257771Speter #				    endif OBJ
258771Speter #				    ifdef PC
259771Speter 					putCON8( p -> real );
260771Speter #				    endif PC
261771Speter #else
262771Speter 				    if (hp21mx) {
263771Speter 					    f = p->real;
264771Speter 					    conv(&f);
265771Speter 					    l = f.plong;
266771Speter 					    put(2, O_CON4, l);
267771Speter 				    } else
268771Speter #					    ifdef OBJ
269771Speter 						put(2, O_CON8, p->real);
270771Speter #					    endif OBJ
271771Speter #					    ifdef PC
272771Speter 						putCON8( p -> real );
273771Speter #					    endif PC
274771Speter #endif
275771Speter 				    break;
276771Speter 			    case 4:
277771Speter #				    ifdef OBJ
278771Speter 					put(2, O_CON4, p->range[0]);
279771Speter #				    endif OBJ
280771Speter #				    ifdef PC
281771Speter 					putleaf( P2ICON , p -> range[0] , 0
282771Speter 						, P2INT , 0 );
283771Speter #				    endif PC
284771Speter 				    break;
285771Speter 			    case 2:
286771Speter #				    ifdef OBJ
2873078Smckusic 					put(2, O_CON2, (short)p->range[0]);
288771Speter #				    endif OBJ
289771Speter #				    ifdef PC
290771Speter 					    /*
291771Speter 					     * make short constants ints
292771Speter 					     */
293771Speter 					putleaf( P2ICON , (short) p -> range[0]
294771Speter 						, 0 , P2INT , 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 					    /*
303771Speter 					     * make char constants ints
304771Speter 					     */
305771Speter 					putleaf( P2ICON , p -> value[0] , 0
306771Speter 						, P2INT , 0 );
307771Speter #				    endif PC
308771Speter 				    break;
309771Speter 			    default:
310771Speter 				    panic("rval");
311771Speter 			    }
312771Speter 			    return (q);
313771Speter 
314771Speter 		    case FUNC:
3151200Speter 		    case FFUNC:
316771Speter 			    /*
317771Speter 			     * Function call with no arguments.
318771Speter 			     */
319771Speter 			    if (r[3]) {
320771Speter 				    error("Can't qualify a function result value");
321771Speter 				    return (NIL);
322771Speter 			    }
323771Speter #			    ifdef OBJ
324771Speter 				return (funccod((int *) r));
325771Speter #			    endif OBJ
326771Speter #			    ifdef PC
327771Speter 				return (pcfunccod( r ));
328771Speter #			    endif PC
329771Speter 
330771Speter 		    case TYPE:
331771Speter 			    error("Type names (e.g. %s) allowed only in declarations", p->symbol);
332771Speter 			    return (NIL);
333771Speter 
334771Speter 		    case PROC:
3351200Speter 		    case FPROC:
336771Speter 			    error("Procedure %s found where expression required", p->symbol);
337771Speter 			    return (NIL);
338771Speter 		    default:
339771Speter 			    panic("rvid");
340771Speter 		}
341771Speter 	/*
342771Speter 	 * Constant sets
343771Speter 	 */
344771Speter 	case T_CSET:
345771Speter #		ifdef OBJ
346771Speter 		    if ( precset( r , contype , &csetd ) ) {
347771Speter 			if ( csetd.csettype == NIL ) {
348771Speter 			    return NIL;
349771Speter 			}
350771Speter 			postcset( r , &csetd );
351771Speter 		    } else {
3523078Smckusic 			put( 2, O_PUSH, -lwidth(csetd.csettype));
353771Speter 			postcset( r , &csetd );
354771Speter 			setran( ( csetd.csettype ) -> type );
355771Speter 			put( 2, O_CON24, set.uprbp);
356771Speter 			put( 2, O_CON24, set.lwrb);
3573078Smckusic 			put( 2, O_CTTOT,
3583078Smckusic 				(int)(4 + csetd.singcnt + 2 * csetd.paircnt));
359771Speter 		    }
360771Speter 		    return csetd.csettype;
361771Speter #		endif OBJ
362771Speter #		ifdef PC
363771Speter 		    if ( precset( r , contype , &csetd ) ) {
364771Speter 			if ( csetd.csettype == NIL ) {
365771Speter 			    return NIL;
366771Speter 			}
367771Speter 			postcset( r , &csetd );
368771Speter 		    } else {
369771Speter 			putleaf( P2ICON , 0 , 0
370771Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR )
371771Speter 				, "_CTTOT" );
372771Speter 			/*
373771Speter 			 *	allocate a temporary and use it
374771Speter 			 */
375771Speter 			sizes[ cbn ].om_off -= lwidth( csetd.csettype );
376771Speter 			tempoff = sizes[ cbn ].om_off;
377771Speter 			putlbracket( ftnno , -tempoff );
378771Speter 			if ( tempoff < sizes[ cbn ].om_max ) {
379771Speter 			    sizes[ cbn ].om_max = tempoff;
380771Speter 			}
381771Speter 			putLV( 0 , cbn , tempoff , P2PTR|P2STRTY );
382771Speter 			setran( ( csetd.csettype ) -> type );
383771Speter 			putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 );
384771Speter 			putop( P2LISTOP , P2INT );
385771Speter 			putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 );
386771Speter 			putop( P2LISTOP , P2INT );
387771Speter 			postcset( r , &csetd );
388771Speter 			putop( P2CALL , P2INT );
389771Speter 		    }
390771Speter 		    return csetd.csettype;
391771Speter #		endif PC
392771Speter 
393771Speter 	/*
394771Speter 	 * Unary plus and minus
395771Speter 	 */
396771Speter 	case T_PLUS:
397771Speter 	case T_MINUS:
398771Speter 		q = rvalue(r[2], NIL , RREQ );
399771Speter 		if (q == NIL)
400771Speter 			return (NIL);
401771Speter 		if (isnta(q, "id")) {
402771Speter 			error("Operand of %s must be integer or real, not %s", opname, nameof(q));
403771Speter 			return (NIL);
404771Speter 		}
405771Speter 		if (r[0] == T_MINUS) {
406771Speter #		    ifdef OBJ
407771Speter 			put(1, O_NEG2 + (width(q) >> 2));
408771Speter #		    endif OBJ
409771Speter #		    ifdef PC
410771Speter 			putop( P2UNARY P2MINUS , p2type( q ) );
411771Speter #		    endif PC
412771Speter 		    return (isa(q, "d") ? q : nl+T4INT);
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
428771Speter 		    putop( P2NOT , P2INT );
429771Speter #		endif PC
430771Speter 		return (nl+T1BOOL);
431771Speter 
432771Speter 	case T_AND:
433771Speter 	case T_OR:
434771Speter 		p = rvalue(r[2], NIL , RREQ );
435771Speter 		p1 = rvalue(r[3], NIL , RREQ );
436771Speter 		if (p == NIL || p1 == NIL)
437771Speter 			return (NIL);
438771Speter 		if (isnta(p, "b")) {
439771Speter 			error("Left operand of %s must be Boolean, not %s", opname, nameof(p));
440771Speter 			return (NIL);
441771Speter 		}
442771Speter 		if (isnta(p1, "b")) {
443771Speter 			error("Right operand of %s must be Boolean, not %s", opname, nameof(p1));
444771Speter 			return (NIL);
445771Speter 		}
446771Speter #		ifdef OBJ
447771Speter 		    put(1, r[0] == T_AND ? O_AND : O_OR);
448771Speter #		endif OBJ
449771Speter #		ifdef PC
450771Speter 			/*
451771Speter 			 * note the use of & and | rather than && and ||
452771Speter 			 * to force evaluation of all the expressions.
453771Speter 			 */
454771Speter 		    putop( r[ 0 ] == T_AND ? P2AND : P2OR , P2INT );
455771Speter #		endif PC
456771Speter 		return (nl+T1BOOL);
457771Speter 
458771Speter 	case T_DIVD:
459771Speter #		ifdef OBJ
460771Speter 		    p = rvalue(r[2], NIL , RREQ );
461771Speter 		    p1 = rvalue(r[3], NIL , RREQ );
462771Speter #		endif OBJ
463771Speter #		ifdef PC
464771Speter 			/*
465771Speter 			 *	force these to be doubles for the divide
466771Speter 			 */
467771Speter 		    p = rvalue( r[ 2 ] , NIL , RREQ );
468771Speter 		    if ( isnta( p , "d" ) ) {
469771Speter 			putop( P2SCONV , P2DOUBLE );
470771Speter 		    }
471771Speter 		    p1 = rvalue( r[ 3 ] , NIL , RREQ );
472771Speter 		    if ( isnta( p1 , "d" ) ) {
473771Speter 			putop( P2SCONV , P2DOUBLE );
474771Speter 		    }
475771Speter #		endif PC
476771Speter 		if (p == NIL || p1 == NIL)
477771Speter 			return (NIL);
478771Speter 		if (isnta(p, "id")) {
479771Speter 			error("Left operand of / must be integer or real, not %s", nameof(p));
480771Speter 			return (NIL);
481771Speter 		}
482771Speter 		if (isnta(p1, "id")) {
483771Speter 			error("Right operand of / must be integer or real, not %s", nameof(p1));
484771Speter 			return (NIL);
485771Speter 		}
486771Speter #		ifdef OBJ
487771Speter 		    return gen(NIL, r[0], width(p), width(p1));
488771Speter #		endif OBJ
489771Speter #		ifdef PC
490771Speter 		    putop( P2DIV , P2DOUBLE );
491771Speter 		    return nl + TDOUBLE;
492771Speter #		endif PC
493771Speter 
494771Speter 	case T_MULT:
495771Speter 	case T_ADD:
496771Speter 	case T_SUB:
497771Speter #		ifdef OBJ
498771Speter 		    /*
4991555Speter 		     * If the context hasn't told us the type
5001555Speter 		     * and a constant set is present
5011555Speter 		     * we need to infer the type
5021555Speter 		     * before generating code.
503771Speter 		     */
5041555Speter 		    if ( contype == NIL ) {
505771Speter 			    codeoff();
5061555Speter 			    contype = rvalue( r[3] , NIL , RREQ );
507771Speter 			    codeon();
5081555Speter 			    if ( contype == lookup( intset ) -> type ) {
5091555Speter 				codeoff();
5101555Speter 				contype = rvalue( r[2] , NIL , RREQ );
5111555Speter 				codeon();
5121555Speter 			    }
513771Speter 		    }
5141555Speter 		    if ( contype == NIL ) {
5151555Speter 			return NIL;
5161555Speter 		    }
5171555Speter 		    p = rvalue( r[2] , contype , RREQ );
5181555Speter 		    p1 = rvalue( r[3] , p , RREQ );
5191555Speter 		    if ( p == NIL || p1 == NIL )
5201555Speter 			    return NIL;
521771Speter 		    if (isa(p, "id") && isa(p1, "id"))
522771Speter 			return (gen(NIL, r[0], width(p), width(p1)));
523771Speter 		    if (isa(p, "t") && isa(p1, "t")) {
524771Speter 			    if (p != p1) {
525771Speter 				    error("Set types of operands of %s must be identical", opname);
526771Speter 				    return (NIL);
527771Speter 			    }
528771Speter 			    gen(TSET, r[0], width(p), 0);
529771Speter 			    return (p);
530771Speter 		    }
531771Speter #		endif OBJ
532771Speter #		ifdef PC
533771Speter 			/*
534771Speter 			 * the second pass can't do
535771Speter 			 *	long op double  or  double op long
536771Speter 			 * so we have to know the type of both operands
537771Speter 			 * also, it gets tricky for sets, which are done
538771Speter 			 * by function calls.
539771Speter 			 */
540771Speter 		    codeoff();
541771Speter 		    p1 = rvalue( r[ 3 ] , contype , RREQ );
542771Speter 		    codeon();
543771Speter 		    if ( isa( p1 , "id" ) ) {
544771Speter 			p = rvalue( r[ 2 ] , contype , RREQ );
545771Speter 			if ( ( p == NIL ) || ( p1 == NIL ) ) {
546771Speter 			    return NIL;
547771Speter 			}
548771Speter 			if ( isa( p , "i" ) && isa( p1 , "d" ) ) {
549771Speter 			    putop( P2SCONV , P2DOUBLE );
550771Speter 			}
551771Speter 			p1 = rvalue( r[ 3 ] , contype , RREQ );
552771Speter 			if ( isa( p , "d" ) && isa( p1 , "i" ) ) {
553771Speter 			    putop( P2SCONV , P2DOUBLE );
554771Speter 			}
555771Speter 			if ( isa( p , "id" ) ) {
556771Speter 			    if ( isa( p , "d" ) || isa( p1 , "d" ) ) {
557771Speter 				ctype = P2DOUBLE;
558771Speter 				rettype = nl + TDOUBLE;
559771Speter 			    } else {
560771Speter 				ctype = P2INT;
561771Speter 				rettype = nl + T4INT;
562771Speter 			    }
563771Speter 			    putop( mathop[ r[0] - T_MULT ] , ctype );
564771Speter 			    return rettype;
565771Speter 			}
566771Speter 		    }
567771Speter 		    if ( isa( p1 , "t" ) ) {
568771Speter 			putleaf( P2ICON , 0 , 0
569771Speter 			    , ADDTYPE( ADDTYPE( P2PTR | P2STRTY , P2FTN )
570771Speter 					, P2PTR )
571771Speter 			    , setop[ r[0] - T_MULT ] );
5721555Speter 			if ( contype == NIL ) {
5731555Speter 			    contype = p1;
5741555Speter 			    if ( contype == lookup( intset ) -> type ) {
5751555Speter 				codeoff();
5761555Speter 				contype = rvalue( r[2] , NIL , LREQ );
5771555Speter 				codeon();
5781555Speter 			    }
5791555Speter 			}
5801555Speter 			if ( contype == NIL ) {
5811555Speter 			    return NIL;
5821555Speter 			}
5831555Speter 			    /*
5841555Speter 			     *	allocate a temporary and use it
5851555Speter 			     */
5861555Speter 			sizes[ cbn ].om_off -= lwidth( contype );
587771Speter 			tempoff = sizes[ cbn ].om_off;
588771Speter 			putlbracket( ftnno , -tempoff );
589771Speter 			if ( tempoff < sizes[ cbn ].om_max ) {
590771Speter 			    sizes[ cbn ].om_max = tempoff;
591771Speter 			}
592771Speter 			putLV( 0 , cbn , tempoff , P2PTR|P2STRTY );
5931555Speter 			p = rvalue( r[2] , contype , LREQ );
594771Speter 			if ( isa( p , "t" ) ) {
595771Speter 			    putop( P2LISTOP , P2INT );
596771Speter 			    if ( p == NIL || p1 == NIL ) {
597771Speter 				return NIL;
598771Speter 			    }
599771Speter 			    p1 = rvalue( r[3] , p , LREQ );
600771Speter 			    if ( p != p1 ) {
601771Speter 				error("Set types of operands of %s must be identical", opname);
602771Speter 				return NIL;
603771Speter 			    }
604771Speter 			    putop( P2LISTOP , P2INT );
605771Speter 			    putleaf( P2ICON , lwidth( p1 ) / sizeof( long ) , 0
606771Speter 				    , P2INT , 0 );
607771Speter 			    putop( P2LISTOP , P2INT );
608771Speter 			    putop( P2CALL , P2PTR | P2STRTY );
609771Speter 			    return p;
610771Speter 			}
611771Speter 		    }
612771Speter 		    if ( isnta( p1 , "idt" ) ) {
613771Speter 			    /*
614771Speter 			     *	find type of left operand for error message.
615771Speter 			     */
616771Speter 			p = rvalue( r[2] , contype , RREQ );
617771Speter 		    }
618771Speter 			/*
619771Speter 			 *	don't give spurious error messages.
620771Speter 			 */
621771Speter 		    if ( p == NIL || p1 == NIL ) {
622771Speter 			return NIL;
623771Speter 		    }
624771Speter #		endif PC
625771Speter 		if (isnta(p, "idt")) {
626771Speter 			error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p));
627771Speter 			return (NIL);
628771Speter 		}
629771Speter 		if (isnta(p1, "idt")) {
630771Speter 			error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1));
631771Speter 			return (NIL);
632771Speter 		}
633771Speter 		error("Cannot mix sets with integers and reals as operands of %s", opname);
634771Speter 		return (NIL);
635771Speter 
636771Speter 	case T_MOD:
637771Speter 	case T_DIV:
638771Speter 		p = rvalue(r[2], NIL , RREQ );
639771Speter 		p1 = rvalue(r[3], NIL , RREQ );
640771Speter 		if (p == NIL || p1 == NIL)
641771Speter 			return (NIL);
642771Speter 		if (isnta(p, "i")) {
643771Speter 			error("Left operand of %s must be integer, not %s", opname, nameof(p));
644771Speter 			return (NIL);
645771Speter 		}
646771Speter 		if (isnta(p1, "i")) {
647771Speter 			error("Right operand of %s must be integer, not %s", opname, nameof(p1));
648771Speter 			return (NIL);
649771Speter 		}
650771Speter #		ifdef OBJ
651771Speter 		    return (gen(NIL, r[0], width(p), width(p1)));
652771Speter #		endif OBJ
653771Speter #		ifdef PC
654771Speter 		    putop( r[ 0 ] == T_DIV ? P2DIV : P2MOD , P2INT );
655771Speter 		    return ( nl + T4INT );
656771Speter #		endif PC
657771Speter 
658771Speter 	case T_EQ:
659771Speter 	case T_NE:
660771Speter 	case T_LT:
661771Speter 	case T_GT:
662771Speter 	case T_LE:
663771Speter 	case T_GE:
664771Speter 		/*
665771Speter 		 * Since there can be no, a priori, knowledge
666771Speter 		 * of the context type should a constant string
667771Speter 		 * or set arise, we must poke around to find such
668771Speter 		 * a type if possible.  Since constant strings can
669771Speter 		 * always masquerade as identifiers, this is always
670771Speter 		 * necessary.
671771Speter 		 */
672771Speter 		codeoff();
673771Speter 		p1 = rvalue(r[3], NIL , RREQ );
674771Speter 		codeon();
675771Speter 		if (p1 == NIL)
676771Speter 			return (NIL);
677771Speter 		contype = p1;
678771Speter #		ifdef OBJ
6791555Speter 		    if (p1->class == STR) {
680771Speter 			    /*
681771Speter 			     * For constant strings we want
682771Speter 			     * the longest type so as to be
683771Speter 			     * able to do padding (more importantly
684771Speter 			     * avoiding truncation). For clarity,
685771Speter 			     * we get this length here.
686771Speter 			     */
687771Speter 			    codeoff();
688771Speter 			    p = rvalue(r[2], NIL , RREQ );
689771Speter 			    codeon();
690771Speter 			    if (p == NIL)
691771Speter 				    return (NIL);
6921555Speter 			    if (width(p) > width(p1))
693771Speter 				    contype = p;
6941555Speter 		    } else if ( isa( p1 , "t" ) ) {
6951555Speter 			if ( contype == lookup( intset ) -> type ) {
6961555Speter 			    codeoff();
6971555Speter 			    contype = rvalue( r[2] , NIL , RREQ );
6981555Speter 			    codeon();
6991555Speter 			    if ( contype == NIL ) {
7001555Speter 				return NIL;
7011555Speter 			    }
7021555Speter 			}
703771Speter 		    }
704771Speter 		    /*
705771Speter 		     * Now we generate code for
706771Speter 		     * the operands of the relational
707771Speter 		     * operation.
708771Speter 		     */
709771Speter 		    p = rvalue(r[2], contype , RREQ );
710771Speter 		    if (p == NIL)
711771Speter 			    return (NIL);
712771Speter 		    p1 = rvalue(r[3], p , RREQ );
713771Speter 		    if (p1 == NIL)
714771Speter 			    return (NIL);
715771Speter #		endif OBJ
716771Speter #		ifdef PC
717771Speter 		    c1 = classify( p1 );
718771Speter 		    if ( c1 == TSET || c1 == TSTR || c1 == TREC ) {
719771Speter 			putleaf( P2ICON , 0 , 0
720771Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR )
721771Speter 				, c1 == TSET  ? relts[ r[0] - T_EQ ]
722771Speter 					      : relss[ r[0] - T_EQ ] );
723771Speter 			    /*
724771Speter 			     *	for [] and strings, comparisons are done on
725771Speter 			     *	the maximum width of the two sides.
726771Speter 			     *	for other sets, we have to ask the left side
727771Speter 			     *	what type it is based on the type of the right.
728771Speter 			     *	(this matters for intsets).
729771Speter 			     */
7301555Speter 			if ( c1 == TSTR ) {
731771Speter 			    codeoff();
732771Speter 			    p = rvalue( r[ 2 ] , NIL , LREQ );
733771Speter 			    codeon();
7341555Speter 			    if ( p == NIL ) {
7351555Speter 				return NIL;
7361555Speter 			    }
7371555Speter 			    if ( lwidth( p ) > lwidth( p1 ) ) {
738771Speter 				contype = p;
739771Speter 			    }
7401555Speter 			} else if ( c1 == TSET ) {
7411555Speter 			    if ( contype == lookup( intset ) -> type ) {
7421555Speter 				codeoff();
7431555Speter 				p = rvalue( r[ 2 ] , NIL , LREQ );
7441555Speter 				codeon();
7451555Speter 				if ( p == NIL ) {
7461555Speter 				    return NIL;
7471555Speter 				}
7481555Speter 				contype = p;
7491555Speter 			    }
7501627Speter 			}
751771Speter 			    /*
752771Speter 			     *	put out the width of the comparison.
753771Speter 			     */
754771Speter 			putleaf( P2ICON , lwidth( contype ) , 0 , P2INT , 0 );
755771Speter 			    /*
756771Speter 			     *	and the left hand side,
757771Speter 			     *	for sets, strings, records
758771Speter 			     */
759771Speter 			p = rvalue( r[ 2 ] , contype , LREQ );
760771Speter 			putop( P2LISTOP , P2INT );
761771Speter 			p1 = rvalue( r[ 3 ] , p , LREQ );
762771Speter 			putop( P2LISTOP , P2INT );
763771Speter 			putop( P2CALL , P2INT );
764771Speter 		    } else {
765771Speter 			    /*
766771Speter 			     *	the easy (scalar or error) case
767771Speter 			     */
768771Speter 			p = rvalue( r[ 2 ] , contype , RREQ );
769771Speter 			if ( p == NIL ) {
770771Speter 			    return NIL;
7712056Speter 			}
772771Speter 			    /*
773771Speter 			     * since the second pass can't do
774771Speter 			     *	long op double  or  double op long
775771Speter 			     * we may have to do some coercing.
776771Speter 			     */
7772056Speter 			if ( isa( p , "i" ) && isa( p1 , "d" ) ) {
778771Speter 			    putop( P2SCONV , P2DOUBLE );
779771Speter 			}
780771Speter 			p1 = rvalue( r[ 3 ] , p , RREQ );
781771Speter 			if ( isa( p , "d" ) && isa( p1 , "i" ) )
782771Speter 			    putop( P2SCONV , P2DOUBLE );
783771Speter 			putop( relops[ r[0] - T_EQ ] , P2INT );
784771Speter 		    }
785771Speter #		endif PC
786771Speter 		c = classify(p);
787771Speter 		c1 = classify(p1);
788771Speter 		if (nocomp(c) || nocomp(c1))
789771Speter 			return (NIL);
790771Speter 		g = NIL;
791771Speter 		switch (c) {
792771Speter 			case TBOOL:
793771Speter 			case TCHAR:
794771Speter 				if (c != c1)
795771Speter 					goto clash;
796771Speter 				break;
797771Speter 			case TINT:
798771Speter 			case TDOUBLE:
799771Speter 				if (c1 != TINT && c1 != TDOUBLE)
800771Speter 					goto clash;
801771Speter 				break;
802771Speter 			case TSCAL:
803771Speter 				if (c1 != TSCAL)
804771Speter 					goto clash;
805771Speter 				if (scalar(p) != scalar(p1))
806771Speter 					goto nonident;
807771Speter 				break;
808771Speter 			case TSET:
809771Speter 				if (c1 != TSET)
810771Speter 					goto clash;
811771Speter 				if (p != p1)
812771Speter 					goto nonident;
813771Speter 				g = TSET;
814771Speter 				break;
815771Speter 			case TREC:
816771Speter 				if ( c1 != TREC ) {
817771Speter 				    goto clash;
818771Speter 				}
819771Speter 				if ( p != p1 ) {
820771Speter 				    goto nonident;
821771Speter 				}
822771Speter 				if (r[0] != T_EQ && r[0] != T_NE) {
823771Speter 					error("%s not allowed on records - only allow = and <>" , opname );
824771Speter 					return (NIL);
825771Speter 				}
826771Speter 				g = TREC;
827771Speter 				break;
828771Speter 			case TPTR:
829771Speter 			case TNIL:
830771Speter 				if (c1 != TPTR && c1 != TNIL)
831771Speter 					goto clash;
832771Speter 				if (r[0] != T_EQ && r[0] != T_NE) {
833771Speter 					error("%s not allowed on pointers - only allow = and <>" , opname );
834771Speter 					return (NIL);
835771Speter 				}
836771Speter 				break;
837771Speter 			case TSTR:
838771Speter 				if (c1 != TSTR)
839771Speter 					goto clash;
840771Speter 				if (width(p) != width(p1)) {
841771Speter 					error("Strings not same length in %s comparison", opname);
842771Speter 					return (NIL);
843771Speter 				}
844771Speter 				g = TSTR;
845771Speter 				break;
846771Speter 			default:
847771Speter 				panic("rval2");
848771Speter 		}
849771Speter #		ifdef OBJ
850771Speter 		    return (gen(g, r[0], width(p), width(p1)));
851771Speter #		endif OBJ
852771Speter #		ifdef PC
853771Speter 		    return nl + TBOOL;
854771Speter #		endif PC
855771Speter clash:
856771Speter 		error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname);
857771Speter 		return (NIL);
858771Speter nonident:
859771Speter 		error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname);
860771Speter 		return (NIL);
861771Speter 
862771Speter 	case T_IN:
863771Speter 	    rt = r[3];
864771Speter #	    ifdef OBJ
865771Speter 		if (rt != NIL && rt[0] == T_CSET) {
866771Speter 			precset( rt , NIL , &csetd );
867771Speter 			p1 = csetd.csettype;
868771Speter 			if (p1 == NIL)
869771Speter 			    return NIL;
870771Speter 			postcset( rt, &csetd);
871771Speter 		    } else {
872771Speter 			p1 = stkrval(r[3], NIL , RREQ );
873771Speter 			rt = NIL;
874771Speter 		    }
875771Speter #		endif OBJ
876771Speter #		ifdef PC
877771Speter 		    if (rt != NIL && rt[0] == T_CSET) {
878771Speter 			if ( precset( rt , NIL , &csetd ) ) {
8791555Speter 			    putleaf( P2ICON , 0 , 0
8801555Speter 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
8811555Speter 				    , "_IN" );
882771Speter 			} else {
883771Speter 			    putleaf( P2ICON , 0 , 0
884771Speter 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
885771Speter 				    , "_INCT" );
886771Speter 			}
887771Speter 			p1 = csetd.csettype;
888771Speter 			if (p1 == NIL)
889771Speter 			    return NIL;
890771Speter 		    } else {
891771Speter 			putleaf( P2ICON , 0 , 0
892771Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR )
893771Speter 				, "_IN" );
894771Speter 			codeoff();
895771Speter 			p1 = rvalue(r[3], NIL , LREQ );
896771Speter 			codeon();
897771Speter 		    }
898771Speter #		endif PC
899771Speter 		p = stkrval(r[2], NIL , RREQ );
900771Speter 		if (p == NIL || p1 == NIL)
901771Speter 			return (NIL);
902771Speter 		if (p1->class != SET) {
903771Speter 			error("Right operand of 'in' must be a set, not %s", nameof(p1));
904771Speter 			return (NIL);
905771Speter 		}
906771Speter 		if (incompat(p, p1->type, r[2])) {
907771Speter 			cerror("Index type clashed with set component type for 'in'");
908771Speter 			return (NIL);
909771Speter 		}
910771Speter 		setran(p1->type);
911771Speter #		ifdef OBJ
912771Speter 		    if (rt == NIL || csetd.comptime)
913771Speter 			    put(4, O_IN, width(p1), set.lwrb, set.uprbp);
914771Speter 		    else
9153078Smckusic 			    put(2, O_INCT,
9163078Smckusic 				(int)(3 + csetd.singcnt + 2*csetd.paircnt));
917771Speter #		endif OBJ
918771Speter #		ifdef PC
919771Speter 		    if ( rt == NIL || rt[0] != T_CSET ) {
920771Speter 			putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 );
921771Speter 			putop( P2LISTOP , P2INT );
922771Speter 			putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 );
923771Speter 			putop( P2LISTOP , P2INT );
924771Speter 			p1 = rvalue( r[3] , NIL , LREQ );
925771Speter 			putop( P2LISTOP , P2INT );
926771Speter 		    } else if ( csetd.comptime ) {
927771Speter 			putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 );
928771Speter 			putop( P2LISTOP , P2INT );
929771Speter 			putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 );
930771Speter 			putop( P2LISTOP , P2INT );
931771Speter 			postcset( r[3] , &csetd );
932771Speter 			putop( P2LISTOP , P2INT );
933771Speter 		    } else {
934771Speter 			postcset( r[3] , &csetd );
935771Speter 		    }
936771Speter 		    putop( P2CALL , P2INT );
937771Speter #		endif PC
938771Speter 		return (nl+T1BOOL);
939771Speter 	default:
940771Speter 		if (r[2] == NIL)
941771Speter 			return (NIL);
942771Speter 		switch (r[0]) {
943771Speter 		default:
944771Speter 			panic("rval3");
945771Speter 
946771Speter 
947771Speter 		/*
948771Speter 		 * An octal number
949771Speter 		 */
950771Speter 		case T_BINT:
951771Speter 			f = a8tol(r[2]);
952771Speter 			goto conint;
953771Speter 
954771Speter 		/*
955771Speter 		 * A decimal number
956771Speter 		 */
957771Speter 		case T_INT:
958771Speter 			f = atof(r[2]);
959771Speter conint:
960771Speter 			if (f > MAXINT || f < MININT) {
961771Speter 				error("Constant too large for this implementation");
962771Speter 				return (NIL);
963771Speter 			}
964771Speter 			l = f;
965771Speter 			if (bytes(l, l) <= 2) {
966771Speter #				ifdef OBJ
967771Speter 				    put(2, O_CON2, ( short ) l);
968771Speter #				endif OBJ
969771Speter #				ifdef PC
970771Speter 				        /*
971771Speter 					 * short constants are ints
972771Speter 					 */
973771Speter 				    putleaf( P2ICON , l , 0 , P2INT , 0 );
974771Speter #				endif PC
975771Speter 				return (nl+T2INT);
976771Speter 			}
977771Speter #			ifdef OBJ
978771Speter 			    put(2, O_CON4, l);
979771Speter #			endif OBJ
980771Speter #			ifdef PC
981771Speter 			    putleaf( P2ICON , l , 0 , P2INT , 0 );
982771Speter #			endif PC
983771Speter 			return (nl+T4INT);
984771Speter 
985771Speter 		/*
986771Speter 		 * A floating point number
987771Speter 		 */
988771Speter 		case T_FINT:
989771Speter #			ifdef OBJ
990771Speter 			    put(2, O_CON8, atof(r[2]));
991771Speter #			endif OBJ
992771Speter #			ifdef PC
993771Speter 			    putCON8( atof( r[2] ) );
994771Speter #			endif PC
995771Speter 			return (nl+TDOUBLE);
996771Speter 
997771Speter 		/*
998771Speter 		 * Constant strings.  Note that constant characters
999771Speter 		 * are constant strings of length one; there is
1000771Speter 		 * no constant string of length one.
1001771Speter 		 */
1002771Speter 		case T_STRNG:
1003771Speter 			cp = r[2];
1004771Speter 			if (cp[1] == 0) {
1005771Speter #				ifdef OBJ
1006771Speter 				    put(2, O_CONC, cp[0]);
1007771Speter #				endif OBJ
1008771Speter #				ifdef PC
1009771Speter 				    putleaf( P2ICON , cp[0] , 0 , P2CHAR , 0 );
1010771Speter #				endif PC
1011771Speter 				return (nl+T1CHAR);
1012771Speter 			}
1013771Speter 			goto cstrng;
1014771Speter 		}
1015771Speter 
1016771Speter 	}
1017771Speter }
1018771Speter 
1019771Speter /*
1020771Speter  * Can a class appear
1021771Speter  * in a comparison ?
1022771Speter  */
1023771Speter nocomp(c)
1024771Speter 	int c;
1025771Speter {
1026771Speter 
1027771Speter 	switch (c) {
1028771Speter 		case TREC:
10291627Speter 			if ( line != reccompline ) {
10301627Speter 			    reccompline = line;
10311627Speter 			    warning();
10321627Speter 			    if ( opt( 's' ) ) {
10331627Speter 				standard();
10341627Speter 			    }
1035771Speter 			    error("record comparison is non-standard");
1036771Speter 			}
1037771Speter 			break;
1038771Speter 		case TFILE:
1039771Speter 		case TARY:
1040771Speter 			error("%ss may not participate in comparisons", clnames[c]);
1041771Speter 			return (1);
1042771Speter 	}
1043771Speter 	return (NIL);
1044771Speter }
1045771Speter 
1046771Speter     /*
1047771Speter      *	this is sort of like gconst, except it works on expression trees
1048771Speter      *	rather than declaration trees, and doesn't give error messages for
1049771Speter      *	non-constant things.
1050771Speter      *	as a side effect this fills in the con structure that gconst uses.
1051771Speter      *	this returns TRUE or FALSE.
1052771Speter      */
1053771Speter constval(r)
1054771Speter 	register int *r;
1055771Speter {
1056771Speter 	register struct nl *np;
1057771Speter 	register *cn;
1058771Speter 	char *cp;
1059771Speter 	int negd, sgnd;
1060771Speter 	long ci;
1061771Speter 
1062771Speter 	con.ctype = NIL;
1063771Speter 	cn = r;
1064771Speter 	negd = sgnd = 0;
1065771Speter loop:
1066771Speter 	    /*
1067771Speter 	     *	cn[2] is nil if error recovery generated a T_STRNG
1068771Speter 	     */
1069771Speter 	if (cn == NIL || cn[2] == NIL)
1070771Speter 		return FALSE;
1071771Speter 	switch (cn[0]) {
1072771Speter 		default:
1073771Speter 			return FALSE;
1074771Speter 		case T_MINUS:
1075771Speter 			negd = 1 - negd;
1076771Speter 			/* and fall through */
1077771Speter 		case T_PLUS:
1078771Speter 			sgnd++;
1079771Speter 			cn = cn[2];
1080771Speter 			goto loop;
1081771Speter 		case T_NIL:
1082771Speter 			con.cpval = NIL;
1083771Speter 			con.cival = 0;
1084771Speter 			con.crval = con.cival;
1085771Speter 			con.ctype = nl + TNIL;
1086771Speter 			break;
1087771Speter 		case T_VAR:
1088771Speter 			np = lookup(cn[2]);
1089771Speter 			if (np == NIL || np->class != CONST) {
1090771Speter 				return FALSE;
1091771Speter 			}
1092771Speter 			if ( cn[3] != NIL ) {
1093771Speter 				return FALSE;
1094771Speter 			}
1095771Speter 			con.ctype = np->type;
1096771Speter 			switch (classify(np->type)) {
1097771Speter 				case TINT:
1098771Speter 					con.crval = np->range[0];
1099771Speter 					break;
1100771Speter 				case TDOUBLE:
1101771Speter 					con.crval = np->real;
1102771Speter 					break;
1103771Speter 				case TBOOL:
1104771Speter 				case TCHAR:
1105771Speter 				case TSCAL:
1106771Speter 					con.cival = np->value[0];
1107771Speter 					con.crval = con.cival;
1108771Speter 					break;
1109771Speter 				case TSTR:
1110771Speter 					con.cpval = np->ptr[0];
1111771Speter 					break;
1112771Speter 				default:
1113771Speter 					con.ctype = NIL;
1114771Speter 					return FALSE;
1115771Speter 			}
1116771Speter 			break;
1117771Speter 		case T_BINT:
1118771Speter 			con.crval = a8tol(cn[2]);
1119771Speter 			goto restcon;
1120771Speter 		case T_INT:
1121771Speter 			con.crval = atof(cn[2]);
1122771Speter 			if (con.crval > MAXINT || con.crval < MININT) {
1123771Speter 				derror("Constant too large for this implementation");
1124771Speter 				con.crval = 0;
1125771Speter 			}
1126771Speter restcon:
1127771Speter 			ci = con.crval;
1128771Speter #ifndef PI0
1129771Speter 			if (bytes(ci, ci) <= 2)
1130771Speter 				con.ctype = nl+T2INT;
1131771Speter 			else
1132771Speter #endif
1133771Speter 				con.ctype = nl+T4INT;
1134771Speter 			break;
1135771Speter 		case T_FINT:
1136771Speter 			con.ctype = nl+TDOUBLE;
1137771Speter 			con.crval = atof(cn[2]);
1138771Speter 			break;
1139771Speter 		case T_STRNG:
1140771Speter 			cp = cn[2];
1141771Speter 			if (cp[1] == 0) {
1142771Speter 				con.ctype = nl+T1CHAR;
1143771Speter 				con.cival = cp[0];
1144771Speter 				con.crval = con.cival;
1145771Speter 				break;
1146771Speter 			}
1147771Speter 			con.ctype = nl+TSTR;
1148771Speter 			con.cpval = cp;
1149771Speter 			break;
1150771Speter 	}
1151771Speter 	if (sgnd) {
1152771Speter 		if (isnta(con.ctype, "id")) {
1153771Speter 			derror("%s constants cannot be signed", nameof(con.ctype));
1154771Speter 			return FALSE;
1155771Speter 		} else if (negd)
1156771Speter 			con.crval = -con.crval;
1157771Speter 	}
1158771Speter 	return TRUE;
1159771Speter }
1160