xref: /original-bsd/usr.bin/pascal/pxp/rval.c (revision aba77441)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)rval.c	5.1 (Berkeley) 06/05/85";
9 #endif not lint
10 
11 /*
12  * pxp - Pascal execution profiler
13  *
14  * Bill Joy UCB
15  * Version 1.2 January 1979
16  */
17 
18 #include "0.h"
19 #include "tree.h"
20 
21 extern	char *opnames[];
22 
23 #define alph(c)		((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
24 /*
25  * Rvalue reformats an expression.
26  * Par is a flag indicating that the expression
27  * should be parenthesized if it is non-atomic.
28  */
29 rvalue(r, par)
30 	register int *r;
31 	int par;
32 {
33 	register int *al;
34 	register char *opname;
35 
36 	if (r == NIL) {
37 		ppid("{expr}");
38 		return;
39 	}
40 	if (r[0] <= T_IN)
41 		opname = opnames[r[0]];
42 	switch (r[0]) {
43 		case T_BINT:
44 		case T_INT:
45 		case T_FINT:
46 			ppnumb(r[2]);
47 			if (r[0] == T_BINT)
48 				ppsep("b");
49 			return;
50 		case T_NIL:
51 			ppkw("nil");
52 			return;
53 		case T_FCALL:
54 			funccod(r);
55 			return;
56 		case T_VAR:
57 			lvalue(r);
58 			return;
59 		case T_CSET:
60 			cset(r);
61 			return;
62 		case T_STRNG:
63 			ppstr(r[2]);
64 			return;
65 	}
66 	if (par)
67 		ppbra("(");
68 	switch (r[0]) {
69 		default:
70 			panic("rval");
71 		case T_PLUS:
72 		case T_MINUS:
73 			/*
74 			 * if child is relational (bogus) or adding operator,
75 			 * parenthesize child.
76 			 * this has the unaesthetic property that
77 			 * --i prints as -(-i), but is needed to catch
78 			 * -(a+b) which must print as -(a+b), not as -a+b.
79 			 * otherwise child has higher precedence
80 			 * and need not be parenthesized.
81 			 */
82 			ppop(r[0] == T_PLUS ? "+" : "-");
83 			al = r[2];
84 			rvalue(r[2], prec(al) <= prec(r) || full);
85 			break;
86 		case T_NOT:
87 			/*
88 			 * if child is of lesser precedence
89 			 * (i.e. not another not operator)
90 			 * parenthesize it.
91 			 * nested not operators need not be parenthesized
92 			 * because it's a prefix operator.
93 			 */
94 			ppkw(opname);
95 			ppspac();
96 			al = r[2];
97 			rvalue(r[2], prec(al) < prec(r) || full);
98 			break;
99 		case T_EQ:
100 		case T_NE:
101 		case T_GE:
102 		case T_LE:
103 		case T_GT:
104 		case T_LT:
105 			/*
106 			 * make the aesthetic choice to
107 			 * fully parenthesize relational expressions,
108 			 * in spite of left to right associativity.
109 			 * note: there are no operators with lower precedence.
110 			 */
111 			al = r[2];
112 			rvalue(al, prec(al) <= prec(r) || full);
113 			goto rest;
114 		case T_AND:
115 		case T_OR:
116 		case T_MULT:
117 		case T_ADD:
118 		case T_SUB:
119 		case T_DIVD:
120 		case T_MOD:
121 		case T_DIV:
122 		case T_IN:
123 			/*
124 			 * need not parenthesize left child
125 			 * if it has equal precedence,
126 			 * due to left to right associativity.
127 			 * right child needs to be parenthesized
128 			 * if it has equal (or lesser) precedence.
129 			 */
130 			al = r[2];
131 			rvalue(al, prec(al) < prec(r) || full);
132 rest:
133 			ppspac();
134 			if (alph(opname[0]))
135 				ppkw(opname);
136 			else
137 				ppop(opname);
138 			ppspac();
139 			al = r[3];
140 			rvalue(al, prec(al) <= prec(r) || full);
141 			break;
142 	}
143 	if (par)
144 		ppket(")");
145 }
146 
147 /*
148  * Prec returns the precedence of an operator,
149  * with larger numbers indicating stronger binding.
150  * This is used to determine when parenthesization
151  * is needed on subexpressions.
152  */
153 prec(r)
154 	register int *r;
155 {
156 
157 	if (r == NIL)
158 		return;
159 	switch (r[0]) {
160 		case T_NOT:
161 			return (3);
162 		case T_MULT:
163 		case T_DIVD:
164 		case T_DIV:
165 		case T_MOD:
166 		case T_AND:
167 			return (2);
168 		case T_ADD:
169 		case T_SUB:
170 		case T_OR:
171 		case T_PLUS:
172 		case T_MINUS:
173 			return (1);
174 		default:
175 			return (0);
176 	}
177 }
178