Commit | Line | Data |
---|---|---|
9d0faba9 PA |
1 | /* CLI options framework, for GDB. |
2 | ||
3 | Copyright (C) 2017-2019 Free Software Foundation, Inc. | |
4 | ||
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #ifndef CLI_OPTION_H | |
21 | #define CLI_OPTION_H 1 | |
22 | ||
268a13a5 TT |
23 | #include "gdbsupport/gdb_optional.h" |
24 | #include "gdbsupport/array-view.h" | |
9d0faba9 PA |
25 | #include "completer.h" |
26 | #include <string> | |
27 | #include "command.h" | |
28 | ||
29 | namespace gdb { | |
30 | namespace option { | |
31 | ||
32 | /* A type-erased option definition. The actual type of the option is | |
33 | stored in the TYPE field. Client code cannot define objects of | |
34 | this type directly (the ctor is protected). Instead, one of the | |
35 | wrapper types below that extends this (boolean_option_def, | |
36 | flag_option_def, uinteger_option_def, etc.) should be defined. */ | |
37 | struct option_def | |
38 | { | |
39 | /* The ctor is protected because you're supposed to construct using | |
40 | one of bool_option_def, etc. below. */ | |
41 | protected: | |
42 | typedef void *(erased_get_var_address_ftype) (); | |
43 | ||
44 | /* Construct an option. NAME_ is the option's name. VAR_TYPE_ | |
45 | defines the option's type. ERASED_GET_VAR_ADDRESS_ is a pointer | |
46 | to a function that returns the option's control variable. | |
47 | SHOW_CMD_CB_ is a pointer to callback for the "show" command that | |
48 | is installed for this option. SET_DOC_, SHOW_DOC_, HELP_DOC_ are | |
49 | used to create the option's "set/show" commands. */ | |
50 | constexpr option_def (const char *name_, | |
51 | var_types var_type_, | |
52 | erased_get_var_address_ftype *erased_get_var_address_, | |
53 | show_value_ftype *show_cmd_cb_, | |
54 | const char *set_doc_, | |
55 | const char *show_doc_, | |
56 | const char *help_doc_) | |
57 | : name (name_), type (var_type_), | |
58 | erased_get_var_address (erased_get_var_address_), | |
59 | var_address {}, | |
60 | show_cmd_cb (show_cmd_cb_), | |
61 | set_doc (set_doc_), show_doc (show_doc_), help_doc (help_doc_) | |
62 | {} | |
63 | ||
64 | public: | |
65 | /* The option's name. */ | |
66 | const char *name; | |
67 | ||
68 | /* The option's type. */ | |
69 | var_types type; | |
70 | ||
71 | /* A function that gets the controlling variable's address, type | |
72 | erased. */ | |
73 | erased_get_var_address_ftype *erased_get_var_address; | |
74 | ||
75 | /* Get the controlling variable's address. Each type of variable | |
76 | uses a different union member. We do this instead of having a | |
77 | single hook that return a "void *", for better type safety. This | |
78 | way, actual instances of concrete option_def types | |
79 | (boolean_option_def, etc.) fail to compile if you pass in a | |
80 | function with incorrect return type. CTX here is the aggregate | |
81 | object that groups the option variables from which the callback | |
82 | returns the address of some member. */ | |
83 | union | |
84 | { | |
491144b5 | 85 | bool *(*boolean) (const option_def &, void *ctx); |
9d0faba9 PA |
86 | unsigned int *(*uinteger) (const option_def &, void *ctx); |
87 | int *(*integer) (const option_def &, void *ctx); | |
88 | const char **(*enumeration) (const option_def &, void *ctx); | |
3d9be6f5 | 89 | char **(*string) (const option_def &, void *ctx); |
9d0faba9 PA |
90 | } |
91 | var_address; | |
92 | ||
93 | /* Pointer to null terminated list of enumerated values (like argv). | |
94 | Only used by var_enum options. */ | |
95 | const char *const *enums = nullptr; | |
96 | ||
97 | /* True if the option takes an argument. */ | |
98 | bool have_argument = true; | |
99 | ||
100 | /* The "show" callback to use in the associated "show" command. | |
101 | E.g., "show print elements". */ | |
102 | show_value_ftype *show_cmd_cb; | |
103 | ||
104 | /* The set/show/help strings. These are shown in both the help of | |
105 | commands that use the option group this option belongs to (e.g., | |
106 | "help print"), and in the associated commands (e.g., "set/show | |
107 | print elements", "help set print elements"). */ | |
108 | const char *set_doc; | |
109 | const char *show_doc; | |
110 | const char *help_doc; | |
111 | ||
112 | /* Convenience method that returns THIS as an option_def. Useful | |
113 | when you're putting an option_def subclass in an option_def | |
114 | array_view. */ | |
115 | const option_def &def () const | |
116 | { | |
117 | return *this; | |
118 | } | |
119 | }; | |
120 | ||
121 | namespace detail | |
122 | { | |
123 | ||
124 | /* Get the address of the option's value, cast to the right type. | |
125 | RetType is the restored type of the variable, and Context is the | |
126 | restored type of the context pointer. */ | |
127 | template<typename RetType, typename Context> | |
128 | static inline RetType * | |
129 | get_var_address (const option_def &option, void *ctx) | |
130 | { | |
131 | using unerased_ftype = RetType *(Context *); | |
132 | unerased_ftype *fun = (unerased_ftype *) option.erased_get_var_address; | |
133 | return fun ((Context *) ctx); | |
134 | } | |
135 | ||
136 | /* Convenience identity helper that just returns SELF. */ | |
137 | ||
138 | template<typename T> | |
139 | static T * | |
140 | return_self (T *self) | |
141 | { | |
142 | return self; | |
143 | } | |
144 | ||
145 | } /* namespace detail */ | |
146 | ||
147 | /* Follows the definitions of the option types that client code should | |
148 | define. Note that objects of these types are placed in option_def | |
149 | arrays, by design, so they must not have data fields of their | |
150 | own. */ | |
151 | ||
152 | /* A var_boolean command line option. */ | |
153 | ||
154 | template<typename Context> | |
155 | struct boolean_option_def : option_def | |
156 | { | |
157 | boolean_option_def (const char *long_option_, | |
491144b5 | 158 | bool *(*get_var_address_cb_) (Context *), |
9d0faba9 PA |
159 | show_value_ftype *show_cmd_cb_, |
160 | const char *set_doc_, | |
161 | const char *show_doc_ = nullptr, | |
162 | const char *help_doc_ = nullptr) | |
163 | : option_def (long_option_, var_boolean, | |
164 | (erased_get_var_address_ftype *) get_var_address_cb_, | |
165 | show_cmd_cb_, | |
166 | set_doc_, show_doc_, help_doc_) | |
167 | { | |
491144b5 | 168 | var_address.boolean = detail::get_var_address<bool, Context>; |
9d0faba9 PA |
169 | } |
170 | }; | |
171 | ||
172 | /* A flag command line option. This is a var_boolean option under the | |
173 | hood, but unlike boolean options, flag options don't take an on/off | |
174 | argument. */ | |
175 | ||
491144b5 | 176 | template<typename Context = bool> |
9d0faba9 PA |
177 | struct flag_option_def : boolean_option_def<Context> |
178 | { | |
179 | flag_option_def (const char *long_option_, | |
491144b5 | 180 | bool *(*var_address_cb_) (Context *), |
9d0faba9 PA |
181 | const char *set_doc_, |
182 | const char *help_doc_ = nullptr) | |
183 | : boolean_option_def<Context> (long_option_, | |
184 | var_address_cb_, | |
185 | NULL, | |
186 | set_doc_, NULL, help_doc_) | |
187 | { | |
188 | this->have_argument = false; | |
189 | } | |
190 | ||
191 | flag_option_def (const char *long_option_, | |
192 | const char *set_doc_, | |
193 | const char *help_doc_ = nullptr) | |
194 | : boolean_option_def<Context> (long_option_, | |
195 | gdb::option::detail::return_self, | |
196 | NULL, | |
197 | set_doc_, nullptr, help_doc_) | |
198 | { | |
199 | this->have_argument = false; | |
200 | } | |
201 | }; | |
202 | ||
203 | /* A var_uinteger command line option. */ | |
204 | ||
205 | template<typename Context> | |
206 | struct uinteger_option_def : option_def | |
207 | { | |
208 | uinteger_option_def (const char *long_option_, | |
209 | unsigned int *(*get_var_address_cb_) (Context *), | |
210 | show_value_ftype *show_cmd_cb_, | |
211 | const char *set_doc_, | |
212 | const char *show_doc_ = nullptr, | |
213 | const char *help_doc_ = nullptr) | |
214 | : option_def (long_option_, var_uinteger, | |
215 | (erased_get_var_address_ftype *) get_var_address_cb_, | |
216 | show_cmd_cb_, | |
217 | set_doc_, show_doc_, help_doc_) | |
218 | { | |
219 | var_address.uinteger = detail::get_var_address<unsigned int, Context>; | |
220 | } | |
221 | }; | |
222 | ||
223 | /* A var_zuinteger_unlimited command line option. */ | |
224 | ||
225 | template<typename Context> | |
226 | struct zuinteger_unlimited_option_def : option_def | |
227 | { | |
228 | zuinteger_unlimited_option_def (const char *long_option_, | |
229 | int *(*get_var_address_cb_) (Context *), | |
230 | show_value_ftype *show_cmd_cb_, | |
231 | const char *set_doc_, | |
232 | const char *show_doc_ = nullptr, | |
233 | const char *help_doc_ = nullptr) | |
234 | : option_def (long_option_, var_zuinteger_unlimited, | |
235 | (erased_get_var_address_ftype *) get_var_address_cb_, | |
236 | show_cmd_cb_, | |
237 | set_doc_, show_doc_, help_doc_) | |
238 | { | |
239 | var_address.integer = detail::get_var_address<int, Context>; | |
240 | } | |
241 | }; | |
242 | ||
243 | /* An var_enum command line option. */ | |
244 | ||
245 | template<typename Context> | |
246 | struct enum_option_def : option_def | |
247 | { | |
248 | enum_option_def (const char *long_option_, | |
249 | const char *const *enumlist, | |
250 | const char **(*get_var_address_cb_) (Context *), | |
251 | show_value_ftype *show_cmd_cb_, | |
252 | const char *set_doc_, | |
253 | const char *show_doc_ = nullptr, | |
254 | const char *help_doc_ = nullptr) | |
255 | : option_def (long_option_, var_enum, | |
256 | (erased_get_var_address_ftype *) get_var_address_cb_, | |
257 | show_cmd_cb_, | |
258 | set_doc_, show_doc_, help_doc_) | |
259 | { | |
260 | var_address.enumeration = detail::get_var_address<const char *, Context>; | |
261 | this->enums = enumlist; | |
262 | } | |
263 | }; | |
264 | ||
3d9be6f5 PA |
265 | /* A var_string command line option. */ |
266 | ||
267 | template<typename Context> | |
268 | struct string_option_def : option_def | |
269 | { | |
270 | string_option_def (const char *long_option_, | |
271 | char **(*get_var_address_cb_) (Context *), | |
272 | show_value_ftype *show_cmd_cb_, | |
273 | const char *set_doc_, | |
274 | const char *show_doc_ = nullptr, | |
275 | const char *help_doc_ = nullptr) | |
276 | : option_def (long_option_, var_string, | |
277 | (erased_get_var_address_ftype *) get_var_address_cb_, | |
278 | show_cmd_cb_, | |
279 | set_doc_, show_doc_, help_doc_) | |
280 | { | |
281 | var_address.enumeration = detail::get_var_address<const char *, Context>; | |
282 | } | |
283 | }; | |
284 | ||
9d0faba9 PA |
285 | /* A group of options that all share the same context pointer to pass |
286 | to the options' get-current-value callbacks. */ | |
287 | struct option_def_group | |
288 | { | |
289 | /* The list of options. */ | |
290 | gdb::array_view<const option_def> options; | |
291 | ||
292 | /* The context pointer to pass to the options' get-current-value | |
293 | callbacks. */ | |
294 | void *ctx; | |
295 | }; | |
296 | ||
297 | /* Modes of operation for process_options. */ | |
298 | enum process_options_mode | |
299 | { | |
300 | /* In this mode, options are only processed if we find a "--" | |
301 | delimiter. Throws an error if unknown options are found. */ | |
302 | PROCESS_OPTIONS_REQUIRE_DELIMITER, | |
303 | ||
304 | /* In this mode, a "--" delimiter is not required. Throws an error | |
305 | if unknown options are found, regardless of whether a delimiter | |
306 | is present. */ | |
307 | PROCESS_OPTIONS_UNKNOWN_IS_ERROR, | |
308 | ||
309 | /* In this mode, a "--" delimiter is not required. If an unknown | |
310 | option is found, assume it is the command's argument/operand. */ | |
311 | PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, | |
312 | }; | |
313 | ||
314 | /* Process ARGS, using OPTIONS_GROUP as valid options. Returns true | |
315 | if the string has been fully parsed and there are no operands to | |
316 | handle by the caller. Return false if options were parsed, and | |
317 | *ARGS now points at the first operand. */ | |
318 | extern bool process_options | |
319 | (const char **args, | |
320 | process_options_mode mode, | |
321 | gdb::array_view<const option_def_group> options_group); | |
322 | ||
323 | /* Complete ARGS on options listed by OPTIONS_GROUP. Returns true if | |
324 | the string has been fully parsed and there are no operands to | |
325 | handle by the caller. Return false if options were parsed, and | |
326 | *ARGS now points at the first operand. */ | |
327 | extern bool complete_options | |
328 | (completion_tracker &tracker, | |
329 | const char **args, | |
330 | process_options_mode mode, | |
331 | gdb::array_view<const option_def_group> options_group); | |
332 | ||
333 | /* Complete on all options listed by OPTIONS_GROUP. */ | |
334 | extern void | |
335 | complete_on_all_options (completion_tracker &tracker, | |
336 | gdb::array_view<const option_def_group> options_group); | |
337 | ||
338 | /* Return a string with the result of replacing %OPTIONS% in HELP_TMLP | |
339 | with an auto-generated "help" string fragment for all the options | |
340 | in OPTIONS_GROUP. */ | |
341 | extern std::string build_help | |
342 | (const char *help_tmpl, | |
343 | gdb::array_view<const option_def_group> options_group); | |
344 | ||
345 | /* Install set/show commands for options defined in OPTIONS. DATA is | |
346 | a pointer to the structure that holds the data associated with the | |
347 | OPTIONS array. */ | |
348 | extern void add_setshow_cmds_for_options (command_class cmd_class, void *data, | |
349 | gdb::array_view<const option_def> options, | |
350 | struct cmd_list_element **set_list, | |
351 | struct cmd_list_element **show_list); | |
352 | ||
353 | } /* namespace option */ | |
354 | } /* namespace gdb */ | |
355 | ||
356 | #endif /* CLI_OPTION_H */ |