summary refs log tree commit diff
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, ...) {