diff options
author | Gennadiy Rozental <rogeeff@google.com> | 2023-03-21 01:04:30 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-03-21 01:05:15 -0700 |
commit | 819272485a0c06abc8d7d62b188a6f54174881cb (patch) | |
tree | 736d215cde8a2598026632c51f3453b4b56036c1 /absl/flags/parse.cc | |
parent | 396e9764cded739f595ba880b95b061051c49128 (diff) |
Change ParseAbseilFlagsOnly function to include handling of usage flags and exit on syntax errors.
PiperOrigin-RevId: 518198160
Change-Id: Ib4fe53e0b0b371472b6b9473aeb84779953b6a38
Diffstat (limited to 'absl/flags/parse.cc')
-rw-r--r-- | absl/flags/parse.cc | 95 |
1 files changed, 56 insertions, 39 deletions
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc index 236d31b7..1f639066 100644 --- a/absl/flags/parse.cc +++ b/absl/flags/parse.cc @@ -666,7 +666,7 @@ std::vector<std::string> GetMisspellingHints(const absl::string_view flag) { const size_t maxCutoff = std::min(flag.size() / 2 + 1, kMaxDistance); auto undefok = absl::GetFlag(FLAGS_undefok); BestHints best_hints(static_cast<uint8_t>(maxCutoff)); - absl::flags_internal::ForEachFlag([&](const CommandLineFlag& f) { + flags_internal::ForEachFlag([&](const CommandLineFlag& f) { if (best_hints.hints.size() >= kMaxHints) return; uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance( flag, f.Name(), best_hints.best_distance); @@ -697,51 +697,42 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[], std::vector<char*> positional_args; std::vector<UnrecognizedFlag> unrecognized_flags; - bool parse_successful = absl::ParseAbseilFlagsOnly( - argc, argv, positional_args, unrecognized_flags); + auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl( + argc, argv, positional_args, unrecognized_flags, usage_flag_action); if (undef_flag_action != OnUndefinedFlag::kIgnoreUndefined) { - if (parse_successful && - undef_flag_action == OnUndefinedFlag::kAbortIfUndefined) { - if (!unrecognized_flags.empty()) { parse_successful = false; } - } - flags_internal::ReportUnrecognizedFlags( unrecognized_flags, - !parse_successful && - (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined)); - } - -#if ABSL_FLAGS_STRIP_NAMES - if (!parse_successful) { - ReportUsageError("NOTE: command line flags are disabled in this build", - true); - } -#endif - - if (!parse_successful) { - HandleUsageFlags(std::cout, ProgramUsageMessage()); - std::exit(1); - } - - if (usage_flag_action == UsageFlagsAction::kHandleUsage) { - int exit_code = HandleUsageFlags(std::cout, ProgramUsageMessage()); + (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined)); - if (exit_code != -1) { - std::exit(exit_code); + if (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined) { + if (!unrecognized_flags.empty()) { std::exit(1); } } } + flags_internal::MaybeExit(help_mode); + return positional_args; } // -------------------------------------------------------------------- -} // namespace flags_internal - -bool ParseAbseilFlagsOnly(int argc, char* argv[], - std::vector<char*>& positional_args, - std::vector<UnrecognizedFlag>& unrecognized_flags) { +// This function handles all Abseil Flags and built-in usage flags and, if any +// help mode was handled, it returns that help mode. The caller of this function +// can decide to exit based on the returned help mode. +// The caller may decide to handle unrecognized positional arguments and +// unrecognized flags first before exiting. +// +// Returns: +// * HelpMode::kFull if parsing errors were detected in recognized arguments +// * The HelpMode that was handled in case when `usage_flag_action` is +// UsageFlagsAction::kHandleUsage and a usage flag was specified on the +// commandline +// * Otherwise it returns HelpMode::kNone +HelpMode ParseAbseilFlagsOnlyImpl( + int argc, char* argv[], std::vector<char*>& positional_args, + std::vector<UnrecognizedFlag>& unrecognized_flags, + UsageFlagsAction usage_flag_action) { ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]"); using flags_internal::ArgsList; @@ -771,9 +762,9 @@ bool ParseAbseilFlagsOnly(int argc, char* argv[], specified_flags->clear(); } - // Iterate through the list of the input arguments. First level are arguments - // originated from argc/argv. Following levels are arguments originated from - // recursive parsing of flagfile(s). + // Iterate through the list of the input arguments. First level are + // arguments originated from argc/argv. Following levels are arguments + // originated from recursive parsing of flagfile(s). bool success = true; while (!input_args.empty()) { // First we process the built-in generator flags. @@ -793,8 +784,8 @@ bool ParseAbseilFlagsOnly(int argc, char* argv[], } // Handle the next argument in the current list. If the stack of argument - // lists contains only one element - we are processing an argument from the - // original argv. + // lists contains only one element - we are processing an argument from + // the original argv. absl::string_view arg(curr_list.Front()); bool arg_from_argv = input_args.size() == 1; @@ -895,7 +886,33 @@ bool ParseAbseilFlagsOnly(int argc, char* argv[], std::swap(unrecognized_flags, filtered); - return success; + if (!success) { +#if ABSL_FLAGS_STRIP_NAMES + flags_internal::ReportUsageError( + "NOTE: command line flags are disabled in this build", true); +#else + flags_internal::HandleUsageFlags(std::cout, ProgramUsageMessage()); +#endif + return HelpMode::kFull; // We just need to make sure the exit with + // code 1. + } + + return usage_flag_action == UsageFlagsAction::kHandleUsage + ? flags_internal::HandleUsageFlags(std::cout, + ProgramUsageMessage()) + : HelpMode::kNone; +} + +} // namespace flags_internal + +void ParseAbseilFlagsOnly(int argc, char* argv[], + std::vector<char*>& positional_args, + std::vector<UnrecognizedFlag>& unrecognized_flags) { + auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl( + argc, argv, positional_args, unrecognized_flags, + flags_internal::UsageFlagsAction::kHandleUsage); + + flags_internal::MaybeExit(help_mode); } // -------------------------------------------------------------------- |