xref: /csrg-svn/usr.bin/pascal/src/stkrval.c (revision 30037)
122194Sdist /*
222194Sdist  * Copyright (c) 1980 Regents of the University of California.
322194Sdist  * All rights reserved.  The Berkeley software License Agreement
422194Sdist  * specifies the terms and conditions for redistribution.
522194Sdist  */
6775Speter 
714743Sthien #ifndef lint
8*30037Smckusick static char sccsid[] = "@(#)stkrval.c	5.2 (Berkeley) 11/12/86";
922194Sdist #endif not lint
10775Speter 
11775Speter #include "whoami.h"
12775Speter #include "0.h"
13775Speter #include "tree.h"
14775Speter #include "opcode.h"
15775Speter #include "objfmt.h"
16*30037Smckusick #include "align.h"
17775Speter #ifdef PC
1818471Sralph #   include <pcc.h>
19775Speter #endif PC
2014743Sthien #include "tree_ty.h"
21775Speter 
22775Speter /*
23775Speter  * stkrval Rvalue - an expression, and coerce it to be a stack quantity.
24775Speter  *
25775Speter  * Contype is the type that the caller would prefer, nand is important
26775Speter  * if constant sets or constant strings are involved, the latter
27775Speter  * because of string padding.
28775Speter  */
29775Speter /*
30775Speter  * for the obj version, this is a copy of rvalue hacked to use fancy new
31775Speter  * push-onto-stack-and-convert opcodes.
32775Speter  * for the pc version, i just call rvalue and convert if i have to,
33775Speter  * based on the return type of rvalue.
34775Speter  */
35775Speter struct nl *
36775Speter stkrval(r, contype , required )
3714743Sthien 	register struct tnode *r;
38775Speter 	struct nl *contype;
39775Speter 	long	required;
40775Speter {
41775Speter 	register struct nl *p;
42775Speter 	register struct nl *q;
43775Speter 	register char *cp, *cp1;
44775Speter 	register int c, w;
4514743Sthien 	struct tnode *pt;
46775Speter 	long l;
4714743Sthien 	union
4814743Sthien 	{
4914743Sthien 		double pdouble;
5014743Sthien 		long   plong[2];
5114743Sthien 	}f;
52775Speter 
5314743Sthien 	if (r == TR_NIL)
5414743Sthien 		return (NLNIL);
55775Speter 	if (nowexp(r))
5614743Sthien 		return (NLNIL);
57775Speter 	/*
58775Speter 	 * The root of the tree tells us what sort of expression we have.
59775Speter 	 */
6014743Sthien 	switch (r->tag) {
61775Speter 
62775Speter 	/*
63775Speter 	 * The constant nil
64775Speter 	 */
65775Speter 	case T_NIL:
66775Speter #		ifdef OBJ
6714743Sthien 		    (void) put(2, O_CON14, 0);
68775Speter #		endif OBJ
69775Speter #		ifdef PC
7018471Sralph 		    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
71775Speter #		endif PC
72775Speter 		return (nl+TNIL);
73775Speter 
74775Speter 	case T_FCALL:
75775Speter 	case T_VAR:
7614743Sthien 		p = lookup(r->var_node.cptr);
7714743Sthien 		if (p == NLNIL || p->class == BADUSE)
7814743Sthien 			return (NLNIL);
79775Speter 		switch (p->class) {
80775Speter 		case VAR:
81775Speter 			/*
823080Smckusic 			 * if a variable is
83775Speter 			 * qualified then get
84775Speter 			 * the rvalue by a
85775Speter 			 * stklval and an ind.
86775Speter 			 */
8714743Sthien 			if (r->var_node.qual != TR_NIL)
88775Speter 				goto ind;
89775Speter 			q = p->type;
9014743Sthien 			if (q == NLNIL)
9114743Sthien 				return (NLNIL);
92775Speter 			if (classify(q) == TSTR)
93775Speter 				return(stklval(r, NOFLAGS));
94775Speter #			ifdef OBJ
9510568Smckusick 				return (stackRV(p));
96775Speter #			endif OBJ
97775Speter #			ifdef PC
9814743Sthien 			    q = rvalue( r , contype , (int) required );
9910360Smckusick 			    if (isa(q, "sbci")) {
10018471Sralph 				sconv(p2type(q),PCCT_INT);
10110360Smckusick 			    }
10210360Smckusick 			    return q;
103775Speter #			endif PC
104775Speter 
105775Speter 		case WITHPTR:
106775Speter 		case REF:
107775Speter 			/*
108775Speter 			 * A stklval for these
109775Speter 			 * is actually what one
110775Speter 			 * might consider a rvalue.
111775Speter 			 */
112775Speter ind:
113775Speter 			q = stklval(r, NOFLAGS);
11414743Sthien 			if (q == NLNIL)
11514743Sthien 				return (NLNIL);
116775Speter 			if (classify(q) == TSTR)
117775Speter 				return(q);
118775Speter #			ifdef OBJ
119775Speter 			    w = width(q);
120775Speter 			    switch (w) {
121775Speter 				    case 8:
12214743Sthien 					    (void) put(1, O_IND8);
123775Speter 					    return(q);
124775Speter 				    case 4:
12514743Sthien 					    (void) put(1, O_IND4);
126775Speter 					    return(q);
127775Speter 				    case 2:
12814743Sthien 					    (void) put(1, O_IND24);
129775Speter 					    return(q);
130775Speter 				    case 1:
13114743Sthien 					    (void) put(1, O_IND14);
132775Speter 					    return(q);
133775Speter 				    default:
13414743Sthien 					    (void) put(2, O_IND, w);
135775Speter 					    return(q);
136775Speter 			    }
137775Speter #			endif OBJ
138775Speter #			ifdef PC
139775Speter 			    if ( required == RREQ ) {
14018471Sralph 				putop( PCCOM_UNARY PCC_MUL , p2type( q ) );
14110360Smckusick 				if (isa(q,"sbci")) {
14218471Sralph 				    sconv(p2type(q),PCCT_INT);
14310360Smckusick 				}
144775Speter 			    }
145775Speter 			    return q;
146775Speter #			endif PC
147775Speter 
148775Speter 		case CONST:
14914743Sthien 			if (r->var_node.qual != TR_NIL) {
15014743Sthien 				error("%s is a constant and cannot be qualified", r->var_node.cptr);
15114743Sthien 				return (NLNIL);
152775Speter 			}
153775Speter 			q = p->type;
15414743Sthien 			if (q == NLNIL)
15514743Sthien 				return (NLNIL);
156775Speter 			if (q == nl+TSTR) {
157775Speter 				/*
158775Speter 				 * Find the size of the string
159775Speter 				 * constant if needed.
160775Speter 				 */
16114743Sthien 				cp = (char *) p->ptr[0];
162775Speter cstrng:
163775Speter 				cp1 = cp;
164775Speter 				for (c = 0; *cp++; c++)
165775Speter 					continue;
16610841Speter 				w = c;
167775Speter 				if (contype != NIL && !opt('s')) {
168775Speter 					if (width(contype) < c && classify(contype) == TSTR) {
169775Speter 						error("Constant string too long");
17014743Sthien 						return (NLNIL);
171775Speter 					}
17210841Speter 					w = width(contype);
173775Speter 				}
174775Speter #				ifdef OBJ
17514743Sthien 				    (void) put(2, O_LVCON, lenstr(cp1, w - c));
17610841Speter 				    putstr(cp1, w - c);
177775Speter #				endif OBJ
178775Speter #				ifdef PC
17910841Speter 				    putCONG( cp1 , w , LREQ );
180775Speter #				endif PC
181775Speter 				/*
182775Speter 				 * Define the string temporarily
183775Speter 				 * so later people can know its
184775Speter 				 * width.
185775Speter 				 * cleaned out by stat.
186775Speter 				 */
18714743Sthien 				q = defnl((char *) 0, STR, NLNIL, w);
188775Speter 				q->type = q;
189775Speter 				return (q);
190775Speter 			}
191775Speter 			if (q == nl+T1CHAR) {
192775Speter #			    ifdef OBJ
19314743Sthien 				(void) put(2, O_CONC4, (int)p->value[0]);
194775Speter #			    endif OBJ
195775Speter #			    ifdef PC
19618471Sralph 				putleaf(PCC_ICON, p -> value[0], 0, PCCT_INT,
19714743Sthien 						(char *) 0);
198775Speter #			    endif PC
199775Speter 			    return(q);
200775Speter 			}
201775Speter 			/*
202775Speter 			 * Every other kind of constant here
203775Speter 			 */
204775Speter #			ifdef OBJ
205775Speter 			    switch (width(q)) {
206775Speter 			    case 8:
207775Speter #ifndef DEBUG
20814743Sthien 				    (void) put(2, O_CON8, p->real);
209775Speter 				    return(q);
210775Speter #else
211775Speter 				    if (hp21mx) {
21214743Sthien 					    f.pdouble = p->real;
21314743Sthien 					    conv((int *) (&f.pdouble));
21414743Sthien 					    l = f.plong[1];
21514743Sthien 					    (void) put(2, O_CON4, l);
216775Speter 				    } else
21714743Sthien 					    (void) put(2, O_CON8, p->real);
218775Speter 				    return(q);
219775Speter #endif
220775Speter 			    case 4:
22114743Sthien 				    (void) put(2, O_CON4, p->range[0]);
222775Speter 				    return(q);
223775Speter 			    case 2:
22414743Sthien 				    (void) put(2, O_CON24, (short)p->range[0]);
225775Speter 				    return(q);
226775Speter 			    case 1:
22714743Sthien 				    (void) put(2, O_CON14, p->value[0]);
228775Speter 				    return(q);
229775Speter 			    default:
230775Speter 				    panic("stkrval");
231775Speter 			    }
232775Speter #			endif OBJ
233775Speter #			ifdef PC
23414743Sthien 			    q = rvalue( r , contype , (int) required );
23510360Smckusick 			    if (isa(q,"sbci")) {
23618471Sralph 				sconv(p2type(q),PCCT_INT);
23710360Smckusick 			    }
23810360Smckusick 			    return q;
239775Speter #			endif PC
240775Speter 
241775Speter 		case FUNC:
2421201Speter 		case FFUNC:
243775Speter 			/*
244775Speter 			 * Function call
245775Speter 			 */
24614743Sthien 			pt = r->var_node.qual;
24714743Sthien 			if (pt != TR_NIL) {
24814743Sthien 				switch (pt->list_node.list->tag) {
249775Speter 				case T_PTR:
250775Speter 				case T_ARGL:
251775Speter 				case T_ARY:
252775Speter 				case T_FIELD:
253775Speter 					error("Can't qualify a function result value");
25414743Sthien 					return (NLNIL);
255775Speter 				}
256775Speter 			}
257775Speter #			ifdef OBJ
258775Speter 			    q = p->type;
259775Speter 			    if (classify(q) == TSTR) {
260775Speter 				    c = width(q);
261*30037Smckusick 				    (void) put(2, O_LVCON,
262*30037Smckusick 					roundup(c+1, (long) A_SHORT));
263775Speter 				    putstr("", c);
26414743Sthien 				    (void) put(1, PTR_DUP);
265775Speter 				    p = funccod(r);
26614743Sthien 				    (void) put(2, O_AS, c);
267775Speter 				    return(p);
268775Speter 			    }
269775Speter 			    p = funccod(r);
270775Speter 			    if (width(p) <= 2)
27114743Sthien 				    (void) put(1, O_STOI);
272775Speter #			endif OBJ
273775Speter #			ifdef PC
274775Speter 			    p = pcfunccod( r );
27510360Smckusick 			    if (isa(p,"sbci")) {
27618471Sralph 				sconv(p2type(p),PCCT_INT);
27710360Smckusick 			    }
278775Speter #			endif PC
279775Speter 			return (p);
280775Speter 
281775Speter 		case TYPE:
282775Speter 			error("Type names (e.g. %s) allowed only in declarations", p->symbol);
28314743Sthien 			return (NLNIL);
284775Speter 
285775Speter 		case PROC:
2861201Speter 		case FPROC:
287775Speter 			error("Procedure %s found where expression required", p->symbol);
28814743Sthien 			return (NLNIL);
289775Speter 		default:
290775Speter 			panic("stkrvid");
291775Speter 		}
292775Speter 	case T_PLUS:
293775Speter 	case T_MINUS:
294775Speter 	case T_NOT:
295775Speter 	case T_AND:
296775Speter 	case T_OR:
297775Speter 	case T_DIVD:
298775Speter 	case T_MULT:
299775Speter 	case T_SUB:
300775Speter 	case T_ADD:
301775Speter 	case T_MOD:
302775Speter 	case T_DIV:
303775Speter 	case T_EQ:
304775Speter 	case T_NE:
305775Speter 	case T_GE:
306775Speter 	case T_LE:
307775Speter 	case T_GT:
308775Speter 	case T_LT:
309775Speter 	case T_IN:
31014743Sthien 		p = rvalue(r, contype , (int) required );
311775Speter #		ifdef OBJ
312775Speter 		    if (width(p) <= 2)
31314743Sthien 			    (void) put(1, O_STOI);
314775Speter #		endif OBJ
31510360Smckusick #		ifdef PC
31610360Smckusick 		    if (isa(p,"sbci")) {
31718471Sralph 			sconv(p2type(p),PCCT_INT);
31810360Smckusick 		    }
31910360Smckusick #		endif PC
320775Speter 		return (p);
321909Speter 	case T_CSET:
32214743Sthien 		p = rvalue(r, contype , (int) required );
323909Speter 		return (p);
324775Speter 	default:
32514743Sthien 		if (r->const_node.cptr == (char *) NIL)
32614743Sthien 			return (NLNIL);
32714743Sthien 		switch (r->tag) {
328775Speter 		default:
329775Speter 			panic("stkrval3");
330775Speter 
331775Speter 		/*
332775Speter 		 * An octal number
333775Speter 		 */
334775Speter 		case T_BINT:
33514743Sthien 			f.pdouble = a8tol(r->const_node.cptr);
336775Speter 			goto conint;
337775Speter 
338775Speter 		/*
339775Speter 		 * A decimal number
340775Speter 		 */
341775Speter 		case T_INT:
34214743Sthien 			f.pdouble = atof(r->const_node.cptr);
343775Speter conint:
34414743Sthien 			if (f.pdouble > MAXINT || f.pdouble < MININT) {
345775Speter 				error("Constant too large for this implementation");
34614743Sthien 				return (NLNIL);
347775Speter 			}
34814743Sthien 			l = f.pdouble;
349775Speter 			if (bytes(l, l) <= 2) {
350775Speter #			    ifdef OBJ
35114743Sthien 				(void) put(2, O_CON24, (short)l);
352775Speter #			    endif OBJ
353775Speter #			    ifdef PC
35418471Sralph 				putleaf( PCC_ICON , (short) l , 0 , PCCT_INT ,
35514743Sthien 						(char *) 0 );
356775Speter #			    endif PC
357775Speter 				return(nl+T4INT);
358775Speter 			}
359775Speter #			ifdef OBJ
36014743Sthien 			    (void) put(2, O_CON4, l);
361775Speter #			endif OBJ
362775Speter #			ifdef PC
36318471Sralph 			    putleaf( PCC_ICON , (int) l , 0 , PCCT_INT , (char *) 0 );
364775Speter #			endif PC
365775Speter 			return (nl+T4INT);
366775Speter 
367775Speter 		/*
368775Speter 		 * A floating point number
369775Speter 		 */
370775Speter 		case T_FINT:
371775Speter #		   	ifdef OBJ
37214743Sthien 			    (void) put(2, O_CON8, atof(r->const_node.cptr));
373775Speter #			endif OBJ
374775Speter #			ifdef PC
37514743Sthien 			    putCON8( atof( r->const_node.cptr ) );
376775Speter #			endif PC
377775Speter 			return (nl+TDOUBLE);
378775Speter 
379775Speter 		/*
380775Speter 		 * Constant strings.  Note that constant characters
381775Speter 		 * are constant strings of length one; there is
382775Speter 		 * no constant string of length one.
383775Speter 		 */
384775Speter 		case T_STRNG:
38514743Sthien 			cp = r->const_node.cptr;
386775Speter 			if (cp[1] == 0) {
387775Speter #				ifdef OBJ
38814743Sthien 				    (void) put(2, O_CONC4, cp[0]);
389775Speter #				endif OBJ
390775Speter #				ifdef PC
39118471Sralph 				    putleaf( PCC_ICON , cp[0] , 0 , PCCT_INT ,
39214743Sthien 						(char *) 0 );
393775Speter #				endif PC
394775Speter 				return(nl+T1CHAR);
395775Speter 			}
396775Speter 			goto cstrng;
397775Speter 		}
398775Speter 
399775Speter 	}
400775Speter }
40110568Smckusick 
40210568Smckusick #ifdef OBJ
40310568Smckusick /*
40410568Smckusick  * push a value onto the interpreter stack, longword aligned.
40510568Smckusick  */
40614743Sthien struct nl
40714743Sthien *stackRV(p)
40810568Smckusick 	struct nl *p;
40910568Smckusick {
41010568Smckusick 	struct nl *q;
41110568Smckusick 	int w, bn;
41210568Smckusick 
41310568Smckusick 	q = p->type;
41414743Sthien 	if (q == NLNIL)
41514743Sthien 		return (NLNIL);
41610568Smckusick 	bn = BLOCKNO(p->nl_block);
41710568Smckusick 	w = width(q);
41810568Smckusick 	switch (w) {
41910568Smckusick 	case 8:
42014743Sthien 		(void) put(2, O_RV8 | bn << 8+INDX, (int)p->value[0]);
42110568Smckusick 		break;
42210568Smckusick 	case 4:
42314743Sthien 		(void) put(2, O_RV4 | bn << 8+INDX, (int)p->value[0]);
42410568Smckusick 		break;
42510568Smckusick 	case 2:
42614743Sthien 		(void) put(2, O_RV24 | bn << 8+INDX, (int)p->value[0]);
42710568Smckusick 		break;
42810568Smckusick 	case 1:
42914743Sthien 		(void) put(2, O_RV14 | bn << 8+INDX, (int)p->value[0]);
43010568Smckusick 		break;
43110568Smckusick 	default:
43214743Sthien 		(void) put(3, O_RV | bn << 8+INDX, (int)p->value[0], w);
43310568Smckusick 		break;
43410568Smckusick 	}
43510568Smckusick 	return (q);
43610568Smckusick }
43710568Smckusick #endif OBJ
438