From eece9692d707ccb20356ec06955f8308c4e59ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 17 Dec 2023 14:18:48 +0100 Subject: New upstream version 4.19 --- src/opt.c | 64 ++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 27 deletions(-) (limited to 'src/opt.c') diff --git a/src/opt.c b/src/opt.c index f91785d..ab482ad 100644 --- a/src/opt.c +++ b/src/opt.c @@ -20,6 +20,7 @@ #include #include #include +#undef HX_getopt #include "internal.h" /* Definitions */ @@ -697,16 +698,19 @@ static int HX_getopt_normal(const char *cur, const struct HX_getopt_vars *par) return HXOPT_S_NORMAL | HXOPT_I_ADVARG; } -EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc, - const char ***argv, unsigned int flags) +EXPORT_SYMBOL int HX_getopt5(const struct HXoption *table, char **orig_argv, + int *new_argc, char ***new_argv, unsigned int flags) { struct HX_getopt_vars ps; - const char **opt = *argv; + const char **opt = const_cast(const char **, orig_argv); int state = HXOPT_S_NORMAL; int ret = -ENOMEM; - unsigned int argk; - const char *cur; + unsigned int argk = 0; + if (new_argc != nullptr) + *new_argc = 0; + if (new_argv != nullptr) + *new_argv = nullptr; memset(&ps, 0, sizeof(ps)); ps.remaining = HXdeque_init(); if (ps.remaining == NULL) { @@ -714,7 +718,7 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc, goto out; } ps.flags = flags; - ps.arg0 = **argv; + ps.arg0 = *opt; ps.cbi.table = table; if (*opt != NULL) { @@ -733,7 +737,7 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc, if (posix_me_harder()) ps.flags |= HXOPT_RQ_ORDER; - for (cur = *opt; cur != NULL; ) { + for (const char *cur = *opt; cur != NULL; ) { if (state == HXOPT_S_TWOLONG) state = HX_getopt_twolong(opt, &ps); else if (state == HXOPT_S_LONG) @@ -764,33 +768,19 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc, state &= ~HXOPT_I_MASK; } - if (!(ps.flags & HXOPT_KEEP_ARGV)) { - const char **nvec = reinterpret_cast(const char **, - HXdeque_to_vec(ps.remaining, &argk)); - if (nvec == NULL) { + if (new_argv != nullptr) { + *new_argv = reinterpret_cast(char **, HXdeque_to_vec(ps.remaining, &argk)); + if (*new_argv == nullptr) { ret = -errno; goto out; } - if (ps.flags & HXOPT_DESTROY_OLD) - /* - * Only the "true, original" argv is stored on the - * stack - the argv that HX_getopt() produces is on - * the heap, so the %HXOPT_DESTROY_OLD flag should be - * passed when you use passthrough chaining, i.e. all - * but the first call to HX_getopt() should have this - * set. - */ - HX_zvecfree(const_cast2(char **, *argv)); - - *argv = nvec; - if (argc != NULL) - *argc = argk; - /* pointers are owned by nvec/argv now */ + if (new_argc != nullptr) + *new_argc = argk; + /* pointers are owned by new_argv now, so free only the deque head */ HXdeque_free(ps.remaining); ps.remaining = nullptr; } ret = HXOPT_ERR_SUCCESS; - out: if (ret == HXOPT_ERR_SUCCESS) { } else if (ret < 0) { @@ -808,6 +798,26 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc, return ret; } +EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc, + char ***argv, unsigned int flags) +{ + int new_argc = 0; + char **new_argv = nullptr; + int ret = HX_getopt5(table, *argv, &new_argc, + flags & HXOPT_KEEP_ARGV ? nullptr : &new_argv, flags); + if (ret != HXOPT_ERR_SUCCESS) + return ret; + if (flags & HXOPT_KEEP_ARGV) + // NO_CREATE_NEW / DESTROY_NEW + new_argv = *argv; + else if (flags & HXOPT_DESTROY_OLD) + HX_zvecfree(*argv); + if (argc != nullptr) + *argc = new_argc; + *argv = new_argv; + return ret; +} + EXPORT_SYMBOL void HX_getopt_help(const struct HXoptcb *cbi, FILE *nfp) { FILE *fp = (nfp == NULL) ? stderr : nfp; -- cgit v1.2.3