xref: /original-bsd/usr.bin/pascal/pxp/rval.c (revision 6c57d260)
1 static	char *sccsid = "@(#)rval.c	1.1 (Berkeley) 03/02/81";
2 /* Copyright (c) 1979 Regents of the University of California */
3 #
4 /*
5  * pxp - Pascal execution profiler
6  *
7  * Bill Joy UCB
8  * Version 1.2 January 1979
9  */
10 
11 #include "0.h"
12 #include "tree.h"
13 
14 extern	char *opnames[];
15 
16 #define alph(c)		((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
17 /*
18  * Rvalue reformats an expression.
19  * Par is a flag indicating that the expression
20  * should be parenthesized if it is non-atomic.
21  */
22 rvalue(r, par)
23 	register int *r;
24 	int par;
25 {
26 	register int *al;
27 	register char *opname;
28 
29 	if (r == NIL) {
30 		ppid("{expr}");
31 		return;
32 	}
33 	if (r[0] <= T_IN)
34 		opname = opnames[r[0]];
35 	switch (r[0]) {
36 		case T_BINT:
37 		case T_INT:
38 		case T_FINT:
39 			ppnumb(r[2]);
40 			if (r[0] == T_BINT)
41 				ppsep("b");
42 			return;
43 		case T_NIL:
44 			ppkw("nil");
45 			return;
46 		case T_FCALL:
47 			funccod(r);
48 			return;
49 		case T_VAR:
50 			lvalue(r);
51 			return;
52 		case T_CSET:
53 			cset(r);
54 			return;
55 		case T_STRNG:
56 			ppstr(r[2]);
57 			return;
58 	}
59 	if (par)
60 		ppbra("(");
61 	switch (r[0]) {
62 		default:
63 			panic("rval");
64 		case T_PLUS:
65 		case T_MINUS:
66 			ppop(r[0] == T_PLUS ? "+" : "-");
67 			al = r[2];
68 			rvalue(r[2], prec(al) > prec(r) || full);
69 			break;
70 		case T_NOT:
71 			ppkw(opname);
72 			ppspac();
73 			rvalue(r[2], 1);
74 			break;
75 		case T_EQ:
76 		case T_NE:
77 		case T_GE:
78 		case T_LE:
79 		case T_GT:
80 		case T_LT:
81 			al = r[2];
82 			rvalue(al, prec(al) <= prec(r) || full);
83 			goto rest;
84 		case T_AND:
85 		case T_OR:
86 		case T_MULT:
87 		case T_ADD:
88 		case T_SUB:
89 		case T_DIVD:
90 		case T_MOD:
91 		case T_DIV:
92 		case T_IN:
93 			al = r[2];
94 			rvalue(al, prec(al) < prec(r) || full);
95 rest:
96 			ppspac();
97 			if (alph(opname[0]))
98 				ppkw(opname);
99 			else
100 				ppop(opname);
101 			ppspac();
102 			al = r[3];
103 			rvalue(al, prec(al) <= prec(r) || full);
104 			break;
105 	}
106 	if (par)
107 		ppket(")");
108 }
109 
110 /*
111  * Prec returns the precedence of an operator,
112  * with larger numbers indicating stronger binding.
113  * This is used to determine when parenthesization
114  * is needed on subexpressions.
115  */
116 prec(r)
117 	register int *r;
118 {
119 
120 	if (r == NIL)
121 		return;
122 	switch (r[0]) {
123 		case T_NOT:
124 			return (3);
125 		case T_MULT:
126 		case T_DIVD:
127 		case T_DIV:
128 		case T_MOD:
129 		case T_AND:
130 			return (2);
131 		case T_ADD:
132 		case T_SUB:
133 		case T_OR:
134 		case T_PLUS:
135 		case T_MINUS:
136 			return (1);
137 		default:
138 			return (0);
139 	}
140 }
141