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