poafloc

Parser 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 |

commitaee752599f659cfc997c7b10dd8f54fc63c30eed
parent2a2b4adf380a3a90c6a04413958986b622219bcf
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateSat, 8 Jun 2024 21:55:01 +0200

Internal renames and shuffling code around

Diffstat:
Margs.hpp|+++++++++++++++++++++++++++++++++++++++++-----------------------------------------

1 files changed, 68 insertions(+), 68 deletions(-)


diff --git a/args.hpp b/args.hpp

@@ -17,7 +17,7 @@ class Parser {

const char *name;
const int key;
const char *arg;
const uint8_t options;
const uint8_t flags;
const char *message;
const int group;
};

@@ -41,7 +41,7 @@ class Parser {

using parse_f = int (*)(int key, const char *arg, Parser *parser);
const option_t *options;
const parse_f parser;
const parse_f parse;
const char *doc;
const char *message;
};

@@ -55,8 +55,8 @@ class Parser {

private:
Parser(void *input, argp_t *argp) : input(input), argp(argp) {
bool hidden = false;
int group = 0, key_last = 0;
bool hidden = false;
for (int i = 0; true; i++) {
const auto &opt = argp->options[i];

@@ -69,7 +69,7 @@ class Parser {

}
if (!opt.key) {
if ((opt.options & ALIAS) == 0) {
if ((opt.flags & ALIAS) == 0) {
std::cerr << "non alias without a key\n";
throw new std::runtime_error("no key");
}

@@ -82,7 +82,7 @@ class Parser {

trie.insert(opt.name, key_last);
if (hidden) continue;
if (opt.options & Option::HIDDEN) continue;
if (opt.flags & Option::HIDDEN) continue;
help_entries.back().push(opt.name);
} else {

@@ -94,10 +94,10 @@ class Parser {

if (opt.name) trie.insert(opt.name, opt.key);
options[key_last = opt.key] = &opt;
bool arg_opt = opt.options & Option::ARG_OPTIONAL;
bool arg_opt = opt.flags & Option::ARG_OPTIONAL;
if ((opt.options & ALIAS) == 0) {
if ((hidden = opt.options & Option::HIDDEN)) continue;
if ((opt.flags & ALIAS) == 0) {
if ((hidden = opt.flags & Option::HIDDEN)) continue;
help_entries.emplace_back(opt.arg, opt.message, group,
arg_opt);

@@ -113,7 +113,7 @@ class Parser {

}
if (hidden) continue;
if (opt.options & Option::HIDDEN) continue;
if (opt.flags & Option::HIDDEN) continue;
if (opt.name) help_entries.back().push(opt.name);
if (std::isprint(opt.key)) {

@@ -123,24 +123,24 @@ class Parser {

}
}
std::sort(begin(help_entries), end(help_entries));
help_entries.emplace_back(nullptr, "Give this help list", -1);
help_entries.back().push("help");
help_entries.back().push('?');
help_entries.emplace_back(nullptr, "Give a short usage message", -1);
help_entries.back().push("usage");
std::sort(begin(help_entries), end(help_entries));
}
int parse(int argc, char *argv[], void *input) {
int args = 0, i;
argp->parser(Key::INIT, 0, this);
argp->parse(Key::INIT, 0, this);
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
argp->parser(Key::ARG, argv[i], this);
argp->parse(Key::ARG, argv[i], this);
args++;
continue;
}

@@ -165,14 +165,14 @@ class Parser {

if (opt[j + 1] != 0) {
// rest of the line is option argument
arg = opt + j + 1;
} else if ((option->options & ARG_OPTIONAL) == 0) {
} else if ((option->flags & ARG_OPTIONAL) == 0) {
// next argv is option argument
if (i == argc) goto missing;
arg = argv[++i];
}
}
argp->parser(key, arg, this);
argp->parse(key, arg, this);
// if last option required argument we are done
if (arg) break;

@@ -205,90 +205,46 @@ class Parser {

if (eq) {
// everything after = is option argument
arg = eq + 1;
} else if ((option->options & ARG_OPTIONAL) == 0) {
} else if ((option->flags & ARG_OPTIONAL) == 0) {
// next argv is option argument
if (i == argc) goto missing;
arg = argv[++i];
}
}
argp->parser(key, arg, this);
argp->parse(key, arg, this);
}
}
// parse rest argv as normal arguments
for (i = i + 1; i < argc; i++) {
argp->parser(Key::ARG, argv[i], this);
argp->parse(Key::ARG, argv[i], this);
args++;
}
if (!args) argp->parser(Key::NO_ARGS, 0, this);
if (!args) argp->parse(Key::NO_ARGS, 0, this);
argp->parser(Key::END, 0, this);
argp->parser(Key::SUCCESS, 0, this);
argp->parse(Key::END, 0, this);
argp->parse(Key::SUCCESS, 0, this);
return 0;
unknown:
std::cerr << std::format("unknown option {}\n", argv[i]);
argp->parser(Key::ERROR, 0, this);
argp->parse(Key::ERROR, 0, this);
return 1;
missing:
std::cerr << std::format("option {} missing a value\n", argv[i]);
argp->parser(Key::ERROR, 0, this);
argp->parse(Key::ERROR, 0, this);
return 2;
excess:
std::cerr << std::format("option {} don't require a value\n", argv[i]);
argp->parser(Key::ERROR, 0, this);
argp->parse(Key::ERROR, 0, this);
return 3;
}
class trie_t {
public:
~trie_t() noexcept {
for (uint8_t i = 0; i < 26; i++) {
delete children[i];
}
}
void insert(const std::string &option, int key) {
trie_t *crnt = this;
for (const char c : option) {
if (!crnt->terminal) crnt->key = key;
crnt->count++;
const uint8_t idx = c - 'a';
if (!crnt->children[idx]) crnt->children[idx] = new trie_t();
crnt = crnt->children[idx];
}
crnt->terminal = true;
crnt->key = key;
}
int get(const std::string &option) const {
const trie_t *crnt = this;
for (const char c : option) {
const uint8_t idx = c - 'a';
if (!crnt->children[idx]) return 0;
crnt = crnt->children[idx];
}
if (!crnt->terminal && crnt->count > 1) return 0;
return crnt->key;
}
private:
trie_t *children[26] = {0};
uint8_t count = 0;
int key = 0;
bool terminal = false;
};
struct help_entry_t {
std::vector<const char *> opt_long;
std::vector<char> opt_short;

@@ -483,6 +439,50 @@ class Parser {

exit(0);
}
class trie_t {
public:
~trie_t() noexcept {
for (uint8_t i = 0; i < 26; i++) {
delete children[i];
}
}
void insert(const std::string &option, int key) {
trie_t *crnt = this;
for (const char c : option) {
if (!crnt->terminal) crnt->key = key;
crnt->count++;
const uint8_t idx = c - 'a';
if (!crnt->children[idx]) crnt->children[idx] = new trie_t();
crnt = crnt->children[idx];
}
crnt->terminal = true;
crnt->key = key;
}
int get(const std::string &option) const {
const trie_t *crnt = this;
for (const char c : option) {
const uint8_t idx = c - 'a';
if (!crnt->children[idx]) return 0;
crnt = crnt->children[idx];
}
if (!crnt->terminal && crnt->count > 1) return 0;
return crnt->key;
}
private:
trie_t *children[26] = {0};
uint8_t count = 0;
int key = 0;
bool terminal = false;
};
const argp_t *argp;
std::unordered_map<int, const option_t *> options;