1 /*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Edward Wang at The University of California, Berkeley.
7 *
8 * %sccs.include.redist.c%
9 */
10
11 #ifndef lint
12 static char sccsid[] = "@(#)parser4.c 8.1 (Berkeley) 06/06/93";
13 #endif /* not lint */
14
15 #include "parser.h"
16
17 /*
18 * | 3
19 * ^ 4
20 * & 5
21 * == != 6
22 * < <= > >= 7
23 * << >> 8
24 * + - 9
25 * * / % 10
26 */
p_expr3_10(level,v,flag)27 p_expr3_10(level, v, flag)
28 register struct value *v;
29 char flag;
30 {
31 struct value l, r;
32 int op;
33 char *opname;
34
35 if ((level == 10 ? p_expr11(v, flag)
36 : p_expr3_10(level + 1, v, flag)) < 0)
37 return -1;
38 for (;;) {
39 switch (level) {
40 case 3:
41 if (token != T_OR)
42 return 0;
43 opname = "|";
44 break;
45 case 4:
46 if (token != T_XOR)
47 return 0;
48 opname = "^";
49 break;
50 case 5:
51 if (token != T_AND)
52 return 0;
53 opname = "&";
54 break;
55 case 6:
56 if (token == T_EQ)
57 opname = "==";
58 else if (token == T_NE)
59 opname = "!=";
60 else
61 return 0;
62 break;
63 case 7:
64 switch (token) {
65 case T_LT:
66 opname = "<";
67 break;
68 case T_LE:
69 opname = "<=";
70 break;
71 case T_GT:
72 opname = ">";
73 break;
74 case T_GE:
75 opname = ">=";
76 break;
77 default:
78 return 0;
79 }
80 break;
81 case 8:
82 if (token == T_LS)
83 opname = "<<";
84 else if (token == T_RS)
85 opname = ">>";
86 else
87 return 0;
88 break;
89 case 9:
90 if (token == T_PLUS)
91 opname = "+";
92 else if (token == T_MINUS)
93 opname = "-";
94 else
95 return 0;
96 break;
97 case 10:
98 switch (token) {
99 case T_MUL:
100 opname = "*";
101 break;
102 case T_DIV:
103 opname = "/";
104 break;
105 case T_MOD:
106 opname = "%";
107 break;
108 default:
109 return 0;
110 }
111 break;
112 }
113 l = *v;
114 if (l.v_type == V_ERR)
115 flag = 0;
116
117 op = token;
118 (void) s_gettok();
119 if ((level == 10 ? p_expr11(&r, flag)
120 : p_expr3_10(level + 1, &r, flag)) < 0) {
121 p_synerror();
122 val_free(l);
123 return -1;
124 }
125
126 if (r.v_type == V_ERR)
127 flag = 0;
128 else switch (op) {
129 case T_EQ:
130 case T_NE:
131 case T_LT:
132 case T_LE:
133 case T_GT:
134 case T_GE:
135 case T_PLUS:
136 if (l.v_type == V_STR) {
137 if (r.v_type == V_NUM)
138 if (p_convstr(&r) < 0)
139 flag = 0;
140 } else
141 if (r.v_type == V_STR)
142 if (p_convstr(&l) < 0)
143 flag = 0;
144 break;
145 case T_LS:
146 case T_RS:
147 if (r.v_type == V_STR) {
148 char *p = r.v_str;
149 r.v_type = V_NUM;
150 r.v_num = strlen(p);
151 str_free(p);
152 }
153 break;
154 case T_OR:
155 case T_XOR:
156 case T_AND:
157 case T_MINUS:
158 case T_MUL:
159 case T_DIV:
160 case T_MOD:
161 default:
162 if (l.v_type == V_STR || r.v_type == V_STR) {
163 p_error("%s: Numeric operands required.",
164 opname);
165 flag = 0;
166 }
167 }
168 if (!flag) {
169 val_free(l);
170 val_free(r);
171 v->v_type = V_ERR;
172 if (p_abort())
173 return -1;
174 continue;
175 }
176
177 v->v_type = V_NUM;
178 switch (op) {
179 case T_EQ:
180 case T_NE:
181 case T_LT:
182 case T_LE:
183 case T_GT:
184 case T_GE:
185 if (l.v_type == V_STR) {
186 int tmp = strcmp(l.v_str, r.v_str);
187 str_free(l.v_str);
188 str_free(r.v_str);
189 l.v_type = V_NUM;
190 l.v_num = tmp;
191 r.v_type = V_NUM;
192 r.v_num = 0;
193 }
194 break;
195 }
196 switch (op) {
197 case T_OR:
198 v->v_num = l.v_num | r.v_num;
199 break;
200 case T_XOR:
201 v->v_num = l.v_num ^ r.v_num;
202 break;
203 case T_AND:
204 v->v_num = l.v_num & r.v_num;
205 break;
206 case T_EQ:
207 v->v_num = l.v_num == r.v_num;
208 break;
209 case T_NE:
210 v->v_num = l.v_num != r.v_num;
211 break;
212 case T_LT:
213 v->v_num = l.v_num < r.v_num;
214 break;
215 case T_LE:
216 v->v_num = l.v_num <= r.v_num;
217 break;
218 case T_GT:
219 v->v_num = l.v_num > r.v_num;
220 break;
221 case T_GE:
222 v->v_num = l.v_num >= r.v_num;
223 break;
224 case T_LS:
225 if (l.v_type == V_STR) {
226 int i;
227 if ((i = strlen(l.v_str)) > r.v_num)
228 i = r.v_num;
229 v->v_str = str_ncpy(l.v_str, i);
230 v->v_type = V_STR;
231 } else
232 v->v_num = l.v_num << r.v_num;
233 break;
234 case T_RS:
235 if (l.v_type == V_STR) {
236 int i;
237 if ((i = strlen(l.v_str)) > r.v_num)
238 i -= r.v_num;
239 else
240 i = 0;
241 v->v_str = str_cpy(l.v_str + i);
242 v->v_type = V_STR;
243 } else
244 v->v_num = l.v_num >> r.v_num;
245 break;
246 case T_PLUS:
247 if (l.v_type == V_STR) {
248 v->v_str = str_cat(l.v_str, r.v_str);
249 v->v_type = V_STR;
250 } else
251 v->v_num = l.v_num + r.v_num;
252 break;
253 case T_MINUS:
254 v->v_num = l.v_num - r.v_num;
255 break;
256 case T_MUL:
257 v->v_num = l.v_num * r.v_num;
258 break;
259 case T_DIV:
260 v->v_num = l.v_num / r.v_num;
261 break;
262 case T_MOD:
263 v->v_num = l.v_num % r.v_num;
264 break;
265 }
266 val_free(l);
267 val_free(r);
268 }
269 /*NOTREACHED*/
270 }
271