]> Savannah Git Hosting - gnulib.git/commitdiff
argmatch: add variants that only match full argument
authorPádraig Brady <P@draigBrady.com>
Sun, 30 Jan 2022 16:50:27 +0000 (16:50 +0000)
committerPádraig Brady <P@draigBrady.com>
Sun, 30 Jan 2022 20:11:58 +0000 (20:11 +0000)
* lib/argmatch.h (argmatch_exact, [X]ARGMATCH_EXACT): New interfaces
that don't allow abbreviations.
* lib/argmatch.c (argmatch_exact): Likewise.
(__xargmatch_internal): Add a bool parameter to disable abbreviations.
* tests/test-argmatch.c: Add tests.

ChangeLog
lib/argmatch.c
lib/argmatch.h
tests/test-argmatch.c

index fedc7dc77733c6c039817fc5afa6a0ac3602083e..a202950bd94469fefb0c15dc4384f337f0f946b6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+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 allow abbreviations.
+       * lib/argmatch.c (argmatch_exact): Likewise.
+       (__xargmatch_internal): Add a bool parameter to disable abbreviations.
+       * tests/test-argmatch.c: Add tests.
+
 2022-01-30  Bruno Haible  <bruno@clisp.org>
 
        tests: Fix interpretation of setupterm's return code.
index 9e3232f9472d292c2b998d561ab102b342dbf9b0..2a28900a4e5cc40cb8dc57a0df824ce177e7a890 100644 (file)
@@ -120,6 +120,21 @@ 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))
+        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.
@@ -174,9 +189,16 @@ ptrdiff_t
 __xargmatch_internal (const char *context,
                       const char *arg, const char *const *arglist,
                       const void *vallist, size_t valsize,
-                      argmatch_exit_fn exit_fn)
+                      argmatch_exit_fn exit_fn,
+                      bool allow_abbreviation)
 {
-  ptrdiff_t res = argmatch (arg, arglist, vallist, valsize);
+  ptrdiff_t res;
+
+  if (allow_abbreviation)
+    res = argmatch (arg, arglist, vallist, valsize);
+  else
+    res = argmatch_exact (arg, arglist);
+
   if (res >= 0)
     /* Success. */
     return res;
index a2364b5a2e17ff6ec302c8a5d1655da04a852efc..52f2bb727be9fd0bf416ec49988fadc16107aa12 100644 (file)
@@ -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)'.  */
@@ -83,13 +89,14 @@ void argmatch_valid (char const *const *arglist,
 
 
 
-/* Same as argmatch, but upon failure, report an explanation of the
-   failure, and exit using the function EXIT_FN. */
+/* Like argmatch/argmatch_exact, but upon failure, report an explanation
+   of the failure, and exit using the function EXIT_FN. */
 
 ptrdiff_t __xargmatch_internal (char const *context,
                                 char const *arg, char const *const *arglist,
                                 void const *vallist, size_t valsize,
-                                argmatch_exit_fn exit_fn);
+                                argmatch_exit_fn exit_fn,
+                                bool allow_abbreviation);
 
 /* Programmer friendly interface to __xargmatch_internal. */
 
@@ -97,7 +104,15 @@ ptrdiff_t __xargmatch_internal (char const *context,
   ((Vallist) [__xargmatch_internal (Context, Arg, Arglist,      \
                                     (void const *) (Vallist),   \
                                     sizeof *(Vallist),          \
-                                    argmatch_die)])
+                                    argmatch_die,               \
+                                    true)])
+
+# define XARGMATCH_EXACT(Context, Arg, Arglist, Vallist)        \
+  ((Vallist) [__xargmatch_internal (Context, Arg, Arglist,      \
+                                    (void const *) (Vallist),   \
+                                    sizeof *(Vallist),          \
+                                    argmatch_die,               \
+                                    false)])
 
 /* Convert a value into a corresponding argument. */
 
index 8345150002c0136a3f449e3581edc76fd8f2bab4..b05e43126699bf66602640bb5ff984da3ecf1eba 100644 (file)
@@ -125,38 +125,63 @@ 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
+#undef CHECK_EXACT
 
   argmatch_backup_usage (stdout);