1*775Speter /* Copyright (c) 1979 Regents of the University of California */
2*775Speter 
3*775Speter static	char sccsid[] = "@(#)stkrval.c 1.1 08/27/80";
4*775Speter 
5*775Speter #include "whoami.h"
6*775Speter #include "0.h"
7*775Speter #include "tree.h"
8*775Speter #include "opcode.h"
9*775Speter #include "objfmt.h"
10*775Speter #ifdef PC
11*775Speter #   include "pcops.h"
12*775Speter #endif PC
13*775Speter 
14*775Speter /*
15*775Speter  * stkrval Rvalue - an expression, and coerce it to be a stack quantity.
16*775Speter  *
17*775Speter  * Contype is the type that the caller would prefer, nand is important
18*775Speter  * if constant sets or constant strings are involved, the latter
19*775Speter  * because of string padding.
20*775Speter  */
21*775Speter /*
22*775Speter  * for the obj version, this is a copy of rvalue hacked to use fancy new
23*775Speter  * push-onto-stack-and-convert opcodes.
24*775Speter  * for the pc version, i just call rvalue and convert if i have to,
25*775Speter  * based on the return type of rvalue.
26*775Speter  */
27*775Speter struct nl *
28*775Speter stkrval(r, contype , required )
29*775Speter 	register int *r;
30*775Speter 	struct nl *contype;
31*775Speter 	long	required;
32*775Speter {
33*775Speter 	register struct nl *p;
34*775Speter 	register struct nl *q;
35*775Speter 	register char *cp, *cp1;
36*775Speter 	register int c, w;
37*775Speter 	int **pt;
38*775Speter 	long l;
39*775Speter 	double f;
40*775Speter 
41*775Speter 	if (r == NIL)
42*775Speter 		return (NIL);
43*775Speter 	if (nowexp(r))
44*775Speter 		return (NIL);
45*775Speter 	/*
46*775Speter 	 * The root of the tree tells us what sort of expression we have.
47*775Speter 	 */
48*775Speter 	switch (r[0]) {
49*775Speter 
50*775Speter 	/*
51*775Speter 	 * The constant nil
52*775Speter 	 */
53*775Speter 	case T_NIL:
54*775Speter #		ifdef OBJ
55*775Speter 		    put(2, O_CON14, 0);
56*775Speter #		endif OBJ
57*775Speter #		ifdef PC
58*775Speter 		    putleaf( P2ICON , 0 , 0 , P2INT , 0 );
59*775Speter #		endif PC
60*775Speter 		return (nl+TNIL);
61*775Speter 
62*775Speter 	case T_FCALL:
63*775Speter 	case T_VAR:
64*775Speter 		p = lookup(r[2]);
65*775Speter 		if (p == NIL || p->class == BADUSE)
66*775Speter 			return (NIL);
67*775Speter 		switch (p->class) {
68*775Speter 		case VAR:
69*775Speter 			/*
70*775Speter 			  if a variable is
71*775Speter 			 * qualified then get
72*775Speter 			 * the rvalue by a
73*775Speter 			 * stklval and an ind.
74*775Speter 			 */
75*775Speter 			if (r[3] != NIL)
76*775Speter 				goto ind;
77*775Speter 			q = p->type;
78*775Speter 			if (q == NIL)
79*775Speter 				return (NIL);
80*775Speter 			if (classify(q) == TSTR)
81*775Speter 				return(stklval(r, NOFLAGS));
82*775Speter #			ifdef OBJ
83*775Speter 			    w = width(q);
84*775Speter 			    switch (w) {
85*775Speter 			    case 8:
86*775Speter 				    put(2, O_RV8 | bn << 8+INDX, p->value[0]);
87*775Speter 				    return(q);
88*775Speter 			    case 4:
89*775Speter 				    put(2, O_RV4 | bn << 8+INDX, p->value[0]);
90*775Speter 				    return(q);
91*775Speter 			    case 2:
92*775Speter 				    put(2, O_RV24 | bn << 8+INDX, p->value[0]);
93*775Speter 				    return(q);
94*775Speter 			    case 1:
95*775Speter 				    put(2, O_RV14 | bn << 8+INDX, p->value[0]);
96*775Speter 				    return(q);
97*775Speter 			    default:
98*775Speter 				    put(3, O_RV | bn << 8+INDX, p->value[0], w);
99*775Speter 				    return(q);
100*775Speter 			     }
101*775Speter #			endif OBJ
102*775Speter #			ifdef PC
103*775Speter 			     return rvalue( r , contype , required );
104*775Speter #			endif PC
105*775Speter 
106*775Speter 		case WITHPTR:
107*775Speter 		case REF:
108*775Speter 			/*
109*775Speter 			 * A stklval for these
110*775Speter 			 * is actually what one
111*775Speter 			 * might consider a rvalue.
112*775Speter 			 */
113*775Speter ind:
114*775Speter 			q = stklval(r, NOFLAGS);
115*775Speter 			if (q == NIL)
116*775Speter 				return (NIL);
117*775Speter 			if (classify(q) == TSTR)
118*775Speter 				return(q);
119*775Speter #			ifdef OBJ
120*775Speter 			    w = width(q);
121*775Speter 			    switch (w) {
122*775Speter 				    case 8:
123*775Speter 					    put(1, O_IND8);
124*775Speter 					    return(q);
125*775Speter 				    case 4:
126*775Speter 					    put(1, O_IND4);
127*775Speter 					    return(q);
128*775Speter 				    case 2:
129*775Speter 					    put(1, O_IND24);
130*775Speter 					    return(q);
131*775Speter 				    case 1:
132*775Speter 					    put(1, O_IND14);
133*775Speter 					    return(q);
134*775Speter 				    default:
135*775Speter 					    put(2, O_IND, w);
136*775Speter 					    return(q);
137*775Speter 			    }
138*775Speter #			endif OBJ
139*775Speter #			ifdef PC
140*775Speter 			    if ( required == RREQ ) {
141*775Speter 				putop( P2UNARY P2MUL , p2type( q ) );
142*775Speter 			    }
143*775Speter 			    return q;
144*775Speter #			endif PC
145*775Speter 
146*775Speter 		case CONST:
147*775Speter 			if (r[3] != NIL) {
148*775Speter 				error("%s is a constant and cannot be qualified", r[2]);
149*775Speter 				return (NIL);
150*775Speter 			}
151*775Speter 			q = p->type;
152*775Speter 			if (q == NIL)
153*775Speter 				return (NIL);
154*775Speter 			if (q == nl+TSTR) {
155*775Speter 				/*
156*775Speter 				 * Find the size of the string
157*775Speter 				 * constant if needed.
158*775Speter 				 */
159*775Speter 				cp = p->ptr[0];
160*775Speter cstrng:
161*775Speter 				cp1 = cp;
162*775Speter 				for (c = 0; *cp++; c++)
163*775Speter 					continue;
164*775Speter 				w = 0;
165*775Speter 				if (contype != NIL && !opt('s')) {
166*775Speter 					if (width(contype) < c && classify(contype) == TSTR) {
167*775Speter 						error("Constant string too long");
168*775Speter 						return (NIL);
169*775Speter 					}
170*775Speter 					w = width(contype) - c;
171*775Speter 				}
172*775Speter #				ifdef OBJ
173*775Speter 				    put(2, O_LVCON, lenstr(cp1, w));
174*775Speter 				    putstr(cp1, w);
175*775Speter #				endif OBJ
176*775Speter #				ifdef PC
177*775Speter 				    putCONG( cp1 , c + w , LREQ );
178*775Speter #				endif PC
179*775Speter 				/*
180*775Speter 				 * Define the string temporarily
181*775Speter 				 * so later people can know its
182*775Speter 				 * width.
183*775Speter 				 * cleaned out by stat.
184*775Speter 				 */
185*775Speter 				q = defnl(0, STR, 0, c);
186*775Speter 				q->type = q;
187*775Speter 				return (q);
188*775Speter 			}
189*775Speter 			if (q == nl+T1CHAR) {
190*775Speter #			    ifdef OBJ
191*775Speter 				put(2, O_CONC4, p->value[0]);
192*775Speter #			    endif OBJ
193*775Speter #			    ifdef PC
194*775Speter 				putleaf( P2ICON , p -> value[0] , 0 , P2CHAR , 0 );
195*775Speter #			    endif PC
196*775Speter 			    return(q);
197*775Speter 			}
198*775Speter 			/*
199*775Speter 			 * Every other kind of constant here
200*775Speter 			 */
201*775Speter #			ifdef OBJ
202*775Speter 			    switch (width(q)) {
203*775Speter 			    case 8:
204*775Speter #ifndef DEBUG
205*775Speter 				    put(2, O_CON8, p->real);
206*775Speter 				    return(q);
207*775Speter #else
208*775Speter 				    if (hp21mx) {
209*775Speter 					    f = p->real;
210*775Speter 					    conv(&f);
211*775Speter 					    l = f.plong;
212*775Speter 					    put(2, O_CON4, l);
213*775Speter 				    } else
214*775Speter 					    put(2, O_CON8, p->real);
215*775Speter 				    return(q);
216*775Speter #endif
217*775Speter 			    case 4:
218*775Speter 				    put(2, O_CON4, p->range[0]);
219*775Speter 				    return(q);
220*775Speter 			    case 2:
221*775Speter 				    put(2, O_CON24, (short)p->range[0]);
222*775Speter 				    return(q);
223*775Speter 			    case 1:
224*775Speter 				    put(2, O_CON14, (short)p->range[0]);
225*775Speter 				    return(q);
226*775Speter 			    default:
227*775Speter 				    panic("stkrval");
228*775Speter 			    }
229*775Speter #			endif OBJ
230*775Speter #			ifdef PC
231*775Speter 			    return rvalue( r , contype , required );
232*775Speter #			endif PC
233*775Speter 
234*775Speter 		case FUNC:
235*775Speter 			/*
236*775Speter 			 * Function call
237*775Speter 			 */
238*775Speter 			pt = (int **)r[3];
239*775Speter 			if (pt != NIL) {
240*775Speter 				switch (pt[1][0]) {
241*775Speter 				case T_PTR:
242*775Speter 				case T_ARGL:
243*775Speter 				case T_ARY:
244*775Speter 				case T_FIELD:
245*775Speter 					error("Can't qualify a function result value");
246*775Speter 					return (NIL);
247*775Speter 				}
248*775Speter 			}
249*775Speter #			ifdef OBJ
250*775Speter 			    q = p->type;
251*775Speter 			    if (classify(q) == TSTR) {
252*775Speter 				    c = width(q);
253*775Speter 				    put(2, O_LVCON, even(c+1));
254*775Speter 				    putstr("", c);
255*775Speter 				    put(1, O_SDUP4);
256*775Speter 				    p = funccod(r);
257*775Speter 				    put(2, O_AS, c);
258*775Speter 				    return(p);
259*775Speter 			    }
260*775Speter 			    p = funccod(r);
261*775Speter 			    if (width(p) <= 2)
262*775Speter 				    put(1, O_STOI);
263*775Speter #			endif OBJ
264*775Speter #			ifdef PC
265*775Speter 			    p = pcfunccod( r );
266*775Speter #			endif PC
267*775Speter 			return (p);
268*775Speter 
269*775Speter 		case TYPE:
270*775Speter 			error("Type names (e.g. %s) allowed only in declarations", p->symbol);
271*775Speter 			return (NIL);
272*775Speter 
273*775Speter 		case PROC:
274*775Speter 			error("Procedure %s found where expression required", p->symbol);
275*775Speter 			return (NIL);
276*775Speter 		default:
277*775Speter 			panic("stkrvid");
278*775Speter 		}
279*775Speter 	case T_CSET:
280*775Speter 	case T_PLUS:
281*775Speter 	case T_MINUS:
282*775Speter 	case T_NOT:
283*775Speter 	case T_AND:
284*775Speter 	case T_OR:
285*775Speter 	case T_DIVD:
286*775Speter 	case T_MULT:
287*775Speter 	case T_SUB:
288*775Speter 	case T_ADD:
289*775Speter 	case T_MOD:
290*775Speter 	case T_DIV:
291*775Speter 	case T_EQ:
292*775Speter 	case T_NE:
293*775Speter 	case T_GE:
294*775Speter 	case T_LE:
295*775Speter 	case T_GT:
296*775Speter 	case T_LT:
297*775Speter 	case T_IN:
298*775Speter 		p = rvalue(r, contype , required );
299*775Speter #		ifdef OBJ
300*775Speter 		    if (width(p) <= 2)
301*775Speter 			    put(1, O_STOI);
302*775Speter #		endif OBJ
303*775Speter 		return (p);
304*775Speter 
305*775Speter 	default:
306*775Speter 		if (r[2] == NIL)
307*775Speter 			return (NIL);
308*775Speter 		switch (r[0]) {
309*775Speter 		default:
310*775Speter 			panic("stkrval3");
311*775Speter 
312*775Speter 		/*
313*775Speter 		 * An octal number
314*775Speter 		 */
315*775Speter 		case T_BINT:
316*775Speter 			f = a8tol(r[2]);
317*775Speter 			goto conint;
318*775Speter 
319*775Speter 		/*
320*775Speter 		 * A decimal number
321*775Speter 		 */
322*775Speter 		case T_INT:
323*775Speter 			f = atof(r[2]);
324*775Speter conint:
325*775Speter 			if (f > MAXINT || f < MININT) {
326*775Speter 				error("Constant too large for this implementation");
327*775Speter 				return (NIL);
328*775Speter 			}
329*775Speter 			l = f;
330*775Speter 			if (bytes(l, l) <= 2) {
331*775Speter #			    ifdef OBJ
332*775Speter 				put(2, O_CON24, (short)l);
333*775Speter #			    endif OBJ
334*775Speter #			    ifdef PC
335*775Speter 				putleaf( P2ICON , (short) l , 0 , P2INT , 0 );
336*775Speter #			    endif PC
337*775Speter 				return(nl+T4INT);
338*775Speter 			}
339*775Speter #			ifdef OBJ
340*775Speter 			    put(2, O_CON4, l);
341*775Speter #			endif OBJ
342*775Speter #			ifdef PC
343*775Speter 			    putleaf( P2ICON , l , 0 , P2INT , 0 );
344*775Speter #			endif PC
345*775Speter 			return (nl+T4INT);
346*775Speter 
347*775Speter 		/*
348*775Speter 		 * A floating point number
349*775Speter 		 */
350*775Speter 		case T_FINT:
351*775Speter #		   	ifdef OBJ
352*775Speter 			    put(2, O_CON8, atof(r[2]));
353*775Speter #			endif OBJ
354*775Speter #			ifdef PC
355*775Speter 			    putCON8( atof( r[2] ) );
356*775Speter #			endif PC
357*775Speter 			return (nl+TDOUBLE);
358*775Speter 
359*775Speter 		/*
360*775Speter 		 * Constant strings.  Note that constant characters
361*775Speter 		 * are constant strings of length one; there is
362*775Speter 		 * no constant string of length one.
363*775Speter 		 */
364*775Speter 		case T_STRNG:
365*775Speter 			cp = r[2];
366*775Speter 			if (cp[1] == 0) {
367*775Speter #				ifdef OBJ
368*775Speter 				    put(2, O_CONC4, cp[0]);
369*775Speter #				endif OBJ
370*775Speter #				ifdef PC
371*775Speter 				    putleaf( P2ICON , cp[0] , 0 , P2CHAR , 0 );
372*775Speter #				endif PC
373*775Speter 				return(nl+T1CHAR);
374*775Speter 			}
375*775Speter 			goto cstrng;
376*775Speter 		}
377*775Speter 
378*775Speter 	}
379*775Speter }
380