Commit | Line | Data |
---|---|---|
8318d219 | 1 | #ifndef lint |
7edc52ec | 2 | static char sccsid[] = "@(#)parser4.c 3.3 %G%"; |
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 | */ | |
17 | p_expr3_10(level, v, flag) | |
18 | register struct value *v; | |
19 | char 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 | } |