catch getopt's errors

This commit is contained in:
Frédéric Mangano-Tarumi 2018-12-01 13:03:44 -05:00
parent 067c9240c3
commit 6f290702a8
4 changed files with 32 additions and 8 deletions

View File

@ -17,6 +17,8 @@
#include <string.h>
#include <unistd.h>
using namespace std::literals::string_literals;
static const char help_message[] =
PROJECT_NAME " version " PROJECT_VERSION
R"raw(
@ -59,7 +61,8 @@ ot::status ot::parse_options(int argc, char** argv, ot::options& opt)
return {st::bad_arguments, "No arguments specified. Use -h for help."};
int c;
while ((c = getopt_long(argc, argv, "ho:i::yd:a:s:DS", getopt_options, NULL)) != -1) {
optind = 0;
while ((c = getopt_long(argc, argv, ":ho:i::yd:a:s:DS", getopt_options, NULL)) != -1) {
switch (c) {
case 'h':
opt.print_help = true;
@ -104,9 +107,12 @@ ot::status ot::parse_options(int argc, char** argv, ot::options& opt)
case 'D':
opt.delete_all = true;
break;
case ':':
return {st::bad_arguments,
"Missing value for option '"s + argv[optind - 1] + "'."};
default:
/* getopt printed a message */
return st::bad_arguments;
return {st::bad_arguments, "Unrecognized option '" +
(optopt ? "-"s + static_cast<char>(optopt) : argv[optind - 1]) + "'."};
}
}

View File

@ -18,9 +18,28 @@ void check_read_comments()
throw failure("parsed user comments did not match expectations");
}
void check_parse_options()
{
auto error_case = [](std::vector<const char*> args, const char* message, const std::string& name) {
ot::options opt;
ot::status rc = parse_options(args.size(), const_cast<char**>(args.data()), opt);
if (rc != ot::st::bad_arguments)
throw failure("bad error code when parsing " + name);
if (rc.message != message)
throw failure("bad error message when parsing " + name);
};
error_case({"opustags", "-a"}, "Missing value for option '-a'.", "short option with missing value");
error_case({"opustags", "--add"}, "Missing value for option '--add'.", "long option with missing value");
error_case({"opustags", "-x"}, "Unrecognized option '-x'.", "unrecognized short option");
error_case({"opustags", "--derp"}, "Unrecognized option '--derp'.", "unrecognized long option");
error_case({"opustags", "-x=y"}, "Unrecognized option '-x'.", "unrecognized short option with value");
error_case({"opustags", "--derp=y"}, "Unrecognized option '--derp=y'.", "unrecognized long option with value");
}
int main(int argc, char **argv)
{
std::cout << "1..1\n";
std::cout << "1..2\n";
run(check_read_comments, "check tags parsing");
run(check_parse_options, "check options parsing");
return 0;
}

View File

@ -70,7 +70,7 @@ is_deeply(opustags('--help'), [$expected_help, '', 0], '--help displays the help
is_deeply(opustags('-h'), [$expected_help, '', 0], '-h displays the help message too');
is_deeply(opustags('--derp'), ['', <<"EOF", 256], 'unrecognized option shows an error');
$opustags: unrecognized option '--derp'
error: Unrecognized option '--derp'.
EOF
####################################################################################################

View File

@ -10,9 +10,8 @@
#include <exception>
#include <iostream>
class failure : public std::runtime_error {
public:
failure(const char *message) : std::runtime_error(message) {}
struct failure : std::runtime_error {
failure(const std::string& what) : std::runtime_error(what) {}
};
template <typename F>