xref: /csrg-svn/usr.bin/pascal/pxp/rval.c (revision 22238)
12864Speter /*
2*22238Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22238Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22238Sdist  * specifies the terms and conditions for redistribution.
5*22238Sdist  */
6*22238Sdist 
7*22238Sdist #ifndef lint
8*22238Sdist static char sccsid[] = "@(#)rval.c	5.1 (Berkeley) 06/05/85";
9*22238Sdist #endif not lint
10*22238Sdist 
11*22238Sdist /*
122864Speter  * pxp - Pascal execution profiler
132864Speter  *
142864Speter  * Bill Joy UCB
152864Speter  * Version 1.2 January 1979
162864Speter  */
172864Speter 
182864Speter #include "0.h"
192864Speter #include "tree.h"
202864Speter 
212864Speter extern	char *opnames[];
222864Speter 
232864Speter #define alph(c)		((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
242864Speter /*
252864Speter  * Rvalue reformats an expression.
262864Speter  * Par is a flag indicating that the expression
272864Speter  * should be parenthesized if it is non-atomic.
282864Speter  */
292864Speter rvalue(r, par)
302864Speter 	register int *r;
312864Speter 	int par;
322864Speter {
332864Speter 	register int *al;
342864Speter 	register char *opname;
352864Speter 
362864Speter 	if (r == NIL) {
372864Speter 		ppid("{expr}");
382864Speter 		return;
392864Speter 	}
402864Speter 	if (r[0] <= T_IN)
412864Speter 		opname = opnames[r[0]];
422864Speter 	switch (r[0]) {
432864Speter 		case T_BINT:
442864Speter 		case T_INT:
452864Speter 		case T_FINT:
462864Speter 			ppnumb(r[2]);
472864Speter 			if (r[0] == T_BINT)
482864Speter 				ppsep("b");
492864Speter 			return;
502864Speter 		case T_NIL:
512864Speter 			ppkw("nil");
522864Speter 			return;
532864Speter 		case T_FCALL:
542864Speter 			funccod(r);
552864Speter 			return;
562864Speter 		case T_VAR:
572864Speter 			lvalue(r);
582864Speter 			return;
592864Speter 		case T_CSET:
602864Speter 			cset(r);
612864Speter 			return;
622864Speter 		case T_STRNG:
632864Speter 			ppstr(r[2]);
642864Speter 			return;
652864Speter 	}
662864Speter 	if (par)
672864Speter 		ppbra("(");
682864Speter 	switch (r[0]) {
692864Speter 		default:
702864Speter 			panic("rval");
712864Speter 		case T_PLUS:
722864Speter 		case T_MINUS:
7316274Speter 			/*
7416274Speter 			 * if child is relational (bogus) or adding operator,
7516274Speter 			 * parenthesize child.
7616274Speter 			 * this has the unaesthetic property that
7716274Speter 			 * --i prints as -(-i), but is needed to catch
7816274Speter 			 * -(a+b) which must print as -(a+b), not as -a+b.
7916274Speter 			 * otherwise child has higher precedence
8016274Speter 			 * and need not be parenthesized.
8116274Speter 			 */
822864Speter 			ppop(r[0] == T_PLUS ? "+" : "-");
832864Speter 			al = r[2];
8416274Speter 			rvalue(r[2], prec(al) <= prec(r) || full);
852864Speter 			break;
862864Speter 		case T_NOT:
8716274Speter 			/*
8816274Speter 			 * if child is of lesser precedence
8916274Speter 			 * (i.e. not another not operator)
9016274Speter 			 * parenthesize it.
9116274Speter 			 * nested not operators need not be parenthesized
9216274Speter 			 * because it's a prefix operator.
9316274Speter 			 */
942864Speter 			ppkw(opname);
952864Speter 			ppspac();
9616274Speter 			al = r[2];
9716274Speter 			rvalue(r[2], prec(al) < prec(r) || full);
982864Speter 			break;
992864Speter 		case T_EQ:
1002864Speter 		case T_NE:
1012864Speter 		case T_GE:
1022864Speter 		case T_LE:
1032864Speter 		case T_GT:
1042864Speter 		case T_LT:
10516274Speter 			/*
10616274Speter 			 * make the aesthetic choice to
10716274Speter 			 * fully parenthesize relational expressions,
10816274Speter 			 * in spite of left to right associativity.
10916274Speter 			 * note: there are no operators with lower precedence.
11016274Speter 			 */
1112864Speter 			al = r[2];
1122864Speter 			rvalue(al, prec(al) <= prec(r) || full);
1132864Speter 			goto rest;
1142864Speter 		case T_AND:
1152864Speter 		case T_OR:
1162864Speter 		case T_MULT:
1172864Speter 		case T_ADD:
1182864Speter 		case T_SUB:
1192864Speter 		case T_DIVD:
1202864Speter 		case T_MOD:
1212864Speter 		case T_DIV:
1222864Speter 		case T_IN:
12316274Speter 			/*
12416274Speter 			 * need not parenthesize left child
12516274Speter 			 * if it has equal precedence,
12616274Speter 			 * due to left to right associativity.
12716274Speter 			 * right child needs to be parenthesized
12816274Speter 			 * if it has equal (or lesser) precedence.
12916274Speter 			 */
1302864Speter 			al = r[2];
1312864Speter 			rvalue(al, prec(al) < prec(r) || full);
1322864Speter rest:
1332864Speter 			ppspac();
1342864Speter 			if (alph(opname[0]))
1352864Speter 				ppkw(opname);
1362864Speter 			else
1372864Speter 				ppop(opname);
1382864Speter 			ppspac();
1392864Speter 			al = r[3];
1402864Speter 			rvalue(al, prec(al) <= prec(r) || full);
1412864Speter 			break;
1422864Speter 	}
1432864Speter 	if (par)
1442864Speter 		ppket(")");
1452864Speter }
1462864Speter 
1472864Speter /*
1482864Speter  * Prec returns the precedence of an operator,
1492864Speter  * with larger numbers indicating stronger binding.
1502864Speter  * This is used to determine when parenthesization
1512864Speter  * is needed on subexpressions.
1522864Speter  */
1532864Speter prec(r)
1542864Speter 	register int *r;
1552864Speter {
1562864Speter 
1572864Speter 	if (r == NIL)
1582864Speter 		return;
1592864Speter 	switch (r[0]) {
1602864Speter 		case T_NOT:
1612864Speter 			return (3);
1622864Speter 		case T_MULT:
1632864Speter 		case T_DIVD:
1642864Speter 		case T_DIV:
1652864Speter 		case T_MOD:
1662864Speter 		case T_AND:
1672864Speter 			return (2);
1682864Speter 		case T_ADD:
1692864Speter 		case T_SUB:
1702864Speter 		case T_OR:
1712864Speter 		case T_PLUS:
1722864Speter 		case T_MINUS:
1732864Speter 			return (1);
1742864Speter 		default:
1752864Speter 			return (0);
1762864Speter 	}
1772864Speter }
178