summaryrefslogtreecommitdiff
path: root/src/opt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/opt.c')
-rw-r--r--src/opt.c64
1 files changed, 37 insertions, 27 deletions
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 <libHX/misc.h>
#include <libHX/option.h>
#include <libHX/string.h>
+#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;