summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2022-06-03 17:27:44 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2022-06-03 17:30:39 -0700
commit1ba2b66ea45f9bc43cdc0f6f93efa59157d2b2ba (patch)
tree9a040418bd7f1291fc0202a516421313991bc5a5
parentff24917703530849f3b109905d437337cdeeab14 (diff)
downloadgnulib-1ba2b66ea45f9bc43cdc0f6f93efa59157d2b2ba.tar.gz
filevercmp: don’t treat entire filename as suffix
Problem reported by Artém S. Tashkinóv in: https://lists.gnu.org/r/bug-gnulib/2022-06/msg00012.html * lib/filevercmp.c (file_prefixlen): When stripping (\.[A-Za-z~][A-Za-z0-9~]*)*$ suffixes, do not strip the entire file name. * tests/test-filevercmp.c (examples): Adjust to match new behavior.
-rw-r--r--ChangeLog10
-rw-r--r--lib/filevercmp.c18
-rw-r--r--lib/filevercmp.h4
-rw-r--r--tests/test-filevercmp.c4
4 files changed, 26 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 4449ff14f9..95d1314cdc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2022-06-03 Paul Eggert <eggert@cs.ucla.edu>
+
+ filevercmp: don’t treat entire filename as suffix
+ Problem reported by Artém S. Tashkinóv in:
+ https://lists.gnu.org/r/bug-gnulib/2022-06/msg00012.html
+ * lib/filevercmp.c (file_prefixlen): When stripping
+ (\.[A-Za-z~][A-Za-z0-9~]*)*$ suffixes, do not strip
+ the entire file name.
+ * tests/test-filevercmp.c (examples): Adjust to match new behavior.
+
2022-06-03 Bruno Haible <bruno@clisp.org>
setlocale: Update after Turkey changed its name.
diff --git a/lib/filevercmp.c b/lib/filevercmp.c
index d546e79054..7e54793e61 100644
--- a/lib/filevercmp.c
+++ b/lib/filevercmp.c
@@ -29,6 +29,8 @@
/* Return the length of a prefix of S that corresponds to the suffix
defined by this extended regular expression in the C locale:
(\.[A-Za-z~][A-Za-z0-9~]*)*$
+ Use the longest suffix matching this regular expression,
+ except do not use all of S as a suffix if S is nonempty.
If *LEN is -1, S is a string; set *LEN to S's length.
Otherwise, *LEN should be nonnegative, S is a char array,
and *LEN does not change. */
@@ -36,20 +38,22 @@ static idx_t
file_prefixlen (char const *s, ptrdiff_t *len)
{
size_t n = *len; /* SIZE_MAX if N == -1. */
+ idx_t prefixlen = 0;
- for (idx_t i = 0; ; i++)
+ for (idx_t i = 0; ; )
{
- idx_t prefixlen = i;
- while (i + 1 < n && s[i] == '.' && (c_isalpha (s[i + 1])
- || s[i + 1] == '~'))
- for (i += 2; i < n && (c_isalnum (s[i]) || s[i] == '~'); i++)
- continue;
-
if (*len < 0 ? !s[i] : i == n)
{
*len = i;
return prefixlen;
}
+
+ i++;
+ prefixlen = i;
+ while (i + 1 < n && s[i] == '.' && (c_isalpha (s[i + 1])
+ || s[i + 1] == '~'))
+ for (i += 2; i < n && (c_isalnum (s[i]) || s[i] == '~'); i++)
+ continue;
}
}
diff --git a/lib/filevercmp.h b/lib/filevercmp.h
index 5a33677671..57949760b2 100644
--- a/lib/filevercmp.h
+++ b/lib/filevercmp.h
@@ -61,7 +61,9 @@
without them, using version sort without special priority;
if they do not compare equal, this comparison result is used and
the suffixes are effectively ignored. Otherwise, the entire
- strings are compared using version sort.
+ strings are compared using version sort. When removing a suffix
+ from a nonempty string, remove the maximal-length suffix such that
+ the remaining string is nonempty.
This function is intended to be a replacement for strverscmp. */
int filevercmp (char const *a, char const *b) _GL_ATTRIBUTE_PURE;
diff --git a/tests/test-filevercmp.c b/tests/test-filevercmp.c
index b2a7e90f3f..998250990d 100644
--- a/tests/test-filevercmp.c
+++ b/tests/test-filevercmp.c
@@ -29,6 +29,8 @@ static const char *const examples[] =
"",
".",
"..",
+ ".0",
+ ".9",
".A",
".Z",
".a~",
@@ -39,8 +41,6 @@ static const char *const examples[] =
".zz~",
".zz",
".zz.~1~",
- ".0",
- ".9",
".zz.0",
".\1",
".\1.txt",