xref: /dragonfly/usr.bin/window/parser4.c (revision 9f3fc534)
1 /*	$NetBSD: parser4.c,v 1.9 2009/04/14 08:50:06 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. 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.
21  *
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.
33  */
34 
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.9 2009/04/14 08:50:06 lukem Exp $");
41 #endif
42 #endif /* not lint */
43 
44 #include <string.h>
45 #include "defs.h"
46 #include "parser.h"
47 
48 /*
49  * |		3
50  * ^		4
51  * &		5
52  * == !=	6
53  * < <= > >=	7
54  * << >>	8
55  * + -		9
56  * * / %	10
57  */
58 int
59 p_expr3_10(int level, struct value *v, char flag)
60 {
61 	struct value l, r;
62 	int op;
63 	const char *opname = 0;
64 
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;
109 			}
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;
140 			}
141 			break;
142 		}
143 		l = *v;
144 		if (l.v_type == V_ERR)
145 			flag = 0;
146 
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;
154 		}
155 
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);
182 			}
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;
196 			}
197 		}
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;
205 		}
206 
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;
223 			}
224 			break;
225 		}
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;
295 		}
296 		val_free(l);
297 		val_free(r);
298 	}
299 	/*NOTREACHED*/
300 }
301