summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2025-03-08 17:48:05 -0500
committerWormHeamer2025-03-08 17:48:05 -0500
commit2b156fe0ca12386a7e61c02067bc16f6028d62d6 (patch)
treec5c1cf01e763371d47592ca7b1d2e090e480ce9e
parentfe358325bd443a076732259bd2a50c97f12d7602 (diff)
allow -- argument to stop parsing options
-rw-r--r--args.h33
1 files changed, 23 insertions, 10 deletions
diff --git a/args.h b/args.h
index 35c5283..b8e2d94 100644
--- a/args.h
+++ b/args.h
@@ -6,6 +6,7 @@
typedef struct {
const char **arg;
const char *opt_end;
+ int no_opts;
} ArgsState;
typedef enum {
@@ -24,7 +25,7 @@ ArgResult arg_getv(ArgsState *a, const char *fmt, Str *arg, ...);
#include <stdarg.h>
ArgsState args_begin(const char **argv) {
- return (ArgsState) { argv + 1, NULL };
+ return (ArgsState) { argv + 1, NULL, 0 };
}
static int arg_opt_find(const char **opts, Str key) {
@@ -89,21 +90,33 @@ static ArgResult arg_got_short(ArgsState *a, const char *fmt, Str *arg) {
}
static ArgResult arg_get_long(ArgsState *a, const char *fmt, const char **opts, int *optv, Str *arg) {
- if (*a->arg && !**a->arg) a->arg++;
+recurse:
if (!*a->arg) return ARG_END;
+ if (a->no_opts) {
+pop: *arg = str_from_cstr(*a->arg++);
+ return ARG_OK;
+ }
const char *arg_end = *a->arg + strlen(*a->arg);
- if (a->opt_end != arg_end) {
- if (a->arg[0][0] != '-' || a->arg[0][1] == '\0') {
- *arg = str_from_cstr(*a->arg++);
- return ARG_OK;
+ if (a->opt_end == arg_end) {
+ if (!**a->arg) {
+ a->arg++;
+ goto recurse;
}
- if (a->arg[0][1] == '-') {
+ return arg_got_short(a, fmt, arg);
+ }
+ if (**a->arg != '-' || a->arg[0][1] == '\0') goto pop;
+ if (a->arg[0][1] == '-') {
+ if (a->arg[0][2] == '\0') {
+ a->no_opts = 1;
+ a->arg++;
+ goto recurse;
+ } else {
return arg_got_long(a, opts, optv, arg);
}
- (*a->arg)++;
- a->opt_end = arg_end;
}
- return arg_got_short(a, fmt, arg);
+ (*a->arg)++;
+ a->opt_end = arg_end;
+ goto recurse;
}
ArgResult arg_getv(ArgsState *a, const char *fmt, Str *arg, ...) {