]>
Commit | Line | Data |
---|---|---|
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 | } |