Welcome to little lamb

Code » limb » commit f935ee3

Add loadopt_auto_noconfig()

author Olivier Brunel
2023-04-05 18:06:12 UTC
committer Olivier Brunel
2023-05-20 18:06:35 UTC
parent dd77362234e044cf541fc46c163abaa61ee61563

Add loadopt_auto_noconfig()

Similar to what's available via autoopt.h this allows to automatically
parse an option "noconfig" to disable loading (specified) options from
configuration file when using loadopt(3).

src/doc/loadopt.h.0.md +7 -0
src/doc/loadopt.h/loadopt_auto_noconfig.3.md +50 -0
src/doc/parseopt.h/parseopt.3.md +1 -1
src/include/loadopt.h +1 -3
src/liblimb/include/limb/loadopt.h +4 -4
src/liblimb/loadopt.h/loadopt.c +0 -31
src/liblimb/loadopt.h/{loadopt_handle_noconfig.c => loadopt_auto_noconfig.c} +15 -12

diff --git a/src/doc/loadopt.h.0.md b/src/doc/loadopt.h.0.md
index 45d6378..d6663b5 100644
--- a/src/doc/loadopt.h.0.md
+++ b/src/doc/loadopt.h.0.md
@@ -35,6 +35,10 @@ The following macros are defined :
 :: To define required or optional argument in a *struct option* array to be
 :: checked by [loadopt](3)
 
+: *AUTOOPT_NOCONFIG*
+:: To define the option to disable loading (specified) options from
+:: configuration
+
 ## Structures
 
 The following structure are defined :
@@ -48,3 +52,6 @@ The following functions are defined :
 
 : [loadopt](3)
 :: To parse options from command-line & optionally configuration file
+
+: [loadopt_auto_noconfig](3)
+:: To parse the "noconfig" option automatically
diff --git a/src/doc/loadopt.h/loadopt_auto_noconfig.3.md b/src/doc/loadopt.h/loadopt_auto_noconfig.3.md
new file mode 100644
index 0000000..2ce1581
--- /dev/null
+++ b/src/doc/loadopt.h/loadopt_auto_noconfig.3.md
@@ -0,0 +1,50 @@
+% limb manual
+% loadopt_auto_noconfig(3)
+
+# NAME
+
+loadopt\_auto\_noconfig - automatic handling of the "noconfig" option
+
+# SYNOPSIS
+
+    #include <limb/autoopt.h>
+
+```pre hl
+AUTOOPT_NOCONFIG(<em>shortopt</em>, <em>longopt</em>, <em>flags</em>, <em>id</em>)
+
+int loadopt_auto_noconfig(int <em>idx</em>, const struct option *<em>options</em>, struct loadopt *<em>ctx</em>)
+```
+
+# DESCRIPTION
+
+The `loadopt_auto_noconfig`() function is intended to be used during parsing of
+command-line options via [loadopt](3), to handle automatically a "noconfig"
+option.
+
+This option can be used on command-line to disable the loading of (specified)
+default values from configuration file, and accepts an optional argument.
+
+You can define such an option through the convenience macro *AUTOOPT_NOCONFIG*.
+
+The `idx` argument must be the index of the option to be processed inside the
+array `options`. The `ctx` argument must be a pointer to the same structure that
+is being used with [loadopt](3).
+
+If no argument was given to the option, it will disable loading options from the
+configuration file altogether. Else, the argument is expected to be a
+coma-separated list of option names (`longopt`) to be disabled. Partial names
+are accepted only when they are unique to one option.
+
+# RETURN VALUE
+
+The `loadopt_auto_noconfig`() function returns 0 on success. Otherwise, it
+returns -1 and sets `errno` to indicate the error. It also emits a warning
+(through the [warn](3) family of functions), similar to what [loadopt](3) does.
+
+# ERRORS
+
+The `loadopt_auto_noconfig`() function may fail i:
+
+: *EINVAL*
+:: The argument contained at least one unknown option (or partial match to more
+:: than a single option).
diff --git a/src/doc/parseopt.h/parseopt.3.md b/src/doc/parseopt.h/parseopt.3.md
index 942621e..6cbfdbb 100644
--- a/src/doc/parseopt.h/parseopt.3.md
+++ b/src/doc/parseopt.h/parseopt.3.md
@@ -171,4 +171,4 @@ The `parseopt`() function may fail if :
 
 # SEE ALSO
 
-[autoopt](3)
+[loadopt](3), [autoopt](3)
diff --git a/src/include/loadopt.h b/src/include/loadopt.h
index 393bf91..6103b1f 100644
--- a/src/include/loadopt.h
+++ b/src/include/loadopt.h
@@ -4,8 +4,8 @@
 #ifndef LIMB_LIMB_LOADOPT_H
 #define LIMB_LIMB_LOADOPT_H
 
-#include <limb/parseopt.h>
 #include <limb/gccattributes.h>
