poafloc

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

commit 5f6fdaafcf0090008b10d438e4cbcbbe7a3ec90f
parent 64db814bc7776fd9567faa466ffbb7813932d83d
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Wed, 12 Jun 2024 11:59:02 +0200

Parse args at the end on in order

Diffstat:
Minclude/args.h | 1+
Minclude/args.hpp | 2+-
Msrc/args.cpp | 63++++++++++++++++++++++++++++-----------------------------------
Msrc/help.cpp | 6+++---
4 files changed, 33 insertions(+), 39 deletions(-)

diff --git a/include/args.h b/include/args.h @@ -91,6 +91,7 @@ enum ENUM_PARSE { MANGLE_ENUM(PARSE, NO_HELP) = 0x2, MANGLE_ENUM(PARSE, NO_EXIT) = 0x4, MANGLE_ENUM(PARSE, SILENT) = 0x8, + MANGLE_ENUM(PARSE, IN_ORDER) = 0x10, }; #if !defined __cplusplus || defined WITH_C_BINDINGS diff --git a/include/args.hpp b/include/args.hpp @@ -48,7 +48,7 @@ class Parser { int handle_missing(bool shrt, const char *argv); int handle_excess(bool shrt, const char *argv); - void print_usage(FILE *stream) const; + void print_other_usages(FILE *stream) const; void help(FILE *stream) const; void usage(FILE *stream) const; void see(FILE *stream) const; diff --git a/src/args.cpp b/src/args.cpp @@ -15,7 +15,6 @@ int parse(const argp_t *argp, int argc, char *argv[], unsigned flags, } void usage(const Parser *parser) { help(parser, stderr, Help::STD_USAGE); } - void help(const Parser *parser, FILE *stream, unsigned flags) { if (!parser || !stream) return; @@ -58,30 +57,22 @@ Parser::Parser(const argp_t *argp, unsigned flags, void *input) } if (!opt.key) { - if (!(opt.flags & ALIAS)) { - // non alias without a key, silently ignoring - continue; - } + // non alias without a key, silently ignoring + if (!(opt.flags & ALIAS)) continue; - if (!key_last) { - // nothing to alias, silently ignoring - continue; - } + // nothing to alias, silently ignoring + if (!key_last) continue; - if (!trie.insert(opt.name, key_last)) { - // option not valid, silently ignoring - continue; - } + // option not valid, silently ignoring + if (!trie.insert(opt.name, key_last)) continue; if (hidden) continue; if (opt.flags & Option::HIDDEN) continue; help_entries.back().push(opt.name); } else { - if (options.count(opt.key)) { - // duplicate key, silently ignoring - continue; - } + // duplicate key, silently ignoring + if (options.count(opt.key)) continue; if (opt.name) trie.insert(opt.name, opt.key); options[key_last = opt.key] = &opt; @@ -97,10 +88,8 @@ Parser::Parser(const argp_t *argp, unsigned flags, void *input) if (opt.name) help_entries.back().push(opt.name); if (std::isprint(opt.key)) help_entries.back().push(opt.key); } else { - if (!key_last) { - // nothing to alias, silently ignoring - continue; - } + // nothing to alias, silently ignoring + if (!key_last) continue; if (hidden) continue; if (opt.flags & Option::HIDDEN) continue; @@ -125,15 +114,17 @@ Parser::Parser(const argp_t *argp, unsigned flags, void *input) int Parser::parse(int argc, char *argv[], void *input) { const bool is_help = !(m_flags & NO_HELP); - int args = 0, err_code = 0, i; + std::vector<const char *> args; + int arg_cnt = 0, err_code = 0, i; m_name = basename(argv[0]); argp->parse(Key::INIT, 0, this); for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { - argp->parse(Key::ARG, argv[i], this); - args++; + if (m_flags & IN_ORDER) argp->parse(Key::ARG, argv[i], this); + else args.push_back(argv[i]); + arg_cnt++; continue; } @@ -194,15 +185,12 @@ int Parser::parse(int argc, char *argv[], void *input) { } const int key = trie.get(opt_s.data()); - if (!key) { err_code = handle_unknown(0, argv[i]); goto error; } const auto *option = options[key]; - const char *arg = nullptr; - if (!option->arg && is_eq) { err_code = handle_excess(0, argv[i]); goto error; @@ -220,13 +208,18 @@ int Parser::parse(int argc, char *argv[], void *input) { } } + // parse previous arguments if IN_ORDER is not set + for (const auto arg : args) { + argp->parse(Key::ARG, arg, this); + } + // parse rest argv as normal arguments for (i = i + 1; i < argc; i++) { argp->parse(Key::ARG, argv[i], this); - args++; + arg_cnt++; } - if (!args) argp->parse(Key::NO_ARGS, 0, this); + if (!arg_cnt) argp->parse(Key::NO_ARGS, 0, this); argp->parse(Key::END, 0, this); argp->parse(Key::SUCCESS, 0, this); @@ -248,8 +241,8 @@ int Parser::handle_unknown(bool shrt, const char *argv) { failure(this, 1, 0, unknown_fmt[shrt], argv + 1); see(stderr); - if(m_flags & NO_EXIT) return 1; - exit(1); + if (m_flags & NO_EXIT) return 1; + exit(1); } int Parser::handle_missing(bool shrt, const char *argv) { @@ -263,8 +256,8 @@ int Parser::handle_missing(bool shrt, const char *argv) { failure(this, 2, 0, missing_fmt[shrt], argv + 1); see(stderr); - if(m_flags & NO_EXIT) return 2; - exit(2); + if (m_flags & NO_EXIT) return 2; + exit(2); } int Parser::handle_excess(bool shrt, const char *argv) { @@ -273,8 +266,8 @@ int Parser::handle_excess(bool shrt, const char *argv) { failure(this, 3, 0, "option '%s' doesn't allow an argument\n", argv); see(stderr); - if(m_flags & NO_EXIT) return 3; - exit(3); + if (m_flags & NO_EXIT) return 3; + exit(3); } const char *Parser::basename(const char *name) { diff --git a/src/help.cpp b/src/help.cpp @@ -30,7 +30,7 @@ bool Parser::help_entry_t::operator<(const help_entry_t &rhs) const { return std::strcmp(opt_long.front(), rhs.opt_long.front()) < 0; } -void Parser::print_usage(FILE *stream) const { +void Parser::print_other_usages(FILE *stream) const { if (argp->doc) { std::istringstream iss(argp->doc); std::string s; @@ -54,7 +54,7 @@ void Parser::help(FILE *stream) const { } std::fprintf(stream, "Usage: %s [OPTIONS...]", m_name); - print_usage(stream); + print_other_usages(stream); if (!m1.empty()) std::fprintf(stream, "\n%s", m1.c_str()); std::fprintf(stream, "\n\n"); @@ -176,7 +176,7 @@ void Parser::usage(FILE *stream) const { } } - print_usage(stream); + print_other_usages(stream); std::putc('\n', stream); }