xref: /csrg-svn/usr.bin/pascal/src/stkrval.c (revision 10360)
1775Speter /* Copyright (c) 1979 Regents of the University of California */
2775Speter 
3*10360Smckusick static char sccsid[] = "@(#)stkrval.c 1.5 01/17/83";
4775Speter 
5775Speter #include "whoami.h"
6775Speter #include "0.h"
7775Speter #include "tree.h"
8775Speter #include "opcode.h"
9775Speter #include "objfmt.h"
10775Speter #ifdef PC
11775Speter #   include "pcops.h"
12775Speter #endif PC
13775Speter 
14775Speter /*
15775Speter  * stkrval Rvalue - an expression, and coerce it to be a stack quantity.
16775Speter  *
17775Speter  * Contype is the type that the caller would prefer, nand is important
18775Speter  * if constant sets or constant strings are involved, the latter
19775Speter  * because of string padding.
20775Speter  */
21775Speter /*
22775Speter  * for the obj version, this is a copy of rvalue hacked to use fancy new
23775Speter  * push-onto-stack-and-convert opcodes.
24775Speter  * for the pc version, i just call rvalue and convert if i have to,
25775Speter  * based on the return type of rvalue.
26775Speter  */
27775Speter struct nl *
28775Speter stkrval(r, contype , required )
29775Speter 	register int *r;
30775Speter 	struct nl *contype;
31775Speter 	long	required;
32775Speter {
33775Speter 	register struct nl *p;
34775Speter 	register struct nl *q;
35775Speter 	register char *cp, *cp1;
36775Speter 	register int c, w;
37775Speter 	int **pt;
38775Speter 	long l;
39775Speter 	double f;
40775Speter 
41775Speter 	if (r == NIL)
42775Speter 		return (NIL);
43775Speter 	if (nowexp(r))
44775Speter 		return (NIL);
45775Speter 	/*
46775Speter 	 * The root of the tree tells us what sort of expression we have.
47775Speter 	 */
48775Speter 	switch (r[0]) {
49775Speter 
50775Speter 	/*
51775Speter 	 * The constant nil
52775Speter 	 */
53775Speter 	case T_NIL:
54775Speter #		ifdef OBJ
55775Speter 		    put(2, O_CON14, 0);
56775Speter #		endif OBJ
57775Speter #		ifdef PC
58775Speter 		    putleaf( P2ICON , 0 , 0 , P2INT , 0 );
59775Speter #		endif PC
60775Speter 		return (nl+TNIL);
61775Speter 
62775Speter 	case T_FCALL:
63775Speter 	case T_VAR:
64775Speter 		p = lookup(r[2]);
65775Speter 		if (p == NIL || p->class == BADUSE)
66775Speter 			return (NIL);
67775Speter 		switch (p->class) {
68775Speter 		case VAR:
69775Speter 			/*
703080Smckusic 			 * if a variable is
71775Speter 			 * qualified then get
72775Speter 			 * the rvalue by a
73775Speter 			 * stklval and an ind.
74775Speter 			 */
75775Speter 			if (r[3] != NIL)
76775Speter 				goto ind;
77775Speter 			q = p->type;
78775Speter 			if (q == NIL)
79775Speter 				return (NIL);
80775Speter 			if (classify(q) == TSTR)
81775Speter 				return(stklval(r, NOFLAGS));
82775Speter #			ifdef OBJ
83775Speter 			    w = width(q);
84775Speter 			    switch (w) {
85775Speter 			    case 8:
863080Smckusic 				    put(2, O_RV8 | bn << 8+INDX,
873080Smckusic 					(int)p->value[0]);
88775Speter 				    return(q);
89775Speter 			    case 4:
903080Smckusic 				    put(2, O_RV4 | bn << 8+INDX,
913080Smckusic 					(int)p->value[0]);
92775Speter 				    return(q);
93775Speter 			    case 2:
943080Smckusic 				    put(2, O_RV24 | bn << 8+INDX,
953080Smckusic 					(int)p->value[0]);
96775Speter 				    return(q);
97775Speter 			    case 1:
983080Smckusic 				    put(2, O_RV14 | bn << 8+INDX,
993080Smckusic 					(int)p->value[0]);
100775Speter 				    return(q);
101775Speter 			    default:
1023080Smckusic 				    put(3, O_RV | bn << 8+INDX,
1033080Smckusic 					(int)p->value[0], w);
104775Speter 				    return(q);
105775Speter 			     }
106775Speter #			endif OBJ
107775Speter #			ifdef PC
108*10360Smckusick 			    q = rvalue( r , contype , required );
109*10360Smckusick 			    if (isa(q, "sbci")) {
110*10360Smckusick 				sconv(p2type(q),P2INT);
111*10360Smckusick 			    }
112*10360Smckusick 			    return q;
113775Speter #			endif PC
114775Speter 
115775Speter 		case WITHPTR:
116775Speter 		case REF:
117775Speter 			/*
118775Speter 			 * A stklval for these
119775Speter 			 * is actually what one
120775Speter 			 * might consider a rvalue.
121775Speter 			 */
122775Speter ind:
123775Speter 			q = stklval(r, NOFLAGS);
124775Speter 			if (q == NIL)
125775Speter 				return (NIL);
126775Speter 			if (classify(q) == TSTR)
127775Speter 				return(q);
128775Speter #			ifdef OBJ
129775Speter 			    w = width(q);
130775Speter 			    switch (w) {
131775Speter 				    case 8:
132775Speter 					    put(1, O_IND8);
133775Speter 					    return(q);
134775Speter 				    case 4:
135775Speter 					    put(1, O_IND4);
136775Speter 					    return(q);
137775Speter 				    case 2:
138775Speter 					    put(1, O_IND24);
139775Speter 					    return(q);
140775Speter 				    case 1:
141775Speter 					    put(1, O_IND14);
142775Speter 					    return(q);
143775Speter 				    default:
144775Speter 					    put(2, O_IND, w);
145775Speter 					    return(q);
146775Speter 			    }
147775Speter #			endif OBJ
148775Speter #			ifdef PC
149775Speter 			    if ( required == RREQ ) {
150775Speter 				putop( P2UNARY P2MUL , p2type( q ) );
151*10360Smckusick 				if (isa(q,"sbci")) {
152*10360Smckusick 				    sconv(p2type(q),P2INT);
153*10360Smckusick 				}
154775Speter 			    }
155775Speter 			    return q;
156775Speter #			endif PC
157775Speter 
158775Speter 		case CONST:
159775Speter 			if (r[3] != NIL) {
160775Speter 				error("%s is a constant and cannot be qualified", r[2]);
161775Speter 				return (NIL);
162775Speter 			}
163775Speter 			q = p->type;
164775Speter 			if (q == NIL)
165775Speter 				return (NIL);
166775Speter 			if (q == nl+TSTR) {
167775Speter 				/*
168775Speter 				 * Find the size of the string
169775Speter 				 * constant if needed.
170775Speter 				 */
171775Speter 				cp = p->ptr[0];
172775Speter cstrng:
173775Speter 				cp1 = cp;
174775Speter 				for (c = 0; *cp++; c++)
175775Speter 					continue;
176775Speter 				w = 0;
177775Speter 				if (contype != NIL && !opt('s')) {
178775Speter 					if (width(contype) < c && classify(contype) == TSTR) {
179775Speter 						error("Constant string too long");
180775Speter 						return (NIL);
181775Speter 					}
182775Speter 					w = width(contype) - c;
183775Speter 				}
184775Speter #				ifdef OBJ
185775Speter 				    put(2, O_LVCON, lenstr(cp1, w));
186775Speter 				    putstr(cp1, w);
187775Speter #				endif OBJ
188775Speter #				ifdef PC
189775Speter 				    putCONG( cp1 , c + w , LREQ );
190775Speter #				endif PC
191775Speter 				/*
192775Speter 				 * Define the string temporarily
193775Speter 				 * so later people can know its
194775Speter 				 * width.
195775Speter 				 * cleaned out by stat.
196775Speter 				 */
197775Speter 				q = defnl(0, STR, 0, c);
198775Speter 				q->type = q;
199775Speter 				return (q);
200775Speter 			}
201775Speter 			if (q == nl+T1CHAR) {
202775Speter #			    ifdef OBJ
2033080Smckusic 				put(2, O_CONC4, (int)p->value[0]);
204775Speter #			    endif OBJ
205775Speter #			    ifdef PC
206*10360Smckusick 				putleaf(P2ICON, p -> value[0], 0, P2INT, 0);
207775Speter #			    endif PC
208775Speter 			    return(q);
209775Speter 			}
210775Speter 			/*
211775Speter 			 * Every other kind of constant here
212775Speter 			 */
213775Speter #			ifdef OBJ
214775Speter 			    switch (width(q)) {
215775Speter 			    case 8:
216775Speter #ifndef DEBUG
217775Speter 				    put(2, O_CON8, p->real);
218775Speter 				    return(q);
219775Speter #else
220775Speter 				    if (hp21mx) {
221775Speter 					    f = p->real;
222775Speter 					    conv(&f);
223775Speter 					    l = f.plong;
224775Speter 					    put(2, O_CON4, l);
225775Speter 				    } else
226775Speter 					    put(2, O_CON8, p->real);
227775Speter 				    return(q);
228775Speter #endif
229775Speter 			    case 4:
230775Speter 				    put(2, O_CON4, p->range[0]);
231775Speter 				    return(q);
232775Speter 			    case 2:
233775Speter 				    put(2, O_CON24, (short)p->range[0]);
234775Speter 				    return(q);
235775Speter 			    case 1:
2363080Smckusic 				    put(2, O_CON14, p->value[0]);
237775Speter 				    return(q);
238775Speter 			    default:
239775Speter 				    panic("stkrval");
240775Speter 			    }
241775Speter #			endif OBJ
242775Speter #			ifdef PC
243*10360Smckusick 			    q = rvalue( r , contype , required );
244*10360Smckusick 			    if (isa(q,"sbci")) {
245*10360Smckusick 				sconv(p2type(q),P2INT);
246*10360Smckusick 			    }
247*10360Smckusick 			    return q;
248775Speter #			endif PC
249775Speter 
250775Speter 		case FUNC:
2511201Speter 		case FFUNC:
252775Speter 			/*
253775Speter 			 * Function call
254775Speter 			 */
255775Speter 			pt = (int **)r[3];
256775Speter 			if (pt != NIL) {
257775Speter 				switch (pt[1][0]) {
258775Speter 				case T_PTR:
259775Speter 				case T_ARGL:
260775Speter 				case T_ARY:
261775Speter 				case T_FIELD:
262775Speter 					error("Can't qualify a function result value");
263775Speter 					return (NIL);
264775Speter 				}
265775Speter 			}
266775Speter #			ifdef OBJ
267775Speter 			    q = p->type;
268775Speter 			    if (classify(q) == TSTR) {
269775Speter 				    c = width(q);
270775Speter 				    put(2, O_LVCON, even(c+1));
271775Speter 				    putstr("", c);
2723080Smckusic 				    put(1, PTR_DUP);
273775Speter 				    p = funccod(r);
274775Speter 				    put(2, O_AS, c);
275775Speter 				    return(p);
276775Speter 			    }
277775Speter 			    p = funccod(r);
278775Speter 			    if (width(p) <= 2)
279775Speter 				    put(1, O_STOI);
280775Speter #			endif OBJ
281775Speter #			ifdef PC
282775Speter 			    p = pcfunccod( r );
283*10360Smckusick 			    if (isa(p,"sbci")) {
284*10360Smckusick 				sconv(p2type(p),P2INT);
285*10360Smckusick 			    }
286775Speter #			endif PC
287775Speter 			return (p);
288775Speter 
289775Speter 		case TYPE:
290775Speter 			error("Type names (e.g. %s) allowed only in declarations", p->symbol);
291775Speter 			return (NIL);
292775Speter 
293775Speter 		case PROC:
2941201Speter 		case FPROC:
295775Speter 			error("Procedure %s found where expression required", p->symbol);
296775Speter 			return (NIL);
297775Speter 		default:
298775Speter 			panic("stkrvid");
299775Speter 		}
300775Speter 	case T_PLUS:
301775Speter 	case T_MINUS:
302775Speter 	case T_NOT:
303775Speter 	case T_AND:
304775Speter 	case T_OR:
305775Speter 	case T_DIVD:
306775Speter 	case T_MULT:
307775Speter 	case T_SUB:
308775Speter 	case T_ADD:
309775Speter 	case T_MOD:
310775Speter 	case T_DIV:
311775Speter 	case T_EQ:
312775Speter 	case T_NE:
313775Speter 	case T_GE:
314775Speter 	case T_LE:
315775Speter 	case T_GT:
316775Speter 	case T_LT:
317775Speter 	case T_IN:
318775Speter 		p = rvalue(r, contype , required );
319775Speter #		ifdef OBJ
320775Speter 		    if (width(p) <= 2)
321775Speter 			    put(1, O_STOI);
322775Speter #		endif OBJ
323*10360Smckusick #		ifdef PC
324*10360Smckusick 		    if (isa(p,"sbci")) {
325*10360Smckusick 			sconv(p2type(p),P2INT);
326*10360Smckusick 		    }
327*10360Smckusick #		endif PC
328775Speter 		return (p);
329909Speter 	case T_CSET:
330909Speter 		p = rvalue(r, contype , required );
331909Speter 		return (p);
332775Speter 	default:
333775Speter 		if (r[2] == NIL)
334775Speter 			return (NIL);
335775Speter 		switch (r[0]) {
336775Speter 		default:
337775Speter 			panic("stkrval3");
338775Speter 
339775Speter 		/*
340775Speter 		 * An octal number
341775Speter 		 */
342775Speter 		case T_BINT:
343775Speter 			f = a8tol(r[2]);
344775Speter 			goto conint;
345775Speter 
346775Speter 		/*
347775Speter 		 * A decimal number
348775Speter 		 */
349775Speter 		case T_INT:
350775Speter 			f = atof(r[2]);
351775Speter conint:
352775Speter 			if (f > MAXINT || f < MININT) {
353775Speter 				error("Constant too large for this implementation");
354775Speter 				return (NIL);
355775Speter 			}
356775Speter 			l = f;
357775Speter 			if (bytes(l, l) <= 2) {
358775Speter #			    ifdef OBJ
359775Speter 				put(2, O_CON24, (short)l);
360775Speter #			    endif OBJ
361775Speter #			    ifdef PC
362775Speter 				putleaf( P2ICON , (short) l , 0 , P2INT , 0 );
363775Speter #			    endif PC
364775Speter 				return(nl+T4INT);
365775Speter 			}
366775Speter #			ifdef OBJ
367775Speter 			    put(2, O_CON4, l);
368775Speter #			endif OBJ
369775Speter #			ifdef PC
370775Speter 			    putleaf( P2ICON , l , 0 , P2INT , 0 );
371775Speter #			endif PC
372775Speter 			return (nl+T4INT);
373775Speter 
374775Speter 		/*
375775Speter 		 * A floating point number
376775Speter 		 */
377775Speter 		case T_FINT:
378775Speter #		   	ifdef OBJ
379775Speter 			    put(2, O_CON8, atof(r[2]));
380775Speter #			endif OBJ
381775Speter #			ifdef PC
382775Speter 			    putCON8( atof( r[2] ) );
383775Speter #			endif PC
384775Speter 			return (nl+TDOUBLE);
385775Speter 
386775Speter 		/*
387775Speter 		 * Constant strings.  Note that constant characters
388775Speter 		 * are constant strings of length one; there is
389775Speter 		 * no constant string of length one.
390775Speter 		 */
391775Speter 		case T_STRNG:
392775Speter 			cp = r[2];
393775Speter 			if (cp[1] == 0) {
394775Speter #				ifdef OBJ
395775Speter 				    put(2, O_CONC4, cp[0]);
396775Speter #				endif OBJ
397775Speter #				ifdef PC
398*10360Smckusick 				    putleaf( P2ICON , cp[0] , 0 , P2INT , 0 );
399775Speter #				endif PC
400775Speter 				return(nl+T1CHAR);
401775Speter 			}
402775Speter 			goto cstrng;
403775Speter 		}
404775Speter 
405775Speter 	}
406775Speter }
407