aboutsummaryrefslogtreecommitdiff
path: root/param.h
blob: ce393d6971043151574bdee0050c4d1ffaf309d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * 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 */