]> git.saurik.com Git - apple/shell_cmds.git/blob - window/parser4.c
shell_cmds-17.1.tar.gz
[apple/shell_cmds.git] / window / parser4.c
1 /* $NetBSD: parser4.c,v 1.6 1997/11/21 08:36:15 lukem Exp $ */
2
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Edward Wang at The University of California, Berkeley.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)parser4.c 8.1 (Berkeley) 6/6/93";
43 #else
44 __RCSID("$NetBSD: parser4.c,v 1.6 1997/11/21 08:36:15 lukem Exp $");
45 #endif
46 #endif /* not lint */
47
48 #include <string.h>
49 #include "defs.h"
50 #include "parser.h"
51
52 /*
53 * | 3
54 * ^ 4
55 * & 5
56 * == != 6
57 * < <= > >= 7
58 * << >> 8
59 * + - 9
60 * * / % 10
61 */
62 int
63 p_expr3_10(level, v, flag)
64 int level;
65 struct value *v;
66 char flag;
67 {
68 struct value l, r;
69 int op;
70 char *opname = 0;
71
72 if ((level == 10 ? p_expr11(v, flag)
73 : p_expr3_10(level + 1, v, flag)) < 0)
74 return -1;
75 for (;;) {
76 switch (level) {
77 case 3:
78 if (token != T_OR)
79 return 0;
80 opname = "|";
81 break;
82 case 4:
83 if (token != T_XOR)
84 return 0;
85 opname = "^";
86 break;
87 case 5:
88 if (token != T_AND)
89 return 0;
90 opname = "&";
91 break;
92 case 6:
93 if (token == T_EQ)
94 opname = "==";
95 else if (token == T_NE)
96 opname = "!=";
97 else
98 return 0;
99 break;
100 case 7:
101 switch (token) {
102 case T_LT:
103 opname = "<";
104 break;
105 case T_LE:
106 opname = "<=";
107 break;
108 case T_GT:
109 opname = ">";
110 break;
111 case T_GE:
112 opname = ">=";
113 break;
114 default:
115 return 0;
116 }
117 break;
118 case 8:
119 if (token == T_LS)
120 opname = "<<";
121 else if (token == T_RS)
122 opname = ">>";
123 else
124 return 0;
125 break;
126 case 9:
127 if (token == T_PLUS)
128 opname = "+";
129 else if (token == T_MINUS)
130 opname = "-";
131 else
132 return 0;
133 break;
134 case 10:
135 switch (token) {
136 case T_MUL:
137 opname = "*";
138 break;
139 case T_DIV:
140 opname = "/";
141 break;
142 case T_MOD:
143 opname = "%";
144 break;
145 default:
146 return 0;
147 }
148 break;
149 }
150 l = *v;
151 if (l.v_type == V_ERR)
152 flag = 0;
153
154 op = token;
155 (void) s_gettok();
156 if ((level == 10 ? p_expr11(&r, flag)
157 : p_expr3_10(level + 1, &r, flag)) < 0) {
158 p_synerror();
159 val_free(l);
160 return -1;
161 }
162
163 if (r.v_type == V_ERR)
164 flag = 0;
165 else switch (op) {
166 case T_EQ:
167 case T_NE:
168 case T_LT:
169 case T_LE:
170 case T_GT:
171 case T_GE:
172 case T_PLUS:
173 if (l.v_type == V_STR) {
174 if (r.v_type == V_NUM)
175 if (p_convstr(&r) < 0)
176 flag = 0;
177 } else
178 if (r.v_type == V_STR)
179 if (p_convstr(&l) < 0)
180 flag = 0;
181 break;
182 case T_LS:
183 case T_RS:
184 if (r.v_type == V_STR) {
185 char *p = r.v_str;
186 r.v_type = V_NUM;
187 r.v_num = strlen(p);
188 str_free(p);
189 }
190 break;
191 case T_OR:
192 case T_XOR:
193 case T_AND:
194 case T_MINUS:
195 case T_MUL:
196 case T_DIV:
197 case T_MOD:
198 default:
199 if (l.v_type == V_STR || r.v_type == V_STR) {
200 p_error("%s: Numeric operands required.",
201 opname);
202 flag = 0;
203 }
204 }
205 if (!flag) {
206 val_free(l);
207 val_free(r);
208 v->v_type = V_ERR;
209 if (p_abort())
210 return -1;
211 continue;
212 }
213
214 v->v_type = V_NUM;
215 switch (op) {
216 case T_EQ:
217 case T_NE:
218 case T_LT:
219 case T_LE:
220 case T_GT:
221 case T_GE:
222 if (l.v_type == V_STR) {
223 int tmp = strcmp(l.v_str, r.v_str);
224 str_free(l.v_str);
225 str_free(r.v_str);
226 l.v_type = V_NUM;
227 l.v_num = tmp;
228 r.v_type = V_NUM;
229 r.v_num = 0;
230 }
231 break;
232 }
233 switch (op) {
234 case T_OR:
235 v->v_num = l.v_num | r.v_num;
236 break;
237 case T_XOR:
238 v->v_num = l.v_num ^ r.v_num;
239 break;
240 case T_AND:
241 v->v_num = l.v_num & r.v_num;
242 break;
243 case T_EQ:
244 v->v_num = l.v_num == r.v_num;
245 break;
246 case T_NE:
247 v->v_num = l.v_num != r.v_num;
248 break;
249 case T_LT:
250 v->v_num = l.v_num < r.v_num;
251 break;
252 case T_LE:
253 v->v_num = l.v_num <= r.v_num;
254 break;
255 case T_GT:
256 v->v_num = l.v_num > r.v_num;
257 break;
258 case T_GE:
259 v->v_num = l.v_num >= r.v_num;
260 break;
261 case T_LS:
262 if (l.v_type == V_STR) {
263 int i;
264 if ((i = strlen(l.v_str)) > r.v_num)
265 i = r.v_num;
266 v->v_str = str_ncpy(l.v_str, i);
267 v->v_type = V_STR;
268 } else
269 v->v_num = l.v_num << r.v_num;
270 break;
271 case T_RS:
272 if (l.v_type == V_STR) {
273 int i;
274 if ((i = strlen(l.v_str)) > r.v_num)
275 i -= r.v_num;
276 else
277 i = 0;
278 v->v_str = str_cpy(l.v_str + i);
279 v->v_type = V_STR;
280 } else
281 v->v_num = l.v_num >> r.v_num;
282 break;
283 case T_PLUS:
284 if (l.v_type == V_STR) {
285 v->v_str = str_cat(l.v_str, r.v_str);
286 v->v_type = V_STR;
287 } else
288 v->v_num = l.v_num + r.v_num;
289 break;
290 case T_MINUS:
291 v->v_num = l.v_num - r.v_num;
292 break;
293 case T_MUL:
294 v->v_num = l.v_num * r.v_num;
295 break;
296 case T_DIV:
297 v->v_num = l.v_num / r.v_num;
298 break;
299 case T_MOD:
300 v->v_num = l.v_num % r.v_num;
301 break;
302 }
303 val_free(l);
304 val_free(r);
305 }
306 /*NOTREACHED*/
307 }