diff options
author | Gereon Kremer <nafur42@gmail.com> | 2021-09-13 17:54:55 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-13 08:54:55 -0700 |
commit | 02088737d2845ea00714b6ba6fed8c20485a9645 (patch) | |
tree | 6b1b6cd483bdaf718172dbabc652f73e43de6364 /src/main/options_template.cpp | |
parent | 2384a8d85517e00bc94e7fcf759a75dc6ea9b009 (diff) |
Refactor options parsing (#7143)
This PR refactors the code for options parsing.
Diffstat (limited to 'src/main/options_template.cpp')
-rw-r--r-- | src/main/options_template.cpp | 126 |
1 files changed, 72 insertions, 54 deletions
diff --git a/src/main/options_template.cpp b/src/main/options_template.cpp index dfd93843e..a7a4429e3 100644 --- a/src/main/options_template.cpp +++ b/src/main/options_template.cpp @@ -82,19 +82,25 @@ Languages currently supported as arguments to the --output-lang option:\n\ "; // clang-format on -void printUsage(const std::string& msg, std::ostream& os) { - os << msg << "\n" << commonOptionsDescription << "\n\n" << additionalOptionsDescription << std::endl - << optionsFootnote << std::endl << std::flush; +void printUsage(const std::string& msg, std::ostream& os) +{ + os << msg << "\n" + << commonOptionsDescription << "\n\n" + << additionalOptionsDescription << std::endl + << optionsFootnote << std::endl; } -void printShortUsage(const std::string& msg, std::ostream& os) { - os << msg << "\n" << commonOptionsDescription << std::endl - << optionsFootnote << std::endl - << "For full usage, please use --help." - << std::endl << std::endl << std::flush; +void printShortUsage(const std::string& msg, std::ostream& os) +{ + os << msg << "\n" + << commonOptionsDescription << std::endl + << optionsFootnote << std::endl + << "For full usage, please use --help." << std::endl + << std::endl; } -void printLanguageHelp(std::ostream& os) { +void printLanguageHelp(std::ostream& os) +{ os << languageDescription << std::flush; } @@ -111,40 +117,45 @@ void printLanguageHelp(std::ostream& os) { * required_argument - an argument is expected * optional_argument - an argument is permitted but not required * 3. this is a pointer to an int which is set to the 4th entry of the - * array if the option is present; or NULL, in which case + * array if the option is present; or nullptr, in which case * getopt_long() returns the 4th entry * 4. the return value for getopt_long() when this long option (or the * value to set the 3rd entry to; see #3) */ -// clang-format off static struct option cmdlineOptions[] = { - ${cmdline_options}$ +// clang-format off + ${cmdoptions_long}$ +// clang-format on {nullptr, no_argument, nullptr, '\0'} }; -// clang-format on std::string suggestCommandLineOptions(const std::string& optionName) { DidYouMean didYouMean; const char* opt; - for(size_t i = 0; (opt = cmdlineOptions[i].name) != nullptr; ++i) { + for (size_t i = 0; (opt = cmdlineOptions[i].name) != nullptr; ++i) + { didYouMean.addWord(std::string("--") + cmdlineOptions[i].name); } - return didYouMean.getMatchAsString(optionName.substr(0, optionName.find('='))); + return didYouMean.getMatchAsString( + optionName.substr(0, optionName.find('='))); } -void parseInternal(api::Solver& solver, int argc, - char* argv[], - std::vector<std::string>& nonoptions) +void parseInternal(api::Solver& solver, + int argc, + char* argv[], + std::vector<std::string>& nonoptions) { Assert(argv != nullptr); - if(Debug.isOn("options")) { - Debug("options") << "starting a new parseInternal with " - << argc << " arguments" << std::endl; - for( int i = 0; i < argc ; i++ ){ - Assert(argv[i] != NULL); + if (Debug.isOn("options")) + { + Debug("options") << "starting a new parseInternal with " << argc + << " arguments" << std::endl; + for (int i = 0; i < argc; ++i) + { + Assert(argv[i] != nullptr); Debug("options") << " argv[" << i << "] = " << argv[i] << std::endl; } } @@ -161,8 +172,8 @@ void parseInternal(api::Solver& solver, int argc, int main_optind = 0; int old_optind; - - while(true) { // Repeat Forever + while (true) + { // Repeat Forever optopt = 0; @@ -172,8 +183,8 @@ void parseInternal(api::Solver& solver, int argc, // If we encounter an element that is not at zero and does not start // with a "-", this is a non-option. We consume this element as a // non-option. - if (main_optind > 0 && main_optind < argc && - argv[main_optind][0] != '-') { + if (main_optind > 0 && main_optind < argc && argv[main_optind][0] != '-') + { Debug("options") << "enqueueing " << argv[main_optind] << " as a non-option." << std::endl; nonoptions.push_back(argv[main_optind]); @@ -181,7 +192,6 @@ void parseInternal(api::Solver& solver, int argc, continue; } - Debug("options") << "[ before, main_optind == " << main_optind << " ]" << std::endl; Debug("options") << "[ before, optind == " << optind << " ]" << std::endl; @@ -189,8 +199,8 @@ void parseInternal(api::Solver& solver, int argc, << std::endl; // clang-format off int c = getopt_long(argc, argv, - "+:${options_short}$", - cmdlineOptions, NULL); + "+:${cmdoptions_short}$", + cmdlineOptions, nullptr); // clang-format on main_optind = optind; @@ -202,15 +212,19 @@ void parseInternal(api::Solver& solver, int argc, // The initial getopt_long call should always determine that argv[0] // is not an option and returns -1. We always manually advance beyond // this element. - if ( old_optind == 0 && c == -1 ) { + if (old_optind == 0 && c == -1) + { Assert(main_optind > 0); continue; } - if ( c == -1 ) { - if(Debug.isOn("options")) { + if (c == -1) + { + if (Debug.isOn("options")) + { Debug("options") << "done with option parsing" << std::endl; - for(int index = optind; index < argc; ++index) { + for (int index = optind; index < argc; ++index) + { Debug("options") << "remaining " << argv[index] << std::endl; } } @@ -220,30 +234,29 @@ void parseInternal(api::Solver& solver, int argc, std::string option = argv[old_optind == 0 ? 1 : old_optind]; std::string optionarg = (optarg == nullptr) ? "" : optarg; - Debug("preemptGetopt") << "processing option " << c - << " (`" << char(c) << "'), " << option << std::endl; + Debug("preemptGetopt") << "processing option " << c << " (`" << char(c) + << "'), " << option << std::endl; - // clang-format off - switch(c) + switch (c) { - ${options_handler}$ +// clang-format off + ${parseinternal_impl}$ +// clang-format on - case ':' : + case ':' : // This can be a long or short option, and the way to get at the // name of it is different. throw OptionException(std::string("option `") + option + "' missing its required argument"); - - case '?': - default: + case '?': + default: throw OptionException(std::string("can't understand option `") + option + "'" + suggestCommandLineOptions(option)); } } - // clang-format on - Debug("options") << "got " << nonoptions.size() - << " non-option arguments." << std::endl; + Debug("options") << "got " << nonoptions.size() << " non-option arguments." + << std::endl; } /** @@ -253,31 +266,36 @@ void parseInternal(api::Solver& solver, int argc, * * Throws OptionException on failures. */ -std::vector<std::string> parse( - api::Solver& solver, int argc, char* argv[], std::string& binaryName) +std::vector<std::string> parse(api::Solver& solver, + int argc, + char* argv[], + std::string& binaryName) { Assert(argv != nullptr); - const char *progName = argv[0]; + const char* progName = argv[0]; // To debug options parsing, you may prefer to simply uncomment this // and recompile. Debug flags have not been parsed yet so these have // not been set. - //DebugChannel.on("options"); + // DebugChannel.on("options"); Debug("options") << "argv == " << argv << std::endl; // Find the base name of the program. - const char *x = strrchr(progName, '/'); - if(x != nullptr) { + const char* x = strrchr(progName, '/'); + if (x != nullptr) + { progName = x + 1; } binaryName = std::string(progName); std::vector<std::string> nonoptions; parseInternal(solver, argc, argv, nonoptions); - if (Debug.isOn("options")){ - for (const auto& no: nonoptions){ + if (Debug.isOn("options")) + { + for (const auto& no : nonoptions) + { Debug("options") << "nonoptions " << no << std::endl; } } |