07d552b7f5bbdaff7bc6f11a4e5c0ba999879ef6
[deliverable/binutils-gdb.git] / gdb / cli / cli-option.c
1 /* CLI options framework, for GDB.
2
3 Copyright (C) 2017-2019 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21 #include "cli/cli-option.h"
22 #include "cli/cli-decode.h"
23 #include "cli/cli-utils.h"
24 #include "cli/cli-setshow.h"
25 #include "command.h"
26 #include <vector>
27
28 namespace gdb {
29 namespace option {
30
31 /* An option's value. Which field is active depends on the option's
32 type. */
33 union option_value
34 {
35 /* For var_boolean options. */
36 bool boolean;
37
38 /* For var_uinteger options. */
39 unsigned int uinteger;
40
41 /* For var_zuinteger_unlimited options. */
42 int integer;
43
44 /* For var_enum options. */
45 const char *enumeration;
46
47 /* For var_string options. This is malloc-allocated. */
48 char *string;
49 };
50
51 /* Holds an options definition and its value. */
52 struct option_def_and_value
53 {
54 /* The option definition. */
55 const option_def &option;
56
57 /* A context. */
58 void *ctx;
59
60 /* The option's value, if any. */
61 gdb::optional<option_value> value;
62
63 /* Constructor. */
64 option_def_and_value (const option_def &option_, void *ctx_,
65 gdb::optional<option_value> &&value_ = {})
66 : option (option_),
67 ctx (ctx_),
68 value (std::move (value_))
69 {
70 clear_value (option_, value_);
71 }
72
73 /* Move constructor. Need this because for some types the values
74 are allocated on the heap. */
75 option_def_and_value (option_def_and_value &&rval)
76 : option (rval.option),
77 ctx (rval.ctx),
78 value (std::move (rval.value))
79 {
80 clear_value (rval.option, rval.value);
81 }
82
83 DISABLE_COPY_AND_ASSIGN (option_def_and_value);
84
85 ~option_def_and_value ()
86 {
87 if (value.has_value ())
88 {
89 if (option.type == var_string)
90 xfree (value->string);
91 }
92 }
93
94 private:
95
96 /* Clear the option_value, without releasing it. This is used after
97 the value has been moved to some other option_def_and_value
98 instance. This is needed because for some types the value is
99 allocated on the heap, so we must clear the pointer in the
100 source, to avoid a double free. */
101 static void clear_value (const option_def &option,
102 gdb::optional<option_value> &value)
103 {
104 if (value.has_value ())
105 {
106 if (option.type == var_string)
107 value->string = nullptr;
108 }
109 }
110 };
111
112 static void save_option_value_in_ctx (gdb::optional<option_def_and_value> &ov);
113
114 /* Info passed around when handling completion. */
115 struct parse_option_completion_info
116 {
117 /* The completion word. */
118 const char *word;
119
120 /* The tracker. */
121 completion_tracker &tracker;
122 };
123
124 /* If ARGS starts with "-", look for a "--" delimiter. If one is
125 found, then interpret everything up until the "--" as command line
126 options. Otherwise, interpret unknown input as the beginning of
127 the command's operands. */
128
129 static const char *
130 find_end_options_delimiter (const char *args)
131 {
132 if (args[0] == '-')
133 {
134 const char *p = args;
135
136 p = skip_spaces (p);
137 while (*p)
138 {
139 if (check_for_argument (&p, "--"))
140 return p;
141 else
142 p = skip_to_space (p);
143 p = skip_spaces (p);
144 }
145 }
146
147 return nullptr;
148 }
149
150 /* Complete TEXT/WORD on all options in OPTIONS_GROUP. */
151
152 static void
153 complete_on_options (gdb::array_view<const option_def_group> options_group,
154 completion_tracker &tracker,
155 const char *text, const char *word)
156 {
157 size_t textlen = strlen (text);
158 for (const auto &grp : options_group)
159 for (const auto &opt : grp.options)
160 if (strncmp (opt.name, text, textlen) == 0)
161 {
162 tracker.add_completion
163 (make_completion_match_str (opt.name, text, word));
164 }
165 }
166
167 /* See cli-option.h. */
168
169 void
170 complete_on_all_options (completion_tracker &tracker,
171 gdb::array_view<const option_def_group> options_group)
172 {
173 static const char opt[] = "-";
174 complete_on_options (options_group, tracker, opt + 1, opt);
175 }
176
177 /* Parse ARGS, guided by OPTIONS_GROUP. HAVE_DELIMITER is true if the
178 whole ARGS line included the "--" options-terminator delimiter. */
179
180 static gdb::optional<option_def_and_value>
181 parse_option (gdb::array_view<const option_def_group> options_group,
182 process_options_mode mode,
183 bool have_delimiter,
184 const char **args,
185 parse_option_completion_info *completion = nullptr)
186 {
187 if (*args == nullptr)
188 return {};
189 else if (**args != '-')
190 {
191 if (have_delimiter)
192 error (_("Unrecognized option at: %s"), *args);
193 return {};
194 }
195 else if (check_for_argument (args, "--"))
196 return {};
197
198 /* Skip the initial '-'. */
199 const char *arg = *args + 1;
200
201 const char *after = skip_to_space (arg);
202 size_t len = after - arg;
203 const option_def *match = nullptr;
204 void *match_ctx = nullptr;
205
206 for (const auto &grp : options_group)
207 {
208 for (const auto &o : grp.options)
209 {
210 if (strncmp (o.name, arg, len) == 0)
211 {
212 if (match != nullptr)
213 {
214 if (completion != nullptr && arg[len] == '\0')
215 {
216 complete_on_options (options_group,
217 completion->tracker,
218 arg, completion->word);
219 return {};
220 }
221
222 error (_("Ambiguous option at: -%s"), arg);
223 }
224
225 match = &o;
226 match_ctx = grp.ctx;
227
228 if ((isspace (arg[len]) || arg[len] == '\0')
229 && strlen (o.name) == len)
230 break; /* Exact match. */
231 }
232 }
233 }
234
235 if (match == nullptr)
236 {
237 if (have_delimiter || mode != PROCESS_OPTIONS_UNKNOWN_IS_OPERAND)
238 error (_("Unrecognized option at: %s"), *args);
239
240 return {};
241 }
242
243 if (completion != nullptr && arg[len] == '\0')
244 {
245 complete_on_options (options_group, completion->tracker,
246 arg, completion->word);
247 return {};
248 }
249
250 *args += 1 + len;
251 *args = skip_spaces (*args);
252 if (completion != nullptr)
253 completion->word = *args;
254
255 switch (match->type)
256 {
257 case var_boolean:
258 {
259 if (!match->have_argument)
260 {
261 option_value val;
262 val.boolean = true;
263 return option_def_and_value {*match, match_ctx, val};
264 }
265
266 const char *val_str = *args;
267 int res;
268
269 if (**args == '\0' && completion != nullptr)
270 {
271 /* Complete on both "on/off" and more options. */
272
273 if (mode == PROCESS_OPTIONS_REQUIRE_DELIMITER)
274 {
275 complete_on_enum (completion->tracker,
276 boolean_enums, val_str, val_str);
277 complete_on_all_options (completion->tracker, options_group);
278 }
279 return option_def_and_value {*match, match_ctx};
280 }
281 else if (**args == '-')
282 {
283 /* Treat:
284 "cmd -boolean-option -another-opt..."
285 as:
286 "cmd -boolean-option on -another-opt..."
287 */
288 res = 1;
289 }
290 else if (**args == '\0')
291 {
292 /* Treat:
293 (1) "cmd -boolean-option "
294 as:
295 (1) "cmd -boolean-option on"
296 */
297 res = 1;
298 }
299 else
300 {
301 res = parse_cli_boolean_value (args);
302 if (res < 0)
303 {
304 const char *end = skip_to_space (*args);
305 if (completion != nullptr)
306 {
307 if (*end == '\0')
308 {
309 complete_on_enum (completion->tracker,
310 boolean_enums, val_str, val_str);
311 return option_def_and_value {*match, match_ctx};
312 }
313 }
314
315 if (have_delimiter)
316 error (_("Value given for `-%s' is not a boolean: %.*s"),
317 match->name, (int) (end - val_str), val_str);
318 /* The user didn't separate options from operands
319 using "--", so treat this unrecognized value as the
320 start of the operands. This makes "frame apply all
321 -past-main CMD" work. */
322 return option_def_and_value {*match, match_ctx};
323 }
324 else if (completion != nullptr && **args == '\0')
325 {
326 /* While "cmd -boolean [TAB]" only offers "on" and
327 "off", the boolean option actually accepts "1",
328 "yes", etc. as boolean values. We complete on all
329 of those instead of BOOLEAN_ENUMS here to make
330 these work:
331
332 "p -object 1[TAB]" -> "p -object 1 "
333 "p -object ye[TAB]" -> "p -object yes "
334
335 Etc. Note that it's important that the space is
336 auto-appended. Otherwise, if we only completed on
337 on/off here, then it might look to the user like
338 "1" isn't valid, like:
339 "p -object 1[TAB]" -> "p -object 1" (i.e., nothing happens).
340 */
341 static const char *const all_boolean_enums[] = {
342 "on", "off",
343 "yes", "no",
344 "enable", "disable",
345 "0", "1",
346 nullptr,
347 };
348 complete_on_enum (completion->tracker, all_boolean_enums,
349 val_str, val_str);
350 return {};
351 }
352 }
353
354 option_value val;
355 val.boolean = res;
356 return option_def_and_value {*match, match_ctx, val};
357 }
358 case var_uinteger:
359 case var_zuinteger_unlimited:
360 {
361 if (completion != nullptr)
362 {
363 if (**args == '\0')
364 {
365 /* Convenience to let the user know what the option
366 can accept. Note there's no common prefix between
367 the strings on purpose, so that readline doesn't do
368 a partial match. */
369 completion->tracker.add_completion
370 (make_unique_xstrdup ("NUMBER"));
371 completion->tracker.add_completion
372 (make_unique_xstrdup ("unlimited"));
373 return {};
374 }
375 else if (startswith ("unlimited", *args))
376 {
377 completion->tracker.add_completion
378 (make_unique_xstrdup ("unlimited"));
379 return {};
380 }
381 }
382
383 if (match->type == var_zuinteger_unlimited)
384 {
385 option_value val;
386 val.integer = parse_cli_var_zuinteger_unlimited (args, false);
387 return option_def_and_value {*match, match_ctx, val};
388 }
389 else
390 {
391 option_value val;
392 val.uinteger = parse_cli_var_uinteger (match->type, args, false);
393 return option_def_and_value {*match, match_ctx, val};
394 }
395 }
396 case var_enum:
397 {
398 if (completion != nullptr)
399 {
400 const char *after_arg = skip_to_space (*args);
401 if (*after_arg == '\0')
402 {
403 complete_on_enum (completion->tracker,
404 match->enums, *args, *args);
405 if (completion->tracker.have_completions ())
406 return {};
407
408 /* If we don't have completions, let the
409 non-completion path throw on invalid enum value
410 below, so that completion processing stops. */
411 }
412 }
413
414 if (check_for_argument (args, "--"))
415 {
416 /* Treat e.g., "backtrace -entry-values --" as if there
417 was no argument after "-entry-values". This makes
418 parse_cli_var_enum throw an error with a suggestion of
419 what are the valid options. */
420 args = nullptr;
421 }
422
423 option_value val;
424 val.enumeration = parse_cli_var_enum (args, match->enums);
425 return option_def_and_value {*match, match_ctx, val};
426 }
427 case var_string:
428 {
429 if (check_for_argument (args, "--"))
430 {
431 /* Treat e.g., "maint test-options -string --" as if there
432 was no argument after "-string". */
433 error (_("-%s requires an argument"), match->name);
434 }
435
436 const char *arg_start = *args;
437 *args = skip_to_space (*args);
438
439 if (*args == arg_start)
440 error (_("-%s requires an argument"), match->name);
441
442 option_value val;
443 val.string = savestring (arg_start, *args - arg_start);
444 return option_def_and_value {*match, match_ctx, val};
445 }
446
447 default:
448 /* Not yet. */
449 gdb_assert_not_reached (_("option type not supported"));
450 }
451
452 return {};
453 }
454
455 /* See cli-option.h. */
456
457 bool
458 complete_options (completion_tracker &tracker,
459 const char **args,
460 process_options_mode mode,
461 gdb::array_view<const option_def_group> options_group)
462 {
463 const char *text = *args;
464
465 tracker.set_use_custom_word_point (true);
466
467 const char *delimiter = find_end_options_delimiter (text);
468 bool have_delimiter = delimiter != nullptr;
469
470 if (text[0] == '-' && (!have_delimiter || *delimiter == '\0'))
471 {
472 parse_option_completion_info completion_info {nullptr, tracker};
473
474 while (1)
475 {
476 *args = skip_spaces (*args);
477 completion_info.word = *args;
478
479 if (strcmp (*args, "-") == 0)
480 {
481 complete_on_options (options_group, tracker, *args + 1,
482 completion_info.word);
483 }
484 else if (strcmp (*args, "--") == 0)
485 {
486 tracker.add_completion (make_unique_xstrdup (*args));
487 }
488 else if (**args == '-')
489 {
490 gdb::optional<option_def_and_value> ov
491 = parse_option (options_group, mode, have_delimiter,
492 args, &completion_info);
493 if (!ov && !tracker.have_completions ())
494 {
495 tracker.advance_custom_word_point_by (*args - text);
496 return mode == PROCESS_OPTIONS_REQUIRE_DELIMITER;
497 }
498
499 if (ov
500 && ov->option.type == var_boolean
501 && !ov->value.has_value ())
502 {
503 /* Looked like a boolean option, but we failed to
504 parse the value. If this command requires a
505 delimiter, this value can't be the start of the
506 operands, so return true. Otherwise, if the
507 command doesn't require a delimiter return false
508 so that the caller tries to complete on the
509 operand. */
510 tracker.advance_custom_word_point_by (*args - text);
511 return mode == PROCESS_OPTIONS_REQUIRE_DELIMITER;
512 }
513
514 /* If we parsed an option with an argument, and reached
515 the end of the input string with no trailing space,
516 return true, so that our callers don't try to
517 complete anything by themselves. E.g., this makes it
518 so that with:
519
520 (gdb) frame apply all -limit 10[TAB]
521
522 we don't try to complete on command names. */
523 if (ov
524 && !tracker.have_completions ()
525 && **args == '\0'
526 && *args > text && !isspace ((*args)[-1]))
527 {
528 tracker.advance_custom_word_point_by
529 (*args - text);
530 return true;
531 }
532
533 /* If the caller passed in a context, then it is
534 interested in the option argument values. */
535 if (ov && ov->ctx != nullptr)
536 save_option_value_in_ctx (ov);
537 }
538 else
539 {
540 tracker.advance_custom_word_point_by
541 (completion_info.word - text);
542
543 /* If the command requires a delimiter, but we haven't
544 seen one, then return true, so that the caller
545 doesn't try to complete on whatever follows options,
546 which for these commands should only be done if
547 there's a delimiter. */
548 if (mode == PROCESS_OPTIONS_REQUIRE_DELIMITER
549 && !have_delimiter)
550 {
551 /* If we reached the end of the input string, then
552 offer all options, since that's all the user can
553 type (plus "--"). */
554 if (completion_info.word[0] == '\0')
555 complete_on_all_options (tracker, options_group);
556 return true;
557 }
558 else
559 return false;
560 }
561
562 if (tracker.have_completions ())
563 {
564 tracker.advance_custom_word_point_by
565 (completion_info.word - text);
566 return true;
567 }
568 }
569 }
570 else if (delimiter != nullptr)
571 {
572 tracker.advance_custom_word_point_by (delimiter - text);
573 *args = delimiter;
574 return false;
575 }
576
577 return false;
578 }
579
580 /* Save the parsed value in the option's context. */
581
582 static void
583 save_option_value_in_ctx (gdb::optional<option_def_and_value> &ov)
584 {
585 switch (ov->option.type)
586 {
587 case var_boolean:
588 {
589 bool value = ov->value.has_value () ? ov->value->boolean : true;
590 *ov->option.var_address.boolean (ov->option, ov->ctx) = value;
591 }
592 break;
593 case var_uinteger:
594 *ov->option.var_address.uinteger (ov->option, ov->ctx)
595 = ov->value->uinteger;
596 break;
597 case var_zuinteger_unlimited:
598 *ov->option.var_address.integer (ov->option, ov->ctx)
599 = ov->value->integer;
600 break;
601 case var_enum:
602 *ov->option.var_address.enumeration (ov->option, ov->ctx)
603 = ov->value->enumeration;
604 break;
605 case var_string:
606 *ov->option.var_address.string (ov->option, ov->ctx)
607 = ov->value->string;
608 ov->value->string = nullptr;
609 break;
610 default:
611 gdb_assert_not_reached ("unhandled option type");
612 }
613 }
614
615 /* See cli-option.h. */
616
617 bool
618 process_options (const char **args,
619 process_options_mode mode,
620 gdb::array_view<const option_def_group> options_group)
621 {
622 if (*args == nullptr)
623 return false;
624
625 /* If ARGS starts with "-", look for a "--" sequence. If one is
626 found, then interpret everything up until the "--" as
627 'gdb::option'-style command line options. Otherwise, interpret
628 ARGS as possibly the command's operands. */
629 bool have_delimiter = find_end_options_delimiter (*args) != nullptr;
630
631 if (mode == PROCESS_OPTIONS_REQUIRE_DELIMITER && !have_delimiter)
632 return false;
633
634 bool processed_any = false;
635
636 while (1)
637 {
638 *args = skip_spaces (*args);
639
640 auto ov = parse_option (options_group, mode, have_delimiter, args);
641 if (!ov)
642 {
643 if (processed_any)
644 return true;
645 return false;
646 }
647
648 processed_any = true;
649
650 save_option_value_in_ctx (ov);
651 }
652 }
653
654 /* Helper for build_help. Return a fragment of a help string showing
655 OPT's possible values. Returns NULL if OPT doesn't take an
656 argument. */
657
658 static const char *
659 get_val_type_str (const option_def &opt, std::string &buffer)
660 {
661 if (!opt.have_argument)
662 return nullptr;
663
664 switch (opt.type)
665 {
666 case var_boolean:
667 return "[on|off]";
668 case var_uinteger:
669 case var_zuinteger_unlimited:
670 return "NUMBER|unlimited";
671 case var_enum:
672 {
673 buffer = "";
674 for (size_t i = 0; opt.enums[i] != nullptr; i++)
675 {
676 if (i != 0)
677 buffer += "|";
678 buffer += opt.enums[i];
679 }
680 return buffer.c_str ();
681 }
682 case var_string:
683 return "STRING";
684 default:
685 return nullptr;
686 }
687 }
688
689 /* Helper for build_help. Appends an indented version of DOC into
690 HELP. */
691
692 static void
693 append_indented_doc (const char *doc, std::string &help)
694 {
695 const char *p = doc;
696 const char *n = strchr (p, '\n');
697
698 while (n != nullptr)
699 {
700 help += " ";
701 help.append (p, n - p + 1);
702 p = n + 1;
703 n = strchr (p, '\n');
704 }
705 help += " ";
706 help += p;
707 help += '\n';
708 }
709
710 /* Fill HELP with an auto-generated "help" string fragment for
711 OPTIONS. */
712
713 static void
714 build_help_option (gdb::array_view<const option_def> options,
715 std::string &help)
716 {
717 std::string buffer;
718
719 for (const auto &o : options)
720 {
721 if (o.set_doc == nullptr)
722 continue;
723
724 help += " -";
725 help += o.name;
726
727 const char *val_type_str = get_val_type_str (o, buffer);
728 if (val_type_str != nullptr)
729 {
730 help += ' ';
731 help += val_type_str;
732 }
733 help += "\n";
734 append_indented_doc (o.set_doc, help);
735 if (o.help_doc != nullptr)
736 append_indented_doc (o.help_doc, help);
737 help += '\n';
738 }
739 }
740
741 /* See cli-option.h. */
742
743 std::string
744 build_help (const char *help_tmpl,
745 gdb::array_view<const option_def_group> options_group)
746 {
747 std::string help_str;
748
749 const char *p = strstr (help_tmpl, "%OPTIONS%");
750 help_str.assign (help_tmpl, p);
751
752 for (const auto &grp : options_group)
753 for (const auto &opt : grp.options)
754 build_help_option (opt, help_str);
755
756 p += strlen ("%OPTIONS%");
757 help_str.append (p);
758
759 return help_str;
760 }
761
762 /* See cli-option.h. */
763
764 void
765 add_setshow_cmds_for_options (command_class cmd_class,
766 void *data,
767 gdb::array_view<const option_def> options,
768 struct cmd_list_element **set_list,
769 struct cmd_list_element **show_list)
770 {
771 for (const auto &option : options)
772 {
773 if (option.type == var_boolean)
774 {
775 add_setshow_boolean_cmd (option.name, cmd_class,
776 option.var_address.boolean (option, data),
777 option.set_doc, option.show_doc,
778 option.help_doc,
779 nullptr, option.show_cmd_cb,
780 set_list, show_list);
781 }
782 else if (option.type == var_uinteger)
783 {
784 add_setshow_uinteger_cmd (option.name, cmd_class,
785 option.var_address.uinteger (option, data),
786 option.set_doc, option.show_doc,
787 option.help_doc,
788 nullptr, option.show_cmd_cb,
789 set_list, show_list);
790 }
791 else if (option.type == var_zuinteger_unlimited)
792 {
793 add_setshow_zuinteger_unlimited_cmd
794 (option.name, cmd_class,
795 option.var_address.integer (option, data),
796 option.set_doc, option.show_doc,
797 option.help_doc,
798 nullptr, option.show_cmd_cb,
799 set_list, show_list);
800 }
801 else if (option.type == var_enum)
802 {
803 add_setshow_enum_cmd (option.name, cmd_class,
804 option.enums,
805 option.var_address.enumeration (option, data),
806 option.set_doc, option.show_doc,
807 option.help_doc,
808 nullptr, option.show_cmd_cb,
809 set_list, show_list);
810 }
811 else if (option.type == var_string)
812 {
813 add_setshow_string_cmd (option.name, cmd_class,
814 option.var_address.string (option, data),
815 option.set_doc, option.show_doc,
816 option.help_doc,
817 nullptr, option.show_cmd_cb,
818 set_list, show_list);
819 }
820 else
821 gdb_assert_not_reached (_("option type not handled"));
822 }
823 }
824
825 } /* namespace option */
826 } /* namespace gdb */
This page took 0.045 seconds and 3 git commands to generate.