about summary refs log tree commit diff
path: root/posix/fnmatch_loop.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-07-04 23:27:39 +0000
committerUlrich Drepper <drepper@redhat.com>2000-07-04 23:27:39 +0000
commitecce00a971d2725175c4dc200e6b2c122363d810 (patch)
tree17d321ebc97681ad0bcd356433add82bfc76f55e /posix/fnmatch_loop.c
parent7239b3a4cfa50ecd088850d13202aeff5cf96e5f (diff)
downloadglibc-ecce00a971d2725175c4dc200e6b2c122363d810.tar.gz
glibc-ecce00a971d2725175c4dc200e6b2c122363d810.tar.xz
glibc-ecce00a971d2725175c4dc200e6b2c122363d810.zip
Update.
	* posix/fnmatch_loop.c: Implement equivalence class handling.
	* posix/tst-fnmatch.input: Add tests for equivalence class
	handling.
Diffstat (limited to 'posix/fnmatch_loop.c')
-rw-r--r--posix/fnmatch_loop.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c
index ad729d2d8f..8b163be24f 100644
--- a/posix/fnmatch_loop.c
+++ b/posix/fnmatch_loop.c
@@ -302,6 +302,112 @@ FCT (pattern, string, no_leading_period, flags)
 #endif
 		    c = *p++;
 		  }
+#ifdef _LIBC
+		else if (c == L('[') && *p == L('='))
+		  {
+		    UCHAR str[1];
+		    uint32_t nrules =
+		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+		    const CHAR *startp = p;
+
+		    c = *++p;
+		    if (c == L('\0'))
+		      {
+			p = startp;
+			c = L('[');
+			goto normal_bracket;
+		      }
+		    str[0] = c;
+
+		    c = *++p;
+		    if (c != L('=') || p[1] != L(']'))
+		      {
+			p = startp;
+			c = L('[');
+			goto normal_bracket;
+		      }
+		    p += 2;
+
+		    if (nrules == 0)
+		      {
+			if ((UCHAR) *n == str[0])
+			  goto matched;
+		      }
+		    else
+		      {
+			const int32_t *table;
+# if WIDE_CHAR_VERSION
+			const int32_t *weights;
+			const int32_t *extra;
+# else
+			const unsigned char *weights;
+			const unsigned char *extra;
+# endif
+			const int32_t *indirect;
+			int32_t idx;
+			const UCHAR *cp = (const UCHAR *) str;
+
+			/* This #include defines a local function!  */
+# if WIDE_CHAR_VERSION
+#  include <locale/weightwc.h>
+# else
+#  include <locale/weight.h>
+# endif
+
+# if WIDE_CHAR_VERSION
+			table = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
+			weights = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
+			extra = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
+			indirect = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
+# else
+			table = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+			weights = (const unsigned char *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+			extra = (const unsigned char *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+			indirect = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+# endif
+
+			idx = findidx (&cp);
+			if (idx != 0)
+			  {
+			    /* We found a table entry.  Now see whether the
+			       character we are currently at has the same
+			       equivalance class value.  */
+			    int len = weights[idx];
+			    int32_t idx2;
+			    const UCHAR *np = (const UCHAR *) n;
+
+			    idx2 = findidx (&np);
+# if !WIDE_CHAR_VERSION
+			    if (idx2 != 0 && len == weights[idx2])
+			      {
+				int cnt = 0;
+
+				while (cnt < len
+				       && (weights[idx + 1 + cnt]
+					   == weights[idx2 + 1 + cnt]))
+				  ++cnt;
+
+				if (cnt == len)
+				  goto matched;
+			      }
+# else
+			    if (idx2 != 0 && weights[idx] == weights[idx2])
+			      goto matched;
+# endif
+			  }
+		      }
+
+		    c = *p++;
+		  }
+#endif
 		else if (c == L('\0'))
 		  /* [ (unterminated) loses.  */
 		  return FNM_NOMATCH;