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