b6b2ce7ada
This is generally frowned upon but it makes this code 10x cleaner. We handle commandLine usage msg printing by using exceptions for control flow. This allows us to centralize the logic for killing the Mind threads in one place. At least with respect to printing the usage msg.
145 lines
3.7 KiB
C++
145 lines
3.7 KiB
C++
#include <opts.h>
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#include <exception>
|
|
#include <getopt.h>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <sys/stat.h>
|
|
#include <sstream>
|
|
|
|
|
|
OptionsParserError::OptionsParserError(
|
|
const std::string& errorMessage, const OptionParser& parser
|
|
)
|
|
: std::invalid_argument(errorMessage + "\n" + parser.getUsage())
|
|
{
|
|
}
|
|
|
|
const char* OptionsParserError::what() const noexcept
|
|
{
|
|
return std::invalid_argument::what();
|
|
}
|
|
|
|
JustPrintUsageNoError::JustPrintUsageNoError(const OptionParser& parser)
|
|
: message(parser.getUsage())
|
|
{
|
|
}
|
|
|
|
const char* JustPrintUsageNoError::what() const noexcept
|
|
{
|
|
return message.c_str();
|
|
}
|
|
|
|
struct option OptionParser::longOptions[] = {
|
|
{"devicespec", required_argument, 0, 's'},
|
|
{"spec", required_argument, 0, 's'},
|
|
{"devspec", required_argument, 0, 's'},
|
|
{"devfile", required_argument, 0, 'd'},
|
|
{"devicefile", required_argument, 0, 'd'},
|
|
{"api-lib", required_argument, 0, 'a'},
|
|
{"apilib", required_argument, 0, 'a'},
|
|
{"api", required_argument, 0, 'a'},
|
|
{"lib", required_argument, 0, 'a'},
|
|
{"api-lib-path", required_argument, 0, 'p'},
|
|
{"apipath", required_argument, 0, 'p'},
|
|
{"libpath", required_argument, 0, 'p'},
|
|
{"verbose", no_argument, 0, 'v'},
|
|
{"help", no_argument, 0, 'h'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
void OptionParser::parseArguments(int argc, char *argv[], char **envp)
|
|
{
|
|
(void)envp;
|
|
int opt;
|
|
int optionIndex = 0;
|
|
|
|
argv0 = argv[0];
|
|
|
|
optind = 1; // Reset optind to 1 before parsing
|
|
opterr = 0;
|
|
while ((opt = getopt_long(
|
|
argc, argv, "s:d:a:p:vh?", longOptions, &optionIndex)) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case 's':
|
|
if (!deviceSpecs.empty()) {
|
|
deviceSpecs += "||";
|
|
}
|
|
deviceSpecs += std::string(optarg);
|
|
break;
|
|
case 'd':
|
|
deviceSpecFiles.push_back(optarg);
|
|
break;
|
|
case 'a':
|
|
senseApiLibs.push_back(optarg);
|
|
break;
|
|
case 'p':
|
|
{
|
|
struct stat info;
|
|
|
|
if (stat(optarg, &info) != 0 || !(info.st_mode & S_IFDIR))
|
|
{
|
|
throw OptionsParserError(
|
|
std::string(__func__) + " - The specified path is not a "
|
|
"directory: " + optarg, *this);
|
|
}
|
|
|
|
senseApiLibPath.push_back(optarg);
|
|
break;
|
|
}
|
|
case 'v':
|
|
verbose = true;
|
|
break;
|
|
case 'h':
|
|
throw JustPrintUsageNoError(*this);
|
|
case '?':
|
|
throw OptionsParserError(
|
|
std::string(__func__) + " - Invalid argument encountered: "
|
|
+ std::string(argv[optind - 1]), *this);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string OptionParser::getUsage() const
|
|
{
|
|
return "Usage: " + argv0 + " [-s|--devicespec|--spec|--devspec <device_spec>] "
|
|
"[-d|--devfile|--devicefile <filename>] "
|
|
"[-a|--api-lib|--apilib|--api|--lib <filename>] "
|
|
"[-p|--api-lib-path|--apipath|--libpath <directory>] "
|
|
"[-v|--verbose] "
|
|
"[-h|--help]";
|
|
}
|
|
|
|
std::string OptionParser::stringifyOptions(void) const
|
|
{
|
|
std::ostringstream oss;
|
|
|
|
if (verbose) {
|
|
oss << "Verbose mode is on" << std::endl;
|
|
}
|
|
|
|
oss << "Device Specs: " << deviceSpecs << std::endl;
|
|
|
|
oss << "Device Spec Files: ";
|
|
for (const auto& file : deviceSpecFiles) {
|
|
oss << file << " ";
|
|
}
|
|
oss << std::endl;
|
|
|
|
oss << "Sense API Library Paths: ";
|
|
for (const auto& path : senseApiLibPath) {
|
|
oss << path << " ";
|
|
}
|
|
oss << std::endl;
|
|
oss << "Sense API Libraries: ";
|
|
for (const auto& lib : senseApiLibs) {
|
|
oss << lib << " ";
|
|
}
|
|
oss << std::endl;
|
|
|
|
return oss.str();
|
|
}
|