334
|
1 /*
|
|
2 lwexpr.c
|
|
3
|
|
4 Copyright © 2010 William Astle
|
|
5
|
|
6 This file is part of LWTOOLS.
|
|
7
|
|
8 LWTOOLS is free software: you can redistribute it and/or modify it under the
|
|
9 terms of the GNU General Public License as published by the Free Software
|
|
10 Foundation, either version 3 of the License, or (at your option) any later
|
|
11 version.
|
|
12
|
|
13 This program is distributed in the hope that it will be useful, but WITHOUT
|
|
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
16 more details.
|
|
17
|
|
18 You should have received a copy of the GNU General Public License along with
|
|
19 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20 */
|
|
21
|
|
22 #include <config.h>
|
|
23
|
|
24 #include <stdarg.h>
|
|
25 #include <stdio.h>
|
|
26 #include <string.h>
|
|
27
|
|
28 #define ___lw_expr_c_seen___
|
|
29 #include "lw_alloc.h"
|
|
30 #include "lw_expr.h"
|
|
31 #include "lw_error.h"
|
|
32 #include "lw_string.h"
|
|
33
|
|
34 lw_expr_t lw_expr_create(void)
|
|
35 {
|
|
36 lw_expr_t r;
|
|
37
|
|
38 r = lw_alloc(sizeof(struct lw_expr_priv));
|
|
39 r -> refcount = 1;
|
|
40 r -> operands = NULL;
|
|
41
|
|
42 return r;
|
|
43 }
|
|
44
|
|
45 /* useful for constant expression construction */
|
|
46 /* lw_expr_deref(lw_expr_create(...)) */
|
|
47 /* use of this function on an expression that is not already referenced by the caller */
|
|
48 lw_expr_t lw_expr_deref(lw_expr_t r)
|
|
49 {
|
|
50 r -> refcount--;
|
|
51 return r;
|
|
52 }
|
|
53
|
|
54 void lw_expr_destroy(lw_expr_t E)
|
|
55 {
|
|
56 E -> refcount--;
|
|
57 if (E -> refcount <= 0)
|
|
58 {
|
|
59 struct lw_expr_opers *o;
|
|
60 for (o = E -> operands; o; o = o -> next)
|
|
61 lw_expr_destroy(o -> p);
|
|
62 if (E -> type == lw_expr_type_var)
|
|
63 lw_free(E -> value2);
|
|
64 lw_free(E);
|
|
65 }
|
|
66 }
|
|
67
|
|
68 lw_expr_t lw_expr_copy(lw_expr_t E)
|
|
69 {
|
|
70 E -> refcount++;
|
|
71 return E;
|
|
72 }
|
|
73
|
|
74 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O)
|
|
75 {
|
|
76 struct lw_expr_opers *o, *t;
|
|
77
|
|
78 o = lw_alloc(sizeof(struct lw_expr_opers));
|
|
79 o -> p = lw_expr_copy(O);
|
|
80 o -> next = NULL;
|
|
81 for (t = E -> operands; t && t -> next; t = t -> next)
|
|
82 /* do nothing */ ;
|
|
83
|
|
84 if (t)
|
|
85 t -> next = o;
|
|
86 else
|
|
87 E -> operands = o;
|
|
88 }
|
|
89
|
|
90 /* actually duplicates the entire expression */
|
|
91 lw_expr_t lw_expr_deepcopy(lw_expr_t E)
|
|
92 {
|
|
93 lw_expr_t r, t;
|
|
94 struct lw_expr_opers *o;
|
|
95
|
|
96 r = lw_alloc(sizeof(struct lw_expr_priv));
|
|
97 *r = *E;
|
|
98 r -> refcount = 1;
|
|
99
|
|
100 if (E -> type == lw_expr_type_var)
|
|
101 r -> value2 = lw_strdup(E -> value2);
|
|
102
|
|
103 for (o = r -> operands; o; o = o -> next)
|
|
104 {
|
|
105 lw_expr_add_operand(r, lw_expr_deref(lw_expr_deepcopy(o -> p)));
|
|
106 }
|
|
107
|
|
108 return r;
|
|
109 }
|
|
110
|
|
111 lw_expr_t lw_expr_build(int exprtype, ...)
|
|
112 {
|
|
113 va_list args;
|
|
114 lw_expr_t r;
|
|
115 int t;
|
|
116 void *p;
|
|
117
|
|
118 lw_expr_t te1, te2;
|
|
119
|
|
120 r = lw_expr_create();
|
|
121 va_start(args, exprtype);
|
|
122
|
|
123 switch (exprtype)
|
|
124 {
|
|
125 case lw_expr_type_int:
|
|
126 t = va_arg(args, int);
|
|
127 r -> type = lw_expr_type_int;
|
|
128 r -> value = t;
|
|
129 break;
|
|
130
|
|
131 case lw_expr_type_var:
|
|
132 p = va_arg(args, char *);
|
|
133 r -> type = lw_expr_type_var;
|
|
134 r -> value2 = lw_strdup(p);
|
|
135 break;
|
|
136
|
|
137 case lw_expr_type_special:
|
|
138 t = va_arg(args, int);
|
|
139 p = va_arg(args, char *);
|
|
140 r -> type = lw_expr_type_special;
|
|
141 r -> value2 = p;
|
|
142 break;
|
|
143
|
|
144 case lw_expr_type_oper:
|
|
145 t = va_arg(args, int);
|
|
146 te1 = va_arg(args, lw_expr_t);
|
|
147 if (t != lw_expr_oper_com && t != lw_expr_oper_neg)
|
|
148 te2 = va_arg(args, lw_expr_t);
|
|
149 else
|
|
150 te2 = NULL;
|
|
151
|
|
152 r -> type = lw_expr_type_oper;
|
|
153 r -> value = t;
|
|
154 lw_expr_add_operand(r, te1);
|
|
155 lw_expr_add_operand(r, te2);
|
|
156 break;
|
|
157
|
|
158 default:
|
|
159 lw_error("Invalid expression type specified to lw_expr_build");
|
|
160 }
|
|
161
|
|
162 va_end(args);
|
|
163 return r;
|
|
164 }
|
|
165
|
|
166 void lw_expr_print(lw_expr_t E)
|
|
167 {
|
|
168 struct lw_expr_opers *o;
|
|
169
|
|
170 for (o = E -> operands; o; o = o -> next)
|
|
171 {
|
|
172 lw_expr_print(o -> p);
|
|
173 }
|
|
174
|
|
175 switch (E -> type)
|
|
176 {
|
|
177 case lw_expr_type_int:
|
|
178 printf("%d ", E -> value);
|
|
179 break;
|
|
180 case lw_expr_type_oper:
|
|
181 switch (E -> value)
|
|
182 {
|
|
183 case lw_expr_oper_plus:
|
|
184 printf("+ ");
|
|
185 break;
|
|
186
|
|
187 case lw_expr_oper_minus:
|
|
188 printf("- ");
|
|
189 break;
|
|
190
|
|
191 case lw_expr_oper_times:
|
|
192 printf("* ");
|
|
193 break;
|
|
194
|
|
195 case lw_expr_oper_divide:
|
|
196 printf("/ ");
|
|
197 break;
|
|
198
|
|
199 case lw_expr_oper_mod:
|
|
200 printf("%% ");
|
|
201 break;
|
|
202
|
|
203 case lw_expr_oper_intdiv:
|
|
204 printf("\\ ");
|
|
205 break;
|
|
206
|
|
207 case lw_expr_oper_bwand:
|
|
208 printf("BWAND ");
|
|
209 break;
|
|
210
|
|
211 case lw_expr_oper_bwor:
|
|
212 printf("BWOR ");
|
|
213 break;
|
|
214
|
|
215 case lw_expr_oper_bwxor:
|
|
216 printf("BWXOR ");
|
|
217 break;
|
|
218
|
|
219 case lw_expr_oper_and:
|
|
220 printf("AND ");
|
|
221 break;
|
|
222
|
|
223 case lw_expr_oper_or:
|
|
224 printf("OR ");
|
|
225 break;
|
|
226
|
|
227 case lw_expr_oper_neg:
|
|
228 printf("NEG ");
|
|
229 break;
|
|
230
|
|
231 case lw_expr_oper_com:
|
|
232 printf("COM ");
|
|
233 break;
|
|
234
|
|
235 default:
|
|
236 printf("OPER ");
|
|
237 break;
|
|
238 }
|
|
239 break;
|
|
240 default:
|
|
241 printf("ERR ");
|
|
242 break;
|
|
243 }
|
|
244 }
|
|
245
|
|
246 /*
|
|
247 Return:
|
|
248 nonzero if expressions are the same (identical pointers or matching values)
|
|
249 zero if expressions are not the same
|
|
250
|
|
251 */
|
|
252 int lw_expr_compare(lw_expr_t E1, lw_expr_t E2)
|
|
253 {
|
|
254 struct lw_expr_opers *o1, *o2;
|
|
255
|
|
256 if (E1 == E2)
|
|
257 return 1;
|
|
258
|
|
259 if (!(E1 -> type == E2 -> type && E1 -> value == E2 -> value))
|
|
260 return 0;
|
|
261
|
|
262 if (E1 -> type == lw_expr_type_var)
|
|
263 {
|
|
264 if (!strcmp(E1 -> value2, E2 -> value2))
|
|
265 return 1;
|
|
266 else
|
|
267 return 0;
|
|
268 }
|
|
269
|
|
270 if (E1 -> type == lw_expr_type_special)
|
|
271 {
|
|
272 if (E1 -> value2 == E2 -> value2)
|
|
273 return 1;
|
|
274 else
|
|
275 return 0;
|
|
276 }
|
|
277
|
|
278 for (o1 = E1 -> operands, o2 = E2 -> operands; o1 && o2; o1 = o1 -> next, o2 = o2 -> next)
|
|
279 if (lw_expr_compare(o1 -> p, o2 -> p) == 0)
|
|
280 return 0;
|
|
281 if (o1 || o2)
|
|
282 return 0;
|
|
283
|
|
284 return 1;
|
|
285 }
|
|
286
|
|
287 /* return true if E is an operator of type oper */
|
|
288 int lw_expr_isoper(lw_expr_t E, int oper)
|
|
289 {
|
|
290 if (E -> type == lw_expr_type_oper && E -> value == oper)
|
|
291 return 1;
|
|
292 return 0;
|
|
293 }
|