monitor: add cli11 argument parsing
Replace our custom argument parser with one from CLIUtils.
This results in a number of minor behavioral differences.
- The -? option is no longer recognized as an alias for -h/--help.
- The original parser returned EXIT_FAILURE in all cases, but CLIUtils
uses different non-zero error codes in different situations.
- Minor changes to help text descriptions:
----new----
Usage: build/phosphor-unit-failure-monitor.new [OPTIONS]
Options:
-h,--help Print this help message and exit
-s,--source TEXT REQUIRED
-t,--target TEXT REQUIRED
-a,--action ENUM:value in {start->0,stop->1} OR {0,1} REQUIRED
----old----
Usage: build/phosphor-unit-failure-monitor [options]
Options:
--help Print this menu
--source=<source> The source unit to monitor
--target=<target> The target unit to start or stop
--action=<action> Target unit action - start or stop
- The original parser displays the full help text on error, CLIUtils
does not:
----new----
$ phosphor-unit-failure-monitor
--source is required
Run with --help for more information.
----old----
$ phosphor-unit-failure-monitor
ERROR: Source not specified
Usage: build/phosphor-unit-failure-monitor [options]
Options:
--help Print this menu
--source=<source> The source unit to monitor
--target=<target> The target unit to start or stop
--action=<action> Target unit action - start or stop
Change-Id: I2417d9c857c6d8fc04807fe4729d2fa154e746a3
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/fail-monitor/argument.cpp b/fail-monitor/argument.cpp
deleted file mode 100644
index 33194ce..0000000
--- a/fail-monitor/argument.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * Copyright © 2017 IBM Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "argument.hpp"
-
-#include <algorithm>
-#include <iostream>
-#include <iterator>
-
-namespace phosphor
-{
-namespace unit
-{
-namespace failure
-{
-
-ArgumentParser::ArgumentParser(int argc, char** argv)
-{
- int option = 0;
- while (-1 != (option = getopt_long(argc, argv, optionStr, options, NULL)))
- {
- if ((option == '?') || (option == 'h'))
- {
- usage(argv);
- exit(-1);
- }
-
- auto i = &options[0];
- while ((i->val != option) && (i->val != 0))
- {
- ++i;
- }
-
- if (i->val)
- {
- arguments[i->name] = (i->has_arg ? optarg : trueString);
- }
- }
-}
-
-const std::string& ArgumentParser::operator[](const std::string& opt)
-{
- auto i = arguments.find(opt);
- if (i == arguments.end())
- {
- return emptyString;
- }
- else
- {
- return i->second;
- }
-}
-
-void ArgumentParser::usage(char** argv)
-{
- std::cerr << "Usage: " << argv[0] << " [options]\n";
- std::cerr << "Options:\n";
- std::cerr << " --help Print this menu\n";
- std::cerr << " --source=<source> The source unit to monitor\n";
- std::cerr << " --target=<target> The target unit to start or stop\n";
- std::cerr << " --action=<action> Target unit action - start or stop\n";
- std::cerr << std::flush;
-}
-
-const option ArgumentParser::options[] = {
- {"source", required_argument, NULL, 's'},
- {"action", required_argument, NULL, 'a'},
- {"target", required_argument, NULL, 't'},
- {"help", no_argument, NULL, 'h'},
- {0, 0, 0, 0},
-};
-
-const char* ArgumentParser::optionStr = "s:a:t:h?";
-
-const std::string ArgumentParser::trueString = "true";
-const std::string ArgumentParser::emptyString = "";
-} // namespace failure
-} // namespace unit
-} // namespace phosphor
diff --git a/fail-monitor/argument.hpp b/fail-monitor/argument.hpp
deleted file mode 100644
index 8648ddd..0000000
--- a/fail-monitor/argument.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-#pragma once
-
-#include <getopt.h>
-
-#include <map>
-#include <string>
-
-namespace phosphor
-{
-namespace unit
-{
-namespace failure
-{
-
-/** @brief Class - Encapsulates parsing command line options and
- * populating arguments
- */
-class ArgumentParser
-{
- public:
- ArgumentParser() = delete;
- ~ArgumentParser() = default;
- ArgumentParser(const ArgumentParser&) = delete;
- ArgumentParser& operator=(const ArgumentParser&) = delete;
- ArgumentParser(ArgumentParser&&) = default;
- ArgumentParser& operator=(ArgumentParser&&) = default;
-
- /** @brief Contructs Argument object
- *
- * @param argc - the main function's argc passed as is
- * @param argv - the main function's argv passed as is
- * @return Object constructed
- */
- ArgumentParser(int argc, char** argv);
-
- /** @brief Given an option, returns its argument(optarg)
- *
- * @param opt - command line option string
- *
- * @return argument which is a standard optarg
- */
- const std::string& operator[](const std::string& opt);
-
- /** @brief Displays usage
- *
- * @param argv - the main function's argv passed as is
- */
- static void usage(char** argv);
-
- /** @brief Set to 'true' when an option is passed */
- static const std::string trueString;
-
- /** @brief Set to '' when an option is not passed */
- static const std::string emptyString;
-
- private:
- /** @brief Option to argument mapping */
- std::map<const std::string, std::string> arguments;
-
- /** @brief Array of struct options as needed by getopt_long */
- static const option options[];
-
- /** @brief optstring as needed by getopt_long */
- static const char* optionStr;
-};
-} // namespace failure
-} // namespace unit
-} // namespace phosphor
diff --git a/fail-monitor/main.cpp b/fail-monitor/main.cpp
index 90c6126..c383a67 100644
--- a/fail-monitor/main.cpp
+++ b/fail-monitor/main.cpp
@@ -20,53 +20,35 @@
* then it will either stop or start the target unit, depending
* on the command line arguments.
*/
-#include "argument.hpp"
#include "monitor.hpp"
-#include <iostream>
+#include <CLI/CLI.hpp>
+
#include <map>
+#include <string>
using namespace phosphor::unit::failure;
-/**
- * Prints usage and exits the program
- *
- * @param[in] err - the error message to print
- * @param[in] argv - argv from main()
- */
-void exitWithError(const char* err, char** argv)
-{
- std::cerr << "ERROR: " << err << "\n";
- ArgumentParser::usage(argv);
- exit(EXIT_FAILURE);
-}
-
static const std::map<std::string, Monitor::Action> actions = {
{"start", Monitor::Action::start}, {"stop", Monitor::Action::stop}};
int main(int argc, char** argv)
{
- ArgumentParser args(argc, argv);
+ CLI::App app;
+ std::string source;
+ std::string target;
+ Monitor::Action action{Monitor::Action::start};
- auto source = args["source"];
- if (source == ArgumentParser::emptyString)
- {
- exitWithError("Source not specified", argv);
- }
+ app.add_option("-s,--source", source, "The source unit to monitor")
+ ->required();
+ app.add_option("-t,--target", target, "The target unit to start or stop")
+ ->required();
+ app.add_option("-a,--action", action, "Target unit action - start or stop")
+ ->required()
+ ->transform(CLI::CheckedTransformer(actions, CLI::ignore_space));
- auto target = args["target"];
- if (target == ArgumentParser::emptyString)
- {
- exitWithError("Target not specified", argv);
- }
-
- auto a = actions.find(args["action"]);
- if (a == actions.end())
- {
- exitWithError("Missing or invalid action specified", argv);
- }
-
- Monitor monitor{source, target, a->second};
+ CLI11_PARSE(app, argc, argv);
+ Monitor monitor{source, target, action};
monitor.analyze();
diff --git a/meson.build b/meson.build
index 209c49f..a7f3a4f 100644
--- a/meson.build
+++ b/meson.build
@@ -12,6 +12,13 @@
version: '1.0',
)
+cxx = meson.get_compiler('cpp')
+
+if cxx.has_header('CLI/CLI.hpp')
+ cli11_dep = declare_dependency()
+else
+ cli11_dep = dependency('cli11')
+endif
phosphor_logging = dependency('phosphor-logging')
phosphor_dbus_interfaces = dependency('phosphor-dbus-interfaces')
sdbusplus = dependency('sdbusplus')
@@ -104,11 +111,11 @@
executable(
'phosphor-unit-failure-monitor',
[
- 'fail-monitor/argument.cpp',
'fail-monitor/main.cpp',
'fail-monitor/monitor.cpp',
],
dependencies: [
+ cli11_dep,
phosphor_logging,
],
install: true
diff --git a/subprojects/CLI11.wrap b/subprojects/CLI11.wrap
new file mode 100644
index 0000000..2e5a95b
--- /dev/null
+++ b/subprojects/CLI11.wrap
@@ -0,0 +1,6 @@
+[wrap-git]
+url = https://github.com/CLIUtils/CLI11.git
+revision = HEAD
+
+[provide]
+CLI11 = CLI11_dep