| /* |
| * This file is part of ltrace. |
| * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of the |
| * License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
| * 02110-1301 USA |
| */ |
| |
| #include <assert.h> |
| #include <stdlib.h> |
| |
| #include "param.h" |
| #include "type.h" |
| #include "value.h" |
| #include "expr.h" |
| |
| void |
| param_init_type(struct param *param, struct arg_type_info *type, int own) |
| { |
| param->flavor = PARAM_FLAVOR_TYPE; |
| param->u.type.type = type; |
| param->u.type.own_type = own; |
| } |
| |
| void |
| param_init_stop(struct param *param) |
| { |
| param->flavor = PARAM_FLAVOR_STOP; |
| } |
| |
| void |
| param_init_pack(struct param *param, enum param_pack_flavor ppflavor, |
| struct expr_node *args, size_t nargs, int own_args, |
| struct param_enum *(*init)(struct value *cb_args, |
| size_t nargs, |
| struct value_dict *arguments), |
| int (*next)(struct param_enum *context, |
| struct arg_type_info *infop, |
| int *insert_stop), |
| enum param_status (*stop)(struct param_enum *ctx, |
| struct value *value), |
| void (*done)(struct param_enum *)) |
| { |
| param->flavor = PARAM_FLAVOR_PACK; |
| param->u.pack.args = args; |
| param->u.pack.nargs = nargs; |
| param->u.pack.own_args = own_args; |
| param->u.pack.ppflavor = ppflavor; |
| param->u.pack.init = init; |
| param->u.pack.next = next; |
| param->u.pack.stop = stop; |
| param->u.pack.done = done; |
| } |
| |
| struct param_enum * |
| param_pack_init(struct param *param, struct value_dict *fargs) |
| { |
| struct value cb_args[param->u.pack.nargs]; |
| size_t i; |
| |
| /* For evaluation of argument expressions, we pass in this as |
| * a "current" value. */ |
| struct arg_type_info *void_type = type_get_simple(ARGTYPE_VOID); |
| struct value void_val; |
| value_init_detached(&void_val, NULL, void_type, 0); |
| |
| struct param_enum *ret = NULL; |
| for (i = 0; i < param->u.pack.nargs; ++i) { |
| if (expr_eval(¶m->u.pack.args[i], &void_val, |
| fargs, &cb_args[i]) < 0) |
| goto release; |
| } |
| |
| ret = param->u.pack.init(cb_args, param->u.pack.nargs, fargs); |
| |
| release: |
| while (i-- > 0) |
| value_destroy(&cb_args[i]); |
| return ret; |
| } |
| |
| int |
| param_pack_next(struct param *param, struct param_enum *context, |
| struct arg_type_info *infop, int *insert_stop) |
| { |
| return param->u.pack.next(context, infop, insert_stop); |
| } |
| |
| enum param_status |
| param_pack_stop(struct param *param, |
| struct param_enum *context, struct value *value) |
| { |
| return param->u.pack.stop(context, value); |
| } |
| |
| void |
| param_pack_done(struct param *param, struct param_enum *context) |
| { |
| return param->u.pack.done(context); |
| } |
| |
| void |
| param_destroy(struct param *param) |
| { |
| if (param == NULL) |
| return; |
| |
| switch (param->flavor) { |
| case PARAM_FLAVOR_TYPE: |
| if (param->u.type.own_type) { |
| type_destroy(param->u.type.type); |
| free(param->u.type.type); |
| } |
| return; |
| |
| case PARAM_FLAVOR_PACK: |
| if (param->u.pack.own_args) { |
| size_t i; |
| for (i = 0; i < param->u.pack.nargs; ++i) |
| expr_destroy(¶m->u.pack.args[i]); |
| free(param->u.pack.args); |
| } |
| return; |
| |
| case PARAM_FLAVOR_STOP: |
| return; |
| } |
| |
| assert(!"Unknown value of param flavor!"); |
| abort(); |
| } |