]> Cypherpunks repositories - gostls13.git/commitdiff
exp/regexp: add CompilePOSIX, more tests
authorRuss Cox <rsc@golang.org>
Thu, 8 Sep 2011 18:49:51 +0000 (14:49 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 8 Sep 2011 18:49:51 +0000 (14:49 -0400)
R=r
CC=golang-dev
https://golang.org/cl/4967060

src/pkg/exp/regexp/exec_test.go
src/pkg/exp/regexp/find_test.go
src/pkg/exp/regexp/re2.txt.gz [deleted file]
src/pkg/exp/regexp/regexp.go
src/pkg/exp/regexp/testdata/README [new file with mode: 0644]
src/pkg/exp/regexp/testdata/basic.dat [new file with mode: 0644]
src/pkg/exp/regexp/testdata/nullsubexpr.dat [new file with mode: 0644]
src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2 [new file with mode: 0644]
src/pkg/exp/regexp/testdata/re2-search.txt [new file with mode: 0644]
src/pkg/exp/regexp/testdata/repetition.dat [new file with mode: 0644]
src/pkg/exp/regexp/testdata/testregex.c [new file with mode: 0644]

index 69f673aca9a34ef2f87c33a7e64ebcb447bd0f6a..b6d9ecefb26f3a9333584faeb5c45c8445c2ff98 100644 (file)
@@ -6,9 +6,12 @@ package regexp
 
 import (
        "bufio"
-       "compress/gzip"
+       "compress/bzip2"
+       "exp/regexp/syntax"
        "fmt"
+       "io"
        "os"
+       "path/filepath"
        "strconv"
        "strings"
        "testing"
@@ -59,24 +62,34 @@ import (
 // At time of writing, re2.txt is 32 MB but compresses to 760 kB,
 // so we store re2.txt.gz in the repository and decompress it on the fly.
 //
-func TestRE2(t *testing.T) {
+func TestRE2Search(t *testing.T) {
+       testRE2(t, "testdata/re2-search.txt")
+}
+
+func TestRE2Exhaustive(t *testing.T) {
        if testing.Short() {
-               t.Log("skipping TestRE2 during short test")
+               t.Log("skipping TestRE2Exhaustive during short test")
                return
        }
+       testRE2(t, "testdata/re2-exhaustive.txt.bz2")
+}
 
-       f, err := os.Open("re2.txt.gz")
+func testRE2(t *testing.T, file string) {
+       f, err := os.Open(file)
        if err != nil {
                t.Fatal(err)
        }
        defer f.Close()
-       gz, err := gzip.NewReader(f)
-       if err != nil {
-               t.Fatalf("decompress re2.txt.gz: %v", err)
+       var txt io.Reader
+       if strings.HasSuffix(file, ".bz2") {
+               z := bzip2.NewReader(f)
+               txt = z
+               file = file[:len(file)-len(".bz2")] // for error messages
+       } else {
+               txt = f
        }
-       defer gz.Close()
        lineno := 0
-       r := bufio.NewReader(gz)
+       r := bufio.NewReader(txt)
        var (
                str       []string
                input     []string
@@ -92,13 +105,13 @@ func TestRE2(t *testing.T) {
                        if err == os.EOF {
                                break
                        }
-                       t.Fatalf("re2.txt:%d: %v", lineno, err)
+                       t.Fatalf("%s:%d: %v", file, lineno, err)
                }
                line = line[:len(line)-1] // chop \n
                lineno++
                switch {
                case line == "":
-                       t.Fatalf("re2.txt:%d: unexpected blank line", lineno)
+                       t.Fatalf("%s:%d: unexpected blank line", file, lineno)
                case line[0] == '#':
                        continue
                case 'A' <= line[0] && line[0] <= 'Z':
@@ -114,7 +127,7 @@ func TestRE2(t *testing.T) {
                        q, err := strconv.Unquote(line)
                        if err != nil {
                                // Fatal because we'll get out of sync.
-                               t.Fatalf("re2.txt:%d: unquote %s: %v", lineno, line, err)
+                               t.Fatalf("%s:%d: unquote %s: %v", file, lineno, line, err)
                        }
                        if inStrings {
                                str = append(str, q)
@@ -122,7 +135,7 @@ func TestRE2(t *testing.T) {
                        }
                        // Is a regexp.
                        if len(input) != 0 {
-                               t.Fatalf("re2.txt:%d: out of sync: have %d strings left before %#q", lineno, len(input), q)
+                               t.Fatalf("%s:%d: out of sync: have %d strings left before %#q", file, lineno, len(input), q)
                        }
                        re, err = tryCompile(q)
                        if err != nil {
@@ -130,7 +143,7 @@ func TestRE2(t *testing.T) {
                                        // We don't and likely never will support \C; keep going.
                                        continue
                                }
-                               t.Errorf("re2.txt:%d: compile %#q: %v", lineno, q, err)
+                               t.Errorf("%s:%d: compile %#q: %v", file, lineno, q, err)
                                if nfail++; nfail >= 100 {
                                        t.Fatalf("stopping after %d errors", nfail)
                                }
@@ -140,7 +153,7 @@ func TestRE2(t *testing.T) {
                        refull, err = tryCompile(full)
                        if err != nil {
                                // Fatal because q worked, so this should always work.
-                               t.Fatalf("re2.txt:%d: compile full %#q: %v", lineno, full, err)
+                               t.Fatalf("%s:%d: compile full %#q: %v", file, lineno, full, err)
                        }
                        input = str
                case line[0] == '-' || '0' <= line[0] && line[0] <= '9':
@@ -151,7 +164,7 @@ func TestRE2(t *testing.T) {
                                continue
                        }
                        if len(input) == 0 {
-                               t.Fatalf("re2.txt:%d: out of sync: no input remaining", lineno)
+                               t.Fatalf("%s:%d: out of sync: no input remaining", file, lineno)
                        }
                        var text string
                        text, input = input[0], input[1:]
@@ -165,13 +178,13 @@ func TestRE2(t *testing.T) {
                        }
                        res := strings.Split(line, ";")
                        if len(res) != len(run) {
-                               t.Fatalf("re2.txt:%d: have %d test results, want %d", lineno, len(res), len(run))
+                               t.Fatalf("%s:%d: have %d test results, want %d", file, lineno, len(res), len(run))
                        }
                        for i := range res {
                                have, suffix := run[i](re, refull, text)
-                               want := parseResult(t, lineno, res[i])
+                               want := parseResult(t, file, lineno, res[i])
                                if !same(have, want) {
-                                       t.Errorf("re2.txt:%d: %#q%s.FindSubmatchIndex(%#q) = %v, want %v", lineno, re, suffix, text, have, want)
+                                       t.Errorf("%s:%d: %#q%s.FindSubmatchIndex(%#q) = %v, want %v", file, lineno, re, suffix, text, have, want)
                                        if nfail++; nfail >= 100 {
                                                t.Fatalf("stopping after %d errors", nfail)
                                        }
@@ -179,7 +192,7 @@ func TestRE2(t *testing.T) {
                                }
                                b, suffix := match[i](re, refull, text)
                                if b != (want != nil) {
-                                       t.Errorf("re2.txt:%d: %#q%s.MatchString(%#q) = %v, want %v", lineno, re, suffix, text, b, !b)
+                                       t.Errorf("%s:%d: %#q%s.MatchString(%#q) = %v, want %v", file, lineno, re, suffix, text, b, !b)
                                        if nfail++; nfail >= 100 {
                                                t.Fatalf("stopping after %d errors", nfail)
                                        }
@@ -188,11 +201,11 @@ func TestRE2(t *testing.T) {
                        }
 
                default:
-                       t.Fatalf("re2.txt:%d: out of sync: %s\n", lineno, line)
+                       t.Fatalf("%s:%d: out of sync: %s\n", file, lineno, line)
                }
        }
        if len(input) != 0 {
-               t.Fatalf("re2.txt:%d: out of sync: have %d strings left at EOF", lineno, len(input))
+               t.Fatalf("%s:%d: out of sync: have %d strings left at EOF", file, lineno, len(input))
        }
        t.Logf("%d cases tested", ncase)
 }
@@ -270,7 +283,7 @@ func tryCompile(s string) (re *Regexp, err os.Error) {
        return Compile(s)
 }
 
-func parseResult(t *testing.T, lineno int, res string) []int {
+func parseResult(t *testing.T, file string, lineno int, res string) []int {
        // A single - indicates no match.
        if res == "-" {
                return nil
@@ -295,12 +308,12 @@ func parseResult(t *testing.T, lineno int, res string) []int {
                        } else {
                                k := strings.Index(pair, "-")
                                if k < 0 {
-                                       t.Fatalf("re2.txt:%d: invalid pair %s", lineno, pair)
+                                       t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair)
                                }
                                lo, err1 := strconv.Atoi(pair[:k])
                                hi, err2 := strconv.Atoi(pair[k+1:])
                                if err1 != nil || err2 != nil || lo > hi {
-                                       t.Fatalf("re2.txt:%d: invalid pair %s", lineno, pair)
+                                       t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair)
                                }
                                out[n] = lo
                                out[n+1] = hi
@@ -323,3 +336,314 @@ func same(x, y []int) bool {
        }
        return true
 }
+
+// TestFowler runs this package's regexp API against the
+// POSIX regular expression tests collected by Glenn Fowler
+// at http://www2.research.att.com/~gsf/testregex/.
+func TestFowler(t *testing.T) {
+       files, err := filepath.Glob("testdata/*.dat")
+       if err != nil {
+               t.Fatal(err)
+       }
+       for _, file := range files {
+               t.Log(file)
+               testFowler(t, file)
+       }
+}
+
+var notab = MustCompile(`[^\t]+`)
+
+func testFowler(t *testing.T, file string) {
+       f, err := os.Open(file)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+       defer f.Close()
+       b := bufio.NewReader(f)
+       lineno := 0
+       lastRegexp := ""
+Reading:
+       for {
+               lineno++
+               line, err := b.ReadString('\n')
+               if err != nil {
+                       if err != os.EOF {
+                               t.Errorf("%s:%d: %v", file, lineno, err)
+                       }
+                       break Reading
+               }
+
+               // http://www2.research.att.com/~gsf/man/man1/testregex.html
+               //
+               // INPUT FORMAT
+               //   Input lines may be blank, a comment beginning with #, or a test
+               //   specification. A specification is five fields separated by one
+               //   or more tabs. NULL denotes the empty string and NIL denotes the
+               //   0 pointer.
+               if line[0] == '#' || line[0] == '\n' {
+                       continue Reading
+               }
+               line = line[:len(line)-1]
+               field := notab.FindAllString(line, -1)
+               for i, f := range field {
+                       if f == "NULL" {
+                               field[i] = ""
+                       }
+                       if f == "NIL" {
+                               t.Logf("%s:%d: skip: %s", file, lineno, line)
+                               continue Reading
+                       }
+               }
+               if len(field) == 0 {
+                       continue Reading
+               }
+
+               //   Field 1: the regex(3) flags to apply, one character per REG_feature
+               //   flag. The test is skipped if REG_feature is not supported by the
+               //   implementation. If the first character is not [BEASKLP] then the
+               //   specification is a global control line. One or more of [BEASKLP] may be
+               //   specified; the test will be repeated for each mode.
+               // 
+               //     B        basic                   BRE     (grep, ed, sed)
+               //     E        REG_EXTENDED            ERE     (egrep)
+               //     A        REG_AUGMENTED           ARE     (egrep with negation)
+               //     S        REG_SHELL               SRE     (sh glob)
+               //     K        REG_SHELL|REG_AUGMENTED KRE     (ksh glob)
+               //     L        REG_LITERAL             LRE     (fgrep)
+               // 
+               //     a        REG_LEFT|REG_RIGHT      implicit ^...$
+               //     b        REG_NOTBOL              lhs does not match ^
+               //     c        REG_COMMENT             ignore space and #...\n
+               //     d        REG_SHELL_DOT           explicit leading . match
+               //     e        REG_NOTEOL              rhs does not match $
+               //     f        REG_MULTIPLE            multiple \n separated patterns
+               //     g        FNM_LEADING_DIR         testfnmatch only -- match until /
+               //     h        REG_MULTIREF            multiple digit backref
+               //     i        REG_ICASE               ignore case
+               //     j        REG_SPAN                . matches \n
+               //     k        REG_ESCAPE              \ to ecape [...] delimiter
+               //     l        REG_LEFT                implicit ^...
+               //     m        REG_MINIMAL             minimal match
+               //     n        REG_NEWLINE             explicit \n match
+               //     o        REG_ENCLOSED            (|&) magic inside [@|&](...)
+               //     p        REG_SHELL_PATH          explicit / match
+               //     q        REG_DELIMITED           delimited pattern
+               //     r        REG_RIGHT               implicit ...$
+               //     s        REG_SHELL_ESCAPED       \ not special
+               //     t        REG_MUSTDELIM           all delimiters must be specified
+               //     u        standard unspecified behavior -- errors not counted
+               //     v        REG_CLASS_ESCAPE        \ special inside [...]
+               //     w        REG_NOSUB               no subexpression match array
+               //     x        REG_LENIENT             let some errors slide
+               //     y        REG_LEFT                regexec() implicit ^...
+               //     z        REG_NULL                NULL subexpressions ok
+               //     $                                expand C \c escapes in fields 2 and 3
+               //     /                                field 2 is a regsubcomp() expression
+               //     =                                field 3 is a regdecomp() expression
+               // 
+               //   Field 1 control lines:
+               // 
+               //     C                set LC_COLLATE and LC_CTYPE to locale in field 2
+               // 
+               //     ?test ...        output field 5 if passed and != EXPECTED, silent otherwise
+               //     &test ...        output field 5 if current and previous passed
+               //     |test ...        output field 5 if current passed and previous failed
+               //     ; ...    output field 2 if previous failed
+               //     {test ...        skip if failed until }
+               //     }                end of skip
+               // 
+               //     : comment                comment copied as output NOTE
+               //     :comment:test    :comment: ignored
+               //     N[OTE] comment   comment copied as output NOTE
+               //     T[EST] comment   comment
+               // 
+               //     number           use number for nmatch (20 by default)
+               flag := field[0]
+               switch flag[0] {
+               case '?', '&', '|', ';', '{', '}':
+                       // Ignore all the control operators.
+                       // Just run everything.
+                       flag = flag[1:]
+                       if flag == "" {
+                               continue Reading
+                       }
+               case ':':
+                       i := strings.Index(flag[1:], ":")
+                       if i < 0 {
+                               t.Logf("skip: %s", line)
+                               continue Reading
+                       }
+                       flag = flag[1+i+1:]
+               case 'C', 'N', 'T', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+                       t.Logf("skip: %s", line)
+                       continue Reading
+               }
+
+               // Can check field count now that we've handled the myriad comment formats.
+               if len(field) < 4 {
+                       t.Errorf("%s:%d: too few fields: %s", file, lineno, line)
+                       continue Reading
+               }
+
+               // Expand C escapes (a.k.a. Go escapes).
+               if strings.Contains(flag, "$") {
+                       f := `"` + field[1] + `"`
+                       if field[1], err = strconv.Unquote(f); err != nil {
+                               t.Errorf("%s:%d: cannot unquote %s", file, lineno, f)
+                       }
+                       f = `"` + field[2] + `"`
+                       if field[2], err = strconv.Unquote(f); err != nil {
+                               t.Errorf("%s:%d: cannot unquote %s", file, lineno, f)
+                       }
+               }
+
+               //   Field 2: the regular expression pattern; SAME uses the pattern from
+               //     the previous specification.
+               // 
+               if field[1] == "SAME" {
+                       field[1] = lastRegexp
+               }
+               lastRegexp = field[1]
+
+               //   Field 3: the string to match.
+               text := field[2]
+
+               //   Field 4: the test outcome...
+               ok, shouldCompile, shouldMatch, pos := parseFowlerResult(field[3])
+               if !ok {
+                       t.Errorf("%s:%d: cannot parse result %#q", file, lineno, field[3])
+                       continue Reading
+               }
+
+               //   Field 5: optional comment appended to the report.
+
+       Testing:
+               // Run test once for each specified capital letter mode that we support.
+               for _, c := range flag {
+                       pattern := field[1]
+                       syn := syntax.POSIX | syntax.ClassNL
+                       switch c {
+                       default:
+                               continue Testing
+                       case 'E':
+                               // extended regexp (what we support)
+                       case 'L':
+                               // literal
+                               pattern = QuoteMeta(pattern)
+                       }
+
+                       for _, c := range flag {
+                               switch c {
+                               case 'i':
+                                       syn |= syntax.FoldCase
+                               }
+                       }
+
+                       re, err := compile(pattern, syn, true)
+                       if err != nil {
+                               if shouldCompile {
+                                       t.Errorf("%s:%d: %#q did not compile", file, lineno, pattern)
+                               }
+                               continue Testing
+                       }
+                       if !shouldCompile {
+                               t.Errorf("%s:%d: %#q should not compile", file, lineno, pattern)
+                               continue Testing
+                       }
+                       match := re.MatchString(text)
+                       if match != shouldMatch {
+                               t.Errorf("%s:%d: %#q.Match(%#q) = %v, want %v", file, lineno, pattern, text, match, shouldMatch)
+                               continue Testing
+                       }
+                       have := re.FindStringSubmatchIndex(text)
+                       if (len(have) > 0) != match {
+                               t.Errorf("%s:%d: %#q.Match(%#q) = %v, but %#q.FindSubmatchIndex(%#q) = %v", file, lineno, pattern, text, match, text, have)
+                               continue Testing
+                       }
+                       if len(have) > len(pos) {
+                               have = have[:len(pos)]
+                       }
+                       if !same(have, pos) {
+                               t.Errorf("%s:%d: %#q.FindSubmatchIndex(%#q) = %v, want %v", file, lineno, pattern, text, have, pos)
+                       }
+               }
+       }
+}
+
+func parseFowlerResult(s string) (ok, compiled, matched bool, pos []int) {
+       //   Field 4: the test outcome. This is either one of the posix error
+       //     codes (with REG_ omitted) or the match array, a list of (m,n)
+       //     entries with m and n being first and last+1 positions in the
+       //     field 3 string, or NULL if REG_NOSUB is in effect and success
+       //     is expected. BADPAT is acceptable in place of any regcomp(3)
+       //     error code. The match[] array is initialized to (-2,-2) before
+       //     each test. All array elements from 0 to nmatch-1 must be specified
+       //     in the outcome. Unspecified endpoints (offset -1) are denoted by ?.
+       //     Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a
+       //     matched (?{...}) expression, where x is the text enclosed by {...},
+       //     o is the expression ordinal counting from 1, and n is the length of
+       //     the unmatched portion of the subject string. If x starts with a
+       //     number then that is the return value of re_execf(), otherwise 0 is
+       //     returned.
+       switch {
+       case s == "":
+               // Match with no position information.
+               ok = true
+               compiled = true
+               matched = true
+               return
+       case s == "NOMATCH":
+               // Match failure.
+               ok = true
+               compiled = true
+               matched = false
+               return
+       case 'A' <= s[0] && s[0] <= 'Z':
+               // All the other error codes are compile errors.
+               ok = true
+               compiled = false
+               return
+       }
+       compiled = true
+
+       var x []int
+       for s != "" {
+               var end byte = ')'
+               if len(x)%2 == 0 {
+                       if s[0] != '(' {
+                               ok = false
+                               return
+                       }
+                       s = s[1:]
+                       end = ','
+               }
+               i := 0
+               for i < len(s) && s[i] != end {
+                       i++
+               }
+               if i == 0 || i == len(s) {
+                       ok = false
+                       return
+               }
+               var v = -1
+               var err os.Error
+               if s[:i] != "?" {
+                       v, err = strconv.Atoi(s[:i])
+                       if err != nil {
+                               ok = false
+                               return
+                       }
+               }
+               x = append(x, v)
+               s = s[i+1:]
+       }
+       if len(x)%2 != 0 {
+               ok = false
+               return
+       }
+       ok = true
+       matched = true
+       pos = x
+       return
+}
index 6406bb6e6564c9f8f1d9068d5dc41c22f1184454..e07eb7d5c05059c3ba0ee74477a3179ebccdf416 100644 (file)
@@ -98,6 +98,15 @@ var findTests = []FindTest{
        {`\B`, "x y", nil},
        {`\B`, "xx yy", build(2, 1, 1, 4, 4)},
 
+       // RE2 tests
+       {`[^\S\s]`, "abcd", nil},
+       {`[^\S[:space:]]`, "abcd", nil},
+       {`[^\D\d]`, "abcd", nil},
+       {`[^\D[:digit:]]`, "abcd", nil},
+       {`(?i)\W`, "x", nil},
+       {`(?i)\W`, "k", nil},
+       {`(?i)\W`, "s", nil},
+
        // can backslash-escape any punctuation
        {`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
                `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
diff --git a/src/pkg/exp/regexp/re2.txt.gz b/src/pkg/exp/regexp/re2.txt.gz
deleted file mode 100644 (file)
index 85b8ead..0000000
Binary files a/src/pkg/exp/regexp/re2.txt.gz and /dev/null differ
index 1d0fc9df8d44fdb34b719952eeba7e8e2c092c60..86c35fa72400b9b1e5a2dda6aaba37eac4688a5b 100644 (file)
@@ -97,10 +97,45 @@ func (re *Regexp) String() string {
        return re.expr
 }
 
-// Compile parses a regular expression and returns, if successful, a Regexp
-// object that can be used to match against text.
+// Compile parses a regular expression and returns, if successful,
+// a Regexp object that can be used to match against text.
+//
+// When matching against text, the regexp returns a match that
+// begins as early as possible in the input (leftmost), and among those
+// it chooses the one that a backtracking search would have found first.
+// This so-called leftmost-first matching is the same semantics
+// that Perl, Python, and other implementations use, although this
+// package implements it without the expense of backtracking.
+// For POSIX leftmost-longest matching, see CompilePOSIX.
 func Compile(expr string) (*Regexp, os.Error) {
-       re, err := syntax.Parse(expr, syntax.Perl)
+       return compile(expr, syntax.Perl, false)
+}
+
+// CompilePOSIX is like Compile but restricts the regular expression
+// to POSIX ERE (egrep) syntax and changes the match semantics to
+// leftmost-longest.
+//
+// That is, when matching against text, the regexp returns a match that
+// begins as early as possible in the input (leftmost), and among those
+// it chooses a match that is as long as possible.
+// This so-called leftmost-longest matching is the same semantics
+// that early regular expression implementations used and that POSIX
+// specifies.
+//
+// However, there can be multiple leftmost-longest matches, with different
+// submatch choices, and here this package diverges from POSIX.
+// Among the possible leftmost-longest matches, this package chooses
+// the one that a backtracking search would have found first, while POSIX
+// specifies that the match be chosen to maximize the length of the first
+// subexpression, then the second, and so on from left to right.
+// The POSIX rule is computationally prohibitive and not even well-defined.
+// See http://swtch.com/~rsc/regexp/regexp2.html#posix for details.
+func CompilePOSIX(expr string) (*Regexp, os.Error) {
+       return compile(expr, syntax.POSIX, true)
+}
+
+func compile(expr string, mode syntax.Flags, longest bool) (*Regexp, os.Error) {
+       re, err := syntax.Parse(expr, mode)
        if err != nil {
                return nil, err
        }
@@ -114,6 +149,8 @@ func Compile(expr string) (*Regexp, os.Error) {
                expr:      expr,
                prog:      prog,
                numSubexp: maxCap,
+               cond:      prog.StartCond(),
+               longest:   longest,
        }
        regexp.prefix, regexp.prefixComplete = prog.Prefix()
        if regexp.prefix != "" {
@@ -122,7 +159,6 @@ func Compile(expr string) (*Regexp, os.Error) {
                regexp.prefixBytes = []byte(regexp.prefix)
                regexp.prefixRune, _ = utf8.DecodeRuneInString(regexp.prefix)
        }
-       regexp.cond = prog.StartCond()
        return regexp, nil
 }
 
diff --git a/src/pkg/exp/regexp/testdata/README b/src/pkg/exp/regexp/testdata/README
new file mode 100644 (file)
index 0000000..b1b301b
--- /dev/null
@@ -0,0 +1,23 @@
+AT&T POSIX Test Files
+See textregex.c for copyright + license.
+
+testregex.c    http://www2.research.att.com/~gsf/testregex/testregex.c
+basic.dat      http://www2.research.att.com/~gsf/testregex/basic.dat
+nullsubexpr.dat        http://www2.research.att.com/~gsf/testregex/nullsubexpr.dat
+repetition.dat http://www2.research.att.com/~gsf/testregex/repetition.dat
+
+The test data has been edited to reflect RE2/Go differences:
+  * In a star of a possibly empty match like (a*)* matching x,
+    the no match case runs the starred subexpression zero times,
+    not once.  This is consistent with (a*)* matching a, which
+    runs the starred subexpression one time, not twice.
+  * The submatch choice is first match, not the POSIX rule.
+
+Such changes are marked with 'RE2/Go'.
+
+
+RE2 Test Files
+
+re2-exhaustive.txt.bz2 and re2-search.txt are built by running
+'make log' in the RE2 distribution.  http://code.google.com/p/re2/.
+The exhaustive file is compressed because it is huge.
diff --git a/src/pkg/exp/regexp/testdata/basic.dat b/src/pkg/exp/regexp/testdata/basic.dat
new file mode 100644 (file)
index 0000000..7859290
--- /dev/null
@@ -0,0 +1,221 @@
+NOTE   all standard compliant implementations should pass these : 2002-05-31
+
+BE     abracadabra$    abracadabracadabra      (7,18)
+BE     a...b           abababbb                (2,7)
+BE     XXXXXX          ..XXXXXX                (2,8)
+E      \)              ()      (1,2)
+BE     a]              a]a     (0,2)
+B      }               }       (0,1)
+E      \}              }       (0,1)
+BE     \]              ]       (0,1)
+B      ]               ]       (0,1)
+E      ]               ]       (0,1)
+B      {               {       (0,1)
+B      }               }       (0,1)
+BE     ^a              ax      (0,1)
+BE     \^a             a^a     (1,3)
+BE     a\^             a^      (0,2)
+BE     a$              aa      (1,2)
+BE     a\$             a$      (0,2)
+BE     ^$              NULL    (0,0)
+E      $^              NULL    (0,0)
+E      a($)            aa      (1,2)(2,2)
+E      a*(^a)          aa      (0,1)(0,1)
+E      (..)*(...)*             a       (0,0)
+E      (..)*(...)*             abcd    (0,4)(2,4)
+E      (ab|a)(bc|c)            abc     (0,3)(0,2)(2,3)
+E      (ab)c|abc               abc     (0,3)(0,2)
+E      a{0}b           ab                      (1,2)
+E      (a*)(b?)(b+)b{3}        aaabbbbbbb      (0,10)(0,3)(3,4)(4,7)
+E      (a*)(b{0,1})(b{1,})b{3} aaabbbbbbb      (0,10)(0,3)(3,4)(4,7)
+E      a{9876543210}   NULL    BADBR
+E      ((a|a)|a)                       a       (0,1)(0,1)(0,1)
+E      (a*)(a|aa)                      aaaa    (0,4)(0,3)(3,4)
+E      a*(a.|aa)                       aaaa    (0,4)(2,4)
+E      a(b)|c(d)|a(e)f                 aef     (0,3)(?,?)(?,?)(1,2)
+E      (a|b)?.*                        b       (0,1)(0,1)
+E      (a|b)c|a(b|c)                   ac      (0,2)(0,1)
+E      (a|b)c|a(b|c)                   ab      (0,2)(?,?)(1,2)
+E      (a|b)*c|(a|ab)*c                abc     (0,3)(1,2)
+E      (a|b)*c|(a|ab)*c                xc      (1,2)
+E      (.a|.b).*|.*(.a|.b)             xa      (0,2)(0,2)
+E      a?(ab|ba)ab                     abab    (0,4)(0,2)
+E      a?(ac{0}b|ba)ab                 abab    (0,4)(0,2)
+E      ab|abab                         abbabab (0,2)
+E      aba|bab|bba                     baaabbbaba      (5,8)
+E      aba|bab                         baaabbbaba      (6,9)
+E      (aa|aaa)*|(a|aaaaa)             aa      (0,2)(0,2)
+E      (a.|.a.)*|(a|.a...)             aa      (0,2)(0,2)
+E      ab|a                            xabc    (1,3)
+E      ab|a                            xxabc   (2,4)
+Ei     (Ab|cD)*                        aBcD    (0,4)(2,4)
+BE     [^-]                    --a             (2,3)
+BE     [a-]*                   --a             (0,3)
+BE     [a-m-]*                 --amoma--       (0,4)
+E      :::1:::0:|:::1:1:0:     :::0:::1:::1:::0:       (8,17)
+E      :::1:::0:|:::1:1:1:     :::0:::1:::1:::0:       (8,17)
+{E     [[:upper:]]             A               (0,1)   [[<element>]] not supported
+E      [[:lower:]]+            `az{            (1,3)
+E      [[:upper:]]+            @AZ[            (1,3)
+# No collation in Go
+#BE    [[-]]                   [[-]]           (2,4)
+#BE    [[.NIL.]]       NULL    ECOLLATE
+#BE    [[=aleph=]]     NULL    ECOLLATE
+}
+BE$    \n              \n      (0,1)
+BEn$   \n              \n      (0,1)
+BE$    [^a]            \n      (0,1)
+BE$    \na             \na     (0,2)
+E      (a)(b)(c)       abc     (0,3)(0,1)(1,2)(2,3)
+BE     xxx             xxx     (0,3)
+E1     (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)      feb 6,  (0,6)
+E1     (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)      2/7     (0,3)
+E1     (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)      feb 1,Feb 6     (5,11)
+E3     ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))   x       (0,1)(0,1)(0,1)
+E3     ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*  xx      (0,2)(1,2)(1,2)
+E      a?(ab|ba)*      ababababababababababababababababababababababababababababababababababababababababa       (0,81)(79,81)
+E      abaa|abbaa|abbbaa|abbbbaa       ababbabbbabbbabbbbabbbbaa       (18,25)
+E      abaa|abbaa|abbbaa|abbbbaa       ababbabbbabbbabbbbabaa  (18,22)
+E      aaac|aabc|abac|abbc|baac|babc|bbac|bbbc baaabbbabac     (7,11)
+BE$    .*                      \x01\xff        (0,2)
+E      aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll            XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa       (53,57)
+L      aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll         XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa       NOMATCH
+E      a*a*a*a*a*b             aaaaaaaaab      (0,10)
+BE     ^                       NULL            (0,0)
+BE     $                       NULL            (0,0)
+BE     ^$                      NULL            (0,0)
+BE     ^a$                     a               (0,1)
+BE     abc                     abc             (0,3)
+BE     abc                     xabcy           (1,4)
+BE     abc                     ababc           (2,5)
+BE     ab*c                    abc             (0,3)
+BE     ab*bc                   abc             (0,3)
+BE     ab*bc                   abbc            (0,4)
+BE     ab*bc                   abbbbc          (0,6)
+E      ab+bc                   abbc            (0,4)
+E      ab+bc                   abbbbc          (0,6)
+E      ab?bc                   abbc            (0,4)
+E      ab?bc                   abc             (0,3)
+E      ab?c                    abc             (0,3)
+BE     ^abc$                   abc             (0,3)
+BE     ^abc                    abcc            (0,3)
+BE     abc$                    aabc            (1,4)
+BE     ^                       abc             (0,0)
+BE     $                       abc             (3,3)
+BE     a.c                     abc             (0,3)
+BE     a.c                     axc             (0,3)
+BE     a.*c                    axyzc           (0,5)
+BE     a[bc]d                  abd             (0,3)
+BE     a[b-d]e                 ace             (0,3)
+BE     a[b-d]                  aac             (1,3)
+BE     a[-b]                   a-              (0,2)
+BE     a[b-]                   a-              (0,2)
+BE     a]                      a]              (0,2)
+BE     a[]]b                   a]b             (0,3)
+BE     a[^bc]d                 aed             (0,3)
+BE     a[^-b]c                 adc             (0,3)
+BE     a[^]b]c                 adc             (0,3)
+E      ab|cd                   abc             (0,2)
+E      ab|cd                   abcd            (0,2)
+E      a\(b                    a(b             (0,3)
+E      a\(*b                   ab              (0,2)
+E      a\(*b                   a((b            (0,4)
+E      ((a))                   abc             (0,1)(0,1)(0,1)
+E      (a)b(c)                 abc             (0,3)(0,1)(2,3)
+E      a+b+c                   aabbabc         (4,7)
+E      a*                      aaa             (0,3)
+#E     (a*)*                   -               (0,0)(0,0)
+E      (a*)*                   -               (0,0)(?,?)      RE2/Go
+E      (a*)+                   -               (0,0)(0,0)
+#E     (a*|b)*                 -               (0,0)(0,0)
+E      (a*|b)*                 -               (0,0)(?,?)      RE2/Go
+E      (a+|b)*                 ab              (0,2)(1,2)
+E      (a+|b)+                 ab              (0,2)(1,2)
+E      (a+|b)?                 ab              (0,1)(0,1)
+BE     [^ab]*                  cde             (0,3)
+#E     (^)*                    -               (0,0)(0,0)
+E      (^)*                    -               (0,0)(?,?)      RE2/Go
+BE     a*                      NULL            (0,0)
+E      ([abc])*d               abbbcd          (0,6)(4,5)
+E      ([abc])*bcd             abcd            (0,4)(0,1)
+E      a|b|c|d|e               e               (0,1)
+E      (a|b|c|d|e)f            ef              (0,2)(0,1)
+#E     ((a*|b))*               -               (0,0)(0,0)(0,0)
+E      ((a*|b))*               -               (0,0)(?,?)(?,?) RE2/Go
+BE     abcd*efg                abcdefg         (0,7)
+BE     ab*                     xabyabbbz       (1,3)
+BE     ab*                     xayabbbz        (1,2)
+E      (ab|cd)e                abcde           (2,5)(2,4)
+BE     [abhgefdc]ij            hij             (0,3)
+E      (a|b)c*d                abcd            (1,4)(1,2)
+E      (ab|ab*)bc              abc             (0,3)(0,1)
+E      a([bc]*)c*              abc             (0,3)(1,3)
+E      a([bc]*)(c*d)           abcd            (0,4)(1,3)(3,4)
+E      a([bc]+)(c*d)           abcd            (0,4)(1,3)(3,4)
+E      a([bc]*)(c+d)           abcd            (0,4)(1,2)(2,4)
+E      a[bcd]*dcdcde           adcdcde         (0,7)
+E      (ab|a)b*c               abc             (0,3)(0,2)
+E      ((a)(b)c)(d)            abcd            (0,4)(0,3)(0,1)(1,2)(3,4)
+BE     [A-Za-z_][A-Za-z0-9_]*  alpha           (0,5)
+E      ^a(bc+|b[eh])g|.h$      abh             (1,3)
+E      (bc+d$|ef*g.|h?i(j|k))  effgz           (0,5)(0,5)
+E      (bc+d$|ef*g.|h?i(j|k))  ij              (0,2)(0,2)(1,2)
+E      (bc+d$|ef*g.|h?i(j|k))  reffgz          (1,6)(1,6)
+E      (((((((((a)))))))))     a               (0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)
+BE     multiple words          multiple words yeah     (0,14)
+E      (.*)c(.*)               abcde           (0,5)(0,2)(3,5)
+BE     abcd                    abcd            (0,4)
+E      a(bc)d                  abcd            (0,4)(1,3)
+E      a[\ 1-\ 3]?c                a\ 2c             (0,3)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Qaddafi (0,15)(?,?)(10,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Mo'ammar Gadhafi        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Kaddafi (0,15)(?,?)(10,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Qadhafi (0,15)(?,?)(10,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Gadafi  (0,14)(?,?)(10,11)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Mu'ammar Qadafi (0,15)(?,?)(11,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Moamar Gaddafi  (0,14)(?,?)(9,11)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Mu'ammar Qadhdhafi      (0,18)(?,?)(13,15)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Khaddafi        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Ghaddafy        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Ghadafi (0,15)(?,?)(11,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Ghaddafi        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muamar Kaddafi  (0,14)(?,?)(9,11)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Quathafi        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Muammar Gheddafi        (0,16)(?,?)(11,13)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Moammar Khadafy (0,15)(?,?)(11,12)
+E      M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]       Moammar Qudhafi (0,15)(?,?)(10,12)
+E      a+(b|c)*d+              aabcdd                  (0,6)(3,4)
+E      ^.+$                    vivi                    (0,4)
+E      ^(.+)$                  vivi                    (0,4)(0,4)
+E      ^([^!.]+).att.com!(.+)$ gryphon.att.com!eby     (0,19)(0,7)(16,19)
+E      ^([^!]+!)?([^!]+)$      bas                     (0,3)(?,?)(0,3)
+E      ^([^!]+!)?([^!]+)$      bar!bas                 (0,7)(0,4)(4,7)
+E      ^([^!]+!)?([^!]+)$      foo!bas                 (0,7)(0,4)(4,7)
+E      ^.+!([^!]+!)([^!]+)$    foo!bar!bas             (0,11)(4,8)(8,11)
+E      ((foo)|(bar))!bas       bar!bas                 (0,7)(0,3)(?,?)(0,3)
+E      ((foo)|(bar))!bas       foo!bar!bas             (4,11)(4,7)(?,?)(4,7)
+E      ((foo)|(bar))!bas       foo!bas                 (0,7)(0,3)(0,3)
+E      ((foo)|bar)!bas         bar!bas                 (0,7)(0,3)
+E      ((foo)|bar)!bas         foo!bar!bas             (4,11)(4,7)
+E      ((foo)|bar)!bas         foo!bas                 (0,7)(0,3)(0,3)
+E      (foo|(bar))!bas         bar!bas                 (0,7)(0,3)(0,3)
+E      (foo|(bar))!bas         foo!bar!bas             (4,11)(4,7)(4,7)
+E      (foo|(bar))!bas         foo!bas                 (0,7)(0,3)
+E      (foo|bar)!bas           bar!bas                 (0,7)(0,3)
+E      (foo|bar)!bas           foo!bar!bas             (4,11)(4,7)
+E      (foo|bar)!bas           foo!bas                 (0,7)(0,3)
+E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas     (0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bas             (0,3)(?,?)(0,3)
+E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bar!bas         (0,7)(0,4)(4,7)
+E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bar!bas     (0,11)(?,?)(?,?)(4,8)(8,11)
+E      ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bas         (0,7)(0,4)(4,7)
+E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bas             (0,3)(0,3)(?,?)(0,3)
+E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bar!bas         (0,7)(0,7)(0,4)(4,7)
+E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas     (0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E      ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bas         (0,7)(0,7)(0,4)(4,7)
+E      .*(/XXX).*                      /XXX                    (0,4)(0,4)
+E      .*(\\XXX).*                     \XXX                    (0,4)(0,4)
+E      \\XXX                           \XXX                    (0,4)
+E      .*(/000).*                      /000                    (0,4)(0,4)
+E      .*(\\000).*                     \000                    (0,4)(0,4)
+E      \\000                           \000                    (0,4)
diff --git a/src/pkg/exp/regexp/testdata/nullsubexpr.dat b/src/pkg/exp/regexp/testdata/nullsubexpr.dat
new file mode 100644 (file)
index 0000000..2e18fbb
--- /dev/null
@@ -0,0 +1,79 @@
+NOTE   null subexpression matches : 2002-06-06
+
+E      (a*)*           a               (0,1)(0,1)
+#E     SAME            x               (0,0)(0,0)
+E      SAME            x               (0,0)(?,?)      RE2/Go
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+E      (a*)+           a               (0,1)(0,1)
+E      SAME            x               (0,0)(0,0)
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+E      (a+)*           a               (0,1)(0,1)
+E      SAME            x               (0,0)
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+E      (a+)+           a               (0,1)(0,1)
+E      SAME            x               NOMATCH
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+
+E      ([a]*)*         a               (0,1)(0,1)
+#E     SAME            x               (0,0)(0,0)
+E      SAME            x               (0,0)(?,?)      RE2/Go
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+E      ([a]*)+         a               (0,1)(0,1)
+E      SAME            x               (0,0)(0,0)
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaax         (0,6)(0,6)
+E      ([^b]*)*        a               (0,1)(0,1)
+#E     SAME            b               (0,0)(0,0)
+E      SAME            b               (0,0)(?,?)      RE2/Go
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            aaaaaab         (0,6)(0,6)
+E      ([ab]*)*        a               (0,1)(0,1)
+E      SAME            aaaaaa          (0,6)(0,6)
+E      SAME            ababab          (0,6)(0,6)
+E      SAME            bababa          (0,6)(0,6)
+E      SAME            b               (0,1)(0,1)
+E      SAME            bbbbbb          (0,6)(0,6)
+E      SAME            aaaabcde        (0,5)(0,5)
+E      ([^a]*)*        b               (0,1)(0,1)
+E      SAME            bbbbbb          (0,6)(0,6)
+#E     SAME            aaaaaa          (0,0)(0,0)
+E      SAME            aaaaaa          (0,0)(?,?)      RE2/Go
+E      ([^ab]*)*       ccccxx          (0,6)(0,6)
+#E     SAME            ababab          (0,0)(0,0)
+E      SAME            ababab          (0,0)(?,?)      RE2/Go
+
+E      ((z)+|a)*       zabcde          (0,2)(1,2)
+
+#{E    a+?             aaaaaa          (0,1)   no *? +? mimimal match ops
+#E     (a)             aaa             (0,1)(0,1)
+#E     (a*?)           aaa             (0,0)(0,0)
+#E     (a)*?           aaa             (0,0)
+#E     (a*?)*?         aaa             (0,0)
+#}
+
+B      \(a*\)*\(x\)            x       (0,1)(0,0)(0,1)
+B      \(a*\)*\(x\)            ax      (0,2)(0,1)(1,2)
+B      \(a*\)*\(x\)            axa     (0,2)(0,1)(1,2)
+B      \(a*\)*\(x\)\(\1\)      x       (0,1)(0,0)(0,1)(1,1)
+B      \(a*\)*\(x\)\(\1\)      ax      (0,2)(1,1)(1,2)(2,2)
+B      \(a*\)*\(x\)\(\1\)      axa     (0,3)(0,1)(1,2)(2,3)
+B      \(a*\)*\(x\)\(\1\)\(x\) axax    (0,4)(0,1)(1,2)(2,3)(3,4)
+B      \(a*\)*\(x\)\(\1\)\(x\) axxa    (0,3)(1,1)(1,2)(2,2)(2,3)
+
+#E     (a*)*(x)                x       (0,1)(0,0)(0,1)
+E      (a*)*(x)                x       (0,1)(?,?)(0,1) RE2/Go
+E      (a*)*(x)                ax      (0,2)(0,1)(1,2)
+E      (a*)*(x)                axa     (0,2)(0,1)(1,2)
+
+E      (a*)+(x)                x       (0,1)(0,0)(0,1)
+E      (a*)+(x)                ax      (0,2)(0,1)(1,2)
+E      (a*)+(x)                axa     (0,2)(0,1)(1,2)
+
+E      (a*){2}(x)              x       (0,1)(0,0)(0,1)
+E      (a*){2}(x)              ax      (0,2)(1,1)(1,2)
+E      (a*){2}(x)              axa     (0,2)(1,1)(1,2)
diff --git a/src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2 b/src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2
new file mode 100644 (file)
index 0000000..a357f28
Binary files /dev/null and b/src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2 differ
diff --git a/src/pkg/exp/regexp/testdata/re2-search.txt b/src/pkg/exp/regexp/testdata/re2-search.txt
new file mode 100644 (file)
index 0000000..f648e55
--- /dev/null
@@ -0,0 +1,3667 @@
+# RE2 basic search tests built by make log
+# Thu Sep 8 13:43:43 EDT 2011
+Regexp.SearchTests
+strings
+""
+"a"
+regexps
+"a"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"zyzzyva"
+regexps
+"a"
+-;-;-;-
+-;6-7;-;6-7
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;6-7;-;6-7
+strings
+""
+"aa"
+regexps
+"a+"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:a+)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:a+)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:a+)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+"ab"
+regexps
+"(a+|b)+"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+"^(?:(a+|b)+)$"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+"^(?:(a+|b)+)"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+"(?:(a+|b)+)$"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+strings
+""
+"xabcdx"
+regexps
+"ab|cd"
+-;-;-;-
+-;1-3;-;1-3
+"^(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+"^(?:ab|cd)"
+-;-;-;-
+-;-;-;-
+"(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"hello\ngoodbye\n"
+regexps
+"h.*od?"
+-;-;-;-
+-;0-5;-;0-5
+"^(?:h.*od?)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*od?)"
+-;-;-;-
+-;0-5;-;0-5
+"(?:h.*od?)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"hello\ngoodbye\n"
+regexps
+"h.*o"
+-;-;-;-
+-;0-5;-;0-5
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;0-5;-;0-5
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"goodbye\nhello\n"
+regexps
+"h.*o"
+-;-;-;-
+-;8-13;-;8-13
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;-;-;-
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"hello world"
+regexps
+"h.*o"
+-;-;-;-
+-;0-8;-;0-8
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;0-8;-;0-8
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"othello, world"
+regexps
+"h.*o"
+-;-;-;-
+-;2-11;-;2-11
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;-;-;-
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aaaaaaa"
+regexps
+"[^\\s\\S]"
+-;-;-;-
+-;-;-;-
+"^(?:[^\\s\\S])$"
+-;-;-;-
+-;-;-;-
+"^(?:[^\\s\\S])"
+-;-;-;-
+-;-;-;-
+"(?:[^\\s\\S])$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aaaaaaa"
+regexps
+"a"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:a)$"
+-;-;-;-
+-;6-7;-;6-7
+strings
+""
+"aaaaaaa"
+regexps
+"a*"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+"^(?:a*)$"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+"^(?:a*)"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+"(?:a*)$"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+strings
+""
+""
+regexps
+"a*"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"a*"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"xabcdx"
+regexps
+"ab|cd"
+-;-;-;-
+-;1-3;-;1-3
+"^(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+"^(?:ab|cd)"
+-;-;-;-
+-;-;-;-
+"(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"cab"
+regexps
+"a"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"cab"
+regexps
+"a*b"
+-;-;-;-
+-;1-3;-;1-3
+"^(?:a*b)$"
+-;-;-;-
+-;-;-;-
+"^(?:a*b)"
+-;-;-;-
+-;-;-;-
+"(?:a*b)$"
+-;-;-;-
+-;1-3;-;1-3
+strings
+""
+"x"
+regexps
+"((((((((((((((((((((x))))))))))))))))))))"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+"^(?:((((((((((((((((((((x)))))))))))))))))))))$"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+"^(?:((((((((((((((((((((x)))))))))))))))))))))"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+"(?:((((((((((((((((((((x)))))))))))))))))))))$"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+strings
+""
+"xxxabcdxxx"
+regexps
+"[abcd]"
+-;-;-;-
+-;3-4;-;3-4
+"^(?:[abcd])$"
+-;-;-;-
+-;-;-;-
+"^(?:[abcd])"
+-;-;-;-
+-;-;-;-
+"(?:[abcd])$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xxxabcdxxx"
+regexps
+"[^x]"
+-;-;-;-
+-;3-4;-;3-4
+"^(?:[^x])$"
+-;-;-;-
+-;-;-;-
+"^(?:[^x])"
+-;-;-;-
+-;-;-;-
+"(?:[^x])$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xxxabcdxxx"
+regexps
+"[abcd]+"
+-;-;-;-
+-;3-7;-;3-7
+"^(?:[abcd]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[abcd]+)"
+-;-;-;-
+-;-;-;-
+"(?:[abcd]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xxxabcdxxx"
+regexps
+"[^x]+"
+-;-;-;-
+-;3-7;-;3-7
+"^(?:[^x]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[^x]+)"
+-;-;-;-
+-;-;-;-
+"(?:[^x]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"(fo|foo)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:(fo|foo))$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:(fo|foo))"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:(fo|foo))$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"(foo|fo)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|fo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|fo))"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:(foo|fo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"aA"
+regexps
+"aa"
+-;-;-;-
+-;-;-;-
+"^(?:aa)$"
+-;-;-;-
+-;-;-;-
+"^(?:aa)"
+-;-;-;-
+-;-;-;-
+"(?:aa)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"Aa"
+regexps
+"a"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;1-2;-;1-2
+strings
+""
+"A"
+regexps
+"a"
+-;-;-;-
+-;-;-;-
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc"
+regexps
+"ABC"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)$"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)"
+-;-;-;-
+-;-;-;-
+"(?:ABC)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"XABCY"
+regexps
+"abc"
+-;-;-;-
+-;-;-;-
+"^(?:abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:abc)"
+-;-;-;-
+-;-;-;-
+"(?:abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xabcy"
+regexps
+"ABC"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)$"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)"
+-;-;-;-
+-;-;-;-
+"(?:ABC)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"foo|bar|[A-Z]"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:foo|bar|[A-Z])$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:foo|bar|[A-Z])"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:foo|bar|[A-Z])$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"foo"
+regexps
+"^(foo|bar|[A-Z])"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z]))"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"(foo|bar|[A-Z])$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])$)"
+-;-;-;-
+-;-;-;-
+"(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"(foo|bar|[A-Z])$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+-;-;-;-
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"bar"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"X"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+strings
+""
+"XY"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+-;-;-;-
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"^(fo|foo)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^(fo|foo)$)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"^(fo|foo)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(fo|foo)$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"fo"
+regexps
+"^^(fo|foo)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^^(fo|foo)$)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:^^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"^^(fo|foo)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^^(fo|foo)$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+""
+regexps
+"^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"^$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^$$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^^$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^^$$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^^^^^^^^$$$$$$$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^$$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^$$$$$$$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^^^^^^^$$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"^(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^)"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"$"
+0-0;0-0;0-0;0-0
+-;1-1;-;1-1
+"^(?:$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$)$"
+0-0;0-0;0-0;0-0
+-;1-1;-;1-1
+strings
+""
+"nofoo foo that"
+regexps
+"\\bfoo\\b"
+-;-;-;-
+-;6-9;-;6-9
+"^(?:\\bfoo\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bfoo\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bfoo\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"faoa x"
+regexps
+"a\\b"
+-;-;-;-
+-;3-4;-;3-4
+"^(?:a\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\b)"
+-;-;-;-
+-;-;-;-
+"(?:a\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"bar x"
+regexps
+"\\bbar"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bbar)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo\nbar x"
+regexps
+"\\bbar"
+-;-;-;-
+-;4-7;-;4-7
+"^(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bbar)"
+-;-;-;-
+-;-;-;-
+"(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foobar"
+regexps
+"bar\\b"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:bar\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\b)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\b)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"foobar\nxxx"
+regexps
+"bar\\b"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:bar\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\b)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:\\b)$"
+-;-;-;-
+-;1-1;-;1-1
+strings
+""
+"foo"
+regexps
+"\\b(foo|bar|[A-Z])"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z]))"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"X"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+strings
+""
+"XY"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"bar"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"ffoo bbar N x"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;10-11 10-11;-;10-11 10-11
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"\\b(fo|foo)\\b"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:\\b(fo|foo)\\b)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"\\b(fo|foo)\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(fo|foo)\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+""
+regexps
+"\\b\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\b\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:\\b\\b)$"
+-;-;-;-
+-;1-1;-;1-1
+strings
+""
+""
+regexps
+"\\b$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\b$"
+-;-;-;-
+-;1-1;-;1-1
+"^(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:\\b$)$"
+-;-;-;-
+-;1-1;-;1-1
+strings
+""
+"y x"
+regexps
+"\\b$"
+-;-;-;-
+-;3-3;-;3-3
+"^(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:\\b$)$"
+-;-;-;-
+-;3-3;-;3-3
+strings
+""
+"x"
+regexps
+"\\b.$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\b.$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"fo"
+regexps
+"^\\b(fo|foo)\\b"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^\\b(fo|foo)\\b)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"^\\b(fo|foo)\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^\\b(fo|foo)\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+""
+regexps
+"^\\b"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\b\\b"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b\\b)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\b$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b.$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:^\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"x"
+regexps
+"^\\b.\\b$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.\\b$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.\\b$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:^\\b.\\b$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+""
+regexps
+"^^^^^^^^\\b$$$$$$$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)"
+-;-;-;-
+-;-;-;-
+"(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\b.$$$$$$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^^^^^^^^\\b.$$$$$$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^^^^^^^^\\b.$$$$$$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:^^^^^^^^\\b.$$$$$$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\b$$$$$$$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)"
+-;-;-;-
+-;-;-;-
+"(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"n foo xfoox that"
+regexps
+"\\Bfoo\\B"
+-;-;-;-
+-;7-10;-;7-10
+"^(?:\\Bfoo\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bfoo\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bfoo\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"faoa x"
+regexps
+"a\\B"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:a\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\B)"
+-;-;-;-
+-;-;-;-
+"(?:a\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"bar x"
+regexps
+"\\Bbar"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo\nbar x"
+regexps
+"\\Bbar"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foobar"
+regexps
+"bar\\B"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foobar\nxxx"
+regexps
+"bar\\B"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foox"
+regexps
+"(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo\n"
+regexps
+"(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"\\B(foo|bar|[A-Z])"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z]))$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z]))"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z]))$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xXy"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-2 1-2;-;1-2 1-2
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"XY"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"XYZ"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-2 1-2;-;1-2 1-2
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abara"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-4 1-4;-;1-4 1-4
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfoo_"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-4 1-4;-;1-4 1-4
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfoo\n"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo bar vNx"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;9-10 9-10;-;9-10 9-10
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfoo"
+regexps
+"\\B(fo|foo)\\B"
+-;-;-;-
+-;1-3 1-3;-;1-3 1-3
+"^(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfooo"
+regexps
+"\\B(foo|fo)\\B"
+-;-;-;-
+-;1-4 1-4;-;1-4 1-4
+"^(?:\\B(foo|fo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|fo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|fo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"\\B\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"\\B\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"\\B$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"\\B$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"y x"
+regexps
+"\\B$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\B.$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B.$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B.$)"
+-;-;-;-
+-;-;-;-
+"(?:\\B.$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"^\\B(fo|foo)\\B"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"^\\B(fo|foo)\\B"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\B\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^\\B\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\B$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^\\B$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\B.$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B.$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\B.\\B$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.\\B$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.\\B$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B.\\B$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^^^^^^^^\\B$$$$$$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^\\B$$$$$$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\B.$$$$$$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\B.$$$$$$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\B.$$$$$$)"
+-;-;-;-
+-;-;-;-
+"(?:^^^^^^^^\\B.$$$$$$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\B$$$$$$$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^^^^^^^\\B$$$$$$$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\bx\\b"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\bx\\b)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\bx\\b)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\bx\\b)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"x>"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"<x"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;1-2;-;1-2
+strings
+""
+"<x>"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"ax"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xb"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"axb"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"«x"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;2-3;-;2-3
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;2-3;-;2-3
+strings
+""
+"x»"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"«x»"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;2-3;-;2-3
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"axb"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"áxβ"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;2-3;-;2-3
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"axb"
+regexps
+"\\Bx\\B"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bx\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"áxβ"
+regexps
+"\\Bx\\B"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bx\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\ny"
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\ny"
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\ny"
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\n\ny"
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\n\ny"
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\n\ny"
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"foo$bar"
+regexps
+"^(foo\\$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo\\$)$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo\\$)$)"
+-;-;-;-
+-;-;-;-
+"(?:^(foo\\$)$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo$bar"
+regexps
+"(foo\\$)"
+-;-;-;-
+-;0-4 0-4;-;0-4 0-4
+"^(?:(foo\\$))$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo\\$))"
+-;-;-;-
+-;0-4 0-4;-;0-4 0-4
+"(?:(foo\\$))$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc"
+regexps
+"^...$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^...$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^...$)"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:^...$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"本"
+regexps
+"^本$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^本$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^本$)"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:^本$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"日本語"
+regexps
+"^...$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+strings
+""
+".本."
+regexps
+"^...$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+strings
+""
+"本"
+regexps
+"^\\C\\C\\C$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^\\C\\C\\C$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^\\C\\C\\C$)"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:^\\C\\C\\C$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"本"
+regexps
+"^\\C$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\C$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"日本語"
+regexps
+"^\\C\\C\\C$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C\\C\\C$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C\\C\\C$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\C\\C\\C$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"日本語"
+regexps
+"^...$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+strings
+""
+"日本語"
+regexps
+"^.........$"
+-;-;-;-
+-;-;-;-
+"^(?:^.........$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^.........$)"
+-;-;-;-
+-;-;-;-
+"(?:^.........$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+".本."
+regexps
+"^...$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+strings
+""
+".本."
+regexps
+"^.....$"
+-;-;-;-
+-;-;-;-
+"^(?:^.....$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^.....$)"
+-;-;-;-
+-;-;-;-
+"(?:^.....$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfooo"
+regexps
+"\\B(fo|foo)\\B"
+-;-;-;-
+-;1-3 1-3;-;1-4 1-4
+"^(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"(fo|foo)"
+-;-;-;-
+0-3 0-3;0-2 0-2;0-3 0-3;0-3 0-3
+"^(?:(fo|foo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(fo|foo))"
+-;-;-;-
+0-3 0-3;0-2 0-2;0-3 0-3;0-3 0-3
+"(?:(fo|foo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"a"
+regexps
+"\\141"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\141)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\141)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\141)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"0"
+regexps
+"\\060"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\060)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\060)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\060)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"00"
+regexps
+"\\0600"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\0600)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\0600)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:\\0600)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+"08"
+regexps
+"\\608"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\608)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\608)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:\\608)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+"\ 1"
+regexps
+"\\01"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\01)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\01)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\01)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"\ 18"
+regexps
+"\\018"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\018)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\018)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:\\018)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+"a"
+regexps
+"\\x{61}"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{61})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{61})"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\x{61})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"\\x61"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x61)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x61)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\x61)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"\\x{00000061}"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{00000061})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{00000061})"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\x{00000061})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"aαβb"
+regexps
+"\\p{Greek}+"
+-;-;-;-
+-;1-5;-;1-5
+"^(?:\\p{Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{Greek}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\p{Greek}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aαβb"
+regexps
+"\\P{Greek}+"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\P{Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{Greek}+)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\P{Greek}+)$"
+-;-;-;-
+-;5-6;-;5-6
+strings
+""
+"aαβb"
+regexps
+"\\p{^Greek}+"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\p{^Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{^Greek}+)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\p{^Greek}+)$"
+-;-;-;-
+-;5-6;-;5-6
+strings
+""
+"aαβb"
+regexps
+"\\P{^Greek}+"
+-;-;-;-
+-;1-5;-;1-5
+"^(?:\\P{^Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{^Greek}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\P{^Greek}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123"
+regexps
+"[^0-9]+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:[^0-9]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[^0-9]+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:[^0-9]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{Nd}+"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:\\p{Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{Nd}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\p{Nd}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{^Nd}+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\p{^Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{^Nd}+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\p{^Nd}+)$"
+-;-;-;-
+-;6-22;-;6-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\P{Nd}+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\P{Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{Nd}+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\P{Nd}+)$"
+-;-;-;-
+-;6-22;-;6-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\P{^Nd}+"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:\\P{^Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{^Nd}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\P{^Nd}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\pN+"
+-;-;-;-
+-;3-22;-;3-22
+"^(?:\\pN+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\pN+)"
+-;-;-;-
+-;-;-;-
+"(?:\\pN+)$"
+-;-;-;-
+-;3-22;-;3-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{N}+"
+-;-;-;-
+-;3-22;-;3-22
+"^(?:\\p{N}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{N}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\p{N}+)$"
+-;-;-;-
+-;3-22;-;3-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{^N}+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\p{^N}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{^N}+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\p{^N}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123"
+regexps
+"\\p{Any}+"
+-;-;-;-
+0-6;0-6;0-6;0-6
+"^(?:\\p{Any}+)$"
+-;-;-;-
+0-6;0-6;0-6;0-6
+"^(?:\\p{Any}+)"
+-;-;-;-
+0-6;0-6;0-6;0-6
+"(?:\\p{Any}+)$"
+-;-;-;-
+0-6;0-6;0-6;0-6
+strings
+""
+"@AaB"
+regexps
+"(?i)[@-A]+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:(?i)[@-A]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?i)[@-A]+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:(?i)[@-A]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aAzZ"
+regexps
+"(?i)[A-Z]+"
+-;-;-;-
+0-4;0-4;0-4;0-4
+"^(?:(?i)[A-Z]+)$"
+-;-;-;-
+0-4;0-4;0-4;0-4
+"^(?:(?i)[A-Z]+)"
+-;-;-;-
+0-4;0-4;0-4;0-4
+"(?:(?i)[A-Z]+)$"
+-;-;-;-
+0-4;0-4;0-4;0-4
+strings
+""
+"Aa\\"
+regexps
+"(?i)[^\\\\]+"
+-;-;-;-
+-;0-2;-;0-2
+"^(?:(?i)[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?i)[^\\\\]+)"
+-;-;-;-
+-;0-2;-;0-2
+"(?:(?i)[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"acegikmoqsuwyACEGIKMOQSUWY"
+regexps
+"(?i)[acegikmoqsuwy]+"
+-;-;-;-
+0-26;0-26;0-26;0-26
+"^(?:(?i)[acegikmoqsuwy]+)$"
+-;-;-;-
+0-26;0-26;0-26;0-26
+"^(?:(?i)[acegikmoqsuwy]+)"
+-;-;-;-
+0-26;0-26;0-26;0-26
+"(?:(?i)[acegikmoqsuwy]+)$"
+-;-;-;-
+0-26;0-26;0-26;0-26
+strings
+""
+"@AaB"
+regexps
+"[@-A]+"
+-;-;-;-
+-;0-2;-;0-2
+"^(?:[@-A]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[@-A]+)"
+-;-;-;-
+-;0-2;-;0-2
+"(?:[@-A]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aAzZ"
+regexps
+"[A-Z]+"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:[A-Z]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[A-Z]+)"
+-;-;-;-
+-;-;-;-
+"(?:[A-Z]+)$"
+-;-;-;-
+-;3-4;-;3-4
+strings
+""
+"Aa\\"
+regexps
+"[^\\\\]+"
+-;-;-;-
+-;0-2;-;0-2
+"^(?:[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[^\\\\]+)"
+-;-;-;-
+-;0-2;-;0-2
+"(?:[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"acegikmoqsuwyACEGIKMOQSUWY"
+regexps
+"[acegikmoqsuwy]+"
+-;-;-;-
+-;0-13;-;0-13
+"^(?:[acegikmoqsuwy]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[acegikmoqsuwy]+)"
+-;-;-;-
+-;0-13;-;0-13
+"(?:[acegikmoqsuwy]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"^abc"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:^abc)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"^abc"
+-;-;-;-
+-;-;-;-
+"^(?:^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:^abc)"
+-;-;-;-
+-;-;-;-
+"(?:^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"^[ay]*[bx]+c"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:^[ay]*[bx]+c)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"^[ay]*[bx]+c"
+-;-;-;-
+-;0-4;-;0-4
+"^(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:^[ay]*[bx]+c)"
+-;-;-;-
+-;0-4;-;0-4
+"(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"def$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:def$)"
+-;-;-;-
+-;-;-;-
+"(?:def$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"def$"
+-;-;-;-
+-;-;-;-
+"^(?:def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:def$)"
+-;-;-;-
+-;-;-;-
+"(?:def$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"d[ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:d[ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"d[ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"[dz][ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"[dz][ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)^abc"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^abc)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"(?m)^abc"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^abc)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)^[ay]*[bx]+c"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^[ay]*[bx]+c)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"(?m)^[ay]*[bx]+c"
+-;-;-;-
+-;0-4;-;0-4
+"^(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^[ay]*[bx]+c)"
+-;-;-;-
+-;0-4;-;0-4
+"(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)def$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:(?m)def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)def$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)def$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"(?m)def$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)def$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)def$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)d[ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"(?m)d[ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)[dz][ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"(?m)[dz][ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"a"
+regexps
+"^"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"^(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^)"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"a"
+regexps
+"^^"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"^(?:^^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^)"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"(?:^^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"a"
+regexps
+"a"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"ab*"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:ab*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:ab*)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:ab*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"a\\C*"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C*)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a\\C*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"baba"
+regexps
+"a\\C*|ba\\C"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:a\\C*|ba\\C)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\C*|ba\\C)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:a\\C*|ba\\C)$"
+-;-;-;-
+-;1-4;-;1-4
diff --git a/src/pkg/exp/regexp/testdata/repetition.dat b/src/pkg/exp/regexp/testdata/repetition.dat
new file mode 100644 (file)
index 0000000..e6361f5
--- /dev/null
@@ -0,0 +1,163 @@
+NOTE   implicit vs. explicit repetitions : 2009-02-02
+
+# Glenn Fowler <gsf@research.att.com>
+# conforming matches (column 4) must match one of the following BREs
+#      NOMATCH
+#      (0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)*
+#      (0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)*
+# i.e., each 3-tuple has two identical elements and one (?,?)
+
+E      ((..)|(.))                              NULL            NOMATCH
+E      ((..)|(.))((..)|(.))                    NULL            NOMATCH
+E      ((..)|(.))((..)|(.))((..)|(.))          NULL            NOMATCH
+
+E      ((..)|(.)){1}                           NULL            NOMATCH
+E      ((..)|(.)){2}                           NULL            NOMATCH
+E      ((..)|(.)){3}                           NULL            NOMATCH
+
+E      ((..)|(.))*                             NULL            (0,0)
+
+E      ((..)|(.))                              a               (0,1)(0,1)(?,?)(0,1)
+E      ((..)|(.))((..)|(.))                    a               NOMATCH
+E      ((..)|(.))((..)|(.))((..)|(.))          a               NOMATCH
+
+E      ((..)|(.)){1}                           a               (0,1)(0,1)(?,?)(0,1)
+E      ((..)|(.)){2}                           a               NOMATCH
+E      ((..)|(.)){3}                           a               NOMATCH
+
+E      ((..)|(.))*                             a               (0,1)(0,1)(?,?)(0,1)
+
+E      ((..)|(.))                              aa              (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.))((..)|(.))                    aa              (0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)
+E      ((..)|(.))((..)|(.))((..)|(.))          aa              NOMATCH
+
+E      ((..)|(.)){1}                           aa              (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.)){2}                           aa              (0,2)(1,2)(?,?)(1,2)
+E      ((..)|(.)){3}                           aa              NOMATCH
+
+E      ((..)|(.))*                             aa              (0,2)(0,2)(0,2)(?,?)
+
+E      ((..)|(.))                              aaa             (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.))((..)|(.))                    aaa             (0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)
+E      ((..)|(.))((..)|(.))((..)|(.))          aaa             (0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3)
+
+E      ((..)|(.)){1}                           aaa             (0,2)(0,2)(0,2)(?,?)
+#E     ((..)|(.)){2}                           aaa             (0,3)(2,3)(?,?)(2,3)
+E      ((..)|(.)){2}                           aaa             (0,3)(2,3)(0,2)(2,3)    RE2/Go
+E      ((..)|(.)){3}                           aaa             (0,3)(2,3)(?,?)(2,3)
+
+#E     ((..)|(.))*                             aaa             (0,3)(2,3)(?,?)(2,3)
+E      ((..)|(.))*                             aaa             (0,3)(2,3)(0,2)(2,3)    RE2/Go
+
+E      ((..)|(.))                              aaaa            (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.))((..)|(.))                    aaaa            (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E      ((..)|(.))((..)|(.))((..)|(.))          aaaa            (0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4)
+
+E      ((..)|(.)){1}                           aaaa            (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.)){2}                           aaaa            (0,4)(2,4)(2,4)(?,?)
+#E     ((..)|(.)){3}                           aaaa            (0,4)(3,4)(?,?)(3,4)
+E      ((..)|(.)){3}                           aaaa            (0,4)(3,4)(0,2)(3,4)    RE2/Go
+
+E      ((..)|(.))*                             aaaa            (0,4)(2,4)(2,4)(?,?)
+
+E      ((..)|(.))                              aaaaa           (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.))((..)|(.))                    aaaaa           (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E      ((..)|(.))((..)|(.))((..)|(.))          aaaaa           (0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5)
+
+E      ((..)|(.)){1}                           aaaaa           (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.)){2}                           aaaaa           (0,4)(2,4)(2,4)(?,?)
+#E     ((..)|(.)){3}                           aaaaa           (0,5)(4,5)(?,?)(4,5)
+E      ((..)|(.)){3}                           aaaaa           (0,5)(4,5)(2,4)(4,5)    RE2/Go
+
+#E     ((..)|(.))*                             aaaaa           (0,5)(4,5)(?,?)(4,5)
+E      ((..)|(.))*                             aaaaa           (0,5)(4,5)(2,4)(4,5)    RE2/Go
+
+E      ((..)|(.))                              aaaaaa          (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.))((..)|(.))                    aaaaaa          (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E      ((..)|(.))((..)|(.))((..)|(.))          aaaaaa          (0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?)
+
+E      ((..)|(.)){1}                           aaaaaa          (0,2)(0,2)(0,2)(?,?)
+E      ((..)|(.)){2}                           aaaaaa          (0,4)(2,4)(2,4)(?,?)
+E      ((..)|(.)){3}                           aaaaaa          (0,6)(4,6)(4,6)(?,?)
+
+E      ((..)|(.))*                             aaaaaa          (0,6)(4,6)(4,6)(?,?)
+
+NOTE   additional repetition tests graciously provided by Chris Kuklewicz www.haskell.org 2009-02-02
+
+# These test a bug in OS X / FreeBSD / NetBSD, and libtree. 
+# Linux/GLIBC gets the {8,} and {8,8} wrong.
+
+:HA#100:E      X(.?){0,}Y      X1234567Y       (0,9)(7,8)
+:HA#101:E      X(.?){1,}Y      X1234567Y       (0,9)(7,8)
+:HA#102:E      X(.?){2,}Y      X1234567Y       (0,9)(7,8)
+:HA#103:E      X(.?){3,}Y      X1234567Y       (0,9)(7,8)
+:HA#104:E      X(.?){4,}Y      X1234567Y       (0,9)(7,8)
+:HA#105:E      X(.?){5,}Y      X1234567Y       (0,9)(7,8)
+:HA#106:E      X(.?){6,}Y      X1234567Y       (0,9)(7,8)
+:HA#107:E      X(.?){7,}Y      X1234567Y       (0,9)(7,8)
+:HA#108:E      X(.?){8,}Y      X1234567Y       (0,9)(8,8)
+#:HA#110:E     X(.?){0,8}Y     X1234567Y       (0,9)(7,8)
+:HA#110:E      X(.?){0,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#111:E     X(.?){1,8}Y     X1234567Y       (0,9)(7,8)
+:HA#111:E      X(.?){1,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#112:E     X(.?){2,8}Y     X1234567Y       (0,9)(7,8)
+:HA#112:E      X(.?){2,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#113:E     X(.?){3,8}Y     X1234567Y       (0,9)(7,8)
+:HA#113:E      X(.?){3,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#114:E     X(.?){4,8}Y     X1234567Y       (0,9)(7,8)
+:HA#114:E      X(.?){4,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#115:E     X(.?){5,8}Y     X1234567Y       (0,9)(7,8)
+:HA#115:E      X(.?){5,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#116:E     X(.?){6,8}Y     X1234567Y       (0,9)(7,8)
+:HA#116:E      X(.?){6,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+#:HA#117:E     X(.?){7,8}Y     X1234567Y       (0,9)(7,8)
+:HA#117:E      X(.?){7,8}Y     X1234567Y       (0,9)(8,8)      RE2/Go
+:HA#118:E      X(.?){8,8}Y     X1234567Y       (0,9)(8,8)
+
+# These test a fixed bug in my regex-tdfa that did not keep the expanded
+# form properly grouped, so right association did the wrong thing with
+# these ambiguous patterns (crafted just to test my code when I became
+# suspicious of my implementation).  The first subexpression should use
+# "ab" then "a" then "bcd".
+
+# OS X / FreeBSD / NetBSD badly fail many of these, with impossible
+# results like (0,6)(4,5)(6,6).
+
+:HA#260:E      (a|ab|c|bcd){0,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#261:E      (a|ab|c|bcd){1,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#262:E      (a|ab|c|bcd){2,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#263:E      (a|ab|c|bcd){3,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#264:E      (a|ab|c|bcd){4,}(d*)    ababcd  NOMATCH
+:HA#265:E      (a|ab|c|bcd){0,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#266:E      (a|ab|c|bcd){1,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#267:E      (a|ab|c|bcd){2,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#268:E      (a|ab|c|bcd){3,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#269:E      (a|ab|c|bcd){4,10}(d*)  ababcd  NOMATCH
+:HA#270:E      (a|ab|c|bcd)*(d*)       ababcd  (0,6)(3,6)(6,6)
+:HA#271:E      (a|ab|c|bcd)+(d*)       ababcd  (0,6)(3,6)(6,6)
+
+# The above worked on Linux/GLIBC but the following often fail.
+# They also trip up OS X / FreeBSD / NetBSD:
+
+#:HA#280:E     (ab|a|c|bcd){0,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#280:E      (ab|a|c|bcd){0,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#281:E     (ab|a|c|bcd){1,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#281:E      (ab|a|c|bcd){1,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#282:E     (ab|a|c|bcd){2,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#282:E      (ab|a|c|bcd){2,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#283:E     (ab|a|c|bcd){3,}(d*)    ababcd  (0,6)(3,6)(6,6)
+:HA#283:E      (ab|a|c|bcd){3,}(d*)    ababcd  (0,6)(4,5)(5,6) RE2/Go
+:HA#284:E      (ab|a|c|bcd){4,}(d*)    ababcd  NOMATCH
+#:HA#285:E     (ab|a|c|bcd){0,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#285:E      (ab|a|c|bcd){0,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#286:E     (ab|a|c|bcd){1,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#286:E      (ab|a|c|bcd){1,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#287:E     (ab|a|c|bcd){2,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#287:E      (ab|a|c|bcd){2,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#288:E     (ab|a|c|bcd){3,10}(d*)  ababcd  (0,6)(3,6)(6,6)
+:HA#288:E      (ab|a|c|bcd){3,10}(d*)  ababcd  (0,6)(4,5)(5,6) RE2/Go
+:HA#289:E      (ab|a|c|bcd){4,10}(d*)  ababcd  NOMATCH
+#:HA#290:E     (ab|a|c|bcd)*(d*)       ababcd  (0,6)(3,6)(6,6)
+:HA#290:E      (ab|a|c|bcd)*(d*)       ababcd  (0,6)(4,5)(5,6) RE2/Go
+#:HA#291:E     (ab|a|c|bcd)+(d*)       ababcd  (0,6)(3,6)(6,6)
+:HA#291:E      (ab|a|c|bcd)+(d*)       ababcd  (0,6)(4,5)(5,6) RE2/Go
diff --git a/src/pkg/exp/regexp/testdata/testregex.c b/src/pkg/exp/regexp/testdata/testregex.c
new file mode 100644 (file)
index 0000000..37545d0
--- /dev/null
@@ -0,0 +1,2286 @@
+#pragma prototyped noticed
+
+/*
+ * regex(3) test harness
+ *
+ * build:      cc -o testregex testregex.c
+ * help:       testregex --man
+ * note:       REG_* features are detected by #ifdef; if REG_* are enums
+ *             then supply #define REG_foo REG_foo for each enum REG_foo
+ *
+ *     Glenn Fowler <gsf@research.att.com>
+ *     AT&T Research
+ *
+ * PLEASE: publish your tests so everyone can benefit
+ *
+ * The following license covers testregex.c and all associated test data.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following disclaimer:
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL AT&T BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+static const char id[] = "\n@(#)$Id: testregex (AT&T Research) 2010-06-10 $\0\n";
+
+#if _PACKAGE_ast
+#include <ast.h>
+#else
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+#include <regex.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __STDC__
+#include <stdlib.h>
+#include <locale.h>
+#endif
+
+#ifndef RE_DUP_MAX
+#define RE_DUP_MAX     32767
+#endif
+
+#if !_PACKAGE_ast
+#undef REG_DISCIPLINE
+#endif
+
+#ifndef REG_DELIMITED
+#undef _REG_subcomp
+#endif
+
+#define TEST_ARE               0x00000001
+#define TEST_BRE               0x00000002
+#define TEST_ERE               0x00000004
+#define TEST_KRE               0x00000008
+#define TEST_LRE               0x00000010
+#define TEST_SRE               0x00000020
+
+#define TEST_EXPAND            0x00000100
+#define TEST_LENIENT           0x00000200
+
+#define TEST_QUERY             0x00000400
+#define TEST_SUB               0x00000800
+#define TEST_UNSPECIFIED       0x00001000
+#define TEST_VERIFY            0x00002000
+#define TEST_AND               0x00004000
+#define TEST_OR                        0x00008000
+
+#define TEST_DELIMIT           0x00010000
+#define TEST_OK                        0x00020000
+#define TEST_SAME              0x00040000
+
+#define TEST_ACTUAL            0x00100000
+#define TEST_BASELINE          0x00200000
+#define TEST_FAIL              0x00400000
+#define TEST_PASS              0x00800000
+#define TEST_SUMMARY           0x01000000
+
+#define TEST_IGNORE_ERROR      0x02000000
+#define TEST_IGNORE_OVER       0x04000000
+#define TEST_IGNORE_POSITION   0x08000000
+
+#define TEST_CATCH             0x10000000
+#define TEST_VERBOSE           0x20000000
+
+#define TEST_DECOMP            0x40000000
+
+#define TEST_GLOBAL            (TEST_ACTUAL|TEST_AND|TEST_BASELINE|TEST_CATCH|TEST_FAIL|TEST_IGNORE_ERROR|TEST_IGNORE_OVER|TEST_IGNORE_POSITION|TEST_OR|TEST_PASS|TEST_SUMMARY|TEST_VERBOSE)
+
+#ifdef REG_DISCIPLINE
+
+
+#include <stk.h>
+
+typedef struct Disc_s
+{
+       regdisc_t       disc;
+       int             ordinal;
+       Sfio_t*         sp;
+} Disc_t;
+
+static void*
+compf(const regex_t* re, const char* xstr, size_t xlen, regdisc_t* disc)
+{
+       Disc_t*         dp = (Disc_t*)disc;
+
+       return (void*)((char*)0 + ++dp->ordinal);
+}
+
+static int
+execf(const regex_t* re, void* data, const char* xstr, size_t xlen, const char* sstr, size_t slen, char** snxt, regdisc_t* disc)
+{
+       Disc_t*         dp = (Disc_t*)disc;
+
+       sfprintf(dp->sp, "{%-.*s}(%lu:%d)", xlen, xstr, (char*)data - (char*)0, slen);
+       return atoi(xstr);
+}
+
+static void*
+resizef(void* handle, void* data, size_t size)
+{
+       if (!size)
+               return 0;
+       return stkalloc((Sfio_t*)handle, size);
+}
+
+#endif
+
+#ifndef NiL
+#ifdef __STDC__
+#define NiL            0
+#else
+#define NiL            (char*)0
+#endif
+#endif
+
+#define H(x)           do{if(html)fprintf(stderr,x);}while(0)
+#define T(x)           fprintf(stderr,x)
+
+static void
+help(int html)
+{
+H("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n");
+H("<HTML>\n");
+H("<HEAD>\n");
+H("<TITLE>testregex man document</TITLE>\n");
+H("</HEAD>\n");
+H("<BODY bgcolor=white>\n");
+H("<PRE>\n");
+T("NAME\n");
+T("  testregex - regex(3) test harness\n");
+T("\n");
+T("SYNOPSIS\n");
+T("  testregex [ options ]\n");
+T("\n");
+T("DESCRIPTION\n");
+T("  testregex reads regex(3) test specifications, one per line, from the\n");
+T("  standard input and writes one output line for each failed test. A\n");
+T("  summary line is written after all tests are done. Each successful\n");
+T("  test is run again with REG_NOSUB. Unsupported features are noted\n");
+T("  before the first test, and tests requiring these features are\n");
+T("  silently ignored.\n");
+T("\n");
+T("OPTIONS\n");
+T("  -c        catch signals and non-terminating calls\n");
+T("  -e        ignore error return mismatches\n");
+T("  -h        list help on standard error\n");
+T("  -n        do not repeat successful tests with regnexec()\n");
+T("  -o        ignore match[] overrun errors\n");
+T("  -p        ignore negative position mismatches\n");
+T("  -s        use stack instead of malloc\n");
+T("  -x        do not repeat successful tests with REG_NOSUB\n");
+T("  -v        list each test line\n");
+T("  -A        list failed test lines with actual answers\n");
+T("  -B        list all test lines with actual answers\n");
+T("  -F        list failed test lines\n");
+T("  -P        list passed test lines\n");
+T("  -S        output one summary line\n");
+T("\n");
+T("INPUT FORMAT\n");
+T("  Input lines may be blank, a comment beginning with #, or a test\n");
+T("  specification. A specification is five fields separated by one\n");
+T("  or more tabs. NULL denotes the empty string and NIL denotes the\n");
+T("  0 pointer.\n");
+T("\n");
+T("  Field 1: the regex(3) flags to apply, one character per REG_feature\n");
+T("  flag. The test is skipped if REG_feature is not supported by the\n");
+T("  implementation. If the first character is not [BEASKLP] then the\n");
+T("  specification is a global control line. One or more of [BEASKLP] may be\n");
+T("  specified; the test will be repeated for each mode.\n");
+T("\n");
+T("    B       basic                   BRE     (grep, ed, sed)\n");
+T("    E       REG_EXTENDED            ERE     (egrep)\n");
+T("    A       REG_AUGMENTED           ARE     (egrep with negation)\n");
+T("    S       REG_SHELL               SRE     (sh glob)\n");
+T("    K       REG_SHELL|REG_AUGMENTED KRE     (ksh glob)\n");
+T("    L       REG_LITERAL             LRE     (fgrep)\n");
+T("\n");
+T("    a       REG_LEFT|REG_RIGHT      implicit ^...$\n");
+T("    b       REG_NOTBOL              lhs does not match ^\n");
+T("    c       REG_COMMENT             ignore space and #...\\n\n");
+T("    d       REG_SHELL_DOT           explicit leading . match\n");
+T("    e       REG_NOTEOL              rhs does not match $\n");
+T("    f       REG_MULTIPLE            multiple \\n separated patterns\n");
+T("    g       FNM_LEADING_DIR         testfnmatch only -- match until /\n");
+T("    h       REG_MULTIREF            multiple digit backref\n");
+T("    i       REG_ICASE               ignore case\n");
+T("    j       REG_SPAN                . matches \\n\n");
+T("    k       REG_ESCAPE              \\ to ecape [...] delimiter\n");
+T("    l       REG_LEFT                implicit ^...\n");
+T("    m       REG_MINIMAL             minimal match\n");
+T("    n       REG_NEWLINE             explicit \\n match\n");
+T("    o       REG_ENCLOSED            (|&) magic inside [@|&](...)\n");
+T("    p       REG_SHELL_PATH          explicit / match\n");
+T("    q       REG_DELIMITED           delimited pattern\n");
+T("    r       REG_RIGHT               implicit ...$\n");
+T("    s       REG_SHELL_ESCAPED       \\ not special\n");
+T("    t       REG_MUSTDELIM           all delimiters must be specified\n");
+T("    u       standard unspecified behavior -- errors not counted\n");
+T("    v       REG_CLASS_ESCAPE        \\ special inside [...]\n");
+T("    w       REG_NOSUB               no subexpression match array\n");
+T("    x       REG_LENIENT             let some errors slide\n");
+T("    y       REG_LEFT                regexec() implicit ^...\n");
+T("    z       REG_NULL                NULL subexpressions ok\n");
+T("    $                               expand C \\c escapes in fields 2 and 3\n");
+T("    /                               field 2 is a regsubcomp() expression\n");
+T("    =                               field 3 is a regdecomp() expression\n");
+T("\n");
+T("  Field 1 control lines:\n");
+T("\n");
+T("    C               set LC_COLLATE and LC_CTYPE to locale in field 2\n");
+T("\n");
+T("    ?test ...       output field 5 if passed and != EXPECTED, silent otherwise\n");
+T("    &test ...       output field 5 if current and previous passed\n");
+T("    |test ...       output field 5 if current passed and previous failed\n");
+T("    ; ...   output field 2 if previous failed\n");
+T("    {test ...       skip if failed until }\n");
+T("    }               end of skip\n");
+T("\n");
+T("    : comment               comment copied as output NOTE\n");
+T("    :comment:test   :comment: ignored\n");
+T("    N[OTE] comment  comment copied as output NOTE\n");
+T("    T[EST] comment  comment\n");
+T("\n");
+T("    number          use number for nmatch (20 by default)\n");
+T("\n");
+T("  Field 2: the regular expression pattern; SAME uses the pattern from\n");
+T("    the previous specification. RE_DUP_MAX inside {...} expands to the\n");
+T("    value from <limits.h>.\n");
+T("\n");
+T("  Field 3: the string to match. X...{RE_DUP_MAX} expands to RE_DUP_MAX\n");
+T("    copies of X.\n");
+T("\n");
+T("  Field 4: the test outcome. This is either one of the posix error\n");
+T("    codes (with REG_ omitted) or the match array, a list of (m,n)\n");
+T("    entries with m and n being first and last+1 positions in the\n");
+T("    field 3 string, or NULL if REG_NOSUB is in effect and success\n");
+T("    is expected. BADPAT is acceptable in place of any regcomp(3)\n");
+T("    error code. The match[] array is initialized to (-2,-2) before\n");
+T("    each test. All array elements from 0 to nmatch-1 must be specified\n");
+T("    in the outcome. Unspecified endpoints (offset -1) are denoted by ?.\n");
+T("    Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a\n");
+T("    matched (?{...}) expression, where x is the text enclosed by {...},\n");
+T("    o is the expression ordinal counting from 1, and n is the length of\n");
+T("    the unmatched portion of the subject string. If x starts with a\n");
+T("    number then that is the return value of re_execf(), otherwise 0 is\n");
+T("    returned. RE_DUP_MAX[-+]N expands to the <limits.h> value -+N.\n");
+T("\n");
+T("  Field 5: optional comment appended to the report.\n");
+T("\n");
+T("CAVEAT\n");
+T("    If a regex implementation misbehaves with memory then all bets are off.\n");
+T("\n");
+T("CONTRIBUTORS\n");
+T("  Glenn Fowler    gsf@research.att.com        (ksh strmatch, regex extensions)\n");
+T("  David Korn      dgk@research.att.com        (ksh glob matcher)\n");
+T("  Doug McIlroy    mcilroy@dartmouth.edu       (ast regex/testre in C++)\n");
+T("  Tom Lord        lord@regexps.com            (rx tests)\n");
+T("  Henry Spencer   henry@zoo.toronto.edu       (original public regex)\n");
+T("  Andrew Hume     andrew@research.att.com     (gre tests)\n");
+T("  John Maddock    John_Maddock@compuserve.com (regex++ tests)\n");
+T("  Philip Hazel    ph10@cam.ac.uk              (pcre tests)\n");
+T("  Ville Laurikari vl@iki.fi                   (libtre tests)\n");
+H("</PRE>\n");
+H("</BODY>\n");
+H("</HTML>\n");
+}
+
+#ifndef elementsof
+#define elementsof(x)  (sizeof(x)/sizeof(x[0]))
+#endif
+
+#ifndef streq
+#define streq(a,b)     (*(a)==*(b)&&!strcmp(a,b))
+#endif
+
+#define HUNG           2
+#define NOTEST         (~0)
+
+#ifndef REG_TEST_DEFAULT
+#define REG_TEST_DEFAULT       0
+#endif
+
+#ifndef REG_EXEC_DEFAULT
+#define REG_EXEC_DEFAULT       0
+#endif
+
+static const char* unsupported[] =
+{
+       "BASIC",
+#ifndef REG_EXTENDED
+       "EXTENDED",
+#endif
+#ifndef REG_AUGMENTED
+       "AUGMENTED",
+#endif
+#ifndef REG_SHELL
+       "SHELL",
+#endif
+
+#ifndef REG_CLASS_ESCAPE
+       "CLASS_ESCAPE",
+#endif
+#ifndef REG_COMMENT
+       "COMMENT",
+#endif
+#ifndef REG_DELIMITED
+       "DELIMITED",
+#endif
+#ifndef REG_DISCIPLINE
+       "DISCIPLINE",
+#endif
+#ifndef REG_ESCAPE
+       "ESCAPE",
+#endif
+#ifndef REG_ICASE
+       "ICASE",
+#endif
+#ifndef REG_LEFT
+       "LEFT",
+#endif
+#ifndef REG_LENIENT
+       "LENIENT",
+#endif
+#ifndef REG_LITERAL
+       "LITERAL",
+#endif
+#ifndef REG_MINIMAL
+       "MINIMAL",
+#endif
+#ifndef REG_MULTIPLE
+       "MULTIPLE",
+#endif
+#ifndef REG_MULTIREF
+       "MULTIREF",
+#endif
+#ifndef REG_MUSTDELIM
+       "MUSTDELIM",
+#endif
+#ifndef REG_NEWLINE
+       "NEWLINE",
+#endif
+#ifndef REG_NOTBOL
+       "NOTBOL",
+#endif
+#ifndef REG_NOTEOL
+       "NOTEOL",
+#endif
+#ifndef REG_NULL
+       "NULL",
+#endif
+#ifndef REG_RIGHT
+       "RIGHT",
+#endif
+#ifndef REG_SHELL_DOT
+       "SHELL_DOT",
+#endif
+#ifndef REG_SHELL_ESCAPED
+       "SHELL_ESCAPED",
+#endif
+#ifndef REG_SHELL_GROUP
+       "SHELL_GROUP",
+#endif
+#ifndef REG_SHELL_PATH
+       "SHELL_PATH",
+#endif
+#ifndef REG_SPAN
+       "SPAN",
+#endif
+#if REG_NOSUB & REG_TEST_DEFAULT
+       "SUBMATCH",
+#endif
+#if !_REG_nexec
+       "regnexec",
+#endif
+#if !_REG_subcomp
+       "regsubcomp",
+#endif
+#if !_REG_decomp
+       "redecomp",
+#endif
+       0
+};
+
+#ifndef REG_CLASS_ESCAPE
+#define REG_CLASS_ESCAPE       NOTEST
+#endif
+#ifndef REG_COMMENT
+#define REG_COMMENT    NOTEST
+#endif
+#ifndef REG_DELIMITED
+#define REG_DELIMITED  NOTEST
+#endif
+#ifndef REG_ESCAPE
+#define REG_ESCAPE     NOTEST
+#endif
+#ifndef REG_ICASE
+#define REG_ICASE      NOTEST
+#endif
+#ifndef REG_LEFT
+#define REG_LEFT       NOTEST
+#endif
+#ifndef REG_LENIENT
+#define REG_LENIENT    0
+#endif
+#ifndef REG_MINIMAL
+#define REG_MINIMAL    NOTEST
+#endif
+#ifndef REG_MULTIPLE
+#define REG_MULTIPLE   NOTEST
+#endif
+#ifndef REG_MULTIREF
+#define REG_MULTIREF   NOTEST
+#endif
+#ifndef REG_MUSTDELIM
+#define REG_MUSTDELIM  NOTEST
+#endif
+#ifndef REG_NEWLINE
+#define REG_NEWLINE    NOTEST
+#endif
+#ifndef REG_NOTBOL
+#define REG_NOTBOL     NOTEST
+#endif
+#ifndef REG_NOTEOL
+#define REG_NOTEOL     NOTEST
+#endif
+#ifndef REG_NULL
+#define REG_NULL       NOTEST
+#endif
+#ifndef REG_RIGHT
+#define REG_RIGHT      NOTEST
+#endif
+#ifndef REG_SHELL_DOT
+#define REG_SHELL_DOT  NOTEST
+#endif
+#ifndef REG_SHELL_ESCAPED
+#define REG_SHELL_ESCAPED      NOTEST
+#endif
+#ifndef REG_SHELL_GROUP
+#define REG_SHELL_GROUP        NOTEST
+#endif
+#ifndef REG_SHELL_PATH
+#define REG_SHELL_PATH NOTEST
+#endif
+#ifndef REG_SPAN
+#define REG_SPAN       NOTEST
+#endif
+
+#define REG_UNKNOWN    (-1)
+
+#ifndef REG_ENEWLINE
+#define REG_ENEWLINE   (REG_UNKNOWN-1)
+#endif
+#ifndef REG_ENULL
+#ifndef REG_EMPTY
+#define REG_ENULL      (REG_UNKNOWN-2)
+#else
+#define REG_ENULL      REG_EMPTY
+#endif
+#endif
+#ifndef REG_ECOUNT
+#define REG_ECOUNT     (REG_UNKNOWN-3)
+#endif
+#ifndef REG_BADESC
+#define REG_BADESC     (REG_UNKNOWN-4)
+#endif
+#ifndef REG_EMEM
+#define REG_EMEM       (REG_UNKNOWN-5)
+#endif
+#ifndef REG_EHUNG
+#define REG_EHUNG      (REG_UNKNOWN-6)
+#endif
+#ifndef REG_EBUS
+#define REG_EBUS       (REG_UNKNOWN-7)
+#endif
+#ifndef REG_EFAULT
+#define REG_EFAULT     (REG_UNKNOWN-8)
+#endif
+#ifndef REG_EFLAGS
+#define REG_EFLAGS     (REG_UNKNOWN-9)
+#endif
+#ifndef REG_EDELIM
+#define REG_EDELIM     (REG_UNKNOWN-9)
+#endif
+
+static const struct { int code; char* name; } codes[] =
+{
+       REG_UNKNOWN,    "UNKNOWN",
+       REG_NOMATCH,    "NOMATCH",
+       REG_BADPAT,     "BADPAT",
+       REG_ECOLLATE,   "ECOLLATE",
+       REG_ECTYPE,     "ECTYPE",
+       REG_EESCAPE,    "EESCAPE",
+       REG_ESUBREG,    "ESUBREG",
+       REG_EBRACK,     "EBRACK",
+       REG_EPAREN,     "EPAREN",
+       REG_EBRACE,     "EBRACE",
+       REG_BADBR,      "BADBR",
+       REG_ERANGE,     "ERANGE",
+       REG_ESPACE,     "ESPACE",
+       REG_BADRPT,     "BADRPT",
+       REG_ENEWLINE,   "ENEWLINE",
+       REG_ENULL,      "ENULL",
+       REG_ECOUNT,     "ECOUNT",
+       REG_BADESC,     "BADESC",
+       REG_EMEM,       "EMEM",
+       REG_EHUNG,      "EHUNG",
+       REG_EBUS,       "EBUS",
+       REG_EFAULT,     "EFAULT",
+       REG_EFLAGS,     "EFLAGS",
+       REG_EDELIM,     "EDELIM",
+};
+
+static struct
+{
+       regmatch_t      NOMATCH;
+       int             errors;
+       int             extracted;
+       int             ignored;
+       int             lineno;
+       int             passed;
+       int             signals;
+       int             unspecified;
+       int             verify;
+       int             warnings;
+       char*           file;
+       char*           stack;
+       char*           which;
+       jmp_buf         gotcha;
+#ifdef REG_DISCIPLINE
+       Disc_t          disc;
+#endif
+} state;
+
+static void
+quote(char* s, int len, unsigned long test)
+{
+       unsigned char*  u = (unsigned char*)s;
+       unsigned char*  e;
+       int             c;
+#ifdef MB_CUR_MAX
+       int             w;
+#endif
+
+       if (!u)
+               printf("NIL");
+       else if (!*u && len <= 1)
+               printf("NULL");
+       else if (test & TEST_EXPAND)
+       {
+               if (len < 0)
+                       len = strlen((char*)u);
+               e = u + len;
+               if (test & TEST_DELIMIT)
+                       printf("\"");
+               while (u < e)
+                       switch (c = *u++)
+                       {
+                       case '\\':
+                               printf("\\\\");
+                               break;
+                       case '"':
+                               if (test & TEST_DELIMIT)
+                                       printf("\\\"");
+                               else
+                                       printf("\"");
+                               break;
+                       case '\a':
+                               printf("\\a");
+                               break;
+                       case '\b':
+                               printf("\\b");
+                               break;
+                       case 033:
+                               printf("\\e");
+                               break;
+                       case '\f':
+                               printf("\\f");
+                               break;
+                       case '\n':
+                               printf("\\n");
+                               break;
+                       case '\r':
+                               printf("\\r");
+                               break;
+                       case '\t':
+                               printf("\\t");
+                               break;
+                       case '\v':
+                               printf("\\v");
+                               break;
+                       default:
+#ifdef MB_CUR_MAX
+                               s = (char*)u - 1;
+                               if ((w = mblen(s, (char*)e - s)) > 1)
+                               {
+                                       u += w - 1;
+                                       fwrite(s, 1, w, stdout);
+                               }
+                               else
+#endif
+                               if (!iscntrl(c) && isprint(c))
+                                       putchar(c);
+                               else
+                                       printf("\\x%02x", c);
+                               break;
+                       }
+               if (test & TEST_DELIMIT)
+                       printf("\"");
+       }
+       else
+               printf("%s", s);
+}
+
+static void
+report(char* comment, char* fun, char* re, char* s, int len, char* msg, int flags, unsigned long test)
+{
+       if (state.file)
+               printf("%s:", state.file);
+       printf("%d:", state.lineno);
+       if (re)
+       {
+               printf(" ");
+               quote(re, -1, test|TEST_DELIMIT);
+               if (s)
+               {
+                       printf(" versus ");
+                       quote(s, len, test|TEST_DELIMIT);
+               }
+       }
+       if (test & TEST_UNSPECIFIED)
+       {
+               state.unspecified++;
+               printf(" unspecified behavior");
+       }
+       else
+               state.errors++;
+       if (state.which)
+               printf(" %s", state.which);
+       if (flags & REG_NOSUB)
+               printf(" NOSUB");
+       if (fun)
+               printf(" %s", fun);
+       if (comment[strlen(comment)-1] == '\n')
+               printf(" %s", comment);
+       else
+       {
+               printf(" %s: ", comment);
+               if (msg)
+                       printf("%s: ", msg);
+       }
+}
+
+static void
+error(regex_t* preg, int code)
+{
+       char*   msg;
+       char    buf[256];
+
+       switch (code)
+       {
+       case REG_EBUS:
+               msg = "bus error";
+               break;
+       case REG_EFAULT:
+               msg = "memory fault";
+               break;
+       case REG_EHUNG:
+               msg = "did not terminate";
+               break;
+       default:
+               regerror(code, preg, msg = buf, sizeof buf);
+               break;
+       }
+       printf("%s\n", msg);
+}
+
+static void
+bad(char* comment, char* re, char* s, int len, unsigned long test)
+{
+       printf("bad test case ");
+       report(comment, NiL, re, s, len, NiL, 0, test);
+       exit(1);
+}
+
+static int
+escape(char* s)
+{
+       char*   b;
+       char*   t;
+       char*   q;
+       char*   e;
+       int     c;
+
+       for (b = t = s; *t = *s; s++, t++)
+               if (*s == '\\')
+                       switch (*++s)
+                       {
+                       case '\\':
+                               break;
+                       case 'a':
+                               *t = '\a';
+                               break;
+                       case 'b':
+                               *t = '\b';
+                               break;
+                       case 'c':
+                               if (*t = *++s)
+                                       *t &= 037;
+                               else
+                                       s--;
+                               break;
+                       case 'e':
+                       case 'E':
+                               *t = 033;
+                               break;
+                       case 'f':
+                               *t = '\f';
+                               break;
+                       case 'n':
+                               *t = '\n';
+                               break;
+                       case 'r':
+                               *t = '\r';
+                               break;
+                       case 's':
+                               *t = ' ';
+                               break;
+                       case 't':
+                               *t = '\t';
+                               break;
+                       case 'v':
+                               *t = '\v';
+                               break;
+                       case 'u':
+                       case 'x':
+                               c = 0;
+                               q = c == 'u' ? (s + 5) : (char*)0;
+                               e = s + 1;
+                               while (!e || !q || s < q)
+                               {
+                                       switch (*++s)
+                                       {
+                                       case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+                                               c = (c << 4) + *s - 'a' + 10;
+                                               continue;
+                                       case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+                                               c = (c << 4) + *s - 'A' + 10;
+                                               continue;
+                                       case '0': case '1': case '2': case '3': case '4':
+                                       case '5': case '6': case '7': case '8': case '9':
+                                               c = (c << 4) + *s - '0';
+                                               continue;
+                                       case '{':
+                                       case '[':
+                                               if (s != e)
+                                               {
+                                                       s--;
+                                                       break;
+                                               }
+                                               e = 0;
+                                               continue;
+                                       case '}':
+                                       case ']':
+                                               if (e)
+                                                       s--;
+                                               break;
+                                       default:
+                                               s--;
+                                               break;
+                                       }
+                                       break;
+                               }
+                               *t = c;
+                               break;
+                       case '0': case '1': case '2': case '3':
+                       case '4': case '5': case '6': case '7':
+                               c = *s - '0';
+                               q = s + 2;
+                               while (s < q)
+                               {
+                                       switch (*++s)
+                                       {
+                                       case '0': case '1': case '2': case '3':
+                                       case '4': case '5': case '6': case '7':
+                                               c = (c << 3) + *s - '0';
+                                               break;
+                                       default:
+                                               q = --s;
+                                               break;
+                                       }
+                               }
+                               *t = c;
+                               break;
+                       default:
+                               *(s + 1) = 0;
+                               bad("invalid C \\ escape\n", s - 1, NiL, 0, 0);
+                       }
+       return t - b;
+}
+
+static void
+matchoffprint(int off)
+{
+       switch (off)
+       {
+       case -2:
+               printf("X");
+               break;
+       case -1:
+               printf("?");
+               break;
+       default:
+               printf("%d", off);
+               break;
+       }
+}
+
+static void
+matchprint(regmatch_t* match, int nmatch, int nsub, char* ans, unsigned long test)
+{
+       int     i;
+
+       for (; nmatch > nsub + 1; nmatch--)
+               if ((match[nmatch-1].rm_so != -1 || match[nmatch-1].rm_eo != -1) && (!(test & TEST_IGNORE_POSITION) || match[nmatch-1].rm_so >= 0 && match[nmatch-1].rm_eo >= 0))
+                       break;
+       for (i = 0; i < nmatch; i++)
+       {
+               printf("(");
+               matchoffprint(match[i].rm_so);
+               printf(",");
+               matchoffprint(match[i].rm_eo);
+               printf(")");
+       }
+       if (!(test & (TEST_ACTUAL|TEST_BASELINE)))
+       {
+               if (ans)
+                       printf(" expected: %s", ans);
+               printf("\n");
+       }
+}
+
+static int
+matchcheck(regmatch_t* match, int nmatch, int nsub, char* ans, char* re, char* s, int len, int flags, unsigned long test)
+{
+       char*   p;
+       int     i;
+       int     m;
+       int     n;
+
+       if (streq(ans, "OK"))
+               return test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY);
+       for (i = 0, p = ans; i < nmatch && *p; i++)
+       {
+               if (*p == '{')
+               {
+#ifdef REG_DISCIPLINE
+                       char*   x;
+
+                       if (!(x = sfstruse(state.disc.sp)))
+                               bad("out of space [discipline string]\n", NiL, NiL, 0, 0);
+                       if (strcmp(p, x))
+                       {
+                               if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                       return 0;
+                               report("callout failed", NiL, re, s, len, NiL, flags, test);
+                               quote(p, -1, test);
+                               printf(" expected, ");
+                               quote(x, -1, test);
+                               printf(" returned\n");
+                       }
+#endif
+                       break;
+               }
+               if (*p++ != '(')
+                       bad("improper answer\n", re, s, -1, test);
+               if (*p == '?')
+               {
+                       m = -1;
+                       p++;
+               }
+               else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10))
+               {
+                       m = RE_DUP_MAX;
+                       p += 10;
+                       if (*p == '+' || *p == '-')
+                               m += strtol(p, &p, 10);
+               }
+               else
+                       m = strtol(p, &p, 10);
+               if (*p++ != ',')
+                       bad("improper answer\n", re, s, -1, test);
+               if (*p == '?')
+               {
+                       n = -1;
+                       p++;
+               }
+               else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10))
+               {
+                       n = RE_DUP_MAX;
+                       p += 10;
+                       if (*p == '+' || *p == '-')
+                               n += strtol(p, &p, 10);
+               }
+               else
+                       n = strtol(p, &p, 10);
+               if (*p++ != ')')
+                       bad("improper answer\n", re, s, -1, test);
+               if (m!=match[i].rm_so || n!=match[i].rm_eo)
+               {
+                       if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)))
+                       {
+                               report("failed: match was", NiL, re, s, len, NiL, flags, test);
+                               matchprint(match, nmatch, nsub, ans, test);
+                       }
+                       return 0;
+               }
+       }
+       for (; i < nmatch; i++)
+       {
+               if (match[i].rm_so!=-1 || match[i].rm_eo!=-1)
+               {
+                       if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_VERIFY)))
+                       {
+                               if ((test & TEST_IGNORE_POSITION) && (match[i].rm_so<0 || match[i].rm_eo<0))
+                               {
+                                       state.ignored++;
+                                       return 0;
+                               }
+                               if (!(test & TEST_SUMMARY))
+                               {
+                                       report("failed: match was", NiL, re, s, len, NiL, flags, test);
+                                       matchprint(match, nmatch, nsub, ans, test);
+                               }
+                       }
+                       return 0;
+               }
+       }
+       if (!(test & TEST_IGNORE_OVER) && match[nmatch].rm_so != state.NOMATCH.rm_so)
+       {
+               if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)))
+               {
+                       report("failed: overran match array", NiL, re, s, len, NiL, flags, test);
+                       matchprint(match, nmatch + 1, nsub, NiL, test);
+               }
+               return 0;
+       }
+       return 1;
+}
+
+static void
+sigunblock(int s)
+{
+#ifdef SIG_SETMASK
+       int             op;
+       sigset_t        mask;
+
+       sigemptyset(&mask);
+       if (s)
+       {
+               sigaddset(&mask, s);
+               op = SIG_UNBLOCK;
+       }
+       else op = SIG_SETMASK;
+       sigprocmask(op, &mask, NiL);
+#else
+#ifdef sigmask
+       sigsetmask(s ? (sigsetmask(0L) & ~sigmask(s)) : 0L);
+#endif
+#endif
+}
+
+static void
+gotcha(int sig)
+{
+       int     ret;
+
+       signal(sig, gotcha);
+       alarm(0);
+       state.signals++;
+       switch (sig)
+       {
+       case SIGALRM:
+               ret = REG_EHUNG;
+               break;
+       case SIGBUS:
+               ret = REG_EBUS;
+               break;
+       default:
+               ret = REG_EFAULT;
+               break;
+       }
+       sigunblock(sig);
+       longjmp(state.gotcha, ret);
+}
+
+static char*
+getline(FILE* fp)
+{
+       static char     buf[32 * 1024];
+
+       register char*  s = buf;
+       register char*  e = &buf[sizeof(buf)];
+       register char*  b;
+
+       for (;;)
+       {
+               if (!(b = fgets(s, e - s, fp)))
+                       return 0;
+               state.lineno++;
+               s += strlen(s);
+               if (s == b || *--s != '\n' || s == b || *(s - 1) != '\\')
+               {
+                       *s = 0;
+                       break;
+               }
+               s--;
+       }
+       return buf;
+}
+
+static unsigned long
+note(unsigned long level, char* msg, unsigned long skip, unsigned long test)
+{
+       if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)) && !skip)
+       {
+               printf("NOTE\t");
+               if (msg)
+                       printf("%s: ", msg);
+               printf("skipping lines %d", state.lineno);
+       }
+       return skip | level;
+}
+
+#define TABS(n)                &ts[7-((n)&7)]
+
+static char            ts[] = "\t\t\t\t\t\t\t";
+
+static unsigned long
+extract(int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test)
+{
+       if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_OK|TEST_PASS|TEST_SUMMARY))
+       {
+               state.extracted = 1;
+               if (test & TEST_OK)
+               {
+                       state.passed++;
+                       if ((test & TEST_VERIFY) && !(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+                       {
+                               if (msg && strcmp(msg, "EXPECTED"))
+                                       printf("NOTE\t%s\n", msg);
+                               return skip;
+                       }
+                       test &= ~(TEST_PASS|TEST_QUERY);
+               }
+               if (test & (TEST_QUERY|TEST_VERIFY))
+               {
+                       if (test & TEST_BASELINE)
+                               test &= ~(TEST_BASELINE|TEST_PASS);
+                       else
+                               test |= TEST_PASS;
+                       skip |= level;
+               }
+               if (!(test & TEST_OK))
+               {
+                       if (test & TEST_UNSPECIFIED)
+                               state.unspecified++;
+                       else
+                               state.errors++;
+               }
+               if (test & (TEST_PASS|TEST_SUMMARY))
+                       return skip;
+               test &= ~TEST_DELIMIT;
+               printf("%s%s", spec, TABS(*tabs++));
+               if ((test & (TEST_BASELINE|TEST_SAME)) == (TEST_BASELINE|TEST_SAME))
+                       printf("SAME");
+               else
+                       quote(re, -1, test);
+               printf("%s", TABS(*tabs++));
+               quote(s, -1, test);
+               printf("%s", TABS(*tabs++));
+               if (!(test & (TEST_ACTUAL|TEST_BASELINE)) || !accept && !match)
+                       printf("%s", ans);
+               else if (accept)
+                       printf("%s", accept);
+               else
+                       matchprint(match, nmatch, nsub, NiL, test);
+               if (msg)
+                       printf("%s%s", TABS(*tabs++), msg);
+               putchar('\n');
+       }
+       else if (test & TEST_QUERY)
+               skip = note(level, msg, skip, test);
+       else if (test & TEST_VERIFY)
+               state.extracted = 1;
+       return skip;
+}
+
+static int
+catchfree(regex_t* preg, int flags, int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test)
+{
+       int     eret;
+
+       if (!(test & TEST_CATCH))
+       {
+               regfree(preg);
+               eret = 0;
+       }
+       else if (!(eret = setjmp(state.gotcha)))
+       {
+               alarm(HUNG);
+               regfree(preg);
+               alarm(0);
+       }
+       else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+               extract(tabs, spec, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+       else
+       {
+               report("failed", "regfree", re, NiL, -1, msg, flags, test);
+               error(preg, eret);
+       }
+       return eret;
+}
+
+static char*
+expand(char* os, char* ot)
+{
+       char*   s = os;
+       char*   t;
+       int     n = 0;
+       int     r;
+       long    m;
+
+       for (;;)
+       {
+               switch (*s++)
+               {
+               case 0:
+                       break;
+               case '{':
+                       n++;
+                       continue;
+               case '}':
+                       n--;
+                       continue;
+               case 'R':
+                       if (n == 1 && !memcmp(s, "E_DUP_MAX", 9))
+                       {
+                               s--;
+                               for (t = ot; os < s; *t++ = *os++);
+                               r = ((t - ot) >= 5 && t[-1] == '{' && t[-2] == '.' && t[-3] == '.' && t[-4] == '.') ? t[-5] : 0;
+                               os = ot;
+                               m = RE_DUP_MAX;
+                               if (*(s += 10) == '+' || *s == '-')
+                                       m += strtol(s, &s, 10);
+                               if (r)
+                               {
+                                       t -= 5;
+                                       while (m-- > 0)
+                                               *t++ = r;
+                                       while (*s && *s++ != '}');
+                               }
+                               else
+                                       t += snprintf(t, 32, "%ld", m);
+                               while (*t = *s++)
+                                       t++;
+                               break;
+                       }
+                       continue;
+               default:
+                       continue;
+               }
+               break;
+       }
+       return os;
+}
+
+int
+main(int argc, char** argv)
+{
+       int             flags;
+       int             cflags;
+       int             eflags;
+       int             nmatch;
+       int             nexec;
+       int             nstr;
+       int             cret;
+       int             eret;
+       int             nsub;
+       int             i;
+       int             j;
+       int             expected;
+       int             got;
+       int             locale;
+       int             subunitlen;
+       int             testno;
+       unsigned long   level;
+       unsigned long   skip;
+       char*           p;
+       char*           line;
+       char*           spec;
+       char*           re;
+       char*           s;
+       char*           ans;
+       char*           msg;
+       char*           fun;
+       char*           ppat;
+       char*           subunit;
+       char*           version;
+       char*           field[6];
+       char*           delim[6];
+       FILE*           fp;
+       int             tabs[6];
+       char            unit[64];
+       regmatch_t      match[100];
+       regex_t         preg;
+
+       static char     pat[32 * 1024];
+       static char     patbuf[32 * 1024];
+       static char     strbuf[32 * 1024];
+
+       int             nonosub = REG_NOSUB == 0;
+       int             nonexec = 0;
+
+       unsigned long   test = 0;
+
+       static char*    filter[] = { "-", 0 };
+
+       state.NOMATCH.rm_so = state.NOMATCH.rm_eo = -2;
+       p = unit;
+       version = (char*)id + 10;
+       while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace(*p))
+               p++;
+       *p = 0;
+       while ((p = *++argv) && *p == '-')
+               for (;;)
+               {
+                       switch (*++p)
+                       {
+                       case 0:
+                               break;
+                       case 'c':
+                               test |= TEST_CATCH;
+                               continue;
+                       case 'e':
+                               test |= TEST_IGNORE_ERROR;
+                               continue;
+                       case 'h':
+                       case '?':
+                               help(0);
+                               return 2;
+                       case '-':
+                               help(p[1] == 'h');
+                               return 2;
+                       case 'n':
+                               nonexec = 1;
+                               continue;
+                       case 'o':
+                               test |= TEST_IGNORE_OVER;
+                               continue;
+                       case 'p':
+                               test |= TEST_IGNORE_POSITION;
+                               continue;
+                       case 's':
+#ifdef REG_DISCIPLINE
+                               if (!(state.stack = stkalloc(stkstd, 0)))
+                                       fprintf(stderr, "%s: out of space [stack]", unit);
+                               state.disc.disc.re_resizef = resizef;
+                               state.disc.disc.re_resizehandle = (void*)stkstd;
+#endif
+                               continue;
+                       case 'x':
+                               nonosub = 1;
+                               continue;
+                       case 'v':
+                               test |= TEST_VERBOSE;
+                               continue;
+                       case 'A':
+                               test |= TEST_ACTUAL;
+                               continue;
+                       case 'B':
+                               test |= TEST_BASELINE;
+                               continue;
+                       case 'F':
+                               test |= TEST_FAIL;
+                               continue;
+                       case 'P':
+                               test |= TEST_PASS;
+                               continue;
+                       case 'S':
+                               test |= TEST_SUMMARY;
+                               continue;
+                       default:
+                               fprintf(stderr, "%s: %c: invalid option\n", unit, *p);
+                               return 2;
+                       }
+                       break;
+               }
+       if (!*argv)
+               argv = filter;
+       locale = 0;
+       while (state.file = *argv++)
+       {
+               if (streq(state.file, "-") || streq(state.file, "/dev/stdin") || streq(state.file, "/dev/fd/0"))
+               {
+                       state.file = 0;
+                       fp = stdin;
+               }
+               else if (!(fp = fopen(state.file, "r")))
+               {
+                       fprintf(stderr, "%s: %s: cannot read\n", unit, state.file);
+                       return 2;
+               }
+               testno = state.errors = state.ignored = state.lineno = state.passed =
+               state.signals = state.unspecified = state.warnings = 0;
+               skip = 0;
+               level = 1;
+               if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+               {
+                       printf("TEST\t%s ", unit);
+                       if (s = state.file)
+                       {
+                               subunit = p = 0;
+                               for (;;)
+                               {
+                                       switch (*s++)
+                                       {
+                                       case 0:
+                                               break;
+                                       case '/':
+                                               subunit = s;
+                                               continue;
+                                       case '.':
+                                               p = s - 1;
+                                               continue;
+                                       default:
+                                               continue;
+                                       }
+                                       break;
+                               }
+                               if (!subunit)
+                                       subunit = state.file;
+                               if (p < subunit)
+                                       p = s - 1;
+                               subunitlen = p - subunit;
+                               printf("%-.*s ", subunitlen, subunit);
+                       }
+                       else
+                               subunit = 0;
+                       for (s = version; *s && (*s != ' ' || *(s + 1) != '$'); s++)
+                               putchar(*s);
+                       if (test & TEST_CATCH)
+                               printf(", catch");
+                       if (test & TEST_IGNORE_ERROR)
+                               printf(", ignore error code mismatches");
+                       if (test & TEST_IGNORE_POSITION)
+                               printf(", ignore negative position mismatches");
+#ifdef REG_DISCIPLINE
+                       if (state.stack)
+                               printf(", stack");
+#endif
+                       if (test & TEST_VERBOSE)
+                               printf(", verbose");
+                       printf("\n");
+#ifdef REG_VERSIONID
+                       if (regerror(REG_VERSIONID, NiL, pat, sizeof(pat)) > 0)
+                               s = pat;
+                       else
+#endif
+#ifdef REG_TEST_VERSION
+                       s = REG_TEST_VERSION;
+#else
+                       s = "regex";
+#endif
+                       printf("NOTE\t%s\n", s);
+                       if (elementsof(unsupported) > 1)
+                       {
+#if (REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) || !defined(REG_EXTENDED)
+                               i = 0;
+#else
+                               i = REG_EXTENDED != 0;
+#endif
+                               for (got = 0; i < elementsof(unsupported) - 1; i++)
+                               {
+                                       if (!got)
+                                       {
+                                               got = 1;
+                                               printf("NOTE\tunsupported: %s", unsupported[i]);
+                                       }
+                                       else
+                                               printf(",%s", unsupported[i]);
+                               }
+                               if (got)
+                                       printf("\n");
+                       }
+               }
+#ifdef REG_DISCIPLINE
+               state.disc.disc.re_version = REG_VERSION;
+               state.disc.disc.re_compf = compf;
+               state.disc.disc.re_execf = execf;
+               if (!(state.disc.sp = sfstropen()))
+                       bad("out of space [discipline string stream]\n", NiL, NiL, 0, 0);
+               preg.re_disc = &state.disc.disc;
+#endif
+               if (test & TEST_CATCH)
+               {
+                       signal(SIGALRM, gotcha);
+                       signal(SIGBUS, gotcha);
+                       signal(SIGSEGV, gotcha);
+               }
+               while (p = getline(fp))
+               {
+
+               /* parse: */
+
+                       line = p;
+                       if (*p == ':' && !isspace(*(p + 1)))
+                       {
+                               while (*++p && *p != ':');
+                               if (!*p++)
+                               {
+                                       if (test & TEST_BASELINE)
+                                               printf("%s\n", line);
+                                       continue;
+                               }
+                       }
+                       while (isspace(*p))
+                               p++;
+                       if (*p == 0 || *p == '#' || *p == 'T')
+                       {
+                               if (test & TEST_BASELINE)
+                                       printf("%s\n", line);
+                               continue;
+                       }
+                       if (*p == ':' || *p == 'N')
+                       {
+                               if (test & TEST_BASELINE)
+                                       printf("%s\n", line);
+                               else if (!(test & (TEST_ACTUAL|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+                               {
+                                       while (*++p && !isspace(*p));
+                                       while (isspace(*p))
+                                               p++;
+                                       printf("NOTE    %s\n", p);
+                               }
+                               continue;
+                       }
+                       j = 0;
+                       i = 0;
+                       field[i++] = p;
+                       for (;;)
+                       {
+                               switch (*p++)
+                               {
+                               case 0:
+                                       p--;
+                                       j = 0;
+                                       goto checkfield;
+                               case '\t':
+                                       *(delim[i] = p - 1) = 0;
+                                       j = 1;
+                               checkfield:
+                                       s = field[i - 1];
+                                       if (streq(s, "NIL"))
+                                               field[i - 1] = 0;
+                                       else if (streq(s, "NULL"))
+                                               *s = 0;
+                                       while (*p == '\t')
+                                       {
+                                               p++;
+                                               j++;
+                                       }
+                                       tabs[i - 1] = j;
+                                       if (!*p)
+                                               break;
+                                       if (i >= elementsof(field))
+                                               bad("too many fields\n", NiL, NiL, 0, 0);
+                                       field[i++] = p;
+                                       /*FALLTHROUGH*/
+                               default:
+                                       continue;
+                               }
+                               break;
+                       }
+                       if (!(spec = field[0]))
+                               bad("NIL spec\n", NiL, NiL, 0, 0);
+
+               /* interpret: */
+
+                       cflags = REG_TEST_DEFAULT;
+                       eflags = REG_EXEC_DEFAULT;
+                       test &= TEST_GLOBAL;
+                       state.extracted = 0;
+                       nmatch = 20;
+                       nsub = -1;
+                       for (p = spec; *p; p++)
+                       {
+                               if (isdigit(*p))
+                               {
+                                       nmatch = strtol(p, &p, 10);
+                                       if (nmatch >= elementsof(match))
+                                               bad("nmatch must be < 100\n", NiL, NiL, 0, 0);
+                                       p--;
+                                       continue;
+                               }
+                               switch (*p)
+                               {
+                               case 'A':
+                                       test |= TEST_ARE;
+                                       continue;
+                               case 'B':
+                                       test |= TEST_BRE;
+                                       continue;
+                               case 'C':
+                                       if (!(test & TEST_QUERY) && !(skip & level))
+                                               bad("locale must be nested\n", NiL, NiL, 0, 0);
+                                       test &= ~TEST_QUERY;
+                                       if (locale)
+                                               bad("locale nesting not supported\n", NiL, NiL, 0, 0);
+                                       if (i != 2)
+                                               bad("locale field expected\n", NiL, NiL, 0, 0);
+                                       if (!(skip & level))
+                                       {
+#if defined(LC_COLLATE) && defined(LC_CTYPE)
+                                               s = field[1];
+                                               if (!s || streq(s, "POSIX"))
+                                                       s = "C";
+                                               if ((ans = setlocale(LC_COLLATE, s)) && streq(ans, "POSIX"))
+                                                       ans = "C";
+                                               if (!ans || !streq(ans, s) && streq(s, "C"))
+                                                       ans = 0;
+                                               else if ((ans = setlocale(LC_CTYPE, s)) && streq(ans, "POSIX"))
+                                                       ans = "C";
+                                               if (!ans || !streq(ans, s) && streq(s, "C"))
+                                                       skip = note(level, s, skip, test);
+                                               else
+                                               {
+                                                       if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+                                                               printf("NOTE    \"%s\" locale\n", s);
+                                                       locale = level;
+                                               }
+#else
+                                               skip = note(level, skip, test, "locales not supported");
+#endif
+                                       }
+                                       cflags = NOTEST;
+                                       continue;
+                               case 'E':
+                                       test |= TEST_ERE;
+                                       continue;
+                               case 'K':
+                                       test |= TEST_KRE;
+                                       continue;
+                               case 'L':
+                                       test |= TEST_LRE;
+                                       continue;
+                               case 'S':
+                                       test |= TEST_SRE;
+                                       continue;
+
+                               case 'a':
+                                       cflags |= REG_LEFT|REG_RIGHT;
+                                       continue;
+                               case 'b':
+                                       eflags |= REG_NOTBOL;
+                                       continue;
+                               case 'c':
+                                       cflags |= REG_COMMENT;
+                                       continue;
+                               case 'd':
+                                       cflags |= REG_SHELL_DOT;
+                                       continue;
+                               case 'e':
+                                       eflags |= REG_NOTEOL;
+                                       continue;
+                               case 'f':
+                                       cflags |= REG_MULTIPLE;
+                                       continue;
+                               case 'g':
+                                       cflags |= NOTEST;
+                                       continue;
+                               case 'h':
+                                       cflags |= REG_MULTIREF;
+                                       continue;
+                               case 'i':
+                                       cflags |= REG_ICASE;
+                                       continue;
+                               case 'j':
+                                       cflags |= REG_SPAN;
+                                       continue;
+                               case 'k':
+                                       cflags |= REG_ESCAPE;
+                                       continue;
+                               case 'l':
+                                       cflags |= REG_LEFT;
+                                       continue;
+                               case 'm':
+                                       cflags |= REG_MINIMAL;
+                                       continue;
+                               case 'n':
+                                       cflags |= REG_NEWLINE;
+                                       continue;
+                               case 'o':
+                                       cflags |= REG_SHELL_GROUP;
+                                       continue;
+                               case 'p':
+                                       cflags |= REG_SHELL_PATH;
+                                       continue;
+                               case 'q':
+                                       cflags |= REG_DELIMITED;
+                                       continue;
+                               case 'r':
+                                       cflags |= REG_RIGHT;
+                                       continue;
+                               case 's':
+                                       cflags |= REG_SHELL_ESCAPED;
+                                       continue;
+                               case 't':
+                                       cflags |= REG_MUSTDELIM;
+                                       continue;
+                               case 'u':
+                                       test |= TEST_UNSPECIFIED;
+                                       continue;
+                               case 'v':
+                                       cflags |= REG_CLASS_ESCAPE;
+                                       continue;
+                               case 'w':
+                                       cflags |= REG_NOSUB;
+                                       continue;
+                               case 'x':
+                                       if (REG_LENIENT)
+                                               cflags |= REG_LENIENT;
+                                       else
+                                               test |= TEST_LENIENT;
+                                       continue;
+                               case 'y':
+                                       eflags |= REG_LEFT;
+                                       continue;
+                               case 'z':
+                                       cflags |= REG_NULL;
+                                       continue;
+
+                               case '$':
+                                       test |= TEST_EXPAND;
+                                       continue;
+
+                               case '/':
+                                       test |= TEST_SUB;
+                                       continue;
+
+                               case '=':
+                                       test |= TEST_DECOMP;
+                                       continue;
+
+                               case '?':
+                                       test |= TEST_VERIFY;
+                                       test &= ~(TEST_AND|TEST_OR);
+                                       state.verify = state.passed;
+                                       continue;
+                               case '&':
+                                       test |= TEST_VERIFY|TEST_AND;
+                                       test &= ~TEST_OR;
+                                       continue;
+                               case '|':
+                                       test |= TEST_VERIFY|TEST_OR;
+                                       test &= ~TEST_AND;
+                                       continue;
+                               case ';':
+                                       test |= TEST_OR;
+                                       test &= ~TEST_AND;
+                                       continue;
+
+                               case '{':
+                                       level <<= 1;
+                                       if (skip & (level >> 1))
+                                       {
+                                               skip |= level;
+                                               cflags = NOTEST;
+                                       }
+                                       else
+                                       {
+                                               skip &= ~level;
+                                               test |= TEST_QUERY;
+                                       }
+                                       continue;
+                               case '}':
+                                       if (level == 1)
+                                               bad("invalid {...} nesting\n", NiL, NiL, 0, 0);
+                                       if ((skip & level) && !(skip & (level>>1)))
+                                       {
+                                               if (!(test & (TEST_BASELINE|TEST_SUMMARY)))
+                                               {
+                                                       if (test & (TEST_ACTUAL|TEST_FAIL))
+                                                               printf("}\n");
+                                                       else if (!(test & TEST_PASS))
+                                                               printf("-%d\n", state.lineno);
+                                               }
+                                       }
+#if defined(LC_COLLATE) && defined(LC_CTYPE)
+                                       else if (locale & level)
+                                       {
+                                               locale = 0;
+                                               if (!(skip & level))
+                                               {
+                                                       s = "C";
+                                                       setlocale(LC_COLLATE, s);
+                                                       setlocale(LC_CTYPE, s);
+                                                       if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+                                                               printf("NOTE    \"%s\" locale\n", s);
+                                                       else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_PASS))
+                                                               printf("}\n");
+                                               }
+                                               else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL))
+                                                       printf("}\n");
+                                       }
+#endif
+                                       level >>= 1;
+                                       cflags = NOTEST;
+                                       continue;
+
+                               default:
+                                       bad("bad spec\n", spec, NiL, 0, test);
+                                       break;
+
+                               }
+                               break;
+                       }
+                       if ((cflags|eflags) == NOTEST || (skip & level) && (test & TEST_BASELINE))
+                       {
+                               if (test & TEST_BASELINE)
+                               {
+                                       while (i > 1)
+                                               *delim[--i] = '\t';
+                                       printf("%s\n", line);
+                               }
+                               continue;
+                       }
+                       if (test & TEST_OR)
+                       {
+                               if (!(test & TEST_VERIFY))
+                               {
+                                       test &= ~TEST_OR;
+                                       if (state.passed == state.verify && i > 1)
+                                               printf("NOTE\t%s\n", field[1]);
+                                       continue;
+                               }
+                               else if (state.passed > state.verify)
+                                       continue;
+                       }
+                       else if (test & TEST_AND)
+                       {
+                               if (state.passed == state.verify)
+                                       continue;
+                               state.passed = state.verify;
+                       }
+                       if (i < ((test & TEST_DECOMP) ? 3 : 4))
+                               bad("too few fields\n", NiL, NiL, 0, test);
+                       while (i < elementsof(field))
+                               field[i++] = 0;
+                       if (re = field[1])
+                       {
+                               if (streq(re, "SAME"))
+                               {
+                                       re = ppat;
+                                       test |= TEST_SAME;
+                               }
+                               else
+                               {
+                                       if (test & TEST_EXPAND)
+                                               escape(re);
+                                       re = expand(re, patbuf);
+                                       strcpy(ppat = pat, re);
+                               }
+                       }
+                       else
+                               ppat = 0;
+                       nstr = -1;
+                       if (s = field[2])
+                       {
+                               s = expand(s, strbuf);
+                               if (test & TEST_EXPAND)
+                               {
+                                       nstr = escape(s);
+#if _REG_nexec
+                                       if (nstr != strlen(s))
+                                               nexec = nstr;
+#endif
+                               }
+                       }
+                       if (!(ans = field[(test & TEST_DECOMP) ? 2 : 3]))
+                               bad("NIL answer\n", NiL, NiL, 0, test);
+                       msg = field[4];
+                       fflush(stdout);
+                       if (test & TEST_SUB)
+#if _REG_subcomp
+                               cflags |= REG_DELIMITED;
+#else
+                               continue;
+#endif
+#if !_REG_decomp
+                       if (test & TEST_DECOMP)
+                               continue;
+#endif
+
+               compile:
+
+                       if (state.extracted || (skip & level))
+                               continue;
+#if !(REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL))
+#ifdef REG_EXTENDED
+                       if (REG_EXTENDED != 0 && (test & TEST_BRE))
+#else
+                       if (test & TEST_BRE)
+#endif
+                       {
+                               test &= ~TEST_BRE;
+                               flags = cflags;
+                               state.which = "BRE";
+                       }
+                       else
+#endif
+#ifdef REG_EXTENDED
+                       if (test & TEST_ERE)
+                       {
+                               test &= ~TEST_ERE;
+                               flags = cflags | REG_EXTENDED;
+                               state.which = "ERE";
+                       }
+                       else
+#endif
+#ifdef REG_AUGMENTED
+                       if (test & TEST_ARE)
+                       {
+                               test &= ~TEST_ARE;
+                               flags = cflags | REG_AUGMENTED;
+                               state.which = "ARE";
+                       }
+                       else
+#endif
+#ifdef REG_LITERAL
+                       if (test & TEST_LRE)
+                       {
+                               test &= ~TEST_LRE;
+                               flags = cflags | REG_LITERAL;
+                               state.which = "LRE";
+                       }
+                       else
+#endif
+#ifdef REG_SHELL
+                       if (test & TEST_SRE)
+                       {
+                               test &= ~TEST_SRE;
+                               flags = cflags | REG_SHELL;
+                               state.which = "SRE";
+                       }
+                       else
+#ifdef REG_AUGMENTED
+                       if (test & TEST_KRE)
+                       {
+                               test &= ~TEST_KRE;
+                               flags = cflags | REG_SHELL | REG_AUGMENTED;
+                               state.which = "KRE";
+                       }
+                       else
+#endif
+#endif
+                       {
+                               if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY))
+                                       extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test|TEST_OK);
+                               continue;
+                       }
+                       if ((test & (TEST_QUERY|TEST_VERBOSE|TEST_VERIFY)) == TEST_VERBOSE)
+                       {
+                               printf("test %-3d %s ", state.lineno, state.which);
+                               quote(re, -1, test|TEST_DELIMIT);
+                               printf(" ");
+                               quote(s, nstr, test|TEST_DELIMIT);
+                               printf("\n");
+                       }
+
+               nosub:
+                       fun = "regcomp";
+#if _REG_nexec
+                       if (nstr >= 0 && nstr != strlen(s))
+                               nexec = nstr;
+
+                       else
+#endif
+                               nexec = -1;
+                       if (state.extracted || (skip & level))
+                               continue;
+                       if (!(test & TEST_QUERY))
+                               testno++;
+#ifdef REG_DISCIPLINE
+                       if (state.stack)
+                               stkset(stkstd, state.stack, 0);
+                       flags |= REG_DISCIPLINE;
+                       state.disc.ordinal = 0;
+                       sfstrseek(state.disc.sp, 0, SEEK_SET);
+#endif
+                       if (!(test & TEST_CATCH))
+                               cret = regcomp(&preg, re, flags);
+                       else if (!(cret = setjmp(state.gotcha)))
+                       {
+                               alarm(HUNG);
+                               cret = regcomp(&preg, re, flags);
+                               alarm(0);
+                       }
+#if _REG_subcomp
+                       if (!cret && (test & TEST_SUB))
+                       {
+                               fun = "regsubcomp";
+                               p = re + preg.re_npat;
+                               if (!(test & TEST_CATCH))
+                                       cret = regsubcomp(&preg, p, NiL, 0, 0);
+                               else if (!(cret = setjmp(state.gotcha)))
+                               {
+                                       alarm(HUNG);
+                                       cret = regsubcomp(&preg, p, NiL, 0, 0);
+                                       alarm(0);
+                               }
+                               if (!cret && *(p += preg.re_npat) && !(preg.re_sub->re_flags & REG_SUB_LAST))
+                               {
+                                       if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
+                                               continue;
+                                       cret = REG_EFLAGS;
+                               }
+                       }
+#endif
+#if _REG_decomp
+                       if (!cret && (test & TEST_DECOMP))
+                       {
+                               char    buf[128];
+
+                               if ((j = nmatch) > sizeof(buf))
+                                       j = sizeof(buf);
+                               fun = "regdecomp";
+                               p = re + preg.re_npat;
+                               if (!(test & TEST_CATCH))
+                                       i = regdecomp(&preg, -1, buf, j);
+                               else if (!(cret = setjmp(state.gotcha)))
+                               {
+                                       alarm(HUNG);
+                                       i = regdecomp(&preg, -1, buf, j);
+                                       alarm(0);
+                               }
+                               if (!cret)
+                               {
+                                       catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+                                       if (i > j)
+                                       {
+                                               if (i != (strlen(ans) + 1))
+                                               {
+                                                       report("failed", fun, re, s, nstr, msg, flags, test);
+                                                       printf(" %d byte buffer supplied, %d byte buffer required\n", j, i);
+                                               }
+                                       }
+                                       else if (strcmp(buf, ans))
+                                       {
+                                               report("failed", fun, re, s, nstr, msg, flags, test);
+                                               quote(ans, -1, test|TEST_DELIMIT);
+                                               printf(" expected, ");
+                                               quote(buf, -1, test|TEST_DELIMIT);
+                                               printf(" returned\n");
+                                       }
+                                       continue;
+                               }
+                       }
+#endif
+                       if (!cret)
+                       {
+                               if (!(flags & REG_NOSUB) && nsub < 0 && *ans == '(')
+                               {
+                                       for (p = ans; *p; p++)
+                                               if (*p == '(')
+                                                       nsub++;
+                                               else if (*p == '{')
+                                                       nsub--;
+                                       if (nsub >= 0)
+                                       {
+                                               if (test & TEST_IGNORE_OVER)
+                                               {
+                                                       if (nmatch > nsub)
+                                                               nmatch = nsub + 1;
+                                               }
+                                               else if (nsub != preg.re_nsub)
+                                               {
+                                                       if (nsub > preg.re_nsub)
+                                                       {
+                                                               if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                                                       skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+                                                               else
+                                                               {
+                                                                       report("re_nsub incorrect", fun, re, NiL, -1, msg, flags, test);
+                                                                       printf("at least %d expected, %d returned\n", nsub, preg.re_nsub);
+                                                                       state.errors++;
+                                                               }
+                                                       }
+                                                       else
+                                                               nsub = preg.re_nsub;
+                                               }
+                                       }
+                               }
+                               if (!(test & (TEST_DECOMP|TEST_SUB)) && *ans && *ans != '(' && !streq(ans, "OK") && !streq(ans, "NOMATCH"))
+                               {
+                                       if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                               skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+                                       else if (!(test & TEST_LENIENT))
+                                       {
+                                               report("failed", fun, re, NiL, -1, msg, flags, test);
+                                               printf("%s expected, OK returned\n", ans);
+                                       }
+                                       catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+                                       continue;
+                               }
+                       }
+                       else
+                       {
+                               if (test & TEST_LENIENT)
+                                       /* we'll let it go this time */;
+                               else if (!*ans || ans[0]=='(' || cret == REG_BADPAT && streq(ans, "NOMATCH"))
+                               {
+                                       got = 0;
+                                       for (i = 1; i < elementsof(codes); i++)
+                                               if (cret==codes[i].code)
+                                                       got = i;
+                                       if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                               skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+                                       else
+                                       {
+                                               report("failed", fun, re, NiL, -1, msg, flags, test);
+                                               printf("%s returned: ", codes[got].name);
+                                               error(&preg, cret);
+                                       }
+                               }
+                               else
+                               {
+                                       expected = got = 0;
+                                       for (i = 1; i < elementsof(codes); i++)
+                                       {
+                                               if (streq(ans, codes[i].name))
+                                                       expected = i;
+                                               if (cret==codes[i].code)
+                                                       got = i;
+                                       }
+                                       if (!expected)
+                                       {
+                                               if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                                       skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+                                               else
+                                               {
+                                                       report("failed: invalid error code", NiL, re, NiL, -1, msg, flags, test);
+                                                       printf("%s expected, %s returned\n", ans, codes[got].name);
+                                               }
+                                       }
+                                       else if (cret != codes[expected].code && cret != REG_BADPAT)
+                                       {
+                                               if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                                       skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+                                               else if (test & TEST_IGNORE_ERROR)
+                                                       state.ignored++;
+                                               else
+                                               {
+                                                       report("should fail and did", fun, re, NiL, -1, msg, flags, test);
+                                                       printf("%s expected, %s returned: ", ans, codes[got].name);
+                                                       state.errors--;
+                                                       state.warnings++;
+                                                       error(&preg, cret);
+                                               }
+                                       }
+                               }
+                               goto compile;
+                       }
+
+#if _REG_nexec
+               execute:
+                       if (nexec >= 0)
+                               fun = "regnexec";
+                       else
+#endif
+                               fun = "regexec";
+                       
+                       for (i = 0; i < elementsof(match); i++)
+                               match[i] = state.NOMATCH;
+
+#if _REG_nexec
+                       if (nexec >= 0)
+                       {
+                               eret = regnexec(&preg, s, nexec, nmatch, match, eflags);
+                               s[nexec] = 0;
+                       }
+                       else
+#endif
+                       {
+                               if (!(test & TEST_CATCH))
+                                       eret = regexec(&preg, s, nmatch, match, eflags);
+                               else if (!(eret = setjmp(state.gotcha)))
+                               {
+                                       alarm(HUNG);
+                                       eret = regexec(&preg, s, nmatch, match, eflags);
+                                       alarm(0);
+                               }
+                       }
+#if _REG_subcomp
+                       if ((test & TEST_SUB) && !eret)
+                       {
+                               fun = "regsubexec";
+                               if (!(test & TEST_CATCH))
+                                       eret = regsubexec(&preg, s, nmatch, match);
+                               else if (!(eret = setjmp(state.gotcha)))
+                               {
+                                       alarm(HUNG);
+                                       eret = regsubexec(&preg, s, nmatch, match);
+                                       alarm(0);
+                               }
+                       }
+#endif
+                       if (flags & REG_NOSUB)
+                       {
+                               if (eret)
+                               {
+                                       if (eret != REG_NOMATCH || !streq(ans, "NOMATCH"))
+                                       {
+                                               if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                                       skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+                                               else
+                                               {
+                                                       report("REG_NOSUB failed", fun, re, s, nstr, msg, flags, test);
+                                                       error(&preg, eret);
+                                               }
+                                       }
+                               }
+                               else if (streq(ans, "NOMATCH"))
+                               {
+                                       if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                               skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
+                                       else
+                                       {
+                                               report("should fail and didn't", fun, re, s, nstr, msg, flags, test);
+                                               error(&preg, eret);
+                                       }
+                               }
+                       }
+                       else if (eret)
+                       {
+                               if (eret != REG_NOMATCH || !streq(ans, "NOMATCH"))
+                               {
+                                       if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                               skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, nsub, skip, level, test|TEST_DELIMIT);
+                                       else
+                                       {
+                                               report("failed", fun, re, s, nstr, msg, flags, test);
+                                               if (eret != REG_NOMATCH)
+                                                       error(&preg, eret);
+                                               else if (*ans)
+                                                       printf("expected: %s\n", ans);
+                                               else
+                                                       printf("\n");
+                                       }
+                               }
+                       }
+                       else if (streq(ans, "NOMATCH"))
+                       {
+                               if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                       skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
+                               else
+                               {
+                                       report("should fail and didn't", fun, re, s, nstr, msg, flags, test);
+                                       matchprint(match, nmatch, nsub, NiL, test);
+                               }
+                       }
+#if _REG_subcomp
+                       else if (test & TEST_SUB)
+                       {
+                               p = preg.re_sub->re_buf;
+                               if (strcmp(p, ans))
+                               {
+                                       report("failed", fun, re, s, nstr, msg, flags, test);
+                                       quote(ans, -1, test|TEST_DELIMIT);
+                                       printf(" expected, ");
+                                       quote(p, -1, test|TEST_DELIMIT);
+                                       printf(" returned\n");
+                               }
+                       }
+#endif
+                       else if (!*ans)
+                       {
+                               if (match[0].rm_so != state.NOMATCH.rm_so)
+                               {
+                                       if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                                               skip = extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+                                       else
+                                       {
+                                               report("failed: no match but match array assigned", NiL, re, s, nstr, msg, flags, test);
+                                               matchprint(match, nmatch, nsub, NiL, test);
+                                       }
+                               }
+                       }
+                       else if (matchcheck(match, nmatch, nsub, ans, re, s, nstr, flags, test))
+                       {
+#if _REG_nexec
+                               if (nexec < 0 && !nonexec)
+                               {
+                                       nexec = nstr >= 0 ? nstr : strlen(s);
+                                       s[nexec] = '\n';
+                                       testno++;
+                                       goto execute;
+                               }
+#endif
+                               if (!(test & (TEST_DECOMP|TEST_SUB|TEST_VERIFY)) && !nonosub)
+                               {
+                                       if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
+                                               continue;
+                                       flags |= REG_NOSUB;
+                                       goto nosub;
+                               }
+                               if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY))
+                                       skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_OK);
+                       }
+                       else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+                               skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
+                       if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
+                               continue;
+                       goto compile;
+               }
+               if (test & TEST_SUMMARY)
+                       printf("tests=%-4d errors=%-4d warnings=%-2d ignored=%-2d unspecified=%-2d signals=%d\n", testno, state.errors, state.warnings, state.ignored, state.unspecified, state.signals);
+               else if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS)))
+               {
+                       printf("TEST\t%s", unit);
+                       if (subunit)
+                               printf(" %-.*s", subunitlen, subunit);
+                       printf(", %d test%s", testno, testno == 1 ? "" : "s");
+                       if (state.ignored)
+                               printf(", %d ignored mismatche%s", state.ignored, state.ignored == 1 ? "" : "s");
+                       if (state.warnings)
+                               printf(", %d warning%s", state.warnings, state.warnings == 1 ? "" : "s");
+                       if (state.unspecified)
+                               printf(", %d unspecified difference%s", state.unspecified, state.unspecified == 1 ? "" : "s");
+                       if (state.signals)
+                               printf(", %d signal%s", state.signals, state.signals == 1 ? "" : "s");
+                       printf(", %d error%s\n", state.errors, state.errors == 1 ? "" : "s");
+               }
+               if (fp != stdin)
+                       fclose(fp);
+       }
+       return 0;
+}