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