comparison lwlib/lw_expr.c @ 334:f2173d18c73f

Checkpoint
author lost
date Thu, 04 Mar 2010 02:24:38 +0000
parents
children 9f58e3bca6e3
comparison
equal deleted inserted replaced
333:ebff3a3e8fa6 334:f2173d18c73f
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 }