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 <assert.h> 22 #include <stdlib.h> 23 24 #include "param.h" 25 #include "type.h" 26 #include "value.h" 27 #include "expr.h" 28 29 void 30 param_init_type(struct param *param, struct arg_type_info *type, int own) 31 { 32 param->flavor = PARAM_FLAVOR_TYPE; 33 param->u.type.type = type; 34 param->u.type.own_type = own; 35 } 36 37 void 38 param_init_stop(struct param *param) 39 { 40 param->flavor = PARAM_FLAVOR_STOP; 41 } 42 43 void 44 param_init_pack(struct param *param, enum param_pack_flavor ppflavor, 45 struct expr_node *args, size_t nargs, int own_args, 46 struct param_enum *(*init)(struct value *cb_args, 47 size_t nargs, 48 struct value_dict *arguments), 49 int (*next)(struct param_enum *context, 50 struct arg_type_info *infop, 51 int *insert_stop), 52 enum param_status (*stop)(struct param_enum *ctx, 53 struct value *value), 54 void (*done)(struct param_enum *)) 55 { 56 param->flavor = PARAM_FLAVOR_PACK; 57 param->u.pack.args = args; 58 param->u.pack.nargs = nargs; 59 param->u.pack.own_args = own_args; 60 param->u.pack.ppflavor = ppflavor; 61 param->u.pack.init = init; 62 param->u.pack.next = next; 63 param->u.pack.stop = stop; 64 param->u.pack.done = done; 65 } 66 67 struct param_enum * 68 param_pack_init(struct param *param, struct value_dict *fargs) 69 { 70 struct value cb_args[param->u.pack.nargs]; 71 size_t i; 72 73 /* For evaluation of argument expressions, we pass in this as 74 * a "current" value. */ 75 struct arg_type_info *void_type = type_get_simple(ARGTYPE_VOID); 76 struct value void_val; 77 value_init_detached(&void_val, NULL, void_type, 0); 78 79 struct param_enum *ret = NULL; 80 for (i = 0; i < param->u.pack.nargs; ++i) { 81 if (expr_eval(¶m->u.pack.args[i], &void_val, 82 fargs, &cb_args[i]) < 0) 83 goto release; 84 } 85 86 ret = param->u.pack.init(cb_args, param->u.pack.nargs, fargs); 87 88 release: 89 while (i-- > 0) 90 value_destroy(&cb_args[i]); 91 return ret; 92 } 93 94 int 95 param_pack_next(struct param *param, struct param_enum *context, 96 struct arg_type_info *infop, int *insert_stop) 97 { 98 return param->u.pack.next(context, infop, insert_stop); 99 } 100 101 enum param_status 102 param_pack_stop(struct param *param, 103 struct param_enum *context, struct value *value) 104 { 105 return param->u.pack.stop(context, value); 106 } 107 108 void 109 param_pack_done(struct param *param, struct param_enum *context) 110 { 111 return param->u.pack.done(context); 112 } 113 114 void 115 param_destroy(struct param *param) 116 { 117 if (param == NULL) 118 return; 119 120 switch (param->flavor) { 121 case PARAM_FLAVOR_TYPE: 122 if (param->u.type.own_type) { 123 type_destroy(param->u.type.type); 124 free(param->u.type.type); 125 } 126 return; 127 128 case PARAM_FLAVOR_PACK: 129 if (param->u.pack.own_args) { 130 size_t i; 131 for (i = 0; i < param->u.pack.nargs; ++i) 132 expr_destroy(¶m->u.pack.args[i]); 133 free(param->u.pack.args); 134 } 135 return; 136 137 case PARAM_FLAVOR_STOP: 138 return; 139 } 140 141 assert(!"Unknown value of param flavor!"); 142 abort(); 143 } 144