bug-gnulib
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]