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