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