expr.c revision 3299797320059f659f3abb80f3ce02bab3db8bb9
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_word(&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_expr(struct expr_node *node, int own)
130{
131	if (own) {
132		expr_destroy(node);
133		free(node);
134	}
135}
136
137void
138expr_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
175int
176expr_is_compile_constant(struct expr_node *node)
177{
178	return node->kind == EXPR_OP_CONST;
179}
180
181static int
182eval_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
196static int
197eval_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
215static int
216eval_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
241int
242eval_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
261int
262expr_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
306int
307expr_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
320int
321expr_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
327struct expr_node *
328expr_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}
339