expr.c revision 94078ecce3a103c28457e6f90f1e5b0dacc61146
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
29static void
30expr_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
38void
39expr_init_self(struct expr_node *node)
40{
41	expr_init_common(node, EXPR_OP_SELF);
42}
43
44void
45expr_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
53void
54expr_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
60void
61expr_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
67void
68expr_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_long(&val, l);
74	expr_init_const(node, &val);
75}
76
77void
78expr_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
89void
90expr_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
98void
99expr_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
111void
112expr_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
128static void
129release_lhs(struct expr_node *node)
130{
131	if (node->own_lhs)
132		expr_destroy(node->lhs);
133}
134
135void
136expr_destroy(struct expr_node *node)
137{
138	if (node == NULL)
139		return;
140
141	switch (node->kind) {
142	case EXPR_OP_ARGNO:
143	case EXPR_OP_SELF:
144		return;
145
146	case EXPR_OP_CONST:
147		value_destroy(&node->u.value);
148		return;
149
150	case EXPR_OP_NAMED:
151		if (node->u.name.own)
152			free((char *)node->u.name.s);
153		return;
154
155	case EXPR_OP_INDEX:
156		release_lhs(node);
157		if (node->u.node.own)
158			expr_destroy(node->u.node.n);
159		return;
160
161	case EXPR_OP_CALL2:
162		if (node->u.call.own_rhs)
163			expr_destroy(node->u.call.rhs);
164	case EXPR_OP_UP:
165	case EXPR_OP_CALL1:
166		release_lhs(node);
167		return;
168	}
169
170	assert(!"Invalid value of node kind");
171	abort();
172}
173
174int
175expr_is_compile_constant(struct expr_node *node)
176{
177	return node->kind == EXPR_OP_CONST;
178}
179
180static int
181eval_up(struct expr_node *node, struct value *context,
182	struct value_dict *arguments, struct value *ret_value)
183{
184	if (expr_eval(node->lhs, context, arguments, ret_value) < 0)
185		return -1;
186	struct value *parent = value_get_parental_struct(ret_value);
187	if (parent == NULL) {
188		value_destroy(ret_value);
189		return -1;
190	}
191	*ret_value = *parent;
192	return 0;
193}
194
195static int
196eval_cb1(struct expr_node *node, struct value *context,
197	 struct value_dict *arguments, struct value *ret_value)
198{
199	struct value val;
200	if (expr_eval(node->lhs, context, arguments, &val) < 0)
201		return -1;
202
203	int ret = 0;
204	if (node->u.call.u.cb1(ret_value, &val, arguments,
205			       node->u.call.data) < 0)
206		ret = -1;
207
208	/* N.B. the callback must return its own value, or somehow
209	 * clone the incoming argument.  */
210	value_destroy(&val);
211	return ret;
212}
213
214static int
215eval_cb2(struct expr_node *node, struct value *context,
216	 struct value_dict *arguments, struct value *ret_value)
217{
218	struct value lhs;
219	if (expr_eval(node->lhs, context, arguments, &lhs) < 0)
220		return -1;
221
222	struct value rhs;
223	if (expr_eval(node->u.call.rhs, context, arguments, &rhs) < 0) {
224		value_destroy(&lhs);
225		return -1;
226	}
227
228	int ret = 0;
229	if (node->u.call.u.cb2(ret_value, &lhs, &rhs, arguments,
230			       node->u.call.data) < 0)
231		ret = -1;
232
233	/* N.B. the callback must return its own value, or somehow
234	 * clone the incoming argument.  */
235	value_destroy(&lhs);
236	value_destroy(&rhs);
237	return ret;
238}
239
240int
241eval_index(struct expr_node *node, struct value *context,
242	   struct value_dict *arguments, struct value *ret_value)
243{
244	struct value lhs;
245	if (expr_eval(node->lhs, context, arguments, &lhs) < 0)
246		return -1;
247
248	long l;
249	if (expr_eval_word(node->u.node.n, context, arguments, &l) < 0) {
250	fail:
251		value_destroy(&lhs);
252		return -1;
253	}
254
255	if (value_init_element(ret_value, &lhs, (size_t)l) < 0)
256		goto fail;
257	return 0;
258}
259
260int
261expr_eval(struct expr_node *node, struct value *context,
262	  struct value_dict *arguments, struct value *ret_value)
263{
264	switch (node->kind) {
265		struct value *valp;
266	case EXPR_OP_ARGNO:
267		valp = val_dict_get_num(arguments, node->u.num);
268		if (valp == NULL)
269			return -1;
270		*ret_value = *valp;
271		return 0;
272
273	case EXPR_OP_NAMED:
274		valp = val_dict_get_name(arguments, node->u.name.s);
275		if (valp == NULL)
276			return -1;
277		*ret_value = *valp;
278		return 0;
279
280	case EXPR_OP_SELF:
281		*ret_value = *context;
282		return 0;
283
284	case EXPR_OP_CONST:
285		*ret_value = node->u.value;
286		return 0;
287
288	case EXPR_OP_INDEX:
289		return eval_index(node, context, arguments, ret_value);
290
291	case EXPR_OP_UP:
292		return eval_up(node, context, arguments, ret_value);
293
294	case EXPR_OP_CALL1:
295		return eval_cb1(node, context, arguments, ret_value);
296
297	case EXPR_OP_CALL2:
298		return eval_cb2(node, context, arguments, ret_value);
299	}
300
301	assert(!"Unknown node kind.");
302	abort();
303}
304
305int
306expr_eval_word(struct expr_node *node, struct value *context,
307	       struct value_dict *arguments, long *ret_value)
308{
309	struct value val;
310	if (expr_eval(node, context, arguments, &val) < 0)
311		return -1;
312	int ret = 0;
313	if (value_extract_word(&val, ret_value, arguments) < 0)
314		ret = -1;
315	value_destroy(&val);
316	return ret;
317}
318
319int
320expr_eval_constant(struct expr_node *node, long *valuep)
321{
322	assert(expr_is_compile_constant(node));
323	return expr_eval_word(node, NULL, NULL, valuep);
324}
325
326struct expr_node *
327expr_self(void)
328{
329	static struct expr_node *node = NULL;
330	if (node == NULL) {
331		node = malloc(sizeof(*node));
332		if (node == NULL)
333			error(1, errno, "malloc expr_self");
334		expr_init_self(node);
335	}
336	return node;
337}
338