Welcome to little lamb

Code » limb » commit 21eee58

loadopt.h: Use LO_*() macros to access members of struct..

author Olivier Brunel
2023-04-22 07:22:21 UTC
committer Olivier Brunel
2023-05-20 18:06:37 UTC
parent 6923aeb465b4b61db6d62945964ee1b7ca8eada5

loadopt.h: Use LO_*() macros to access members of struct..

..loadopt, to be considered opaque.

src/doc/loadopt.h.0.md +16 -1
src/doc/loadopt.h/loadopt.3.md +19 -12
src/liblimb/include/limb/loadopt.h +9 -6
src/liblimb/loadopt.h/loadopt.c +13 -13
src/liblimb/loadopt.h/loadopt_auto_noconfig.c +3 -3

diff --git a/src/doc/loadopt.h.0.md b/src/doc/loadopt.h.0.md
index d6663b5..53c61ee 100644
--- a/src/doc/loadopt.h.0.md
+++ b/src/doc/loadopt.h.0.md
@@ -31,6 +31,9 @@ The following macros are defined :
 : *LOADOPT_ARGUMENTS*, *LOADOPT_DONE_OPEN*, *LOADOPT_DONE*
 :: To be used as element in a *struct option* array
 
+: *LOADOPT_INIT*
+:: Value to initialize a *struct loadopt*.
+
 : *ARGUMENT_REQ*, *ARGUMENT_OPT*
 :: To define required or optional argument in a *struct option* array to be
 :: checked by [loadopt](3)
@@ -39,12 +42,24 @@ The following macros are defined :
 :: To define the option to disable loading (specified) options from
 :: configuration
 
+: *LO_ARG(`ctx`)*
+:: To get a pointer to the current option's argument.
+
+: *LO_CUR(`ctx`)*
+:: To get the index of the first argument in argv.
+
+: *LO_IDX(`ctx`)*
+:: To get the index of the current option.
+
+: *LO_FROMFILE(`ctx`)*
+:: Return whether or not the option was set in configuration file.
+
 ## Structures
 
 The following structure are defined :
 
 : *struct loadopt*
-:: A semi-opaque structure to be passed to [loadopt](3)
+:: An opaque structure to be passed to [loadopt](3)
 
 ## Functions
 
diff --git a/src/doc/loadopt.h/loadopt.3.md b/src/doc/loadopt.h/loadopt.3.md
index 3fd2e92..4b6b24a 100644
--- a/src/doc/loadopt.h/loadopt.3.md
+++ b/src/doc/loadopt.h/loadopt.3.md
@@ -13,6 +13,10 @@ loadopt - parse options from command-line and (optionally) configuration file
 int loadopt(int <em>argc</em>, const char **<em>argv</em>, const struct option *<em>options</em>,
             const char *<em>file</em>, const char *<em>section</em>, unsigned int <em>flags</em>,
             struct loadopt *<em>ctx</em>)
