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