| /* |
| * 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 |
| */ |
| |
| #ifndef PARAM_H |
| #define PARAM_H |
| |
| #include "forward.h" |
| |
| /* The structure param holds information about a parameter of a |
| * function. It's used to configure a function prototype. There are |
| * two flavors of parameters: |
| * |
| * - simple types |
| * - parameter packs |
| * |
| * Parameter packs are used to describe various vararg constructs. |
| * They themselves are parametrized by ltrace expressions. Those will |
| * typically be references to other arguments, but constants might |
| * also make sense, and it principle, anything can be used. */ |
| |
| enum param_flavor { |
| PARAM_FLAVOR_TYPE, |
| PARAM_FLAVOR_PACK, |
| |
| /* This is for emitting arguments in two bunches. This is |
| * where we should stop emitting "left" bunch. All that's |
| * after this parameter should be emitted in the "right" |
| * bunch. */ |
| PARAM_FLAVOR_STOP, |
| }; |
| |
| enum param_pack_flavor { |
| /* This parameter pack expands to a list of ordinary |
| * arguments. For example if the last argument is sometimes |
| * ignored, that would be described by a PARAM_PACK_ARGS |
| * parameter pack. ioctl or ptrace are two examples that |
| * would benefit from this. */ |
| PARAM_PACK_ARGS, |
| |
| /* This parameter pack represents a vararg argument. */ |
| PARAM_PACK_VARARGS, |
| }; |
| |
| enum param_status { |
| PPCB_ERR = -1, /* An error occurred. */ |
| PPCB_STOP, /* Stop fetching the arguments. */ |
| PPCB_CONT, /* Display this argument and keep going. */ |
| }; |
| |
| /* Each parameter enumerator defines its own context object. |
| * Definitions of these are in respective .c files of each |
| * enumerator. */ |
| struct param_enum; |
| |
| struct param { |
| enum param_flavor flavor; |
| union { |
| struct { |
| struct arg_type_info *type; |
| int own_type; |
| } type; |
| struct { |
| struct expr_node *args; |
| size_t nargs; |
| int own_args; |
| enum param_pack_flavor ppflavor; |
| |
| struct param_enum *(*init)(struct value *cb_args, |
| size_t nargs, |
| struct value_dict *arguments); |
| int (*next)(struct param_enum *self, |
| struct arg_type_info *info, |
| int *insert_stop); |
| enum param_status (*stop)(struct param_enum *self, |
| struct value *value); |
| void (*done)(struct param_enum *self); |
| } pack; |
| } u; |
| }; |
| |
| /* Initialize simple type parameter. TYPE is owned and released by |
| * PARAM if OWN_TYPE. */ |
| void param_init_type(struct param *param, |
| struct arg_type_info *type, int own_type); |
| |
| /* Initialize a stop. */ |
| void param_init_stop(struct param *param); |
| |
| /* Initialize parameter pack PARAM. ARGS is an array of expressions |
| * with parameters. ARGS is owned and released by the pack if |
| * OWN_ARGS. NARGS is number of ARGS. |
| * |
| * When the parameter pack should be expanded, those expressions are |
| * evaluated and passed to the INIT callback. This has to return a |
| * non-NULL context object. |
| * |
| * The NEXT callback is then called repeatedly, and should initialize |
| * its INFOP argument to a type of the next parameter in the pack. |
| * When there are no more parameters in the pack, the NEXT callback |
| * will set INFOP to a VOID parameter. If the callback sets |
| * INSERT_STOP to a non-zero value, a stop parameter shall be inserted |
| * before this actual parameter. |
| * |
| * Core then uses the passed-in type to fetch the next argument, which |
| * is in turn passed to STOP callback. This callback then tells |
| * ltrace core what to do next: whether there are more arguments, and |
| * if not, whether this argument should be displayed. |
| * |
| * After the enumeration is ended, DONE callback is called. */ |
| 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 *self, |
| struct arg_type_info *infop, |
| int *insert_stop), |
| enum param_status (*stop)(struct param_enum *self, |
| struct value *value), |
| void (*done)(struct param_enum *self)); |
| |
| /* Start enumerating types in parameter pack. This evaluates the |
| * parameter the pack arguments and calls the init callback. See the |
| * documentation of param_init_pack for details. */ |
| struct param_enum *param_pack_init(struct param *param, |
| struct value_dict *fargs); |
| |
| /* Ask for next type in enumeration. See the documentation of |
| * param_init_pack for details. */ |
| int param_pack_next(struct param *param, struct param_enum *self, |
| struct arg_type_info *infop, int *insert_stop); |
| |
| /* Ask whether we should stop enumerating. See the documentation of |
| * param_init_pack for details. */ |
| enum param_status param_pack_stop(struct param *param, |
| struct param_enum *self, struct value *value); |
| |
| /* Finish enumerating types in parameter pack. See the documentation |
| * of param_init_pack for details. */ |
| void param_pack_done(struct param *param, struct param_enum *self); |
| |
| /* Destroy data held by PARAM, but not the PARAM pointer itself. */ |
| void param_destroy(struct param *param); |
| |
| #endif /* PARAM_H */ |