+
+const char *LO_ARG(struct loadopt *<em>ctx</em>)
+u16 LO_CUR(struct loadopt *<em>ctx</em>)
+int LO_IDX(struct loadopt *<em>ctx</em>)
 ```
 
 # DESCRIPTION
@@ -40,14 +44,15 @@ value is constructed as a bitwise-inclusive OR of the following :
 :: file), the option has not been set.
 :: Mostly useful when option that require an argument.
 
-The last argument `ctx` is a semi-opaque structure, that should be initialized
-to all zeroes. It contains the same members as *struct parseopt* with the same
-meaning/use as described in [parseopt](3).
-Additionally, the following members are of interest :
+The last argument `ctx` is an opaque structure that should be initialized to
+*LOADOPT_ZERO*.
+
+Accessing information is done through macros `LO_ARG`(), `LO_IDX`() and
+`LO_CUR`(), which are similar to their [parseopt](3) counterparts *PO_ARG*(),
+*PO_IDX*() and *PO_CUR*() respectively.
 
-: `from_file`
-:: When an option was found, set to 0 when the option was set on command-line,
-:: set to 1 when it comes from the configuration file.
+Additionally, macro `LO_FROMFILE`() will return 1 when the current option came
+from configuration file, zero otherwise (i.e. from command-line).
 
 ## Configuration File
 
@@ -65,9 +70,11 @@ Note however that any option already set (on command-line) will be ignored, as
 command-line options overwrite the defaults from configuration file.
 
 ! HINT:
-! If you need to know whether an option was specified an command-line or from
-! configuration file, you can check the member `from_file` of the *struct
-! loadopt*.
+! You can use `LO_FROMFILE`() to know whether an option was specified on
+! command-line or from configuration file 
+!
+! Note that when an option was specified on configuration file, its argument, if
+! any, will /not/ be preserved/remain valid once parsing the option is done.
 
 If `section` was not NULL, `loadopt`() will first look for a section of the
 specified name in the file (defined by a line containing nothing but an open
@@ -77,8 +84,8 @@ close square bracket ']'), and only process options from within said section.
 Very little is done in parsing the file, however any space at the beginning of
 a line will be skipped/ignored (except for the section header, as described
 above). Additionally, if the first character (save for spaces) on a line is
-either a semi-colon ';' or a number sign '#' then the entire line is ignored,
-allowing for comments.
+either a semi-colon (`;`) or a number sign (`#`) then the entire line is
+ignored, allowing for comments.
 
 ## Command-line Arguments
 
