]>
Commit | Line | Data |
---|---|---|
c906108c | 1 | /* Handle lists of commands, their decoding and documentation, for GDB. |
8926118c | 2 | |
d01e8234 | 3 | Copyright (C) 1986-2025 Free Software Foundation, Inc. |
c906108c | 4 | |
c5aa993b JM |
5 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by | |
a9762ec7 | 7 | the Free Software Foundation; either version 3 of the License, or |
c5aa993b | 8 | (at your option) any later version. |
c906108c | 9 | |
c5aa993b JM |
10 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
c906108c | 14 | |
c5aa993b | 15 | You should have received a copy of the GNU General Public License |
a9762ec7 | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
c906108c | 17 | |
c906108c | 18 | #include "symtab.h" |
c906108c | 19 | #include <ctype.h> |
d322d6d6 | 20 | #include "gdbsupport/gdb_regex.h" |
f397e303 | 21 | #include "completer.h" |
8b93c638 | 22 | #include "ui-out.h" |
d318976c FN |
23 | #include "cli/cli-cmds.h" |
24 | #include "cli/cli-decode.h" | |
66d8c862 | 25 | #include "cli/cli-style.h" |
6447969d | 26 | #include "cli/cli-utils.h" |
6b09f134 | 27 | #include <optional> |
b2875cc0 | 28 | |
ebcd3b23 | 29 | /* Prototypes for local functions. */ |
c906108c | 30 | |
6f937416 | 31 | static void undef_cmd_error (const char *, const char *); |
c906108c | 32 | |
c471bdb1 SM |
33 | static cmd_list_element::aliases_list_type delete_cmd |
34 | (const char *name, cmd_list_element **list, cmd_list_element **prehook, | |
35 | cmd_list_element **prehookee, cmd_list_element **posthook, | |
36 | cmd_list_element **posthookee); | |
b05dcbb7 | 37 | |
6f937416 | 38 | static struct cmd_list_element *find_cmd (const char *command, |
a14ed312 KB |
39 | int len, |
40 | struct cmd_list_element *clist, | |
41 | int ignore_help_classes, | |
42 | int *nfound); | |
6837a0a2 | 43 | |
3b3aaacb PW |
44 | static void help_cmd_list (struct cmd_list_element *list, |
45 | enum command_class theclass, | |
46 | bool recurse, | |
47 | struct ui_file *stream); | |
48 | ||
c85871a3 | 49 | static void help_all (struct ui_file *stream); |
6e381ba0 | 50 | |
9ef6d4a1 AB |
51 | static int lookup_cmd_composition_1 (const char *text, |
52 | struct cmd_list_element **alias, | |
53 | struct cmd_list_element **prefix_cmd, | |
54 | struct cmd_list_element **cmd, | |
55 | struct cmd_list_element *cur_list); | |
56 | ||
14b42fc4 SM |
57 | /* Look up a command whose 'subcommands' field is SUBCOMMANDS. Return the |
58 | command if found, otherwise return NULL. */ | |
5b9afe8a YQ |
59 | |
60 | static struct cmd_list_element * | |
14b42fc4 SM |
61 | lookup_cmd_with_subcommands (cmd_list_element **subcommands, |
62 | cmd_list_element *list) | |
5b9afe8a YQ |
63 | { |
64 | struct cmd_list_element *p = NULL; | |
65 | ||
66 | for (p = list; p != NULL; p = p->next) | |
67 | { | |
68 | struct cmd_list_element *q; | |
69 | ||
3d0b3564 | 70 | if (!p->is_prefix ()) |
5b9afe8a | 71 | continue; |
3d0b3564 | 72 | |
14b42fc4 | 73 | else if (p->subcommands == subcommands) |
3f4d92eb PW |
74 | { |
75 | /* If we found an alias, we must return the aliased | |
76 | command. */ | |
1be99b11 | 77 | return p->is_alias () ? p->alias_target : p; |
3f4d92eb | 78 | } |
5b9afe8a | 79 | |
14b42fc4 | 80 | q = lookup_cmd_with_subcommands (subcommands, *(p->subcommands)); |
5b9afe8a YQ |
81 | if (q != NULL) |
82 | return q; | |
83 | } | |
84 | ||
85 | return NULL; | |
86 | } | |
87 | ||
6e381ba0 | 88 | static void |
eccd14b3 | 89 | print_help_for_command (const cmd_list_element &c, |
3b3aaacb | 90 | bool recurse, struct ui_file *stream); |
6e381ba0 | 91 | |
0450cc4c | 92 | static void |
5538b03c | 93 | do_simple_func (const char *args, int from_tty, cmd_list_element *c) |
0450cc4c | 94 | { |
3a553c80 | 95 | c->function.simple_func (args, from_tty); |
0450cc4c TT |
96 | } |
97 | ||
c2252c0d | 98 | static void |
3a553c80 | 99 | set_cmd_simple_func (struct cmd_list_element *cmd, cmd_simple_func_ftype *simple_func) |
0450cc4c | 100 | { |
3a553c80 | 101 | if (simple_func == NULL) |
0450cc4c TT |
102 | cmd->func = NULL; |
103 | else | |
3a553c80 SM |
104 | cmd->func = do_simple_func; |
105 | ||
106 | cmd->function.simple_func = simple_func; | |
9f60d481 AC |
107 | } |
108 | ||
0450cc4c | 109 | int |
3a553c80 | 110 | cmd_simple_func_eq (struct cmd_list_element *cmd, cmd_simple_func_ftype *simple_func) |
0450cc4c | 111 | { |
3a553c80 SM |
112 | return (cmd->func == do_simple_func |
113 | && cmd->function.simple_func == simple_func); | |
0450cc4c TT |
114 | } |
115 | ||
5ba2abeb | 116 | void |
625e8578 | 117 | set_cmd_completer (struct cmd_list_element *cmd, completer_ftype *completer) |
5ba2abeb AC |
118 | { |
119 | cmd->completer = completer; /* Ok. */ | |
120 | } | |
121 | ||
7d793aa9 SDJ |
122 | /* See definition in commands.h. */ |
123 | ||
124 | void | |
125 | set_cmd_completer_handle_brkchars (struct cmd_list_element *cmd, | |
6e1dbf8c | 126 | completer_handle_brkchars_ftype *func) |
7d793aa9 | 127 | { |
6e1dbf8c | 128 | cmd->completer_handle_brkchars = func; |
7d793aa9 SDJ |
129 | } |
130 | ||
652e09d5 TT |
131 | /* See cli-decode.h. */ |
132 | ||
413b49c2 | 133 | std::string |
652e09d5 | 134 | cmd_list_element::prefixname_no_space () const |
413b49c2 | 135 | { |
3d0b3564 | 136 | if (!this->is_prefix ()) |
413b49c2 SM |
137 | /* Not a prefix command. */ |
138 | return ""; | |
139 | ||
140 | std::string prefixname; | |
141 | if (this->prefix != nullptr) | |
652e09d5 TT |
142 | { |
143 | prefixname = this->prefix->prefixname_no_space (); | |
144 | prefixname += " "; | |
145 | } | |
413b49c2 SM |
146 | |
147 | prefixname += this->name; | |
413b49c2 SM |
148 | |
149 | return prefixname; | |
150 | } | |
151 | ||
652e09d5 TT |
152 | /* See cli-decode.h. */ |
153 | ||
154 | std::string | |
155 | cmd_list_element::prefixname () const | |
156 | { | |
157 | std::string result = prefixname_no_space (); | |
158 | if (!result.empty ()) | |
159 | result += " "; | |
160 | return result; | |
161 | } | |
162 | ||
bbea6807 AB |
163 | /* See cli/cli-decode.h. */ |
164 | ||
165 | std::vector<std::string> | |
166 | cmd_list_element::command_components () const | |
167 | { | |
168 | std::vector<std::string> result; | |
169 | ||
170 | if (this->prefix != nullptr) | |
171 | result = this->prefix->command_components (); | |
172 | ||
efe2296b | 173 | result.emplace_back (this->name); |
bbea6807 AB |
174 | return result; |
175 | } | |
176 | ||
c906108c | 177 | /* Add element named NAME. |
bc587a6b | 178 | Space for NAME and DOC must be allocated by the caller. |
a58c8793 | 179 | THECLASS is the top level category into which commands are broken down |
c906108c SS |
180 | for "help" purposes. |
181 | FUN should be the function to execute the command; | |
182 | it will get a character string as argument, with leading | |
183 | and trailing blanks already eliminated. | |
184 | ||
185 | DOC is a documentation string for the command. | |
186 | Its first line should be a complete sentence. | |
187 | It should start with ? for a command that is an abbreviation | |
188 | or with * for a command that most users don't need to know about. | |
189 | ||
ebcd3b23 | 190 | Add this command to command list *LIST. |
c906108c SS |
191 | |
192 | Returns a pointer to the added command (not necessarily the head | |
ebcd3b23 | 193 | of *LIST). */ |
c906108c | 194 | |
0450cc4c TT |
195 | static struct cmd_list_element * |
196 | do_add_cmd (const char *name, enum command_class theclass, | |
197 | const char *doc, struct cmd_list_element **list) | |
c906108c | 198 | { |
e2fc72e2 TT |
199 | struct cmd_list_element *c = new struct cmd_list_element (name, theclass, |
200 | doc); | |
c906108c | 201 | |
b05dcbb7 TT |
202 | /* Turn each alias of the old command into an alias of the new |
203 | command. */ | |
fad6eecd TT |
204 | c->aliases = delete_cmd (name, list, &c->hook_pre, &c->hookee_pre, |
205 | &c->hook_post, &c->hookee_post); | |
c471bdb1 SM |
206 | |
207 | for (cmd_list_element &alias : c->aliases) | |
208 | alias.alias_target = c; | |
209 | ||
fad6eecd TT |
210 | if (c->hook_pre) |
211 | c->hook_pre->hookee_pre = c; | |
c471bdb1 | 212 | |
fad6eecd TT |
213 | if (c->hookee_pre) |
214 | c->hookee_pre->hook_pre = c; | |
c471bdb1 | 215 | |
fad6eecd TT |
216 | if (c->hook_post) |
217 | c->hook_post->hookee_post = c; | |
c471bdb1 | 218 | |
fad6eecd TT |
219 | if (c->hookee_post) |
220 | c->hookee_post->hook_post = c; | |
c906108c | 221 | |
494b7ec9 | 222 | if (*list == NULL || strcmp ((*list)->name, name) >= 0) |
c906108c SS |
223 | { |
224 | c->next = *list; | |
225 | *list = c; | |
226 | } | |
227 | else | |
228 | { | |
c471bdb1 | 229 | cmd_list_element *p = *list; |
494b7ec9 | 230 | while (p->next && strcmp (p->next->name, name) <= 0) |
c5aa993b JM |
231 | { |
232 | p = p->next; | |
233 | } | |
c906108c SS |
234 | c->next = p->next; |
235 | p->next = c; | |
236 | } | |
237 | ||
3f4d92eb PW |
238 | /* Search the prefix cmd of C, and assigns it to C->prefix. |
239 | See also add_prefix_cmd and update_prefix_field_of_prefixed_commands. */ | |
14b42fc4 | 240 | cmd_list_element *prefixcmd = lookup_cmd_with_subcommands (list, cmdlist); |
3f4d92eb PW |
241 | c->prefix = prefixcmd; |
242 | ||
243 | ||
c906108c SS |
244 | return c; |
245 | } | |
246 | ||
0450cc4c TT |
247 | struct cmd_list_element * |
248 | add_cmd (const char *name, enum command_class theclass, | |
249 | const char *doc, struct cmd_list_element **list) | |
250 | { | |
251 | cmd_list_element *result = do_add_cmd (name, theclass, doc, list); | |
252 | result->func = NULL; | |
3a553c80 | 253 | result->function.simple_func = NULL; |
0450cc4c TT |
254 | return result; |
255 | } | |
256 | ||
257 | struct cmd_list_element * | |
258 | add_cmd (const char *name, enum command_class theclass, | |
3a553c80 | 259 | cmd_simple_func_ftype *fun, |
0450cc4c TT |
260 | const char *doc, struct cmd_list_element **list) |
261 | { | |
262 | cmd_list_element *result = do_add_cmd (name, theclass, doc, list); | |
3a553c80 | 263 | set_cmd_simple_func (result, fun); |
0450cc4c TT |
264 | return result; |
265 | } | |
266 | ||
f67ffa6a AB |
267 | /* Add an element with a suppress notification to the LIST of commands. */ |
268 | ||
269 | struct cmd_list_element * | |
270 | add_cmd_suppress_notification (const char *name, enum command_class theclass, | |
3a553c80 | 271 | cmd_simple_func_ftype *fun, const char *doc, |
f67ffa6a | 272 | struct cmd_list_element **list, |
f36c8918 | 273 | bool *suppress_notification) |
f67ffa6a AB |
274 | { |
275 | struct cmd_list_element *element; | |
276 | ||
277 | element = add_cmd (name, theclass, fun, doc, list); | |
278 | element->suppress_notification = suppress_notification; | |
279 | ||
280 | return element; | |
281 | } | |
282 | ||
283 | ||
56382845 | 284 | /* Deprecates a command CMD. |
ebcd3b23 MS |
285 | REPLACEMENT is the name of the command which should be used in |
286 | place of this command, or NULL if no such command exists. | |
56382845 FN |
287 | |
288 | This function does not check to see if command REPLACEMENT exists | |
ebcd3b23 MS |
289 | since gdb may not have gotten around to adding REPLACEMENT when |
290 | this function is called. | |
56382845 FN |
291 | |
292 | Returns a pointer to the deprecated command. */ | |
293 | ||
294 | struct cmd_list_element * | |
429e55ea | 295 | deprecate_cmd (struct cmd_list_element *cmd, const char *replacement) |
56382845 | 296 | { |
1f2bdf09 TT |
297 | cmd->cmd_deprecated = 1; |
298 | cmd->deprecated_warn_user = 1; | |
56382845 FN |
299 | |
300 | if (replacement != NULL) | |
301 | cmd->replacement = replacement; | |
302 | else | |
303 | cmd->replacement = NULL; | |
304 | ||
305 | return cmd; | |
306 | } | |
307 | ||
c906108c | 308 | struct cmd_list_element * |
99858724 | 309 | add_alias_cmd (const char *name, cmd_list_element *target, |
21873064 YQ |
310 | enum command_class theclass, int abbrev_flag, |
311 | struct cmd_list_element **list) | |
c906108c | 312 | { |
99858724 | 313 | gdb_assert (target != nullptr); |
c906108c | 314 | |
99858724 | 315 | struct cmd_list_element *c = add_cmd (name, theclass, target->doc, list); |
5bc81a00 | 316 | |
99858724 SM |
317 | /* If TARGET->DOC can be freed, we should make another copy. */ |
318 | if (target->doc_allocated) | |
5bc81a00 | 319 | { |
99858724 | 320 | c->doc = xstrdup (target->doc); |
1f2bdf09 | 321 | c->doc_allocated = 1; |
5bc81a00 | 322 | } |
9f60d481 | 323 | /* NOTE: Both FUNC and all the FUNCTIONs need to be copied. */ |
99858724 SM |
324 | c->func = target->func; |
325 | c->function = target->function; | |
326 | c->subcommands = target->subcommands; | |
327 | c->allow_unknown = target->allow_unknown; | |
c906108c | 328 | c->abbrev_flag = abbrev_flag; |
99858724 | 329 | c->alias_target = target; |
c471bdb1 | 330 | target->aliases.push_front (*c); |
5b9afe8a | 331 | |
c906108c SS |
332 | return c; |
333 | } | |
334 | ||
3f4d92eb PW |
335 | /* Update the prefix field of all sub-commands of the prefix command C. |
336 | We must do this when a prefix command is defined as the GDB init sequence | |
337 | does not guarantee that a prefix command is created before its sub-commands. | |
338 | For example, break-catch-sig.c initialization runs before breakpoint.c | |
339 | initialization, but it is breakpoint.c that creates the "catch" command used | |
340 | by the "catch signal" command created by break-catch-sig.c. */ | |
341 | ||
342 | static void | |
343 | update_prefix_field_of_prefixed_commands (struct cmd_list_element *c) | |
344 | { | |
14b42fc4 | 345 | for (cmd_list_element *p = *c->subcommands; p != NULL; p = p->next) |
3f4d92eb PW |
346 | { |
347 | p->prefix = c; | |
348 | ||
349 | /* We must recursively update the prefix field to cover | |
350 | e.g. 'info auto-load libthread-db' where the creation | |
351 | order was: | |
dda83cd7 SM |
352 | libthread-db |
353 | auto-load | |
354 | info | |
3f4d92eb | 355 | In such a case, when 'auto-load' was created by do_add_cmd, |
dda83cd7 | 356 | the 'libthread-db' prefix field could not be updated, as the |
3f4d92eb | 357 | 'auto-load' command was not yet reachable by |
14b42fc4 | 358 | lookup_cmd_for_subcommands (list, cmdlist) |
3f4d92eb | 359 | that searches from the top level 'cmdlist'. */ |
3d0b3564 | 360 | if (p->is_prefix ()) |
3f4d92eb PW |
361 | update_prefix_field_of_prefixed_commands (p); |
362 | } | |
363 | } | |
364 | ||
365 | ||
ebcd3b23 MS |
366 | /* Like add_cmd but adds an element for a command prefix: a name that |
367 | should be followed by a subcommand to be looked up in another | |
14b42fc4 | 368 | command list. SUBCOMMANDS should be the address of the variable |
ebcd3b23 | 369 | containing that list. */ |
c906108c SS |
370 | |
371 | struct cmd_list_element * | |
fe978cb0 | 372 | add_prefix_cmd (const char *name, enum command_class theclass, |
3a553c80 | 373 | cmd_simple_func_ftype *fun, |
14b42fc4 | 374 | const char *doc, struct cmd_list_element **subcommands, |
2f822da5 | 375 | int allow_unknown, struct cmd_list_element **list) |
c906108c | 376 | { |
fe978cb0 | 377 | struct cmd_list_element *c = add_cmd (name, theclass, fun, doc, list); |
cdb27c12 | 378 | |
14b42fc4 | 379 | c->subcommands = subcommands; |
c906108c | 380 | c->allow_unknown = allow_unknown; |
5b9afe8a | 381 | |
3f4d92eb PW |
382 | /* Now that prefix command C is defined, we need to set the prefix field |
383 | of all prefixed commands that were defined before C itself was defined. */ | |
384 | update_prefix_field_of_prefixed_commands (c); | |
5b9afe8a | 385 | |
c906108c SS |
386 | return c; |
387 | } | |
388 | ||
0743fc83 TT |
389 | /* A helper function for add_basic_prefix_cmd. This is a command |
390 | function that just forwards to help_list. */ | |
391 | ||
392 | static void | |
393 | do_prefix_cmd (const char *args, int from_tty, struct cmd_list_element *c) | |
394 | { | |
395 | /* Look past all aliases. */ | |
1be99b11 | 396 | while (c->is_alias ()) |
99858724 | 397 | c = c->alias_target; |
0743fc83 | 398 | |
652e09d5 | 399 | help_list (*c->subcommands, c->prefixname_no_space ().c_str (), |
2f822da5 | 400 | all_commands, gdb_stdout); |
0743fc83 TT |
401 | } |
402 | ||
403 | /* See command.h. */ | |
404 | ||
405 | struct cmd_list_element * | |
406 | add_basic_prefix_cmd (const char *name, enum command_class theclass, | |
14b42fc4 | 407 | const char *doc, struct cmd_list_element **subcommands, |
2f822da5 | 408 | int allow_unknown, struct cmd_list_element **list) |
0743fc83 TT |
409 | { |
410 | struct cmd_list_element *cmd = add_prefix_cmd (name, theclass, nullptr, | |
14b42fc4 | 411 | doc, subcommands, |
0743fc83 | 412 | allow_unknown, list); |
5538b03c | 413 | cmd->func = do_prefix_cmd; |
0743fc83 TT |
414 | return cmd; |
415 | } | |
416 | ||
417 | /* A helper function for add_show_prefix_cmd. This is a command | |
418 | function that just forwards to cmd_show_list. */ | |
419 | ||
420 | static void | |
421 | do_show_prefix_cmd (const char *args, int from_tty, struct cmd_list_element *c) | |
422 | { | |
14b42fc4 | 423 | cmd_show_list (*c->subcommands, from_tty); |
0743fc83 TT |
424 | } |
425 | ||
426 | /* See command.h. */ | |
427 | ||
428 | struct cmd_list_element * | |
429 | add_show_prefix_cmd (const char *name, enum command_class theclass, | |
14b42fc4 | 430 | const char *doc, struct cmd_list_element **subcommands, |
2f822da5 | 431 | int allow_unknown, struct cmd_list_element **list) |
0743fc83 TT |
432 | { |
433 | struct cmd_list_element *cmd = add_prefix_cmd (name, theclass, nullptr, | |
14b42fc4 | 434 | doc, subcommands, |
0743fc83 | 435 | allow_unknown, list); |
5538b03c | 436 | cmd->func = do_show_prefix_cmd; |
0743fc83 TT |
437 | return cmd; |
438 | } | |
439 | ||
f54bdb6d SM |
440 | /* See command.h. */ |
441 | ||
442 | set_show_commands | |
443 | add_setshow_prefix_cmd (const char *name, command_class theclass, | |
444 | const char *set_doc, const char *show_doc, | |
445 | cmd_list_element **set_subcommands_list, | |
446 | cmd_list_element **show_subcommands_list, | |
447 | cmd_list_element **set_list, | |
448 | cmd_list_element **show_list) | |
449 | { | |
450 | set_show_commands cmds; | |
451 | ||
452 | cmds.set = add_basic_prefix_cmd (name, theclass, set_doc, | |
453 | set_subcommands_list, 0, | |
454 | set_list); | |
455 | cmds.show = add_show_prefix_cmd (name, theclass, show_doc, | |
456 | show_subcommands_list, 0, | |
457 | show_list); | |
458 | ||
459 | return cmds; | |
460 | } | |
461 | ||
f67ffa6a AB |
462 | /* Like ADD_PREFIX_CMD but sets the suppress_notification pointer on the |
463 | new command list element. */ | |
464 | ||
465 | struct cmd_list_element * | |
466 | add_prefix_cmd_suppress_notification | |
dda83cd7 | 467 | (const char *name, enum command_class theclass, |
3a553c80 | 468 | cmd_simple_func_ftype *fun, |
14b42fc4 | 469 | const char *doc, struct cmd_list_element **subcommands, |
2f822da5 | 470 | int allow_unknown, struct cmd_list_element **list, |
f36c8918 | 471 | bool *suppress_notification) |
f67ffa6a AB |
472 | { |
473 | struct cmd_list_element *element | |
14b42fc4 | 474 | = add_prefix_cmd (name, theclass, fun, doc, subcommands, |
2f822da5 | 475 | allow_unknown, list); |
f67ffa6a AB |
476 | element->suppress_notification = suppress_notification; |
477 | return element; | |
478 | } | |
479 | ||
ebcd3b23 | 480 | /* Like add_prefix_cmd but sets the abbrev_flag on the new command. */ |
c5aa993b | 481 | |
c906108c | 482 | struct cmd_list_element * |
fe978cb0 | 483 | add_abbrev_prefix_cmd (const char *name, enum command_class theclass, |
3a553c80 | 484 | cmd_simple_func_ftype *fun, const char *doc, |
14b42fc4 | 485 | struct cmd_list_element **subcommands, |
af1c1752 | 486 | int allow_unknown, struct cmd_list_element **list) |
c906108c | 487 | { |
fe978cb0 | 488 | struct cmd_list_element *c = add_cmd (name, theclass, fun, doc, list); |
cdb27c12 | 489 | |
14b42fc4 | 490 | c->subcommands = subcommands; |
c906108c SS |
491 | c->allow_unknown = allow_unknown; |
492 | c->abbrev_flag = 1; | |
493 | return c; | |
494 | } | |
495 | ||
3a553c80 | 496 | /* This is an empty "simple func". */ |
c906108c | 497 | void |
eb7c454d | 498 | not_just_help_class_command (const char *args, int from_tty) |
c906108c SS |
499 | { |
500 | } | |
501 | ||
5538b03c | 502 | /* This is an empty cmd func. */ |
c906108c SS |
503 | |
504 | static void | |
5538b03c | 505 | empty_func (const char *args, int from_tty, cmd_list_element *c) |
c906108c SS |
506 | { |
507 | } | |
508 | ||
b2875cc0 | 509 | /* Add element named NAME to command list LIST (the list for set/show |
c906108c | 510 | or some sublist thereof). |
b2875cc0 | 511 | TYPE is set_cmd or show_cmd. |
a58c8793 | 512 | THECLASS is as in add_cmd. |
c906108c | 513 | VAR_TYPE is the kind of thing we are setting. |
7aeb03e2 MR |
514 | EXTRA_LITERALS if non-NULL define extra literals to be accepted in lieu of |
515 | a number for integer variables. | |
0e38c6ff MR |
516 | ARGS is a pre-validated type-erased reference to the variable being |
517 | controlled by this command. | |
c906108c SS |
518 | DOC is the documentation string. */ |
519 | ||
b2875cc0 | 520 | static struct cmd_list_element * |
6f937416 | 521 | add_set_or_show_cmd (const char *name, |
b2875cc0 | 522 | enum cmd_types type, |
fe978cb0 | 523 | enum command_class theclass, |
b2875cc0 | 524 | var_types var_type, |
7aeb03e2 | 525 | const literal_def *extra_literals, |
1d7fe7f0 | 526 | const setting::erased_args &arg, |
1947513d | 527 | const char *doc, |
b2875cc0 | 528 | struct cmd_list_element **list) |
c906108c | 529 | { |
0450cc4c | 530 | struct cmd_list_element *c = add_cmd (name, theclass, doc, list); |
cdb27c12 | 531 | |
b2875cc0 AC |
532 | gdb_assert (type == set_cmd || type == show_cmd); |
533 | c->type = type; | |
7aeb03e2 | 534 | c->var.emplace (var_type, extra_literals, arg); |
1d7fe7f0 | 535 | |
e00d1dc8 | 536 | /* This needs to be something besides NULL so that this isn't |
c906108c | 537 | treated as a help class. */ |
5538b03c | 538 | c->func = empty_func; |
c906108c SS |
539 | return c; |
540 | } | |
541 | ||
3cfe8022 | 542 | /* Add element named NAME to both command lists SET_LIST and SHOW_LIST. |
a58c8793 | 543 | THECLASS is as in add_cmd. VAR_TYPE is the kind of thing we are |
7aeb03e2 MR |
544 | setting. EXTRA_LITERALS if non-NULL define extra literals to be |
545 | accepted in lieu of a number for integer variables. ARGS is a | |
546 | pre-validated type-erased reference to the variable being controlled | |
547 | by this command. SET_FUNC and SHOW_FUNC are the callback functions | |
548 | (if non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the documentation | |
549 | strings. | |
e707bbc2 | 550 | |
af7f8f52 SM |
551 | Return the newly created set and show commands. */ |
552 | ||
553 | static set_show_commands | |
1d7fe7f0 LS |
554 | add_setshow_cmd_full_erased (const char *name, |
555 | enum command_class theclass, | |
556 | var_types var_type, | |
7aeb03e2 | 557 | const literal_def *extra_literals, |
1d7fe7f0 LS |
558 | const setting::erased_args &args, |
559 | const char *set_doc, const char *show_doc, | |
560 | const char *help_doc, | |
561 | cmd_func_ftype *set_func, | |
562 | show_value_ftype *show_func, | |
563 | struct cmd_list_element **set_list, | |
564 | struct cmd_list_element **show_list) | |
e707bbc2 AC |
565 | { |
566 | struct cmd_list_element *set; | |
567 | struct cmd_list_element *show; | |
8579fd13 AB |
568 | gdb::unique_xmalloc_ptr<char> full_set_doc; |
569 | gdb::unique_xmalloc_ptr<char> full_show_doc; | |
be7d7357 AC |
570 | |
571 | if (help_doc != NULL) | |
572 | { | |
573 | full_set_doc = xstrprintf ("%s\n%s", set_doc, help_doc); | |
574 | full_show_doc = xstrprintf ("%s\n%s", show_doc, help_doc); | |
575 | } | |
576 | else | |
577 | { | |
8579fd13 AB |
578 | full_set_doc = make_unique_xstrdup (set_doc); |
579 | full_show_doc = make_unique_xstrdup (show_doc); | |
be7d7357 | 580 | } |
7aeb03e2 MR |
581 | set = add_set_or_show_cmd (name, set_cmd, theclass, var_type, |
582 | extra_literals, args, | |
8579fd13 | 583 | full_set_doc.release (), set_list); |
1f2bdf09 | 584 | set->doc_allocated = 1; |
5bc81a00 | 585 | |
e707bbc2 | 586 | if (set_func != NULL) |
5538b03c | 587 | set->func = set_func; |
5b9afe8a | 588 | |
7aeb03e2 MR |
589 | show = add_set_or_show_cmd (name, show_cmd, theclass, var_type, |
590 | extra_literals, args, | |
8579fd13 | 591 | full_show_doc.release (), show_list); |
1f2bdf09 | 592 | show->doc_allocated = 1; |
08546159 | 593 | show->show_value_func = show_func; |
597bf39d PA |
594 | /* Disable the default symbol completer. Doesn't make much sense |
595 | for the "show" command to complete on anything. */ | |
596 | set_cmd_completer (show, nullptr); | |
9f064c95 | 597 | |
af7f8f52 | 598 | return {set, show}; |
9f064c95 TT |
599 | } |
600 | ||
7aeb03e2 MR |
601 | /* Completes on integer commands that support extra literals. */ |
602 | ||
603 | static void | |
604 | integer_literals_completer (struct cmd_list_element *c, | |
605 | completion_tracker &tracker, | |
606 | const char *text, const char *word) | |
607 | { | |
608 | const literal_def *extra_literals = c->var->extra_literals (); | |
609 | ||
610 | if (*text == '\0') | |
611 | { | |
612 | tracker.add_completion (make_unique_xstrdup ("NUMBER")); | |
613 | for (const literal_def *l = extra_literals; | |
614 | l->literal != nullptr; | |
615 | l++) | |
616 | tracker.add_completion (make_unique_xstrdup (l->literal)); | |
617 | } | |
618 | else | |
619 | for (const literal_def *l = extra_literals; | |
620 | l->literal != nullptr; | |
621 | l++) | |
622 | if (startswith (l->literal, text)) | |
623 | tracker.add_completion (make_unique_xstrdup (l->literal)); | |
624 | } | |
625 | ||
439ee793 MR |
626 | /* Add element named NAME to both command lists SET_LIST and SHOW_LIST. |
627 | THECLASS is as in add_cmd. VAR_TYPE is the kind of thing we are | |
628 | setting. VAR is address of the variable being controlled by this | |
7aeb03e2 MR |
629 | command. EXTRA_LITERALS if non-NULL define extra literals to be |
630 | accepted in lieu of a number for integer variables. If nullptr is | |
631 | given as VAR, then both SET_SETTING_FUNC and GET_SETTING_FUNC must | |
632 | be provided. SET_SETTING_FUNC and GET_SETTING_FUNC are callbacks | |
633 | used to access and modify the underlying property, whatever its | |
634 | storage is. SET_FUNC and SHOW_FUNC are the callback functions | |
635 | (if non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the | |
439ee793 MR |
636 | documentation strings. |
637 | ||
638 | Return the newly created set and show commands. */ | |
639 | ||
1d7fe7f0 LS |
640 | template<typename T> |
641 | static set_show_commands | |
642 | add_setshow_cmd_full (const char *name, | |
643 | enum command_class theclass, | |
644 | var_types var_type, T *var, | |
7aeb03e2 | 645 | const literal_def *extra_literals, |
1d7fe7f0 LS |
646 | const char *set_doc, const char *show_doc, |
647 | const char *help_doc, | |
fcef6471 SM |
648 | typename setting_func_types<T>::set set_setting_func, |
649 | typename setting_func_types<T>::get get_setting_func, | |
1d7fe7f0 LS |
650 | cmd_func_ftype *set_func, |
651 | show_value_ftype *show_func, | |
652 | struct cmd_list_element **set_list, | |
653 | struct cmd_list_element **show_list) | |
654 | { | |
655 | auto erased_args | |
70299171 LS |
656 | = setting::erase_args (var_type, var, |
657 | set_setting_func, get_setting_func); | |
7aeb03e2 MR |
658 | auto cmds = add_setshow_cmd_full_erased (name, |
659 | theclass, | |
660 | var_type, extra_literals, | |
661 | erased_args, | |
662 | set_doc, show_doc, | |
663 | help_doc, | |
664 | set_func, | |
665 | show_func, | |
666 | set_list, | |
667 | show_list); | |
668 | ||
669 | if (extra_literals != nullptr) | |
670 | set_cmd_completer (cmds.set, integer_literals_completer); | |
1d7fe7f0 | 671 | |
7aeb03e2 MR |
672 | return cmds; |
673 | } | |
674 | ||
675 | /* Same as above but omitting EXTRA_LITERALS. */ | |
676 | ||
677 | template<typename T> | |
678 | static set_show_commands | |
679 | add_setshow_cmd_full (const char *name, | |
680 | enum command_class theclass, | |
681 | var_types var_type, T *var, | |
682 | const char *set_doc, const char *show_doc, | |
683 | const char *help_doc, | |
684 | typename setting_func_types<T>::set set_setting_func, | |
685 | typename setting_func_types<T>::get get_setting_func, | |
686 | cmd_func_ftype *set_func, | |
687 | show_value_ftype *show_func, | |
688 | struct cmd_list_element **set_list, | |
689 | struct cmd_list_element **show_list) | |
690 | { | |
691 | return add_setshow_cmd_full (name, theclass, var_type, var, nullptr, | |
692 | set_doc, show_doc, help_doc, | |
693 | set_setting_func, get_setting_func, | |
694 | set_func, show_func, set_list, show_list); | |
1d7fe7f0 LS |
695 | } |
696 | ||
1b295c3d | 697 | /* Add element named NAME to command list LIST (the list for set or |
a58c8793 | 698 | some sublist thereof). THECLASS is as in add_cmd. ENUMLIST is a list |
1b295c3d AC |
699 | of strings which may follow NAME. VAR is address of the variable |
700 | which will contain the matching string (from ENUMLIST). */ | |
701 | ||
af7f8f52 | 702 | set_show_commands |
6f937416 | 703 | add_setshow_enum_cmd (const char *name, |
fe978cb0 | 704 | enum command_class theclass, |
40478521 | 705 | const char *const *enumlist, |
1b295c3d AC |
706 | const char **var, |
707 | const char *set_doc, | |
708 | const char *show_doc, | |
709 | const char *help_doc, | |
5538b03c | 710 | cmd_func_ftype *set_func, |
08546159 | 711 | show_value_ftype *show_func, |
1b295c3d | 712 | struct cmd_list_element **set_list, |
4c0ba02a | 713 | struct cmd_list_element **show_list) |
1b295c3d | 714 | { |
dedb7102 TT |
715 | /* We require *VAR to be initialized before this call, and |
716 | furthermore it must be == to one of the values in ENUMLIST. */ | |
717 | gdb_assert (var != nullptr && *var != nullptr); | |
718 | for (int i = 0; ; ++i) | |
719 | { | |
720 | gdb_assert (enumlist[i] != nullptr); | |
721 | if (*var == enumlist[i]) | |
722 | break; | |
723 | } | |
724 | ||
af7f8f52 | 725 | set_show_commands commands |
1d7fe7f0 LS |
726 | = add_setshow_cmd_full<const char *> (name, theclass, var_enum, var, |
727 | set_doc, show_doc, help_doc, | |
70299171 LS |
728 | nullptr, nullptr, set_func, |
729 | show_func, set_list, show_list); | |
af7f8f52 | 730 | commands.set->enums = enumlist; |
af7f8f52 | 731 | return commands; |
1b295c3d AC |
732 | } |
733 | ||
70299171 LS |
734 | /* Same as above but using a getter and a setter function instead of a pointer |
735 | to a global storage buffer. */ | |
736 | ||
737 | set_show_commands | |
738 | add_setshow_enum_cmd (const char *name, command_class theclass, | |
739 | const char *const *enumlist, const char *set_doc, | |
740 | const char *show_doc, const char *help_doc, | |
fcef6471 SM |
741 | setting_func_types<const char *>::set set_func, |
742 | setting_func_types<const char *>::get get_func, | |
70299171 LS |
743 | show_value_ftype *show_func, |
744 | cmd_list_element **set_list, | |
745 | cmd_list_element **show_list) | |
746 | { | |
747 | auto cmds = add_setshow_cmd_full<const char *> (name, theclass, var_enum, | |
748 | nullptr, set_doc, show_doc, | |
749 | help_doc, set_func, get_func, | |
750 | nullptr, show_func, set_list, | |
751 | show_list); | |
752 | ||
753 | cmds.set->enums = enumlist; | |
754 | ||
755 | return cmds; | |
756 | } | |
757 | ||
6447969d AP |
758 | /* See cli-decode.h. */ |
759 | ||
760 | void | |
761 | complete_on_color (completion_tracker &tracker, | |
762 | const char *text, const char *word) | |
763 | { | |
764 | complete_on_enum (tracker, ui_file_style::basic_color_enums.data (), | |
765 | text, word); | |
766 | if (*text == '\0') | |
767 | { | |
768 | /* Convenience to let the user know what the option | |
769 | can accept. Note there's no common prefix between | |
770 | the strings on purpose, so that complete_on_enum doesn't do | |
771 | a partial match. */ | |
772 | tracker.add_completion (make_unique_xstrdup ("NUMBER")); | |
773 | tracker.add_completion (make_unique_xstrdup ("#RRGGBB")); | |
774 | } | |
775 | } | |
776 | ||
777 | /* Completer used in color commands. */ | |
778 | ||
779 | static void | |
780 | color_completer (struct cmd_list_element *ignore, | |
781 | completion_tracker &tracker, | |
782 | const char *text, const char *word) | |
783 | { | |
784 | complete_on_color (tracker, text, word); | |
785 | } | |
786 | ||
787 | ||
788 | /* Add element named NAME to command list LIST (the list for set or | |
789 | some sublist thereof). CLASS is as in add_cmd. VAR is address | |
790 | of the variable which will contain the color. */ | |
791 | ||
792 | set_show_commands | |
793 | add_setshow_color_cmd (const char *name, | |
794 | enum command_class theclass, | |
795 | ui_file_style::color *var, | |
796 | const char *set_doc, | |
797 | const char *show_doc, | |
798 | const char *help_doc, | |
799 | cmd_func_ftype *set_func, | |
800 | show_value_ftype *show_func, | |
801 | struct cmd_list_element **set_list, | |
802 | struct cmd_list_element **show_list) | |
803 | { | |
804 | set_show_commands commands = add_setshow_cmd_full<ui_file_style::color> | |
805 | (name, theclass, var_color, var, | |
806 | set_doc, show_doc, help_doc, | |
807 | nullptr, nullptr, set_func, show_func, | |
808 | set_list, show_list); | |
809 | ||
810 | set_cmd_completer (commands.set, color_completer); | |
811 | ||
812 | return commands; | |
813 | } | |
814 | ||
815 | /* Same as above but using a getter and a setter function instead of a pointer | |
816 | to a global storage buffer. */ | |
817 | ||
818 | set_show_commands | |
819 | add_setshow_color_cmd (const char *name, command_class theclass, | |
820 | const char *set_doc, const char *show_doc, | |
821 | const char *help_doc, | |
822 | setting_func_types<ui_file_style::color>::set set_func, | |
823 | setting_func_types<ui_file_style::color>::get get_func, | |
824 | show_value_ftype *show_func, | |
825 | cmd_list_element **set_list, | |
826 | cmd_list_element **show_list) | |
827 | { | |
828 | auto cmds = add_setshow_cmd_full<ui_file_style::color> | |
829 | (name, theclass, var_color, nullptr, | |
830 | set_doc, show_doc, help_doc, | |
831 | set_func, get_func, nullptr, show_func, | |
832 | set_list, show_list); | |
833 | ||
834 | set_cmd_completer (cmds.set, color_completer); | |
835 | ||
836 | return cmds; | |
837 | } | |
838 | ||
9d0faba9 | 839 | /* See cli-decode.h. */ |
5b9afe8a YQ |
840 | const char * const auto_boolean_enums[] = { "on", "off", "auto", NULL }; |
841 | ||
e9e68a56 | 842 | /* Add an auto-boolean command named NAME to both the set and show |
a58c8793 | 843 | command list lists. THECLASS is as in add_cmd. VAR is address of the |
e9e68a56 AC |
844 | variable which will contain the value. DOC is the documentation |
845 | string. FUNC is the corresponding callback. */ | |
af7f8f52 SM |
846 | |
847 | set_show_commands | |
6f937416 | 848 | add_setshow_auto_boolean_cmd (const char *name, |
fe978cb0 | 849 | enum command_class theclass, |
e9e68a56 | 850 | enum auto_boolean *var, |
3b64bf98 | 851 | const char *set_doc, const char *show_doc, |
335cca0d | 852 | const char *help_doc, |
5538b03c | 853 | cmd_func_ftype *set_func, |
08546159 | 854 | show_value_ftype *show_func, |
e9e68a56 AC |
855 | struct cmd_list_element **set_list, |
856 | struct cmd_list_element **show_list) | |
97c3646f | 857 | { |
af7f8f52 | 858 | set_show_commands commands |
70299171 LS |
859 | = add_setshow_cmd_full<enum auto_boolean> (name, theclass, var_auto_boolean, |
860 | var, set_doc, show_doc, help_doc, | |
861 | nullptr, nullptr, set_func, | |
862 | show_func, set_list, show_list); | |
cdb27c12 | 863 | |
af7f8f52 SM |
864 | commands.set->enums = auto_boolean_enums; |
865 | ||
866 | return commands; | |
97c3646f AC |
867 | } |
868 | ||
70299171 LS |
869 | /* Same as above but using a getter and a setter function instead of a pointer |
870 | to a global storage buffer. */ | |
871 | ||
872 | set_show_commands | |
873 | add_setshow_auto_boolean_cmd (const char *name, command_class theclass, | |
874 | const char *set_doc, const char *show_doc, | |
875 | const char *help_doc, | |
fcef6471 SM |
876 | setting_func_types<enum auto_boolean>::set set_func, |
877 | setting_func_types<enum auto_boolean>::get get_func, | |
70299171 LS |
878 | show_value_ftype *show_func, |
879 | cmd_list_element **set_list, | |
880 | cmd_list_element **show_list) | |
881 | { | |
882 | auto cmds = add_setshow_cmd_full<enum auto_boolean> (name, theclass, | |
883 | var_auto_boolean, | |
884 | nullptr, set_doc, | |
885 | show_doc, help_doc, | |
886 | set_func, get_func, | |
887 | nullptr, show_func, | |
888 | set_list, show_list); | |
889 | ||
890 | cmds.set->enums = auto_boolean_enums; | |
891 | ||
892 | return cmds; | |
893 | } | |
894 | ||
9d0faba9 PA |
895 | /* See cli-decode.h. */ |
896 | const char * const boolean_enums[] = { "on", "off", NULL }; | |
897 | ||
e707bbc2 | 898 | /* Add element named NAME to both the set and show command LISTs (the |
a58c8793 | 899 | list for set/show or some sublist thereof). THECLASS is as in |
e707bbc2 | 900 | add_cmd. VAR is address of the variable which will contain the |
2daf894e PA |
901 | value. SET_DOC and SHOW_DOC are the documentation strings. |
902 | Returns the new command element. */ | |
903 | ||
af7f8f52 | 904 | set_show_commands |
491144b5 | 905 | add_setshow_boolean_cmd (const char *name, enum command_class theclass, bool *var, |
3b64bf98 | 906 | const char *set_doc, const char *show_doc, |
335cca0d | 907 | const char *help_doc, |
5538b03c | 908 | cmd_func_ftype *set_func, |
08546159 | 909 | show_value_ftype *show_func, |
e707bbc2 AC |
910 | struct cmd_list_element **set_list, |
911 | struct cmd_list_element **show_list) | |
f3796e26 | 912 | { |
af7f8f52 | 913 | set_show_commands commands |
1d7fe7f0 LS |
914 | = add_setshow_cmd_full<bool> (name, theclass, var_boolean, var, |
915 | set_doc, show_doc, help_doc, | |
70299171 | 916 | nullptr, nullptr, set_func, show_func, |
1d7fe7f0 | 917 | set_list, show_list); |
cdb27c12 | 918 | |
af7f8f52 | 919 | commands.set->enums = boolean_enums; |
2daf894e | 920 | |
af7f8f52 | 921 | return commands; |
f3796e26 AC |
922 | } |
923 | ||
70299171 LS |
924 | /* Same as above but using a getter and a setter function instead of a pointer |
925 | to a global storage buffer. */ | |
926 | ||
927 | set_show_commands | |
928 | add_setshow_boolean_cmd (const char *name, command_class theclass, | |
929 | const char *set_doc, const char *show_doc, | |
930 | const char *help_doc, | |
fcef6471 SM |
931 | setting_func_types<bool>::set set_func, |
932 | setting_func_types<bool>::get get_func, | |
70299171 LS |
933 | show_value_ftype *show_func, |
934 | cmd_list_element **set_list, | |
935 | cmd_list_element **show_list) | |
936 | { | |
937 | auto cmds = add_setshow_cmd_full<bool> (name, theclass, var_boolean, nullptr, | |
938 | set_doc, show_doc, help_doc, | |
939 | set_func, get_func, nullptr, | |
940 | show_func, set_list, show_list); | |
941 | ||
942 | cmds.set->enums = boolean_enums; | |
943 | ||
944 | return cmds; | |
945 | } | |
946 | ||
b3f42336 AC |
947 | /* Add element named NAME to both the set and show command LISTs (the |
948 | list for set/show or some sublist thereof). */ | |
af7f8f52 SM |
949 | |
950 | set_show_commands | |
fe978cb0 | 951 | add_setshow_filename_cmd (const char *name, enum command_class theclass, |
e0700ba4 | 952 | std::string *var, |
b3f42336 | 953 | const char *set_doc, const char *show_doc, |
335cca0d | 954 | const char *help_doc, |
5538b03c | 955 | cmd_func_ftype *set_func, |
08546159 | 956 | show_value_ftype *show_func, |
b3f42336 AC |
957 | struct cmd_list_element **set_list, |
958 | struct cmd_list_element **show_list) | |
959 | { | |
af7f8f52 | 960 | set_show_commands commands |
e0700ba4 SM |
961 | = add_setshow_cmd_full<std::string> (name, theclass, var_filename, var, |
962 | set_doc, show_doc, help_doc, | |
70299171 LS |
963 | nullptr, nullptr, set_func, |
964 | show_func, set_list, show_list); | |
cdb27c12 | 965 | |
dc22ab49 | 966 | set_cmd_completer (commands.set, deprecated_filename_completer); |
af7f8f52 SM |
967 | |
968 | return commands; | |
b3f42336 AC |
969 | } |
970 | ||
70299171 LS |
971 | /* Same as above but using a getter and a setter function instead of a pointer |
972 | to a global storage buffer. */ | |
973 | ||
974 | set_show_commands | |
975 | add_setshow_filename_cmd (const char *name, command_class theclass, | |
976 | const char *set_doc, const char *show_doc, | |
977 | const char *help_doc, | |
fcef6471 SM |
978 | setting_func_types<std::string>::set set_func, |
979 | setting_func_types<std::string>::get get_func, | |
70299171 LS |
980 | show_value_ftype *show_func, |
981 | cmd_list_element **set_list, | |
982 | cmd_list_element **show_list) | |
983 | { | |
984 | auto cmds = add_setshow_cmd_full<std::string> (name, theclass, var_filename, | |
985 | nullptr, set_doc, show_doc, | |
986 | help_doc, set_func, get_func, | |
987 | nullptr, show_func, set_list, | |
988 | show_list); | |
989 | ||
dc22ab49 | 990 | set_cmd_completer (cmds.set, deprecated_filename_completer); |
70299171 LS |
991 | |
992 | return cmds; | |
993 | } | |
994 | ||
b3f42336 | 995 | /* Add element named NAME to both the set and show command LISTs (the |
5efd5804 | 996 | list for set/show or some sublist thereof). */ |
af7f8f52 SM |
997 | |
998 | set_show_commands | |
fe978cb0 | 999 | add_setshow_string_cmd (const char *name, enum command_class theclass, |
e0700ba4 | 1000 | std::string *var, |
6df3bc68 MS |
1001 | const char *set_doc, const char *show_doc, |
1002 | const char *help_doc, | |
5538b03c | 1003 | cmd_func_ftype *set_func, |
6df3bc68 MS |
1004 | show_value_ftype *show_func, |
1005 | struct cmd_list_element **set_list, | |
1006 | struct cmd_list_element **show_list) | |
b3f42336 | 1007 | { |
af7f8f52 | 1008 | set_show_commands commands |
e0700ba4 | 1009 | = add_setshow_cmd_full<std::string> (name, theclass, var_string, var, |
70299171 LS |
1010 | set_doc, show_doc, help_doc, |
1011 | nullptr, nullptr, set_func, | |
1012 | show_func, set_list, show_list); | |
597bf39d PA |
1013 | |
1014 | /* Disable the default symbol completer. */ | |
af7f8f52 SM |
1015 | set_cmd_completer (commands.set, nullptr); |
1016 | ||
1017 | return commands; | |
b3f42336 AC |
1018 | } |
1019 | ||
70299171 LS |
1020 | /* Same as above but using a getter and a setter function instead of a pointer |
1021 | to a global storage buffer. */ | |
1022 | ||
1023 | set_show_commands | |
1024 | add_setshow_string_cmd (const char *name, command_class theclass, | |
1025 | const char *set_doc, const char *show_doc, | |
1026 | const char *help_doc, | |
fcef6471 SM |
1027 | setting_func_types<std::string>::set set_func, |
1028 | setting_func_types<std::string>::get get_func, | |
70299171 LS |
1029 | show_value_ftype *show_func, |
1030 | cmd_list_element **set_list, | |
1031 | cmd_list_element **show_list) | |
1032 | { | |
1033 | auto cmds = add_setshow_cmd_full<std::string> (name, theclass, var_string, | |
1034 | nullptr, set_doc, show_doc, | |
1035 | help_doc, set_func, get_func, | |
1036 | nullptr, show_func, set_list, | |
1037 | show_list); | |
1038 | ||
1039 | /* Disable the default symbol completer. */ | |
1040 | set_cmd_completer (cmds.set, nullptr); | |
1041 | ||
1042 | return cmds; | |
1043 | } | |
1044 | ||
26c41df3 | 1045 | /* Add element named NAME to both the set and show command LISTs (the |
5efd5804 | 1046 | list for set/show or some sublist thereof). */ |
af7f8f52 SM |
1047 | |
1048 | set_show_commands | |
fe978cb0 | 1049 | add_setshow_string_noescape_cmd (const char *name, enum command_class theclass, |
e0700ba4 | 1050 | std::string *var, |
26c41df3 AC |
1051 | const char *set_doc, const char *show_doc, |
1052 | const char *help_doc, | |
5538b03c | 1053 | cmd_func_ftype *set_func, |
26c41df3 AC |
1054 | show_value_ftype *show_func, |
1055 | struct cmd_list_element **set_list, | |
1056 | struct cmd_list_element **show_list) | |
1057 | { | |
af7f8f52 | 1058 | set_show_commands commands |
e0700ba4 SM |
1059 | = add_setshow_cmd_full<std::string> (name, theclass, var_string_noescape, |
1060 | var, set_doc, show_doc, help_doc, | |
70299171 LS |
1061 | nullptr, nullptr, set_func, show_func, |
1062 | set_list, show_list); | |
597bf39d PA |
1063 | |
1064 | /* Disable the default symbol completer. */ | |
af7f8f52 | 1065 | set_cmd_completer (commands.set, nullptr); |
597bf39d | 1066 | |
af7f8f52 | 1067 | return commands; |
26c41df3 AC |
1068 | } |
1069 | ||
70299171 LS |
1070 | /* Same as above but using a getter and a setter function instead of a pointer |
1071 | to a global storage buffer. */ | |
1072 | ||
1073 | set_show_commands | |
1074 | add_setshow_string_noescape_cmd (const char *name, command_class theclass, | |
1075 | const char *set_doc, const char *show_doc, | |
1076 | const char *help_doc, | |
fcef6471 SM |
1077 | setting_func_types<std::string>::set set_func, |
1078 | setting_func_types<std::string>::get get_func, | |
70299171 LS |
1079 | show_value_ftype *show_func, |
1080 | cmd_list_element **set_list, | |
1081 | cmd_list_element **show_list) | |
1082 | { | |
1083 | auto cmds = add_setshow_cmd_full<std::string> (name, theclass, | |
1084 | var_string_noescape, nullptr, | |
1085 | set_doc, show_doc, help_doc, | |
1086 | set_func, get_func, | |
1087 | nullptr, show_func, set_list, | |
1088 | show_list); | |
1089 | ||
1090 | /* Disable the default symbol completer. */ | |
1091 | set_cmd_completer (cmds.set, nullptr); | |
1092 | ||
1093 | return cmds; | |
1094 | } | |
1095 | ||
b4b4ac0b AC |
1096 | /* Add element named NAME to both the set and show command LISTs (the |
1097 | list for set/show or some sublist thereof). */ | |
af7f8f52 SM |
1098 | |
1099 | set_show_commands | |
fe978cb0 | 1100 | add_setshow_optional_filename_cmd (const char *name, enum command_class theclass, |
e0700ba4 | 1101 | std::string *var, |
b4b4ac0b AC |
1102 | const char *set_doc, const char *show_doc, |
1103 | const char *help_doc, | |
5538b03c | 1104 | cmd_func_ftype *set_func, |
b4b4ac0b AC |
1105 | show_value_ftype *show_func, |
1106 | struct cmd_list_element **set_list, | |
1107 | struct cmd_list_element **show_list) | |
1108 | { | |
af7f8f52 | 1109 | set_show_commands commands |
e0700ba4 SM |
1110 | = add_setshow_cmd_full<std::string> (name, theclass, var_optional_filename, |
1111 | var, set_doc, show_doc, help_doc, | |
70299171 LS |
1112 | nullptr, nullptr, set_func, show_func, |
1113 | set_list, show_list); | |
1d7fe7f0 | 1114 | |
dc22ab49 | 1115 | set_cmd_completer (commands.set, deprecated_filename_completer); |
7f6a6314 | 1116 | |
af7f8f52 | 1117 | return commands; |
b4b4ac0b AC |
1118 | } |
1119 | ||
70299171 LS |
1120 | /* Same as above but using a getter and a setter function instead of a pointer |
1121 | to a global storage buffer. */ | |
1122 | ||
1123 | set_show_commands | |
1124 | add_setshow_optional_filename_cmd (const char *name, command_class theclass, | |
1125 | const char *set_doc, const char *show_doc, | |
1126 | const char *help_doc, | |
fcef6471 SM |
1127 | setting_func_types<std::string>::set set_func, |
1128 | setting_func_types<std::string>::get get_func, | |
70299171 LS |
1129 | show_value_ftype *show_func, |
1130 | cmd_list_element **set_list, | |
1131 | cmd_list_element **show_list) | |
1132 | { | |
1133 | auto cmds = | |
1134 | add_setshow_cmd_full<std::string> (name, theclass, var_optional_filename, | |
1135 | nullptr, set_doc, show_doc, help_doc, | |
1136 | set_func, get_func, nullptr, show_func, | |
1137 | set_list,show_list); | |
1138 | ||
dc22ab49 | 1139 | set_cmd_completer (cmds.set, deprecated_filename_completer); |
70299171 LS |
1140 | |
1141 | return cmds; | |
1142 | } | |
1143 | ||
c0d88b1b | 1144 | /* Add element named NAME to both the set and show command LISTs (the |
a58c8793 | 1145 | list for set/show or some sublist thereof). THECLASS is as in |
c0d88b1b | 1146 | add_cmd. VAR is address of the variable which will contain the |
6fc1c773 YQ |
1147 | value. SET_DOC and SHOW_DOC are the documentation strings. This |
1148 | function is only used in Python API. Please don't use it elsewhere. */ | |
af7f8f52 | 1149 | |
7aeb03e2 MR |
1150 | set_show_commands |
1151 | add_setshow_integer_cmd (const char *name, enum command_class theclass, | |
1152 | int *var, const literal_def *extra_literals, | |
1153 | const char *set_doc, const char *show_doc, | |
1154 | const char *help_doc, | |
1155 | cmd_func_ftype *set_func, | |
1156 | show_value_ftype *show_func, | |
1157 | struct cmd_list_element **set_list, | |
1158 | struct cmd_list_element **show_list) | |
1159 | { | |
1160 | set_show_commands commands | |
1161 | = add_setshow_cmd_full<int> (name, theclass, var_integer, var, | |
1162 | extra_literals, set_doc, show_doc, | |
1163 | help_doc, nullptr, nullptr, set_func, | |
1164 | show_func, set_list, show_list); | |
1165 | return commands; | |
1166 | } | |
1167 | ||
1168 | /* Same as above but using a getter and a setter function instead of a pointer | |
1169 | to a global storage buffer. */ | |
1170 | ||
1171 | set_show_commands | |
1172 | add_setshow_integer_cmd (const char *name, command_class theclass, | |
1173 | const literal_def *extra_literals, | |
1174 | const char *set_doc, const char *show_doc, | |
1175 | const char *help_doc, | |
1176 | setting_func_types<int>::set set_func, | |
1177 | setting_func_types<int>::get get_func, | |
1178 | show_value_ftype *show_func, | |
1179 | cmd_list_element **set_list, | |
1180 | cmd_list_element **show_list) | |
1181 | { | |
1182 | auto cmds = add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr, | |
1183 | extra_literals, set_doc, show_doc, | |
1184 | help_doc, set_func, get_func, nullptr, | |
1185 | show_func, set_list, show_list); | |
1186 | return cmds; | |
1187 | } | |
1188 | ||
1189 | /* Accept `unlimited' or 0, translated internally to INT_MAX. */ | |
1190 | const literal_def integer_unlimited_literals[] = | |
1191 | { | |
1192 | { "unlimited", INT_MAX, 0 }, | |
1193 | { nullptr } | |
1194 | }; | |
1195 | ||
1196 | /* Same as above but using `integer_unlimited_literals', with a pointer | |
1197 | to a global storage buffer. */ | |
1198 | ||
af7f8f52 | 1199 | set_show_commands |
fe978cb0 | 1200 | add_setshow_integer_cmd (const char *name, enum command_class theclass, |
47b667de | 1201 | int *var, |
6df3bc68 MS |
1202 | const char *set_doc, const char *show_doc, |
1203 | const char *help_doc, | |
5538b03c | 1204 | cmd_func_ftype *set_func, |
6df3bc68 MS |
1205 | show_value_ftype *show_func, |
1206 | struct cmd_list_element **set_list, | |
1207 | struct cmd_list_element **show_list) | |
c0d88b1b | 1208 | { |
af7f8f52 | 1209 | set_show_commands commands |
70299171 | 1210 | = add_setshow_cmd_full<int> (name, theclass, var_integer, var, |
7aeb03e2 | 1211 | integer_unlimited_literals, |
70299171 LS |
1212 | set_doc, show_doc, help_doc, |
1213 | nullptr, nullptr, set_func, | |
1214 | show_func, set_list, show_list); | |
af7f8f52 | 1215 | return commands; |
c0d88b1b AC |
1216 | } |
1217 | ||
70299171 LS |
1218 | /* Same as above but using a getter and a setter function instead of a pointer |
1219 | to a global storage buffer. */ | |
1220 | ||
1221 | set_show_commands | |
1222 | add_setshow_integer_cmd (const char *name, command_class theclass, | |
1223 | const char *set_doc, const char *show_doc, | |
1224 | const char *help_doc, | |
fcef6471 SM |
1225 | setting_func_types<int>::set set_func, |
1226 | setting_func_types<int>::get get_func, | |
70299171 LS |
1227 | show_value_ftype *show_func, |
1228 | cmd_list_element **set_list, | |
1229 | cmd_list_element **show_list) | |
1230 | { | |
1231 | auto cmds = add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr, | |
7aeb03e2 | 1232 | integer_unlimited_literals, |
70299171 LS |
1233 | set_doc, show_doc, help_doc, set_func, |
1234 | get_func, nullptr, show_func, set_list, | |
1235 | show_list); | |
7aeb03e2 MR |
1236 | return cmds; |
1237 | } | |
70299171 | 1238 | |
7aeb03e2 MR |
1239 | /* Add element named NAME to both the set and show command LISTs (the |
1240 | list for set/show or some sublist thereof). CLASS is as in | |
1241 | add_cmd. VAR is address of the variable which will contain the | |
1242 | value. SET_DOC and SHOW_DOC are the documentation strings. */ | |
70299171 | 1243 | |
7aeb03e2 MR |
1244 | set_show_commands |
1245 | add_setshow_pinteger_cmd (const char *name, enum command_class theclass, | |
1246 | int *var, const literal_def *extra_literals, | |
1247 | const char *set_doc, const char *show_doc, | |
1248 | const char *help_doc, | |
1249 | cmd_func_ftype *set_func, | |
1250 | show_value_ftype *show_func, | |
1251 | struct cmd_list_element **set_list, | |
1252 | struct cmd_list_element **show_list) | |
1253 | { | |
1254 | set_show_commands commands | |
1255 | = add_setshow_cmd_full<int> (name, theclass, var_pinteger, var, | |
1256 | extra_literals, set_doc, show_doc, | |
1257 | help_doc, nullptr, nullptr, set_func, | |
1258 | show_func, set_list, show_list); | |
1259 | return commands; | |
1260 | } | |
1261 | ||
1262 | /* Same as above but using a getter and a setter function instead of a pointer | |
1263 | to a global storage buffer. */ | |
1264 | ||
1265 | set_show_commands | |
1266 | add_setshow_pinteger_cmd (const char *name, command_class theclass, | |
1267 | const literal_def *extra_literals, | |
1268 | const char *set_doc, const char *show_doc, | |
1269 | const char *help_doc, | |
1270 | setting_func_types<int>::set set_func, | |
1271 | setting_func_types<int>::get get_func, | |
1272 | show_value_ftype *show_func, | |
1273 | cmd_list_element **set_list, | |
1274 | cmd_list_element **show_list) | |
1275 | { | |
1276 | auto cmds = add_setshow_cmd_full<int> (name, theclass, var_pinteger, nullptr, | |
1277 | extra_literals, set_doc, show_doc, | |
1278 | help_doc, set_func, get_func, nullptr, | |
1279 | show_func, set_list, show_list); | |
70299171 LS |
1280 | return cmds; |
1281 | } | |
1282 | ||
25d29d70 | 1283 | /* Add element named NAME to both the set and show command LISTs (the |
a58c8793 | 1284 | list for set/show or some sublist thereof). THECLASS is as in |
25d29d70 | 1285 | add_cmd. VAR is address of the variable which will contain the |
5efd5804 | 1286 | value. SET_DOC and SHOW_DOC are the documentation strings. */ |
af7f8f52 SM |
1287 | |
1288 | set_show_commands | |
fe978cb0 | 1289 | add_setshow_uinteger_cmd (const char *name, enum command_class theclass, |
7aeb03e2 | 1290 | unsigned int *var, const literal_def *extra_literals, |
3b64bf98 | 1291 | const char *set_doc, const char *show_doc, |
335cca0d | 1292 | const char *help_doc, |
5538b03c | 1293 | cmd_func_ftype *set_func, |
08546159 | 1294 | show_value_ftype *show_func, |
25d29d70 AC |
1295 | struct cmd_list_element **set_list, |
1296 | struct cmd_list_element **show_list) | |
1297 | { | |
af7f8f52 | 1298 | set_show_commands commands |
1d7fe7f0 | 1299 | = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, var, |
7aeb03e2 MR |
1300 | extra_literals, set_doc, show_doc, |
1301 | help_doc, nullptr, nullptr, set_func, | |
70299171 | 1302 | show_func, set_list, show_list); |
af7f8f52 | 1303 | return commands; |
25d29d70 AC |
1304 | } |
1305 | ||
70299171 LS |
1306 | /* Same as above but using a getter and a setter function instead of a pointer |
1307 | to a global storage buffer. */ | |
1308 | ||
1309 | set_show_commands | |
1310 | add_setshow_uinteger_cmd (const char *name, command_class theclass, | |
7aeb03e2 | 1311 | const literal_def *extra_literals, |
70299171 LS |
1312 | const char *set_doc, const char *show_doc, |
1313 | const char *help_doc, | |
fcef6471 SM |
1314 | setting_func_types<unsigned int>::set set_func, |
1315 | setting_func_types<unsigned int>::get get_func, | |
70299171 LS |
1316 | show_value_ftype *show_func, |
1317 | cmd_list_element **set_list, | |
1318 | cmd_list_element **show_list) | |
1319 | { | |
1320 | auto cmds = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, | |
7aeb03e2 MR |
1321 | nullptr, extra_literals, |
1322 | set_doc, show_doc, help_doc, | |
1323 | set_func, get_func, nullptr, | |
1324 | show_func, set_list, | |
70299171 | 1325 | show_list); |
7aeb03e2 MR |
1326 | return cmds; |
1327 | } | |
1328 | ||
1329 | /* Accept `unlimited' or 0, translated internally to UINT_MAX. */ | |
1330 | const literal_def uinteger_unlimited_literals[] = | |
1331 | { | |
1332 | { "unlimited", UINT_MAX, 0 }, | |
1333 | { nullptr } | |
1334 | }; | |
70299171 | 1335 | |
7aeb03e2 MR |
1336 | /* Same as above but using `uinteger_unlimited_literals', with a pointer |
1337 | to a global storage buffer. */ | |
1338 | ||
1339 | set_show_commands | |
1340 | add_setshow_uinteger_cmd (const char *name, enum command_class theclass, | |
1341 | unsigned int *var, | |
1342 | const char *set_doc, const char *show_doc, | |
1343 | const char *help_doc, | |
1344 | cmd_func_ftype *set_func, | |
1345 | show_value_ftype *show_func, | |
1346 | struct cmd_list_element **set_list, | |
1347 | struct cmd_list_element **show_list) | |
1348 | { | |
1349 | set_show_commands commands | |
1350 | = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, var, | |
1351 | uinteger_unlimited_literals, | |
1352 | set_doc, show_doc, help_doc, nullptr, | |
1353 | nullptr, set_func, show_func, | |
1354 | set_list, show_list); | |
1355 | return commands; | |
1356 | } | |
1357 | ||
1358 | /* Same as above but using a getter and a setter function instead of a pointer | |
1359 | to a global storage buffer. */ | |
70299171 | 1360 | |
7aeb03e2 MR |
1361 | set_show_commands |
1362 | add_setshow_uinteger_cmd (const char *name, command_class theclass, | |
1363 | const char *set_doc, const char *show_doc, | |
1364 | const char *help_doc, | |
1365 | setting_func_types<unsigned int>::set set_func, | |
1366 | setting_func_types<unsigned int>::get get_func, | |
1367 | show_value_ftype *show_func, | |
1368 | cmd_list_element **set_list, | |
1369 | cmd_list_element **show_list) | |
1370 | { | |
1371 | auto cmds = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, | |
1372 | nullptr, | |
1373 | uinteger_unlimited_literals, | |
1374 | set_doc, show_doc, help_doc, | |
1375 | set_func, get_func, nullptr, | |
1376 | show_func, set_list, | |
1377 | show_list); | |
70299171 LS |
1378 | return cmds; |
1379 | } | |
1380 | ||
15170568 | 1381 | /* Add element named NAME to both the set and show command LISTs (the |
a58c8793 | 1382 | list for set/show or some sublist thereof). THECLASS is as in |
15170568 | 1383 | add_cmd. VAR is address of the variable which will contain the |
5efd5804 | 1384 | value. SET_DOC and SHOW_DOC are the documentation strings. */ |
af7f8f52 SM |
1385 | |
1386 | set_show_commands | |
fe978cb0 | 1387 | add_setshow_zinteger_cmd (const char *name, enum command_class theclass, |
3b64bf98 AC |
1388 | int *var, |
1389 | const char *set_doc, const char *show_doc, | |
335cca0d | 1390 | const char *help_doc, |
5538b03c | 1391 | cmd_func_ftype *set_func, |
08546159 | 1392 | show_value_ftype *show_func, |
15170568 AC |
1393 | struct cmd_list_element **set_list, |
1394 | struct cmd_list_element **show_list) | |
1395 | { | |
7aeb03e2 | 1396 | return add_setshow_cmd_full<int> (name, theclass, var_integer, var, |
1d7fe7f0 | 1397 | set_doc, show_doc, help_doc, |
70299171 LS |
1398 | nullptr, nullptr, set_func, |
1399 | show_func, set_list, show_list); | |
1400 | } | |
1401 | ||
1402 | /* Same as above but using a getter and a setter function instead of a pointer | |
1403 | to a global storage buffer. */ | |
1404 | ||
1405 | set_show_commands | |
1406 | add_setshow_zinteger_cmd (const char *name, command_class theclass, | |
1407 | const char *set_doc, const char *show_doc, | |
1408 | const char *help_doc, | |
fcef6471 SM |
1409 | setting_func_types<int>::set set_func, |
1410 | setting_func_types<int>::get get_func, | |
70299171 LS |
1411 | show_value_ftype *show_func, |
1412 | cmd_list_element **set_list, | |
1413 | cmd_list_element **show_list) | |
1414 | { | |
7aeb03e2 | 1415 | return add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr, |
70299171 LS |
1416 | set_doc, show_doc, help_doc, set_func, |
1417 | get_func, nullptr, show_func, set_list, | |
1418 | show_list); | |
15170568 AC |
1419 | } |
1420 | ||
7aeb03e2 MR |
1421 | /* Accept `unlimited' or -1, using -1 internally. */ |
1422 | const literal_def pinteger_unlimited_literals[] = | |
1423 | { | |
1424 | { "unlimited", -1, -1 }, | |
1425 | { nullptr } | |
1426 | }; | |
1427 | ||
1428 | /* Same as above but using `pinteger_unlimited_literals', with a pointer | |
1429 | to a global storage buffer. */ | |
1430 | ||
af7f8f52 | 1431 | set_show_commands |
6f937416 | 1432 | add_setshow_zuinteger_unlimited_cmd (const char *name, |
fe978cb0 | 1433 | enum command_class theclass, |
b69b1fb1 | 1434 | int *var, |
6fc1c773 YQ |
1435 | const char *set_doc, |
1436 | const char *show_doc, | |
1437 | const char *help_doc, | |
5538b03c | 1438 | cmd_func_ftype *set_func, |
6fc1c773 YQ |
1439 | show_value_ftype *show_func, |
1440 | struct cmd_list_element **set_list, | |
1441 | struct cmd_list_element **show_list) | |
1442 | { | |
af7f8f52 | 1443 | set_show_commands commands |
7aeb03e2 MR |
1444 | = add_setshow_cmd_full<int> (name, theclass, var_pinteger, var, |
1445 | pinteger_unlimited_literals, | |
70299171 LS |
1446 | set_doc, show_doc, help_doc, nullptr, |
1447 | nullptr, set_func, show_func, set_list, | |
1448 | show_list); | |
af7f8f52 | 1449 | return commands; |
6fc1c773 YQ |
1450 | } |
1451 | ||
70299171 LS |
1452 | /* Same as above but using a getter and a setter function instead of a pointer |
1453 | to a global storage buffer. */ | |
1454 | ||
1455 | set_show_commands | |
1456 | add_setshow_zuinteger_unlimited_cmd (const char *name, command_class theclass, | |
1457 | const char *set_doc, const char *show_doc, | |
1458 | const char *help_doc, | |
fcef6471 SM |
1459 | setting_func_types<int>::set set_func, |
1460 | setting_func_types<int>::get get_func, | |
70299171 LS |
1461 | show_value_ftype *show_func, |
1462 | cmd_list_element **set_list, | |
1463 | cmd_list_element **show_list) | |
1464 | { | |
1465 | auto cmds | |
7aeb03e2 MR |
1466 | = add_setshow_cmd_full<int> (name, theclass, var_pinteger, nullptr, |
1467 | pinteger_unlimited_literals, | |
1468 | set_doc, show_doc, help_doc, set_func, | |
70299171 LS |
1469 | get_func, nullptr, show_func, set_list, |
1470 | show_list); | |
70299171 LS |
1471 | return cmds; |
1472 | } | |
1473 | ||
1e8fb976 | 1474 | /* Add element named NAME to both the set and show command LISTs (the |
a58c8793 | 1475 | list for set/show or some sublist thereof). THECLASS is as in |
1e8fb976 | 1476 | add_cmd. VAR is address of the variable which will contain the |
5efd5804 | 1477 | value. SET_DOC and SHOW_DOC are the documentation strings. */ |
af7f8f52 SM |
1478 | |
1479 | set_show_commands | |
fe978cb0 | 1480 | add_setshow_zuinteger_cmd (const char *name, enum command_class theclass, |
1e8fb976 PA |
1481 | unsigned int *var, |
1482 | const char *set_doc, const char *show_doc, | |
1483 | const char *help_doc, | |
5538b03c | 1484 | cmd_func_ftype *set_func, |
1e8fb976 PA |
1485 | show_value_ftype *show_func, |
1486 | struct cmd_list_element **set_list, | |
1487 | struct cmd_list_element **show_list) | |
1488 | { | |
7aeb03e2 | 1489 | return add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, |
1d7fe7f0 | 1490 | var, set_doc, show_doc, help_doc, |
70299171 LS |
1491 | nullptr, nullptr, set_func, |
1492 | show_func, set_list, show_list); | |
1493 | } | |
1494 | ||
1495 | /* Same as above but using a getter and a setter function instead of a pointer | |
1496 | to a global storage buffer. */ | |
1497 | ||
1498 | set_show_commands | |
1499 | add_setshow_zuinteger_cmd (const char *name, command_class theclass, | |
1500 | const char *set_doc, const char *show_doc, | |
1501 | const char *help_doc, | |
fcef6471 SM |
1502 | setting_func_types<unsigned int>::set set_func, |
1503 | setting_func_types<unsigned int>::get get_func, | |
70299171 LS |
1504 | show_value_ftype *show_func, |
1505 | cmd_list_element **set_list, | |
1506 | cmd_list_element **show_list) | |
1507 | { | |
7aeb03e2 | 1508 | return add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, |
70299171 LS |
1509 | nullptr, set_doc, show_doc, |
1510 | help_doc, set_func, get_func, | |
1511 | nullptr, show_func, set_list, | |
1d7fe7f0 | 1512 | show_list); |
1e8fb976 PA |
1513 | } |
1514 | ||
c471bdb1 SM |
1515 | /* Remove the command named NAME from the command list. Return the list |
1516 | commands which were aliased to the deleted command. The various *HOOKs are | |
1517 | set to the pre- and post-hook commands for the deleted command. If the | |
1518 | command does not have a hook, the corresponding out parameter is set to | |
1519 | NULL. */ | |
c906108c | 1520 | |
c471bdb1 | 1521 | static cmd_list_element::aliases_list_type |
6f937416 | 1522 | delete_cmd (const char *name, struct cmd_list_element **list, |
fad6eecd TT |
1523 | struct cmd_list_element **prehook, |
1524 | struct cmd_list_element **prehookee, | |
1525 | struct cmd_list_element **posthook, | |
1526 | struct cmd_list_element **posthookee) | |
c906108c | 1527 | { |
b05dcbb7 TT |
1528 | struct cmd_list_element *iter; |
1529 | struct cmd_list_element **previous_chain_ptr; | |
c471bdb1 | 1530 | cmd_list_element::aliases_list_type aliases; |
c906108c | 1531 | |
fad6eecd TT |
1532 | *prehook = NULL; |
1533 | *prehookee = NULL; | |
1534 | *posthook = NULL; | |
1535 | *posthookee = NULL; | |
b05dcbb7 TT |
1536 | previous_chain_ptr = list; |
1537 | ||
1538 | for (iter = *previous_chain_ptr; iter; iter = *previous_chain_ptr) | |
c906108c | 1539 | { |
b05dcbb7 TT |
1540 | if (strcmp (iter->name, name) == 0) |
1541 | { | |
d8906c6f | 1542 | if (iter->destroyer) |
0f8e2034 SM |
1543 | iter->destroyer (iter, iter->context ()); |
1544 | ||
b05dcbb7 TT |
1545 | if (iter->hookee_pre) |
1546 | iter->hookee_pre->hook_pre = 0; | |
fad6eecd TT |
1547 | *prehook = iter->hook_pre; |
1548 | *prehookee = iter->hookee_pre; | |
b05dcbb7 TT |
1549 | if (iter->hookee_post) |
1550 | iter->hookee_post->hook_post = 0; | |
fad6eecd TT |
1551 | *posthook = iter->hook_post; |
1552 | *posthookee = iter->hookee_post; | |
b05dcbb7 TT |
1553 | |
1554 | /* Update the link. */ | |
1555 | *previous_chain_ptr = iter->next; | |
1556 | ||
c471bdb1 | 1557 | aliases = std::move (iter->aliases); |
b05dcbb7 TT |
1558 | |
1559 | /* If this command was an alias, remove it from the list of | |
1560 | aliases. */ | |
1be99b11 | 1561 | if (iter->is_alias ()) |
b05dcbb7 | 1562 | { |
c471bdb1 SM |
1563 | auto it = iter->alias_target->aliases.iterator_to (*iter); |
1564 | iter->alias_target->aliases.erase (it); | |
b05dcbb7 TT |
1565 | } |
1566 | ||
e2fc72e2 | 1567 | delete iter; |
b05dcbb7 TT |
1568 | |
1569 | /* We won't see another command with the same name. */ | |
1570 | break; | |
1571 | } | |
1572 | else | |
1573 | previous_chain_ptr = &iter->next; | |
c906108c SS |
1574 | } |
1575 | ||
b05dcbb7 | 1576 | return aliases; |
c906108c | 1577 | } |
d318976c | 1578 | \f |
ebcd3b23 | 1579 | /* Shorthands to the commands above. */ |
d318976c FN |
1580 | |
1581 | /* Add an element to the list of info subcommands. */ | |
1582 | ||
1583 | struct cmd_list_element * | |
3a553c80 | 1584 | add_info (const char *name, cmd_simple_func_ftype *fun, const char *doc) |
d318976c | 1585 | { |
f3575e08 | 1586 | return add_cmd (name, class_info, fun, doc, &infolist); |
d318976c FN |
1587 | } |
1588 | ||
1589 | /* Add an alias to the list of info subcommands. */ | |
1590 | ||
e0f25bd9 SM |
1591 | cmd_list_element * |
1592 | add_info_alias (const char *name, cmd_list_element *target, int abbrev_flag) | |
d318976c | 1593 | { |
e0f25bd9 | 1594 | return add_alias_cmd (name, target, class_run, abbrev_flag, &infolist); |
d318976c FN |
1595 | } |
1596 | ||
1597 | /* Add an element to the list of commands. */ | |
1598 | ||
1599 | struct cmd_list_element * | |
0b39b52e | 1600 | add_com (const char *name, enum command_class theclass, |
3a553c80 | 1601 | cmd_simple_func_ftype *fun, |
1947513d | 1602 | const char *doc) |
d318976c | 1603 | { |
fe978cb0 | 1604 | return add_cmd (name, theclass, fun, doc, &cmdlist); |
d318976c FN |
1605 | } |
1606 | ||
57b4f16e PW |
1607 | /* Add an alias or abbreviation command to the list of commands. |
1608 | For aliases predefined by GDB (such as bt), THECLASS must be | |
1609 | different of class_alias, as class_alias is used to identify | |
1610 | user defined aliases. */ | |
d318976c | 1611 | |
3947f654 SM |
1612 | cmd_list_element * |
1613 | add_com_alias (const char *name, cmd_list_element *target, | |
99858724 | 1614 | command_class theclass, int abbrev_flag) |
d318976c | 1615 | { |
3947f654 | 1616 | return add_alias_cmd (name, target, theclass, abbrev_flag, &cmdlist); |
d318976c | 1617 | } |
4034d0ff AT |
1618 | |
1619 | /* Add an element with a suppress notification to the list of commands. */ | |
1620 | ||
1621 | struct cmd_list_element * | |
1622 | add_com_suppress_notification (const char *name, enum command_class theclass, | |
3a553c80 | 1623 | cmd_simple_func_ftype *fun, const char *doc, |
f36c8918 | 1624 | bool *suppress_notification) |
4034d0ff | 1625 | { |
f67ffa6a AB |
1626 | return add_cmd_suppress_notification (name, theclass, fun, doc, |
1627 | &cmdlist, suppress_notification); | |
4034d0ff AT |
1628 | } |
1629 | ||
b5f91cd4 | 1630 | /* Print the prefix of C followed by name of C in command style. */ |
3b3aaacb PW |
1631 | |
1632 | static void | |
eccd14b3 | 1633 | fput_command_name_styled (const cmd_list_element &c, struct ui_file *stream) |
3b3aaacb | 1634 | { |
2f822da5 | 1635 | std::string prefixname |
eccd14b3 | 1636 | = c.prefix == nullptr ? "" : c.prefix->prefixname (); |
3b3aaacb | 1637 | |
b5f91cd4 | 1638 | fprintf_styled (stream, command_style.style (), "%s%s", |
eccd14b3 | 1639 | prefixname.c_str (), c.name); |
3b3aaacb PW |
1640 | } |
1641 | ||
effcf7b1 PW |
1642 | /* True if ALIAS has a user-defined documentation. */ |
1643 | ||
1644 | static bool | |
1645 | user_documented_alias (const cmd_list_element &alias) | |
1646 | { | |
1647 | gdb_assert (alias.is_alias ()); | |
1648 | /* Alias is user documented if it has an allocated documentation | |
1649 | that differs from the aliased command. */ | |
1650 | return (alias.doc_allocated | |
1651 | && strcmp (alias.doc, alias.alias_target->doc) != 0); | |
1652 | } | |
1653 | ||
cf00cd6f PW |
1654 | /* Print the definition of alias C using title style for alias |
1655 | and aliased command. */ | |
1656 | ||
1657 | static void | |
eccd14b3 | 1658 | fput_alias_definition_styled (const cmd_list_element &c, |
cf00cd6f PW |
1659 | struct ui_file *stream) |
1660 | { | |
eccd14b3 | 1661 | gdb_assert (c.is_alias ()); |
0426ad51 | 1662 | gdb_puts (" alias ", stream); |
cf00cd6f | 1663 | fput_command_name_styled (c, stream); |
6cb06a8c | 1664 | gdb_printf (stream, " = "); |
eccd14b3 | 1665 | fput_command_name_styled (*c.alias_target, stream); |
6cb06a8c | 1666 | gdb_printf (stream, " %s\n", c.default_args.c_str ()); |
cf00cd6f PW |
1667 | } |
1668 | ||
effcf7b1 PW |
1669 | /* Print the definition of CMD aliases not deprecated and having default args |
1670 | and not specifically documented by the user. */ | |
cf00cd6f PW |
1671 | |
1672 | static void | |
eccd14b3 | 1673 | fput_aliases_definition_styled (const cmd_list_element &cmd, |
cf00cd6f PW |
1674 | struct ui_file *stream) |
1675 | { | |
eccd14b3 | 1676 | for (const cmd_list_element &alias : cmd.aliases) |
effcf7b1 PW |
1677 | if (!alias.cmd_deprecated |
1678 | && !user_documented_alias (alias) | |
1679 | && !alias.default_args.empty ()) | |
eccd14b3 | 1680 | fput_alias_definition_styled (alias, stream); |
cf00cd6f PW |
1681 | } |
1682 | ||
effcf7b1 PW |
1683 | /* If C has one or more aliases, style print the name of C and the name of its |
1684 | aliases not documented specifically by the user, separated by commas. | |
3b3aaacb PW |
1685 | If ALWAYS_FPUT_C_NAME, print the name of C even if it has no aliases. |
1686 | If one or more names are printed, POSTFIX is printed after the last name. | |
1687 | */ | |
1688 | ||
1689 | static void | |
eccd14b3 | 1690 | fput_command_names_styled (const cmd_list_element &c, |
3b3aaacb PW |
1691 | bool always_fput_c_name, const char *postfix, |
1692 | struct ui_file *stream) | |
1693 | { | |
e34e3918 SM |
1694 | /* First, check if we are going to print something. That is, either if |
1695 | ALWAYS_FPUT_C_NAME is true or if there exists at least one non-deprecated | |
effcf7b1 | 1696 | alias not documented specifically by the user. */ |
e34e3918 SM |
1697 | |
1698 | auto print_alias = [] (const cmd_list_element &alias) | |
1699 | { | |
effcf7b1 | 1700 | return !alias.cmd_deprecated && !user_documented_alias (alias); |
e34e3918 SM |
1701 | }; |
1702 | ||
1703 | bool print_something = always_fput_c_name; | |
1704 | if (!print_something) | |
1705 | for (const cmd_list_element &alias : c.aliases) | |
1706 | { | |
1707 | if (!print_alias (alias)) | |
1708 | continue; | |
1709 | ||
1710 | print_something = true; | |
1711 | break; | |
1712 | } | |
1713 | ||
1714 | if (print_something) | |
3b3aaacb | 1715 | fput_command_name_styled (c, stream); |
143f5a38 | 1716 | |
eccd14b3 | 1717 | for (const cmd_list_element &alias : c.aliases) |
3b3aaacb | 1718 | { |
e34e3918 SM |
1719 | if (!print_alias (alias)) |
1720 | continue; | |
1721 | ||
0426ad51 | 1722 | gdb_puts (", ", stream); |
1285ce86 | 1723 | stream->wrap_here (3); |
eccd14b3 | 1724 | fput_command_name_styled (alias, stream); |
3b3aaacb | 1725 | } |
143f5a38 | 1726 | |
e34e3918 | 1727 | if (print_something) |
0426ad51 | 1728 | gdb_puts (postfix, stream); |
3b3aaacb PW |
1729 | } |
1730 | ||
66d8c862 PW |
1731 | /* If VERBOSE, print the full help for command C and highlight the |
1732 | documentation parts matching HIGHLIGHT, | |
1733 | otherwise print only one-line help for command C. */ | |
1734 | ||
1735 | static void | |
c4e37fa8 SM |
1736 | print_doc_of_command (const cmd_list_element &c, bool verbose, |
1737 | compiled_regex &highlight, struct ui_file *stream) | |
66d8c862 PW |
1738 | { |
1739 | /* When printing the full documentation, add a line to separate | |
1740 | this documentation from the previous command help, in the likely | |
1741 | case that apropos finds several commands. */ | |
1742 | if (verbose) | |
0426ad51 | 1743 | gdb_puts ("\n", stream); |
66d8c862 | 1744 | |
cf00cd6f PW |
1745 | fput_command_names_styled (c, true, |
1746 | verbose ? "" : " -- ", stream); | |
66d8c862 | 1747 | if (verbose) |
cf00cd6f | 1748 | { |
0426ad51 | 1749 | gdb_puts ("\n", stream); |
cf00cd6f | 1750 | fput_aliases_definition_styled (c, stream); |
eccd14b3 | 1751 | fputs_highlighted (c.doc, highlight, stream); |
0426ad51 | 1752 | gdb_puts ("\n", stream); |
cf00cd6f | 1753 | } |
66d8c862 | 1754 | else |
cf00cd6f | 1755 | { |
eccd14b3 | 1756 | print_doc_line (stream, c.doc, false); |
0426ad51 | 1757 | gdb_puts ("\n", stream); |
cf00cd6f PW |
1758 | fput_aliases_definition_styled (c, stream); |
1759 | } | |
66d8c862 PW |
1760 | } |
1761 | ||
6837a0a2 DB |
1762 | /* Recursively walk the commandlist structures, and print out the |
1763 | documentation of commands that match our regex in either their | |
1764 | name, or their documentation. | |
66d8c862 PW |
1765 | If VERBOSE, prints the complete documentation and highlight the |
1766 | documentation parts matching REGEX, otherwise prints only | |
1767 | the first line. | |
6837a0a2 | 1768 | */ |
66d8c862 PW |
1769 | void |
1770 | apropos_cmd (struct ui_file *stream, | |
ebcd3b23 | 1771 | struct cmd_list_element *commandlist, |
c4e37fa8 | 1772 | bool verbose, compiled_regex ®ex) |
6837a0a2 | 1773 | { |
d5b5ac79 | 1774 | struct cmd_list_element *c; |
4a98be19 | 1775 | int returnvalue; |
cdb27c12 | 1776 | |
ebcd3b23 | 1777 | /* Walk through the commands. */ |
6837a0a2 DB |
1778 | for (c=commandlist;c;c=c->next) |
1779 | { | |
effcf7b1 | 1780 | if (c->is_alias () && !user_documented_alias (*c)) |
7c05caf7 | 1781 | { |
effcf7b1 PW |
1782 | /* Command aliases/abbreviations not specifically documented by the |
1783 | user are skipped to ensure we print the doc of a command only once, | |
1784 | when encountering the aliased command. */ | |
7c05caf7 PW |
1785 | continue; |
1786 | } | |
1787 | ||
ebcd3b23 | 1788 | returnvalue = -1; /* Needed to avoid double printing. */ |
6837a0a2 DB |
1789 | if (c->name != NULL) |
1790 | { | |
2d7cc5c7 PA |
1791 | size_t name_len = strlen (c->name); |
1792 | ||
ebcd3b23 | 1793 | /* Try to match against the name. */ |
2d7cc5c7 | 1794 | returnvalue = regex.search (c->name, name_len, 0, name_len, NULL); |
6837a0a2 | 1795 | if (returnvalue >= 0) |
c4e37fa8 | 1796 | print_doc_of_command (*c, verbose, regex, stream); |
7c05caf7 PW |
1797 | |
1798 | /* Try to match against the name of the aliases. */ | |
c471bdb1 | 1799 | for (const cmd_list_element &alias : c->aliases) |
7c05caf7 | 1800 | { |
c471bdb1 SM |
1801 | name_len = strlen (alias.name); |
1802 | returnvalue = regex.search (alias.name, name_len, 0, name_len, NULL); | |
7c05caf7 | 1803 | if (returnvalue >= 0) |
c471bdb1 | 1804 | { |
c4e37fa8 | 1805 | print_doc_of_command (*c, verbose, regex, stream); |
c471bdb1 SM |
1806 | break; |
1807 | } | |
7c05caf7 | 1808 | } |
6837a0a2 | 1809 | } |
4a98be19 | 1810 | if (c->doc != NULL && returnvalue < 0) |
6837a0a2 | 1811 | { |
2d7cc5c7 PA |
1812 | size_t doc_len = strlen (c->doc); |
1813 | ||
ebcd3b23 | 1814 | /* Try to match against documentation. */ |
2d7cc5c7 | 1815 | if (regex.search (c->doc, doc_len, 0, doc_len, NULL) >= 0) |
c4e37fa8 | 1816 | print_doc_of_command (*c, verbose, regex, stream); |
6837a0a2 | 1817 | } |
7c05caf7 | 1818 | /* Check if this command has subcommands. */ |
3d0b3564 | 1819 | if (c->is_prefix ()) |
6837a0a2 DB |
1820 | { |
1821 | /* Recursively call ourselves on the subcommand list, | |
ebcd3b23 | 1822 | passing the right prefix in. */ |
c4e37fa8 | 1823 | apropos_cmd (stream, *c->subcommands, verbose, regex); |
6837a0a2 DB |
1824 | } |
1825 | } | |
1826 | } | |
c906108c SS |
1827 | |
1828 | /* This command really has to deal with two things: | |
ebcd3b23 MS |
1829 | 1) I want documentation on *this string* (usually called by |
1830 | "help commandname"). | |
1831 | ||
1832 | 2) I want documentation on *this list* (usually called by giving a | |
1833 | command that requires subcommands. Also called by saying just | |
1834 | "help".) | |
1835 | ||
30baf67b | 1836 | I am going to split this into two separate commands, help_cmd and |
ebcd3b23 | 1837 | help_list. */ |
c906108c SS |
1838 | |
1839 | void | |
64669f3b | 1840 | help_cmd (const char *command, struct ui_file *stream) |
c906108c | 1841 | { |
7c05caf7 | 1842 | struct cmd_list_element *c, *alias, *prefix_cmd, *c_cmd; |
c906108c SS |
1843 | |
1844 | if (!command) | |
1845 | { | |
1846 | help_list (cmdlist, "", all_classes, stream); | |
1847 | return; | |
1848 | } | |
1849 | ||
49a5a3a3 GM |
1850 | if (strcmp (command, "all") == 0) |
1851 | { | |
1852 | help_all (stream); | |
1853 | return; | |
1854 | } | |
1855 | ||
7c05caf7 | 1856 | const char *orig_command = command; |
cf00cd6f | 1857 | c = lookup_cmd (&command, cmdlist, "", NULL, 0, 0); |
c906108c SS |
1858 | |
1859 | if (c == 0) | |
1860 | return; | |
1861 | ||
7c05caf7 PW |
1862 | lookup_cmd_composition (orig_command, &alias, &prefix_cmd, &c_cmd); |
1863 | ||
c906108c | 1864 | /* There are three cases here. |
14b42fc4 | 1865 | If c->subcommands is nonzero, we have a prefix command. |
c906108c | 1866 | Print its documentation, then list its subcommands. |
c5aa993b | 1867 | |
9f60d481 AC |
1868 | If c->func is non NULL, we really have a command. Print its |
1869 | documentation and return. | |
c5aa993b | 1870 | |
9f60d481 AC |
1871 | If c->func is NULL, we have a class name. Print its |
1872 | documentation (as if it were a command) and then set class to the | |
1873 | number of this class so that the commands in the class will be | |
1874 | listed. */ | |
c906108c | 1875 | |
effcf7b1 PW |
1876 | if (alias == nullptr || !user_documented_alias (*alias)) |
1877 | { | |
3bfdcabb | 1878 | /* Case of a normal command, or an alias not explicitly |
effcf7b1 PW |
1879 | documented by the user. */ |
1880 | /* If the user asked 'help somecommand' and there is no alias, | |
1881 | the false indicates to not output the (single) command name. */ | |
1882 | fput_command_names_styled (*c, false, "\n", stream); | |
1883 | fput_aliases_definition_styled (*c, stream); | |
1884 | gdb_puts (c->doc, stream); | |
1885 | } | |
1886 | else | |
1887 | { | |
3bfdcabb | 1888 | /* Case of an alias explicitly documented by the user. |
effcf7b1 PW |
1889 | Only output the alias definition and its explicit documentation. */ |
1890 | fput_alias_definition_styled (*alias, stream); | |
1891 | fput_command_names_styled (*alias, false, "\n", stream); | |
1892 | gdb_puts (alias->doc, stream); | |
1893 | } | |
0426ad51 | 1894 | gdb_puts ("\n", stream); |
c906108c | 1895 | |
034dce7a | 1896 | if (!c->is_prefix () && !c->is_command_class_help ()) |
c906108c | 1897 | return; |
3d0b3564 | 1898 | |
6cb06a8c | 1899 | gdb_printf (stream, "\n"); |
c906108c | 1900 | |
ebcd3b23 | 1901 | /* If this is a prefix command, print it's subcommands. */ |
3d0b3564 | 1902 | if (c->is_prefix ()) |
652e09d5 | 1903 | help_list (*c->subcommands, c->prefixname_no_space ().c_str (), |
2f822da5 | 1904 | all_commands, stream); |
c906108c | 1905 | |
ebcd3b23 | 1906 | /* If this is a class name, print all of the commands in the class. */ |
034dce7a | 1907 | if (c->is_command_class_help ()) |
fe978cb0 | 1908 | help_list (cmdlist, "", c->theclass, stream); |
c906108c | 1909 | |
73bc900d | 1910 | if (c->hook_pre || c->hook_post) |
6cb06a8c TT |
1911 | gdb_printf (stream, |
1912 | "\nThis command has a hook (or hooks) defined:\n"); | |
73bc900d FN |
1913 | |
1914 | if (c->hook_pre) | |
6cb06a8c TT |
1915 | gdb_printf (stream, |
1916 | "\tThis command is run after : %s (pre hook)\n", | |
1917 | c->hook_pre->name); | |
73bc900d | 1918 | if (c->hook_post) |
6cb06a8c TT |
1919 | gdb_printf (stream, |
1920 | "\tThis command is run before : %s (post hook)\n", | |
1921 | c->hook_post->name); | |
c906108c SS |
1922 | } |
1923 | ||
652e09d5 TT |
1924 | /* Get a specific kind of help on a command list. |
1925 | ||
1926 | LIST is the list. | |
1927 | CMDTYPE is the prefix to use in the title string. It should not | |
1928 | end in a space. | |
1929 | THECLASS is the class with which to list the nodes of this list (see | |
1930 | documentation for help_cmd_list below), As usual, ALL_COMMANDS for | |
1931 | everything, ALL_CLASSES for just classes, and non-negative for only things | |
1932 | in a specific class. | |
1933 | and STREAM is the output stream on which to print things. | |
1934 | If you call this routine with a class >= 0, it recurses. */ | |
c906108c | 1935 | void |
64e61d29 | 1936 | help_list (struct cmd_list_element *list, const char *cmdtype, |
fe978cb0 | 1937 | enum command_class theclass, struct ui_file *stream) |
c906108c | 1938 | { |
652e09d5 TT |
1939 | int len = strlen (cmdtype); |
1940 | const char *space = ""; | |
1941 | const char *prefix = ""; | |
1942 | if (len > 0) | |
c906108c | 1943 | { |
652e09d5 TT |
1944 | prefix = "sub"; |
1945 | space = " "; | |
c906108c SS |
1946 | } |
1947 | ||
fe978cb0 | 1948 | if (theclass == all_classes) |
652e09d5 TT |
1949 | gdb_printf (stream, "List of classes of %scommands:\n\n", |
1950 | prefix); | |
1951 | else if (len == 0) | |
1952 | gdb_printf (stream, "List of commands:\n\n"); | |
c906108c | 1953 | else |
652e09d5 TT |
1954 | gdb_printf (stream, "List of \"%ps\" %scommands:\n\n", |
1955 | styled_string (command_style.style (), cmdtype), | |
1956 | prefix); | |
c906108c | 1957 | |
3b3aaacb | 1958 | help_cmd_list (list, theclass, theclass >= 0, stream); |
c906108c | 1959 | |
fe978cb0 | 1960 | if (theclass == all_classes) |
de74f71f | 1961 | { |
6cb06a8c | 1962 | gdb_printf (stream, "\n\ |
652e09d5 | 1963 | Type \"%p[help%s%s%p]\" followed by a class name for a list of commands in ", |
9e69a2e1 | 1964 | command_style.style ().ptr (), |
652e09d5 | 1965 | space, cmdtype, |
9e69a2e1 | 1966 | nullptr); |
1285ce86 | 1967 | stream->wrap_here (0); |
6cb06a8c | 1968 | gdb_printf (stream, "that class."); |
6e381ba0 | 1969 | |
6cb06a8c | 1970 | gdb_printf (stream, "\n\ |
9e69a2e1 TT |
1971 | Type \"%ps\" for the list of all commands.", |
1972 | styled_string (command_style.style (), "help all")); | |
de74f71f | 1973 | } |
c906108c | 1974 | |
652e09d5 TT |
1975 | gdb_printf (stream, "\nType \"%p[help%s%s%p]\" followed by %scommand name ", |
1976 | command_style.style ().ptr (), space, cmdtype, nullptr, | |
1977 | prefix); | |
1285ce86 | 1978 | stream->wrap_here (0); |
0426ad51 | 1979 | gdb_puts ("for ", stream); |
1285ce86 | 1980 | stream->wrap_here (0); |
0426ad51 | 1981 | gdb_puts ("full ", stream); |
1285ce86 | 1982 | stream->wrap_here (0); |
0426ad51 | 1983 | gdb_puts ("documentation.\n", stream); |
9e69a2e1 TT |
1984 | gdb_printf (stream, |
1985 | "Type \"%ps\" to search " | |
1986 | "for commands related to \"word\".\n", | |
1987 | styled_string (command_style.style (), "apropos word")); | |
1988 | gdb_printf (stream, "Type \"%ps\" for full documentation", | |
1989 | styled_string (command_style.style (), "apropos -v word")); | |
1285ce86 | 1990 | stream->wrap_here (0); |
0426ad51 TT |
1991 | gdb_puts (" of commands related to \"word\".\n", stream); |
1992 | gdb_puts ("Command name abbreviations are allowed if unambiguous.\n", | |
1993 | stream); | |
c906108c | 1994 | } |
c5aa993b | 1995 | |
49a5a3a3 | 1996 | static void |
c85871a3 | 1997 | help_all (struct ui_file *stream) |
49a5a3a3 GM |
1998 | { |
1999 | struct cmd_list_element *c; | |
6e381ba0 | 2000 | int seen_unclassified = 0; |
49a5a3a3 GM |
2001 | |
2002 | for (c = cmdlist; c; c = c->next) | |
2003 | { | |
2004 | if (c->abbrev_flag) | |
dda83cd7 | 2005 | continue; |
ebcd3b23 MS |
2006 | /* If this is a class name, print all of the commands in the |
2007 | class. */ | |
6e381ba0 | 2008 | |
034dce7a | 2009 | if (c->is_command_class_help ()) |
6e381ba0 | 2010 | { |
6cb06a8c | 2011 | gdb_printf (stream, "\nCommand class: %s\n\n", c->name); |
3b3aaacb | 2012 | help_cmd_list (cmdlist, c->theclass, true, stream); |
6e381ba0 | 2013 | } |
49a5a3a3 | 2014 | } |
6e381ba0 VP |
2015 | |
2016 | /* While it's expected that all commands are in some class, | |
2017 | as a safety measure, we'll print commands outside of any | |
2018 | class at the end. */ | |
2019 | ||
2020 | for (c = cmdlist; c; c = c->next) | |
2021 | { | |
2022 | if (c->abbrev_flag) | |
dda83cd7 | 2023 | continue; |
6e381ba0 | 2024 | |
fe978cb0 | 2025 | if (c->theclass == no_class) |
6e381ba0 VP |
2026 | { |
2027 | if (!seen_unclassified) | |
2028 | { | |
6cb06a8c | 2029 | gdb_printf (stream, "\nUnclassified commands\n\n"); |
6e381ba0 VP |
2030 | seen_unclassified = 1; |
2031 | } | |
eccd14b3 | 2032 | print_help_for_command (*c, true, stream); |
6e381ba0 VP |
2033 | } |
2034 | } | |
2035 | ||
49a5a3a3 GM |
2036 | } |
2037 | ||
590042fc PW |
2038 | /* See cli-decode.h. */ |
2039 | ||
d318976c | 2040 | void |
590042fc PW |
2041 | print_doc_line (struct ui_file *stream, const char *str, |
2042 | bool for_value_prefix) | |
c906108c | 2043 | { |
ae871f29 | 2044 | const char *p = strchr (str, '\n'); |
c906108c | 2045 | |
ae871f29 TT |
2046 | /* Only copy the input string if we really need to. */ |
2047 | std::optional<std::string> line_buffer; | |
2048 | if (p != nullptr) | |
2049 | line_buffer = std::string (str, p); | |
2050 | else if (for_value_prefix) | |
2051 | line_buffer = str; | |
c906108c | 2052 | |
590042fc PW |
2053 | if (for_value_prefix) |
2054 | { | |
ae871f29 TT |
2055 | char &c = (*line_buffer)[0]; |
2056 | if (islower (c)) | |
2057 | c = toupper (c); | |
2058 | if (line_buffer->back () == '.') | |
2059 | line_buffer->pop_back (); | |
590042fc | 2060 | } |
ae871f29 TT |
2061 | |
2062 | gdb_puts (line_buffer.has_value () | |
2063 | ? line_buffer->c_str () | |
2064 | : str, | |
2065 | stream); | |
c906108c SS |
2066 | } |
2067 | ||
6e381ba0 VP |
2068 | /* Print one-line help for command C. |
2069 | If RECURSE is non-zero, also print one-line descriptions | |
ebcd3b23 | 2070 | of all prefixed subcommands. */ |
6e381ba0 | 2071 | static void |
eccd14b3 | 2072 | print_help_for_command (const cmd_list_element &c, |
3b3aaacb | 2073 | bool recurse, struct ui_file *stream) |
6e381ba0 | 2074 | { |
3b3aaacb | 2075 | fput_command_names_styled (c, true, " -- ", stream); |
eccd14b3 | 2076 | print_doc_line (stream, c.doc, false); |
0426ad51 | 2077 | gdb_puts ("\n", stream); |
eccd14b3 | 2078 | if (!c.default_args.empty ()) |
cf00cd6f PW |
2079 | fput_alias_definition_styled (c, stream); |
2080 | fput_aliases_definition_styled (c, stream); | |
66d8c862 | 2081 | |
6e381ba0 | 2082 | if (recurse |
eccd14b3 SM |
2083 | && c.is_prefix () |
2084 | && c.abbrev_flag == 0) | |
6e381ba0 VP |
2085 | /* Subcommands of a prefix command typically have 'all_commands' |
2086 | as class. If we pass CLASS to recursive invocation, | |
ebcd3b23 | 2087 | most often we won't see anything. */ |
eccd14b3 | 2088 | help_cmd_list (*c.subcommands, all_commands, true, stream); |
6e381ba0 VP |
2089 | } |
2090 | ||
c906108c SS |
2091 | /* |
2092 | * Implement a help command on command list LIST. | |
2093 | * RECURSE should be non-zero if this should be done recursively on | |
2094 | * all sublists of LIST. | |
c906108c | 2095 | * STREAM is the stream upon which the output should be written. |
2aa08bd1 | 2096 | * THECLASS should be: |
c5aa993b | 2097 | * A non-negative class number to list only commands in that |
c5aa993b JM |
2098 | * ALL_COMMANDS to list all commands in list. |
2099 | * ALL_CLASSES to list all classes in list. | |
c906108c | 2100 | * |
3b3aaacb PW |
2101 | * Note that aliases are only shown when THECLASS is class_alias. |
2102 | * In the other cases, the aliases will be shown together with their | |
2103 | * aliased command. | |
2104 | * | |
c906108c SS |
2105 | * Note that RECURSE will be active on *all* sublists, not just the |
2106 | * ones selected by the criteria above (ie. the selection mechanism | |
2107 | * is at the low level, not the high-level). | |
2108 | */ | |
3b3aaacb PW |
2109 | |
2110 | static void | |
fe978cb0 | 2111 | help_cmd_list (struct cmd_list_element *list, enum command_class theclass, |
3b3aaacb | 2112 | bool recurse, struct ui_file *stream) |
c906108c | 2113 | { |
d5b5ac79 | 2114 | struct cmd_list_element *c; |
c906108c SS |
2115 | |
2116 | for (c = list; c; c = c->next) | |
2aa08bd1 | 2117 | { |
3b3aaacb | 2118 | if (c->abbrev_flag == 1 || c->cmd_deprecated) |
c906108c | 2119 | { |
3b3aaacb PW |
2120 | /* Do not show abbreviations or deprecated commands. */ |
2121 | continue; | |
c906108c | 2122 | } |
3b3aaacb | 2123 | |
1be99b11 | 2124 | if (c->is_alias () && theclass != class_alias) |
3b3aaacb PW |
2125 | { |
2126 | /* Do not show an alias, unless specifically showing the | |
2127 | list of aliases: for all other classes, an alias is | |
2128 | shown (if needed) together with its aliased command. */ | |
2129 | continue; | |
2130 | } | |
2131 | ||
2132 | if (theclass == all_commands | |
034dce7a SM |
2133 | || (theclass == all_classes && c->is_command_class_help ()) |
2134 | || (theclass == c->theclass && !c->is_command_class_help ())) | |
3b3aaacb PW |
2135 | { |
2136 | /* show C when | |
dda83cd7 | 2137 | - showing all commands |
3b3aaacb PW |
2138 | - showing all classes and C is a help class |
2139 | - showing commands of THECLASS and C is not the help class */ | |
2140 | ||
2141 | /* If we show the class_alias and C is an alias, do not recurse, | |
2142 | as this would show the (possibly very long) not very useful | |
2143 | list of sub-commands of the aliased command. */ | |
2144 | print_help_for_command | |
eccd14b3 | 2145 | (*c, |
1be99b11 | 2146 | recurse && (theclass != class_alias || !c->is_alias ()), |
3b3aaacb PW |
2147 | stream); |
2148 | continue; | |
2149 | } | |
2150 | ||
2151 | if (recurse | |
2152 | && (theclass == class_user || theclass == class_alias) | |
3d0b3564 | 2153 | && c->is_prefix ()) |
3b3aaacb PW |
2154 | { |
2155 | /* User-defined commands or aliases may be subcommands. */ | |
14b42fc4 | 2156 | help_cmd_list (*c->subcommands, theclass, recurse, stream); |
3b3aaacb PW |
2157 | continue; |
2158 | } | |
2159 | ||
2160 | /* Do not show C or recurse on C, e.g. because C does not belong to | |
2161 | THECLASS or because C is a help class. */ | |
c906108c SS |
2162 | } |
2163 | } | |
c906108c | 2164 | \f |
c5aa993b | 2165 | |
c906108c SS |
2166 | /* Search the input clist for 'command'. Return the command if |
2167 | found (or NULL if not), and return the number of commands | |
ebcd3b23 | 2168 | found in nfound. */ |
c906108c SS |
2169 | |
2170 | static struct cmd_list_element * | |
6f937416 | 2171 | find_cmd (const char *command, int len, struct cmd_list_element *clist, |
fba45db2 | 2172 | int ignore_help_classes, int *nfound) |
c906108c SS |
2173 | { |
2174 | struct cmd_list_element *found, *c; | |
2175 | ||
b03e6ad9 | 2176 | found = NULL; |
c906108c SS |
2177 | *nfound = 0; |
2178 | for (c = clist; c; c = c->next) | |
2179 | if (!strncmp (command, c->name, len) | |
034dce7a | 2180 | && (!ignore_help_classes || !c->is_command_class_help ())) |
c906108c | 2181 | { |
c5aa993b JM |
2182 | found = c; |
2183 | (*nfound)++; | |
2184 | if (c->name[len] == '\0') | |
2185 | { | |
2186 | *nfound = 1; | |
2187 | break; | |
2188 | } | |
c906108c SS |
2189 | } |
2190 | return found; | |
2191 | } | |
2192 | ||
604c4576 JG |
2193 | /* Return the length of command name in TEXT. */ |
2194 | ||
2195 | int | |
3386243e AS |
2196 | find_command_name_length (const char *text) |
2197 | { | |
2198 | const char *p = text; | |
2199 | ||
2200 | /* Treating underscores as part of command words is important | |
2201 | so that "set args_foo()" doesn't get interpreted as | |
2202 | "set args _foo()". */ | |
ebcd3b23 MS |
2203 | /* Some characters are only used for TUI specific commands. |
2204 | However, they are always allowed for the sake of consistency. | |
2205 | ||
ebcd3b23 MS |
2206 | Note that this is larger than the character set allowed when |
2207 | creating user-defined commands. */ | |
2208 | ||
947d3946 | 2209 | /* Recognize the single character commands so that, e.g., "!ls" |
ed59ded5 | 2210 | works as expected. */ |
947d3946 | 2211 | if (*p == '!' || *p == '|') |
ed59ded5 DE |
2212 | return 1; |
2213 | ||
be09caf1 | 2214 | while (valid_cmd_char_p (*p) |
3386243e | 2215 | /* Characters used by TUI specific commands. */ |
4f45d445 | 2216 | || *p == '+' || *p == '<' || *p == '>' || *p == '$') |
3386243e AS |
2217 | p++; |
2218 | ||
2219 | return p - text; | |
2220 | } | |
2221 | ||
be09caf1 PW |
2222 | /* See command.h. */ |
2223 | ||
2224 | bool | |
2225 | valid_cmd_char_p (int c) | |
2226 | { | |
2227 | /* Alas "42" is a legitimate user-defined command. | |
2228 | In the interests of not breaking anything we preserve that. */ | |
2229 | ||
2230 | return isalnum (c) || c == '-' || c == '_' || c == '.'; | |
2231 | } | |
2232 | ||
2233 | /* See command.h. */ | |
5a56e9c5 | 2234 | |
7f008c9e | 2235 | bool |
5a56e9c5 DE |
2236 | valid_user_defined_cmd_name_p (const char *name) |
2237 | { | |
2238 | const char *p; | |
2239 | ||
2240 | if (*name == '\0') | |
7f008c9e | 2241 | return false; |
5a56e9c5 | 2242 | |
5a56e9c5 DE |
2243 | for (p = name; *p != '\0'; ++p) |
2244 | { | |
be09caf1 | 2245 | if (valid_cmd_char_p (*p)) |
5a56e9c5 DE |
2246 | ; /* Ok. */ |
2247 | else | |
7f008c9e | 2248 | return false; |
5a56e9c5 DE |
2249 | } |
2250 | ||
7f008c9e | 2251 | return true; |
5a56e9c5 DE |
2252 | } |
2253 | ||
1536146f | 2254 | /* See command.h. */ |
c906108c SS |
2255 | |
2256 | struct cmd_list_element * | |
6f937416 | 2257 | lookup_cmd_1 (const char **text, struct cmd_list_element *clist, |
cf00cd6f | 2258 | struct cmd_list_element **result_list, std::string *default_args, |
1536146f | 2259 | int ignore_help_classes, bool lookup_for_completion_p) |
c906108c | 2260 | { |
3386243e | 2261 | char *command; |
798a7429 | 2262 | int len, nfound; |
c906108c | 2263 | struct cmd_list_element *found, *c; |
cf00cd6f | 2264 | bool found_alias = false; |
6f937416 | 2265 | const char *line = *text; |
c906108c SS |
2266 | |
2267 | while (**text == ' ' || **text == '\t') | |
2268 | (*text)++; | |
2269 | ||
3386243e AS |
2270 | /* Identify the name of the command. */ |
2271 | len = find_command_name_length (*text); | |
c906108c SS |
2272 | |
2273 | /* If nothing but whitespace, return 0. */ | |
3386243e | 2274 | if (len == 0) |
c906108c | 2275 | return 0; |
c5aa993b | 2276 | |
c906108c | 2277 | /* *text and p now bracket the first command word to lookup (and |
ebcd3b23 | 2278 | it's length is len). We copy this into a local temporary. */ |
c906108c SS |
2279 | |
2280 | ||
2281 | command = (char *) alloca (len + 1); | |
22ad7fee | 2282 | memcpy (command, *text, len); |
c906108c SS |
2283 | command[len] = '\0'; |
2284 | ||
2285 | /* Look it up. */ | |
2286 | found = 0; | |
2287 | nfound = 0; | |
c5aa993b | 2288 | found = find_cmd (command, len, clist, ignore_help_classes, &nfound); |
c906108c | 2289 | |
c906108c SS |
2290 | /* If nothing matches, we have a simple failure. */ |
2291 | if (nfound == 0) | |
2292 | return 0; | |
2293 | ||
2294 | if (nfound > 1) | |
2295 | { | |
cf00cd6f | 2296 | if (result_list != nullptr) |
c906108c SS |
2297 | /* Will be modified in calling routine |
2298 | if we know what the prefix command is. */ | |
c5aa993b | 2299 | *result_list = 0; |
cf00cd6f PW |
2300 | if (default_args != nullptr) |
2301 | *default_args = std::string (); | |
1427fe5e | 2302 | return CMD_LIST_AMBIGUOUS; /* Ambiguous. */ |
c906108c SS |
2303 | } |
2304 | ||
ebcd3b23 | 2305 | /* We've matched something on this list. Move text pointer forward. */ |
c906108c | 2306 | |
3386243e | 2307 | *text += len; |
c906108c | 2308 | |
1be99b11 | 2309 | if (found->is_alias ()) |
56382845 | 2310 | { |
ebcd3b23 MS |
2311 | /* We drop the alias (abbreviation) in favor of the command it |
2312 | is pointing to. If the alias is deprecated, though, we need to | |
56382845 FN |
2313 | warn the user about it before we drop it. Note that while we |
2314 | are warning about the alias, we may also warn about the command | |
2315 | itself and we will adjust the appropriate DEPRECATED_WARN_USER | |
ebcd3b23 | 2316 | flags. */ |
cf00cd6f | 2317 | |
1536146f | 2318 | if (found->deprecated_warn_user && !lookup_for_completion_p) |
9ef6d4a1 | 2319 | deprecated_cmd_warning (line, clist); |
cf00cd6f | 2320 | |
44c77c32 | 2321 | |
cf00cd6f PW |
2322 | /* Return the default_args of the alias, not the default_args |
2323 | of the command it is pointing to. */ | |
2324 | if (default_args != nullptr) | |
2325 | *default_args = found->default_args; | |
99858724 | 2326 | found = found->alias_target; |
cf00cd6f | 2327 | found_alias = true; |
56382845 | 2328 | } |
c906108c SS |
2329 | /* If we found a prefix command, keep looking. */ |
2330 | ||
3d0b3564 | 2331 | if (found->is_prefix ()) |
c906108c | 2332 | { |
14b42fc4 | 2333 | c = lookup_cmd_1 (text, *found->subcommands, result_list, default_args, |
1536146f | 2334 | ignore_help_classes, lookup_for_completion_p); |
c906108c SS |
2335 | if (!c) |
2336 | { | |
2337 | /* Didn't find anything; this is as far as we got. */ | |
cf00cd6f | 2338 | if (result_list != nullptr) |
c906108c | 2339 | *result_list = clist; |
cf00cd6f PW |
2340 | if (!found_alias && default_args != nullptr) |
2341 | *default_args = found->default_args; | |
c906108c SS |
2342 | return found; |
2343 | } | |
1427fe5e | 2344 | else if (c == CMD_LIST_AMBIGUOUS) |
c906108c | 2345 | { |
ebcd3b23 MS |
2346 | /* We've gotten this far properly, but the next step is |
2347 | ambiguous. We need to set the result list to the best | |
c906108c | 2348 | we've found (if an inferior hasn't already set it). */ |
cf00cd6f | 2349 | if (result_list != nullptr) |
c906108c | 2350 | if (!*result_list) |
14b42fc4 | 2351 | /* This used to say *result_list = *found->subcommands. |
dda83cd7 SM |
2352 | If that was correct, need to modify the documentation |
2353 | at the top of this function to clarify what is | |
2354 | supposed to be going on. */ | |
c906108c | 2355 | *result_list = found; |
cf00cd6f PW |
2356 | /* For ambiguous commands, do not return any default_args args. */ |
2357 | if (default_args != nullptr) | |
2358 | *default_args = std::string (); | |
c906108c SS |
2359 | return c; |
2360 | } | |
2361 | else | |
2362 | { | |
2363 | /* We matched! */ | |
2364 | return c; | |
2365 | } | |
2366 | } | |
2367 | else | |
2368 | { | |
cf00cd6f | 2369 | if (result_list != nullptr) |
c906108c | 2370 | *result_list = clist; |
cf00cd6f PW |
2371 | if (!found_alias && default_args != nullptr) |
2372 | *default_args = found->default_args; | |
c906108c SS |
2373 | return found; |
2374 | } | |
2375 | } | |
2376 | ||
2377 | /* All this hair to move the space to the front of cmdtype */ | |
2378 | ||
2379 | static void | |
6f937416 | 2380 | undef_cmd_error (const char *cmdtype, const char *q) |
c906108c | 2381 | { |
8a3fe4f8 | 2382 | error (_("Undefined %scommand: \"%s\". Try \"help%s%.*s\"."), |
c5aa993b JM |
2383 | cmdtype, |
2384 | q, | |
2385 | *cmdtype ? " " : "", | |
823ca731 | 2386 | (int) strlen (cmdtype) - 1, |
c5aa993b | 2387 | cmdtype); |
c906108c SS |
2388 | } |
2389 | ||
2390 | /* Look up the contents of *LINE as a command in the command list LIST. | |
2391 | LIST is a chain of struct cmd_list_element's. | |
cf00cd6f PW |
2392 | If it is found, return the struct cmd_list_element for that command, |
2393 | update *LINE to point after the command name, at the first argument | |
2394 | and update *DEFAULT_ARGS (if DEFAULT_ARGS is not null) to the default | |
2395 | args to prepend to the user provided args when running the command. | |
2396 | Note that if the found cmd_list_element is found via an alias, | |
2397 | the default args of the alias are returned. | |
2398 | ||
c906108c SS |
2399 | If not found, call error if ALLOW_UNKNOWN is zero |
2400 | otherwise (or if error returns) return zero. | |
2401 | Call error if specified command is ambiguous, | |
2402 | unless ALLOW_UNKNOWN is negative. | |
2403 | CMDTYPE precedes the word "command" in the error message. | |
2404 | ||
30baf67b | 2405 | If IGNORE_HELP_CLASSES is nonzero, ignore any command list |
c906108c SS |
2406 | elements which are actually help classes rather than commands (i.e. |
2407 | the function field of the struct cmd_list_element is 0). */ | |
2408 | ||
2409 | struct cmd_list_element * | |
a121b7c1 PA |
2410 | lookup_cmd (const char **line, struct cmd_list_element *list, |
2411 | const char *cmdtype, | |
cf00cd6f | 2412 | std::string *default_args, |
fba45db2 | 2413 | int allow_unknown, int ignore_help_classes) |
c906108c SS |
2414 | { |
2415 | struct cmd_list_element *last_list = 0; | |
3cebf8d8 | 2416 | struct cmd_list_element *c; |
c64601c7 FN |
2417 | |
2418 | /* Note: Do not remove trailing whitespace here because this | |
2419 | would be wrong for complete_command. Jim Kingdon */ | |
c5aa993b | 2420 | |
3cebf8d8 MS |
2421 | if (!*line) |
2422 | error (_("Lack of needed %scommand"), cmdtype); | |
2423 | ||
cf00cd6f | 2424 | c = lookup_cmd_1 (line, list, &last_list, default_args, ignore_help_classes); |
3cebf8d8 | 2425 | |
c906108c SS |
2426 | if (!c) |
2427 | { | |
2428 | if (!allow_unknown) | |
2429 | { | |
3cebf8d8 MS |
2430 | char *q; |
2431 | int len = find_command_name_length (*line); | |
c906108c | 2432 | |
3cebf8d8 MS |
2433 | q = (char *) alloca (len + 1); |
2434 | strncpy (q, *line, len); | |
2435 | q[len] = '\0'; | |
2436 | undef_cmd_error (cmdtype, q); | |
c906108c SS |
2437 | } |
2438 | else | |
2439 | return 0; | |
2440 | } | |
1427fe5e | 2441 | else if (c == CMD_LIST_AMBIGUOUS) |
c906108c | 2442 | { |
6fdebf12 | 2443 | /* Ambiguous. Local values should be off subcommands or called |
dda83cd7 | 2444 | values. */ |
c906108c SS |
2445 | int local_allow_unknown = (last_list ? last_list->allow_unknown : |
2446 | allow_unknown); | |
2f822da5 MB |
2447 | std::string local_cmdtype |
2448 | = last_list ? last_list->prefixname () : cmdtype; | |
c906108c | 2449 | struct cmd_list_element *local_list = |
14b42fc4 | 2450 | (last_list ? *(last_list->subcommands) : list); |
c5aa993b | 2451 | |
c906108c SS |
2452 | if (local_allow_unknown < 0) |
2453 | { | |
2454 | if (last_list) | |
2455 | return last_list; /* Found something. */ | |
2456 | else | |
2457 | return 0; /* Found nothing. */ | |
2458 | } | |
2459 | else | |
2460 | { | |
2461 | /* Report as error. */ | |
2462 | int amb_len; | |
2463 | char ambbuf[100]; | |
2464 | ||
2465 | for (amb_len = 0; | |
2466 | ((*line)[amb_len] && (*line)[amb_len] != ' ' | |
2467 | && (*line)[amb_len] != '\t'); | |
2468 | amb_len++) | |
2469 | ; | |
c5aa993b | 2470 | |
c906108c SS |
2471 | ambbuf[0] = 0; |
2472 | for (c = local_list; c; c = c->next) | |
2473 | if (!strncmp (*line, c->name, amb_len)) | |
2474 | { | |
9a2b4c1b MS |
2475 | if (strlen (ambbuf) + strlen (c->name) + 6 |
2476 | < (int) sizeof ambbuf) | |
c906108c SS |
2477 | { |
2478 | if (strlen (ambbuf)) | |
2479 | strcat (ambbuf, ", "); | |
2480 | strcat (ambbuf, c->name); | |
2481 | } | |
2482 | else | |
2483 | { | |
2484 | strcat (ambbuf, ".."); | |
2485 | break; | |
2486 | } | |
2487 | } | |
2f822da5 MB |
2488 | error (_("Ambiguous %scommand \"%s\": %s."), |
2489 | local_cmdtype.c_str (), *line, ambbuf); | |
c906108c SS |
2490 | } |
2491 | } | |
2492 | else | |
2493 | { | |
bf9e4d0c | 2494 | if (c->type == set_cmd && **line != '\0' && !isspace (**line)) |
dda83cd7 | 2495 | error (_("Argument must be preceded by space.")); |
bf9e4d0c | 2496 | |
c906108c | 2497 | /* We've got something. It may still not be what the caller |
dda83cd7 | 2498 | wants (if this command *needs* a subcommand). */ |
c906108c SS |
2499 | while (**line == ' ' || **line == '\t') |
2500 | (*line)++; | |
2501 | ||
3d0b3564 | 2502 | if (c->is_prefix () && **line && !c->allow_unknown) |
2f822da5 | 2503 | undef_cmd_error (c->prefixname ().c_str (), *line); |
c906108c SS |
2504 | |
2505 | /* Seems to be what he wants. Return it. */ | |
2506 | return c; | |
2507 | } | |
2508 | return 0; | |
2509 | } | |
c5aa993b | 2510 | |
a9b49cbc MB |
2511 | /* See command.h. */ |
2512 | ||
2513 | struct cmd_list_element * | |
2514 | lookup_cmd_exact (const char *name, | |
2515 | struct cmd_list_element *list, | |
2516 | bool ignore_help_classes) | |
2517 | { | |
2518 | const char *tem = name; | |
2519 | struct cmd_list_element *cmd = lookup_cmd (&tem, list, "", NULL, -1, | |
2520 | ignore_help_classes); | |
2521 | if (cmd != nullptr && strcmp (name, cmd->name) != 0) | |
2522 | cmd = nullptr; | |
2523 | return cmd; | |
2524 | } | |
2525 | ||
6f937416 | 2526 | /* We are here presumably because an alias or command in TEXT is |
ebcd3b23 | 2527 | deprecated and a warning message should be generated. This |
6f937416 | 2528 | function decodes TEXT and potentially generates a warning message |
ebcd3b23 | 2529 | as outlined below. |
56382845 FN |
2530 | |
2531 | Example for 'set endian big' which has a fictitious alias 'seb'. | |
2532 | ||
6f937416 | 2533 | If alias wasn't used in TEXT, and the command is deprecated: |
56382845 FN |
2534 | "warning: 'set endian big' is deprecated." |
2535 | ||
2536 | If alias was used, and only the alias is deprecated: | |
2537 | "warning: 'seb' an alias for the command 'set endian big' is deprecated." | |
2538 | ||
ebcd3b23 MS |
2539 | If alias was used and command is deprecated (regardless of whether |
2540 | the alias itself is deprecated: | |
56382845 FN |
2541 | |
2542 | "warning: 'set endian big' (seb) is deprecated." | |
2543 | ||
2544 | After the message has been sent, clear the appropriate flags in the | |
2545 | command and/or the alias so the user is no longer bothered. | |
2546 | ||
2547 | */ | |
2548 | void | |
9ef6d4a1 | 2549 | deprecated_cmd_warning (const char *text, struct cmd_list_element *list) |
56382845 | 2550 | { |
44c77c32 | 2551 | struct cmd_list_element *alias = nullptr; |
44c77c32 | 2552 | struct cmd_list_element *cmd = nullptr; |
edefbb7c | 2553 | |
19c659f1 AB |
2554 | /* Return if text doesn't evaluate to a command. We place this lookup |
2555 | within its own scope so that the PREFIX_CMD local is not visible | |
2556 | later in this function. The value returned in PREFIX_CMD is based on | |
2557 | the prefix found in TEXT, and is our case this prefix can be missing | |
2558 | in some situations (when LIST is not the global CMDLIST). | |
2559 | ||
2560 | It is better for our purposes to use the prefix commands directly from | |
2561 | the ALIAS and CMD results. */ | |
2562 | { | |
2563 | struct cmd_list_element *prefix_cmd = nullptr; | |
2564 | if (!lookup_cmd_composition_1 (text, &alias, &prefix_cmd, &cmd, list)) | |
2565 | return; | |
2566 | } | |
56382845 | 2567 | |
44c77c32 AB |
2568 | /* Return if nothing is deprecated. */ |
2569 | if (!((alias != nullptr ? alias->deprecated_warn_user : 0) | |
2570 | || cmd->deprecated_warn_user)) | |
56382845 | 2571 | return; |
56382845 | 2572 | |
44c77c32 AB |
2573 | /* Join command prefix (if any) and the command name. */ |
2574 | std::string tmp_cmd_str; | |
19c659f1 | 2575 | if (cmd->prefix != nullptr) |
2f822da5 | 2576 | tmp_cmd_str += cmd->prefix->prefixname (); |
44c77c32 | 2577 | tmp_cmd_str += std::string (cmd->name); |
56382845 | 2578 | |
44c77c32 AB |
2579 | /* Display the appropriate first line, this warns that the thing the user |
2580 | entered is deprecated. */ | |
2581 | if (alias != nullptr) | |
56382845 | 2582 | { |
19c659f1 AB |
2583 | /* Join the alias prefix (if any) and the alias name. */ |
2584 | std::string tmp_alias_str; | |
2585 | if (alias->prefix != nullptr) | |
2f822da5 | 2586 | tmp_alias_str += alias->prefix->prefixname (); |
19c659f1 AB |
2587 | tmp_alias_str += std::string (alias->name); |
2588 | ||
44c77c32 | 2589 | if (cmd->cmd_deprecated) |
6cb06a8c | 2590 | gdb_printf (_("Warning: command '%ps' (%ps) is deprecated.\n"), |
b5f91cd4 | 2591 | styled_string (command_style.style (), |
6cb06a8c | 2592 | tmp_cmd_str.c_str ()), |
b5f91cd4 | 2593 | styled_string (command_style.style (), |
6cb06a8c | 2594 | tmp_alias_str.c_str ())); |
56382845 | 2595 | else |
6cb06a8c TT |
2596 | gdb_printf (_("Warning: '%ps', an alias for the command '%ps', " |
2597 | "is deprecated.\n"), | |
b5f91cd4 | 2598 | styled_string (command_style.style (), |
6cb06a8c | 2599 | tmp_alias_str.c_str ()), |
b5f91cd4 | 2600 | styled_string (command_style.style (), |
6cb06a8c | 2601 | tmp_cmd_str.c_str ())); |
56382845 | 2602 | } |
44c77c32 | 2603 | else |
6cb06a8c | 2604 | gdb_printf (_("Warning: command '%ps' is deprecated.\n"), |
b5f91cd4 | 2605 | styled_string (command_style.style (), |
6cb06a8c | 2606 | tmp_cmd_str.c_str ())); |
44c77c32 AB |
2607 | |
2608 | /* Now display a second line indicating what the user should use instead. | |
2609 | If it is only the alias that is deprecated, we want to indicate the | |
2610 | new alias, otherwise we'll indicate the new command. */ | |
2611 | const char *replacement; | |
2612 | if (alias != nullptr && !cmd->cmd_deprecated) | |
2613 | replacement = alias->replacement; | |
2614 | else | |
2615 | replacement = cmd->replacement; | |
2616 | if (replacement != nullptr) | |
6cb06a8c | 2617 | gdb_printf (_("Use '%ps'.\n\n"), |
b5f91cd4 | 2618 | styled_string (command_style.style (), |
6cb06a8c | 2619 | replacement)); |
44c77c32 | 2620 | else |
6cb06a8c | 2621 | gdb_printf (_("No alternative known.\n\n")); |
56382845 | 2622 | |
ebcd3b23 | 2623 | /* We've warned you, now we'll keep quiet. */ |
44c77c32 | 2624 | if (alias != nullptr) |
1f2bdf09 | 2625 | alias->deprecated_warn_user = 0; |
1f2bdf09 | 2626 | cmd->deprecated_warn_user = 0; |
56382845 FN |
2627 | } |
2628 | ||
9ef6d4a1 | 2629 | /* Look up the contents of TEXT as a command in the command list CUR_LIST. |
56382845 | 2630 | Return 1 on success, 0 on failure. |
bc3609fd PW |
2631 | |
2632 | If TEXT refers to an alias, *ALIAS will point to that alias. | |
2633 | ||
2634 | If TEXT is a subcommand (i.e. one that is preceded by a prefix | |
2635 | command) set *PREFIX_CMD. | |
2636 | ||
276d9db2 HD |
2637 | Set *CMD to point to the command TEXT indicates, or to |
2638 | CMD_LIST_AMBIGUOUS if there are multiple possible matches. | |
bc3609fd PW |
2639 | |
2640 | If any of *ALIAS, *PREFIX_CMD, or *CMD cannot be determined or do not | |
56382845 | 2641 | exist, they are NULL when we return. |
bc3609fd | 2642 | |
56382845 | 2643 | */ |
9ef6d4a1 AB |
2644 | |
2645 | static int | |
2646 | lookup_cmd_composition_1 (const char *text, | |
2647 | struct cmd_list_element **alias, | |
2648 | struct cmd_list_element **prefix_cmd, | |
2649 | struct cmd_list_element **cmd, | |
2650 | struct cmd_list_element *cur_list) | |
56382845 | 2651 | { |
19c659f1 AB |
2652 | *alias = nullptr; |
2653 | *prefix_cmd = cur_list->prefix; | |
2654 | *cmd = nullptr; | |
bc3609fd | 2655 | |
0605465f PW |
2656 | text = skip_spaces (text); |
2657 | ||
19c659f1 AB |
2658 | /* Go through as many command lists as we need to, to find the command |
2659 | TEXT refers to. */ | |
56382845 | 2660 | while (1) |
bc3609fd | 2661 | { |
3386243e | 2662 | /* Identify the name of the command. */ |
19c659f1 | 2663 | int len = find_command_name_length (text); |
bc3609fd | 2664 | |
56382845 | 2665 | /* If nothing but whitespace, return. */ |
3386243e AS |
2666 | if (len == 0) |
2667 | return 0; | |
bc3609fd PW |
2668 | |
2669 | /* TEXT is the start of the first command word to lookup (and | |
0605465f | 2670 | it's length is LEN). We copy this into a local temporary. */ |
19c659f1 | 2671 | std::string command (text, len); |
bc3609fd | 2672 | |
56382845 | 2673 | /* Look it up. */ |
19c659f1 AB |
2674 | int nfound = 0; |
2675 | *cmd = find_cmd (command.c_str (), len, cur_list, 1, &nfound); | |
bc3609fd | 2676 | |
19c659f1 | 2677 | /* We only handle the case where a single command was found. */ |
276d9db2 HD |
2678 | if (nfound > 1) |
2679 | { | |
2680 | *cmd = CMD_LIST_AMBIGUOUS; | |
2681 | return 0; | |
2682 | } | |
2683 | else if (*cmd == nullptr) | |
19c659f1 | 2684 | return 0; |
56382845 | 2685 | else |
cdb27c12 | 2686 | { |
1be99b11 | 2687 | if ((*cmd)->is_alias ()) |
cdb27c12 | 2688 | { |
19c659f1 AB |
2689 | /* If the command was actually an alias, we note that an |
2690 | alias was used (by assigning *ALIAS) and we set *CMD. */ | |
cdb27c12 | 2691 | *alias = *cmd; |
99858724 | 2692 | *cmd = (*cmd)->alias_target; |
cdb27c12 | 2693 | } |
cdb27c12 | 2694 | } |
0605465f PW |
2695 | |
2696 | text += len; | |
2697 | text = skip_spaces (text); | |
2698 | ||
3d0b3564 | 2699 | if ((*cmd)->is_prefix () && *text != '\0') |
19c659f1 | 2700 | { |
14b42fc4 | 2701 | cur_list = *(*cmd)->subcommands; |
19c659f1 AB |
2702 | *prefix_cmd = *cmd; |
2703 | } | |
56382845 | 2704 | else |
cdb27c12 | 2705 | return 1; |
56382845 FN |
2706 | } |
2707 | } | |
2708 | ||
9ef6d4a1 AB |
2709 | /* Look up the contents of TEXT as a command in the command list 'cmdlist'. |
2710 | Return 1 on success, 0 on failure. | |
2711 | ||
2712 | If TEXT refers to an alias, *ALIAS will point to that alias. | |
2713 | ||
2714 | If TEXT is a subcommand (i.e. one that is preceded by a prefix | |
2715 | command) set *PREFIX_CMD. | |
2716 | ||
276d9db2 HD |
2717 | Set *CMD to point to the command TEXT indicates, or to |
2718 | CMD_LIST_AMBIGUOUS if there are multiple possible matches. | |
9ef6d4a1 AB |
2719 | |
2720 | If any of *ALIAS, *PREFIX_CMD, or *CMD cannot be determined or do not | |
2721 | exist, they are NULL when we return. | |
2722 | ||
2723 | */ | |
2724 | ||
2725 | int | |
2726 | lookup_cmd_composition (const char *text, | |
2727 | struct cmd_list_element **alias, | |
2728 | struct cmd_list_element **prefix_cmd, | |
2729 | struct cmd_list_element **cmd) | |
2730 | { | |
2731 | return lookup_cmd_composition_1 (text, alias, prefix_cmd, cmd, cmdlist); | |
2732 | } | |
2733 | ||
c906108c SS |
2734 | /* Helper function for SYMBOL_COMPLETION_FUNCTION. */ |
2735 | ||
2736 | /* Return a vector of char pointers which point to the different | |
ebcd3b23 | 2737 | possible completions in LIST of TEXT. |
c906108c SS |
2738 | |
2739 | WORD points in the same buffer as TEXT, and completions should be | |
ebcd3b23 MS |
2740 | returned relative to this position. For example, suppose TEXT is |
2741 | "foo" and we want to complete to "foobar". If WORD is "oo", return | |
c906108c SS |
2742 | "oobar"; if WORD is "baz/foo", return "baz/foobar". */ |
2743 | ||
eb3ff9a5 | 2744 | void |
6f937416 | 2745 | complete_on_cmdlist (struct cmd_list_element *list, |
eb3ff9a5 | 2746 | completion_tracker &tracker, |
6f937416 | 2747 | const char *text, const char *word, |
ace21957 | 2748 | int ignore_help_classes) |
c906108c SS |
2749 | { |
2750 | struct cmd_list_element *ptr; | |
c906108c | 2751 | int textlen = strlen (text); |
3f172e24 TT |
2752 | int pass; |
2753 | int saw_deprecated_match = 0; | |
c906108c | 2754 | |
3f172e24 TT |
2755 | /* We do one or two passes. In the first pass, we skip deprecated |
2756 | commands. If we see no matching commands in the first pass, and | |
2757 | if we did happen to see a matching deprecated command, we do | |
2758 | another loop to collect those. */ | |
eb3ff9a5 | 2759 | for (pass = 0; pass < 2; ++pass) |
3f172e24 | 2760 | { |
eb3ff9a5 PA |
2761 | bool got_matches = false; |
2762 | ||
3f172e24 TT |
2763 | for (ptr = list; ptr; ptr = ptr->next) |
2764 | if (!strncmp (ptr->name, text, textlen) | |
2765 | && !ptr->abbrev_flag | |
034dce7a | 2766 | && (!ignore_help_classes || !ptr->is_command_class_help () |
3d0b3564 | 2767 | || ptr->is_prefix ())) |
c906108c | 2768 | { |
3f172e24 TT |
2769 | if (pass == 0) |
2770 | { | |
1f2bdf09 | 2771 | if (ptr->cmd_deprecated) |
3f172e24 TT |
2772 | { |
2773 | saw_deprecated_match = 1; | |
2774 | continue; | |
2775 | } | |
2776 | } | |
c906108c | 2777 | |
60a20c19 PA |
2778 | tracker.add_completion |
2779 | (make_completion_match_str (ptr->name, text, word)); | |
eb3ff9a5 | 2780 | got_matches = true; |
c906108c | 2781 | } |
eb3ff9a5 PA |
2782 | |
2783 | if (got_matches) | |
2784 | break; | |
2785 | ||
3f172e24 TT |
2786 | /* If we saw no matching deprecated commands in the first pass, |
2787 | just bail out. */ | |
2788 | if (!saw_deprecated_match) | |
2789 | break; | |
2790 | } | |
c906108c SS |
2791 | } |
2792 | ||
2793 | /* Helper function for SYMBOL_COMPLETION_FUNCTION. */ | |
2794 | ||
eb3ff9a5 | 2795 | /* Add the different possible completions in ENUMLIST of TEXT. |
c906108c SS |
2796 | |
2797 | WORD points in the same buffer as TEXT, and completions should be | |
2798 | returned relative to this position. For example, suppose TEXT is "foo" | |
2799 | and we want to complete to "foobar". If WORD is "oo", return | |
2800 | "oobar"; if WORD is "baz/foo", return "baz/foobar". */ | |
2801 | ||
eb3ff9a5 PA |
2802 | void |
2803 | complete_on_enum (completion_tracker &tracker, | |
2804 | const char *const *enumlist, | |
6f937416 | 2805 | const char *text, const char *word) |
c906108c | 2806 | { |
c906108c SS |
2807 | int textlen = strlen (text); |
2808 | int i; | |
53904c9e | 2809 | const char *name; |
c906108c | 2810 | |
c906108c SS |
2811 | for (i = 0; (name = enumlist[i]) != NULL; i++) |
2812 | if (strncmp (name, text, textlen) == 0) | |
60a20c19 | 2813 | tracker.add_completion (make_completion_match_str (name, text, word)); |
c906108c SS |
2814 | } |
2815 | ||
ebcd3b23 | 2816 | /* Call the command function. */ |
f436dd25 | 2817 | void |
95a6b0a1 | 2818 | cmd_func (struct cmd_list_element *cmd, const char *args, int from_tty) |
f436dd25 | 2819 | { |
034dce7a | 2820 | if (!cmd->is_command_class_help ()) |
4034d0ff | 2821 | { |
6b09f134 | 2822 | std::optional<scoped_restore_tmpl<bool>> restore_suppress; |
4034d0ff AT |
2823 | |
2824 | if (cmd->suppress_notification != NULL) | |
f36c8918 | 2825 | restore_suppress.emplace (cmd->suppress_notification, true); |
4034d0ff | 2826 | |
5538b03c | 2827 | cmd->func (args, from_tty, cmd); |
4034d0ff | 2828 | } |
f436dd25 | 2829 | else |
8a3fe4f8 | 2830 | error (_("Invalid command")); |
f436dd25 | 2831 | } |
a9f116cb GKB |
2832 | |
2833 | int | |
2834 | cli_user_command_p (struct cmd_list_element *cmd) | |
2835 | { | |
5538b03c | 2836 | return cmd->theclass == class_user && cmd->func == do_simple_func; |
a9f116cb | 2837 | } |
6447969d AP |
2838 | |
2839 | /* See cli-decode.h. */ | |
2840 | ||
2841 | ui_file_style::color | |
2842 | parse_cli_var_color (const char **args) | |
2843 | { | |
2844 | /* Do a "set" command. ARG is nullptr if no argument, or the | |
2845 | text of the argument. */ | |
2846 | ||
2847 | if (args == nullptr || *args == nullptr || **args == '\0') | |
2848 | { | |
2849 | std::string msg; | |
2850 | ||
2851 | for (size_t i = 0; ui_file_style::basic_color_enums[i]; ++i) | |
2852 | { | |
2853 | msg.append ("\""); | |
2854 | msg.append (ui_file_style::basic_color_enums[i]); | |
2855 | msg.append ("\", "); | |
2856 | } | |
2857 | ||
2858 | error (_("Requires an argument. Valid arguments are %sinteger from -1 " | |
2859 | "to 255 or an RGB hex triplet in a format #RRGGBB"), | |
2860 | msg.c_str ()); | |
2861 | } | |
2862 | ||
2863 | const char *p = skip_to_space (*args); | |
2864 | size_t len = p - *args; | |
2865 | ||
2866 | int nmatches = 0; | |
2867 | ui_file_style::basic_color match = ui_file_style::NONE; | |
2868 | for (int i = 0; ui_file_style::basic_color_enums[i]; ++i) | |
2869 | if (strncmp (*args, ui_file_style::basic_color_enums[i], len) == 0) | |
2870 | { | |
2871 | match = static_cast<ui_file_style::basic_color> (i - 1); | |
2872 | if (ui_file_style::basic_color_enums[i][len] == '\0') | |
2873 | { | |
2874 | nmatches = 1; | |
2875 | break; /* Exact match. */ | |
2876 | } | |
2877 | else | |
2878 | nmatches++; | |
2879 | } | |
2880 | ||
2881 | if (nmatches == 1) | |
2882 | { | |
2883 | *args += len; | |
2884 | return ui_file_style::color (match); | |
2885 | } | |
2886 | ||
2887 | if (nmatches > 1) | |
2888 | error (_("Ambiguous item \"%.*s\"."), (int) len, *args); | |
2889 | ||
2890 | if (**args != '#') | |
2891 | { | |
2892 | ULONGEST num = get_ulongest (args); | |
2893 | if (num > 255) | |
2894 | error (_("integer %s out of range"), pulongest (num)); | |
2895 | return ui_file_style::color (color_space::XTERM_256COLOR, | |
2896 | static_cast<int> (num)); | |
2897 | } | |
2898 | ||
2899 | /* Try to parse #RRGGBB string. */ | |
2900 | if (len != 7) | |
2901 | error_no_arg (_("invalid RGB hex triplet format")); | |
2902 | ||
4fed821e | 2903 | uint32_t rgb; |
6447969d AP |
2904 | uint8_t r, g, b; |
2905 | int scanned_chars = 0; | |
4fed821e TV |
2906 | int parsed_args = sscanf (*args, "#%6" SCNx32 "%n", |
2907 | &rgb, &scanned_chars); | |
6447969d | 2908 | |
4fed821e | 2909 | if (parsed_args != 1 || scanned_chars != 7) |
6447969d AP |
2910 | error_no_arg (_("invalid RGB hex triplet format")); |
2911 | ||
4fed821e TV |
2912 | gdb_assert ((rgb >> 24) == 0); |
2913 | r = (rgb >> 16) & 0xff; | |
2914 | g = (rgb >> 8) & 0xff; | |
2915 | b = rgb & 0xff; | |
2916 | ||
6447969d AP |
2917 | *args += len; |
2918 | return ui_file_style::color (r, g, b); | |
2919 | } | |
2920 | ||
2921 | /* See cli-decode.h. */ | |
2922 | ||
2923 | ui_file_style::color | |
2924 | parse_var_color (const char *arg) | |
2925 | { | |
2926 | const char *end_arg = arg; | |
2927 | ui_file_style::color color = parse_cli_var_color (&end_arg); | |
2928 | ||
2929 | int len = end_arg - arg; | |
2930 | const char *after = skip_spaces (end_arg); | |
2931 | if (*after != '\0') | |
2932 | error (_("Junk after item \"%.*s\": %s"), len, arg, after); | |
2933 | ||
2934 | return color; | |
2935 | } |