Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.bin / window / parser4.c
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  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36
37 #ifndef lint
38 static char sccsid[] = "@(#)parser4.c   8.1 (Berkeley) 6/6/93";
39 static char rcsid[] =
40   "$FreeBSD: src/usr.bin/window/parser4.c,v 1.2.6.1 2001/05/17 09:45:00 obrien Exp $";
41 #endif /* not lint */
42
43 #include <string.h>
44 #include "parser.h"
45
46 /*
47  * |            3
48  * ^            4
49  * &            5
50  * == !=        6
51  * < <= > >=    7
52  * << >>        8
53  * + -          9
54  * * / %        10
55  */
56 p_expr3_10(level, v, flag)
57 register struct value *v;
58 char flag;
59 {
60         struct value l, r;
61         int op;
62         char *opname;
63
64         if ((level == 10 ? p_expr11(v, flag)
65              : p_expr3_10(level + 1, v, flag)) < 0)
66                 return -1;
67         for (;;) {
68                 switch (level) {
69                 case 3:
70                         if (token != T_OR)
71                                 return 0;
72                         opname = "|";
73                         break;
74                 case 4:
75                         if (token != T_XOR)
76                                 return 0;
77                         opname = "^";
78                         break;
79                 case 5:
80                         if (token != T_AND)
81                                 return 0;
82                         opname = "&";
83                         break;
84                 case 6:
85                         if (token == T_EQ)
86                                 opname = "==";
87                         else if (token == T_NE)
88                                 opname = "!=";
89                         else
90                                 return 0;
91                         break;
92                 case 7:
93                         switch (token) {
94                         case T_LT:
95                                 opname = "<";
96                                 break;
97                         case T_LE:
98                                 opname = "<=";
99                                 break;
100                         case T_GT:
101                                 opname = ">";
102                                 break;
103                         case T_GE:
104                                 opname = ">=";
105                                 break;
106                         default:
107                                 return 0;
108                         }
109                         break;
110                 case 8:
111                         if (token == T_LS)
112                                 opname = "<<";
113                         else if (token == T_RS)
114                                 opname = ">>";
115                         else
116                                 return 0;
117                         break;
118                 case 9:
119                         if (token == T_PLUS)
120                                 opname = "+";
121                         else if (token == T_MINUS)
122                                 opname = "-";
123                         else
124                                 return 0;
125                         break;
126                 case 10:
127                         switch (token) {
128                         case T_MUL:
129                                 opname = "*";
130                                 break;
131                         case T_DIV:
132                                 opname = "/";
133                                 break;
134                         case T_MOD:
135                                 opname = "%";
136                                 break;
137                         default:
138                                 return 0;
139                         }
140                         break;
141                 }
142                 l = *v;
143                 if (l.v_type == V_ERR)
144                         flag = 0;
145
146                 op = token;
147                 (void) s_gettok();
148                 if ((level == 10 ? p_expr11(&r, flag)
149                      : p_expr3_10(level + 1, &r, flag)) < 0) {
150                         p_synerror();
151                         val_free(l);
152                         return -1;
153                 }
154
155                 if (r.v_type == V_ERR)
156                         flag = 0;
157                 else switch (op) {
158                 case T_EQ:
159                 case T_NE:
160                 case T_LT:
161                 case T_LE:
162                 case T_GT:
163                 case T_GE:
164                 case T_PLUS:
165                         if (l.v_type == V_STR) {
166                                 if (r.v_type == V_NUM)
167                                         if (p_convstr(&r) < 0)
168                                                 flag = 0;
169                         } else
170                                 if (r.v_type == V_STR)
171                                         if (p_convstr(&l) < 0)
172                                                 flag = 0;
173                         break;
174                 case T_LS:
175                 case T_RS:
176                         if (r.v_type == V_STR) {
177                                 char *p = r.v_str;
178                                 r.v_type = V_NUM;
179                                 r.v_num = strlen(p);
180                                 str_free(p);
181                         }
182                         break;
183                 case T_OR:
184                 case T_XOR:
185                 case T_AND:
186                 case T_MINUS:
187                 case T_MUL:
188                 case T_DIV:
189                 case T_MOD:
190                 default:
191                         if (l.v_type == V_STR || r.v_type == V_STR) {
192                                 p_error("%s: Numeric operands required.",
193                                         opname);
194                                 flag = 0;
195                         }
196                 }
197                 if (!flag) {
198                         val_free(l);
199                         val_free(r);
200                         v->v_type = V_ERR;
201                         if (p_abort())
202                                 return -1;
203                         continue;
204                 }
205
206                 v->v_type = V_NUM;
207                 switch (op) {
208                 case T_EQ:
209                 case T_NE:
210                 case T_LT:
211                 case T_LE:
212                 case T_GT:
213                 case T_GE:
214                         if (l.v_type == V_STR) {
215                                 int tmp = strcmp(l.v_str, r.v_str);
216                                 str_free(l.v_str);
217                                 str_free(r.v_str);
218                                 l.v_type = V_NUM;
219                                 l.v_num = tmp;
220                                 r.v_type = V_NUM;
221                                 r.v_num = 0;
222                         }
223                         break;
224                 }
225                 switch (op) {
226                 case T_OR:
227                         v->v_num = l.v_num | r.v_num;
228                         break;
229                 case T_XOR:
230                         v->v_num = l.v_num ^ r.v_num;
231                         break;
232                 case T_AND:
233                         v->v_num = l.v_num & r.v_num;
234                         break;
235                 case T_EQ:
236                         v->v_num = l.v_num == r.v_num;
237                         break;
238                 case T_NE:
239                         v->v_num = l.v_num != r.v_num;
240                         break;
241                 case T_LT:
242                         v->v_num = l.v_num < r.v_num;
243                         break;
244                 case T_LE:
245                         v->v_num = l.v_num <= r.v_num;
246                         break;
247                 case T_GT:
248                         v->v_num = l.v_num > r.v_num;
249                         break;
250                 case T_GE:
251                         v->v_num = l.v_num >= r.v_num;
252                         break;
253                 case T_LS:
254                         if (l.v_type == V_STR) {
255                                 int i;
256                                 if ((i = strlen(l.v_str)) > r.v_num)
257                                         i = r.v_num;
258                                 v->v_str = str_ncpy(l.v_str, i);
259                                 v->v_type = V_STR;
260                         } else
261                                 v->v_num = l.v_num << r.v_num;
262                         break;
263                 case T_RS:
264                         if (l.v_type == V_STR) {
265                                 int i;
266                                 if ((i = strlen(l.v_str)) > r.v_num)
267                                         i -= r.v_num;
268                                 else
269                                         i = 0;
270                                 v->v_str = str_cpy(l.v_str + i);
271                                 v->v_type = V_STR;
272                         } else
273                                 v->v_num = l.v_num >> r.v_num;
274                         break;
275                 case T_PLUS:
276                         if (l.v_type == V_STR) {
277                                 v->v_str = str_cat(l.v_str, r.v_str);
278                                 v->v_type = V_STR;
279                         } else
280                                 v->v_num = l.v_num + r.v_num;
281                         break;
282                 case T_MINUS:
283                         v->v_num = l.v_num - r.v_num;
284                         break;
285                 case T_MUL:
286                         v->v_num = l.v_num * r.v_num;
287                         break;
288                 case T_DIV:
289                         v->v_num = l.v_num / r.v_num;
290                         break;
291                 case T_MOD:
292                         v->v_num = l.v_num % r.v_num;
293                         break;
294                 }
295                 val_free(l);
296                 val_free(r);
297         }
298         /*NOTREACHED*/
299 }