[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] argmatch: add variants that only match full argument
From: |
Pádraig Brady |
Subject: |
[PATCH] argmatch: add variants that only match full argument |
Date: |
Sun, 30 Jan 2022 17:11:16 +0000 |
* lib/argmatch.h (argmatch_exact, [X]ARGMATCH_EXACT): New interfaces
that don't support abbreviations.
* lib/argmatch.c (argmatch_exact, __xargmatch_exact_internal): Likewise.
* tests/test-argmatch.c: Add tests.
---
ChangeLog | 8 ++++++++
lib/argmatch.c | 37 +++++++++++++++++++++++++++++++++++++
lib/argmatch.h | 17 +++++++++++++++++
tests/test-argmatch.c | 23 +++++++++++++++++++++++
4 files changed, 85 insertions(+)
diff --git a/ChangeLog b/ChangeLog
index 4c9a1e7989..e51a00190a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2022-01-30 Pádraig Brady <P@draigBrady.com>
+
+ argmatch: add variants that only match full argument
+ * lib/argmatch.h (argmatch_exact, [X]ARGMATCH_EXACT): New interfaces
+ that don't support abbreviations.
+ * lib/argmatch.c (argmatch_exact, __xargmatch_exact_internal): Likewise.
+ * tests/test-argmatch.c: Add tests.
+
2022-01-30 Bruno Haible <bruno@clisp.org>
terminfo: Add tests.
diff --git a/lib/argmatch.c b/lib/argmatch.c
index 9e3232f947..71059e8f7e 100644
--- a/lib/argmatch.c
+++ b/lib/argmatch.c
@@ -120,6 +120,24 @@ argmatch (const char *arg, const char *const *arglist,
return matchind;
}
+ptrdiff_t
+argmatch_exact (const char *arg, const char *const *arglist)
+{
+ size_t i;
+
+ /* Test elements for exact match. */
+ for (i = 0; arglist[i]; i++)
+ {
+ if (!strcmp (arglist[i], arg))
+ {
+ /* Exact match found. */
+ return i;
+ }
+ }
+
+ return -1;
+}
+
/* Error reporting for argmatch.
CONTEXT is a description of the type of entity that was being matched.
VALUE is the invalid value that was given.
@@ -189,6 +207,25 @@ __xargmatch_internal (const char *context,
return -1; /* To please the compilers. */
}
+ptrdiff_t
+__xargmatch_exact_internal (const char *context,
+ const char *arg, const char *const *arglist,
+ const void *vallist, size_t valsize,
+ argmatch_exit_fn exit_fn)
+{
+ ptrdiff_t res = argmatch_exact (arg, arglist);
+ if (res >= 0)
+ /* Success. */
+ return res;
+
+ /* We failed. Explain why. */
+ argmatch_invalid (context, arg, res);
+ argmatch_valid (arglist, vallist, valsize);
+ (*exit_fn) ();
+
+ return -1; /* To please the compilers. */
+}
+
/* Look for VALUE in VALLIST, an array of objects of size VALSIZE and
return the first corresponding argument in ARGLIST */
const char *
diff --git a/lib/argmatch.h b/lib/argmatch.h
index a2364b5a2e..c6d24d981c 100644
--- a/lib/argmatch.h
+++ b/lib/argmatch.h
@@ -52,9 +52,15 @@ extern "C" {
ptrdiff_t argmatch (char const *arg, char const *const *arglist,
void const *vallist, size_t valsize) _GL_ATTRIBUTE_PURE;
+ptrdiff_t argmatch_exact (char const *arg, char const *const *arglist)
+ _GL_ATTRIBUTE_PURE;
+
# define ARGMATCH(Arg, Arglist, Vallist) \
argmatch (Arg, Arglist, (void const *) (Vallist), sizeof *(Vallist))
+# define ARGMATCH_EXACT(Arg, Arglist) \
+ argmatch_exact (Arg, Arglist)
+
/* xargmatch calls this function when it fails. This function should not
return. By default, this is a function that calls ARGMATCH_DIE which
in turn defaults to 'exit (exit_failure)'. */
@@ -91,6 +97,11 @@ ptrdiff_t __xargmatch_internal (char const *context,
void const *vallist, size_t valsize,
argmatch_exit_fn exit_fn);
+ptrdiff_t __xargmatch_exact_internal (char const *context,
+ char const *arg, char const *const *arglist,
+ void const *vallist, size_t valsize,
+ argmatch_exit_fn exit_fn);
+
/* Programmer friendly interface to __xargmatch_internal. */
# define XARGMATCH(Context, Arg, Arglist, Vallist) \
@@ -99,6 +110,12 @@ ptrdiff_t __xargmatch_internal (char const *context,
sizeof *(Vallist), \
argmatch_die)])
+# define XARGMATCH_EXACT(Context, Arg, Arglist, Vallist) \
+ ((Vallist) [__xargmatch_exact_internal (Context, Arg, Arglist,\
+ (void const *) (Vallist), \
+ sizeof *(Vallist), \
+ argmatch_die)])
+
/* Convert a value into a corresponding argument. */
char const *argmatch_to_argument (void const *value,
diff --git a/tests/test-argmatch.c b/tests/test-argmatch.c
index 8345150002..46a7f07153 100644
--- a/tests/test-argmatch.c
+++ b/tests/test-argmatch.c
@@ -125,37 +125,60 @@ main (int argc, char *argv[])
} \
} while (0)
+#define CHECK_EXACT(Input, Output) \
+ do { \
+ ASSERT (ARGMATCH_EXACT (Input, backup_args) == Output); \
+ } while (0)
+
/* Not found. */
CHECK ("klingon", -1);
+ CHECK_EXACT ("klingon", -1);
/* Exact match. */
CHECK ("none", 1);
+ CHECK_EXACT ("none", 1);
CHECK ("nil", 7);
+ CHECK_EXACT ("nil", 7);
/* Too long. */
CHECK ("nilpotent", -1);
+ CHECK_EXACT ("nilpotent", -1);
/* Abbreviated. */
CHECK ("simpl", 3);
+ CHECK_EXACT ("simpl", -1);
CHECK ("simp", 3);
+ CHECK_EXACT ("simp", -1);
CHECK ("sim", 3);
+ CHECK_EXACT ("sim", -1);
/* Exact match and abbreviated. */
CHECK ("numbered", 9);
+ CHECK_EXACT ("numbered", 9);
CHECK ("numbere", -2);
+ CHECK_EXACT ("numbere", -1);
CHECK ("number", -2);
+ CHECK_EXACT ("number", -1);
CHECK ("numbe", -2);
+ CHECK_EXACT ("numbe", -1);
CHECK ("numb", -2);
+ CHECK_EXACT ("numb", -1);
CHECK ("num", -2);
+ CHECK_EXACT ("num", -1);
CHECK ("nu", -2);
+ CHECK_EXACT ("nu", -1);
CHECK ("n", -2);
+ CHECK_EXACT ("n", -1);
/* Ambiguous abbreviated. */
CHECK ("ne", -2);
+ CHECK_EXACT ("ne", -1);
/* Ambiguous abbreviated, but same value ("single" and "simple"). */
CHECK ("si", 3);
+ CHECK_EXACT ("si", -1);
CHECK ("s", 3);
+ CHECK_EXACT ("s", -1);
#undef CHECK
argmatch_backup_usage (stdout);
--
2.26.2