From 7e5a1fa68dbdc2aa034d9e22648837ef63e57d5e Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sat, 18 Oct 2025 15:38:02 -0400 Subject: Fix '--' arg parsing --- src/stdlib/cli.c | 51 ++++++++++++++++++++++++++++++++------------------- src/stdlib/cli.h | 2 +- 2 files changed, 33 insertions(+), 20 deletions(-) (limited to 'src/stdlib') diff --git a/src/stdlib/cli.c b/src/stdlib/cli.c index d545cbc3..6e0a4b81 100644 --- a/src/stdlib/cli.c +++ b/src/stdlib/cli.c @@ -205,35 +205,48 @@ void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help, const c for (int i = 0; i < spec_len; i++) { parsed[i] = pop_cli_flag(&args, spec[i].short_flag, spec[i].name, spec[i].dest, spec[i].type); } - for (int64_t i = 0; i < (int64_t)args.length; i++) { + + bool show_help = false; + if (pop_boolean_cli_flag(&args, 'h', "help", &show_help) && show_help) { + print(help); + exit(0); + } + bool show_version = false; + if (pop_boolean_cli_flag(&args, 'v', "version", &show_version) && show_version) { + print(version); + exit(0); + } + + List_t before_double_dash = args, after_double_dash = EMPTY_LIST; + for (int i = 0; i < (int64_t)args.length; i++) { const char *arg = *(const char **)(args.data + i * args.stride); if (streq(arg, "--")) { - List$remove_at(&args, I(i + 1), I(1), sizeof(const char *)); + before_double_dash = List$slice(args, I(1), I(i)); + after_double_dash = List$slice(args, I(i + 2), I(-1)); break; } else if (arg[0] == '-') { print_err("Unrecognized argument: ", arg); } } - for (int i = 0; i < spec_len && args.length > 0; i++) { - if (!parsed[i] && spec[i].required) { - parsed[i] = pop_cli_positional(&args, spec[i].name, spec[i].dest, spec[i].type); + + for (int i = 0; i < spec_len && before_double_dash.length > 0; i++) { + if (!parsed[i]) { + parsed[i] = pop_cli_positional(&before_double_dash, spec[i].name, spec[i].dest, spec[i].type, false); } } + for (int i = 0; i < spec_len && after_double_dash.length > 0; i++) { + if (!parsed[i]) { + parsed[i] = pop_cli_positional(&after_double_dash, spec[i].name, spec[i].dest, spec[i].type, true); + } + } + for (int i = 0; i < spec_len; i++) { if (!parsed[i] && spec[i].required) print_err("Missing required flag: --", spec[i].name, "\n", usage); } - bool show_help = false; - if (pop_boolean_cli_flag(&args, 'h', "help", &show_help) && show_help) { - print(help); - exit(0); - } - bool show_version = false; - if (pop_boolean_cli_flag(&args, 'v', "version", &show_version) && show_version) { - print(version); - exit(0); - } - if (args.length > 0) { - print_err("Unknown flag values: ", generic_as_text(&args, true, List$info(&CString$info))); + + List_t remaining_args = List$concat(before_double_dash, after_double_dash, sizeof(const char *)); + if (remaining_args.length > 0) { + print_err("Unknown flag values: ", generic_as_text(&remaining_args, true, List$info(&CString$info))); } } @@ -397,12 +410,12 @@ bool pop_cli_flag(List_t *args, char short_flag, const char *flag, void *dest, c return false; } -bool pop_cli_positional(List_t *args, const char *flag, void *dest, const TypeInfo_t *type) { +bool pop_cli_positional(List_t *args, const char *flag, void *dest, const TypeInfo_t *type, bool allow_dashes) { if (args->length == 0) { print_err("No value provided for flag: --", flag); return false; } - int64_t n = parse_arg_list(*args, flag, dest, type, true); + int64_t n = parse_arg_list(*args, flag, dest, type, allow_dashes); if (n == 0) print_err("No value provided for flag: --", flag); List$remove_at(args, I(1), I(n), sizeof(const char *)); return true; diff --git a/src/stdlib/cli.h b/src/stdlib/cli.h index 8f9e2a9c..596409c1 100644 --- a/src/stdlib/cli.h +++ b/src/stdlib/cli.h @@ -22,4 +22,4 @@ void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help, const c (cli_arg_t[]){__VA_ARGS__}) bool pop_cli_flag(List_t *args, char short_flag, const char *flag, void *dest, const TypeInfo_t *type); -bool pop_cli_positional(List_t *args, const char *flag, void *dest, const TypeInfo_t *type); +bool pop_cli_positional(List_t *args, const char *flag, void *dest, const TypeInfo_t *type, bool allow_dashes); -- cgit v1.2.3