poaflocParser Of Arguments For Lines Of Commands |
git clone git://git.dimitrijedobrota.com/poafloc.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | 36fd7278d9c884f92d36fa9a886e0c420dc36551 |
parent | 660f946bfbd9e8aa1aae6eca0d235385ef89ed45 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Wed, 5 Jun 2024 21:15:12 +0200 |
Recognize long and short options
Diffstat:M | args.hpp | | | +++++++++++++++++++++++++++++++--------------- |
M | demo.cpp | | | ++++++++++++++++---------------------------- |
2 files changed, 47 insertions(+), 43 deletions(-)
diff --git a/args.hpp b/args.hpp
@@ -9,7 +9,7 @@ class Parser {
public:
struct option_t {
const char *name;
char key;
const char key;
const char *arg;
};
@@ -20,25 +20,44 @@ class Parser {
const parse_f parser;
};
static int parse(const argp_t *argp, int argc, const char *argv[], void *input) {
static int parse(argp_t *argp, int argc, char *argv[], void *input) {
for (int i = 1; i < argc; i++) {
bool opt_short = false, opt_long = false;
if (argv[i][0] != '-') {
argp->parser(-1, argv[i], input);
continue;
}
if (argv[i][1] != '-') opt_short = true;
else opt_long = true;
const char *opt = argv[i] + opt_long + 1;
bool found = false;
for (int j = 0; argp->options[j].name; j++) {
for (int j = 0; argp->options[j].key; j++) {
const auto &option = argp->options[j];
const auto n = std::strlen(option.name);
const char *arg = 0;
if (std::strncmp(argv[i], option.name, n)) continue;
if (opt_short && opt[0] != option.key) continue;
if (argv[i][n] == '=') {
if (!option.arg) {
std::cerr << "option doesn't require a value\n";
exit(1);
if (opt_long) {
if(!option.name) continue;
const auto n = std::strlen(option.name);
if (std::strncmp(argv[i] + 2, option.name, n)) continue;
if (opt[n] == '=') {
if (!option.arg) {
std::cerr << "option doesn't require a value\n";
exit(1);
}
arg = opt + n + 1;
}
}
arg = argv[i] + n + 1;
} else if (option.arg) {
if (option.arg && !arg) {
if (i == argc) {
std::cerr << "option missing a value\n";
exit(1);
@@ -59,8 +78,6 @@ class Parser {
std::cerr << std::format("unknown option {}\n", argv[i]);
return 1;
}
argp->parser(-1, argv[i], input);
}
return 0;
@@ -70,4 +87,3 @@ class Parser {
};
#endif
diff --git a/demo.cpp b/demo.cpp
@@ -1,7 +1,6 @@
#include "args.hpp"
#include <cstdint>
#include <unordered_map>
#include <vector>
void error(const std::string &message) {
@@ -10,14 +9,13 @@ void error(const std::string &message) {
}
struct arguments_t {
std::vector<const char *> args;
std::unordered_map<std::string, uint32_t> places;
const char *output_file = 0;
bool debug = 0;
bool hex = 0;
bool relocatable = 0;
std::vector<const char *> args;
};
int parse_opt(int key, const char *arg, void *input) {
@@ -34,18 +32,6 @@ int parse_opt(int key, const char *arg, void *input) {
arguments->relocatable = true;
break;
case 'o': arguments->output_file = arg; break;
case 'p': {
const std::string s = arg;
const auto pos = s.find('@');
if (pos == std::string::npos) error("Invalid argument for -place");
const auto value = stol(s.substr(pos + 1), 0, 16);
const auto [_, a] = arguments->places.emplace(s.substr(0, pos), value);
if (!a) error("duplicate place for the same section");
break;
}
default: arguments->args.push_back(arg);
}
@@ -54,16 +40,15 @@ int parse_opt(int key, const char *arg, void *input) {
// clang-format off
static const Parser::option_t options[] = {
{ "--debug", 'd', 0},
{ "--hex", 'h', 0},
{"--relocatable", 'r', 0},
{ "-o", 'o', "file"},
{ "--place", 'p', "address"},
{ 0, 'o', "file"},
{ "debug", 'd', 0},
{ "hex", 'h', 0},
{"relocatable", 'r', 0},
{0},
};
// clang-format on
int main(int argc, const char *argv[]) {
int main(int argc, char *argv[]) {
Parser::argp_t argp = {options, parse_opt};
arguments_t arguments;
@@ -71,13 +56,16 @@ int main(int argc, const char *argv[]) {
error("There was an error while parsing arguments");
}
if (arguments.args.size() == 0) {
error("please provide at least one input file");
}
std::cout << "Command line options: " << std::endl;
if (!arguments.hex && !arguments.relocatable) {
error("please provide hex or relocatable flags");
}
std::cout << "\t output: " << arguments.output_file << std::endl;
std::cout << "\t hex: " << arguments.hex << std::endl;
std::cout << "\t debug: " << arguments.debug << std::endl;
std::cout << "\t relocatable: " << arguments.relocatable << std::endl;
std::cout << "\t args: ";
for (const auto &arg : arguments.args) std::cout << arg << " ";
std::cout << std::endl;
return 0;
}