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