xref: /original-bsd/usr.bin/pascal/src/stkrval.c (revision 14bff7df)
1b85afe43Sbostic /*-
2*14bff7dfSbostic  * Copyright (c) 1980, 1993
3*14bff7dfSbostic  *	The Regents of the University of California.  All rights reserved.
4b85afe43Sbostic  *
5b85afe43Sbostic  * %sccs.include.redist.c%
6f0040ab9Sdist  */
714ea4644Speter 
821e3cc22Sthien #ifndef lint
9*14bff7dfSbostic static char sccsid[] = "@(#)stkrval.c	8.1 (Berkeley) 06/06/93";
10b85afe43Sbostic #endif /* not lint */
1114ea4644Speter 
1214ea4644Speter #include "whoami.h"
1314ea4644Speter #include "0.h"
1414ea4644Speter #include "tree.h"
1514ea4644Speter #include "opcode.h"
1614ea4644Speter #include "objfmt.h"
1771395e85Smckusick #include "align.h"
1814ea4644Speter #ifdef PC
19fdbf02bfSralph #   include <pcc.h>
2014ea4644Speter #endif PC
2121e3cc22Sthien #include "tree_ty.h"
2214ea4644Speter 
2314ea4644Speter /*
2414ea4644Speter  * stkrval Rvalue - an expression, and coerce it to be a stack quantity.
2514ea4644Speter  *
2614ea4644Speter  * Contype is the type that the caller would prefer, nand is important
2714ea4644Speter  * if constant sets or constant strings are involved, the latter
2814ea4644Speter  * because of string padding.
2914ea4644Speter  */
3014ea4644Speter /*
3114ea4644Speter  * for the obj version, this is a copy of rvalue hacked to use fancy new
3214ea4644Speter  * push-onto-stack-and-convert opcodes.
3314ea4644Speter  * for the pc version, i just call rvalue and convert if i have to,
3414ea4644Speter  * based on the return type of rvalue.
3514ea4644Speter  */
3614ea4644Speter struct nl *
stkrval(r,contype,required)3714ea4644Speter stkrval(r, contype , required )
3821e3cc22Sthien 	register struct tnode *r;
3914ea4644Speter 	struct nl *contype;
4014ea4644Speter 	long	required;
4114ea4644Speter {
4214ea4644Speter 	register struct nl *p;
4314ea4644Speter 	register struct nl *q;
4414ea4644Speter 	register char *cp, *cp1;
4514ea4644Speter 	register int c, w;
4621e3cc22Sthien 	struct tnode *pt;
4714ea4644Speter 	long l;
4821e3cc22Sthien 	union
4921e3cc22Sthien 	{
5021e3cc22Sthien 		double pdouble;
5121e3cc22Sthien 		long   plong[2];
5221e3cc22Sthien 	}f;
5314ea4644Speter 
5421e3cc22Sthien 	if (r == TR_NIL)
5521e3cc22Sthien 		return (NLNIL);
5614ea4644Speter 	if (nowexp(r))
5721e3cc22Sthien 		return (NLNIL);
5814ea4644Speter 	/*
5914ea4644Speter 	 * The root of the tree tells us what sort of expression we have.
6014ea4644Speter 	 */
6121e3cc22Sthien 	switch (r->tag) {
6214ea4644Speter 
6314ea4644Speter 	/*
6414ea4644Speter 	 * The constant nil
6514ea4644Speter 	 */
6614ea4644Speter 	case T_NIL:
6714ea4644Speter #		ifdef OBJ
6821e3cc22Sthien 		    (void) put(2, O_CON14, 0);
6914ea4644Speter #		endif OBJ
7014ea4644Speter #		ifdef PC
71fdbf02bfSralph 		    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
7214ea4644Speter #		endif PC
7314ea4644Speter 		return (nl+TNIL);
7414ea4644Speter 
7514ea4644Speter 	case T_FCALL:
7614ea4644Speter 	case T_VAR:
7721e3cc22Sthien 		p = lookup(r->var_node.cptr);
7821e3cc22Sthien 		if (p == NLNIL || p->class == BADUSE)
7921e3cc22Sthien 			return (NLNIL);
8014ea4644Speter 		switch (p->class) {
8114ea4644Speter 		case VAR:
8214ea4644Speter 			/*
836334a5ecSmckusic 			 * if a variable is
8414ea4644Speter 			 * qualified then get
8514ea4644Speter 			 * the rvalue by a
8614ea4644Speter 			 * stklval and an ind.
8714ea4644Speter 			 */
8821e3cc22Sthien 			if (r->var_node.qual != TR_NIL)
8914ea4644Speter 				goto ind;
9014ea4644Speter 			q = p->type;
9121e3cc22Sthien 			if (q == NLNIL)
9221e3cc22Sthien 				return (NLNIL);
9314ea4644Speter 			if (classify(q) == TSTR)
9414ea4644Speter 				return(stklval(r, NOFLAGS));
9514ea4644Speter #			ifdef OBJ
96a7017dacSmckusick 				return (stackRV(p));
9714ea4644Speter #			endif OBJ
9814ea4644Speter #			ifdef PC
9921e3cc22Sthien 			    q = rvalue( r , contype , (int) required );
100cf237f00Smckusick 			    if (isa(q, "sbci")) {
101fdbf02bfSralph 				sconv(p2type(q),PCCT_INT);
102cf237f00Smckusick 			    }
103cf237f00Smckusick 			    return q;
10414ea4644Speter #			endif PC
10514ea4644Speter 
10614ea4644Speter 		case WITHPTR:
10714ea4644Speter 		case REF:
10814ea4644Speter 			/*
10914ea4644Speter 			 * A stklval for these
11014ea4644Speter 			 * is actually what one
11114ea4644Speter 			 * might consider a rvalue.
11214ea4644Speter 			 */
11314ea4644Speter ind:
11414ea4644Speter 			q = stklval(r, NOFLAGS);
11521e3cc22Sthien 			if (q == NLNIL)
11621e3cc22Sthien 				return (NLNIL);
11714ea4644Speter 			if (classify(q) == TSTR)
11814ea4644Speter 				return(q);
11914ea4644Speter #			ifdef OBJ
12014ea4644Speter 			    w = width(q);
12114ea4644Speter 			    switch (w) {
12214ea4644Speter 				    case 8:
12321e3cc22Sthien 					    (void) put(1, O_IND8);
12414ea4644Speter 					    return(q);
12514ea4644Speter 				    case 4:
12621e3cc22Sthien 					    (void) put(1, O_IND4);
12714ea4644Speter 					    return(q);
12814ea4644Speter 				    case 2:
12921e3cc22Sthien 					    (void) put(1, O_IND24);
13014ea4644Speter 					    return(q);
13114ea4644Speter 				    case 1:
13221e3cc22Sthien 					    (void) put(1, O_IND14);
13314ea4644Speter 					    return(q);
13414ea4644Speter 				    default:
13521e3cc22Sthien 					    (void) put(2, O_IND, w);
13614ea4644Speter 					    return(q);
13714ea4644Speter 			    }
13814ea4644Speter #			endif OBJ
13914ea4644Speter #			ifdef PC
14014ea4644Speter 			    if ( required == RREQ ) {
141fdbf02bfSralph 				putop( PCCOM_UNARY PCC_MUL , p2type( q ) );
142cf237f00Smckusick 				if (isa(q,"sbci")) {
143fdbf02bfSralph 				    sconv(p2type(q),PCCT_INT);
144cf237f00Smckusick 				}
14514ea4644Speter 			    }
14614ea4644Speter 			    return q;
14714ea4644Speter #			endif PC
14814ea4644Speter 
14914ea4644Speter 		case CONST:
15021e3cc22Sthien 			if (r->var_node.qual != TR_NIL) {
15121e3cc22Sthien 				error("%s is a constant and cannot be qualified", r->var_node.cptr);
15221e3cc22Sthien 				return (NLNIL);
15314ea4644Speter 			}
15414ea4644Speter 			q = p->type;
15521e3cc22Sthien 			if (q == NLNIL)
15621e3cc22Sthien 				return (NLNIL);
15714ea4644Speter 			if (q == nl+TSTR) {
15814ea4644Speter 				/*
15914ea4644Speter 				 * Find the size of the string
16014ea4644Speter 				 * constant if needed.
16114ea4644Speter 				 */
16221e3cc22Sthien 				cp = (char *) p->ptr[0];
16314ea4644Speter cstrng:
16414ea4644Speter 				cp1 = cp;
16514ea4644Speter 				for (c = 0; *cp++; c++)
16614ea4644Speter 					continue;
167946687beSpeter 				w = c;
16814ea4644Speter 				if (contype != NIL && !opt('s')) {
16914ea4644Speter 					if (width(contype) < c && classify(contype) == TSTR) {
17014ea4644Speter 						error("Constant string too long");
17121e3cc22Sthien 						return (NLNIL);
17214ea4644Speter 					}
173946687beSpeter 					w = width(contype);
17414ea4644Speter 				}
17514ea4644Speter #				ifdef OBJ
17621e3cc22Sthien 				    (void) put(2, O_LVCON, lenstr(cp1, w - c));
177946687beSpeter 				    putstr(cp1, w - c);
17814ea4644Speter #				endif OBJ
17914ea4644Speter #				ifdef PC
180946687beSpeter 				    putCONG( cp1 , w , LREQ );
18114ea4644Speter #				endif PC
18214ea4644Speter 				/*
18314ea4644Speter 				 * Define the string temporarily
18414ea4644Speter 				 * so later people can know its
18514ea4644Speter 				 * width.
18614ea4644Speter 				 * cleaned out by stat.
18714ea4644Speter 				 */
18821e3cc22Sthien 				q = defnl((char *) 0, STR, NLNIL, w);
18914ea4644Speter 				q->type = q;
19014ea4644Speter 				return (q);
19114ea4644Speter 			}
19214ea4644Speter 			if (q == nl+T1CHAR) {
19314ea4644Speter #			    ifdef OBJ
19421e3cc22Sthien 				(void) put(2, O_CONC4, (int)p->value[0]);
19514ea4644Speter #			    endif OBJ
19614ea4644Speter #			    ifdef PC
197fdbf02bfSralph 				putleaf(PCC_ICON, p -> value[0], 0, PCCT_INT,
19821e3cc22Sthien 						(char *) 0);
19914ea4644Speter #			    endif PC
20014ea4644Speter 			    return(q);
20114ea4644Speter 			}
20214ea4644Speter 			/*
20314ea4644Speter 			 * Every other kind of constant here
20414ea4644Speter 			 */
20514ea4644Speter #			ifdef OBJ
20614ea4644Speter 			    switch (width(q)) {
20714ea4644Speter 			    case 8:
20814ea4644Speter #ifndef DEBUG
20921e3cc22Sthien 				    (void) put(2, O_CON8, p->real);
21014ea4644Speter 				    return(q);
21114ea4644Speter #else
21214ea4644Speter 				    if (hp21mx) {
21321e3cc22Sthien 					    f.pdouble = p->real;
21421e3cc22Sthien 					    conv((int *) (&f.pdouble));
21521e3cc22Sthien 					    l = f.plong[1];
21621e3cc22Sthien 					    (void) put(2, O_CON4, l);
21714ea4644Speter 				    } else
21821e3cc22Sthien 					    (void) put(2, O_CON8, p->real);
21914ea4644Speter 				    return(q);
22014ea4644Speter #endif
22114ea4644Speter 			    case 4:
22221e3cc22Sthien 				    (void) put(2, O_CON4, p->range[0]);
22314ea4644Speter 				    return(q);
22414ea4644Speter 			    case 2:
22521e3cc22Sthien 				    (void) put(2, O_CON24, (short)p->range[0]);
22614ea4644Speter 				    return(q);
22714ea4644Speter 			    case 1:
22821e3cc22Sthien 				    (void) put(2, O_CON14, p->value[0]);
22914ea4644Speter 				    return(q);
23014ea4644Speter 			    default:
23114ea4644Speter 				    panic("stkrval");
23214ea4644Speter 			    }
23314ea4644Speter #			endif OBJ
23414ea4644Speter #			ifdef PC
23521e3cc22Sthien 			    q = rvalue( r , contype , (int) required );
236cf237f00Smckusick 			    if (isa(q,"sbci")) {
237fdbf02bfSralph 				sconv(p2type(q),PCCT_INT);
238cf237f00Smckusick 			    }
239cf237f00Smckusick 			    return q;
24014ea4644Speter #			endif PC
24114ea4644Speter 
24214ea4644Speter 		case FUNC:
2435ff17cbdSpeter 		case FFUNC:
24414ea4644Speter 			/*
24514ea4644Speter 			 * Function call
24614ea4644Speter 			 */
24721e3cc22Sthien 			pt = r->var_node.qual;
24821e3cc22Sthien 			if (pt != TR_NIL) {
24921e3cc22Sthien 				switch (pt->list_node.list->tag) {
25014ea4644Speter 				case T_PTR:
25114ea4644Speter 				case T_ARGL:
25214ea4644Speter 				case T_ARY:
25314ea4644Speter 				case T_FIELD:
25414ea4644Speter 					error("Can't qualify a function result value");
25521e3cc22Sthien 					return (NLNIL);
25614ea4644Speter 				}
25714ea4644Speter 			}
25814ea4644Speter #			ifdef OBJ
25914ea4644Speter 			    q = p->type;
26014ea4644Speter 			    if (classify(q) == TSTR) {
26114ea4644Speter 				    c = width(q);
26271395e85Smckusick 				    (void) put(2, O_LVCON,
26371395e85Smckusick 					roundup(c+1, (long) A_SHORT));
26414ea4644Speter 				    putstr("", c);
26521e3cc22Sthien 				    (void) put(1, PTR_DUP);
26614ea4644Speter 				    p = funccod(r);
26721e3cc22Sthien 				    (void) put(2, O_AS, c);
26814ea4644Speter 				    return(p);
26914ea4644Speter 			    }
27014ea4644Speter 			    p = funccod(r);
27114ea4644Speter 			    if (width(p) <= 2)
27221e3cc22Sthien 				    (void) put(1, O_STOI);
27314ea4644Speter #			endif OBJ
27414ea4644Speter #			ifdef PC
27514ea4644Speter 			    p = pcfunccod( r );
276cf237f00Smckusick 			    if (isa(p,"sbci")) {
277fdbf02bfSralph 				sconv(p2type(p),PCCT_INT);
278cf237f00Smckusick 			    }
27914ea4644Speter #			endif PC
28014ea4644Speter 			return (p);
28114ea4644Speter 
28214ea4644Speter 		case TYPE:
28314ea4644Speter 			error("Type names (e.g. %s) allowed only in declarations", p->symbol);
28421e3cc22Sthien 			return (NLNIL);
28514ea4644Speter 
28614ea4644Speter 		case PROC:
2875ff17cbdSpeter 		case FPROC:
28814ea4644Speter 			error("Procedure %s found where expression required", p->symbol);
28921e3cc22Sthien 			return (NLNIL);
29014ea4644Speter 		default:
29114ea4644Speter 			panic("stkrvid");
29214ea4644Speter 		}
29314ea4644Speter 	case T_PLUS:
29414ea4644Speter 	case T_MINUS:
29514ea4644Speter 	case T_NOT:
29614ea4644Speter 	case T_AND:
29714ea4644Speter 	case T_OR:
29814ea4644Speter 	case T_DIVD:
29914ea4644Speter 	case T_MULT:
30014ea4644Speter 	case T_SUB:
30114ea4644Speter 	case T_ADD:
30214ea4644Speter 	case T_MOD:
30314ea4644Speter 	case T_DIV:
30414ea4644Speter 	case T_EQ:
30514ea4644Speter 	case T_NE:
30614ea4644Speter 	case T_GE:
30714ea4644Speter 	case T_LE:
30814ea4644Speter 	case T_GT:
30914ea4644Speter 	case T_LT:
31014ea4644Speter 	case T_IN:
31121e3cc22Sthien 		p = rvalue(r, contype , (int) required );
31214ea4644Speter #		ifdef OBJ
31314ea4644Speter 		    if (width(p) <= 2)
31421e3cc22Sthien 			    (void) put(1, O_STOI);
31514ea4644Speter #		endif OBJ
316cf237f00Smckusick #		ifdef PC
317cf237f00Smckusick 		    if (isa(p,"sbci")) {
318fdbf02bfSralph 			sconv(p2type(p),PCCT_INT);
319cf237f00Smckusick 		    }
320cf237f00Smckusick #		endif PC
32114ea4644Speter 		return (p);
32205640cc4Speter 	case T_CSET:
32321e3cc22Sthien 		p = rvalue(r, contype , (int) required );
32405640cc4Speter 		return (p);
32514ea4644Speter 	default:
32621e3cc22Sthien 		if (r->const_node.cptr == (char *) NIL)
32721e3cc22Sthien 			return (NLNIL);
32821e3cc22Sthien 		switch (r->tag) {
32914ea4644Speter 		default:
33014ea4644Speter 			panic("stkrval3");
33114ea4644Speter 
33214ea4644Speter 		/*
33314ea4644Speter 		 * An octal number
33414ea4644Speter 		 */
33514ea4644Speter 		case T_BINT:
33621e3cc22Sthien 			f.pdouble = a8tol(r->const_node.cptr);
33714ea4644Speter 			goto conint;
33814ea4644Speter 
33914ea4644Speter 		/*
34014ea4644Speter 		 * A decimal number
34114ea4644Speter 		 */
34214ea4644Speter 		case T_INT:
34321e3cc22Sthien 			f.pdouble = atof(r->const_node.cptr);
34414ea4644Speter conint:
34521e3cc22Sthien 			if (f.pdouble > MAXINT || f.pdouble < MININT) {
34614ea4644Speter 				error("Constant too large for this implementation");
34721e3cc22Sthien 				return (NLNIL);
34814ea4644Speter 			}
34921e3cc22Sthien 			l = f.pdouble;
35014ea4644Speter 			if (bytes(l, l) <= 2) {
35114ea4644Speter #			    ifdef OBJ
35221e3cc22Sthien 				(void) put(2, O_CON24, (short)l);
35314ea4644Speter #			    endif OBJ
35414ea4644Speter #			    ifdef PC
355fdbf02bfSralph 				putleaf( PCC_ICON , (short) l , 0 , PCCT_INT ,
35621e3cc22Sthien 						(char *) 0 );
35714ea4644Speter #			    endif PC
35814ea4644Speter 				return(nl+T4INT);
35914ea4644Speter 			}
36014ea4644Speter #			ifdef OBJ
36121e3cc22Sthien 			    (void) put(2, O_CON4, l);
36214ea4644Speter #			endif OBJ
36314ea4644Speter #			ifdef PC
364fdbf02bfSralph 			    putleaf( PCC_ICON , (int) l , 0 , PCCT_INT , (char *) 0 );
36514ea4644Speter #			endif PC
36614ea4644Speter 			return (nl+T4INT);
36714ea4644Speter 
36814ea4644Speter 		/*
36914ea4644Speter 		 * A floating point number
37014ea4644Speter 		 */
37114ea4644Speter 		case T_FINT:
37214ea4644Speter #		   	ifdef OBJ
37321e3cc22Sthien 			    (void) put(2, O_CON8, atof(r->const_node.cptr));
37414ea4644Speter #			endif OBJ
37514ea4644Speter #			ifdef PC
37621e3cc22Sthien 			    putCON8( atof( r->const_node.cptr ) );
37714ea4644Speter #			endif PC
37814ea4644Speter 			return (nl+TDOUBLE);
37914ea4644Speter 
38014ea4644Speter 		/*
38114ea4644Speter 		 * Constant strings.  Note that constant characters
38214ea4644Speter 		 * are constant strings of length one; there is
38314ea4644Speter 		 * no constant string of length one.
38414ea4644Speter 		 */
38514ea4644Speter 		case T_STRNG:
38621e3cc22Sthien 			cp = r->const_node.cptr;
38714ea4644Speter 			if (cp[1] == 0) {
38814ea4644Speter #				ifdef OBJ
38921e3cc22Sthien 				    (void) put(2, O_CONC4, cp[0]);
39014ea4644Speter #				endif OBJ
39114ea4644Speter #				ifdef PC
392fdbf02bfSralph 				    putleaf( PCC_ICON , cp[0] , 0 , PCCT_INT ,
39321e3cc22Sthien 						(char *) 0 );
39414ea4644Speter #				endif PC
39514ea4644Speter 				return(nl+T1CHAR);
39614ea4644Speter 			}
39714ea4644Speter 			goto cstrng;
39814ea4644Speter 		}
39914ea4644Speter 
40014ea4644Speter 	}
40114ea4644Speter }
402a7017dacSmckusick 
403a7017dacSmckusick #ifdef OBJ
404a7017dacSmckusick /*
405a7017dacSmckusick  * push a value onto the interpreter stack, longword aligned.
406a7017dacSmckusick  */
40721e3cc22Sthien struct nl
stackRV(p)40821e3cc22Sthien *stackRV(p)
409a7017dacSmckusick 	struct nl *p;
410a7017dacSmckusick {
411a7017dacSmckusick 	struct nl *q;
412a7017dacSmckusick 	int w, bn;
413a7017dacSmckusick 
414a7017dacSmckusick 	q = p->type;
41521e3cc22Sthien 	if (q == NLNIL)
41621e3cc22Sthien 		return (NLNIL);
417a7017dacSmckusick 	bn = BLOCKNO(p->nl_block);
418a7017dacSmckusick 	w = width(q);
419a7017dacSmckusick 	switch (w) {
420a7017dacSmckusick 	case 8:
42121e3cc22Sthien 		(void) put(2, O_RV8 | bn << 8+INDX, (int)p->value[0]);
422a7017dacSmckusick 		break;
423a7017dacSmckusick 	case 4:
42421e3cc22Sthien 		(void) put(2, O_RV4 | bn << 8+INDX, (int)p->value[0]);
425a7017dacSmckusick 		break;
426a7017dacSmckusick 	case 2:
42721e3cc22Sthien 		(void) put(2, O_RV24 | bn << 8+INDX, (int)p->value[0]);
428a7017dacSmckusick 		break;
429a7017dacSmckusick 	case 1:
43021e3cc22Sthien 		(void) put(2, O_RV14 | bn << 8+INDX, (int)p->value[0]);
431a7017dacSmckusick 		break;
432a7017dacSmckusick 	default:
43321e3cc22Sthien 		(void) put(3, O_RV | bn << 8+INDX, (int)p->value[0], w);
434a7017dacSmckusick 		break;
435a7017dacSmckusick 	}
436a7017dacSmckusick 	return (q);
437a7017dacSmckusick }
438a7017dacSmckusick #endif OBJ
439