+#include <limb/loadopt.h>
 
 enum state {
     STATE_NONE = 0,
@@ -29,6 +29,4 @@ enum {
 void add_optflags(u8 *optflags, int idx, u8 val) gccattr_hidden;
 u8 get_optflags(const u8 *optflags, int idx) gccattr_hidden;
 
-int loadopt_handle_noconfig(int idx, const struct option *options, struct loadopt *ctx) gccattr_hidden;
-
 #endif /* LIMB_LIMB_LOADOPT_H */
diff --git a/src/liblimb/include/limb/loadopt.h b/src/liblimb/include/limb/loadopt.h
index d484333..9fadd92 100644
--- a/src/liblimb/include/limb/loadopt.h
+++ b/src/liblimb/include/limb/loadopt.h
@@ -45,12 +45,12 @@ struct loadopt {
     u16 from_file       : 1;
 };
 
-enum {
-    LOADOPT_ID_NOCONFIG  = 1,
-};
-
 extern int loadopt(int argc, const char **argv, const struct option *options,
                    const char *file, const char *section, unsigned int poflags,
                    struct loadopt *ctx);
 
+/* dont load (specified) options fro config file */
+#define AUTOOPT_NOCONFIG(s,l,f,i)   OPTION_ARG_OPT( s, l, OPT_SKIP | f, i)
+extern int loadopt_auto_noconfig(int idx, const struct option *options, struct loadopt *ctx);
+
 #endif /* LIMB_LOADOPT_H */
diff --git a/src/liblimb/loadopt.h/loadopt.c b/src/liblimb/loadopt.h/loadopt.c
index bcd4b21..7de2984 100644
--- a/src/liblimb/loadopt.h/loadopt.c
+++ b/src/liblimb/loadopt.h/loadopt.c
@@ -64,26 +64,6 @@ parseopt_warn(int c, const char **argv, const struct option *options,
     }
 }
 
-static int
-loadopt_handle(int c, const char **argv, const struct option *options,
-               int from_file, struct parseopt *ctx)
-{
-    if (!from_file && c >= 0 && options[ctx->idx].id == LOADOPT_ID_NOCONFIG)
-        return loadopt_handle_noconfig(ctx->idx, options, (struct loadopt *) ctx);
-
-    if (errno == ENOENT && ctx->idx >= 0) {
-        const char *s = argv[ctx->cur] + ctx->off;
-        size_t l = byte_chr(s, strlen(s), '=');
-        adde("did you mean --", options[ctx->idx].longopt);
-        for (int i = ctx->idx + 1; options[i].longopt; ++i)
-            if (!strncmp(s, options[i].longopt, l))
-                adde(" or --", options[i].longopt);
-        err(" ?");
-    }
-
-    return c;
-}
-
 int
 loadopt(int argc, const char **argv, const struct option *options,
         const char *file, const char *section, unsigned int poflags,
@@ -98,7 +78,6 @@ loadopt(int argc, const char **argv, const struct option *options,
     }
 
     /* init is done, parse options from command line */
-nextopt:
     if (ctx->state == STATE_INIT) {
         int c;
         c = parseopt(argc, argv, options, poflags, (struct parseopt *) ctx);
@@ -108,11 +87,6 @@ nextopt:
         else
             parseopt_warn(c, argv, options, (struct parseopt *) ctx);
 
-        if (c) {
-            c = loadopt_handle(c, argv, options, 0, (struct parseopt *) ctx);
-            if (!c)
-                goto nextopt;
-        }
         if (c)
             return c;
         ctx->state = STATE_CMDLINE;
@@ -229,11 +203,6 @@ nextfileopt:
             else
                 parseopt_warn(c, argv, options, &po);
 
-            if (c) {
-                c = loadopt_handle(c, argv, options, 1, &po);
-                if (!c)
-                    goto nextfileopt;
-            }
             if (c) {
                 /* adjust returned value */
                 ctx->arg = po.arg;
diff --git a/src/liblimb/loadopt.h/loadopt_handle_noconfig.c b/src/liblimb/loadopt.h/loadopt_auto_noconfig.c
similarity index 50%
rename from src/liblimb/loadopt.h/loadopt_handle_noconfig.c
rename to src/liblimb/loadopt.h/loadopt_auto_noconfig.c
index 723fe02..46f85fb 100644
--- a/src/liblimb/loadopt.h/loadopt_handle_noconfig.c
+++ b/src/liblimb/loadopt.h/loadopt_auto_noconfig.c
@@ -2,12 +2,13 @@
  * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
 /* SPDX-License-Identifier: GPL-2.0-only */
 #include <errno.h>
-#include <limb/loadopt.h>
+#include <stddef.h> /* offsetof() */
+#include <limb/bytestr.h>
 #include <limb/output.h>
 #include "loadopt.h"
 
 int
-loadopt_handle_noconfig(int idx, const struct option *options, struct loadopt *ctx)
+loadopt_auto_noconfig(int idx, const struct option *options, struct loadopt *ctx)
 {
     if (!ctx->arg) {
         for (int i = 0; options[i].longopt; ++i)
@@ -15,21 +16,23 @@ loadopt_handle_noconfig(int idx, const struct option *options, struct loadopt *c
                 add_optflags(ctx->optflags, i, OPT_SKIP);
     } else {
         for (char *s = strtok((char *) ctx->arg, ","); s; s = strtok(NULL, ",")) {
-            int i;
-            for (i = 0; options[i].longopt; ++i) {
-                if (!strcmp(s, options[i].longopt)) {
-                    add_optflags(ctx->optflags, i, OPT_SKIP);
-                    break;
-                }
-            }
-            if (!options[i].longopt) {
+            size_t l= strlen(s);
+            int first = -1, i;
+            i = byte_get_match_full(&first, s, l, options,
+                                    offsetof(struct option, longopt), sizeof(*options));
+            if (i < 0) {
                 char buf[2] = { options[idx].shortopt, 0 };
                 warn("invalid argument to option --", options[idx].longopt,
                      (*buf) ? "/-" : "", buf, ": ", ctx->arg);
-                return (errno = EINVAL, -1);
+                if (first >= 0)
+                    list_matches_full(err_putmsg, OLVL_NORMAL, "did you mean ",
+                                      "--", " or ", " ?", s, l, first, options,
+                                      offsetof(struct option, longopt), sizeof(*options));
+                return (errno = EINVAL, 0);
             }
+            add_optflags(ctx->optflags, i, OPT_SKIP);
         }
     }
 
-    return 0;
+    return 1;
 }