* 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
+
+ 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
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