+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.
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.
__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;
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)'. */
-/* 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. */
((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. */
} \
} 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);