author | Olivier Brunel
<jjk@jjacky.com> 2023-04-14 12:54:22 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-05-20 18:06:36 UTC |
parent | 09dd44238a5219ba2118e6d31703603dbe23dfbc |
src/doc/loadopt.h/loadopt.3.md | +4 | -5 |
src/doc/parseopt.h.0.md | +1 | -1 |
src/doc/parseopt.h/parseopt.3.md | +6 | -3 |
src/include/parseopt.h | +13 | -0 |
src/liblimb/include/limb/parseopt.h | +1 | -0 |
src/liblimb/loadopt.h/loadopt.c | +5 | -42 |
src/liblimb/parseopt.h/parseopt.c | +14 | -4 |
src/liblimb/parseopt.h/parseopt_warn.c | +41 | -0 |
diff --git a/src/doc/loadopt.h/loadopt.3.md b/src/doc/loadopt.h/loadopt.3.md index 1324e38..3fd2e92 100644 --- a/src/doc/loadopt.h/loadopt.3.md +++ b/src/doc/loadopt.h/loadopt.3.md @@ -131,13 +131,12 @@ If an option was successfully found, `loadopt`() returns the option's `id` if non-zero, else its `shortopt`. When all options, and, optionally, arguments, have been successfully parsed it returns 0. -If an error occurs, a warning is emitted to *stderr* and it returns -1, setting -`errno` to indicate the error. +If an error occurs, `loadopt`() returns -1 and sets `errno` to indicate the +error. ! INFO: -! The warnings are actually written out using one of the [warn](3) family of -! functions. Refer to it for more on how and where data is being written to, or -! how to silence them. +! Warnings may be emitted on error unless *PARSEOPT_SILENT* was set in `flags`. +! Refer to [parseopt](3) for more. # ERRORS diff --git a/src/doc/parseopt.h.0.md b/src/doc/parseopt.h.0.md index 32914c6..4aafe68 100644 --- a/src/doc/parseopt.h.0.md +++ b/src/doc/parseopt.h.0.md @@ -34,7 +34,7 @@ The following constants are defined : : *OPTID_SHORTOPT* :: Special ID for an option, meaning to return its `shortopt` instead. -: *PARSEOPT_IS_LONG*, *PARSEOPT_STRICT* +: *PARSEOPT_IS_LONG*, *PARSEOPT_STRICT*, *PARSEOPT_SILENT* :: Flags that can be passed to [parseopt](3). ## Structures diff --git a/src/doc/parseopt.h/parseopt.3.md b/src/doc/parseopt.h/parseopt.3.md index 76dc32a..d74c579 100644 --- a/src/doc/parseopt.h/parseopt.3.md +++ b/src/doc/parseopt.h/parseopt.3.md @@ -139,6 +139,9 @@ constructed as a bitwise-inclusive OR of flags from the following list : : *PARSEOPT_STRICT* :: Long options can not be abbreviated, and must be exact match. +: *PARSEOPT_SILENT* +:: Do not emit any warnings in case of errors. + : *PARSEOPT_IS_LONG* :: /Intended for internal use./ Assumes all elements of `argv` are option :: elements, composed of long option names directly (i.e. without "--" prefix). @@ -153,9 +156,9 @@ When all command-line options have been parsed it returns 0. If an error occurs, it returns -1 and sets `errno` to indicate the error. ! NOTE: -! Unlike [getopt](3), `parseopt`() will not print any warning/error messages. -! The indication of the error is sent through `errno` and it is up to the -! caller to inform the user of what failed. +! In case of error, `parseopt`() will also write a warning explaining the error +! on *stderr* (done through the [warn](3) family of functions), /unless/ +! *PARSEOPT_SILENT* was specified in its `flags` argument. # ERRORS diff --git a/src/include/parseopt.h b/src/include/parseopt.h new file mode 100644 index 0000000..5e0a058 --- /dev/null +++ b/src/include/parseopt.h @@ -0,0 +1,13 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef LIMB_LIMB_PARSEOPT_H +#define LIMB_LIMB_PARSEOPT_H + +#include <limb/gccattributes.h> +#include <limb/parseopt.h> + +void parseopt_warn(const char **argv, const struct option *options, + const struct parseopt *ctx) gccattr_hidden; + +#endif /* LIMB_LIMB_PARSEOPT_H */ diff --git a/src/liblimb/include/limb/parseopt.h b/src/liblimb/include/limb/parseopt.h index b3f31bf..9dedd93 100644 --- a/src/liblimb/include/limb/parseopt.h +++ b/src/liblimb/include/limb/parseopt.h @@ -39,6 +39,7 @@ enum { PARSEOPT_IS_LONG = 1 << 0, /* public */ PARSEOPT_STRICT = 1 << 1, + PARSEOPT_SILENT = 1 << 2, }; struct parseopt { diff --git a/src/liblimb/loadopt.h/loadopt.c b/src/liblimb/loadopt.h/loadopt.c index 7de2984..a2c1818 100644 --- a/src/liblimb/loadopt.h/loadopt.c +++ b/src/liblimb/loadopt.h/loadopt.c @@ -7,6 +7,7 @@ #include <limb/djbunix.h> #include <limb/loadopt.h> #include <limb/output.h> +#include "parseopt.h" #include "loadopt.h" void @@ -27,43 +28,6 @@ get_optflags(const u8 *optflags, int idx) return b & 0xf; } -static void -parseopt_warn(int c, const char **argv, const struct option *options, - const struct parseopt *ctx) -{ - if (c >= 0) - return; - - switch (errno) { - case EINVAL: - warn("option name missing"); - break; - case ENOENT: - if (!strncmp(argv[ctx->cur], "--", 2)) { - warn("unknown option: ", argv[ctx->cur]); - /* was there a partial match? */ - if (ctx->idx >= 0) { - const char *s = argv[ctx->cur] + ctx->off; - size_t l = byte_chr(s, strlen(s), '='); - list_matches_full(err_putmsg, OLVL_NORMAL, "did you mean ", - "--", " or ", " ?", s, l, ctx->idx, options, - offsetof(struct option, longopt), sizeof(*options)); - } - } else { - char buf[3] = { '-', argv[ctx->cur][ctx->off], 0 }; - warn("unknown option: ", buf); - } - break; - case ENOMSG: - { - char buf[2] = { options[ctx->idx].shortopt, 0 }; - warn("option --", options[ctx->idx].longopt, - (*buf) ? "/-" : "", buf, " requires an argument"); - } - break; - } -} - int loadopt(int argc, const char **argv, const struct option *options, const char *file, const char *section, unsigned int poflags, @@ -84,8 +48,6 @@ loadopt(int argc, const char **argv, const struct option *options, if (c > 0) add_optflags(ctx->optflags, ctx->idx, OPT_SET); - else - parseopt_warn(c, argv, options, (struct parseopt *) ctx); if (c) return c; @@ -186,7 +148,8 @@ nextfileopt: const char *argv[] = { "", ctx->sa.s + ctx->saoff }; errno = 0; - int c = parseopt(2, argv, options, PARSEOPT_IS_LONG | PARSEOPT_STRICT, &po); + int c = parseopt(2, argv, options, PARSEOPT_IS_LONG + | PARSEOPT_STRICT | PARSEOPT_SILENT, &po); /* seek past the line */ ctx->saoff = o + 1; @@ -200,8 +163,8 @@ nextfileopt: if (c > 0) add_optflags(ctx->optflags, po.idx, OPT_SET); - else - parseopt_warn(c, argv, options, &po); + else if (c < 0 && !(poflags & PARSEOPT_SILENT)) + parseopt_warn(argv, options, &po); if (c) { /* adjust returned value */ diff --git a/src/liblimb/parseopt.h/parseopt.c b/src/liblimb/parseopt.h/parseopt.c index 958eb63..668a68f 100644 --- a/src/liblimb/parseopt.h/parseopt.c +++ b/src/liblimb/parseopt.h/parseopt.c @@ -4,11 +4,11 @@ #include <errno.h> #include <stddef.h> /* offsetof() */ #include <limb/bytestr.h> -#include <limb/parseopt.h> +#include "parseopt.h" -int -parseopt(int argc, const char **argv, const struct option *options, - unsigned int flags, struct parseopt *ctx) +static int +do_parseopt(int argc, const char **argv, const struct option *options, + unsigned int flags, struct parseopt *ctx) { const char *arg; int is_long, arg_long; @@ -116,3 +116,13 @@ again: return (options[ctx->idx].id) ? options[ctx->idx].id : options[ctx->idx].shortopt; } + +int +parseopt(int argc, const char **argv, const struct option *options, + unsigned int flags, struct parseopt *ctx) +{ + int r = do_parseopt(argc, argv, options, flags, ctx); + if (r < 0 && !(flags & PARSEOPT_SILENT)) + parseopt_warn(argv, options, ctx); + return r; +} diff --git a/src/liblimb/parseopt.h/parseopt_warn.c b/src/liblimb/parseopt.h/parseopt_warn.c new file mode 100644 index 0000000..891ff38 --- /dev/null +++ b/src/liblimb/parseopt.h/parseopt_warn.c @@ -0,0 +1,41 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <errno.h> +#include <limb/bytestr.h> +#include <limb/output.h> +#include "parseopt.h" + +void +parseopt_warn(const char **argv, const struct option *options, + const struct parseopt *ctx) +{ + switch (errno) { + case EINVAL: + warn("option name missing"); + break; + case ENOENT: + if (!strncmp(argv[ctx->cur], "--", 2)) { + warn("unknown option: ", argv[ctx->cur]); + /* was there a partial match? */ + if (ctx->idx >= 0) { + const char *s = argv[ctx->cur] + ctx->off; + size_t l = byte_chr(s, strlen(s), '='); + list_matches_full(err_putmsg, OLVL_NORMAL, "did you mean ", + "--", " or ", " ?", s, l, ctx->idx, options, + offsetof(struct option, longopt), sizeof(*options)); + } + } else { + char buf[3] = { '-', argv[ctx->cur][ctx->off], 0 }; + warn("unknown option: ", buf); + } + break; + case ENOMSG: + { + char buf[2] = { options[ctx->idx].shortopt, 0 }; + warn("option --", options[ctx->idx].longopt, + (*buf) ? "/-" : "", buf, " requires an argument"); + } + break; + } +}