Imported Upstream version 0.7.2
[platform/upstream/ltrace.git] / expr.c
1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA
19  */
20
21 #include <string.h>
22 #include <assert.h>
23 #include <errno.h>
24 #include <error.h>
25 #include <stdlib.h>
26
27 #include "expr.h"
28
29 static void
30 expr_init_common(struct expr_node *node, enum expr_node_kind kind)
31 {
32         node->kind = kind;
33         node->lhs = NULL;
34         node->own_lhs = 0;
35         memset(&node->u, 0, sizeof(node->u));
36 }
37
38 void
39 expr_init_self(struct expr_node *node)
40 {
41         expr_init_common(node, EXPR_OP_SELF);
42 }
43
44 void
45 expr_init_named(struct expr_node *node,
46                 const char *name, int own_name)
47 {
48         expr_init_common(node, EXPR_OP_NAMED);
49         node->u.name.s = name;
50         node->u.name.own = own_name;
51 }
52
53 void
54 expr_init_argno(struct expr_node *node, size_t num)
55 {
56         expr_init_common(node, EXPR_OP_ARGNO);
57         node->u.num = num;
58 }
59
60 void
61 expr_init_const(struct expr_node *node, struct value *val)
62 {
63         expr_init_common(node, EXPR_OP_CONST);
64         node->u.value = *val;
65 }
66
67 void
68 expr_init_const_word(struct expr_node *node, long l,
69                      struct arg_type_info *type, int own_type)
70 {
71         struct value val;
72         value_init_detached(&val, NULL, type, own_type);
73         value_set_word(&val, l);
74         expr_init_const(node, &val);
75 }
76
77 void
78 expr_init_index(struct expr_node *node,
79                 struct expr_node *lhs, int own_lhs,
80                 struct expr_node *rhs, int own_rhs)
81 {
82         expr_init_common(node, EXPR_OP_INDEX);
83         node->lhs = lhs;
84         node->own_lhs = own_lhs;
85         node->u.node.n = rhs;
86         node->u.node.own = own_rhs;
87 }
88
89 void
90 expr_init_up(struct expr_node *node, struct expr_node *lhs, int own_lhs)
91 {
92         assert(lhs != NULL);
93         expr_init_common(node, EXPR_OP_UP);
94         node->lhs = lhs;
95         node->own_lhs = own_lhs;
96 }
97
98 void
99 expr_init_cb1(struct expr_node *node,
100               int (*cb)(struct value *ret_value, struct value *value,
101                         struct value_dict *arguments, void *data),
102               struct expr_node *lhs, int own_lhs, void *data)
103 {
104         expr_init_common(node, EXPR_OP_CALL1);
105         node->lhs = lhs;
106         node->own_lhs = own_lhs;
107         node->u.call.u.cb1 = cb;
108         node->u.call.data = data;
109 }
110
111 void
112 expr_init_cb2(struct expr_node *node,
113               int (*cb)(struct value *ret_value,
114                         struct value *lhs, struct value *rhs,
115                         struct value_dict *arguments, void *data),
116               struct expr_node *lhs, int own_lhs,
117               struct expr_node *rhs, int own_rhs, void *data)
118 {
119         expr_init_common(node, EXPR_OP_CALL2);
120         node->lhs = lhs;
121         node->own_lhs = own_lhs;
122         node->u.call.rhs = rhs;
123         node->u.call.own_rhs = own_rhs;
124         node->u.call.u.cb2 = cb;
125         node->u.call.data = data;
126 }
127
128 static void
129 release_expr(struct expr_node *node, int own)
130 {
131         if (own) {
132                 expr_destroy(node);
133                 free(node);
134         }
135 }
136
137 void
138 expr_destroy(struct expr_node *node)
139 {
140         if (node == NULL)
141                 return;
142
143         switch (node->kind) {
144         case EXPR_OP_ARGNO:
145         case EXPR_OP_SELF:
146                 return;
147
148         case EXPR_OP_CONST:
149                 value_destroy(&node->u.value);
150                 return;
151
152         case EXPR_OP_NAMED:
153                 if (node->u.name.own)
154                         free((char *)node->u.name.s);
155                 return;
156
157         case EXPR_OP_INDEX:
158                 release_expr(node->lhs, node->own_lhs);
159                 release_expr(node->u.node.n, node->u.node.own);
160                 return;
161
162         case EXPR_OP_CALL2:
163                 release_expr(node->u.call.rhs, node->u.call.own_rhs);
164                 /* Fall through.  */
165         case EXPR_OP_UP:
166         case EXPR_OP_CALL1:
167                 release_expr(node->lhs, node->own_lhs);
168                 return;
169         }
170
171         assert(!"Invalid value of node kind");
172         abort();
173 }
174
175 int
176 expr_is_compile_constant(struct expr_node *node)
177 {
178         return node->kind == EXPR_OP_CONST;
179 }
180
181 static int
182 eval_up(struct expr_node *node, struct value *context,
183         struct value_dict *arguments, struct value *ret_value)
184 {
185         if (expr_eval(node->lhs, context, arguments, ret_value) < 0)
186                 return -1;
187         struct value *parent = value_get_parental_struct(ret_value);
188         if (parent == NULL) {
189                 value_destroy(ret_value);
190                 return -1;
191         }
192         *ret_value = *parent;
193         return 0;
194 }
195
196 static int
197 eval_cb1(struct expr_node *node, struct value *context,
198          struct value_dict *arguments, struct value *ret_value)
199 {
200         struct value val;
201         if (expr_eval(node->lhs, context, arguments, &val) < 0)
202                 return -1;
203
204         int ret = 0;
205         if (node->u.call.u.cb1(ret_value, &val, arguments,
206                                node->u.call.data) < 0)
207                 ret = -1;
208
209         /* N.B. the callback must return its own value, or somehow
210          * clone the incoming argument.  */
211         value_destroy(&val);
212         return ret;
213 }
214
215 static int
216 eval_cb2(struct expr_node *node, struct value *context,
217          struct value_dict *arguments, struct value *ret_value)
218 {
219         struct value lhs;
220         if (expr_eval(node->lhs, context, arguments, &lhs) < 0)
221                 return -1;
222
223         struct value rhs;
224         if (expr_eval(node->u.call.rhs, context, arguments, &rhs) < 0) {
225                 value_destroy(&lhs);
226                 return -1;
227         }
228
229         int ret = 0;
230         if (node->u.call.u.cb2(ret_value, &lhs, &rhs, arguments,
231                                node->u.call.data) < 0)
232                 ret = -1;
233
234         /* N.B. the callback must return its own value, or somehow
235          * clone the incoming argument.  */
236         value_destroy(&lhs);
237         value_destroy(&rhs);
238         return ret;
239 }
240
241 int
242 eval_index(struct expr_node *node, struct value *context,
243            struct value_dict *arguments, struct value *ret_value)
244 {
245         struct value lhs;
246         if (expr_eval(node->lhs, context, arguments, &lhs) < 0)
247                 return -1;
248
249         long l;
250         if (expr_eval_word(node->u.node.n, context, arguments, &l) < 0) {
251         fail:
252                 value_destroy(&lhs);
253                 return -1;
254         }
255
256         if (value_init_element(ret_value, &lhs, (size_t)l) < 0)
257                 goto fail;
258         return 0;
259 }
260
261 int
262 expr_eval(struct expr_node *node, struct value *context,
263           struct value_dict *arguments, struct value *ret_value)
264 {
265         switch (node->kind) {
266                 struct value *valp;
267         case EXPR_OP_ARGNO:
268                 valp = val_dict_get_num(arguments, node->u.num);
269                 if (valp == NULL)
270                         return -1;
271                 *ret_value = *valp;
272                 return 0;
273
274         case EXPR_OP_NAMED:
275                 valp = val_dict_get_name(arguments, node->u.name.s);
276                 if (valp == NULL)
277                         return -1;
278                 *ret_value = *valp;
279                 return 0;
280
281         case EXPR_OP_SELF:
282                 *ret_value = *context;
283                 return 0;
284
285         case EXPR_OP_CONST:
286                 *ret_value = node->u.value;
287                 return 0;
288
289         case EXPR_OP_INDEX:
290                 return eval_index(node, context, arguments, ret_value);
291
292         case EXPR_OP_UP:
293                 return eval_up(node, context, arguments, ret_value);
294
295         case EXPR_OP_CALL1:
296                 return eval_cb1(node, context, arguments, ret_value);
297
298         case EXPR_OP_CALL2:
299                 return eval_cb2(node, context, arguments, ret_value);
300         }
301
302         assert(!"Unknown node kind.");
303         abort();
304 }
305
306 int
307 expr_eval_word(struct expr_node *node, struct value *context,
308                struct value_dict *arguments, long *ret_value)
309 {
310         struct value val;
311         if (expr_eval(node, context, arguments, &val) < 0)
312                 return -1;
313         int ret = 0;
314         if (value_extract_word(&val, ret_value, arguments) < 0)
315                 ret = -1;
316         value_destroy(&val);
317         return ret;
318 }
319
320 int
321 expr_eval_constant(struct expr_node *node, long *valuep)
322 {
323         assert(expr_is_compile_constant(node));
324         return expr_eval_word(node, NULL, NULL, valuep);
325 }
326
327 struct expr_node *
328 expr_self(void)
329 {
330         static struct expr_node *node = NULL;
331         if (node == NULL) {
332                 node = malloc(sizeof(*node));
333                 if (node == NULL)
334                         error(1, errno, "malloc expr_self");
335                 expr_init_self(node);
336         }
337         return node;
338 }