xref: /csrg-svn/usr.bin/pascal/src/stkrval.c (revision 14743)
1775Speter /* Copyright (c) 1979 Regents of the University of California */
2775Speter 
3*14743Sthien #ifndef lint
4*14743Sthien static char sccsid[] = "@(#)stkrval.c 1.8 08/19/83";
5*14743Sthien #endif
6775Speter 
7775Speter #include "whoami.h"
8775Speter #include "0.h"
9775Speter #include "tree.h"
10775Speter #include "opcode.h"
11775Speter #include "objfmt.h"
12775Speter #ifdef PC
13775Speter #   include "pcops.h"
14775Speter #endif PC
15*14743Sthien #include "tree_ty.h"
16775Speter 
17775Speter /*
18775Speter  * stkrval Rvalue - an expression, and coerce it to be a stack quantity.
19775Speter  *
20775Speter  * Contype is the type that the caller would prefer, nand is important
21775Speter  * if constant sets or constant strings are involved, the latter
22775Speter  * because of string padding.
23775Speter  */
24775Speter /*
25775Speter  * for the obj version, this is a copy of rvalue hacked to use fancy new
26775Speter  * push-onto-stack-and-convert opcodes.
27775Speter  * for the pc version, i just call rvalue and convert if i have to,
28775Speter  * based on the return type of rvalue.
29775Speter  */
30775Speter struct nl *
31775Speter stkrval(r, contype , required )
32*14743Sthien 	register struct tnode *r;
33775Speter 	struct nl *contype;
34775Speter 	long	required;
35775Speter {
36775Speter 	register struct nl *p;
37775Speter 	register struct nl *q;
38775Speter 	register char *cp, *cp1;
39775Speter 	register int c, w;
40*14743Sthien 	struct tnode *pt;
41775Speter 	long l;
42*14743Sthien 	union
43*14743Sthien 	{
44*14743Sthien 		double pdouble;
45*14743Sthien 		long   plong[2];
46*14743Sthien 	}f;
47775Speter 
48*14743Sthien 	if (r == TR_NIL)
49*14743Sthien 		return (NLNIL);
50775Speter 	if (nowexp(r))
51*14743Sthien 		return (NLNIL);
52775Speter 	/*
53775Speter 	 * The root of the tree tells us what sort of expression we have.
54775Speter 	 */
55*14743Sthien 	switch (r->tag) {
56775Speter 
57775Speter 	/*
58775Speter 	 * The constant nil
59775Speter 	 */
60775Speter 	case T_NIL:
61775Speter #		ifdef OBJ
62*14743Sthien 		    (void) put(2, O_CON14, 0);
63775Speter #		endif OBJ
64775Speter #		ifdef PC
65*14743Sthien 		    putleaf( P2ICON , 0 , 0 , P2INT , (char *) 0 );
66775Speter #		endif PC
67775Speter 		return (nl+TNIL);
68775Speter 
69775Speter 	case T_FCALL:
70775Speter 	case T_VAR:
71*14743Sthien 		p = lookup(r->var_node.cptr);
72*14743Sthien 		if (p == NLNIL || p->class == BADUSE)
73*14743Sthien 			return (NLNIL);
74775Speter 		switch (p->class) {
75775Speter 		case VAR:
76775Speter 			/*
773080Smckusic 			 * if a variable is
78775Speter 			 * qualified then get
79775Speter 			 * the rvalue by a
80775Speter 			 * stklval and an ind.
81775Speter 			 */
82*14743Sthien 			if (r->var_node.qual != TR_NIL)
83775Speter 				goto ind;
84775Speter 			q = p->type;
85*14743Sthien 			if (q == NLNIL)
86*14743Sthien 				return (NLNIL);
87775Speter 			if (classify(q) == TSTR)
88775Speter 				return(stklval(r, NOFLAGS));
89775Speter #			ifdef OBJ
9010568Smckusick 				return (stackRV(p));
91775Speter #			endif OBJ
92775Speter #			ifdef PC
93*14743Sthien 			    q = rvalue( r , contype , (int) required );
9410360Smckusick 			    if (isa(q, "sbci")) {
9510360Smckusick 				sconv(p2type(q),P2INT);
9610360Smckusick 			    }
9710360Smckusick 			    return q;
98775Speter #			endif PC
99775Speter 
100775Speter 		case WITHPTR:
101775Speter 		case REF:
102775Speter 			/*
103775Speter 			 * A stklval for these
104775Speter 			 * is actually what one
105775Speter 			 * might consider a rvalue.
106775Speter 			 */
107775Speter ind:
108775Speter 			q = stklval(r, NOFLAGS);
109*14743Sthien 			if (q == NLNIL)
110*14743Sthien 				return (NLNIL);
111775Speter 			if (classify(q) == TSTR)
112775Speter 				return(q);
113775Speter #			ifdef OBJ
114775Speter 			    w = width(q);
115775Speter 			    switch (w) {
116775Speter 				    case 8:
117*14743Sthien 					    (void) put(1, O_IND8);
118775Speter 					    return(q);
119775Speter 				    case 4:
120*14743Sthien 					    (void) put(1, O_IND4);
121775Speter 					    return(q);
122775Speter 				    case 2:
123*14743Sthien 					    (void) put(1, O_IND24);
124775Speter 					    return(q);
125775Speter 				    case 1:
126*14743Sthien 					    (void) put(1, O_IND14);
127775Speter 					    return(q);
128775Speter 				    default:
129*14743Sthien 					    (void) put(2, O_IND, w);
130775Speter 					    return(q);
131775Speter 			    }
132775Speter #			endif OBJ
133775Speter #			ifdef PC
134775Speter 			    if ( required == RREQ ) {
135775Speter 				putop( P2UNARY P2MUL , p2type( q ) );
13610360Smckusick 				if (isa(q,"sbci")) {
13710360Smckusick 				    sconv(p2type(q),P2INT);
13810360Smckusick 				}
139775Speter 			    }
140775Speter 			    return q;
141775Speter #			endif PC
142775Speter 
143775Speter 		case CONST:
144*14743Sthien 			if (r->var_node.qual != TR_NIL) {
145*14743Sthien 				error("%s is a constant and cannot be qualified", r->var_node.cptr);
146*14743Sthien 				return (NLNIL);
147775Speter 			}
148775Speter 			q = p->type;
149*14743Sthien 			if (q == NLNIL)
150*14743Sthien 				return (NLNIL);
151775Speter 			if (q == nl+TSTR) {
152775Speter 				/*
153775Speter 				 * Find the size of the string
154775Speter 				 * constant if needed.
155775Speter 				 */
156*14743Sthien 				cp = (char *) p->ptr[0];
157775Speter cstrng:
158775Speter 				cp1 = cp;
159775Speter 				for (c = 0; *cp++; c++)
160775Speter 					continue;
16110841Speter 				w = c;
162775Speter 				if (contype != NIL && !opt('s')) {
163775Speter 					if (width(contype) < c && classify(contype) == TSTR) {
164775Speter 						error("Constant string too long");
165*14743Sthien 						return (NLNIL);
166775Speter 					}
16710841Speter 					w = width(contype);
168775Speter 				}
169775Speter #				ifdef OBJ
170*14743Sthien 				    (void) put(2, O_LVCON, lenstr(cp1, w - c));
17110841Speter 				    putstr(cp1, w - c);
172775Speter #				endif OBJ
173775Speter #				ifdef PC
17410841Speter 				    putCONG( cp1 , w , LREQ );
175775Speter #				endif PC
176775Speter 				/*
177775Speter 				 * Define the string temporarily
178775Speter 				 * so later people can know its
179775Speter 				 * width.
180775Speter 				 * cleaned out by stat.
181775Speter 				 */
182*14743Sthien 				q = defnl((char *) 0, STR, NLNIL, w);
183775Speter 				q->type = q;
184775Speter 				return (q);
185775Speter 			}
186775Speter 			if (q == nl+T1CHAR) {
187775Speter #			    ifdef OBJ
188*14743Sthien 				(void) put(2, O_CONC4, (int)p->value[0]);
189775Speter #			    endif OBJ
190775Speter #			    ifdef PC
191*14743Sthien 				putleaf(P2ICON, p -> value[0], 0, P2INT,
192*14743Sthien 						(char *) 0);
193775Speter #			    endif PC
194775Speter 			    return(q);
195775Speter 			}
196775Speter 			/*
197775Speter 			 * Every other kind of constant here
198775Speter 			 */
199775Speter #			ifdef OBJ
200775Speter 			    switch (width(q)) {
201775Speter 			    case 8:
202775Speter #ifndef DEBUG
203*14743Sthien 				    (void) put(2, O_CON8, p->real);
204775Speter 				    return(q);
205775Speter #else
206775Speter 				    if (hp21mx) {
207*14743Sthien 					    f.pdouble = p->real;
208*14743Sthien 					    conv((int *) (&f.pdouble));
209*14743Sthien 					    l = f.plong[1];
210*14743Sthien 					    (void) put(2, O_CON4, l);
211775Speter 				    } else
212*14743Sthien 					    (void) put(2, O_CON8, p->real);
213775Speter 				    return(q);
214775Speter #endif
215775Speter 			    case 4:
216*14743Sthien 				    (void) put(2, O_CON4, p->range[0]);
217775Speter 				    return(q);
218775Speter 			    case 2:
219*14743Sthien 				    (void) put(2, O_CON24, (short)p->range[0]);
220775Speter 				    return(q);
221775Speter 			    case 1:
222*14743Sthien 				    (void) put(2, O_CON14, p->value[0]);
223775Speter 				    return(q);
224775Speter 			    default:
225775Speter 				    panic("stkrval");
226775Speter 			    }
227775Speter #			endif OBJ
228775Speter #			ifdef PC
229*14743Sthien 			    q = rvalue( r , contype , (int) required );
23010360Smckusick 			    if (isa(q,"sbci")) {
23110360Smckusick 				sconv(p2type(q),P2INT);
23210360Smckusick 			    }
23310360Smckusick 			    return q;
234775Speter #			endif PC
235775Speter 
236775Speter 		case FUNC:
2371201Speter 		case FFUNC:
238775Speter 			/*
239775Speter 			 * Function call
240775Speter 			 */
241*14743Sthien 			pt = r->var_node.qual;
242*14743Sthien 			if (pt != TR_NIL) {
243*14743Sthien 				switch (pt->list_node.list->tag) {
244775Speter 				case T_PTR:
245775Speter 				case T_ARGL:
246775Speter 				case T_ARY:
247775Speter 				case T_FIELD:
248775Speter 					error("Can't qualify a function result value");
249*14743Sthien 					return (NLNIL);
250775Speter 				}
251775Speter 			}
252775Speter #			ifdef OBJ
253775Speter 			    q = p->type;
254775Speter 			    if (classify(q) == TSTR) {
255775Speter 				    c = width(q);
256*14743Sthien 				    (void) put(2, O_LVCON, even(c+1));
257775Speter 				    putstr("", c);
258*14743Sthien 				    (void) put(1, PTR_DUP);
259775Speter 				    p = funccod(r);
260*14743Sthien 				    (void) put(2, O_AS, c);
261775Speter 				    return(p);
262775Speter 			    }
263775Speter 			    p = funccod(r);
264775Speter 			    if (width(p) <= 2)
265*14743Sthien 				    (void) put(1, O_STOI);
266775Speter #			endif OBJ
267775Speter #			ifdef PC
268775Speter 			    p = pcfunccod( r );
26910360Smckusick 			    if (isa(p,"sbci")) {
27010360Smckusick 				sconv(p2type(p),P2INT);
27110360Smckusick 			    }
272775Speter #			endif PC
273775Speter 			return (p);
274775Speter 
275775Speter 		case TYPE:
276775Speter 			error("Type names (e.g. %s) allowed only in declarations", p->symbol);
277*14743Sthien 			return (NLNIL);
278775Speter 
279775Speter 		case PROC:
2801201Speter 		case FPROC:
281775Speter 			error("Procedure %s found where expression required", p->symbol);
282*14743Sthien 			return (NLNIL);
283775Speter 		default:
284775Speter 			panic("stkrvid");
285775Speter 		}
286775Speter 	case T_PLUS:
287775Speter 	case T_MINUS:
288775Speter 	case T_NOT:
289775Speter 	case T_AND:
290775Speter 	case T_OR:
291775Speter 	case T_DIVD:
292775Speter 	case T_MULT:
293775Speter 	case T_SUB:
294775Speter 	case T_ADD:
295775Speter 	case T_MOD:
296775Speter 	case T_DIV:
297775Speter 	case T_EQ:
298775Speter 	case T_NE:
299775Speter 	case T_GE:
300775Speter 	case T_LE:
301775Speter 	case T_GT:
302775Speter 	case T_LT:
303775Speter 	case T_IN:
304*14743Sthien 		p = rvalue(r, contype , (int) required );
305775Speter #		ifdef OBJ
306775Speter 		    if (width(p) <= 2)
307*14743Sthien 			    (void) put(1, O_STOI);
308775Speter #		endif OBJ
30910360Smckusick #		ifdef PC
31010360Smckusick 		    if (isa(p,"sbci")) {
31110360Smckusick 			sconv(p2type(p),P2INT);
31210360Smckusick 		    }
31310360Smckusick #		endif PC
314775Speter 		return (p);
315909Speter 	case T_CSET:
316*14743Sthien 		p = rvalue(r, contype , (int) required );
317909Speter 		return (p);
318775Speter 	default:
319*14743Sthien 		if (r->const_node.cptr == (char *) NIL)
320*14743Sthien 			return (NLNIL);
321*14743Sthien 		switch (r->tag) {
322775Speter 		default:
323775Speter 			panic("stkrval3");
324775Speter 
325775Speter 		/*
326775Speter 		 * An octal number
327775Speter 		 */
328775Speter 		case T_BINT:
329*14743Sthien 			f.pdouble = a8tol(r->const_node.cptr);
330775Speter 			goto conint;
331775Speter 
332775Speter 		/*
333775Speter 		 * A decimal number
334775Speter 		 */
335775Speter 		case T_INT:
336*14743Sthien 			f.pdouble = atof(r->const_node.cptr);
337775Speter conint:
338*14743Sthien 			if (f.pdouble > MAXINT || f.pdouble < MININT) {
339775Speter 				error("Constant too large for this implementation");
340*14743Sthien 				return (NLNIL);
341775Speter 			}
342*14743Sthien 			l = f.pdouble;
343775Speter 			if (bytes(l, l) <= 2) {
344775Speter #			    ifdef OBJ
345*14743Sthien 				(void) put(2, O_CON24, (short)l);
346775Speter #			    endif OBJ
347775Speter #			    ifdef PC
348*14743Sthien 				putleaf( P2ICON , (short) l , 0 , P2INT ,
349*14743Sthien 						(char *) 0 );
350775Speter #			    endif PC
351775Speter 				return(nl+T4INT);
352775Speter 			}
353775Speter #			ifdef OBJ
354*14743Sthien 			    (void) put(2, O_CON4, l);
355775Speter #			endif OBJ
356775Speter #			ifdef PC
357*14743Sthien 			    putleaf( P2ICON , (int) l , 0 , P2INT , (char *) 0 );
358775Speter #			endif PC
359775Speter 			return (nl+T4INT);
360775Speter 
361775Speter 		/*
362775Speter 		 * A floating point number
363775Speter 		 */
364775Speter 		case T_FINT:
365775Speter #		   	ifdef OBJ
366*14743Sthien 			    (void) put(2, O_CON8, atof(r->const_node.cptr));
367775Speter #			endif OBJ
368775Speter #			ifdef PC
369*14743Sthien 			    putCON8( atof( r->const_node.cptr ) );
370775Speter #			endif PC
371775Speter 			return (nl+TDOUBLE);
372775Speter 
373775Speter 		/*
374775Speter 		 * Constant strings.  Note that constant characters
375775Speter 		 * are constant strings of length one; there is
376775Speter 		 * no constant string of length one.
377775Speter 		 */
378775Speter 		case T_STRNG:
379*14743Sthien 			cp = r->const_node.cptr;
380775Speter 			if (cp[1] == 0) {
381775Speter #				ifdef OBJ
382*14743Sthien 				    (void) put(2, O_CONC4, cp[0]);
383775Speter #				endif OBJ
384775Speter #				ifdef PC
385*14743Sthien 				    putleaf( P2ICON , cp[0] , 0 , P2INT ,
386*14743Sthien 						(char *) 0 );
387775Speter #				endif PC
388775Speter 				return(nl+T1CHAR);
389775Speter 			}
390775Speter 			goto cstrng;
391775Speter 		}
392775Speter 
393775Speter 	}
394775Speter }
39510568Smckusick 
39610568Smckusick #ifdef OBJ
39710568Smckusick /*
39810568Smckusick  * push a value onto the interpreter stack, longword aligned.
39910568Smckusick  */
400*14743Sthien struct nl
401*14743Sthien *stackRV(p)
40210568Smckusick 	struct nl *p;
40310568Smckusick {
40410568Smckusick 	struct nl *q;
40510568Smckusick 	int w, bn;
40610568Smckusick 
40710568Smckusick 	q = p->type;
408*14743Sthien 	if (q == NLNIL)
409*14743Sthien 		return (NLNIL);
41010568Smckusick 	bn = BLOCKNO(p->nl_block);
41110568Smckusick 	w = width(q);
41210568Smckusick 	switch (w) {
41310568Smckusick 	case 8:
414*14743Sthien 		(void) put(2, O_RV8 | bn << 8+INDX, (int)p->value[0]);
41510568Smckusick 		break;
41610568Smckusick 	case 4:
417*14743Sthien 		(void) put(2, O_RV4 | bn << 8+INDX, (int)p->value[0]);
41810568Smckusick 		break;
41910568Smckusick 	case 2:
420*14743Sthien 		(void) put(2, O_RV24 | bn << 8+INDX, (int)p->value[0]);
42110568Smckusick 		break;
42210568Smckusick 	case 1:
423*14743Sthien 		(void) put(2, O_RV14 | bn << 8+INDX, (int)p->value[0]);
42410568Smckusick 		break;
42510568Smckusick 	default:
426*14743Sthien 		(void) put(3, O_RV | bn << 8+INDX, (int)p->value[0], w);
42710568Smckusick 		break;
42810568Smckusick 	}
42910568Smckusick 	return (q);
43010568Smckusick }
43110568Smckusick #endif OBJ
432