author | Olivier Brunel
<jjk@jjacky.com> 2023-04-22 07:22:21 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-05-20 18:06:37 UTC |
parent | 6923aeb465b4b61db6d62945964ee1b7ca8eada5 |
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,