Petr Machata | 865303f | 2012-01-06 18:40:38 +0100 | [diff] [blame] | 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 | #ifndef PARAM_H |
| 22 | #define PARAM_H |
| 23 | |
| 24 | #include "forward.h" |
| 25 | |
| 26 | /* The structure param holds information about a parameter of a |
| 27 | * function. It's used to configure a function prototype. There are |
| 28 | * two flavors of parameters: |
| 29 | * |
| 30 | * - simple types |
| 31 | * - parameter packs |
| 32 | * |
| 33 | * Parameter packs are used to describe various vararg constructs. |
| 34 | * They themselves are parametrized by ltrace expressions. Those will |
| 35 | * typically be references to other arguments, but constants might |
| 36 | * also make sense, and it principle, anything can be used. */ |
| 37 | |
| 38 | enum param_flavor { |
| 39 | PARAM_FLAVOR_TYPE, |
| 40 | PARAM_FLAVOR_PACK, |
| 41 | |
| 42 | /* This is for emitting arguments in two bunches. This is |
| 43 | * where we should stop emitting "left" bunch. All that's |
| 44 | * after this parameter should be emitted in the "right" |
| 45 | * bunch. */ |
| 46 | PARAM_FLAVOR_STOP, |
| 47 | }; |
| 48 | |
Petr Machata | e36298a | 2012-09-13 17:12:41 +0200 | [diff] [blame] | 49 | enum param_pack_flavor { |
| 50 | /* This parameter pack expands to a list of ordinary |
| 51 | * arguments. For example if the last argument is sometimes |
| 52 | * ignored, that would be described by a PARAM_PACK_ARGS |
| 53 | * parameter pack. ioctl or ptrace are two examples that |
| 54 | * would benefit from this. */ |
| 55 | PARAM_PACK_ARGS, |
| 56 | |
| 57 | /* This parameter pack represents a vararg argument. */ |
| 58 | PARAM_PACK_VARARGS, |
| 59 | }; |
| 60 | |
Petr Machata | 865303f | 2012-01-06 18:40:38 +0100 | [diff] [blame] | 61 | enum param_status { |
| 62 | PPCB_ERR = -1, /* An error occurred. */ |
| 63 | PPCB_STOP, /* Stop fetching the arguments. */ |
| 64 | PPCB_CONT, /* Display this argument and keep going. */ |
| 65 | }; |
| 66 | |
| 67 | /* Each parameter enumerator defines its own context object. |
| 68 | * Definitions of these are in respective .c files of each |
| 69 | * enumerator. */ |
| 70 | struct param_enum; |
| 71 | |
Petr Machata | 865303f | 2012-01-06 18:40:38 +0100 | [diff] [blame] | 72 | struct param { |
| 73 | enum param_flavor flavor; |
| 74 | union { |
| 75 | struct { |
| 76 | struct arg_type_info *type; |
| 77 | int own_type; |
| 78 | } type; |
| 79 | struct { |
| 80 | struct expr_node *args; |
| 81 | size_t nargs; |
| 82 | int own_args; |
Petr Machata | e36298a | 2012-09-13 17:12:41 +0200 | [diff] [blame] | 83 | enum param_pack_flavor ppflavor; |
Petr Machata | 865303f | 2012-01-06 18:40:38 +0100 | [diff] [blame] | 84 | |
| 85 | struct param_enum *(*init)(struct value *cb_args, |
| 86 | size_t nargs, |
| 87 | struct value_dict *arguments); |
| 88 | int (*next)(struct param_enum *self, |
| 89 | struct arg_type_info *info, |
| 90 | int *insert_stop); |
| 91 | enum param_status (*stop)(struct param_enum *self, |
| 92 | struct value *value); |
| 93 | void (*done)(struct param_enum *self); |
| 94 | } pack; |
| 95 | } u; |
| 96 | }; |
| 97 | |
| 98 | /* Initialize simple type parameter. TYPE is owned and released by |
| 99 | * PARAM if OWN_TYPE. */ |
| 100 | void param_init_type(struct param *param, |
| 101 | struct arg_type_info *type, int own_type); |
| 102 | |
| 103 | /* Initialize a stop. */ |
| 104 | void param_init_stop(struct param *param); |
| 105 | |
| 106 | /* Initialize parameter pack PARAM. ARGS is an array of expressions |
| 107 | * with parameters. ARGS is owned and released by the pack if |
| 108 | * OWN_ARGS. NARGS is number of ARGS. |
| 109 | * |
| 110 | * When the parameter pack should be expanded, those expressions are |
| 111 | * evaluated and passed to the INIT callback. This has to return a |
| 112 | * non-NULL context object. |
| 113 | * |
| 114 | * The NEXT callback is then called repeatedly, and should initialize |
| 115 | * its INFOP argument to a type of the next parameter in the pack. |
| 116 | * When there are no more parameters in the pack, the NEXT callback |
| 117 | * will set INFOP to a VOID parameter. If the callback sets |
| 118 | * INSERT_STOP to a non-zero value, a stop parameter shall be inserted |
| 119 | * before this actual parameter. |
| 120 | * |
| 121 | * Core then uses the passed-in type to fetch the next argument, which |
| 122 | * is in turn passed to STOP callback. This callback then tells |
| 123 | * ltrace core what to do next: whether there are more arguments, and |
| 124 | * if not, whether this argument should be displayed. |
| 125 | * |
| 126 | * After the enumeration is ended, DONE callback is called. */ |
Petr Machata | e36298a | 2012-09-13 17:12:41 +0200 | [diff] [blame] | 127 | void param_init_pack(struct param *param, enum param_pack_flavor ppflavor, |
Petr Machata | 865303f | 2012-01-06 18:40:38 +0100 | [diff] [blame] | 128 | struct expr_node *args, size_t nargs, int own_args, |
| 129 | struct param_enum *(*init)(struct value *cb_args, |
| 130 | size_t nargs, |
| 131 | struct value_dict *arguments), |
| 132 | int (*next)(struct param_enum *self, |
| 133 | struct arg_type_info *infop, |
| 134 | int *insert_stop), |
| 135 | enum param_status (*stop)(struct param_enum *self, |
| 136 | struct value *value), |
| 137 | void (*done)(struct param_enum *self)); |
| 138 | |
| 139 | /* Start enumerating types in parameter pack. This evaluates the |
| 140 | * parameter the pack arguments and calls the init callback. See the |
| 141 | * documentation of param_init_pack for details. */ |
| 142 | struct param_enum *param_pack_init(struct param *param, |
| 143 | struct value_dict *fargs); |
| 144 | |
| 145 | /* Ask for next type in enumeration. See the documentation of |
| 146 | * param_init_pack for details. */ |
| 147 | int param_pack_next(struct param *param, struct param_enum *self, |
| 148 | struct arg_type_info *infop, int *insert_stop); |
| 149 | |
| 150 | /* Ask whether we should stop enumerating. See the documentation of |
| 151 | * param_init_pack for details. */ |
| 152 | enum param_status param_pack_stop(struct param *param, |
| 153 | struct param_enum *self, struct value *value); |
| 154 | |
| 155 | /* Finish enumerating types in parameter pack. See the documentation |
| 156 | * of param_init_pack for details. */ |
| 157 | void param_pack_done(struct param *param, struct param_enum *self); |
| 158 | |
| 159 | /* Destroy data held by PARAM, but not the PARAM pointer itself. */ |
| 160 | void param_destroy(struct param *param); |
| 161 | |
| 162 | #endif /* PARAM_H */ |