summaryrefslogtreecommitdiff
path: root/posix
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-07-04 08:22:44 +0000
committerUlrich Drepper <drepper@redhat.com>2000-07-04 08:22:44 +0000
commit83b1b6d8faca6d279867c1c76f75e89786b76f4f (patch)
treed76728853dc9f8d2852e035c865e5e9732d65c81 /posix
parent0d6af3a86d34a5b32c46353fdc863216c1a44baf (diff)
Update.
2000-07-04 Ulrich Drepper <drepper@redhat.com> * spinlock.c (__pthread_unlock): Properly place write barrier. Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
Diffstat (limited to 'posix')
-rw-r--r--posix/fnmatch_loop.c9
-rw-r--r--posix/tst-fnmatch.c374
-rw-r--r--posix/tst-fnmatch.input286
3 files changed, 666 insertions, 3 deletions
diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c
index 831bd0631a..3a6dffb1e4 100644
--- a/posix/fnmatch_loop.c
+++ b/posix/fnmatch_loop.c
@@ -176,8 +176,8 @@ FCT (pattern, string, no_leading_period, flags)
case L('['):
{
- /* Nonzero if the sense of the character class is inverted. */
static int posixly_correct;
+ /* Nonzero if the sense of the character class is inverted. */
register int not;
CHAR cold;
@@ -273,6 +273,7 @@ FCT (pattern, string, no_leading_period, flags)
|| (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n)))
goto matched;
#endif
+ c = *p++;
}
else if (c == L('\0'))
/* [ (unterminated) loses. */
@@ -415,13 +416,14 @@ FCT (pattern, string, no_leading_period, flags)
matched:
/* Skip the rest of the [...] that already matched. */
- while (c != L(']'))
+ do
{
+ c = *p++;
+
if (c == L('\0'))
/* [... (unterminated) loses. */
return FNM_NOMATCH;
- c = *p++;
if (!(flags & FNM_NOESCAPE) && c == L('\\'))
{
if (*p == L('\0'))
@@ -439,6 +441,7 @@ FCT (pattern, string, no_leading_period, flags)
c = *p;
}
}
+ while (c != L(']'));
if (not)
return FNM_NOMATCH;
}
diff --git a/posix/tst-fnmatch.c b/posix/tst-fnmatch.c
new file mode 100644
index 0000000000..b582a51889
--- /dev/null
+++ b/posix/tst-fnmatch.c
@@ -0,0 +1,374 @@
+/* Tests for fnmatch function.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <error.h>
+#include <fnmatch.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+
+static char *next_input (char **line, int first, int last);
+static int convert_flags (const char *str);
+static char *flag_output (int flags);
+static char *escape (const char *str, size_t *reslenp, char **resbuf);
+
+
+int
+main (void)
+{
+ char *linebuf = NULL;
+ size_t linebuflen = 0;
+ int ntests = 0;
+ int nfailed = 0;
+ char *escinput = NULL;
+ size_t escinputlen = 0;
+ char *escpattern = NULL;
+ size_t escpatternlen = 0;
+ int nr = 0;
+
+ /* Read lines from stdin with the following format:
+
+ locale input-string match-string flags result
+
+ where `result' is either 0 or 1. If the first character of a
+ string is '"' we read until the next '"' and handled escaped '"'. */
+ while (! feof (stdin))
+ {
+ ssize_t n = getline (&linebuf, &linebuflen, stdin);
+ char *cp;
+ const char *locale;
+ const char *input;
+ const char *pattern;
+ const char *result_str;
+ int result;
+ const char *flags;
+ int flags_val;
+ int fnmres;
+ char numbuf[24];
+
+ if (n == -1)
+ break;
+
+ if (n == 0)
+ /* Maybe an empty line. */
+ continue;
+
+ /* Skip over all leading white spaces. */
+ cp = linebuf;
+
+ locale = next_input (&cp, 1, 0);
+ if (locale == NULL)
+ continue;
+
+ input = next_input (&cp, 0, 0);
+ if (input == NULL)
+ continue;
+
+ pattern = next_input (&cp, 0, 0);
+ if (pattern == NULL)
+ continue;
+
+ result_str = next_input (&cp, 0, 0);
+ if (result_str == NULL)
+ continue;
+
+ if (strcmp (result_str, "0") == 0)
+ result = 0;
+ else if (strcasecmp (result_str, "NOMATCH") == 0)
+ result = FNM_NOMATCH;
+ else
+ {
+ char *endp;
+ result = strtol (result_str, &endp, 0);
+ if (*endp != '\0')
+ continue;
+ }
+
+ flags = next_input (&cp, 0, 1);
+ if (flags == NULL)
+ /* We allow the flags missing. */
+ flags = "";
+
+ /* Convert the text describing the flags in a numeric value. */
+ flags_val = convert_flags (flags);
+ if (flags_val == -1)
+ /* Something went wrong. */
+ continue;
+
+ /* Now run the actual test. */
+ ++ntests;
+
+ if (setlocale (LC_COLLATE, locale) == NULL)
+ {
+ puts ("*** Cannot set locale");
+ ++nfailed;
+ continue;
+ }
+
+ fnmres = fnmatch (pattern, input, flags_val);
+
+ printf ("%3d: fnmatch (\"%s\", \"%s\", %s) = %s%c",
+ ++nr,
+ escape (pattern, &escpatternlen, &escpattern),
+ escape (input, &escinputlen, &escinput),
+ flag_output (flags_val),
+ (fnmres == 0
+ ? "0" : (fnmres == FNM_NOMATCH
+ ? "FNM_NOMATCH"
+ : (sprintf (numbuf, "%d", fnmres), numbuf))),
+ (fnmres != 0) != (result != 0) ? ' ' : '\n');
+
+ if ((fnmres != 0) != (result != 0))
+ {
+ printf ("(FAIL, expected %s) ***\n",
+ result == 0
+ ? "0" : (result == FNM_NOMATCH
+ ? "FNM_NOMATCH"
+ : (sprintf (numbuf, "%d", result), numbuf)));
+ ++nfailed;
+ }
+ }
+
+ printf ("=====================\n%3d tests, %3d failed\n", ntests, nfailed);
+
+ free (escpattern);
+ free (escinput);
+ free (linebuf);
+
+ return nfailed != 0;
+}
+
+
+static char *
+next_input (char **line, int first, int last)
+{
+ char *cp = *line;
+ char *result;
+
+ while (*cp == ' ' || *cp == '\t')
+ ++cp;
+
+ /* We allow comment lines starting with '#'. */
+ if (first && *cp == '#')
+ return NULL;
+
+ if (*cp == '"')
+ {
+ char *wp;
+
+ result = ++cp;
+ wp = cp;
+
+ while (*cp != '"' && *cp != '\0' && *cp != '\n')
+ if (*cp == '\\')
+ {
+ if (cp[1] == '\n' || cp[1] == '\0')
+ return NULL;
+
+ ++cp;
+ if (*cp == 't')
+ *wp++ = '\t';
+ else if (*cp == 'n')
+ *wp++ = '\n';
+ else
+ *wp++ = *cp;
+
+ ++cp;
+ }
+ else
+ *wp++ = *cp++;
+
+ if (*cp != '"')
+ return NULL;
+
+ if (wp != cp)
+ *wp = '\0';
+ }
+ else
+ {
+ result = cp;
+ while (*cp != '\0' && *cp != '\n' && *cp != ' ' && *cp != '\t')
+ ++cp;
+
+ if (cp == result && ! last)
+ /* Premature end of line. */
+ return NULL;
+ }
+
+ /* Terminate and skip over the next white spaces. */
+ *cp++ = '\0';
+
+ *line = cp;
+ return result;
+}
+
+
+static int
+convert_flags (const char *str)
+{
+ int result = 0;
+
+ while (*str != '\0')
+ {
+ int len;
+
+ if (strncasecmp (str, "PATHNAME", 8) == 0
+ && (str[8] == '|' || str[8] == '\0'))
+ {
+ result |= FNM_PATHNAME;
+ len = 8;
+ }
+ else if (strncasecmp (str, "NOESCAPE", 8) == 0
+ && (str[8] == '|' || str[8] == '\0'))
+ {
+ result |= FNM_NOESCAPE;
+ len = 8;
+ }
+ else if (strncasecmp (str, "PERIOD", 6) == 0
+ && (str[6] == '|' || str[6] == '\0'))
+ {
+ result |= FNM_PERIOD;
+ len = 6;
+ }
+ else if (strncasecmp (str, "LEADING_DIR", 11) == 0
+ && (str[11] == '|' || str[11] == '\0'))
+ {
+ result |= FNM_LEADING_DIR;
+ len = 11;
+ }
+ else if (strncasecmp (str, "CASEFOLD", 8) == 0
+ && (str[8] == '|' || str[8] == '\0'))
+ {
+ result |= FNM_CASEFOLD;
+ len = 8;
+ }
+ else
+ return -1;
+
+ str += len;
+ if (*str != '\0')
+ ++str;
+ }
+
+ return result;
+}
+
+
+static char *
+flag_output (int flags)
+{
+ static char buf[100];
+ int first = 1;
+ char *cp = buf;
+
+ if (flags & FNM_PATHNAME)
+ {
+ cp = stpcpy (cp, "FNM_PATHNAME");
+ first = 0;
+ }
+ if (flags & FNM_NOESCAPE)
+ {
+ if (! first)
+ *cp++ = '|';
+ cp = stpcpy (cp, "FNM_NOESCAPE");
+ first = 0;
+ }
+ if (flags & FNM_PERIOD)
+ {
+ if (! first)
+ *cp++ = '|';
+ cp = stpcpy (cp, "FNM_PERIOD");
+ first = 0;
+ }
+ if (flags & FNM_LEADING_DIR)
+ {
+ if (! first)
+ *cp++ = '|';
+ cp = stpcpy (cp, "FNM_LEADING_DIR");
+ first = 0;
+ }
+ if (flags & FNM_CASEFOLD)
+ {
+ if (! first)
+ *cp++ = '|';
+ cp = stpcpy (cp, "FNM_CASEFOLD");
+ first = 0;
+ }
+ if (cp == buf)
+ *cp++ = '0';
+ *cp = '\0';
+
+ return buf;
+}
+
+
+static char *
+escape (const char *str, size_t *reslenp, char **resbufp)
+{
+ size_t reslen = *reslenp;
+ char *resbuf = *resbufp;
+ size_t len = strlen (str);
+ char *wp;
+
+ if (2 * len + 1 > reslen)
+ {
+ resbuf = (char *) realloc (resbuf, 2 * len + 1);
+ if (resbuf == NULL)
+ error (EXIT_FAILURE, errno, "while allocating buffer for printing");
+ *reslenp = 2 * len + 1;
+ *resbufp = resbuf;
+ }
+
+ wp = resbuf;
+ while (*str != '\0')
+ if (*str == '\t')
+ {
+ *wp++ = '\\';
+ *wp++ = 't';
+ ++str;
+ }
+ else if (*str == '\n')
+ {
+ *wp++ = '\\';
+ *wp++ = 'n';
+ ++str;
+ }
+ else if (*str == '"')
+ {
+ *wp++ = '\\';
+ *wp++ = '"';
+ ++str;
+ }
+ else if (*str == '\\')
+ {
+ *wp++ = '\\';
+ *wp++ = '\\';
+ ++str;
+ }
+ else
+ *wp++ = *str++;
+
+ *wp = '\0';
+
+ return resbuf;
+}
diff --git a/posix/tst-fnmatch.input b/posix/tst-fnmatch.input
new file mode 100644
index 0000000000..bf28653cd5
--- /dev/null
+++ b/posix/tst-fnmatch.input
@@ -0,0 +1,286 @@
+# Tests for fnmatch.
+# Copyright (C) 2000 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+# Contributes by Ulrich Drepper <drepper@redhat.com>.
+#
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with the GNU C Library; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+# Derived from the IEEE 2003.2 text. The standard only contains some
+# wording describing the situations to be tested. It does not specify
+# any specific tests. I.e., the tests below are in no case sufficient.
+# They are hopefully necessary, though.
+
+# B.6 004(C)
+C "!#%+,-./01234567889" "!#%+,-./01234567889" 0
+C ":;=@ABCDEFGHIJKLMNO" ":;=@ABCDEFGHIJKLMNO" 0
+C "PQRSTUVWXYZ]abcdefg" "PQRSTUVWXYZ]abcdefg" 0
+C "hijklmnopqrstuvwxyz" "hijklmnopqrstuvwxyz" 0
+C "^_{}~" "^_{}~" 0
+
+# B.6 005(C)
+C "\"$&'()" "\\\"\\$\\&\\'\\(\\)" 0
+C "*?[\\`|" "\\*\\?\\[\\\\\\`\\|" 0
+C "<>" "\\<\\>" 0
+
+# B.6 006(C)
+C "?*[" "[?*[][?*[][?*[]" 0
+C "a/b" "?/b" 0
+
+# B.6 007(C)
+C "a/b" "a?b" 0
+C "a/b" "a/?" 0
+C "a/b" "a?b" NOMATCH PATHNAME
+C "aa/b" "?/b" NOMATCH
+C "aa/b" "a?b" NOMATCH
+C "a/bb" "a/?" NOMATCH
+
+# B.6 009(C)
+C "abc" "[abc]" NOMATCH
+C "x" "[abc]" NOMATCH
+C "a" "[abc]" 0
+C "[" "[[abc]" 0
+C "a" "[][abc]" 0
+C "a]" "[]a]]" 0
+
+# B.6 010(C)
+C "xyz" "[!abc]" NOMATCH
+C "x" "[!abc]" 0
+C "a" "[!abc]" NOMATCH
+
+# B.6 011(C)
+C "]" "[][abc]" 0
+C "abc]" "[][abc]" NOMATCH
+C "[]abc" "[][]abc" NOMATCH
+C "]" "[!]]" NOMATCH
+C "aa]" "[!]a]" NOMATCH
+C "]" "[!a]" 0
+C "]]" "[!a]]" 0
+
+# B.6 012(C)
+# *** implement [. .]
+
+# B.6 013(C)
+# *** implement [. .]
+
+# B.6 014(C)
+# *** implement [. .]
+
+# B.6 015(C)
+# *** implement [= =]
+
+# B.6 016(C)
+# *** implement [= =]
+
+# B.6 017(C)
+C "a" "[[:alnum:]]" 0
+C "a" "[![:alnum:]]" NOMATCH
+C "-" "[[:alnum:]]" NOMATCH
+C "a]a" "[[:alnum:]]a" NOMATCH
+C "-" "[[:alnum:]-]" 0
+C "aa" "[[:alnum:]]a" 0
+C "-" "[![:alnum:]]" 0
+C "]" "[!][:alnum:]]" NOMATCH
+C "[" "[![:alnum:][]" NOMATCH
+C "a" "[[:alnum:]]" 0
+C "b" "[[:alnum:]]" 0
+C "c" "[[:alnum:]]" 0
+C "d" "[[:alnum:]]" 0
+C "e" "[[:alnum:]]" 0
+C "f" "[[:alnum:]]" 0
+C "g" "[[:alnum:]]" 0
+C "h" "[[:alnum:]]" 0
+C "i" "[[:alnum:]]" 0
+C "j" "[[:alnum:]]" 0
+C "k" "[[:alnum:]]" 0
+C "l" "[[:alnum:]]" 0
+C "m" "[[:alnum:]]" 0
+C "n" "[[:alnum:]]" 0
+C "o" "[[:alnum:]]" 0
+C "p" "[[:alnum:]]" 0
+C "q" "[[:alnum:]]" 0
+C "r" "[[:alnum:]]" 0
+C "s" "[[:alnum:]]" 0
+C "t" "[[:alnum:]]" 0
+C "u" "[[:alnum:]]" 0
+C "v" "[[:alnum:]]" 0
+C "w" "[[:alnum:]]" 0
+C "x" "[[:alnum:]]" 0
+C "y" "[[:alnum:]]" 0
+C "z" "[[:alnum:]]" 0
+C "A" "[[:alnum:]]" 0
+C "B" "[[:alnum:]]" 0
+C "C" "[[:alnum:]]" 0
+C "D" "[[:alnum:]]" 0
+C "E" "[[:alnum:]]" 0
+C "F" "[[:alnum:]]" 0
+C "G" "[[:alnum:]]" 0
+C "H" "[[:alnum:]]" 0
+C "I" "[[:alnum:]]" 0
+C "J" "[[:alnum:]]" 0
+C "K" "[[:alnum:]]" 0
+C "L" "[[:alnum:]]" 0
+C "M" "[[:alnum:]]" 0
+C "N" "[[:alnum:]]" 0
+C "O" "[[:alnum:]]" 0
+C "P" "[[:alnum:]]" 0
+C "Q" "[[:alnum:]]" 0
+C "R" "[[:alnum:]]" 0
+C "S" "[[:alnum:]]" 0
+C "T" "[[:alnum:]]" 0
+C "U" "[[:alnum:]]" 0
+C "V" "[[:alnum:]]" 0
+C "W" "[[:alnum:]]" 0
+C "X" "[[:alnum:]]" 0
+C "Y" "[[:alnum:]]" 0
+C "Z" "[[:alnum:]]" 0
+C "0" "[[:alnum:]]" 0
+C "1" "[[:alnum:]]" 0
+C "2" "[[:alnum:]]" 0
+C "3" "[[:alnum:]]" 0
+C "4" "[[:alnum:]]" 0
+C "5" "[[:alnum:]]" 0
+C "6" "[[:alnum:]]" 0
+C "7" "[[:alnum:]]" 0
+C "8" "[[:alnum:]]" 0
+C "9" "[[:alnum:]]" 0
+C "!" "[[:alnum:]]" NOMATCH
+C "#" "[[:alnum:]]" NOMATCH
+C "%" "[[:alnum:]]" NOMATCH
+C "+" "[[:alnum:]]" NOMATCH
+C "," "[[:alnum:]]" NOMATCH
+C "-" "[[:alnum:]]" NOMATCH
+C "." "[[:alnum:]]" NOMATCH
+C "/" "[[:alnum:]]" NOMATCH
+C ":" "[[:alnum:]]" NOMATCH
+C ";" "[[:alnum:]]" NOMATCH
+C "=" "[[:alnum:]]" NOMATCH
+C "@" "[[:alnum:]]" NOMATCH
+C "[" "[[:alnum:]]" NOMATCH
+C "\\" "[[:alnum:]]" NOMATCH
+C "]" "[[:alnum:]]" NOMATCH
+C "^" "[[:alnum:]]" NOMATCH
+C "_" "[[:alnum:]]" NOMATCH
+C "{" "[[:alnum:]]" NOMATCH
+C "}" "[[:alnum:]]" NOMATCH
+C "~" "[[:alnum:]]" NOMATCH
+C "\"" "[[:alnum:]]" NOMATCH
+C "$" "[[:alnum:]]" NOMATCH
+C "&" "[[:alnum:]]" NOMATCH
+C "'" "[[:alnum:]]" NOMATCH
+C "(" "[[:alnum:]]" NOMATCH
+C ")" "[[:alnum:]]" NOMATCH
+C "*" "[[:alnum:]]" NOMATCH
+C "?" "[[:alnum:]]" NOMATCH
+C "`" "[[:alnum:]]" NOMATCH
+C "|" "[[:alnum:]]" NOMATCH
+C "<" "[[:alnum:]]" NOMATCH
+C ">" "[[:alnum:]]" NOMATCH
+C "\t" "[[:cntrl:]]" 0
+C "t" "[[:cntrl:]]" NOMATCH
+C "t" "[[:lower:]]" 0
+C "\t" "[[:lower:]]" NOMATCH
+C "T" "[[:lower:]]" NOMATCH
+C "\t" "[[:space:]]" 0
+C "t" "[[:space:]]" NOMATCH
+C "t" "[[:alpha:]]" 0
+C "\t" "[[:alpha:]]" NOMATCH
+C "0" "[[:digit:]]" 0
+C "\t" "[[:digit:]]" NOMATCH
+C "t" "[[:digit:]]" NOMATCH
+C "\t" "[[:print:]]" NOMATCH
+C "t" "[[:print:]]" 0
+C "T" "[[:upper:]]" 0
+C "\t" "[[:upper:]]" NOMATCH
+C "t" "[[:upper:]]" NOMATCH
+C "\t" "[[:blank:]]" 0
+C "t" "[[:blank:]]" NOMATCH
+C "\t" "[[:graph:]]" NOMATCH
+C "t" "[[:graph:]]" 0
+C "." "[[:punct:]]" 0
+C "t" "[[:punct:]]" NOMATCH
+C "\t" "[[:punct:]]" NOMATCH
+C "0" "[[:xdigit:]]" 0
+C "\t" "[[:xdigit:]]" NOMATCH
+C "a" "[[:xdigit:]]" 0
+C "A" "[[:xdigit:]]" 0
+C "t" "[[:xdigit:]]" NOMATCH
+C "a" "[[alpha]]" NOMATCH
+C "a" "[[alpha:]]" NOMATCH
+C "a]" "[[alpha]]" 0
+C "a]" "[[alpha:]]" 0
+
+# B.6 018(C)
+C "a" "[a-c]" 0
+C "b" "[a-c]" 0
+C "c" "[a-c]" 0
+C "a" "[b-c]" NOMATCH
+C "d" "[b-c]" NOMATCH
+C "B" "[a-c]" NOMATCH
+C "b" "[A-C]" NOMATCH
+C "" "[a-c]" NOMATCH
+C "as" "[a-ca-z]" NOMATCH
+
+# B.6 019(C)
+C "b" "[c-a]" NOMATCH
+
+# B.6 020(C)
+C "a" "[a-c0-9]" 0
+C "d" "[a-c0-9]" NOMATCH
+C "B" "[a-c0-9]" NOMATCH
+
+# B.6 021(C)
+C "-" "[-a]" 0
+C "a" "[-b]" NOMATCH
+C "-" "[!-a]" NOMATCH
+C "a" "[!-b]" 0
+C "-" "[a-c-0-9]" 0
+C "b" "[a-c-0-9]" 0
+C "a:" "a[0-9-a]" NOMATCH
+C "a:" "a[09-a]" 0
+
+# B.6 024(C)
+C "" "*" 0
+C "asd/sdf" "*" 0
+
+# B.6 025(C)
+C "as" "[a-c][a-z]" 0
+C "as" "??" 0
+
+# B.6 026(C)
+C "asd/sdf" "as*df" 0
+C "asd/sdf" "as*" 0
+C "asd/sdf" "*df" 0
+C "asd/sdf" "as*dg" NOMATCH
+C "asdf" "as*df" 0
+C "asdf" "as*df?" NOMATCH
+C "asdf" "as*??" 0
+C "asdf" "a*???" 0
+C "asdf" "*????" 0
+C "asdf" "????*" 0
+C "asdf" "??*?" 0
+
+# B.6 027(C)
+C "/" "/" 0
+C "/" "/*" 0
+C "/" "*/" 0
+C "/" "/?" NOMATCH
+C "/" "?/" NOMATCH
+C "/" "?" 0
+C "." "?" 0
+C "/." "??" 0
+C "/" "[!a-c]" 0
+C "." "[!a-c]" 0