poafloc

poafloc - Parser Of Arguments For Lines Of Commands
git clone git://git.dimitrijedobrota.com/poafloc.git
Log | Files | Refs | README | LICENSE

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:
Margs.hpp | 46+++++++++++++++++++++++++++++++---------------
Mdemo.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; }