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:
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);
}