xref: /original-bsd/usr.bin/window/parser4.c (revision 262b24ac)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)parser4.c	3.6 (Berkeley) 06/29/88";
20 #endif /* not lint */
21 
22 #include "parser.h"
23 
24 /*
25  * |		3
26  * ^		4
27  * &		5
28  * == !=	6
29  * < <= > >=	7
30  * << >>	8
31  * + -		9
32  * * / %	10
33  */
34 p_expr3_10(level, v, flag)
35 register struct value *v;
36 char flag;
37 {
38 	struct value l, r;
39 	int op;
40 	char *opname;
41 
42 	if ((level == 10 ? p_expr11(v, flag)
43 	     : p_expr3_10(level + 1, v, flag)) < 0)
44 		return -1;
45 	for (;;) {
46 		switch (level) {
47 		case 3:
48 			if (token != T_OR)
49 				return 0;
50 			opname = "|";
51 			break;
52 		case 4:
53 			if (token != T_XOR)
54 				return 0;
55 			opname = "^";
56 			break;
57 		case 5:
58 			if (token != T_AND)
59 				return 0;
60 			opname = "&";
61 			break;
62 		case 6:
63 			if (token == T_EQ)
64 				opname = "==";
65 			else if (token == T_NE)
66 				opname = "!=";
67 			else
68 				return 0;
69 			break;
70 		case 7:
71 			switch (token) {
72 			case T_LT:
73 				opname = "<";
74 				break;
75 			case T_LE:
76 				opname = "<=";
77 				break;
78 			case T_GT:
79 				opname = ">";
80 				break;
81 			case T_GE:
82 				opname = ">=";
83 				break;
84 			default:
85 				return 0;
86 			}
87 			break;
88 		case 8:
89 			if (token == T_LS)
90 				opname = "<<";
91 			else if (token == T_RS)
92 				opname = ">>";
93 			else
94 				return 0;
95 			break;
96 		case 9:
97 			if (token == T_PLUS)
98 				opname = "+";
99 			else if (token == T_MINUS)
100 				opname = "-";
101 			else
102 				return 0;
103 			break;
104 		case 10:
105 			switch (token) {
106 			case T_MUL:
107 				opname = "*";
108 				break;
109 			case T_DIV:
110 				opname = "/";
111 				break;
112 			case T_MOD:
113 				opname = "%";
114 				break;
115 			default:
116 				return 0;
117 			}
118 			break;
119 		}
120 		l = *v;
121 		if (l.v_type == V_ERR)
122 			flag = 0;
123 
124 		op = token;
125 		(void) s_gettok();
126 		if ((level == 10 ? p_expr11(&r, flag)
127 		     : p_expr3_10(level + 1, &r, flag)) < 0) {
128 			p_synerror();
129 			val_free(l);
130 			return -1;
131 		}
132 
133 		if (r.v_type == V_ERR)
134 			flag = 0;
135 		else switch (op) {
136 		case T_EQ:
137 		case T_NE:
138 		case T_LT:
139 		case T_LE:
140 		case T_GT:
141 		case T_GE:
142 		case T_PLUS:
143 			if (l.v_type == V_STR) {
144 				if (r.v_type == V_NUM)
145 					if (p_convstr(&r) < 0)
146 						flag = 0;
147 			} else
148 				if (r.v_type == V_STR)
149 					if (p_convstr(&l) < 0)
150 						flag = 0;
151 			break;
152 		case T_LS:
153 		case T_RS:
154 			if (r.v_type == V_STR) {
155 				char *p = r.v_str;
156 				r.v_type = V_NUM;
157 				r.v_num = strlen(p);
158 				str_free(p);
159 			}
160 			break;
161 		case T_OR:
162 		case T_XOR:
163 		case T_AND:
164 		case T_MINUS:
165 		case T_MUL:
166 		case T_DIV:
167 		case T_MOD:
168 		default:
169 			if (l.v_type == V_STR || r.v_type == V_STR) {
170 				p_error("%s: Numeric operands required.",
171 					opname);
172 				flag = 0;
173 			}
174 		}
175 		if (!flag) {
176 			val_free(l);
177 			val_free(r);
178 			v->v_type = V_ERR;
179 			if (p_abort())
180 				return -1;
181 			continue;
182 		}
183 
184 		v->v_type = V_NUM;
185 		switch (op) {
186 		case T_EQ:
187 		case T_NE:
188 		case T_LT:
189 		case T_LE:
190 		case T_GT:
191 		case T_GE:
192 			if (l.v_type == V_STR) {
193 				int tmp = strcmp(l.v_str, r.v_str);
194 				str_free(l.v_str);
195 				str_free(r.v_str);
196 				l.v_type = V_NUM;
197 				l.v_num = tmp;
198 				r.v_type = V_NUM;
199 				r.v_num = 0;
200 			}
201 			break;
202 		}
203 		switch (op) {
204 		case T_OR:
205 			v->v_num = l.v_num | r.v_num;
206 			break;
207 		case T_XOR:
208 			v->v_num = l.v_num ^ r.v_num;
209 			break;
210 		case T_AND:
211 			v->v_num = l.v_num & r.v_num;
212 			break;
213 		case T_EQ:
214 			v->v_num = l.v_num == r.v_num;
215 			break;
216 		case T_NE:
217 			v->v_num = l.v_num != r.v_num;
218 			break;
219 		case T_LT:
220 			v->v_num = l.v_num < r.v_num;
221 			break;
222 		case T_LE:
223 			v->v_num = l.v_num <= r.v_num;
224 			break;
225 		case T_GT:
226 			v->v_num = l.v_num > r.v_num;
227 			break;
228 		case T_GE:
229 			v->v_num = l.v_num >= r.v_num;
230 			break;
231 		case T_LS:
232 			if (l.v_type == V_STR) {
233 				int i;
234 				if ((i = strlen(l.v_str)) > r.v_num)
235 					i = r.v_num;
236 				v->v_str = str_ncpy(l.v_str, i);
237 				v->v_type = V_STR;
238 			} else
239 				v->v_num = l.v_num << r.v_num;
240 			break;
241 		case T_RS:
242 			if (l.v_type == V_STR) {
243 				int i;
244 				if ((i = strlen(l.v_str)) > r.v_num)
245 					i -= r.v_num;
246 				else
247 					i = 0;
248 				v->v_str = str_cpy(l.v_str + i);
249 				v->v_type = V_STR;
250 			} else
251 				v->v_num = l.v_num >> r.v_num;
252 			break;
253 		case T_PLUS:
254 			if (l.v_type == V_STR) {
255 				v->v_str = str_cat(l.v_str, r.v_str);
256 				v->v_type = V_STR;
257 			} else
258 				v->v_num = l.v_num + r.v_num;
259 			break;
260 		case T_MINUS:
261 			v->v_num = l.v_num - r.v_num;
262 			break;
263 		case T_MUL:
264 			v->v_num = l.v_num * r.v_num;
265 			break;
266 		case T_DIV:
267 			v->v_num = l.v_num / r.v_num;
268 			break;
269 		case T_MOD:
270 			v->v_num = l.v_num % r.v_num;
271 			break;
272 		}
273 		val_free(l);
274 		val_free(r);
275 	}
276 	/*NOTREACHED*/
277 }
278