summaryrefslogtreecommitdiff
path: root/lib/glob
diff options
context:
space:
mode:
Diffstat (limited to 'lib/glob')
-rw-r--r--lib/glob/sm_loop.c11
-rw-r--r--lib/glob/smatch.c70
2 files changed, 78 insertions, 3 deletions
diff --git a/lib/glob/sm_loop.c b/lib/glob/sm_loop.c
index 2de5acd3..cc14fb16 100644
--- a/lib/glob/sm_loop.c
+++ b/lib/glob/sm_loop.c
@@ -384,7 +384,7 @@ BRACKMATCH (p, test, flags)
{
register CHAR cstart, cend, c;
register int not; /* Nonzero if the sense of the character class is inverted. */
- int brcnt, brchr, forcecoll;
+ int brcnt, brchr, forcecoll, isrange;
INT pc;
CHAR *savep;
U_CHAR orig_test;
@@ -519,6 +519,7 @@ BRACKMATCH (p, test, flags)
}
cstart = cend = FOLD (cstart);
+ isrange = 0;
/* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
is not preceded by a backslash and is not part of a bracket
@@ -573,10 +574,18 @@ BRACKMATCH (p, test, flags)
c = FOLD (c);
continue;
}
+ isrange = 1;
}
+#if 0 /* TAG: bash-5.1 */
+ if (isrange == 0 && test == cstart)
+ goto matched;
+ if (isrange && RANGECMP (test, cstart, forcecoll) >= 0 && RANGECMP (test, cend, forcecoll) <= 0)
+ goto matched;
+#else
if (RANGECMP (test, cstart, forcecoll) >= 0 && RANGECMP (test, cend, forcecoll) <= 0)
goto matched;
+#endif
if (c == L(']'))
break;
diff --git a/lib/glob/smatch.c b/lib/glob/smatch.c
index 025fe4fc..64fdbbb7 100644
--- a/lib/glob/smatch.c
+++ b/lib/glob/smatch.c
@@ -30,6 +30,12 @@
#include "shmbutil.h"
#include "xmalloc.h"
+#include <errno.h>
+
+#if !defined (errno)
+extern int errno;
+#endif
+
/* First, compile `sm_loop.c' for single-byte characters. */
#define CHAR unsigned char
#define U_CHAR unsigned char
@@ -82,7 +88,7 @@ rangecmp (c1, c2, forcecoll)
if ((ret = strcoll (s1, s2)) != 0)
return ret;
- return (c1 - c2);
+ return (c1 - c2); /* impose total ordering */
}
#else /* !HAVE_STRCOLL */
# define rangecmp(c1, c2, f) ((int)(c1) - (int)(c2))
@@ -282,6 +288,41 @@ is_cclass (c, name)
extern char *mbsmbchar __P((const char *));
+#if FNMATCH_EQUIV_FALLBACK
+/* We don't include <fnmatch.h> in order to avoid namespace collisions; the
+ internal strmatch still uses the FNM_ constants. */
+extern int fnmatch (const char *, const char *, int);
+
+/* Construct a string w1 = "c1" and a pattern w2 = "[[=c2=]]" and pass them
+ to fnmatch to see if wide characters c1 and c2 collate as members of the
+ same equivalence class. We can't really do this portably any other way */
+static int
+_fnmatch_fallback_wc (c1, c2)
+ wchar_t c1, c2; /* string char, patchar */
+{
+ char w1[MB_LEN_MAX+1]; /* string */
+ char w2[MB_LEN_MAX+8]; /* constructed pattern */
+ int l1, l2;
+
+ l1 = wctomb (w1, c1);
+ if (l1 == -1)
+ return (2);
+ w1[l1] = '\0';
+
+ /* reconstruct the pattern */
+ w2[0] = w2[1] = '[';
+ w2[2] = '=';
+ l2 = wctomb (w2+3, c2);
+ if (l2 == -1)
+ return (2);
+ w2[l2+3] = '=';
+ w2[l2+4] = w2[l2+5] = ']';
+ w2[l2+6] = '\0';
+
+ return (fnmatch ((const char *)w2, (const char *)w1, 0));
+}
+#endif
+
static int
rangecmp_wc (c1, c2, forcecoll)
wint_t c1, c2;
@@ -289,6 +330,7 @@ rangecmp_wc (c1, c2, forcecoll)
{
static wchar_t s1[2] = { L' ', L'\0' };
static wchar_t s2[2] = { L' ', L'\0' };
+ int r, oerrno;
if (c1 == c2)
return 0;
@@ -299,14 +341,38 @@ rangecmp_wc (c1, c2, forcecoll)
s1[0] = c1;
s2[0] = c2;
+#if 0 /* TAG:bash-5.1 */
+ /* We impose a total ordering here by returning c1-c2 if wcscoll returns 0,
+ as we do above in the single-byte case. If we do this, we can no longer
+ use this code in collequiv_wc */
+ if ((r = wcscoll (s1, s2)) != 0)
+ return r;
+ return ((int)(c1 - c2)); /* impose total ordering */
+#else
return (wcscoll (s1, s2));
+#endif
}
+/* Returns non-zero on success */
static int
collequiv_wc (c, equiv)
wint_t c, equiv;
{
- return (c == equiv);
+ wchar_t s, p;
+
+ if (rangecmp_wc (c, equiv, 1) == 0)
+ return 1;
+#if FNMATCH_EQUIV_FALLBACK
+/* We check explicitly for success (fnmatch returns 0) to avoid problems if
+ our local definition of FNM_NOMATCH (strmatch.h) doesn't match the
+ system's (fnmatch.h). We don't care about error return values here. */
+
+ s = c;
+ p = equiv;
+ return (_fnmatch_fallback_wc (s, p) == 0);
+#else
+ return 0;
+#endif
}
/* Helper function for collating symbol. */