summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2022-12-31 15:02:08 +0000
committerMichael Drake <mdrake.unique@gmail.com>2023-01-01 18:02:44 +0000
commitd63e9e479c63f8f0a1579ea58205862047297f1a (patch)
treeef4005c1be13a49b9e4dea906ecd0f7a6172eb7e
parentca8b9c3784f1f0f074cff1e5474d4a16b80885c6 (diff)
downloadlibnsgif-d63e9e479c63f8f0a1579ea58205862047297f1a.tar.gz
cli: Allow arguments that disable positional argument requirement
-rw-r--r--test/cli.c39
-rw-r--r--test/cli.h3
2 files changed, 31 insertions, 11 deletions
diff --git a/test/cli.c b/test/cli.c
index 031cd97..e1d1a8b 100644
--- a/test/cli.c
+++ b/test/cli.c
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
- * Copyright (C) 2021 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright (C) 2021-2022 Michael Drake <tlsa@netsurf-browser.org>
*/
/**
@@ -18,6 +18,14 @@
#include "cli.h"
/**
+ * CLI parsing context.
+ */
+struct cli_ctx {
+ const struct cli_table *cli; /**< Client CLI spec. */
+ bool no_pos; /**< Have an argument that negates min_positional. */
+};
+
+/**
* Check whether a CLI argument type should have a numerical value.
*
* \param[in] type An argument type.
@@ -289,13 +297,13 @@ static bool cli__handle_arg_value(const struct cli_table_entry *entry,
/**
* Parse a flags argument.
*
- * \param[in] cli Client command line interface specification.
+ * \param[in] ctx Command line interface parsing context.
* \param[in] argc Number of command line arguments.
* \param[in] argv String vector containing command line arguments.
* \param[out] arg_pos Current position in argv, updated on exit.
* \return true on success, or false otherwise.
*/
-static bool cli__parse_short(const struct cli_table *cli,
+static bool cli__parse_short(struct cli_ctx *ctx,
int argc, const char **argv, int *arg_pos)
{
const char *arg = argv[*arg_pos];
@@ -308,11 +316,15 @@ static bool cli__parse_short(const struct cli_table *cli,
while (arg[pos] != '\0') {
const struct cli_table_entry *entry;
- entry = cli__lookup_short(cli, arg[pos]);
+ entry = cli__lookup_short(ctx->cli, arg[pos]);
if (entry == NULL) {
return false;
}
+ if (entry->no_pos) {
+ ctx->no_pos = true;
+ }
+
if (entry->t == CLI_BOOL) {
*entry->v.b = true;
} else {
@@ -364,13 +376,13 @@ static const struct cli_table_entry *cli__lookup_long(
/**
* Parse a long argument.
*
- * \param[in] cli Client command line interface specification.
+ * \param[in] ctx Command line interface parsing context.
* \param[in] argc Number of command line arguments.
* \param[in] argv String vector containing command line arguments.
* \param[out] arg_pos Current position in argv, updated on exit.
* \return true on success, or false otherwise.
*/
-static bool cli__parse_long(const struct cli_table *cli,
+static bool cli__parse_long(struct cli_ctx *ctx,
int argc, const char **argv, int *arg_pos)
{
const struct cli_table_entry *entry;
@@ -382,11 +394,15 @@ static bool cli__parse_long(const struct cli_table *cli,
return false;
}
- entry = cli__lookup_long(cli, arg, &pos);
+ entry = cli__lookup_long(ctx->cli, arg, &pos);
if (entry == NULL) {
return false;
}
+ if (entry->no_pos) {
+ ctx->no_pos = true;
+ }
+
if (entry->t == CLI_BOOL) {
if (arg[pos] != '\0') {
fprintf(stderr, "Unexpected value for argument '%s'\n",
@@ -567,6 +583,9 @@ static inline bool cli__is_negative(const char *arg)
bool cli_parse(const struct cli_table *cli, int argc, const char **argv)
{
size_t pos_count = 0;
+ struct cli_ctx ctx = {
+ .cli = cli,
+ };
enum {
ARG_PROG_NAME,
ARG_FIRST,
@@ -579,9 +598,9 @@ bool cli_parse(const struct cli_table *cli, int argc, const char **argv)
if (arg[0] == '-') {
if (arg[1] == '-') {
- ret = cli__parse_long(cli, argc, argv, &i);
+ ret = cli__parse_long(&ctx, argc, argv, &i);
} else {
- ret = cli__parse_short(cli, argc, argv, &i);
+ ret = cli__parse_short(&ctx, argc, argv, &i);
if (ret != true) {
if (cli__is_negative(argv[i])) {
pos_inc = 1;
@@ -603,7 +622,7 @@ bool cli_parse(const struct cli_table *cli, int argc, const char **argv)
pos_count += pos_inc;
}
- if (pos_count < cli->min_positional) {
+ if (ctx.no_pos == false && pos_count < cli->min_positional) {
fprintf(stderr, "Insufficient positional arguments found.\n");
return false;
}
diff --git a/test/cli.h b/test/cli.h
index 91db086..ec14d1e 100644
--- a/test/cli.h
+++ b/test/cli.h
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
- * Copyright (C) 2021 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright (C) 2021-2022 Michael Drake <tlsa@netsurf-browser.org>
*/
/**
@@ -51,6 +51,7 @@ struct cli_table_entry {
const char *l; /**< Long argument name. */
const char s; /**< Short flag name. (Non-positional arguments.) */
bool p; /**< Whether the argument is a positional argument. */
+ bool no_pos; /**< When present, no positional arguments are required. */
enum cli_arg_type t; /**< Argument type. */
union {
bool *b; /**< Location to store \ref CLI_BOOL value. */