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