commit 36fd7278d9c884f92d36fa9a886e0c420dc36551
parent 660f946bfbd9e8aa1aae6eca0d235385ef89ed45
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Wed, 5 Jun 2024 23:15:12 +0200
Recognize long and short options
Diffstat:
M | args.hpp | | | 46 | +++++++++++++++++++++++++++++++--------------- |
M | demo.cpp | | | 44 | ++++++++++++++++---------------------------- |
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;
}