xref: /csrg-svn/usr.bin/pascal/src/stkrval.c (revision 62217)
148116Sbostic /*-
2*62217Sbostic  * Copyright (c) 1980, 1993
3*62217Sbostic  *	The Regents of the University of California.  All rights reserved.
448116Sbostic  *
548116Sbostic  * %sccs.include.redist.c%
622194Sdist  */
7775Speter 
814743Sthien #ifndef lint
9*62217Sbostic static char sccsid[] = "@(#)stkrval.c	8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11775Speter 
12775Speter #include "whoami.h"
13775Speter #include "0.h"
14775Speter #include "tree.h"
15775Speter #include "opcode.h"
16775Speter #include "objfmt.h"
1730037Smckusick #include "align.h"
18775Speter #ifdef PC
1918471Sralph #   include <pcc.h>
20775Speter #endif PC
2114743Sthien #include "tree_ty.h"
22775Speter 
23775Speter /*
24775Speter  * stkrval Rvalue - an expression, and coerce it to be a stack quantity.
25775Speter  *
26775Speter  * Contype is the type that the caller would prefer, nand is important
27775Speter  * if constant sets or constant strings are involved, the latter
28775Speter  * because of string padding.
29775Speter  */
30775Speter /*
31775Speter  * for the obj version, this is a copy of rvalue hacked to use fancy new
32775Speter  * push-onto-stack-and-convert opcodes.
33775Speter  * for the pc version, i just call rvalue and convert if i have to,
34775Speter  * based on the return type of rvalue.
35775Speter  */
36775Speter struct nl *
stkrval(r,contype,required)37775Speter stkrval(r, contype , required )
3814743Sthien 	register struct tnode *r;
39775Speter 	struct nl *contype;
40775Speter 	long	required;
41775Speter {
42775Speter 	register struct nl *p;
43775Speter 	register struct nl *q;
44775Speter 	register char *cp, *cp1;
45775Speter 	register int c, w;
4614743Sthien 	struct tnode *pt;
47775Speter 	long l;
4814743Sthien 	union
4914743Sthien 	{
5014743Sthien 		double pdouble;
5114743Sthien 		long   plong[2];
5214743Sthien 	}f;
53775Speter 
5414743Sthien 	if (r == TR_NIL)
5514743Sthien 		return (NLNIL);
56775Speter 	if (nowexp(r))
5714743Sthien 		return (NLNIL);
58775Speter 	/*
59775Speter 	 * The root of the tree tells us what sort of expression we have.
60775Speter 	 */
6114743Sthien 	switch (r->tag) {
62775Speter 
63775Speter 	/*
64775Speter 	 * The constant nil
65775Speter 	 */
66775Speter 	case T_NIL:
67775Speter #		ifdef OBJ
6814743Sthien 		    (void) put(2, O_CON14, 0);
69775Speter #		endif OBJ
70775Speter #		ifdef PC
7118471Sralph 		    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
72775Speter #		endif PC
73775Speter 		return (nl+TNIL);
74775Speter 
75775Speter 	case T_FCALL:
76775Speter 	case T_VAR:
7714743Sthien 		p = lookup(r->var_node.cptr);
7814743Sthien 		if (p == NLNIL || p->class == BADUSE)
7914743Sthien 			return (NLNIL);
80775Speter 		switch (p->class) {
81775Speter 		case VAR:
82775Speter 			/*
833080Smckusic 			 * if a variable is
84775Speter 			 * qualified then get
85775Speter 			 * the rvalue by a
86775Speter 			 * stklval and an ind.
87775Speter 			 */
8814743Sthien 			if (r->var_node.qual != TR_NIL)
89775Speter 				goto ind;
90775Speter 			q = p->type;
9114743Sthien 			if (q == NLNIL)
9214743Sthien 				return (NLNIL);
93775Speter 			if (classify(q) == TSTR)
94775Speter 				return(stklval(r, NOFLAGS));
95775Speter #			ifdef OBJ
9610568Smckusick 				return (stackRV(p));
97775Speter #			endif OBJ
98775Speter #			ifdef PC
9914743Sthien 			    q = rvalue( r , contype , (int) required );
10010360Smckusick 			    if (isa(q, "sbci")) {
10118471Sralph 				sconv(p2type(q),PCCT_INT);
10210360Smckusick 			    }
10310360Smckusick 			    return q;
104775Speter #			endif PC
105775Speter 
106775Speter 		case WITHPTR:
107775Speter 		case REF:
108775Speter 			/*
109775Speter 			 * A stklval for these
110775Speter 			 * is actually what one
111775Speter 			 * might consider a rvalue.
112775Speter 			 */
113775Speter ind:
114775Speter 			q = stklval(r, NOFLAGS);
11514743Sthien 			if (q == NLNIL)
11614743Sthien 				return (NLNIL);
117775Speter 			if (classify(q) == TSTR)
118775Speter 				return(q);
119775Speter #			ifdef OBJ
120775Speter 			    w = width(q);
121775Speter 			    switch (w) {
122775Speter 				    case 8:
12314743Sthien 					    (void) put(1, O_IND8);
124775Speter 					    return(q);
125775Speter 				    case 4:
12614743Sthien 					    (void) put(1, O_IND4);
127775Speter 					    return(q);
128775Speter 				    case 2:
12914743Sthien 					    (void) put(1, O_IND24);
130775Speter 					    return(q);
131775Speter 				    case 1:
13214743Sthien 					    (void) put(1, O_IND14);
133775Speter 					    return(q);
134775Speter 				    default:
13514743Sthien 					    (void) put(2, O_IND, w);
136775Speter 					    return(q);
137775Speter 			    }
138775Speter #			endif OBJ
139775Speter #			ifdef PC
140775Speter 			    if ( required == RREQ ) {
14118471Sralph 				putop( PCCOM_UNARY PCC_MUL , p2type( q ) );
14210360Smckusick 				if (isa(q,"sbci")) {
14318471Sralph 				    sconv(p2type(q),PCCT_INT);
14410360Smckusick 				}
145775Speter 			    }
146775Speter 			    return q;
147775Speter #			endif PC
148775Speter 
149775Speter 		case CONST:
15014743Sthien 			if (r->var_node.qual != TR_NIL) {
15114743Sthien 				error("%s is a constant and cannot be qualified", r->var_node.cptr);
15214743Sthien 				return (NLNIL);
153775Speter 			}
154775Speter 			q = p->type;
15514743Sthien 			if (q == NLNIL)
15614743Sthien 				return (NLNIL);
157775Speter 			if (q == nl+TSTR) {
158775Speter 				/*
159775Speter 				 * Find the size of the string
160775Speter 				 * constant if needed.
161775Speter 				 */
16214743Sthien 				cp = (char *) p->ptr[0];
163775Speter cstrng:
164775Speter 				cp1 = cp;
165775Speter 				for (c = 0; *cp++; c++)
166775Speter 					continue;
16710841Speter 				w = c;
168775Speter 				if (contype != NIL && !opt('s')) {
169775Speter 					if (width(contype) < c && classify(contype) == TSTR) {
170775Speter 						error("Constant string too long");
17114743Sthien 						return (NLNIL);
172775Speter 					}
17310841Speter 					w = width(contype);
174775Speter 				}
175775Speter #				ifdef OBJ
17614743Sthien 				    (void) put(2, O_LVCON, lenstr(cp1, w - c));
17710841Speter 				    putstr(cp1, w - c);
178775Speter #				endif OBJ
179775Speter #				ifdef PC
18010841Speter 				    putCONG( cp1 , w , LREQ );
181775Speter #				endif PC
182775Speter 				/*
183775Speter 				 * Define the string temporarily
184775Speter 				 * so later people can know its
185775Speter 				 * width.
186775Speter 				 * cleaned out by stat.
187775Speter 				 */
18814743Sthien 				q = defnl((char *) 0, STR, NLNIL, w);
189775Speter 				q->type = q;
190775Speter 				return (q);
191775Speter 			}
192775Speter 			if (q == nl+T1CHAR) {
193775Speter #			    ifdef OBJ
19414743Sthien 				(void) put(2, O_CONC4, (int)p->value[0]);
195775Speter #			    endif OBJ
196775Speter #			    ifdef PC
19718471Sralph 				putleaf(PCC_ICON, p -> value[0], 0, PCCT_INT,
19814743Sthien 						(char *) 0);
199775Speter #			    endif PC
200775Speter 			    return(q);
201775Speter 			}
202775Speter 			/*
203775Speter 			 * Every other kind of constant here
204775Speter 			 */
205775Speter #			ifdef OBJ
206775Speter 			    switch (width(q)) {
207775Speter 			    case 8:
208775Speter #ifndef DEBUG
20914743Sthien 				    (void) put(2, O_CON8, p->real);
210775Speter 				    return(q);
211775Speter #else
212775Speter 				    if (hp21mx) {
21314743Sthien 					    f.pdouble = p->real;
21414743Sthien 					    conv((int *) (&f.pdouble));
21514743Sthien 					    l = f.plong[1];
21614743Sthien 					    (void) put(2, O_CON4, l);
217775Speter 				    } else
21814743Sthien 					    (void) put(2, O_CON8, p->real);
219775Speter 				    return(q);
220775Speter #endif
221775Speter 			    case 4:
22214743Sthien 				    (void) put(2, O_CON4, p->range[0]);
223775Speter 				    return(q);
224775Speter 			    case 2:
22514743Sthien 				    (void) put(2, O_CON24, (short)p->range[0]);
226775Speter 				    return(q);
227775Speter 			    case 1:
22814743Sthien 				    (void) put(2, O_CON14, p->value[0]);
229775Speter 				    return(q);
230775Speter 			    default:
231775Speter 				    panic("stkrval");
232775Speter 			    }
233775Speter #			endif OBJ
234775Speter #			ifdef PC
23514743Sthien 			    q = rvalue( r , contype , (int) required );
23610360Smckusick 			    if (isa(q,"sbci")) {
23718471Sralph 				sconv(p2type(q),PCCT_INT);
23810360Smckusick 			    }
23910360Smckusick 			    return q;
240775Speter #			endif PC
241775Speter 
242775Speter 		case FUNC:
2431201Speter 		case FFUNC:
244775Speter 			/*
245775Speter 			 * Function call
246775Speter 			 */
24714743Sthien 			pt = r->var_node.qual;
24814743Sthien 			if (pt != TR_NIL) {
24914743Sthien 				switch (pt->list_node.list->tag) {
250775Speter 				case T_PTR:
251775Speter 				case T_ARGL:
252775Speter 				case T_ARY:
253775Speter 				case T_FIELD:
254775Speter 					error("Can't qualify a function result value");
25514743Sthien 					return (NLNIL);
256775Speter 				}
257775Speter 			}
258775Speter #			ifdef OBJ
259775Speter 			    q = p->type;
260775Speter 			    if (classify(q) == TSTR) {
261775Speter 				    c = width(q);
26230037Smckusick 				    (void) put(2, O_LVCON,
26330037Smckusick 					roundup(c+1, (long) A_SHORT));
264775Speter 				    putstr("", c);
26514743Sthien 				    (void) put(1, PTR_DUP);
266775Speter 				    p = funccod(r);
26714743Sthien 				    (void) put(2, O_AS, c);
268775Speter 				    return(p);
269775Speter 			    }
270775Speter 			    p = funccod(r);
271775Speter 			    if (width(p) <= 2)
27214743Sthien 				    (void) put(1, O_STOI);
273775Speter #			endif OBJ
274775Speter #			ifdef PC
275775Speter 			    p = pcfunccod( r );
27610360Smckusick 			    if (isa(p,"sbci")) {
27718471Sralph 				sconv(p2type(p),PCCT_INT);
27810360Smckusick 			    }
279775Speter #			endif PC
280775Speter 			return (p);
281775Speter 
282775Speter 		case TYPE:
283775Speter 			error("Type names (e.g. %s) allowed only in declarations", p->symbol);
28414743Sthien 			return (NLNIL);
285775Speter 
286775Speter 		case PROC:
2871201Speter 		case FPROC:
288775Speter 			error("Procedure %s found where expression required", p->symbol);
28914743Sthien 			return (NLNIL);
290775Speter 		default:
291775Speter 			panic("stkrvid");
292775Speter 		}
293775Speter 	case T_PLUS:
294775Speter 	case T_MINUS:
295775Speter 	case T_NOT:
296775Speter 	case T_AND:
297775Speter 	case T_OR:
298775Speter 	case T_DIVD:
299775Speter 	case T_MULT:
300775Speter 	case T_SUB:
301775Speter 	case T_ADD:
302775Speter 	case T_MOD:
303775Speter 	case T_DIV:
304775Speter 	case T_EQ:
305775Speter 	case T_NE:
306775Speter 	case T_GE:
307775Speter 	case T_LE:
308775Speter 	case T_GT:
309775Speter 	case T_LT:
310775Speter 	case T_IN:
31114743Sthien 		p = rvalue(r, contype , (int) required );
312775Speter #		ifdef OBJ
313775Speter 		    if (width(p) <= 2)
31414743Sthien 			    (void) put(1, O_STOI);
315775Speter #		endif OBJ
31610360Smckusick #		ifdef PC
31710360Smckusick 		    if (isa(p,"sbci")) {
31818471Sralph 			sconv(p2type(p),PCCT_INT);
31910360Smckusick 		    }
32010360Smckusick #		endif PC
321775Speter 		return (p);
322909Speter 	case T_CSET:
32314743Sthien 		p = rvalue(r, contype , (int) required );
324909Speter 		return (p);
325775Speter 	default:
32614743Sthien 		if (r->const_node.cptr == (char *) NIL)
32714743Sthien 			return (NLNIL);
32814743Sthien 		switch (r->tag) {
329775Speter 		default:
330775Speter 			panic("stkrval3");
331775Speter 
332775Speter 		/*
333775Speter 		 * An octal number
334775Speter 		 */
335775Speter 		case T_BINT:
33614743Sthien 			f.pdouble = a8tol(r->const_node.cptr);
337775Speter 			goto conint;
338775Speter 
339775Speter 		/*
340775Speter 		 * A decimal number
341775Speter 		 */
342775Speter 		case T_INT:
34314743Sthien 			f.pdouble = atof(r->const_node.cptr);
344775Speter conint:
34514743Sthien 			if (f.pdouble > MAXINT || f.pdouble < MININT) {
346775Speter 				error("Constant too large for this implementation");
34714743Sthien 				return (NLNIL);
348775Speter 			}
34914743Sthien 			l = f.pdouble;
350775Speter 			if (bytes(l, l) <= 2) {
351775Speter #			    ifdef OBJ
35214743Sthien 				(void) put(2, O_CON24, (short)l);
353775Speter #			    endif OBJ
354775Speter #			    ifdef PC
35518471Sralph 				putleaf( PCC_ICON , (short) l , 0 , PCCT_INT ,
35614743Sthien 						(char *) 0 );
357775Speter #			    endif PC
358775Speter 				return(nl+T4INT);
359775Speter 			}
360775Speter #			ifdef OBJ
36114743Sthien 			    (void) put(2, O_CON4, l);
362775Speter #			endif OBJ
363775Speter #			ifdef PC
36418471Sralph 			    putleaf( PCC_ICON , (int) l , 0 , PCCT_INT , (char *) 0 );
365775Speter #			endif PC
366775Speter 			return (nl+T4INT);
367775Speter 
368775Speter 		/*
369775Speter 		 * A floating point number
370775Speter 		 */
371775Speter 		case T_FINT:
372775Speter #		   	ifdef OBJ
37314743Sthien 			    (void) put(2, O_CON8, atof(r->const_node.cptr));
374775Speter #			endif OBJ
375775Speter #			ifdef PC
37614743Sthien 			    putCON8( atof( r->const_node.cptr ) );
377775Speter #			endif PC
378775Speter 			return (nl+TDOUBLE);
379775Speter 
380775Speter 		/*
381775Speter 		 * Constant strings.  Note that constant characters
382775Speter 		 * are constant strings of length one; there is
383775Speter 		 * no constant string of length one.
384775Speter 		 */
385775Speter 		case T_STRNG:
38614743Sthien 			cp = r->const_node.cptr;
387775Speter 			if (cp[1] == 0) {
388775Speter #				ifdef OBJ
38914743Sthien 				    (void) put(2, O_CONC4, cp[0]);
390775Speter #				endif OBJ
391775Speter #				ifdef PC
39218471Sralph 				    putleaf( PCC_ICON , cp[0] , 0 , PCCT_INT ,
39314743Sthien 						(char *) 0 );
394775Speter #				endif PC
395775Speter 				return(nl+T1CHAR);
396775Speter 			}
397775Speter 			goto cstrng;
398775Speter 		}
399775Speter 
400775Speter 	}
401775Speter }
40210568Smckusick 
40310568Smckusick #ifdef OBJ
40410568Smckusick /*
40510568Smckusick  * push a value onto the interpreter stack, longword aligned.
40610568Smckusick  */
40714743Sthien struct nl
stackRV(p)40814743Sthien *stackRV(p)
40910568Smckusick 	struct nl *p;
41010568Smckusick {
41110568Smckusick 	struct nl *q;
41210568Smckusick 	int w, bn;
41310568Smckusick 
41410568Smckusick 	q = p->type;
41514743Sthien 	if (q == NLNIL)
41614743Sthien 		return (NLNIL);
41710568Smckusick 	bn = BLOCKNO(p->nl_block);
41810568Smckusick 	w = width(q);
41910568Smckusick 	switch (w) {
42010568Smckusick 	case 8:
42114743Sthien 		(void) put(2, O_RV8 | bn << 8+INDX, (int)p->value[0]);
42210568Smckusick 		break;
42310568Smckusick 	case 4:
42414743Sthien 		(void) put(2, O_RV4 | bn << 8+INDX, (int)p->value[0]);
42510568Smckusick 		break;
42610568Smckusick 	case 2:
42714743Sthien 		(void) put(2, O_RV24 | bn << 8+INDX, (int)p->value[0]);
42810568Smckusick 		break;
42910568Smckusick 	case 1:
43014743Sthien 		(void) put(2, O_RV14 | bn << 8+INDX, (int)p->value[0]);
43110568Smckusick 		break;
43210568Smckusick 	default:
43314743Sthien 		(void) put(3, O_RV | bn << 8+INDX, (int)p->value[0], w);
43410568Smckusick 		break;
43510568Smckusick 	}
43610568Smckusick 	return (q);
43710568Smckusick }
43810568Smckusick #endif OBJ
439