Files
salmanoff/smocore/opts.cpp
T

145 lines
3.7 KiB
C++
Raw Normal View History

#include <opts.h>
#include <iostream>
#include <stdexcept>
2025-08-13 09:43:34 -04:00
#include <exception>
#include <getopt.h>
#include <string>
#include <vector>
#include <sys/stat.h>
#include <sstream>
2025-01-08 13:47:16 -04:00
2025-08-13 09:43:34 -04:00
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[] = {
2025-01-07 14:05:23 -04:00
{"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)
{
2025-01-07 14:05:23 -04:00
case 's':
2025-08-29 16:12:30 -04:00
if (!dapSpecs.empty()) {
dapSpecs += "||";
2025-01-07 14:05:23 -04:00
}
2025-08-29 16:12:30 -04:00
dapSpecs += std::string(optarg);
break;
case 'd':
2025-08-29 16:12:30 -04:00
dapSpecFiles.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))
{
2025-08-13 09:43:34 -04:00
throw OptionsParserError(
std::string(__func__) + " - The specified path is not a "
2025-08-13 09:43:34 -04:00
"directory: " + optarg, *this);
}
senseApiLibPath.push_back(optarg);
break;
}
case 'v':
verbose = true;
break;
case 'h':
2025-08-13 09:43:34 -04:00
throw JustPrintUsageNoError(*this);
case '?':
2025-08-13 09:43:34 -04:00
throw OptionsParserError(
std::string(__func__) + " - Invalid argument encountered: "
2025-08-13 09:43:34 -04:00
+ 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>] "
2025-01-05 13:35:14 -04:00
"[-v|--verbose] "
"[-h|--help]";
}
std::string OptionParser::stringifyOptions(void) const
{
std::ostringstream oss;
if (verbose) {
oss << "Verbose mode is on" << std::endl;
}
2025-08-29 16:12:30 -04:00
oss << "DAP Specs: " << dapSpecs << std::endl;
2025-08-29 16:12:30 -04:00
oss << "DAP Spec Files: ";
for (const auto& file : dapSpecFiles) {
oss << file << " ";
2025-01-05 14:04:31 -04:00
}
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();
}