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