diff --git a/src/liblimb/include/limb/loadopt.h b/src/liblimb/include/limb/loadopt.h
index 9fadd92..be8f949 100644
--- a/src/liblimb/include/limb/loadopt.h
+++ b/src/liblimb/include/limb/loadopt.h
@@ -28,13 +28,9 @@ enum {
 #define LOADOPT_DONE        { 0, 0, ARG_NONE, OPT_DONE, 0 }
 #define LOADOPT_DONE_OPEN   { 0, 0, ARG_OPT,  OPT_DONE, 0 }
 
+/* opaque structure */
 struct loadopt {
-    /* struct parseopt */
-    u16 cur;
-    u16 off;
-    int idx;
-    const char *arg;
-    /* loadopt */
+    struct parseopt po;
     stralloc sa;
     size_t saoff;
     u8 optflags[64];
@@ -45,6 +41,13 @@ struct loadopt {
     u16 from_file       : 1;
 };
 
+#define LOADOPT_ZERO        { PARSEOPT_ZERO, STRALLOC_ZERO, 0, { 0 }, 0, 0, 0, 0 }
+
+#define LO_ARG(ctx)         (ctx)->po.arg
+#define LO_IDX(ctx)         (ctx)->po.idx
+#define LO_CUR(ctx)         (ctx)->po.cur
+#define LO_FROMFILE(ctx)    (ctx)->from_file
+
 extern int loadopt(int argc, const char **argv, const struct option *options,
                    const char *file, const char *section, unsigned int poflags,
                    struct loadopt *ctx);
diff --git a/src/liblimb/loadopt.h/loadopt.c b/src/liblimb/loadopt.h/loadopt.c
index a2c1818..b14af80 100644
--- a/src/liblimb/loadopt.h/loadopt.c
+++ b/src/liblimb/loadopt.h/loadopt.c
@@ -44,10 +44,10 @@ loadopt(int argc, const char **argv, const struct option *options,
     /* init is done, parse options from command line */
     if (ctx->state == STATE_INIT) {
         int c;
-        c = parseopt(argc, argv, options, poflags, (struct parseopt *) ctx);
+        c = parseopt(argc, argv, options, poflags, &ctx->po);
 
         if (c > 0)
-            add_optflags(ctx->optflags, ctx->idx, OPT_SET);
+            add_optflags(ctx->optflags, ctx->po.idx, OPT_SET);
 
         if (c)
             return c;
@@ -168,8 +168,8 @@ nextfileopt:
 
             if (c) {
                 /* adjust returned value */
-                ctx->arg = po.arg;
-                ctx->idx = po.idx;
+                ctx->po.arg = po.arg;
+                ctx->po.idx = po.idx;
                 ctx->from_file = 1;
                 return c;
             }
@@ -190,40 +190,40 @@ nextfileopt:
             }
         }
         /* re-use off as the current argument's index from w/in options */
-        ctx->off = i;
+        ctx->po.off = i;
         /* set arg as the first argument */
-        ctx->arg = (const char *) (uintptr_t) ctx->cur;
+        ctx->po.arg = (const char *) (uintptr_t) ctx->po.cur;
         ctx->state = STATE_OPTIONS;
     }
 
     /* options done, on to arguments */
     if (ctx->state == STATE_OPTIONS) {
         while (ctx->state == STATE_OPTIONS) {
-            const struct option *arg = &options[ctx->off];
+            const struct option *arg = &options[ctx->po.off];
             if (arg->flags & OPT_DONE) {
-                if (arg->arg == ARG_NONE && ctx->cur < argc) {
+                if (arg->arg == ARG_NONE && ctx->po.cur < argc) {
                     warn("too many arguments");
                     return (errno = ETOOMANYREFS, -1);
                 } else if (arg->arg == ARG_REQ) {
-                    ++ctx->off;
+                    ++ctx->po.off;
                     continue;
                 }
                 /* ARG_NONE w/out args, or ARG_OPT; i.e. ok we're done */
                 break;
             }
 
-            if (arg->arg == ARG_REQ && ctx->cur == argc) {
+            if (arg->arg == ARG_REQ && ctx->po.cur == argc) {
                 warn("argument ", ESC, arg->longopt, ESC," missing");
                 return (errno = ENODATA, -1);
             }
 
             /* next argument from command line */
-            ++ctx->cur;
+            ++ctx->po.cur;
             /* next argument defined/to check for */
-            ++ctx->off;
+            ++ctx->po.off;
         }
         /* set cur to the first argument */
-        ctx->cur = (uintptr_t) ctx->arg & 0xffff;
+        ctx->po.cur = (uintptr_t) ctx->po.arg & 0xffff;
         /* done */
         ctx->state = STATE_ARGS;
     }
diff --git a/src/liblimb/loadopt.h/loadopt_auto_noconfig.c b/src/liblimb/loadopt.h/loadopt_auto_noconfig.c
index 46f85fb..ace8cee 100644
--- a/src/liblimb/loadopt.h/loadopt_auto_noconfig.c
+++ b/src/liblimb/loadopt.h/loadopt_auto_noconfig.c
@@ -10,12 +10,12 @@
 int
 loadopt_auto_noconfig(int idx, const struct option *options, struct loadopt *ctx)
 {
-    if (!ctx->arg) {
+    if (!ctx->po.arg) {
         for (int i = 0; options[i].longopt; ++i)
             if (!(get_optflags(ctx->optflags, i) & OPT_SET))
                 add_optflags(ctx->optflags, i, OPT_SKIP);
     } else {
-        for (char *s = strtok((char *) ctx->arg, ","); s; s = strtok(NULL, ",")) {
+        for (char *s = strtok((char *) ctx->po.arg, ","); s; s = strtok(NULL, ",")) {
             size_t l= strlen(s);
             int first = -1, i;
             i = byte_get_match_full(&first, s, l, options,
@@ -23,7 +23,7 @@ loadopt_auto_noconfig(int idx, const struct option *options, struct loadopt *ctx
             if (i < 0) {
                 char buf[2] = { options[idx].shortopt, 0 };
                 warn("invalid argument to option --", options[idx].longopt,
-                     (*buf) ? "/-" : "", buf, ": ", ctx->arg);
+                     (*buf) ? "/-" : "", buf, ": ", ctx->po.arg);
                 if (first >= 0)
                     list_matches_full(err_putmsg, OLVL_NORMAL, "did you mean ",
                                       "--", " or ", " ?", s, l, first, options,