pax_global_header00006660000000000000000000000064134720226550014520gustar00rootroot0000000000000052 comment=857b9542aaa89cfa42a1477b43fa1f24192fe921 binaryregexp-0.2.0/000077500000000000000000000000001347202265500142165ustar00rootroot00000000000000binaryregexp-0.2.0/LICENSE000066400000000000000000000027071347202265500152310ustar00rootroot00000000000000Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. binaryregexp-0.2.0/all_test.go000066400000000000000000000611021347202265500163540ustar00rootroot00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package binaryregexp import ( "reflect" "strings" "testing" "unicode/utf8" "rsc.io/binaryregexp/syntax" ) var goodRe = []string{ ``, `.`, `^.$`, `a`, `a*`, `a+`, `a?`, `a|b`, `a*|b*`, `(a*|b)(c*|d)`, `[a-z]`, `[a-abc-c\-\]\[]`, `[a-z]+`, `[abc]`, `[^1234]`, `[^\n]`, `\!\\`, } type stringError struct { re string err string } var badRe = []stringError{ {`*`, "missing argument to repetition operator: `*`"}, {`+`, "missing argument to repetition operator: `+`"}, {`?`, "missing argument to repetition operator: `?`"}, {`(abc`, "missing closing ): `(abc`"}, {`abc)`, "unexpected ): `abc)`"}, {`x[a-z`, "missing closing ]: `[a-z`"}, {`[z-a]`, "invalid character class range: `z-a`"}, {`abc\`, "trailing backslash at end of expression"}, {`a**`, "invalid nested repetition operator: `**`"}, {`a*+`, "invalid nested repetition operator: `*+`"}, {`\x`, "invalid escape sequence: `\\x`"}, } func compileTest(t *testing.T, expr string, error string) *Regexp { re, err := Compile(expr) if error == "" && err != nil { t.Error("compiling `", expr, "`; unexpected error: ", err.Error()) } if error != "" && err == nil { t.Error("compiling `", expr, "`; missing error") } else if error != "" && !strings.Contains(err.Error(), error) { t.Error("compiling `", expr, "`; wrong error: ", err.Error(), "; want ", error) } return re } func TestGoodCompile(t *testing.T) { for i := 0; i < len(goodRe); i++ { compileTest(t, goodRe[i], "") } } func TestBadCompile(t *testing.T) { for i := 0; i < len(badRe); i++ { compileTest(t, badRe[i].re, badRe[i].err) } } func matchTest(t *testing.T, test *FindTest) { re := compileTest(t, test.pat, "") if re == nil { return } m := re.MatchString(test.text) if m != (len(test.matches) > 0) { t.Errorf("MatchString failure on %s: %t should be %t", test, m, len(test.matches) > 0) } // now try bytes m = re.Match([]byte(test.text)) if m != (len(test.matches) > 0) { t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0) } } func TestMatch(t *testing.T) { for _, test := range findTests[:1] { matchTest(t, &test) } } func matchFunctionTest(t *testing.T, test *FindTest) { m, err := MatchString(test.pat, test.text) if err == nil { return } if m != (len(test.matches) > 0) { t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0) } } func TestMatchFunction(t *testing.T) { for _, test := range findTests { matchFunctionTest(t, &test) } } func copyMatchTest(t *testing.T, test *FindTest) { re := compileTest(t, test.pat, "") if re == nil { return } m1 := re.MatchString(test.text) m2 := re.Copy().MatchString(test.text) if m1 != m2 { t.Errorf("Copied Regexp match failure on %s: original gave %t; copy gave %t; should be %t", test, m1, m2, len(test.matches) > 0) } } func TestCopyMatch(t *testing.T) { for _, test := range findTests { copyMatchTest(t, &test) } } type ReplaceTest struct { pattern, replacement, input, output string } var replaceTests = []ReplaceTest{ // Test empty input and/or replacement, with pattern that matches the empty string. {"", "", "", ""}, {"", "x", "", "x"}, {"", "", "abc", "abc"}, {"", "x", "abc", "xaxbxcx"}, // Test empty input and/or replacement, with pattern that does not match the empty string. {"b", "", "", ""}, {"b", "x", "", ""}, {"b", "", "abc", "ac"}, {"b", "x", "abc", "axc"}, {"y", "", "", ""}, {"y", "x", "", ""}, {"y", "", "abc", "abc"}, {"y", "x", "abc", "abc"}, // Multibyte characters -- verify that we don't try to match in the middle // of a character. {"[a-c]*", "x", "\u65e5", "x\xe6x\x97x\xa5x"}, {"[^\u65e5]", "x", "abc\u65e5def", "xxxxxxxxx"}, // Start and end of a string. {"^[a-c]*", "x", "abcdabc", "xdabc"}, {"[a-c]*$", "x", "abcdabc", "abcdx"}, {"^[a-c]*$", "x", "abcdabc", "abcdabc"}, {"^[a-c]*", "x", "abc", "x"}, {"[a-c]*$", "x", "abc", "x"}, {"^[a-c]*$", "x", "abc", "x"}, {"^[a-c]*", "x", "dabce", "xdabce"}, {"[a-c]*$", "x", "dabce", "dabcex"}, {"^[a-c]*$", "x", "dabce", "dabce"}, {"^[a-c]*", "x", "", "x"}, {"[a-c]*$", "x", "", "x"}, {"^[a-c]*$", "x", "", "x"}, {"^[a-c]+", "x", "abcdabc", "xdabc"}, {"[a-c]+$", "x", "abcdabc", "abcdx"}, {"^[a-c]+$", "x", "abcdabc", "abcdabc"}, {"^[a-c]+", "x", "abc", "x"}, {"[a-c]+$", "x", "abc", "x"}, {"^[a-c]+$", "x", "abc", "x"}, {"^[a-c]+", "x", "dabce", "dabce"}, {"[a-c]+$", "x", "dabce", "dabce"}, {"^[a-c]+$", "x", "dabce", "dabce"}, {"^[a-c]+", "x", "", ""}, {"[a-c]+$", "x", "", ""}, {"^[a-c]+$", "x", "", ""}, // Other cases. {"abc", "def", "abcdefg", "defdefg"}, {"bc", "BC", "abcbcdcdedef", "aBCBCdcdedef"}, {"abc", "", "abcdabc", "d"}, {"x", "xXx", "xxxXxxx", "xXxxXxxXxXxXxxXxxXx"}, {"abc", "d", "", ""}, {"abc", "d", "abc", "d"}, {".+", "x", "abc", "x"}, {"[a-c]*", "x", "def", "xdxexfx"}, {"[a-c]+", "x", "abcbcdcdedef", "xdxdedef"}, {"[a-c]*", "x", "abcbcdcdedef", "xdxdxexdxexfx"}, // Substitutions {"a+", "($0)", "banana", "b(a)n(a)n(a)"}, {"a+", "(${0})", "banana", "b(a)n(a)n(a)"}, {"a+", "(${0})$0", "banana", "b(a)an(a)an(a)a"}, {"a+", "(${0})$0", "banana", "b(a)an(a)an(a)a"}, {"hello, (.+)", "goodbye, ${1}", "hello, world", "goodbye, world"}, {"hello, (.+)", "goodbye, $1x", "hello, world", "goodbye, "}, {"hello, (.+)", "goodbye, ${1}x", "hello, world", "goodbye, worldx"}, {"hello, (.+)", "<$0><$1><$2><$3>", "hello, world", "<><>"}, {"hello, (?P.+)", "goodbye, $noun!", "hello, world", "goodbye, world!"}, {"hello, (?P.+)", "goodbye, ${noun}", "hello, world", "goodbye, world"}, {"(?Phi)|(?Pbye)", "$x$x$x", "hi", "hihihi"}, {"(?Phi)|(?Pbye)", "$x$x$x", "bye", "byebyebye"}, {"(?Phi)|(?Pbye)", "$xyz", "hi", ""}, {"(?Phi)|(?Pbye)", "${x}yz", "hi", "hiyz"}, {"(?Phi)|(?Pbye)", "hello $$x", "hi", "hello $x"}, {"a+", "${oops", "aaa", "${oops"}, {"a+", "$$", "aaa", "$"}, {"a+", "$", "aaa", "$"}, // Substitution when subexpression isn't found {"(x)?", "$1", "123", "123"}, {"abc", "$1", "123", "123"}, // Substitutions involving a (x){0} {"(a)(b){0}(c)", ".$1|$3.", "xacxacx", "x.a|c.x.a|c.x"}, {"(a)(((b))){0}c", ".$1.", "xacxacx", "x.a.x.a.x"}, {"((a(b){0}){3}){5}(h)", "y caramb$2", "say aaaaaaaaaaaaaaaah", "say ay caramba"}, {"((a(b){0}){3}){5}h", "y caramb$2", "say aaaaaaaaaaaaaaaah", "say ay caramba"}, } var replaceLiteralTests = []ReplaceTest{ // Substitutions {"a+", "($0)", "banana", "b($0)n($0)n($0)"}, {"a+", "(${0})", "banana", "b(${0})n(${0})n(${0})"}, {"a+", "(${0})$0", "banana", "b(${0})$0n(${0})$0n(${0})$0"}, {"a+", "(${0})$0", "banana", "b(${0})$0n(${0})$0n(${0})$0"}, {"hello, (.+)", "goodbye, ${1}", "hello, world", "goodbye, ${1}"}, {"hello, (?P.+)", "goodbye, $noun!", "hello, world", "goodbye, $noun!"}, {"hello, (?P.+)", "goodbye, ${noun}", "hello, world", "goodbye, ${noun}"}, {"(?Phi)|(?Pbye)", "$x$x$x", "hi", "$x$x$x"}, {"(?Phi)|(?Pbye)", "$x$x$x", "bye", "$x$x$x"}, {"(?Phi)|(?Pbye)", "$xyz", "hi", "$xyz"}, {"(?Phi)|(?Pbye)", "${x}yz", "hi", "${x}yz"}, {"(?Phi)|(?Pbye)", "hello $$x", "hi", "hello $$x"}, {"a+", "${oops", "aaa", "${oops"}, {"a+", "$$", "aaa", "$$"}, {"a+", "$", "aaa", "$"}, } type ReplaceFuncTest struct { pattern string replacement func(string) string input, output string } var replaceFuncTests = []ReplaceFuncTest{ {"[a-c]", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxayxbyxcydef"}, {"[a-c]+", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxabcydef"}, {"[a-c]*", func(s string) string { return "x" + s + "y" }, "defabcdef", "xydxyexyfxabcydxyexyfxy"}, } func TestReplaceAll(t *testing.T) { for _, tc := range replaceTests { re, err := Compile(tc.pattern) if err != nil { t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err) continue } actual := re.ReplaceAllString(tc.input, tc.replacement) if actual != tc.output { t.Errorf("%q.ReplaceAllString(%q,%q) = %q; want %q", tc.pattern, tc.input, tc.replacement, actual, tc.output) } // now try bytes actual = string(re.ReplaceAll([]byte(tc.input), []byte(tc.replacement))) if actual != tc.output { t.Errorf("%q.ReplaceAll(%q,%q) = %q; want %q", tc.pattern, tc.input, tc.replacement, actual, tc.output) } } } func TestReplaceAllLiteral(t *testing.T) { // Run ReplaceAll tests that do not have $ expansions. for _, tc := range replaceTests { if strings.Contains(tc.replacement, "$") { continue } re, err := Compile(tc.pattern) if err != nil { t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err) continue } actual := re.ReplaceAllLiteralString(tc.input, tc.replacement) if actual != tc.output { t.Errorf("%q.ReplaceAllLiteralString(%q,%q) = %q; want %q", tc.pattern, tc.input, tc.replacement, actual, tc.output) } // now try bytes actual = string(re.ReplaceAllLiteral([]byte(tc.input), []byte(tc.replacement))) if actual != tc.output { t.Errorf("%q.ReplaceAllLiteral(%q,%q) = %q; want %q", tc.pattern, tc.input, tc.replacement, actual, tc.output) } } // Run literal-specific tests. for _, tc := range replaceLiteralTests { re, err := Compile(tc.pattern) if err != nil { t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err) continue } actual := re.ReplaceAllLiteralString(tc.input, tc.replacement) if actual != tc.output { t.Errorf("%q.ReplaceAllLiteralString(%q,%q) = %q; want %q", tc.pattern, tc.input, tc.replacement, actual, tc.output) } // now try bytes actual = string(re.ReplaceAllLiteral([]byte(tc.input), []byte(tc.replacement))) if actual != tc.output { t.Errorf("%q.ReplaceAllLiteral(%q,%q) = %q; want %q", tc.pattern, tc.input, tc.replacement, actual, tc.output) } } } func TestReplaceAllFunc(t *testing.T) { for _, tc := range replaceFuncTests { re, err := Compile(tc.pattern) if err != nil { t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err) continue } actual := re.ReplaceAllStringFunc(tc.input, tc.replacement) if actual != tc.output { t.Errorf("%q.ReplaceFunc(%q,fn) = %q; want %q", tc.pattern, tc.input, actual, tc.output) } // now try bytes actual = string(re.ReplaceAllFunc([]byte(tc.input), func(s []byte) []byte { return []byte(tc.replacement(string(s))) })) if actual != tc.output { t.Errorf("%q.ReplaceFunc(%q,fn) = %q; want %q", tc.pattern, tc.input, actual, tc.output) } } } type MetaTest struct { pattern, output, literal string isLiteral bool } var metaTests = []MetaTest{ {``, ``, ``, true}, {`foo`, `foo`, `foo`, true}, {`ÿ+`, `ÿ\+`, `ÿ`, false}, {`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator {`foo.\$`, `foo\.\\\$`, `foo`, false}, // has escaped operators and real operators {`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[\{\]\}\\\|,<\.>/\?~`, `!@#`, false}, } var literalPrefixTests = []MetaTest{ // See golang.org/issue/11175. // output is unused. {`^0^0$`, ``, `0`, false}, {`^0^`, ``, ``, false}, {`^0$`, ``, `0`, true}, {`$0^`, ``, ``, false}, {`$0$`, ``, ``, false}, {`^^0$$`, ``, ``, false}, {`^$^$`, ``, ``, false}, {`$$0^^`, ``, ``, false}, } func TestQuoteMeta(t *testing.T) { for _, tc := range metaTests { // Verify that QuoteMeta returns the expected string. quoted := QuoteMeta(tc.pattern) if quoted != tc.output { t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`", tc.pattern, quoted, tc.output) continue } // Verify that the quoted string is in fact treated as expected // by Compile -- i.e. that it matches the original, unquoted string. if tc.pattern != "" { re, err := Compile(quoted) if err != nil { t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err) continue } src := "abc" + toLatin1(tc.pattern) + "def" repl := "xyz" replaced := re.ReplaceAllString(src, repl) expected := "abcxyzdef" if replaced != expected { t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`", tc.pattern, src, repl, replaced, expected) } } } } func toLatin1(s string) string { runes := []rune(s) b := make([]byte, len(runes)) for i, r := range runes { if r > 0xff { panic("cannot toLatin1") } b[i] = byte(r) } return string(b) } func TestLiteralPrefix(t *testing.T) { for _, tc := range append(metaTests, literalPrefixTests...) { // Literal method needs to scan the pattern. re := MustCompile(tc.pattern) str, complete := re.LiteralPrefix() if complete != tc.isLiteral { t.Errorf("LiteralPrefix(`%s`) = %t; want %t", tc.pattern, complete, tc.isLiteral) } if str != toLatin1(tc.literal) { t.Errorf("LiteralPrefix(`%s`) = %#q; want %#q", tc.pattern, str, toLatin1(tc.literal)) } } } type subexpCase struct { input string num int names []string } var subexpCases = []subexpCase{ {``, 0, nil}, {`.*`, 0, nil}, {`abba`, 0, nil}, {`ab(b)a`, 1, []string{"", ""}}, {`ab(.*)a`, 1, []string{"", ""}}, {`(.*)ab(.*)a`, 2, []string{"", "", ""}}, {`(.*)(ab)(.*)a`, 3, []string{"", "", "", ""}}, {`(.*)((a)b)(.*)a`, 4, []string{"", "", "", "", ""}}, {`(.*)(\(ab)(.*)a`, 3, []string{"", "", "", ""}}, {`(.*)(\(a\)b)(.*)a`, 3, []string{"", "", "", ""}}, {`(?P.*)(?P(a)b)(?P.*)a`, 4, []string{"", "foo", "bar", "", "foo"}}, } func TestSubexp(t *testing.T) { for _, c := range subexpCases { re := MustCompile(c.input) n := re.NumSubexp() if n != c.num { t.Errorf("%q: NumSubexp = %d, want %d", c.input, n, c.num) continue } names := re.SubexpNames() if len(names) != 1+n { t.Errorf("%q: len(SubexpNames) = %d, want %d", c.input, len(names), n) continue } if c.names != nil { for i := 0; i < 1+n; i++ { if names[i] != c.names[i] { t.Errorf("%q: SubexpNames[%d] = %q, want %q", c.input, i, names[i], c.names[i]) } } } } } var splitTests = []struct { s string r string n int out []string }{ {"foo:and:bar", ":", -1, []string{"foo", "and", "bar"}}, {"foo:and:bar", ":", 1, []string{"foo:and:bar"}}, {"foo:and:bar", ":", 2, []string{"foo", "and:bar"}}, {"foo:and:bar", "foo", -1, []string{"", ":and:bar"}}, {"foo:and:bar", "bar", -1, []string{"foo:and:", ""}}, {"foo:and:bar", "baz", -1, []string{"foo:and:bar"}}, {"baabaab", "a", -1, []string{"b", "", "b", "", "b"}}, {"baabaab", "a*", -1, []string{"b", "b", "b"}}, {"baabaab", "ba*", -1, []string{"", "", "", ""}}, {"foobar", "f*b*", -1, []string{"", "o", "o", "a", "r"}}, {"foobar", "f+.*b+", -1, []string{"", "ar"}}, {"foobooboar", "o{2}", -1, []string{"f", "b", "boar"}}, {"a,b,c,d,e,f", ",", 3, []string{"a", "b", "c,d,e,f"}}, {"a,b,c,d,e,f", ",", 0, nil}, {",", ",", -1, []string{"", ""}}, {",,,", ",", -1, []string{"", "", "", ""}}, {"", ",", -1, []string{""}}, {"", ".*", -1, []string{""}}, {"", ".+", -1, []string{""}}, {"", "", -1, []string{}}, {"foobar", "", -1, []string{"f", "o", "o", "b", "a", "r"}}, {"abaabaccadaaae", "a*", 5, []string{"", "b", "b", "c", "cadaaae"}}, {":x:y:z:", ":", -1, []string{"", "x", "y", "z", ""}}, } func TestSplit(t *testing.T) { for i, test := range splitTests { re, err := Compile(test.r) if err != nil { t.Errorf("#%d: %q: compile error: %s", i, test.r, err.Error()) continue } split := re.Split(test.s, test.n) if !reflect.DeepEqual(split, test.out) { t.Errorf("#%d: %q: got %q; want %q", i, test.r, split, test.out) } if QuoteMeta(test.r) == test.r { strsplit := strings.SplitN(test.s, test.r, test.n) if !reflect.DeepEqual(split, strsplit) { t.Errorf("#%d: Split(%q, %q, %d): regexp vs strings mismatch\nregexp=%q\nstrings=%q", i, test.s, test.r, test.n, split, strsplit) } } } } // The following sequence of Match calls used to panic. See issue #12980. func TestParseAndCompile(t *testing.T) { expr := "a$" s := "a\nb" for i, tc := range []struct { reFlags syntax.Flags expMatch bool }{ {syntax.Perl | syntax.OneLine, false}, {syntax.Perl &^ syntax.OneLine, true}, } { parsed, err := syntax.Parse(expr, tc.reFlags) if err != nil { t.Fatalf("%d: parse: %v", i, err) } re, err := Compile(parsed.String()) if err != nil { t.Fatalf("%d: compile: %v", i, err) } if match := re.MatchString(s); match != tc.expMatch { t.Errorf("%d: %q.MatchString(%q)=%t; expected=%t", i, re, s, match, tc.expMatch) } } } // Check that one-pass cutoff does trigger. func TestOnePassCutoff(t *testing.T) { re, err := syntax.Parse(`^x{1,1000}y{1,1000}$`, syntax.Perl) if err != nil { t.Fatalf("parse: %v", err) } p, err := syntax.Compile(re.Simplify()) if err != nil { t.Fatalf("compile: %v", err) } if compileOnePass(p) != nil { t.Fatalf("makeOnePass succeeded; wanted nil") } } // Check that the same machine can be used with the standard matcher // and then the backtracker when there are no captures. func TestSwitchBacktrack(t *testing.T) { re := MustCompile(`a|b`) long := make([]byte, maxBacktrackVector+1) // The following sequence of Match calls used to panic. See issue #10319. re.Match(long) // triggers standard matcher re.Match(long[:1]) // triggers backtracker } func BenchmarkFind(b *testing.B) { b.StopTimer() re := MustCompile("a+b+") wantSubs := "aaabb" s := []byte("acbb" + wantSubs + "dd") b.StartTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { subs := re.Find(s) if string(subs) != wantSubs { b.Fatalf("Find(%q) = %q; want %q", s, subs, wantSubs) } } } func BenchmarkFindAllNoMatches(b *testing.B) { re := MustCompile("a+b+") s := []byte("acddee") b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { all := re.FindAll(s, -1) if all != nil { b.Fatalf("FindAll(%q) = %q; want nil", s, all) } } } func BenchmarkFindString(b *testing.B) { b.StopTimer() re := MustCompile("a+b+") wantSubs := "aaabb" s := "acbb" + wantSubs + "dd" b.StartTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { subs := re.FindString(s) if subs != wantSubs { b.Fatalf("FindString(%q) = %q; want %q", s, subs, wantSubs) } } } func BenchmarkFindSubmatch(b *testing.B) { b.StopTimer() re := MustCompile("a(a+b+)b") wantSubs := "aaabb" s := []byte("acbb" + wantSubs + "dd") b.StartTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { subs := re.FindSubmatch(s) if string(subs[0]) != wantSubs { b.Fatalf("FindSubmatch(%q)[0] = %q; want %q", s, subs[0], wantSubs) } if string(subs[1]) != "aab" { b.Fatalf("FindSubmatch(%q)[1] = %q; want %q", s, subs[1], "aab") } } } func BenchmarkFindStringSubmatch(b *testing.B) { b.StopTimer() re := MustCompile("a(a+b+)b") wantSubs := "aaabb" s := "acbb" + wantSubs + "dd" b.StartTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { subs := re.FindStringSubmatch(s) if subs[0] != wantSubs { b.Fatalf("FindStringSubmatch(%q)[0] = %q; want %q", s, subs[0], wantSubs) } if subs[1] != "aab" { b.Fatalf("FindStringSubmatch(%q)[1] = %q; want %q", s, subs[1], "aab") } } } func BenchmarkLiteral(b *testing.B) { x := strings.Repeat("x", 50) + "y" b.StopTimer() re := MustCompile("y") b.StartTimer() for i := 0; i < b.N; i++ { if !re.MatchString(x) { b.Fatalf("no match!") } } } func BenchmarkNotLiteral(b *testing.B) { x := strings.Repeat("x", 50) + "y" b.StopTimer() re := MustCompile(".y") b.StartTimer() for i := 0; i < b.N; i++ { if !re.MatchString(x) { b.Fatalf("no match!") } } } func BenchmarkMatchClass(b *testing.B) { b.StopTimer() x := strings.Repeat("xxxx", 20) + "w" re := MustCompile("[abcdw]") b.StartTimer() for i := 0; i < b.N; i++ { if !re.MatchString(x) { b.Fatalf("no match!") } } } func BenchmarkMatchClass_InRange(b *testing.B) { b.StopTimer() // 'b' is between 'a' and 'c', so the charclass // range checking is no help here. x := strings.Repeat("bbbb", 20) + "c" re := MustCompile("[ac]") b.StartTimer() for i := 0; i < b.N; i++ { if !re.MatchString(x) { b.Fatalf("no match!") } } } func BenchmarkReplaceAll(b *testing.B) { x := "abcdefghijklmnopqrstuvwxyz" b.StopTimer() re := MustCompile("[cjrw]") b.StartTimer() for i := 0; i < b.N; i++ { re.ReplaceAllString(x, "") } } func BenchmarkAnchoredLiteralShortNonMatch(b *testing.B) { b.StopTimer() x := []byte("abcdefghijklmnopqrstuvwxyz") re := MustCompile("^zbc(d|e)") b.StartTimer() for i := 0; i < b.N; i++ { re.Match(x) } } func BenchmarkAnchoredLiteralLongNonMatch(b *testing.B) { b.StopTimer() x := []byte("abcdefghijklmnopqrstuvwxyz") for i := 0; i < 15; i++ { x = append(x, x...) } re := MustCompile("^zbc(d|e)") b.StartTimer() for i := 0; i < b.N; i++ { re.Match(x) } } func BenchmarkAnchoredShortMatch(b *testing.B) { b.StopTimer() x := []byte("abcdefghijklmnopqrstuvwxyz") re := MustCompile("^.bc(d|e)") b.StartTimer() for i := 0; i < b.N; i++ { re.Match(x) } } func BenchmarkAnchoredLongMatch(b *testing.B) { b.StopTimer() x := []byte("abcdefghijklmnopqrstuvwxyz") for i := 0; i < 15; i++ { x = append(x, x...) } re := MustCompile("^.bc(d|e)") b.StartTimer() for i := 0; i < b.N; i++ { re.Match(x) } } func BenchmarkOnePassShortA(b *testing.B) { b.StopTimer() x := []byte("abcddddddeeeededd") re := MustCompile("^.bc(d|e)*$") b.StartTimer() for i := 0; i < b.N; i++ { re.Match(x) } } func BenchmarkNotOnePassShortA(b *testing.B) { b.StopTimer() x := []byte("abcddddddeeeededd") re := MustCompile(".bc(d|e)*$") b.StartTimer() for i := 0; i < b.N; i++ { re.Match(x) } } func BenchmarkOnePassShortB(b *testing.B) { b.StopTimer() x := []byte("abcddddddeeeededd") re := MustCompile("^.bc(?:d|e)*$") b.StartTimer() for i := 0; i < b.N; i++ { re.Match(x) } } func BenchmarkNotOnePassShortB(b *testing.B) { b.StopTimer() x := []byte("abcddddddeeeededd") re := MustCompile(".bc(?:d|e)*$") b.StartTimer() for i := 0; i < b.N; i++ { re.Match(x) } } func BenchmarkOnePassLongPrefix(b *testing.B) { b.StopTimer() x := []byte("abcdefghijklmnopqrstuvwxyz") re := MustCompile("^abcdefghijklmnopqrstuvwxyz.*$") b.StartTimer() for i := 0; i < b.N; i++ { re.Match(x) } } func BenchmarkOnePassLongNotPrefix(b *testing.B) { b.StopTimer() x := []byte("abcdefghijklmnopqrstuvwxyz") re := MustCompile("^.bcdefghijklmnopqrstuvwxyz.*$") b.StartTimer() for i := 0; i < b.N; i++ { re.Match(x) } } func BenchmarkMatchParallelShared(b *testing.B) { x := []byte("this is a long line that contains foo bar baz") re := MustCompile("foo (ba+r)? baz") b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { re.Match(x) } }) } func BenchmarkMatchParallelCopied(b *testing.B) { x := []byte("this is a long line that contains foo bar baz") re := MustCompile("foo (ba+r)? baz") b.ResetTimer() b.RunParallel(func(pb *testing.PB) { re := re.Copy() for pb.Next() { re.Match(x) } }) } var sink string func BenchmarkQuoteMetaAll(b *testing.B) { specials := make([]byte, 0) for i := byte(0); i < utf8.RuneSelf; i++ { if special(i) { specials = append(specials, i) } } s := string(specials) b.SetBytes(int64(len(s))) b.ResetTimer() for i := 0; i < b.N; i++ { sink = QuoteMeta(s) } } func BenchmarkQuoteMetaNone(b *testing.B) { s := "abcdefghijklmnopqrstuvwxyz" b.SetBytes(int64(len(s))) b.ResetTimer() for i := 0; i < b.N; i++ { sink = QuoteMeta(s) } } var compileBenchData = []struct{ name, re string }{ {"Onepass", `^a.[l-nA-Cg-j]?e$`}, {"Medium", `^((a|b|[d-z0-9])*(日){4,5}.)+$`}, {"Hard", strings.Repeat(`((abc)*|`, 50) + strings.Repeat(`)`, 50)}, } func BenchmarkCompile(b *testing.B) { for _, data := range compileBenchData { b.Run(data.name, func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := Compile(data.re); err != nil { b.Fatal(err) } } }) } } func TestDeepEqual(t *testing.T) { re1 := MustCompile("a.*b.*c.*d") re2 := MustCompile("a.*b.*c.*d") if !reflect.DeepEqual(re1, re2) { // has always been true, since Go 1. t.Errorf("DeepEqual(re1, re2) = false, want true") } re1.MatchString("abcdefghijklmn") if !reflect.DeepEqual(re1, re2) { t.Errorf("DeepEqual(re1, re2) = false, want true") } re2.MatchString("abcdefghijklmn") if !reflect.DeepEqual(re1, re2) { t.Errorf("DeepEqual(re1, re2) = false, want true") } re2.MatchString(strings.Repeat("abcdefghijklmn", 100)) if !reflect.DeepEqual(re1, re2) { t.Errorf("DeepEqual(re1, re2) = false, want true") } } var minInputLenTests = []struct { Regexp string min int }{ {``, 0}, {`a`, 1}, {`aa`, 2}, {`(aa)a`, 3}, {`(?:aa)a`, 3}, {`a?a`, 1}, {`(aaa)|(aa)`, 2}, {`(aa)+a`, 3}, {`(aa)*a`, 1}, {`(aa){3,5}`, 6}, {`[a-z]`, 1}, {`日`, 1}, } func TestMinInputLen(t *testing.T) { for _, tt := range minInputLenTests { re, _ := syntax.Parse(tt.Regexp, syntax.Perl) m := minInputLen(re) if m != tt.min { t.Errorf("regexp %#q has minInputLen %d, should be %d", tt.Regexp, m, tt.min) } } } binaryregexp-0.2.0/backtrack.go000066400000000000000000000215121347202265500164730ustar00rootroot00000000000000// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // backtrack is a regular expression search with submatch // tracking for small regular expressions and texts. It allocates // a bit vector with (length of input) * (length of prog) bits, // to make sure it never explores the same (character position, instruction) // state multiple times. This limits the search to run in time linear in // the length of the test. // // backtrack is a fast replacement for the NFA code on small // regexps when onepass cannot be used. package binaryregexp import ( "sync" "rsc.io/binaryregexp/syntax" ) // A job is an entry on the backtracker's job stack. It holds // the instruction pc and the position in the input. type job struct { pc uint32 arg bool pos int } const ( visitedBits = 32 maxBacktrackProg = 500 // len(prog.Inst) <= max maxBacktrackVector = 256 * 1024 // bit vector size <= max (bits) ) // bitState holds state for the backtracker. type bitState struct { end int cap []int matchcap []int jobs []job visited []uint32 inputs inputs } var bitStatePool sync.Pool func newBitState() *bitState { b, ok := bitStatePool.Get().(*bitState) if !ok { b = new(bitState) } return b } func freeBitState(b *bitState) { b.inputs.clear() bitStatePool.Put(b) } // maxBitStateLen returns the maximum length of a string to search with // the backtracker using prog. func maxBitStateLen(prog *syntax.Prog) int { if !shouldBacktrack(prog) { return 0 } return maxBacktrackVector / len(prog.Inst) } // shouldBacktrack reports whether the program is too // long for the backtracker to run. func shouldBacktrack(prog *syntax.Prog) bool { return len(prog.Inst) <= maxBacktrackProg } // reset resets the state of the backtracker. // end is the end position in the input. // ncap is the number of captures. func (b *bitState) reset(prog *syntax.Prog, end int, ncap int) { b.end = end if cap(b.jobs) == 0 { b.jobs = make([]job, 0, 256) } else { b.jobs = b.jobs[:0] } visitedSize := (len(prog.Inst)*(end+1) + visitedBits - 1) / visitedBits if cap(b.visited) < visitedSize { b.visited = make([]uint32, visitedSize, maxBacktrackVector/visitedBits) } else { b.visited = b.visited[:visitedSize] for i := range b.visited { b.visited[i] = 0 } } if cap(b.cap) < ncap { b.cap = make([]int, ncap) } else { b.cap = b.cap[:ncap] } for i := range b.cap { b.cap[i] = -1 } if cap(b.matchcap) < ncap { b.matchcap = make([]int, ncap) } else { b.matchcap = b.matchcap[:ncap] } for i := range b.matchcap { b.matchcap[i] = -1 } } // shouldVisit reports whether the combination of (pc, pos) has not // been visited yet. func (b *bitState) shouldVisit(pc uint32, pos int) bool { n := uint(int(pc)*(b.end+1) + pos) if b.visited[n/visitedBits]&(1<<(n&(visitedBits-1))) != 0 { return false } b.visited[n/visitedBits] |= 1 << (n & (visitedBits - 1)) return true } // push pushes (pc, pos, arg) onto the job stack if it should be // visited. func (b *bitState) push(re *Regexp, pc uint32, pos int, arg bool) { // Only check shouldVisit when arg is false. // When arg is true, we are continuing a previous visit. if re.prog.Inst[pc].Op != syntax.InstFail && (arg || b.shouldVisit(pc, pos)) { b.jobs = append(b.jobs, job{pc: pc, arg: arg, pos: pos}) } } // tryBacktrack runs a backtracking search starting at pos. func (re *Regexp) tryBacktrack(b *bitState, i input, pc uint32, pos int) bool { longest := re.longest b.push(re, pc, pos, false) for len(b.jobs) > 0 { l := len(b.jobs) - 1 // Pop job off the stack. pc := b.jobs[l].pc pos := b.jobs[l].pos arg := b.jobs[l].arg b.jobs = b.jobs[:l] // Optimization: rather than push and pop, // code that is going to Push and continue // the loop simply updates ip, p, and arg // and jumps to CheckAndLoop. We have to // do the ShouldVisit check that Push // would have, but we avoid the stack // manipulation. goto Skip CheckAndLoop: if !b.shouldVisit(pc, pos) { continue } Skip: inst := re.prog.Inst[pc] switch inst.Op { default: panic("bad inst") case syntax.InstFail: panic("unexpected InstFail") case syntax.InstAlt: // Cannot just // b.push(inst.Out, pos, false) // b.push(inst.Arg, pos, false) // If during the processing of inst.Out, we encounter // inst.Arg via another path, we want to process it then. // Pushing it here will inhibit that. Instead, re-push // inst with arg==true as a reminder to push inst.Arg out // later. if arg { // Finished inst.Out; try inst.Arg. arg = false pc = inst.Arg goto CheckAndLoop } else { b.push(re, pc, pos, true) pc = inst.Out goto CheckAndLoop } case syntax.InstAltMatch: // One opcode consumes runes; the other leads to match. switch re.prog.Inst[inst.Out].Op { case syntax.InstRune, syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL: // inst.Arg is the match. b.push(re, inst.Arg, pos, false) pc = inst.Arg pos = b.end goto CheckAndLoop } // inst.Out is the match - non-greedy b.push(re, inst.Out, b.end, false) pc = inst.Out goto CheckAndLoop case syntax.InstRune: r, width := i.step(pos) if !inst.MatchRune(r) { continue } pos += width pc = inst.Out goto CheckAndLoop case syntax.InstRune1: r, width := i.step(pos) if r != inst.Rune[0] { continue } pos += width pc = inst.Out goto CheckAndLoop case syntax.InstRuneAnyNotNL: r, width := i.step(pos) if r == '\n' || r == endOfText { continue } pos += width pc = inst.Out goto CheckAndLoop case syntax.InstRuneAny: r, width := i.step(pos) if r == endOfText { continue } pos += width pc = inst.Out goto CheckAndLoop case syntax.InstCapture: if arg { // Finished inst.Out; restore the old value. b.cap[inst.Arg] = pos continue } else { if 0 <= inst.Arg && inst.Arg < uint32(len(b.cap)) { // Capture pos to register, but save old value. b.push(re, pc, b.cap[inst.Arg], true) // come back when we're done. b.cap[inst.Arg] = pos } pc = inst.Out goto CheckAndLoop } case syntax.InstEmptyWidth: flag := i.context(pos) if !flag.match(syntax.EmptyOp(inst.Arg)) { continue } pc = inst.Out goto CheckAndLoop case syntax.InstNop: pc = inst.Out goto CheckAndLoop case syntax.InstMatch: // We found a match. If the caller doesn't care // where the match is, no point going further. if len(b.cap) == 0 { return true } // Record best match so far. // Only need to check end point, because this entire // call is only considering one start position. if len(b.cap) > 1 { b.cap[1] = pos } if old := b.matchcap[1]; old == -1 || (longest && pos > 0 && pos > old) { copy(b.matchcap, b.cap) } // If going for first match, we're done. if !longest { return true } // If we used the entire text, no longer match is possible. if pos == b.end { return true } // Otherwise, continue on in hope of a longer match. continue } } return longest && len(b.matchcap) > 1 && b.matchcap[1] >= 0 } // backtrack runs a backtracking search of prog on the input starting at pos. func (re *Regexp) backtrack(ib []byte, is string, pos int, ncap int, dstCap []int) []int { startCond := re.cond if startCond == ^syntax.EmptyOp(0) { // impossible return nil } if startCond&syntax.EmptyBeginText != 0 && pos != 0 { // Anchored match, past beginning of text. return nil } b := newBitState() i, end := b.inputs.init(nil, ib, is) b.reset(re.prog, end, ncap) // Anchored search must start at the beginning of the input if startCond&syntax.EmptyBeginText != 0 { if len(b.cap) > 0 { b.cap[0] = pos } if !re.tryBacktrack(b, i, uint32(re.prog.Start), pos) { freeBitState(b) return nil } } else { // Unanchored search, starting from each possible text position. // Notice that we have to try the empty string at the end of // the text, so the loop condition is pos <= end, not pos < end. // This looks like it's quadratic in the size of the text, // but we are not clearing visited between calls to TrySearch, // so no work is duplicated and it ends up still being linear. width := -1 for ; pos <= end && width != 0; pos += width { if len(re.prefix) > 0 { // Match requires literal prefix; fast search for it. advance := i.index(re, pos) if advance < 0 { freeBitState(b) return nil } pos += advance } if len(b.cap) > 0 { b.cap[0] = pos } if re.tryBacktrack(b, i, uint32(re.prog.Start), pos) { // Match must be leftmost; done. goto Match } _, width = i.step(pos) } freeBitState(b) return nil } Match: dstCap = append(dstCap, b.matchcap...) freeBitState(b) return dstCap } binaryregexp-0.2.0/example_test.go000066400000000000000000000220131347202265500172350ustar00rootroot00000000000000// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package binaryregexp_test import ( "fmt" "strings" "rsc.io/binaryregexp" ) func Example() { // Compile the expression once, usually at init time. // Use raw strings to avoid having to quote the backslashes. var validID = binaryregexp.MustCompile(`^[a-z]+\[[0-9]+\]$`) fmt.Println(validID.MatchString("adam[23]")) fmt.Println(validID.MatchString("eve[7]")) fmt.Println(validID.MatchString("Job[48]")) fmt.Println(validID.MatchString("snakey")) // Output: // true // true // false // false } func ExampleMatch() { matched, err := binaryregexp.Match(`foo.*`, []byte(`seafood`)) fmt.Println(matched, err) matched, err = binaryregexp.Match(`bar.*`, []byte(`seafood`)) fmt.Println(matched, err) matched, err = binaryregexp.Match(`a(b`, []byte(`seafood`)) fmt.Println(matched, err) // Output: // true // false // false error parsing regexp: missing closing ): `a(b` } func ExampleMatchString() { matched, err := binaryregexp.MatchString(`foo.*`, "seafood") fmt.Println(matched, err) matched, err = binaryregexp.MatchString(`bar.*`, "seafood") fmt.Println(matched, err) matched, err = binaryregexp.MatchString(`a(b`, "seafood") fmt.Println(matched, err) // Output: // true // false // false error parsing regexp: missing closing ): `a(b` } func ExampleQuoteMeta() { fmt.Println(binaryregexp.QuoteMeta(`Escaping symbols like: .+*?()|[]{}^$`)) // Output: // Escaping symbols like: \.\+\*\?\(\)\|\[\]\{\}\^\$ } func ExampleRegexp_Find() { re := binaryregexp.MustCompile(`foo.?`) fmt.Printf("%q\n", re.Find([]byte(`seafood fool`))) // Output: // "food" } func ExampleRegexp_FindAll() { re := binaryregexp.MustCompile(`foo.?`) fmt.Printf("%q\n", re.FindAll([]byte(`seafood fool`), -1)) // Output: // ["food" "fool"] } func ExampleRegexp_FindAllSubmatch() { re := binaryregexp.MustCompile(`foo(.?)`) fmt.Printf("%q\n", re.FindAllSubmatch([]byte(`seafood fool`), -1)) // Output: // [["food" "d"] ["fool" "l"]] } func ExampleRegexp_FindSubmatch() { re := binaryregexp.MustCompile(`foo(.?)`) fmt.Printf("%q\n", re.FindSubmatch([]byte(`seafood fool`))) // Output: // ["food" "d"] } func ExampleRegexp_Match() { re := binaryregexp.MustCompile(`foo.?`) fmt.Println(re.Match([]byte(`seafood fool`))) // Output: // true } func ExampleRegexp_FindString() { re := binaryregexp.MustCompile(`foo.?`) fmt.Printf("%q\n", re.FindString("seafood fool")) fmt.Printf("%q\n", re.FindString("meat")) // Output: // "food" // "" } func ExampleRegexp_FindStringIndex() { re := binaryregexp.MustCompile(`ab?`) fmt.Println(re.FindStringIndex("tablett")) fmt.Println(re.FindStringIndex("foo") == nil) // Output: // [1 3] // true } func ExampleRegexp_FindStringSubmatch() { re := binaryregexp.MustCompile(`a(x*)b(y|z)c`) fmt.Printf("%q\n", re.FindStringSubmatch("-axxxbyc-")) fmt.Printf("%q\n", re.FindStringSubmatch("-abzc-")) // Output: // ["axxxbyc" "xxx" "y"] // ["abzc" "" "z"] } func ExampleRegexp_FindAllString() { re := binaryregexp.MustCompile(`a.`) fmt.Println(re.FindAllString("paranormal", -1)) fmt.Println(re.FindAllString("paranormal", 2)) fmt.Println(re.FindAllString("graal", -1)) fmt.Println(re.FindAllString("none", -1)) // Output: // [ar an al] // [ar an] // [aa] // [] } func ExampleRegexp_FindAllStringSubmatch() { re := binaryregexp.MustCompile(`a(x*)b`) fmt.Printf("%q\n", re.FindAllStringSubmatch("-ab-", -1)) fmt.Printf("%q\n", re.FindAllStringSubmatch("-axxb-", -1)) fmt.Printf("%q\n", re.FindAllStringSubmatch("-ab-axb-", -1)) fmt.Printf("%q\n", re.FindAllStringSubmatch("-axxb-ab-", -1)) // Output: // [["ab" ""]] // [["axxb" "xx"]] // [["ab" ""] ["axb" "x"]] // [["axxb" "xx"] ["ab" ""]] } func ExampleRegexp_FindAllStringSubmatchIndex() { re := binaryregexp.MustCompile(`a(x*)b`) // Indices: // 01234567 012345678 // -ab-axb- -axxb-ab- fmt.Println(re.FindAllStringSubmatchIndex("-ab-", -1)) fmt.Println(re.FindAllStringSubmatchIndex("-axxb-", -1)) fmt.Println(re.FindAllStringSubmatchIndex("-ab-axb-", -1)) fmt.Println(re.FindAllStringSubmatchIndex("-axxb-ab-", -1)) fmt.Println(re.FindAllStringSubmatchIndex("-foo-", -1)) // Output: // [[1 3 2 2]] // [[1 5 2 4]] // [[1 3 2 2] [4 7 5 6]] // [[1 5 2 4] [6 8 7 7]] // [] } func ExampleRegexp_MatchString() { re := binaryregexp.MustCompile(`(gopher){2}`) fmt.Println(re.MatchString("gopher")) fmt.Println(re.MatchString("gophergopher")) fmt.Println(re.MatchString("gophergophergopher")) // Output: // false // true // true } func ExampleRegexp_ReplaceAllLiteralString() { re := binaryregexp.MustCompile(`a(x*)b`) fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-", "T")) fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-", "$1")) fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-", "${1}")) // Output: // -T-T- // -$1-$1- // -${1}-${1}- } func ExampleRegexp_ReplaceAllString() { re := binaryregexp.MustCompile(`a(x*)b`) fmt.Println(re.ReplaceAllString("-ab-axxb-", "T")) fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1")) fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1W")) fmt.Println(re.ReplaceAllString("-ab-axxb-", "${1}W")) // Output: // -T-T- // --xx- // --- // -W-xxW- } func ExampleRegexp_ReplaceAllStringFunc() { re := binaryregexp.MustCompile(`[^aeiou]`) fmt.Println(re.ReplaceAllStringFunc("seafood fool", strings.ToUpper)) // Output: // SeaFooD FooL } func ExampleRegexp_SubexpNames() { re := binaryregexp.MustCompile(`(?P[a-zA-Z]+) (?P[a-zA-Z]+)`) fmt.Println(re.MatchString("Alan Turing")) fmt.Printf("%q\n", re.SubexpNames()) reversed := fmt.Sprintf("${%s} ${%s}", re.SubexpNames()[2], re.SubexpNames()[1]) fmt.Println(reversed) fmt.Println(re.ReplaceAllString("Alan Turing", reversed)) // Output: // true // ["" "first" "last"] // ${last} ${first} // Turing Alan } func ExampleRegexp_Split() { a := binaryregexp.MustCompile(`a`) fmt.Println(a.Split("banana", -1)) fmt.Println(a.Split("banana", 0)) fmt.Println(a.Split("banana", 1)) fmt.Println(a.Split("banana", 2)) zp := binaryregexp.MustCompile(`z+`) fmt.Println(zp.Split("pizza", -1)) fmt.Println(zp.Split("pizza", 0)) fmt.Println(zp.Split("pizza", 1)) fmt.Println(zp.Split("pizza", 2)) // Output: // [b n n ] // [] // [banana] // [b nana] // [pi a] // [] // [pizza] // [pi a] } func ExampleRegexp_Expand() { content := []byte(` # comment line option1: value1 option2: value2 # another comment line option3: value3 `) // Regex pattern captures "key: value" pair from the content. pattern := binaryregexp.MustCompile(`(?m)(?P\w+):\s+(?P\w+)$`) // Template to convert "key: value" to "key=value" by // referencing the values captured by the regex pattern. template := []byte("$key=$value\n") result := []byte{} // For each match of the regex in the content. for _, submatches := range pattern.FindAllSubmatchIndex(content, -1) { // Apply the captured submatches to the template and append the output // to the result. result = pattern.Expand(result, template, content, submatches) } fmt.Println(string(result)) // Output: // option1=value1 // option2=value2 // option3=value3 } func ExampleRegexp_ExpandString() { content := ` # comment line option1: value1 option2: value2 # another comment line option3: value3 ` // Regex pattern captures "key: value" pair from the content. pattern := binaryregexp.MustCompile(`(?m)(?P\w+):\s+(?P\w+)$`) // Template to convert "key: value" to "key=value" by // referencing the values captured by the regex pattern. template := "$key=$value\n" result := []byte{} // For each match of the regex in the content. for _, submatches := range pattern.FindAllStringSubmatchIndex(content, -1) { // Apply the captured submatches to the template and append the output // to the result. result = pattern.ExpandString(result, template, content, submatches) } fmt.Println(string(result)) // Output: // option1=value1 // option2=value2 // option3=value3 } func ExampleRegexp_FindIndex() { content := []byte(` # comment line option1: value1 option2: value2 `) // Regex pattern captures "key: value" pair from the content. pattern := binaryregexp.MustCompile(`(?m)(?P\w+):\s+(?P\w+)$`) loc := pattern.FindIndex(content) fmt.Println(loc) fmt.Println(string(content[loc[0]:loc[1]])) // Output: // [18 33] // option1: value1 } func ExampleRegexp_FindAllSubmatchIndex() { content := []byte(` # comment line option1: value1 option2: value2 `) // Regex pattern captures "key: value" pair from the content. pattern := binaryregexp.MustCompile(`(?m)(?P\w+):\s+(?P\w+)$`) allIndexes := pattern.FindAllSubmatchIndex(content, -1) for _, loc := range allIndexes { fmt.Println(loc) fmt.Println(string(content[loc[0]:loc[1]])) fmt.Println(string(content[loc[2]:loc[3]])) fmt.Println(string(content[loc[4]:loc[5]])) } // Output: // [18 33 18 25 27 33] // option1: value1 // option1 // value1 // [35 50 35 42 44 50] // option2: value2 // option2 // value2 } binaryregexp-0.2.0/exec.go000066400000000000000000000304611347202265500154750ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package binaryregexp import ( "io" "sync" "rsc.io/binaryregexp/syntax" ) // A queue is a 'sparse array' holding pending threads of execution. // See https://research.swtch.com/2008/03/using-uninitialized-memory-for-fun-and.html type queue struct { sparse []uint32 dense []entry } // An entry is an entry on a queue. // It holds both the instruction pc and the actual thread. // Some queue entries are just place holders so that the machine // knows it has considered that pc. Such entries have t == nil. type entry struct { pc uint32 t *thread } // A thread is the state of a single path through the machine: // an instruction and a corresponding capture array. // See https://swtch.com/~rsc/regexp/regexp2.html type thread struct { inst *syntax.Inst cap []int } // A machine holds all the state during an NFA simulation for p. type machine struct { re *Regexp // corresponding Regexp p *syntax.Prog // compiled program q0, q1 queue // two queues for runq, nextq pool []*thread // pool of available threads matched bool // whether a match was found matchcap []int // capture information for the match inputs inputs } type inputs struct { // cached inputs, to avoid allocation bytes inputBytes string inputString reader inputReader } func (i *inputs) newBytes(b []byte) input { i.bytes.str = b return &i.bytes } func (i *inputs) newString(s string) input { i.string.str = s return &i.string } func (i *inputs) newReader(r io.ByteReader) input { i.reader.r = r i.reader.atEOT = false i.reader.pos = 0 return &i.reader } func (i *inputs) clear() { // We need to clear 1 of these. // Avoid the expense of clearing the others (pointer write barrier). if i.bytes.str != nil { i.bytes.str = nil } else if i.reader.r != nil { i.reader.r = nil } else { i.string.str = "" } } func (i *inputs) init(r io.ByteReader, b []byte, s string) (input, int) { if r != nil { return i.newReader(r), 0 } if b != nil { return i.newBytes(b), len(b) } return i.newString(s), len(s) } func (m *machine) init(ncap int) { for _, t := range m.pool { t.cap = t.cap[:ncap] } m.matchcap = m.matchcap[:ncap] } // alloc allocates a new thread with the given instruction. // It uses the free pool if possible. func (m *machine) alloc(i *syntax.Inst) *thread { var t *thread if n := len(m.pool); n > 0 { t = m.pool[n-1] m.pool = m.pool[:n-1] } else { t = new(thread) t.cap = make([]int, len(m.matchcap), cap(m.matchcap)) } t.inst = i return t } // A lazyFlag is a lazily-evaluated syntax.EmptyOp, // for checking zero-width flags like ^ $ \A \z \B \b. // It records the pair of relevant runes and does not // determine the implied flags until absolutely necessary // (most of the time, that means never). type lazyFlag uint64 func newLazyFlag(r1, r2 rune) lazyFlag { return lazyFlag(uint64(r1)<<32 | uint64(uint32(r2))) } func (f lazyFlag) match(op syntax.EmptyOp) bool { if op == 0 { return true } r1 := rune(f >> 32) if op&syntax.EmptyBeginLine != 0 { if r1 != '\n' && r1 >= 0 { return false } op &^= syntax.EmptyBeginLine } if op&syntax.EmptyBeginText != 0 { if r1 >= 0 { return false } op &^= syntax.EmptyBeginText } if op == 0 { return true } r2 := rune(f) if op&syntax.EmptyEndLine != 0 { if r2 != '\n' && r2 >= 0 { return false } op &^= syntax.EmptyEndLine } if op&syntax.EmptyEndText != 0 { if r2 >= 0 { return false } op &^= syntax.EmptyEndText } if op == 0 { return true } if syntax.IsWordChar(r1) != syntax.IsWordChar(r2) { op &^= syntax.EmptyWordBoundary } else { op &^= syntax.EmptyNoWordBoundary } return op == 0 } // match runs the machine over the input starting at pos. // It reports whether a match was found. // If so, m.matchcap holds the submatch information. func (m *machine) match(i input, pos int) bool { startCond := m.re.cond if startCond == ^syntax.EmptyOp(0) { // impossible return false } m.matched = false for i := range m.matchcap { m.matchcap[i] = -1 } runq, nextq := &m.q0, &m.q1 r, r1 := endOfText, endOfText width, width1 := 0, 0 r, width = i.step(pos) if r != endOfText { r1, width1 = i.step(pos + width) } var flag lazyFlag if pos == 0 { flag = newLazyFlag(-1, r) } else { flag = i.context(pos) } for { if len(runq.dense) == 0 { if startCond&syntax.EmptyBeginText != 0 && pos != 0 { // Anchored match, past beginning of text. break } if m.matched { // Have match; finished exploring alternatives. break } if len(m.re.prefix) > 0 && r1 != rune(m.re.prefix[0]) && i.canCheckPrefix() { // Match requires literal prefix; fast search for it. advance := i.index(m.re, pos) if advance < 0 { break } pos += advance r, width = i.step(pos) r1, width1 = i.step(pos + width) } } if !m.matched { if len(m.matchcap) > 0 { m.matchcap[0] = pos } m.add(runq, uint32(m.p.Start), pos, m.matchcap, &flag, nil) } flag = newLazyFlag(r, r1) m.step(runq, nextq, pos, pos+width, r, &flag) if width == 0 { break } if len(m.matchcap) == 0 && m.matched { // Found a match and not paying attention // to where it is, so any match will do. break } pos += width r, width = r1, width1 if r != endOfText { r1, width1 = i.step(pos + width) } runq, nextq = nextq, runq } m.clear(nextq) return m.matched } // clear frees all threads on the thread queue. func (m *machine) clear(q *queue) { for _, d := range q.dense { if d.t != nil { m.pool = append(m.pool, d.t) } } q.dense = q.dense[:0] } // step executes one step of the machine, running each of the threads // on runq and appending new threads to nextq. // The step processes the rune c (which may be endOfText), // which starts at position pos and ends at nextPos. // nextCond gives the setting for the empty-width flags after c. func (m *machine) step(runq, nextq *queue, pos, nextPos int, c rune, nextCond *lazyFlag) { longest := m.re.longest for j := 0; j < len(runq.dense); j++ { d := &runq.dense[j] t := d.t if t == nil { continue } if longest && m.matched && len(t.cap) > 0 && m.matchcap[0] < t.cap[0] { m.pool = append(m.pool, t) continue } i := t.inst add := false switch i.Op { default: panic("bad inst") case syntax.InstMatch: if len(t.cap) > 0 && (!longest || !m.matched || m.matchcap[1] < pos) { t.cap[1] = pos copy(m.matchcap, t.cap) } if !longest { // First-match mode: cut off all lower-priority threads. for _, d := range runq.dense[j+1:] { if d.t != nil { m.pool = append(m.pool, d.t) } } runq.dense = runq.dense[:0] } m.matched = true case syntax.InstRune: add = i.MatchRune(c) case syntax.InstRune1: add = c == i.Rune[0] case syntax.InstRuneAny: add = true case syntax.InstRuneAnyNotNL: add = c != '\n' } if add { t = m.add(nextq, i.Out, nextPos, t.cap, nextCond, t) } if t != nil { m.pool = append(m.pool, t) } } runq.dense = runq.dense[:0] } // add adds an entry to q for pc, unless the q already has such an entry. // It also recursively adds an entry for all instructions reachable from pc by following // empty-width conditions satisfied by cond. pos gives the current position // in the input. func (m *machine) add(q *queue, pc uint32, pos int, cap []int, cond *lazyFlag, t *thread) *thread { Again: if pc == 0 { return t } if j := q.sparse[pc]; j < uint32(len(q.dense)) && q.dense[j].pc == pc { return t } j := len(q.dense) q.dense = q.dense[:j+1] d := &q.dense[j] d.t = nil d.pc = pc q.sparse[pc] = uint32(j) i := &m.p.Inst[pc] switch i.Op { default: panic("unhandled") case syntax.InstFail: // nothing case syntax.InstAlt, syntax.InstAltMatch: t = m.add(q, i.Out, pos, cap, cond, t) pc = i.Arg goto Again case syntax.InstEmptyWidth: if cond.match(syntax.EmptyOp(i.Arg)) { pc = i.Out goto Again } case syntax.InstNop: pc = i.Out goto Again case syntax.InstCapture: if int(i.Arg) < len(cap) { opos := cap[i.Arg] cap[i.Arg] = pos m.add(q, i.Out, pos, cap, cond, nil) cap[i.Arg] = opos } else { pc = i.Out goto Again } case syntax.InstMatch, syntax.InstRune, syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL: if t == nil { t = m.alloc(i) } else { t.inst = i } if len(cap) > 0 && &t.cap[0] != &cap[0] { copy(t.cap, cap) } d.t = t t = nil } return t } type onePassMachine struct { inputs inputs matchcap []int } var onePassPool sync.Pool func newOnePassMachine() *onePassMachine { m, ok := onePassPool.Get().(*onePassMachine) if !ok { m = new(onePassMachine) } return m } func freeOnePassMachine(m *onePassMachine) { m.inputs.clear() onePassPool.Put(m) } // doOnePass implements r.doExecute using the one-pass execution engine. func (re *Regexp) doOnePass(ir io.ByteReader, ib []byte, is string, pos, ncap int, dstCap []int) []int { startCond := re.cond if startCond == ^syntax.EmptyOp(0) { // impossible return nil } m := newOnePassMachine() if cap(m.matchcap) < ncap { m.matchcap = make([]int, ncap) } else { m.matchcap = m.matchcap[:ncap] } matched := false for i := range m.matchcap { m.matchcap[i] = -1 } i, _ := m.inputs.init(ir, ib, is) r, r1 := endOfText, endOfText width, width1 := 0, 0 r, width = i.step(pos) if r != endOfText { r1, width1 = i.step(pos + width) } var flag lazyFlag if pos == 0 { flag = newLazyFlag(-1, r) } else { flag = i.context(pos) } pc := re.onepass.Start inst := re.onepass.Inst[pc] // If there is a simple literal prefix, skip over it. if pos == 0 && flag.match(syntax.EmptyOp(inst.Arg)) && len(re.prefix) > 0 && i.canCheckPrefix() { // Match requires literal prefix; fast search for it. if !i.hasPrefix(re) { goto Return } pos += len(re.prefix) r, width = i.step(pos) r1, width1 = i.step(pos + width) flag = i.context(pos) pc = int(re.prefixEnd) } for { inst = re.onepass.Inst[pc] pc = int(inst.Out) switch inst.Op { default: panic("bad inst") case syntax.InstMatch: matched = true if len(m.matchcap) > 0 { m.matchcap[0] = 0 m.matchcap[1] = pos } goto Return case syntax.InstRune: if !inst.MatchRune(r) { goto Return } case syntax.InstRune1: if r != inst.Rune[0] { goto Return } case syntax.InstRuneAny: // Nothing case syntax.InstRuneAnyNotNL: if r == '\n' { goto Return } // peek at the input rune to see which branch of the Alt to take case syntax.InstAlt, syntax.InstAltMatch: pc = int(onePassNext(&inst, r)) continue case syntax.InstFail: goto Return case syntax.InstNop: continue case syntax.InstEmptyWidth: if !flag.match(syntax.EmptyOp(inst.Arg)) { goto Return } continue case syntax.InstCapture: if int(inst.Arg) < len(m.matchcap) { m.matchcap[inst.Arg] = pos } continue } if width == 0 { break } flag = newLazyFlag(r, r1) pos += width r, width = r1, width1 if r != endOfText { r1, width1 = i.step(pos + width) } } Return: if !matched { freeOnePassMachine(m) return nil } dstCap = append(dstCap, m.matchcap...) freeOnePassMachine(m) return dstCap } // doMatch reports whether either r, b or s match the regexp. func (re *Regexp) doMatch(r io.ByteReader, b []byte, s string) bool { return re.doExecute(r, b, s, 0, 0, nil) != nil } // doExecute finds the leftmost match in the input, appends the position // of its subexpressions to dstCap and returns dstCap. // // nil is returned if no matches are found and non-nil if matches are found. func (re *Regexp) doExecute(r io.ByteReader, b []byte, s string, pos int, ncap int, dstCap []int) []int { if dstCap == nil { // Make sure 'return dstCap' is non-nil. dstCap = arrayNoInts[:0:0] } if r == nil && len(b)+len(s) < re.minInputLen { return nil } if re.onepass != nil { return re.doOnePass(r, b, s, pos, ncap, dstCap) } if r == nil && len(b)+len(s) < re.maxBitStateLen { return re.backtrack(b, s, pos, ncap, dstCap) } m := re.get() i, _ := m.inputs.init(r, b, s) m.init(ncap) if !m.match(i, pos) { re.put(m) return nil } dstCap = append(dstCap, m.matchcap...) re.put(m) return dstCap } // arrayNoInts is returned by doExecute match if nil dstCap is passed // to it with ncap=0. var arrayNoInts [0]int binaryregexp-0.2.0/exec2_test.go000066400000000000000000000010011347202265500166020ustar00rootroot00000000000000// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !race package binaryregexp import ( "testing" ) // This test is excluded when running under the race detector because // it is a very expensive test and takes too long. func TestRE2Exhaustive(t *testing.T) { if testing.Short() { t.Skip("skipping TestRE2Exhaustive during short test") } testRE2(t, "testdata/re2-exhaustive.txt.bz2") } binaryregexp-0.2.0/exec_test.go000066400000000000000000000514521347202265500165370ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package binaryregexp import ( "bufio" "compress/bzip2" "fmt" "io" "os" "path/filepath" "strconv" "strings" "testing" "unicode/utf8" "rsc.io/binaryregexp/syntax" ) // TestRE2 tests this package's regexp API against test cases // considered during RE2's exhaustive tests, which run all possible // regexps over a given set of atoms and operators, up to a given // complexity, over all possible strings over a given alphabet, // up to a given size. Rather than try to link with RE2, we read a // log file containing the test cases and the expected matches. // The log file, re2-exhaustive.txt, is generated by running 'make log' // in the open source RE2 distribution https://github.com/google/re2/. // // The test file format is a sequence of stanzas like: // // strings // "abc" // "123x" // regexps // "[a-z]+" // 0-3;0-3 // -;- // "([0-9])([0-9])([0-9])" // -;- // -;0-3 0-1 1-2 2-3 // // The stanza begins by defining a set of strings, quoted // using Go double-quote syntax, one per line. Then the // regexps section gives a sequence of regexps to run on // the strings. In the block that follows a regexp, each line // gives the semicolon-separated match results of running // the regexp on the corresponding string. // Each match result is either a single -, meaning no match, or a // space-separated sequence of pairs giving the match and // submatch indices. An unmatched subexpression formats // its pair as a single - (not illustrated above). For now // each regexp run produces two match results, one for a // ``full match'' that restricts the regexp to matching the entire // string or nothing, and one for a ``partial match'' that gives // the leftmost first match found in the string. // // Lines beginning with # are comments. Lines beginning with // a capital letter are test names printed during RE2's test suite // and are echoed into t but otherwise ignored. // // At time of writing, re2-exhaustive.txt is 59 MB but compresses to 385 kB, // so we store re2-exhaustive.txt.bz2 in the repository and decompress it on the fly. // func TestRE2Search(t *testing.T) { testRE2(t, "testdata/re2-search.txt") } func testRE2(t *testing.T, file string) { t.Skip("skipping - RE2 testdata assumes UTF-8") f, err := os.Open(file) if err != nil { t.Fatal(err) } defer f.Close() 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 } lineno := 0 scanner := bufio.NewScanner(txt) var ( str []string input []string inStrings bool re *Regexp refull *Regexp nfail int ncase int ) for lineno := 1; scanner.Scan(); lineno++ { line := scanner.Text() switch { case line == "": t.Fatalf("%s:%d: unexpected blank line", file, lineno) case line[0] == '#': continue case 'A' <= line[0] && line[0] <= 'Z': // Test name. t.Logf("%s\n", line) continue case line == "strings": str = str[:0] inStrings = true case line == "regexps": inStrings = false case line[0] == '"': q, err := strconv.Unquote(line) if err != nil { // Fatal because we'll get out of sync. t.Fatalf("%s:%d: unquote %s: %v", file, lineno, line, err) } if inStrings { str = append(str, q) continue } // Is a regexp. if len(input) != 0 { 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 { if err.Error() == "error parsing regexp: invalid escape sequence: `\\C`" { // We don't and likely never will support \C; keep going. continue } t.Errorf("%s:%d: compile %#q: %v", file, lineno, q, err) if nfail++; nfail >= 100 { t.Fatalf("stopping after %d errors", nfail) } continue } full := `\A(?:` + q + `)\z` refull, err = tryCompile(full) if err != nil { // Fatal because q worked, so this should always work. t.Fatalf("%s:%d: compile full %#q: %v", file, lineno, full, err) } input = str case line[0] == '-' || '0' <= line[0] && line[0] <= '9': // A sequence of match results. ncase++ if re == nil { // Failed to compile: skip results. continue } if len(input) == 0 { t.Fatalf("%s:%d: out of sync: no input remaining", file, lineno) } var text string text, input = input[0], input[1:] if !isSingleBytes(text) && strings.Contains(re.String(), `\B`) { // RE2's \B considers every byte position, // so it sees 'not word boundary' in the // middle of UTF-8 sequences. This package // only considers the positions between runes, // so it disagrees. Skip those cases. continue } res := strings.Split(line, ";") if 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, file, lineno, res[i]) if !same(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) } continue } b, suffix := match[i](re, refull, text) if b != (want != nil) { 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) } continue } } default: t.Fatalf("%s:%d: out of sync: %s\n", file, lineno, line) } } if err := scanner.Err(); err != nil { t.Fatalf("%s:%d: %v", file, lineno, err) } if len(input) != 0 { t.Fatalf("%s:%d: out of sync: have %d strings left at EOF", file, lineno, len(input)) } t.Logf("%d cases tested", ncase) } var run = []func(*Regexp, *Regexp, string) ([]int, string){ runFull, runPartial, runFullLongest, runPartialLongest, } func runFull(re, refull *Regexp, text string) ([]int, string) { refull.longest = false return refull.FindStringSubmatchIndex(text), "[full]" } func runPartial(re, refull *Regexp, text string) ([]int, string) { re.longest = false return re.FindStringSubmatchIndex(text), "" } func runFullLongest(re, refull *Regexp, text string) ([]int, string) { refull.longest = true return refull.FindStringSubmatchIndex(text), "[full,longest]" } func runPartialLongest(re, refull *Regexp, text string) ([]int, string) { re.longest = true return re.FindStringSubmatchIndex(text), "[longest]" } var match = []func(*Regexp, *Regexp, string) (bool, string){ matchFull, matchPartial, matchFullLongest, matchPartialLongest, } func matchFull(re, refull *Regexp, text string) (bool, string) { refull.longest = false return refull.MatchString(text), "[full]" } func matchPartial(re, refull *Regexp, text string) (bool, string) { re.longest = false return re.MatchString(text), "" } func matchFullLongest(re, refull *Regexp, text string) (bool, string) { refull.longest = true return refull.MatchString(text), "[full,longest]" } func matchPartialLongest(re, refull *Regexp, text string) (bool, string) { re.longest = true return re.MatchString(text), "[longest]" } func isSingleBytes(s string) bool { for _, c := range s { if c >= utf8.RuneSelf { return false } } return true } func tryCompile(s string) (re *Regexp, err error) { // Protect against panic during Compile. defer func() { if r := recover(); r != nil { err = fmt.Errorf("panic: %v", r) } }() return Compile(s) } func parseResult(t *testing.T, file string, lineno int, res string) []int { // A single - indicates no match. if res == "-" { return nil } // Otherwise, a space-separated list of pairs. n := 1 for j := 0; j < len(res); j++ { if res[j] == ' ' { n++ } } out := make([]int, 2*n) i := 0 n = 0 for j := 0; j <= len(res); j++ { if j == len(res) || res[j] == ' ' { // Process a single pair. - means no submatch. pair := res[i:j] if pair == "-" { out[n] = -1 out[n+1] = -1 } else { k := strings.Index(pair, "-") if k < 0 { 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("%s:%d: invalid pair %s", file, lineno, pair) } out[n] = lo out[n+1] = hi } n += 2 i = j + 1 } } return out } func same(x, y []int) bool { if len(x) != len(y) { return false } for i, xi := range x { if xi != y[i] { return false } } 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/~astopen/testregex/testregex.html. 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 = MustCompilePOSIX(`[^\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 != io.EOF { t.Errorf("%s:%d: %v", file, lineno, err) } break Reading } // http://www2.research.att.com/~astopen/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 escape [...] 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, pattern, 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 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 } var text []byte func makeText(n int) []byte { if len(text) >= n { return text[:n] } text = make([]byte, n) x := ^uint32(0) for i := range text { x += x x ^= 1 if int32(x) < 0 { x ^= 0x88888eef } if x%31 == 0 { text[i] = '\n' } else { text[i] = byte(x%(0x7E+1-0x20) + 0x20) } } return text } func BenchmarkMatch(b *testing.B) { isRaceBuilder := false for _, data := range benchData { r := MustCompile(data.re) for _, size := range benchSizes { if isRaceBuilder && size.n > 1<<10 { continue } t := makeText(size.n) b.Run(data.name+"/"+size.name, func(b *testing.B) { b.SetBytes(int64(size.n)) for i := 0; i < b.N; i++ { if r.Match(t) { b.Fatal("match!") } } }) } } } func BenchmarkMatch_onepass_regex(b *testing.B) { isRaceBuilder := false r := MustCompile(`(?s)\A.*\z`) if r.onepass == nil { b.Fatalf("want onepass regex, but %q is not onepass", r) } for _, size := range benchSizes { if isRaceBuilder && size.n > 1<<10 { continue } t := makeText(size.n) b.Run(size.name, func(b *testing.B) { b.SetBytes(int64(size.n)) b.ReportAllocs() for i := 0; i < b.N; i++ { if !r.Match(t) { b.Fatal("not match!") } } }) } } var benchData = []struct{ name, re string }{ {"Easy0", "ABCDEFGHIJKLMNOPQRSTUVWXYZ$"}, {"Easy0i", "(?i)ABCDEFGHIJklmnopqrstuvwxyz$"}, {"Easy1", "A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$"}, {"Medium", "[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$"}, {"Hard", "[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$"}, {"Hard1", "ABCD|CDEF|EFGH|GHIJ|IJKL|KLMN|MNOP|OPQR|QRST|STUV|UVWX|WXYZ"}, } var benchSizes = []struct { name string n int }{ {"16", 16}, {"32", 32}, {"1K", 1 << 10}, {"32K", 32 << 10}, {"1M", 1 << 20}, {"32M", 32 << 20}, } func TestLongest(t *testing.T) { re, err := Compile(`a(|b)`) if err != nil { t.Fatal(err) } if g, w := re.FindString("ab"), "a"; g != w { t.Errorf("first match was %q, want %q", g, w) } re.Longest() if g, w := re.FindString("ab"), "ab"; g != w { t.Errorf("longest match was %q, want %q", g, w) } } // TestProgramTooLongForBacktrack tests that a regex which is too long // for the backtracker still executes properly. func TestProgramTooLongForBacktrack(t *testing.T) { longRegex := MustCompile(`(one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty|twentyone|twentytwo|twentythree|twentyfour|twentyfive|twentysix|twentyseven|twentyeight|twentynine|thirty|thirtyone|thirtytwo|thirtythree|thirtyfour|thirtyfive|thirtysix|thirtyseven|thirtyeight|thirtynine|forty|fortyone|fortytwo|fortythree|fortyfour|fortyfive|fortysix|fortyseven|fortyeight|fortynine|fifty|fiftyone|fiftytwo|fiftythree|fiftyfour|fiftyfive|fiftysix|fiftyseven|fiftyeight|fiftynine|sixty|sixtyone|sixtytwo|sixtythree|sixtyfour|sixtyfive|sixtysix|sixtyseven|sixtyeight|sixtynine|seventy|seventyone|seventytwo|seventythree|seventyfour|seventyfive|seventysix|seventyseven|seventyeight|seventynine|eighty|eightyone|eightytwo|eightythree|eightyfour|eightyfive|eightysix|eightyseven|eightyeight|eightynine|ninety|ninetyone|ninetytwo|ninetythree|ninetyfour|ninetyfive|ninetysix|ninetyseven|ninetyeight|ninetynine|onehundred)`) if !longRegex.MatchString("two") { t.Errorf("longRegex.MatchString(\"two\") was false, want true") } if longRegex.MatchString("xxx") { t.Errorf("longRegex.MatchString(\"xxx\") was true, want false") } } binaryregexp-0.2.0/find_test.go000066400000000000000000000401111347202265500165210ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package binaryregexp import ( "fmt" "strings" "testing" ) // For each pattern/text pair, what is the expected output of each function? // We can derive the textual results from the indexed results, the non-submatch // results from the submatched results, the single results from the 'all' results, // and the byte results from the string results. Therefore the table includes // only the FindAllStringSubmatchIndex result. type FindTest struct { pat string text string matches [][]int } func (t FindTest) String() string { return fmt.Sprintf("pat: %#q text: %#q", t.pat, t.text) } var findTests = []FindTest{ {`Æ`, "\xC6", build(1, 0, 1)}, {``, ``, build(1, 0, 0)}, {`^abcdefg`, "abcdefg", build(1, 0, 7)}, {`a+`, "baaab", build(1, 1, 4)}, {"abcd..", "abcdef", build(1, 0, 6)}, {`a`, "a", build(1, 0, 1)}, {`x`, "y", nil}, {`b`, "abc", build(1, 1, 2)}, {`.`, "a", build(1, 0, 1)}, {`.*`, "abcdef", build(1, 0, 6)}, {`^`, "abcde", build(1, 0, 0)}, {`$`, "abcde", build(1, 5, 5)}, {`^abcd$`, "abcd", build(1, 0, 4)}, {`^bcd'`, "abcdef", nil}, {`^abcd$`, "abcde", nil}, {`a+`, "baaab", build(1, 1, 4)}, {`a*`, "baaab", build(3, 0, 0, 1, 4, 5, 5)}, {`[a-z]+`, "abcd", build(1, 0, 4)}, {`[^a-z]+`, "ab1234cd", build(1, 2, 6)}, {`[a\-\]z]+`, "az]-bcz", build(2, 0, 4, 6, 7)}, {`[^\n]+`, "abcd\n", build(1, 0, 4)}, {`[日本語]+`, "日本語日本語", nil}, {`日本語+`, "日本語", nil}, {`日本語+`, "日本語語語語", nil}, {`Æ`, "\xC6", build(1, 0, 1)}, {`ÆÌÓÿ`, "\xC6\xCC\xD3\xFF", build(1, 0, 4)}, {`()`, "", build(1, 0, 0, 0, 0)}, {`(a)`, "a", build(1, 0, 1, 0, 1)}, {`(.)(.)`, "日a", build(2, 0, 2, 0, 1, 1, 2, 2, 4, 2, 3, 3, 4)}, {`(.*)`, "", build(1, 0, 0, 0, 0)}, {`(.*)`, "abcd", build(1, 0, 4, 0, 4)}, {`(..)(..)`, "abcd", build(1, 0, 4, 0, 2, 2, 4)}, {`(([^xyz]*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 3, 4)}, {`((a|b|c)*(d))`, "abcd", build(1, 0, 4, 0, 4, 2, 3, 3, 4)}, {`(((a|b|c)*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)}, {`\a\f\n\r\t\v`, "\a\f\n\r\t\v", build(1, 0, 6)}, {`[\a\f\n\r\t\v]+`, "\a\f\n\r\t\v", build(1, 0, 6)}, {`a*(|(b))c*`, "aacc", build(1, 0, 4, 2, 2, -1, -1)}, {`(.*).*`, "ab", build(1, 0, 2, 0, 2)}, {`[.]`, ".", build(1, 0, 1)}, {`/$`, "/abc/", build(1, 4, 5)}, {`/$`, "/abc", nil}, // multiple matches {`.`, "abc", build(3, 0, 1, 1, 2, 2, 3)}, {`(.)`, "abc", build(3, 0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 2, 3)}, {`.(.)`, "abcd", build(2, 0, 2, 1, 2, 2, 4, 3, 4)}, {`ab*`, "abbaab", build(3, 0, 3, 3, 4, 4, 6)}, {`a(b*)`, "abbaab", build(3, 0, 3, 1, 3, 3, 4, 4, 4, 4, 6, 5, 6)}, // fixed bugs {`ab$`, "cab", build(1, 1, 3)}, {`axxb$`, "axxcb", nil}, {`data`, "daXY data", build(1, 5, 9)}, {`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)}, {`zx+`, "zzx", build(1, 1, 3)}, {`ab$`, "abcab", build(1, 3, 5)}, {`(aa)*$`, "a", build(1, 1, 1, -1, -1)}, {`(?:.|(?:.a))`, "", nil}, {`(?:A(?:A|a))`, "Aa", build(1, 0, 2)}, {`(?:A|(?:A|a))`, "a", build(1, 0, 1)}, {`(a){0}`, "", build(1, 0, 0, -1, -1)}, {`(?-s)(?:(?:^).)`, "\n", nil}, {`(?s)(?:(?:^).)`, "\n", build(1, 0, 1)}, {`(?:(?:^).)`, "\n", nil}, {`\b`, "x", build(2, 0, 0, 1, 1)}, {`\b`, "xx", build(2, 0, 0, 2, 2)}, {`\b`, "x y", build(4, 0, 0, 1, 1, 2, 2, 3, 3)}, {`\b`, "xx yy", build(4, 0, 0, 2, 2, 3, 3, 5, 5)}, {`\B`, "x", nil}, {`\B`, "xx", build(1, 1, 1)}, {`\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)}, {`[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~]+`, `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)}, {"\\`", "`", build(1, 0, 1)}, {"[\\`]+", "`", build(1, 0, 1)}, // long set of matches (longer than startSize) { ".", "qwertyuiopasdfghjklzxcvbnm1234567890", build(36, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36), }, } // build is a helper to construct a [][]int by extracting n sequences from x. // This represents n matches with len(x)/n submatches each. func build(n int, x ...int) [][]int { ret := make([][]int, n) runLength := len(x) / n j := 0 for i := range ret { ret[i] = make([]int, runLength) copy(ret[i], x[j:]) j += runLength if j > len(x) { panic("invalid build entry") } } return ret } // First the simple cases. func TestFind(t *testing.T) { for _, test := range findTests { re := MustCompile(test.pat) if re.String() != test.pat { t.Errorf("String() = `%s`; should be `%s`", re.String(), test.pat) } result := re.Find([]byte(test.text)) switch { case len(test.matches) == 0 && len(result) == 0: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Errorf("expected match; got none: %s", test) case test.matches != nil && result != nil: expect := test.text[test.matches[0][0]:test.matches[0][1]] if len(result) != cap(result) { t.Errorf("expected capacity %d got %d: %s", len(result), cap(result), test) } if expect != string(result) { t.Errorf("expected %q got %q: %s", expect, result, test) } } } } func TestFindString(t *testing.T) { for _, test := range findTests { result := MustCompile(test.pat).FindString(test.text) switch { case len(test.matches) == 0 && len(result) == 0: // ok case test.matches == nil && result != "": t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == "": // Tricky because an empty result has two meanings: no match or empty match. if test.matches[0][0] != test.matches[0][1] { t.Errorf("expected match; got none: %s", test) } case test.matches != nil && result != "": expect := test.text[test.matches[0][0]:test.matches[0][1]] if expect != result { t.Errorf("expected %q got %q: %s", expect, result, test) } } } } func testFindIndex(test *FindTest, result []int, t *testing.T) { switch { case len(test.matches) == 0 && len(result) == 0: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Errorf("expected match; got none: %s", test) case test.matches != nil && result != nil: expect := test.matches[0] if expect[0] != result[0] || expect[1] != result[1] { t.Errorf("expected %v got %v: %s", expect, result, test) } } } func TestFindIndex(t *testing.T) { for _, test := range findTests { testFindIndex(&test, MustCompile(test.pat).FindIndex([]byte(test.text)), t) } } func TestFindStringIndex(t *testing.T) { for _, test := range findTests { testFindIndex(&test, MustCompile(test.pat).FindStringIndex(test.text), t) } } func TestFindReaderIndex(t *testing.T) { for _, test := range findTests { testFindIndex(&test, MustCompile(test.pat).FindReaderIndex(strings.NewReader(test.text)), t) } } // Now come the simple All cases. func TestFindAll(t *testing.T) { for _, test := range findTests { result := MustCompile(test.pat).FindAll([]byte(test.text), -1) switch { case test.matches == nil && result == nil: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Fatalf("expected match; got none: %s", test) case test.matches != nil && result != nil: if len(test.matches) != len(result) { t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test) continue } for k, e := range test.matches { got := result[k] if len(got) != cap(got) { t.Errorf("match %d: expected capacity %d got %d: %s", k, len(got), cap(got), test) } expect := test.text[e[0]:e[1]] if expect != string(got) { t.Errorf("match %d: expected %q got %q: %s", k, expect, got, test) } } } } } func TestFindAllString(t *testing.T) { for _, test := range findTests { result := MustCompile(test.pat).FindAllString(test.text, -1) switch { case test.matches == nil && result == nil: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Errorf("expected match; got none: %s", test) case test.matches != nil && result != nil: if len(test.matches) != len(result) { t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test) continue } for k, e := range test.matches { expect := test.text[e[0]:e[1]] if expect != result[k] { t.Errorf("expected %q got %q: %s", expect, result, test) } } } } } func testFindAllIndex(test *FindTest, result [][]int, t *testing.T) { switch { case test.matches == nil && result == nil: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Errorf("expected match; got none: %s", test) case test.matches != nil && result != nil: if len(test.matches) != len(result) { t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test) return } for k, e := range test.matches { if e[0] != result[k][0] || e[1] != result[k][1] { t.Errorf("match %d: expected %v got %v: %s", k, e, result[k], test) } } } } func TestFindAllIndex(t *testing.T) { for _, test := range findTests { testFindAllIndex(&test, MustCompile(test.pat).FindAllIndex([]byte(test.text), -1), t) } } func TestFindAllStringIndex(t *testing.T) { for _, test := range findTests { testFindAllIndex(&test, MustCompile(test.pat).FindAllStringIndex(test.text, -1), t) } } // Now come the Submatch cases. func testSubmatchBytes(test *FindTest, n int, submatches []int, result [][]byte, t *testing.T) { if len(submatches) != len(result)*2 { t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test) return } for k := 0; k < len(submatches); k += 2 { if submatches[k] == -1 { if result[k/2] != nil { t.Errorf("match %d: expected nil got %q: %s", n, result, test) } continue } got := result[k/2] if len(got) != cap(got) { t.Errorf("match %d: expected capacity %d got %d: %s", n, len(got), cap(got), test) return } expect := test.text[submatches[k]:submatches[k+1]] if expect != string(got) { t.Errorf("match %d: expected %q got %q: %s", n, expect, got, test) return } } } func TestFindSubmatch(t *testing.T) { for _, test := range findTests { result := MustCompile(test.pat).FindSubmatch([]byte(test.text)) switch { case test.matches == nil && result == nil: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Errorf("expected match; got none: %s", test) case test.matches != nil && result != nil: testSubmatchBytes(&test, 0, test.matches[0], result, t) } } } func testSubmatchString(test *FindTest, n int, submatches []int, result []string, t *testing.T) { if len(submatches) != len(result)*2 { t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test) return } for k := 0; k < len(submatches); k += 2 { if submatches[k] == -1 { if result[k/2] != "" { t.Errorf("match %d: expected nil got %q: %s", n, result, test) } continue } expect := test.text[submatches[k]:submatches[k+1]] if expect != result[k/2] { t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test) return } } } func TestFindStringSubmatch(t *testing.T) { for _, test := range findTests { result := MustCompile(test.pat).FindStringSubmatch(test.text) switch { case test.matches == nil && result == nil: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Errorf("expected match; got none: %s", test) case test.matches != nil && result != nil: testSubmatchString(&test, 0, test.matches[0], result, t) } } } func testSubmatchIndices(test *FindTest, n int, expect, result []int, t *testing.T) { if len(expect) != len(result) { t.Errorf("match %d: expected %d matches; got %d: %s", n, len(expect)/2, len(result)/2, test) return } for k, e := range expect { if e != result[k] { t.Errorf("match %d: submatch error: expected %v got %v: %s", n, expect, result, test) } } } func testFindSubmatchIndex(test *FindTest, result []int, t *testing.T) { switch { case test.matches == nil && result == nil: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Errorf("expected match; got none: %s", test) case test.matches != nil && result != nil: testSubmatchIndices(test, 0, test.matches[0], result, t) } } func TestFindSubmatchIndex(t *testing.T) { for _, test := range findTests { testFindSubmatchIndex(&test, MustCompile(test.pat).FindSubmatchIndex([]byte(test.text)), t) } } func TestFindStringSubmatchIndex(t *testing.T) { for _, test := range findTests { testFindSubmatchIndex(&test, MustCompile(test.pat).FindStringSubmatchIndex(test.text), t) } } func TestFindReaderSubmatchIndex(t *testing.T) { for _, test := range findTests { testFindSubmatchIndex(&test, MustCompile(test.pat).FindReaderSubmatchIndex(strings.NewReader(test.text)), t) } } // Now come the monster AllSubmatch cases. func TestFindAllSubmatch(t *testing.T) { for _, test := range findTests { result := MustCompile(test.pat).FindAllSubmatch([]byte(test.text), -1) switch { case test.matches == nil && result == nil: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Errorf("expected match; got none: %s", test) case len(test.matches) != len(result): t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test) case test.matches != nil && result != nil: for k, match := range test.matches { testSubmatchBytes(&test, k, match, result[k], t) } } } } func TestFindAllStringSubmatch(t *testing.T) { for _, test := range findTests { result := MustCompile(test.pat).FindAllStringSubmatch(test.text, -1) switch { case test.matches == nil && result == nil: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Errorf("expected match; got none: %s", test) case len(test.matches) != len(result): t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test) case test.matches != nil && result != nil: for k, match := range test.matches { testSubmatchString(&test, k, match, result[k], t) } } } } func testFindAllSubmatchIndex(test *FindTest, result [][]int, t *testing.T) { switch { case test.matches == nil && result == nil: // ok case test.matches == nil && result != nil: t.Errorf("expected no match; got one: %s", test) case test.matches != nil && result == nil: t.Errorf("expected match; got none: %s", test) case len(test.matches) != len(result): t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test) case test.matches != nil && result != nil: for k, match := range test.matches { testSubmatchIndices(test, k, match, result[k], t) } } } func TestFindAllSubmatchIndex(t *testing.T) { for _, test := range findTests { testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllSubmatchIndex([]byte(test.text), -1), t) } } func TestFindAllStringSubmatchIndex(t *testing.T) { for _, test := range findTests { testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllStringSubmatchIndex(test.text, -1), t) } } binaryregexp-0.2.0/go.mod000066400000000000000000000000441347202265500153220ustar00rootroot00000000000000module rsc.io/binaryregexp go 1.12 binaryregexp-0.2.0/onepass.go000066400000000000000000000340311347202265500162160ustar00rootroot00000000000000// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package binaryregexp import ( "bytes" "sort" "unicode" "rsc.io/binaryregexp/syntax" ) // "One-pass" regexp execution. // Some regexps can be analyzed to determine that they never need // backtracking: they are guaranteed to run in one pass over the string // without bothering to save all the usual NFA state. // Detect those and execute them more quickly. // A onePassProg is a compiled one-pass regular expression program. // It is the same as syntax.Prog except for the use of onePassInst. type onePassProg struct { Inst []onePassInst Start int // index of start instruction NumCap int // number of InstCapture insts in re } // A onePassInst is a single instruction in a one-pass regular expression program. // It is the same as syntax.Inst except for the new 'Next' field. type onePassInst struct { syntax.Inst Next []uint32 } // OnePassPrefix returns a literal string that all matches for the // regexp must start with. Complete is true if the prefix // is the entire match. Pc is the index of the last rune instruction // in the string. The OnePassPrefix skips over the mandatory // EmptyBeginText func onePassPrefix(p *syntax.Prog) (prefix string, complete bool, pc uint32) { i := &p.Inst[p.Start] if i.Op != syntax.InstEmptyWidth || (syntax.EmptyOp(i.Arg))&syntax.EmptyBeginText == 0 { return "", i.Op == syntax.InstMatch, uint32(p.Start) } pc = i.Out i = &p.Inst[pc] for i.Op == syntax.InstNop { pc = i.Out i = &p.Inst[pc] } // Avoid allocation of buffer if prefix is empty. if iop(i) != syntax.InstRune || len(i.Rune) != 1 { return "", i.Op == syntax.InstMatch, uint32(p.Start) } // Have prefix; gather characters. var buf bytes.Buffer for iop(i) == syntax.InstRune && len(i.Rune) == 1 && i.Rune[0] <= 0xFF && syntax.Flags(i.Arg)&syntax.FoldCase == 0 { buf.WriteByte(byte(i.Rune[0])) pc, i = i.Out, &p.Inst[i.Out] } if i.Op == syntax.InstEmptyWidth && syntax.EmptyOp(i.Arg)&syntax.EmptyEndText != 0 && p.Inst[i.Out].Op == syntax.InstMatch { complete = true } return buf.String(), complete, pc } // OnePassNext selects the next actionable state of the prog, based on the input character. // It should only be called when i.Op == InstAlt or InstAltMatch, and from the one-pass machine. // One of the alternates may ultimately lead without input to end of line. If the instruction // is InstAltMatch the path to the InstMatch is in i.Out, the normal node in i.Next. func onePassNext(i *onePassInst, r rune) uint32 { next := i.MatchRunePos(r) if next >= 0 { return i.Next[next] } if i.Op == syntax.InstAltMatch { return i.Out } return 0 } func iop(i *syntax.Inst) syntax.InstOp { op := i.Op switch op { case syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL: op = syntax.InstRune } return op } // Sparse Array implementation is used as a queueOnePass. type queueOnePass struct { sparse []uint32 dense []uint32 size, nextIndex uint32 } func (q *queueOnePass) empty() bool { return q.nextIndex >= q.size } func (q *queueOnePass) next() (n uint32) { n = q.dense[q.nextIndex] q.nextIndex++ return } func (q *queueOnePass) clear() { q.size = 0 q.nextIndex = 0 } func (q *queueOnePass) contains(u uint32) bool { if u >= uint32(len(q.sparse)) { return false } return q.sparse[u] < q.size && q.dense[q.sparse[u]] == u } func (q *queueOnePass) insert(u uint32) { if !q.contains(u) { q.insertNew(u) } } func (q *queueOnePass) insertNew(u uint32) { if u >= uint32(len(q.sparse)) { return } q.sparse[u] = q.size q.dense[q.size] = u q.size++ } func newQueue(size int) (q *queueOnePass) { return &queueOnePass{ sparse: make([]uint32, size), dense: make([]uint32, size), } } // mergeRuneSets merges two non-intersecting runesets, and returns the merged result, // and a NextIp array. The idea is that if a rune matches the OnePassRunes at index // i, NextIp[i/2] is the target. If the input sets intersect, an empty runeset and a // NextIp array with the single element mergeFailed is returned. // The code assumes that both inputs contain ordered and non-intersecting rune pairs. const mergeFailed = uint32(0xffffffff) var ( noRune = []rune{} noNext = []uint32{mergeFailed} ) func mergeRuneSets(leftRunes, rightRunes *[]rune, leftPC, rightPC uint32) ([]rune, []uint32) { leftLen := len(*leftRunes) rightLen := len(*rightRunes) if leftLen&0x1 != 0 || rightLen&0x1 != 0 { panic("mergeRuneSets odd length []rune") } var ( lx, rx int ) merged := make([]rune, 0) next := make([]uint32, 0) ok := true defer func() { if !ok { merged = nil next = nil } }() ix := -1 extend := func(newLow *int, newArray *[]rune, pc uint32) bool { if ix > 0 && (*newArray)[*newLow] <= merged[ix] { return false } merged = append(merged, (*newArray)[*newLow], (*newArray)[*newLow+1]) *newLow += 2 ix += 2 next = append(next, pc) return true } for lx < leftLen || rx < rightLen { switch { case rx >= rightLen: ok = extend(&lx, leftRunes, leftPC) case lx >= leftLen: ok = extend(&rx, rightRunes, rightPC) case (*rightRunes)[rx] < (*leftRunes)[lx]: ok = extend(&rx, rightRunes, rightPC) default: ok = extend(&lx, leftRunes, leftPC) } if !ok { return noRune, noNext } } return merged, next } // cleanupOnePass drops working memory, and restores certain shortcut instructions. func cleanupOnePass(prog *onePassProg, original *syntax.Prog) { for ix, instOriginal := range original.Inst { switch instOriginal.Op { case syntax.InstAlt, syntax.InstAltMatch, syntax.InstRune: case syntax.InstCapture, syntax.InstEmptyWidth, syntax.InstNop, syntax.InstMatch, syntax.InstFail: prog.Inst[ix].Next = nil case syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL: prog.Inst[ix].Next = nil prog.Inst[ix] = onePassInst{Inst: instOriginal} } } } // onePassCopy creates a copy of the original Prog, as we'll be modifying it func onePassCopy(prog *syntax.Prog) *onePassProg { p := &onePassProg{ Start: prog.Start, NumCap: prog.NumCap, Inst: make([]onePassInst, len(prog.Inst)), } for i, inst := range prog.Inst { p.Inst[i] = onePassInst{Inst: inst} } // rewrites one or more common Prog constructs that enable some otherwise // non-onepass Progs to be onepass. A:BD (for example) means an InstAlt at // ip A, that points to ips B & C. // A:BC + B:DA => A:BC + B:CD // A:BC + B:DC => A:DC + B:DC for pc := range p.Inst { switch p.Inst[pc].Op { default: continue case syntax.InstAlt, syntax.InstAltMatch: // A:Bx + B:Ay p_A_Other := &p.Inst[pc].Out p_A_Alt := &p.Inst[pc].Arg // make sure a target is another Alt instAlt := p.Inst[*p_A_Alt] if !(instAlt.Op == syntax.InstAlt || instAlt.Op == syntax.InstAltMatch) { p_A_Alt, p_A_Other = p_A_Other, p_A_Alt instAlt = p.Inst[*p_A_Alt] if !(instAlt.Op == syntax.InstAlt || instAlt.Op == syntax.InstAltMatch) { continue } } instOther := p.Inst[*p_A_Other] // Analyzing both legs pointing to Alts is for another day if instOther.Op == syntax.InstAlt || instOther.Op == syntax.InstAltMatch { // too complicated continue } // simple empty transition loop // A:BC + B:DA => A:BC + B:DC p_B_Alt := &p.Inst[*p_A_Alt].Out p_B_Other := &p.Inst[*p_A_Alt].Arg patch := false if instAlt.Out == uint32(pc) { patch = true } else if instAlt.Arg == uint32(pc) { patch = true p_B_Alt, p_B_Other = p_B_Other, p_B_Alt } if patch { *p_B_Alt = *p_A_Other } // empty transition to common target // A:BC + B:DC => A:DC + B:DC if *p_A_Other == *p_B_Alt { *p_A_Alt = *p_B_Other } } } return p } // runeSlice exists to permit sorting the case-folded rune sets. type runeSlice []rune func (p runeSlice) Len() int { return len(p) } func (p runeSlice) Less(i, j int) bool { return p[i] < p[j] } func (p runeSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } var anyRuneNotNL = []rune{0, '\n' - 1, '\n' + 1, unicode.MaxRune} var anyRune = []rune{0, unicode.MaxRune} // makeOnePass creates a onepass Prog, if possible. It is possible if at any alt, // the match engine can always tell which branch to take. The routine may modify // p if it is turned into a onepass Prog. If it isn't possible for this to be a // onepass Prog, the Prog nil is returned. makeOnePass is recursive // to the size of the Prog. func makeOnePass(p *onePassProg) *onePassProg { // If the machine is very long, it's not worth the time to check if we can use one pass. if len(p.Inst) >= 1000 { return nil } var ( instQueue = newQueue(len(p.Inst)) visitQueue = newQueue(len(p.Inst)) check func(uint32, []bool) bool onePassRunes = make([][]rune, len(p.Inst)) ) // check that paths from Alt instructions are unambiguous, and rebuild the new // program as a onepass program check = func(pc uint32, m []bool) (ok bool) { ok = true inst := &p.Inst[pc] if visitQueue.contains(pc) { return } visitQueue.insert(pc) switch inst.Op { case syntax.InstAlt, syntax.InstAltMatch: ok = check(inst.Out, m) && check(inst.Arg, m) // check no-input paths to InstMatch matchOut := m[inst.Out] matchArg := m[inst.Arg] if matchOut && matchArg { ok = false break } // Match on empty goes in inst.Out if matchArg { inst.Out, inst.Arg = inst.Arg, inst.Out matchOut, matchArg = matchArg, matchOut } if matchOut { m[pc] = true inst.Op = syntax.InstAltMatch } // build a dispatch operator from the two legs of the alt. onePassRunes[pc], inst.Next = mergeRuneSets( &onePassRunes[inst.Out], &onePassRunes[inst.Arg], inst.Out, inst.Arg) if len(inst.Next) > 0 && inst.Next[0] == mergeFailed { ok = false break } case syntax.InstCapture, syntax.InstNop: ok = check(inst.Out, m) m[pc] = m[inst.Out] // pass matching runes back through these no-ops. onePassRunes[pc] = append([]rune{}, onePassRunes[inst.Out]...) inst.Next = make([]uint32, len(onePassRunes[pc])/2+1) for i := range inst.Next { inst.Next[i] = inst.Out } case syntax.InstEmptyWidth: ok = check(inst.Out, m) m[pc] = m[inst.Out] onePassRunes[pc] = append([]rune{}, onePassRunes[inst.Out]...) inst.Next = make([]uint32, len(onePassRunes[pc])/2+1) for i := range inst.Next { inst.Next[i] = inst.Out } case syntax.InstMatch, syntax.InstFail: m[pc] = inst.Op == syntax.InstMatch case syntax.InstRune: m[pc] = false if len(inst.Next) > 0 { break } instQueue.insert(inst.Out) if len(inst.Rune) == 0 { onePassRunes[pc] = []rune{} inst.Next = []uint32{inst.Out} break } runes := make([]rune, 0) if len(inst.Rune) == 1 && syntax.Flags(inst.Arg)&syntax.FoldCase != 0 { r0 := inst.Rune[0] runes = append(runes, r0, r0) for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) { runes = append(runes, r1, r1) } sort.Sort(runeSlice(runes)) } else { runes = append(runes, inst.Rune...) } onePassRunes[pc] = runes inst.Next = make([]uint32, len(onePassRunes[pc])/2+1) for i := range inst.Next { inst.Next[i] = inst.Out } inst.Op = syntax.InstRune case syntax.InstRune1: m[pc] = false if len(inst.Next) > 0 { break } instQueue.insert(inst.Out) runes := []rune{} // expand case-folded runes if syntax.Flags(inst.Arg)&syntax.FoldCase != 0 { r0 := inst.Rune[0] runes = append(runes, r0, r0) for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) { runes = append(runes, r1, r1) } sort.Sort(runeSlice(runes)) } else { runes = append(runes, inst.Rune[0], inst.Rune[0]) } onePassRunes[pc] = runes inst.Next = make([]uint32, len(onePassRunes[pc])/2+1) for i := range inst.Next { inst.Next[i] = inst.Out } inst.Op = syntax.InstRune case syntax.InstRuneAny: m[pc] = false if len(inst.Next) > 0 { break } instQueue.insert(inst.Out) onePassRunes[pc] = append([]rune{}, anyRune...) inst.Next = []uint32{inst.Out} case syntax.InstRuneAnyNotNL: m[pc] = false if len(inst.Next) > 0 { break } instQueue.insert(inst.Out) onePassRunes[pc] = append([]rune{}, anyRuneNotNL...) inst.Next = make([]uint32, len(onePassRunes[pc])/2+1) for i := range inst.Next { inst.Next[i] = inst.Out } } return } instQueue.clear() instQueue.insert(uint32(p.Start)) m := make([]bool, len(p.Inst)) for !instQueue.empty() { visitQueue.clear() pc := instQueue.next() if !check(pc, m) { p = nil break } } if p != nil { for i := range p.Inst { p.Inst[i].Rune = onePassRunes[i] } } return p } // compileOnePass returns a new *syntax.Prog suitable for onePass execution if the original Prog // can be recharacterized as a one-pass regexp program, or syntax.nil if the // Prog cannot be converted. For a one pass prog, the fundamental condition that must // be true is: at any InstAlt, there must be no ambiguity about what branch to take. func compileOnePass(prog *syntax.Prog) (p *onePassProg) { if prog.Start == 0 { return nil } // onepass regexp is anchored if prog.Inst[prog.Start].Op != syntax.InstEmptyWidth || syntax.EmptyOp(prog.Inst[prog.Start].Arg)&syntax.EmptyBeginText != syntax.EmptyBeginText { return nil } // every instruction leading to InstMatch must be EmptyEndText for _, inst := range prog.Inst { opOut := prog.Inst[inst.Out].Op switch inst.Op { default: if opOut == syntax.InstMatch { return nil } case syntax.InstAlt, syntax.InstAltMatch: if opOut == syntax.InstMatch || prog.Inst[inst.Arg].Op == syntax.InstMatch { return nil } case syntax.InstEmptyWidth: if opOut == syntax.InstMatch { if syntax.EmptyOp(inst.Arg)&syntax.EmptyEndText == syntax.EmptyEndText { continue } return nil } } } // Creates a slightly optimized copy of the original Prog // that cleans up some Prog idioms that block valid onepass programs p = onePassCopy(prog) // checkAmbiguity on InstAlts, build onepass Prog if possible p = makeOnePass(p) if p != nil { cleanupOnePass(p, prog) } return p } binaryregexp-0.2.0/onepass_test.go000066400000000000000000000111651347202265500172600ustar00rootroot00000000000000// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package binaryregexp import ( "reflect" "rsc.io/binaryregexp/syntax" "strings" "testing" ) var runeMergeTests = []struct { left, right, merged []rune next []uint32 leftPC, rightPC uint32 }{ { // empty rhs []rune{69, 69}, []rune{}, []rune{69, 69}, []uint32{1}, 1, 2, }, { // identical runes, identical targets []rune{69, 69}, []rune{69, 69}, []rune{}, []uint32{mergeFailed}, 1, 1, }, { // identical runes, different targets []rune{69, 69}, []rune{69, 69}, []rune{}, []uint32{mergeFailed}, 1, 2, }, { // append right-first []rune{69, 69}, []rune{71, 71}, []rune{69, 69, 71, 71}, []uint32{1, 2}, 1, 2, }, { // append, left-first []rune{71, 71}, []rune{69, 69}, []rune{69, 69, 71, 71}, []uint32{2, 1}, 1, 2, }, { // successful interleave []rune{60, 60, 71, 71, 101, 101}, []rune{69, 69, 88, 88}, []rune{60, 60, 69, 69, 71, 71, 88, 88, 101, 101}, []uint32{1, 2, 1, 2, 1}, 1, 2, }, { // left surrounds right []rune{69, 74}, []rune{71, 71}, []rune{}, []uint32{mergeFailed}, 1, 2, }, { // right surrounds left []rune{69, 74}, []rune{68, 75}, []rune{}, []uint32{mergeFailed}, 1, 2, }, { // overlap at interval begin []rune{69, 74}, []rune{74, 75}, []rune{}, []uint32{mergeFailed}, 1, 2, }, { // overlap ar interval end []rune{69, 74}, []rune{65, 69}, []rune{}, []uint32{mergeFailed}, 1, 2, }, { // overlap from above []rune{69, 74}, []rune{71, 74}, []rune{}, []uint32{mergeFailed}, 1, 2, }, { // overlap from below []rune{69, 74}, []rune{65, 71}, []rune{}, []uint32{mergeFailed}, 1, 2, }, { // out of order []rune []rune{69, 74, 60, 65}, []rune{66, 67}, []rune{}, []uint32{mergeFailed}, 1, 2, }, } func TestMergeRuneSet(t *testing.T) { for ix, test := range runeMergeTests { merged, next := mergeRuneSets(&test.left, &test.right, test.leftPC, test.rightPC) if !reflect.DeepEqual(merged, test.merged) { t.Errorf("mergeRuneSet :%d (%v, %v) merged\n have\n%v\nwant\n%v", ix, test.left, test.right, merged, test.merged) } if !reflect.DeepEqual(next, test.next) { t.Errorf("mergeRuneSet :%d(%v, %v) next\n have\n%v\nwant\n%v", ix, test.left, test.right, next, test.next) } } } var onePassTests = []struct { re string isOnePass bool }{ {`^(?:a|(?:a*))$`, false}, {`^(?:(a)|(?:a*))$`, false}, {`^(?:(?:(?:.(?:$))?))$`, true}, {`^abcd$`, true}, {`^(?:(?:a{0,})*?)$`, true}, {`^(?:(?:a+)*)$`, true}, {`^(?:(?:a|(?:aa)))$`, true}, {`^(?:[^\s\S])$`, true}, {`^(?:(?:a{3,4}){0,})$`, false}, {`^(?:(?:(?:a*)+))$`, true}, {`^[a-c]+$`, true}, {`^[a-c]*$`, true}, {`^(?:a*)$`, true}, {`^(?:(?:aa)|a)$`, true}, {`^[a-c]*`, false}, {`^...$`, true}, {`^(?:a|(?:aa))$`, true}, {`^a((b))c$`, true}, {`^a.[l-nA-Cg-j]?e$`, true}, {`^a((b))$`, true}, {`^a(?:(b)|(c))c$`, true}, {`^a(?:(b*)|(c))c$`, false}, {`^a(?:b|c)$`, true}, {`^a(?:b?|c)$`, true}, {`^a(?:b?|c?)$`, false}, {`^a(?:b?|c+)$`, true}, {`^a(?:b+|(bc))d$`, false}, {`^a(?:bc)+$`, true}, {`^a(?:[bcd])+$`, true}, {`^a((?:[bcd])+)$`, true}, {`^a(:?b|c)*d$`, true}, {`^.bc(d|e)*$`, true}, {`^(?:(?:aa)|.)$`, false}, {`^(?:(?:a{1,2}){1,2})$`, false}, {`^l` + strings.Repeat("o", 2<<8) + `ng$`, true}, } func TestCompileOnePass(t *testing.T) { var ( p *syntax.Prog re *syntax.Regexp err error ) for _, test := range onePassTests { if re, err = syntax.Parse(test.re, syntax.Perl); err != nil { t.Errorf("Parse(%q) got err:%s, want success", test.re, err) continue } // needs to be done before compile... re = re.Simplify() if p, err = syntax.Compile(re); err != nil { t.Errorf("Compile(%q) got err:%s, want success", test.re, err) continue } isOnePass := compileOnePass(p) != nil if isOnePass != test.isOnePass { t.Errorf("CompileOnePass(%q) got isOnePass=%v, expected %v", test.re, isOnePass, test.isOnePass) } } } // TODO(cespare): Unify with onePassTests and rationalize one-pass test cases. var onePassTests1 = []struct { re string match string }{ {`^a(/b+(#c+)*)*$`, "a/b#c"}, // golang.org/issue/11905 } func TestRunOnePass(t *testing.T) { for _, test := range onePassTests1 { re, err := Compile(test.re) if err != nil { t.Errorf("Compile(%q): got err: %s", test.re, err) continue } if re.onepass == nil { t.Errorf("Compile(%q): got nil, want one-pass", test.re) continue } if !re.MatchString(test.match) { t.Errorf("onepass %q did not match %q", test.re, test.match) } } } binaryregexp-0.2.0/regexp.go000066400000000000000000001075611347202265500160510ustar00rootroot00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package regexp implements regular expression search. // // The syntax of the regular expressions accepted is the same // general syntax used by Perl, Python, and other languages. // More precisely, it is the syntax accepted by RE2 and described at // https://golang.org/s/re2syntax, except for \C. // For an overview of the syntax, run // go doc regexp/syntax // // The regexp implementation provided by this package is // guaranteed to run in time linear in the size of the input. // (This is a property not guaranteed by most open source // implementations of regular expressions.) For more information // about this property, see // https://swtch.com/~rsc/regexp/regexp1.html // or any book about automata theory. // // All characters are UTF-8-encoded code points. // // There are 16 methods of Regexp that match a regular expression and identify // the matched text. Their names are matched by this regular expression: // // Find(All)?(String)?(Submatch)?(Index)? // // If 'All' is present, the routine matches successive non-overlapping // matches of the entire expression. Empty matches abutting a preceding // match are ignored. The return value is a slice containing the successive // return values of the corresponding non-'All' routine. These routines take // an extra integer argument, n. If n >= 0, the function returns at most n // matches/submatches; otherwise, it returns all of them. // // If 'String' is present, the argument is a string; otherwise it is a slice // of bytes; return values are adjusted as appropriate. // // If 'Submatch' is present, the return value is a slice identifying the // successive submatches of the expression. Submatches are matches of // parenthesized subexpressions (also known as capturing groups) within the // regular expression, numbered from left to right in order of opening // parenthesis. Submatch 0 is the match of the entire expression, submatch 1 // the match of the first parenthesized subexpression, and so on. // // If 'Index' is present, matches and submatches are identified by byte index // pairs within the input string: result[2*n:2*n+1] identifies the indexes of // the nth submatch. The pair for n==0 identifies the match of the entire // expression. If 'Index' is not present, the match is identified by the text // of the match/submatch. If an index is negative or text is nil, it means that // subexpression did not match any string in the input. For 'String' versions // an empty string means either no match or an empty match. // // There is also a subset of the methods that can be applied to text read // from a ByteReader: // // MatchReader, FindReaderIndex, FindReaderSubmatchIndex // // This set may grow. Note that regular expression matches may need to // examine text beyond the text returned by a match, so the methods that // match text from a ByteReader may read arbitrarily far into the input // before returning. // // (There are a few other methods that do not match this pattern.) // package binaryregexp import ( "bytes" "io" "strconv" "strings" "sync" "unicode" "rsc.io/binaryregexp/syntax" ) // Regexp is the representation of a compiled regular expression. // A Regexp is safe for concurrent use by multiple goroutines, // except for configuration methods, such as Longest. type Regexp struct { expr string // as passed to Compile prog *syntax.Prog // compiled program onepass *onePassProg // onepass program or nil numSubexp int maxBitStateLen int subexpNames []string prefix string // required prefix in unanchored matches prefixBytes []byte // prefix, as a []byte prefixEnd uint32 // pc for last rune in prefix mpool int // pool for machines matchcap int // size of recorded match lengths prefixComplete bool // prefix is the entire regexp cond syntax.EmptyOp // empty-width conditions required at start of match minInputLen int // minimum length of the input in bytes // This field can be modified by the Longest method, // but it is otherwise read-only. longest bool // whether regexp prefers leftmost-longest match } // String returns the source text used to compile the regular expression. func (re *Regexp) String() string { return re.expr } // Copy returns a new Regexp object copied from re. // Calling Longest on one copy does not affect another. // // Deprecated: In earlier releases, when using a Regexp in multiple goroutines, // giving each goroutine its own copy helped to avoid lock contention. // As of Go 1.12, using Copy is no longer necessary to avoid lock contention. // Copy may still be appropriate if the reason for its use is to make // two copies with different Longest settings. func (re *Regexp) Copy() *Regexp { re2 := *re return &re2 } // 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, error) { 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 https://swtch.com/~rsc/regexp/regexp2.html#posix for details. func CompilePOSIX(expr string) (*Regexp, error) { return compile(expr, syntax.POSIX, true) } // Longest makes future searches prefer the leftmost-longest match. // 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 method modifies the Regexp and may not be called concurrently // with any other methods. func (re *Regexp) Longest() { re.longest = true } func compile(expr string, mode syntax.Flags, longest bool) (*Regexp, error) { re, err := syntax.Parse(expr, mode) if err != nil { return nil, err } maxCap := re.MaxCap() capNames := re.CapNames() re = re.Simplify() prog, err := syntax.Compile(re) if err != nil { return nil, err } matchcap := prog.NumCap if matchcap < 2 { matchcap = 2 } regexp := &Regexp{ expr: expr, prog: prog, onepass: compileOnePass(prog), numSubexp: maxCap, subexpNames: capNames, cond: prog.StartCond(), longest: longest, matchcap: matchcap, minInputLen: minInputLen(re), } if regexp.onepass == nil { regexp.prefix, regexp.prefixComplete = prog.Prefix() regexp.maxBitStateLen = maxBitStateLen(prog) } else { regexp.prefix, regexp.prefixComplete, regexp.prefixEnd = onePassPrefix(prog) } if regexp.prefix != "" { // TODO(rsc): Remove this allocation by adding // IndexString to package bytes. regexp.prefixBytes = []byte(regexp.prefix) } n := len(prog.Inst) i := 0 for matchSize[i] != 0 && matchSize[i] < n { i++ } regexp.mpool = i return regexp, nil } // Pools of *machine for use during (*Regexp).doExecute, // split up by the size of the execution queues. // matchPool[i] machines have queue size matchSize[i]. // On a 64-bit system each queue entry is 16 bytes, // so matchPool[0] has 16*2*128 = 4kB queues, etc. // The final matchPool is a catch-all for very large queues. var ( matchSize = [...]int{128, 512, 2048, 16384, 0} matchPool [len(matchSize)]sync.Pool ) // get returns a machine to use for matching re. // It uses the re's machine cache if possible, to avoid // unnecessary allocation. func (re *Regexp) get() *machine { m, ok := matchPool[re.mpool].Get().(*machine) if !ok { m = new(machine) } m.re = re m.p = re.prog if cap(m.matchcap) < re.matchcap { m.matchcap = make([]int, re.matchcap) for _, t := range m.pool { t.cap = make([]int, re.matchcap) } } // Allocate queues if needed. // Or reallocate, for "large" match pool. n := matchSize[re.mpool] if n == 0 { // large pool n = len(re.prog.Inst) } if len(m.q0.sparse) < n { m.q0 = queue{make([]uint32, n), make([]entry, 0, n)} m.q1 = queue{make([]uint32, n), make([]entry, 0, n)} } return m } // put returns a machine to the correct machine pool. func (re *Regexp) put(m *machine) { m.re = nil m.p = nil m.inputs.clear() matchPool[re.mpool].Put(m) } // minInputLen walks the regexp to find the minimum length of any matchable input func minInputLen(re *syntax.Regexp) int { switch re.Op { default: return 0 case syntax.OpAnyChar, syntax.OpAnyCharNotNL, syntax.OpCharClass: return 1 case syntax.OpLiteral: return len(re.Rune) case syntax.OpCapture, syntax.OpPlus: return minInputLen(re.Sub[0]) case syntax.OpRepeat: return re.Min * minInputLen(re.Sub[0]) case syntax.OpConcat: l := 0 for _, sub := range re.Sub { l += minInputLen(sub) } return l case syntax.OpAlternate: l := minInputLen(re.Sub[0]) var lnext int for _, sub := range re.Sub[1:] { lnext = minInputLen(sub) if lnext < l { l = lnext } } return l } } // MustCompile is like Compile but panics if the expression cannot be parsed. // It simplifies safe initialization of global variables holding compiled regular // expressions. func MustCompile(str string) *Regexp { regexp, err := Compile(str) if err != nil { panic(`regexp: Compile(` + quote(str) + `): ` + err.Error()) } return regexp } // MustCompilePOSIX is like CompilePOSIX but panics if the expression cannot be parsed. // It simplifies safe initialization of global variables holding compiled regular // expressions. func MustCompilePOSIX(str string) *Regexp { regexp, err := CompilePOSIX(str) if err != nil { panic(`regexp: CompilePOSIX(` + quote(str) + `): ` + err.Error()) } return regexp } func quote(s string) string { if strconv.CanBackquote(s) { return "`" + s + "`" } return strconv.Quote(s) } // NumSubexp returns the number of parenthesized subexpressions in this Regexp. func (re *Regexp) NumSubexp() int { return re.numSubexp } // SubexpNames returns the names of the parenthesized subexpressions // in this Regexp. The name for the first sub-expression is names[1], // so that if m is a match slice, the name for m[i] is SubexpNames()[i]. // Since the Regexp as a whole cannot be named, names[0] is always // the empty string. The slice should not be modified. func (re *Regexp) SubexpNames() []string { return re.subexpNames } const endOfText rune = -1 // input abstracts different representations of the input text. It provides // one-character lookahead. type input interface { step(pos int) (r rune, width int) // advance one rune canCheckPrefix() bool // can we look ahead without losing info? hasPrefix(re *Regexp) bool index(re *Regexp, pos int) int context(pos int) lazyFlag } // inputString scans a string. type inputString struct { str string } func (i *inputString) step(pos int) (rune, int) { if pos < len(i.str) { c := i.str[pos] return rune(c), 1 } return endOfText, 0 } func (i *inputString) canCheckPrefix() bool { return true } func (i *inputString) hasPrefix(re *Regexp) bool { return strings.HasPrefix(i.str, re.prefix) } func (i *inputString) index(re *Regexp, pos int) int { return strings.Index(i.str[pos:], re.prefix) } func (i *inputString) context(pos int) lazyFlag { r1, r2 := endOfText, endOfText // 0 < pos && pos <= len(i.str) if uint(pos-1) < uint(len(i.str)) { r1 = rune(i.str[pos-1]) } // 0 <= pos && pos < len(i.str) if uint(pos) < uint(len(i.str)) { r2 = rune(i.str[pos]) } return newLazyFlag(r1, r2) } // inputBytes scans a byte slice. type inputBytes struct { str []byte } func (i *inputBytes) step(pos int) (rune, int) { if pos < len(i.str) { c := i.str[pos] return rune(c), 1 } return endOfText, 0 } func (i *inputBytes) canCheckPrefix() bool { return true } func (i *inputBytes) hasPrefix(re *Regexp) bool { return bytes.HasPrefix(i.str, re.prefixBytes) } func (i *inputBytes) index(re *Regexp, pos int) int { return bytes.Index(i.str[pos:], re.prefixBytes) } func (i *inputBytes) context(pos int) lazyFlag { r1, r2 := endOfText, endOfText // 0 < pos && pos <= len(i.str) if uint(pos-1) < uint(len(i.str)) { r1 = rune(i.str[pos-1]) } // 0 <= pos && pos < len(i.str) if uint(pos) < uint(len(i.str)) { r2 = rune(i.str[pos]) } return newLazyFlag(r1, r2) } // inputReader scans a ByteReader. type inputReader struct { r io.ByteReader atEOT bool pos int } func (i *inputReader) step(pos int) (rune, int) { if !i.atEOT && pos != i.pos { return endOfText, 0 } r, err := i.r.ReadByte() if err != nil { i.atEOT = true return endOfText, 0 } i.pos++ return rune(r), 1 } func (i *inputReader) canCheckPrefix() bool { return false } func (i *inputReader) hasPrefix(re *Regexp) bool { return false } func (i *inputReader) index(re *Regexp, pos int) int { return -1 } func (i *inputReader) context(pos int) lazyFlag { return 0 // not used } // LiteralPrefix returns a literal string that must begin any match // of the regular expression re. It returns the boolean true if the // literal string comprises the entire regular expression. func (re *Regexp) LiteralPrefix() (prefix string, complete bool) { return re.prefix, re.prefixComplete } // MatchReader reports whether the text returned by the ByteReader // contains any match of the regular expression re. func (re *Regexp) MatchReader(r io.ByteReader) bool { return re.doMatch(r, nil, "") } // MatchString reports whether the string s // contains any match of the regular expression re. func (re *Regexp) MatchString(s string) bool { return re.doMatch(nil, nil, s) } // Match reports whether the byte slice b // contains any match of the regular expression re. func (re *Regexp) Match(b []byte) bool { return re.doMatch(nil, b, "") } // MatchReader reports whether the text returned by the ByteReader // contains any match of the regular expression pattern. // More complicated queries need to use Compile and the full Regexp interface. func MatchReader(pattern string, r io.ByteReader) (matched bool, err error) { re, err := Compile(pattern) if err != nil { return false, err } return re.MatchReader(r), nil } // MatchString reports whether the string s // contains any match of the regular expression pattern. // More complicated queries need to use Compile and the full Regexp interface. func MatchString(pattern string, s string) (matched bool, err error) { re, err := Compile(pattern) if err != nil { return false, err } return re.MatchString(s), nil } // Match reports whether the byte slice b // contains any match of the regular expression pattern. // More complicated queries need to use Compile and the full Regexp interface. func Match(pattern string, b []byte) (matched bool, err error) { re, err := Compile(pattern) if err != nil { return false, err } return re.Match(b), nil } // ReplaceAllString returns a copy of src, replacing matches of the Regexp // with the replacement string repl. Inside repl, $ signs are interpreted as // in Expand, so for instance $1 represents the text of the first submatch. func (re *Regexp) ReplaceAllString(src, repl string) string { n := 2 if strings.Contains(repl, "$") { n = 2 * (re.numSubexp + 1) } b := re.replaceAll(nil, src, n, func(dst []byte, match []int) []byte { return re.expand(dst, repl, nil, src, match) }) return string(b) } // ReplaceAllLiteralString returns a copy of src, replacing matches of the Regexp // with the replacement string repl. The replacement repl is substituted directly, // without using Expand. func (re *Regexp) ReplaceAllLiteralString(src, repl string) string { return string(re.replaceAll(nil, src, 2, func(dst []byte, match []int) []byte { return append(dst, repl...) })) } // ReplaceAllStringFunc returns a copy of src in which all matches of the // Regexp have been replaced by the return value of function repl applied // to the matched substring. The replacement returned by repl is substituted // directly, without using Expand. func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string { b := re.replaceAll(nil, src, 2, func(dst []byte, match []int) []byte { return append(dst, repl(src[match[0]:match[1]])...) }) return string(b) } func (re *Regexp) replaceAll(bsrc []byte, src string, nmatch int, repl func(dst []byte, m []int) []byte) []byte { lastMatchEnd := 0 // end position of the most recent match searchPos := 0 // position where we next look for a match var buf []byte var endPos int if bsrc != nil { endPos = len(bsrc) } else { endPos = len(src) } if nmatch > re.prog.NumCap { nmatch = re.prog.NumCap } var dstCap [2]int for searchPos <= endPos { a := re.doExecute(nil, bsrc, src, searchPos, nmatch, dstCap[:0]) if len(a) == 0 { break // no more matches } // Copy the unmatched characters before this match. if bsrc != nil { buf = append(buf, bsrc[lastMatchEnd:a[0]]...) } else { buf = append(buf, src[lastMatchEnd:a[0]]...) } // Now insert a copy of the replacement string, but not for a // match of the empty string immediately after another match. // (Otherwise, we get double replacement for patterns that // match both empty and nonempty strings.) if a[1] > lastMatchEnd || a[0] == 0 { buf = repl(buf, a) } lastMatchEnd = a[1] // Advance past this match; always advance at least one character. if searchPos+1 > a[1] { searchPos++ } else { searchPos = a[1] } } // Copy the unmatched characters after the last match. if bsrc != nil { buf = append(buf, bsrc[lastMatchEnd:]...) } else { buf = append(buf, src[lastMatchEnd:]...) } return buf } // ReplaceAll returns a copy of src, replacing matches of the Regexp // with the replacement text repl. Inside repl, $ signs are interpreted as // in Expand, so for instance $1 represents the text of the first submatch. func (re *Regexp) ReplaceAll(src, repl []byte) []byte { n := 2 if bytes.IndexByte(repl, '$') >= 0 { n = 2 * (re.numSubexp + 1) } srepl := "" b := re.replaceAll(src, "", n, func(dst []byte, match []int) []byte { if len(srepl) != len(repl) { srepl = string(repl) } return re.expand(dst, srepl, src, "", match) }) return b } // ReplaceAllLiteral returns a copy of src, replacing matches of the Regexp // with the replacement bytes repl. The replacement repl is substituted directly, // without using Expand. func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte { return re.replaceAll(src, "", 2, func(dst []byte, match []int) []byte { return append(dst, repl...) }) } // ReplaceAllFunc returns a copy of src in which all matches of the // Regexp have been replaced by the return value of function repl applied // to the matched byte slice. The replacement returned by repl is substituted // directly, without using Expand. func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte { return re.replaceAll(src, "", 2, func(dst []byte, match []int) []byte { return append(dst, repl(src[match[0]:match[1]])...) }) } // Bitmap used by func special to check whether a character needs to be escaped. var specialBytes [16]byte // special reports whether byte b needs to be escaped by QuoteMeta. func special(b byte) bool { return b < 16*8 && specialBytes[b%16]&(1<<(b/16)) != 0 } func init() { for _, b := range []byte(`\.+*?()|[]{}^$`) { specialBytes[b%16] |= 1 << (b / 16) } } // QuoteMeta returns a string that escapes all regular expression metacharacters // inside the argument text; the returned string is a regular expression matching // the literal text. func QuoteMeta(s string) string { // A byte loop is correct because all metacharacters are ASCII. var i int for i = 0; i < len(s); i++ { if special(s[i]) { break } } // No meta characters found, so return original string. if i >= len(s) { return s } b := make([]byte, 2*len(s)-i) copy(b, s[:i]) j := i for ; i < len(s); i++ { if special(s[i]) { b[j] = '\\' j++ } b[j] = s[i] j++ } return string(b[:j]) } // The number of capture values in the program may correspond // to fewer capturing expressions than are in the regexp. // For example, "(a){0}" turns into an empty program, so the // maximum capture in the program is 0 but we need to return // an expression for \1. Pad appends -1s to the slice a as needed. func (re *Regexp) pad(a []int) []int { if a == nil { // No match. return nil } n := (1 + re.numSubexp) * 2 for len(a) < n { a = append(a, -1) } return a } // allMatches calls deliver at most n times // with the location of successive matches in the input text. // The input text is b if non-nil, otherwise s. func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) { var end int if b == nil { end = len(s) } else { end = len(b) } for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; { matches := re.doExecute(nil, b, s, pos, re.prog.NumCap, nil) if len(matches) == 0 { break } accept := true if matches[1] == pos { // We've found an empty match. if matches[0] == prevMatchEnd { // We don't allow an empty match right // after a previous match, so ignore it. accept = false } if pos < end { pos++ } else { pos = end + 1 } } else { pos = matches[1] } prevMatchEnd = matches[1] if accept { deliver(re.pad(matches)) i++ } } } // Find returns a slice holding the text of the leftmost match in b of the regular expression. // A return value of nil indicates no match. func (re *Regexp) Find(b []byte) []byte { var dstCap [2]int a := re.doExecute(nil, b, "", 0, 2, dstCap[:0]) if a == nil { return nil } return b[a[0]:a[1]:a[1]] } // FindIndex returns a two-element slice of integers defining the location of // the leftmost match in b of the regular expression. The match itself is at // b[loc[0]:loc[1]]. // A return value of nil indicates no match. func (re *Regexp) FindIndex(b []byte) (loc []int) { a := re.doExecute(nil, b, "", 0, 2, nil) if a == nil { return nil } return a[0:2] } // FindString returns a string holding the text of the leftmost match in s of the regular // expression. If there is no match, the return value is an empty string, // but it will also be empty if the regular expression successfully matches // an empty string. Use FindStringIndex or FindStringSubmatch if it is // necessary to distinguish these cases. func (re *Regexp) FindString(s string) string { var dstCap [2]int a := re.doExecute(nil, nil, s, 0, 2, dstCap[:0]) if a == nil { return "" } return s[a[0]:a[1]] } // FindStringIndex returns a two-element slice of integers defining the // location of the leftmost match in s of the regular expression. The match // itself is at s[loc[0]:loc[1]]. // A return value of nil indicates no match. func (re *Regexp) FindStringIndex(s string) (loc []int) { a := re.doExecute(nil, nil, s, 0, 2, nil) if a == nil { return nil } return a[0:2] } // FindReaderIndex returns a two-element slice of integers defining the // location of the leftmost match of the regular expression in text read from // the ByteReader. The match text was found in the input stream at // byte offset loc[0] through loc[1]-1. // A return value of nil indicates no match. func (re *Regexp) FindReaderIndex(r io.ByteReader) (loc []int) { a := re.doExecute(r, nil, "", 0, 2, nil) if a == nil { return nil } return a[0:2] } // FindSubmatch returns a slice of slices holding the text of the leftmost // match of the regular expression in b and the matches, if any, of its // subexpressions, as defined by the 'Submatch' descriptions in the package // comment. // A return value of nil indicates no match. func (re *Regexp) FindSubmatch(b []byte) [][]byte { var dstCap [4]int a := re.doExecute(nil, b, "", 0, re.prog.NumCap, dstCap[:0]) if a == nil { return nil } ret := make([][]byte, 1+re.numSubexp) for i := range ret { if 2*i < len(a) && a[2*i] >= 0 { ret[i] = b[a[2*i]:a[2*i+1]:a[2*i+1]] } } return ret } // Expand appends template to dst and returns the result; during the // append, Expand replaces variables in the template with corresponding // matches drawn from src. The match slice should have been returned by // FindSubmatchIndex. // // In the template, a variable is denoted by a substring of the form // $name or ${name}, where name is a non-empty sequence of letters, // digits, and underscores. A purely numeric name like $1 refers to // the submatch with the corresponding index; other names refer to // capturing parentheses named with the (?P...) syntax. A // reference to an out of range or unmatched index or a name that is not // present in the regular expression is replaced with an empty slice. // // In the $name form, name is taken to be as long as possible: $1x is // equivalent to ${1x}, not ${1}x, and, $10 is equivalent to ${10}, not ${1}0. // // To insert a literal $ in the output, use $$ in the template. func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte { return re.expand(dst, string(template), src, "", match) } // ExpandString is like Expand but the template and source are strings. // It appends to and returns a byte slice in order to give the calling // code control over allocation. func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte { return re.expand(dst, template, nil, src, match) } func (re *Regexp) expand(dst []byte, template string, bsrc []byte, src string, match []int) []byte { for len(template) > 0 { i := strings.Index(template, "$") if i < 0 { break } dst = append(dst, template[:i]...) template = template[i:] if len(template) > 1 && template[1] == '$' { // Treat $$ as $. dst = append(dst, '$') template = template[2:] continue } name, num, rest, ok := extract(template) if !ok { // Malformed; treat $ as raw text. dst = append(dst, '$') template = template[1:] continue } template = rest if num >= 0 { if 2*num+1 < len(match) && match[2*num] >= 0 { if bsrc != nil { dst = append(dst, bsrc[match[2*num]:match[2*num+1]]...) } else { dst = append(dst, src[match[2*num]:match[2*num+1]]...) } } } else { for i, namei := range re.subexpNames { if name == namei && 2*i+1 < len(match) && match[2*i] >= 0 { if bsrc != nil { dst = append(dst, bsrc[match[2*i]:match[2*i+1]]...) } else { dst = append(dst, src[match[2*i]:match[2*i+1]]...) } break } } } } dst = append(dst, template...) return dst } // extract returns the name from a leading "$name" or "${name}" in str. // If it is a number, extract returns num set to that number; otherwise num = -1. func extract(str string) (name string, num int, rest string, ok bool) { if len(str) < 2 || str[0] != '$' { return } brace := false if str[1] == '{' { brace = true str = str[2:] } else { str = str[1:] } i := 0 for i < len(str) { rune := rune(str[i]) if !unicode.IsLetter(rune) && !unicode.IsDigit(rune) && rune != '_' { break } i++ } if i == 0 { // empty name is not okay return } name = str[:i] if brace { if i >= len(str) || str[i] != '}' { // missing closing brace return } i++ } // Parse number. num = 0 for i := 0; i < len(name); i++ { if name[i] < '0' || '9' < name[i] || num >= 1e8 { num = -1 break } num = num*10 + int(name[i]) - '0' } // Disallow leading zeros. if name[0] == '0' && len(name) > 1 { num = -1 } rest = str[i:] ok = true return } // FindSubmatchIndex returns a slice holding the index pairs identifying the // leftmost match of the regular expression in b and the matches, if any, of // its subexpressions, as defined by the 'Submatch' and 'Index' descriptions // in the package comment. // A return value of nil indicates no match. func (re *Regexp) FindSubmatchIndex(b []byte) []int { return re.pad(re.doExecute(nil, b, "", 0, re.prog.NumCap, nil)) } // FindStringSubmatch returns a slice of strings holding the text of the // leftmost match of the regular expression in s and the matches, if any, of // its subexpressions, as defined by the 'Submatch' description in the // package comment. // A return value of nil indicates no match. func (re *Regexp) FindStringSubmatch(s string) []string { var dstCap [4]int a := re.doExecute(nil, nil, s, 0, re.prog.NumCap, dstCap[:0]) if a == nil { return nil } ret := make([]string, 1+re.numSubexp) for i := range ret { if 2*i < len(a) && a[2*i] >= 0 { ret[i] = s[a[2*i]:a[2*i+1]] } } return ret } // FindStringSubmatchIndex returns a slice holding the index pairs // identifying the leftmost match of the regular expression in s and the // matches, if any, of its subexpressions, as defined by the 'Submatch' and // 'Index' descriptions in the package comment. // A return value of nil indicates no match. func (re *Regexp) FindStringSubmatchIndex(s string) []int { return re.pad(re.doExecute(nil, nil, s, 0, re.prog.NumCap, nil)) } // FindReaderSubmatchIndex returns a slice holding the index pairs // identifying the leftmost match of the regular expression of text read by // the ByteReader, and the matches, if any, of its subexpressions, as defined // by the 'Submatch' and 'Index' descriptions in the package comment. A // return value of nil indicates no match. func (re *Regexp) FindReaderSubmatchIndex(r io.ByteReader) []int { return re.pad(re.doExecute(r, nil, "", 0, re.prog.NumCap, nil)) } const startSize = 10 // The size at which to start a slice in the 'All' routines. // FindAll is the 'All' version of Find; it returns a slice of all successive // matches of the expression, as defined by the 'All' description in the // package comment. // A return value of nil indicates no match. func (re *Regexp) FindAll(b []byte, n int) [][]byte { if n < 0 { n = len(b) + 1 } var result [][]byte re.allMatches("", b, n, func(match []int) { if result == nil { result = make([][]byte, 0, startSize) } result = append(result, b[match[0]:match[1]:match[1]]) }) return result } // FindAllIndex is the 'All' version of FindIndex; it returns a slice of all // successive matches of the expression, as defined by the 'All' description // in the package comment. // A return value of nil indicates no match. func (re *Regexp) FindAllIndex(b []byte, n int) [][]int { if n < 0 { n = len(b) + 1 } var result [][]int re.allMatches("", b, n, func(match []int) { if result == nil { result = make([][]int, 0, startSize) } result = append(result, match[0:2]) }) return result } // FindAllString is the 'All' version of FindString; it returns a slice of all // successive matches of the expression, as defined by the 'All' description // in the package comment. // A return value of nil indicates no match. func (re *Regexp) FindAllString(s string, n int) []string { if n < 0 { n = len(s) + 1 } var result []string re.allMatches(s, nil, n, func(match []int) { if result == nil { result = make([]string, 0, startSize) } result = append(result, s[match[0]:match[1]]) }) return result } // FindAllStringIndex is the 'All' version of FindStringIndex; it returns a // slice of all successive matches of the expression, as defined by the 'All' // description in the package comment. // A return value of nil indicates no match. func (re *Regexp) FindAllStringIndex(s string, n int) [][]int { if n < 0 { n = len(s) + 1 } var result [][]int re.allMatches(s, nil, n, func(match []int) { if result == nil { result = make([][]int, 0, startSize) } result = append(result, match[0:2]) }) return result } // FindAllSubmatch is the 'All' version of FindSubmatch; it returns a slice // of all successive matches of the expression, as defined by the 'All' // description in the package comment. // A return value of nil indicates no match. func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte { if n < 0 { n = len(b) + 1 } var result [][][]byte re.allMatches("", b, n, func(match []int) { if result == nil { result = make([][][]byte, 0, startSize) } slice := make([][]byte, len(match)/2) for j := range slice { if match[2*j] >= 0 { slice[j] = b[match[2*j]:match[2*j+1]:match[2*j+1]] } } result = append(result, slice) }) return result } // FindAllSubmatchIndex is the 'All' version of FindSubmatchIndex; it returns // a slice of all successive matches of the expression, as defined by the // 'All' description in the package comment. // A return value of nil indicates no match. func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int { if n < 0 { n = len(b) + 1 } var result [][]int re.allMatches("", b, n, func(match []int) { if result == nil { result = make([][]int, 0, startSize) } result = append(result, match) }) return result } // FindAllStringSubmatch is the 'All' version of FindStringSubmatch; it // returns a slice of all successive matches of the expression, as defined by // the 'All' description in the package comment. // A return value of nil indicates no match. func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string { if n < 0 { n = len(s) + 1 } var result [][]string re.allMatches(s, nil, n, func(match []int) { if result == nil { result = make([][]string, 0, startSize) } slice := make([]string, len(match)/2) for j := range slice { if match[2*j] >= 0 { slice[j] = s[match[2*j]:match[2*j+1]] } } result = append(result, slice) }) return result } // FindAllStringSubmatchIndex is the 'All' version of // FindStringSubmatchIndex; it returns a slice of all successive matches of // the expression, as defined by the 'All' description in the package // comment. // A return value of nil indicates no match. func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int { if n < 0 { n = len(s) + 1 } var result [][]int re.allMatches(s, nil, n, func(match []int) { if result == nil { result = make([][]int, 0, startSize) } result = append(result, match) }) return result } // Split slices s into substrings separated by the expression and returns a slice of // the substrings between those expression matches. // // The slice returned by this method consists of all the substrings of s // not contained in the slice returned by FindAllString. When called on an expression // that contains no metacharacters, it is equivalent to strings.SplitN. // // Example: // s := regexp.MustCompile("a*").Split("abaabaccadaaae", 5) // // s: ["", "b", "b", "c", "cadaaae"] // // The count determines the number of substrings to return: // n > 0: at most n substrings; the last substring will be the unsplit remainder. // n == 0: the result is nil (zero substrings) // n < 0: all substrings func (re *Regexp) Split(s string, n int) []string { if n == 0 { return nil } if len(re.expr) > 0 && len(s) == 0 { return []string{""} } matches := re.FindAllStringIndex(s, n) strings := make([]string, 0, len(matches)) beg := 0 end := 0 for _, match := range matches { if n > 0 && len(strings) >= n-1 { break } end = match[0] if match[1] != 0 { strings = append(strings, s[beg:end]) } beg = match[1] } if end != len(s) { strings = append(strings, s[beg:]) } return strings } binaryregexp-0.2.0/syntax/000077500000000000000000000000001347202265500155445ustar00rootroot00000000000000binaryregexp-0.2.0/syntax/compile.go000066400000000000000000000141761347202265500175340ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package syntax import "unicode" // A patchList is a list of instruction pointers that need to be filled in (patched). // Because the pointers haven't been filled in yet, we can reuse their storage // to hold the list. It's kind of sleazy, but works well in practice. // See https://swtch.com/~rsc/regexp/regexp1.html for inspiration. // // These aren't really pointers: they're integers, so we can reinterpret them // this way without using package unsafe. A value l denotes // p.inst[l>>1].Out (l&1==0) or .Arg (l&1==1). // l == 0 denotes the empty list, okay because we start every program // with a fail instruction, so we'll never want to point at its output link. type patchList uint32 func (l patchList) next(p *Prog) patchList { i := &p.Inst[l>>1] if l&1 == 0 { return patchList(i.Out) } return patchList(i.Arg) } func (l patchList) patch(p *Prog, val uint32) { for l != 0 { i := &p.Inst[l>>1] if l&1 == 0 { l = patchList(i.Out) i.Out = val } else { l = patchList(i.Arg) i.Arg = val } } } func (l1 patchList) append(p *Prog, l2 patchList) patchList { if l1 == 0 { return l2 } if l2 == 0 { return l1 } last := l1 for { next := last.next(p) if next == 0 { break } last = next } i := &p.Inst[last>>1] if last&1 == 0 { i.Out = uint32(l2) } else { i.Arg = uint32(l2) } return l1 } // A frag represents a compiled program fragment. type frag struct { i uint32 // index of first instruction out patchList // where to record end instruction } type compiler struct { p *Prog } // Compile compiles the regexp into a program to be executed. // The regexp should have been simplified already (returned from re.Simplify). func Compile(re *Regexp) (*Prog, error) { var c compiler c.init() f := c.compile(re) f.out.patch(c.p, c.inst(InstMatch).i) c.p.Start = int(f.i) return c.p, nil } func (c *compiler) init() { c.p = new(Prog) c.p.NumCap = 2 // implicit ( and ) for whole match $0 c.inst(InstFail) } var anyRuneNotNL = []rune{0, '\n' - 1, '\n' + 1, unicode.MaxRune} var anyRune = []rune{0, unicode.MaxRune} func (c *compiler) compile(re *Regexp) frag { switch re.Op { case OpNoMatch: return c.fail() case OpEmptyMatch: return c.nop() case OpLiteral: if len(re.Rune) == 0 { return c.nop() } var f frag for j := range re.Rune { f1 := c.rune(re.Rune[j:j+1], re.Flags) if j == 0 { f = f1 } else { f = c.cat(f, f1) } } return f case OpCharClass: return c.rune(re.Rune, re.Flags) case OpAnyCharNotNL: return c.rune(anyRuneNotNL, 0) case OpAnyChar: return c.rune(anyRune, 0) case OpBeginLine: return c.empty(EmptyBeginLine) case OpEndLine: return c.empty(EmptyEndLine) case OpBeginText: return c.empty(EmptyBeginText) case OpEndText: return c.empty(EmptyEndText) case OpWordBoundary: return c.empty(EmptyWordBoundary) case OpNoWordBoundary: return c.empty(EmptyNoWordBoundary) case OpCapture: bra := c.cap(uint32(re.Cap << 1)) sub := c.compile(re.Sub[0]) ket := c.cap(uint32(re.Cap<<1 | 1)) return c.cat(c.cat(bra, sub), ket) case OpStar: return c.star(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0) case OpPlus: return c.plus(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0) case OpQuest: return c.quest(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0) case OpConcat: if len(re.Sub) == 0 { return c.nop() } var f frag for i, sub := range re.Sub { if i == 0 { f = c.compile(sub) } else { f = c.cat(f, c.compile(sub)) } } return f case OpAlternate: var f frag for _, sub := range re.Sub { f = c.alt(f, c.compile(sub)) } return f } panic("regexp: unhandled case in compile") } func (c *compiler) inst(op InstOp) frag { // TODO: impose length limit f := frag{i: uint32(len(c.p.Inst))} c.p.Inst = append(c.p.Inst, Inst{Op: op}) return f } func (c *compiler) nop() frag { f := c.inst(InstNop) f.out = patchList(f.i << 1) return f } func (c *compiler) fail() frag { return frag{} } func (c *compiler) cap(arg uint32) frag { f := c.inst(InstCapture) f.out = patchList(f.i << 1) c.p.Inst[f.i].Arg = arg if c.p.NumCap < int(arg)+1 { c.p.NumCap = int(arg) + 1 } return f } func (c *compiler) cat(f1, f2 frag) frag { // concat of failure is failure if f1.i == 0 || f2.i == 0 { return frag{} } // TODO: elide nop f1.out.patch(c.p, f2.i) return frag{f1.i, f2.out} } func (c *compiler) alt(f1, f2 frag) frag { // alt of failure is other if f1.i == 0 { return f2 } if f2.i == 0 { return f1 } f := c.inst(InstAlt) i := &c.p.Inst[f.i] i.Out = f1.i i.Arg = f2.i f.out = f1.out.append(c.p, f2.out) return f } func (c *compiler) quest(f1 frag, nongreedy bool) frag { f := c.inst(InstAlt) i := &c.p.Inst[f.i] if nongreedy { i.Arg = f1.i f.out = patchList(f.i << 1) } else { i.Out = f1.i f.out = patchList(f.i<<1 | 1) } f.out = f.out.append(c.p, f1.out) return f } func (c *compiler) star(f1 frag, nongreedy bool) frag { f := c.inst(InstAlt) i := &c.p.Inst[f.i] if nongreedy { i.Arg = f1.i f.out = patchList(f.i << 1) } else { i.Out = f1.i f.out = patchList(f.i<<1 | 1) } f1.out.patch(c.p, f.i) return f } func (c *compiler) plus(f1 frag, nongreedy bool) frag { return frag{f1.i, c.star(f1, nongreedy).out} } func (c *compiler) empty(op EmptyOp) frag { f := c.inst(InstEmptyWidth) c.p.Inst[f.i].Arg = uint32(op) f.out = patchList(f.i << 1) return f } func (c *compiler) rune(r []rune, flags Flags) frag { f := c.inst(InstRune) i := &c.p.Inst[f.i] i.Rune = r flags &= FoldCase // only relevant flag is FoldCase if len(r) != 1 || unicode.SimpleFold(r[0]) == r[0] { // and sometimes not even that flags &^= FoldCase } i.Arg = uint32(flags) f.out = patchList(f.i << 1) // Special cases for exec machine. switch { case flags&FoldCase == 0 && (len(r) == 1 || len(r) == 2 && r[0] == r[1]): i.Op = InstRune1 case len(r) == 2 && r[0] == 0 && r[1] == unicode.MaxRune: i.Op = InstRuneAny case len(r) == 4 && r[0] == 0 && r[1] == '\n'-1 && r[2] == '\n'+1 && r[3] == unicode.MaxRune: i.Op = InstRuneAnyNotNL } return f } binaryregexp-0.2.0/syntax/doc.go000066400000000000000000000124331347202265500166430ustar00rootroot00000000000000// Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // DO NOT EDIT. This file is generated by mksyntaxgo from the RE2 distribution. /* Package syntax parses regular expressions into parse trees and compiles parse trees into programs. Most clients of regular expressions will use the facilities of package regexp (such as Compile and Match) instead of this package. Syntax The regular expression syntax understood by this package when parsing with the Perl flag is as follows. Parts of the syntax can be disabled by passing alternate flags to Parse. Single characters: . any character, possibly including newline (flag s=true) [xyz] character class [^xyz] negated character class \d Perl character class \D negated Perl character class [[:alpha:]] ASCII character class [[:^alpha:]] negated ASCII character class \pN Unicode character class (one-letter name) \p{Greek} Unicode character class \PN negated Unicode character class (one-letter name) \P{Greek} negated Unicode character class Composites: xy x followed by y x|y x or y (prefer x) Repetitions: x* zero or more x, prefer more x+ one or more x, prefer more x? zero or one x, prefer one x{n,m} n or n+1 or ... or m x, prefer more x{n,} n or more x, prefer more x{n} exactly n x x*? zero or more x, prefer fewer x+? one or more x, prefer fewer x?? zero or one x, prefer zero x{n,m}? n or n+1 or ... or m x, prefer fewer x{n,}? n or more x, prefer fewer x{n}? exactly n x Implementation restriction: The counting forms x{n,m}, x{n,}, and x{n} reject forms that create a minimum or maximum repetition count above 1000. Unlimited repetitions are not subject to this restriction. Grouping: (re) numbered capturing group (submatch) (?Pre) named & numbered capturing group (submatch) (?:re) non-capturing group (?flags) set flags within current group; non-capturing (?flags:re) set flags during re; non-capturing Flag syntax is xyz (set) or -xyz (clear) or xy-z (set xy, clear z). The flags are: i case-insensitive (default false) m multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false) s let . match \n (default false) U ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false) Empty strings: ^ at beginning of text or line (flag m=true) $ at end of text (like \z not Perl's \Z) or line (flag m=true) \A at beginning of text \b at ASCII word boundary (\w on one side and \W, \A, or \z on the other) \B not at ASCII word boundary \z at end of text Escape sequences: \a bell (== \007) \f form feed (== \014) \t horizontal tab (== \011) \n newline (== \012) \r carriage return (== \015) \v vertical tab character (== \013) \* literal *, for any punctuation character * \123 octal character code (up to three digits) \x7F hex character code (exactly two digits) \x{10FFFF} hex character code \Q...\E literal text ... even if ... has punctuation Character class elements: x single character A-Z character range (inclusive) \d Perl character class [:foo:] ASCII character class foo \p{Foo} Unicode character class Foo \pF Unicode character class F (one-letter name) Named character classes as character class elements: [\d] digits (== \d) [^\d] not digits (== \D) [\D] not digits (== \D) [^\D] not not digits (== \d) [[:name:]] named ASCII class inside character class (== [:name:]) [^[:name:]] named ASCII class inside negated character class (== [:^name:]) [\p{Name}] named Unicode property inside character class (== \p{Name}) [^\p{Name}] named Unicode property inside negated character class (== \P{Name}) Perl character classes (all ASCII-only): \d digits (== [0-9]) \D not digits (== [^0-9]) \s whitespace (== [\t\n\f\r ]) \S not whitespace (== [^\t\n\f\r ]) \w word characters (== [0-9A-Za-z_]) \W not word characters (== [^0-9A-Za-z_]) ASCII character classes: [[:alnum:]] alphanumeric (== [0-9A-Za-z]) [[:alpha:]] alphabetic (== [A-Za-z]) [[:ascii:]] ASCII (== [\x00-\x7F]) [[:blank:]] blank (== [\t ]) [[:cntrl:]] control (== [\x00-\x1F\x7F]) [[:digit:]] digits (== [0-9]) [[:graph:]] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]) [[:lower:]] lower case (== [a-z]) [[:print:]] printable (== [ -~] == [ [:graph:]]) [[:punct:]] punctuation (== [!-/:-@[-`{-~]) [[:space:]] whitespace (== [\t\n\v\f\r ]) [[:upper:]] upper case (== [A-Z]) [[:word:]] word characters (== [0-9A-Za-z_]) [[:xdigit:]] hex digit (== [0-9A-Fa-f]) */ package syntax binaryregexp-0.2.0/syntax/op_string.go000066400000000000000000000012271347202265500201010ustar00rootroot00000000000000// Code generated by "stringer -type Op -trimprefix Op"; DO NOT EDIT. package syntax import "strconv" const ( _Op_name_0 = "NoMatchEmptyMatchLiteralCharClassAnyCharNotNLAnyCharBeginLineEndLineBeginTextEndTextWordBoundaryNoWordBoundaryCaptureStarPlusQuestRepeatConcatAlternate" _Op_name_1 = "opPseudo" ) var ( _Op_index_0 = [...]uint8{0, 7, 17, 24, 33, 45, 52, 61, 68, 77, 84, 96, 110, 117, 121, 125, 130, 136, 142, 151} ) func (i Op) String() string { switch { case 1 <= i && i <= 19: i -= 1 return _Op_name_0[_Op_index_0[i]:_Op_index_0[i+1]] case i == 128: return _Op_name_1 default: return "Op(" + strconv.FormatInt(int64(i), 10) + ")" } } binaryregexp-0.2.0/syntax/parse.go000066400000000000000000001342401347202265500172110ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package syntax import ( "sort" "strings" "unicode" "unicode/utf8" ) // An Error describes a failure to parse a regular expression // and gives the offending expression. type Error struct { Code ErrorCode Expr string } func (e *Error) Error() string { return "error parsing regexp: " + e.Code.String() + ": `" + e.Expr + "`" } // An ErrorCode describes a failure to parse a regular expression. type ErrorCode string const ( // Unexpected error ErrInternalError ErrorCode = "regexp/syntax: internal error" // Parse errors ErrInvalidCharClass ErrorCode = "invalid character class" ErrInvalidCharRange ErrorCode = "invalid character class range" ErrInvalidEscape ErrorCode = "invalid escape sequence" ErrInvalidNamedCapture ErrorCode = "invalid named capture" ErrInvalidPerlOp ErrorCode = "invalid or unsupported Perl syntax" ErrInvalidRepeatOp ErrorCode = "invalid nested repetition operator" ErrInvalidRepeatSize ErrorCode = "invalid repeat count" ErrInvalidUTF8 ErrorCode = "invalid UTF-8" ErrMissingBracket ErrorCode = "missing closing ]" ErrMissingParen ErrorCode = "missing closing )" ErrMissingRepeatArgument ErrorCode = "missing argument to repetition operator" ErrTrailingBackslash ErrorCode = "trailing backslash at end of expression" ErrUnexpectedParen ErrorCode = "unexpected )" ) func (e ErrorCode) String() string { return string(e) } // Flags control the behavior of the parser and record information about regexp context. type Flags uint16 const ( FoldCase Flags = 1 << iota // case-insensitive match Literal // treat pattern as literal string ClassNL // allow character classes like [^a-z] and [[:space:]] to match newline DotNL // allow . to match newline OneLine // treat ^ and $ as only matching at beginning and end of text NonGreedy // make repetition operators default to non-greedy PerlX // allow Perl extensions UnicodeGroups // allow \p{Han}, \P{Han} for Unicode group and negation WasDollar // regexp OpEndText was $, not \z Simple // regexp contains no counted repetition MatchNL = ClassNL | DotNL Perl = ClassNL | OneLine | PerlX | UnicodeGroups // as close to Perl as possible POSIX Flags = 0 // POSIX syntax ) // Pseudo-ops for parsing stack. const ( opLeftParen = opPseudo + iota opVerticalBar ) type parser struct { flags Flags // parse mode flags stack []*Regexp // stack of parsed expressions free *Regexp numCap int // number of capturing groups seen wholeRegexp string tmpClass []rune // temporary char class work space } func (p *parser) newRegexp(op Op) *Regexp { re := p.free if re != nil { p.free = re.Sub0[0] *re = Regexp{} } else { re = new(Regexp) } re.Op = op return re } func (p *parser) reuse(re *Regexp) { re.Sub0[0] = p.free p.free = re } // Parse stack manipulation. // push pushes the regexp re onto the parse stack and returns the regexp. func (p *parser) push(re *Regexp) *Regexp { if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] { // Single rune. if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) { return nil } re.Op = OpLiteral re.Rune = re.Rune[:1] re.Flags = p.flags &^ FoldCase } else if re.Op == OpCharClass && len(re.Rune) == 4 && re.Rune[0] == re.Rune[1] && re.Rune[2] == re.Rune[3] && unicode.SimpleFold(re.Rune[0]) == re.Rune[2] && unicode.SimpleFold(re.Rune[2]) == re.Rune[0] || re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0]+1 == re.Rune[1] && unicode.SimpleFold(re.Rune[0]) == re.Rune[1] && unicode.SimpleFold(re.Rune[1]) == re.Rune[0] { // Case-insensitive rune like [Aa] or [Δδ]. if p.maybeConcat(re.Rune[0], p.flags|FoldCase) { return nil } // Rewrite as (case-insensitive) literal. re.Op = OpLiteral re.Rune = re.Rune[:1] re.Flags = p.flags | FoldCase } else { // Incremental concatenation. p.maybeConcat(-1, 0) } p.stack = append(p.stack, re) return re } // maybeConcat implements incremental concatenation // of literal runes into string nodes. The parser calls this // before each push, so only the top fragment of the stack // might need processing. Since this is called before a push, // the topmost literal is no longer subject to operators like * // (Otherwise ab* would turn into (ab)*.) // If r >= 0 and there's a node left over, maybeConcat uses it // to push r with the given flags. // maybeConcat reports whether r was pushed. func (p *parser) maybeConcat(r rune, flags Flags) bool { n := len(p.stack) if n < 2 { return false } re1 := p.stack[n-1] re2 := p.stack[n-2] if re1.Op != OpLiteral || re2.Op != OpLiteral || re1.Flags&FoldCase != re2.Flags&FoldCase { return false } // Push re1 into re2. re2.Rune = append(re2.Rune, re1.Rune...) // Reuse re1 if possible. if r >= 0 { re1.Rune = re1.Rune0[:1] re1.Rune[0] = r re1.Flags = flags return true } p.stack = p.stack[:n-1] p.reuse(re1) return false // did not push r } // newLiteral returns a new OpLiteral Regexp with the given flags func (p *parser) newLiteral(r rune, flags Flags) *Regexp { re := p.newRegexp(OpLiteral) re.Flags = flags if flags&FoldCase != 0 { r = minFoldRune(r) } re.Rune0[0] = r re.Rune = re.Rune0[:1] return re } // minFoldRune returns the minimum rune fold-equivalent to r. func minFoldRune(r rune) rune { if r < minFold || r > maxFold { return r } min := r r0 := r for r = unicode.SimpleFold(r); r != r0; r = unicode.SimpleFold(r) { if min > r { min = r } } return min } // literal pushes a literal regexp for the rune r on the stack // and returns that regexp. func (p *parser) literal(r rune) { p.push(p.newLiteral(r, p.flags)) } // op pushes a regexp with the given op onto the stack // and returns that regexp. func (p *parser) op(op Op) *Regexp { re := p.newRegexp(op) re.Flags = p.flags return p.push(re) } // repeat replaces the top stack element with itself repeated according to op, min, max. // before is the regexp suffix starting at the repetition operator. // after is the regexp suffix following after the repetition operator. // repeat returns an updated 'after' and an error, if any. func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (string, error) { flags := p.flags if p.flags&PerlX != 0 { if len(after) > 0 && after[0] == '?' { after = after[1:] flags ^= NonGreedy } if lastRepeat != "" { // In Perl it is not allowed to stack repetition operators: // a** is a syntax error, not a doubled star, and a++ means // something else entirely, which we don't support! return "", &Error{ErrInvalidRepeatOp, lastRepeat[:len(lastRepeat)-len(after)]} } } n := len(p.stack) if n == 0 { return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]} } sub := p.stack[n-1] if sub.Op >= opPseudo { return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]} } re := p.newRegexp(op) re.Min = min re.Max = max re.Flags = flags re.Sub = re.Sub0[:1] re.Sub[0] = sub p.stack[n-1] = re if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) { return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]} } return after, nil } // repeatIsValid reports whether the repetition re is valid. // Valid means that the combination of the top-level repetition // and any inner repetitions does not exceed n copies of the // innermost thing. // This function rewalks the regexp tree and is called for every repetition, // so we have to worry about inducing quadratic behavior in the parser. // We avoid this by only calling repeatIsValid when min or max >= 2. // In that case the depth of any >= 2 nesting can only get to 9 without // triggering a parse error, so each subtree can only be rewalked 9 times. func repeatIsValid(re *Regexp, n int) bool { if re.Op == OpRepeat { m := re.Max if m == 0 { return true } if m < 0 { m = re.Min } if m > n { return false } if m > 0 { n /= m } } for _, sub := range re.Sub { if !repeatIsValid(sub, n) { return false } } return true } // concat replaces the top of the stack (above the topmost '|' or '(') with its concatenation. func (p *parser) concat() *Regexp { p.maybeConcat(-1, 0) // Scan down to find pseudo-operator | or (. i := len(p.stack) for i > 0 && p.stack[i-1].Op < opPseudo { i-- } subs := p.stack[i:] p.stack = p.stack[:i] // Empty concatenation is special case. if len(subs) == 0 { return p.push(p.newRegexp(OpEmptyMatch)) } return p.push(p.collapse(subs, OpConcat)) } // alternate replaces the top of the stack (above the topmost '(') with its alternation. func (p *parser) alternate() *Regexp { // Scan down to find pseudo-operator (. // There are no | above (. i := len(p.stack) for i > 0 && p.stack[i-1].Op < opPseudo { i-- } subs := p.stack[i:] p.stack = p.stack[:i] // Make sure top class is clean. // All the others already are (see swapVerticalBar). if len(subs) > 0 { cleanAlt(subs[len(subs)-1]) } // Empty alternate is special case // (shouldn't happen but easy to handle). if len(subs) == 0 { return p.push(p.newRegexp(OpNoMatch)) } return p.push(p.collapse(subs, OpAlternate)) } // cleanAlt cleans re for eventual inclusion in an alternation. func cleanAlt(re *Regexp) { switch re.Op { case OpCharClass: re.Rune = cleanClass(&re.Rune) if len(re.Rune) == 2 && re.Rune[0] == 0 && re.Rune[1] == unicode.MaxRune { re.Rune = nil re.Op = OpAnyChar return } if len(re.Rune) == 4 && re.Rune[0] == 0 && re.Rune[1] == '\n'-1 && re.Rune[2] == '\n'+1 && re.Rune[3] == unicode.MaxRune { re.Rune = nil re.Op = OpAnyCharNotNL return } if cap(re.Rune)-len(re.Rune) > 100 { // re.Rune will not grow any more. // Make a copy or inline to reclaim storage. re.Rune = append(re.Rune0[:0], re.Rune...) } } } // collapse returns the result of applying op to sub. // If sub contains op nodes, they all get hoisted up // so that there is never a concat of a concat or an // alternate of an alternate. func (p *parser) collapse(subs []*Regexp, op Op) *Regexp { if len(subs) == 1 { return subs[0] } re := p.newRegexp(op) re.Sub = re.Sub0[:0] for _, sub := range subs { if sub.Op == op { re.Sub = append(re.Sub, sub.Sub...) p.reuse(sub) } else { re.Sub = append(re.Sub, sub) } } if op == OpAlternate { re.Sub = p.factor(re.Sub) if len(re.Sub) == 1 { old := re re = re.Sub[0] p.reuse(old) } } return re } // factor factors common prefixes from the alternation list sub. // It returns a replacement list that reuses the same storage and // frees (passes to p.reuse) any removed *Regexps. // // For example, // ABC|ABD|AEF|BCX|BCY // simplifies by literal prefix extraction to // A(B(C|D)|EF)|BC(X|Y) // which simplifies by character class introduction to // A(B[CD]|EF)|BC[XY] // func (p *parser) factor(sub []*Regexp) []*Regexp { if len(sub) < 2 { return sub } // Round 1: Factor out common literal prefixes. var str []rune var strflags Flags start := 0 out := sub[:0] for i := 0; i <= len(sub); i++ { // Invariant: the Regexps that were in sub[0:start] have been // used or marked for reuse, and the slice space has been reused // for out (len(out) <= start). // // Invariant: sub[start:i] consists of regexps that all begin // with str as modified by strflags. var istr []rune var iflags Flags if i < len(sub) { istr, iflags = p.leadingString(sub[i]) if iflags == strflags { same := 0 for same < len(str) && same < len(istr) && str[same] == istr[same] { same++ } if same > 0 { // Matches at least one rune in current range. // Keep going around. str = str[:same] continue } } } // Found end of a run with common leading literal string: // sub[start:i] all begin with str[0:len(str)], but sub[i] // does not even begin with str[0]. // // Factor out common string and append factored expression to out. if i == start { // Nothing to do - run of length 0. } else if i == start+1 { // Just one: don't bother factoring. out = append(out, sub[start]) } else { // Construct factored form: prefix(suffix1|suffix2|...) prefix := p.newRegexp(OpLiteral) prefix.Flags = strflags prefix.Rune = append(prefix.Rune[:0], str...) for j := start; j < i; j++ { sub[j] = p.removeLeadingString(sub[j], len(str)) } suffix := p.collapse(sub[start:i], OpAlternate) // recurse re := p.newRegexp(OpConcat) re.Sub = append(re.Sub[:0], prefix, suffix) out = append(out, re) } // Prepare for next iteration. start = i str = istr strflags = iflags } sub = out // Round 2: Factor out common simple prefixes, // just the first piece of each concatenation. // This will be good enough a lot of the time. // // Complex subexpressions (e.g. involving quantifiers) // are not safe to factor because that collapses their // distinct paths through the automaton, which affects // correctness in some cases. start = 0 out = sub[:0] var first *Regexp for i := 0; i <= len(sub); i++ { // Invariant: the Regexps that were in sub[0:start] have been // used or marked for reuse, and the slice space has been reused // for out (len(out) <= start). // // Invariant: sub[start:i] consists of regexps that all begin with ifirst. var ifirst *Regexp if i < len(sub) { ifirst = p.leadingRegexp(sub[i]) if first != nil && first.Equal(ifirst) && // first must be a character class OR a fixed repeat of a character class. (isCharClass(first) || (first.Op == OpRepeat && first.Min == first.Max && isCharClass(first.Sub[0]))) { continue } } // Found end of a run with common leading regexp: // sub[start:i] all begin with first but sub[i] does not. // // Factor out common regexp and append factored expression to out. if i == start { // Nothing to do - run of length 0. } else if i == start+1 { // Just one: don't bother factoring. out = append(out, sub[start]) } else { // Construct factored form: prefix(suffix1|suffix2|...) prefix := first for j := start; j < i; j++ { reuse := j != start // prefix came from sub[start] sub[j] = p.removeLeadingRegexp(sub[j], reuse) } suffix := p.collapse(sub[start:i], OpAlternate) // recurse re := p.newRegexp(OpConcat) re.Sub = append(re.Sub[:0], prefix, suffix) out = append(out, re) } // Prepare for next iteration. start = i first = ifirst } sub = out // Round 3: Collapse runs of single literals into character classes. start = 0 out = sub[:0] for i := 0; i <= len(sub); i++ { // Invariant: the Regexps that were in sub[0:start] have been // used or marked for reuse, and the slice space has been reused // for out (len(out) <= start). // // Invariant: sub[start:i] consists of regexps that are either // literal runes or character classes. if i < len(sub) && isCharClass(sub[i]) { continue } // sub[i] is not a char or char class; // emit char class for sub[start:i]... if i == start { // Nothing to do - run of length 0. } else if i == start+1 { out = append(out, sub[start]) } else { // Make new char class. // Start with most complex regexp in sub[start]. max := start for j := start + 1; j < i; j++ { if sub[max].Op < sub[j].Op || sub[max].Op == sub[j].Op && len(sub[max].Rune) < len(sub[j].Rune) { max = j } } sub[start], sub[max] = sub[max], sub[start] for j := start + 1; j < i; j++ { mergeCharClass(sub[start], sub[j]) p.reuse(sub[j]) } cleanAlt(sub[start]) out = append(out, sub[start]) } // ... and then emit sub[i]. if i < len(sub) { out = append(out, sub[i]) } start = i + 1 } sub = out // Round 4: Collapse runs of empty matches into a single empty match. start = 0 out = sub[:0] for i := range sub { if i+1 < len(sub) && sub[i].Op == OpEmptyMatch && sub[i+1].Op == OpEmptyMatch { continue } out = append(out, sub[i]) } sub = out return sub } // leadingString returns the leading literal string that re begins with. // The string refers to storage in re or its children. func (p *parser) leadingString(re *Regexp) ([]rune, Flags) { if re.Op == OpConcat && len(re.Sub) > 0 { re = re.Sub[0] } if re.Op != OpLiteral { return nil, 0 } return re.Rune, re.Flags & FoldCase } // removeLeadingString removes the first n leading runes // from the beginning of re. It returns the replacement for re. func (p *parser) removeLeadingString(re *Regexp, n int) *Regexp { if re.Op == OpConcat && len(re.Sub) > 0 { // Removing a leading string in a concatenation // might simplify the concatenation. sub := re.Sub[0] sub = p.removeLeadingString(sub, n) re.Sub[0] = sub if sub.Op == OpEmptyMatch { p.reuse(sub) switch len(re.Sub) { case 0, 1: // Impossible but handle. re.Op = OpEmptyMatch re.Sub = nil case 2: old := re re = re.Sub[1] p.reuse(old) default: copy(re.Sub, re.Sub[1:]) re.Sub = re.Sub[:len(re.Sub)-1] } } return re } if re.Op == OpLiteral { re.Rune = re.Rune[:copy(re.Rune, re.Rune[n:])] if len(re.Rune) == 0 { re.Op = OpEmptyMatch } } return re } // leadingRegexp returns the leading regexp that re begins with. // The regexp refers to storage in re or its children. func (p *parser) leadingRegexp(re *Regexp) *Regexp { if re.Op == OpEmptyMatch { return nil } if re.Op == OpConcat && len(re.Sub) > 0 { sub := re.Sub[0] if sub.Op == OpEmptyMatch { return nil } return sub } return re } // removeLeadingRegexp removes the leading regexp in re. // It returns the replacement for re. // If reuse is true, it passes the removed regexp (if no longer needed) to p.reuse. func (p *parser) removeLeadingRegexp(re *Regexp, reuse bool) *Regexp { if re.Op == OpConcat && len(re.Sub) > 0 { if reuse { p.reuse(re.Sub[0]) } re.Sub = re.Sub[:copy(re.Sub, re.Sub[1:])] switch len(re.Sub) { case 0: re.Op = OpEmptyMatch re.Sub = nil case 1: old := re re = re.Sub[0] p.reuse(old) } return re } if reuse { p.reuse(re) } return p.newRegexp(OpEmptyMatch) } func literalRegexp(s string, flags Flags) *Regexp { re := &Regexp{Op: OpLiteral} re.Flags = flags re.Rune = re.Rune0[:0] // use local storage for small strings for _, c := range s { if len(re.Rune) >= cap(re.Rune) { // string is too long to fit in Rune0. let Go handle it re.Rune = []rune(s) break } re.Rune = append(re.Rune, c) } return re } // Parsing. // Parse parses a regular expression string s, controlled by the specified // Flags, and returns a regular expression parse tree. The syntax is // described in the top-level comment. func Parse(s string, flags Flags) (*Regexp, error) { if flags&Literal != 0 { // Trivial parser for literal string. if err := checkUTF8(s); err != nil { return nil, err } return literalRegexp(s, flags), nil } // Otherwise, must do real work. var ( p parser err error c rune op Op lastRepeat string ) p.flags = flags p.wholeRegexp = s t := s for t != "" { repeat := "" BigSwitch: switch t[0] { default: if c, t, err = nextRune(t); err != nil { return nil, err } p.literal(c) case '(': if p.flags&PerlX != 0 && len(t) >= 2 && t[1] == '?' { // Flag changes and non-capturing groups. if t, err = p.parsePerlFlags(t); err != nil { return nil, err } break } p.numCap++ p.op(opLeftParen).Cap = p.numCap t = t[1:] case '|': if err = p.parseVerticalBar(); err != nil { return nil, err } t = t[1:] case ')': if err = p.parseRightParen(); err != nil { return nil, err } t = t[1:] case '^': if p.flags&OneLine != 0 { p.op(OpBeginText) } else { p.op(OpBeginLine) } t = t[1:] case '$': if p.flags&OneLine != 0 { p.op(OpEndText).Flags |= WasDollar } else { p.op(OpEndLine) } t = t[1:] case '.': if p.flags&DotNL != 0 { p.op(OpAnyChar) } else { p.op(OpAnyCharNotNL) } t = t[1:] case '[': if t, err = p.parseClass(t); err != nil { return nil, err } case '*', '+', '?': before := t switch t[0] { case '*': op = OpStar case '+': op = OpPlus case '?': op = OpQuest } after := t[1:] if after, err = p.repeat(op, 0, 0, before, after, lastRepeat); err != nil { return nil, err } repeat = before t = after case '{': op = OpRepeat before := t min, max, after, ok := p.parseRepeat(t) if !ok { // If the repeat cannot be parsed, { is a literal. p.literal('{') t = t[1:] break } if min < 0 || min > 1000 || max > 1000 || max >= 0 && min > max { // Numbers were too big, or max is present and min > max. return nil, &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]} } if after, err = p.repeat(op, min, max, before, after, lastRepeat); err != nil { return nil, err } repeat = before t = after case '\\': if p.flags&PerlX != 0 && len(t) >= 2 { switch t[1] { case 'A': p.op(OpBeginText) t = t[2:] break BigSwitch case 'b': p.op(OpWordBoundary) t = t[2:] break BigSwitch case 'B': p.op(OpNoWordBoundary) t = t[2:] break BigSwitch case 'C': // any byte; not supported p.op(OpAnyChar) t = t[2:] break BigSwitch case 'Q': // \Q ... \E: the ... is always literals var lit string if i := strings.Index(t, `\E`); i < 0 { lit = t[2:] t = "" } else { lit = t[2:i] t = t[i+2:] } for lit != "" { c, rest, err := nextRune(lit) if err != nil { return nil, err } p.literal(c) lit = rest } break BigSwitch case 'z': p.op(OpEndText) t = t[2:] break BigSwitch } } re := p.newRegexp(OpCharClass) re.Flags = p.flags // Look for Unicode character group like \p{Han} if len(t) >= 2 && (t[1] == 'p' || t[1] == 'P') { r, rest, err := p.parseUnicodeClass(t, re.Rune0[:0]) if err != nil { return nil, err } if r != nil { re.Rune = r t = rest p.push(re) break BigSwitch } } // Perl character class escape. if r, rest := p.parsePerlClassEscape(t, re.Rune0[:0]); r != nil { re.Rune = r t = rest p.push(re) break BigSwitch } p.reuse(re) // Ordinary single-character escape. if c, t, err = p.parseEscape(t); err != nil { return nil, err } p.literal(c) } lastRepeat = repeat } p.concat() if p.swapVerticalBar() { // pop vertical bar p.stack = p.stack[:len(p.stack)-1] } p.alternate() n := len(p.stack) if n != 1 { return nil, &Error{ErrMissingParen, s} } return p.stack[0], nil } // parseRepeat parses {min} (max=min) or {min,} (max=-1) or {min,max}. // If s is not of that form, it returns ok == false. // If s has the right form but the values are too big, it returns min == -1, ok == true. func (p *parser) parseRepeat(s string) (min, max int, rest string, ok bool) { if s == "" || s[0] != '{' { return } s = s[1:] var ok1 bool if min, s, ok1 = p.parseInt(s); !ok1 { return } if s == "" { return } if s[0] != ',' { max = min } else { s = s[1:] if s == "" { return } if s[0] == '}' { max = -1 } else if max, s, ok1 = p.parseInt(s); !ok1 { return } else if max < 0 { // parseInt found too big a number min = -1 } } if s == "" || s[0] != '}' { return } rest = s[1:] ok = true return } // parsePerlFlags parses a Perl flag setting or non-capturing group or both, // like (?i) or (?: or (?i:. It removes the prefix from s and updates the parse state. // The caller must have ensured that s begins with "(?". func (p *parser) parsePerlFlags(s string) (rest string, err error) { t := s // Check for named captures, first introduced in Python's regexp library. // As usual, there are three slightly different syntaxes: // // (?Pexpr) the original, introduced by Python // (?expr) the .NET alteration, adopted by Perl 5.10 // (?'name'expr) another .NET alteration, adopted by Perl 5.10 // // Perl 5.10 gave in and implemented the Python version too, // but they claim that the last two are the preferred forms. // PCRE and languages based on it (specifically, PHP and Ruby) // support all three as well. EcmaScript 4 uses only the Python form. // // In both the open source world (via Code Search) and the // Google source tree, (?Pname) is the dominant form, // so that's the one we implement. One is enough. if len(t) > 4 && t[2] == 'P' && t[3] == '<' { // Pull out name. end := strings.IndexRune(t, '>') if end < 0 { if err = checkUTF8(t); err != nil { return "", err } return "", &Error{ErrInvalidNamedCapture, s} } capture := t[:end+1] // "(?P" name := t[4:end] // "name" if err = checkUTF8(name); err != nil { return "", err } if !isValidCaptureName(name) { return "", &Error{ErrInvalidNamedCapture, capture} } // Like ordinary capture, but named. p.numCap++ re := p.op(opLeftParen) re.Cap = p.numCap re.Name = name return t[end+1:], nil } // Non-capturing group. Might also twiddle Perl flags. var c rune t = t[2:] // skip (? flags := p.flags sign := +1 sawFlag := false Loop: for t != "" { if c, t, err = nextRune(t); err != nil { return "", err } switch c { default: break Loop // Flags. case 'i': flags |= FoldCase sawFlag = true case 'm': flags &^= OneLine sawFlag = true case 's': flags |= DotNL sawFlag = true case 'U': flags |= NonGreedy sawFlag = true // Switch to negation. case '-': if sign < 0 { break Loop } sign = -1 // Invert flags so that | above turn into &^ and vice versa. // We'll invert flags again before using it below. flags = ^flags sawFlag = false // End of flags, starting group or not. case ':', ')': if sign < 0 { if !sawFlag { break Loop } flags = ^flags } if c == ':' { // Open new group p.op(opLeftParen) } p.flags = flags return t, nil } } return "", &Error{ErrInvalidPerlOp, s[:len(s)-len(t)]} } // isValidCaptureName reports whether name // is a valid capture name: [A-Za-z0-9_]+. // PCRE limits names to 32 bytes. // Python rejects names starting with digits. // We don't enforce either of those. func isValidCaptureName(name string) bool { if name == "" { return false } for _, c := range name { if c != '_' && !isalnum(c) { return false } } return true } // parseInt parses a decimal integer. func (p *parser) parseInt(s string) (n int, rest string, ok bool) { if s == "" || s[0] < '0' || '9' < s[0] { return } // Disallow leading zeros. if len(s) >= 2 && s[0] == '0' && '0' <= s[1] && s[1] <= '9' { return } t := s for s != "" && '0' <= s[0] && s[0] <= '9' { s = s[1:] } rest = s ok = true // Have digits, compute value. t = t[:len(t)-len(s)] for i := 0; i < len(t); i++ { // Avoid overflow. if n >= 1e8 { n = -1 break } n = n*10 + int(t[i]) - '0' } return } // can this be represented as a character class? // single-rune literal string, char class, ., and .|\n. func isCharClass(re *Regexp) bool { return re.Op == OpLiteral && len(re.Rune) == 1 || re.Op == OpCharClass || re.Op == OpAnyCharNotNL || re.Op == OpAnyChar } // does re match r? func matchRune(re *Regexp, r rune) bool { switch re.Op { case OpLiteral: return len(re.Rune) == 1 && re.Rune[0] == r case OpCharClass: for i := 0; i < len(re.Rune); i += 2 { if re.Rune[i] <= r && r <= re.Rune[i+1] { return true } } return false case OpAnyCharNotNL: return r != '\n' case OpAnyChar: return true } return false } // parseVerticalBar handles a | in the input. func (p *parser) parseVerticalBar() error { p.concat() // The concatenation we just parsed is on top of the stack. // If it sits above an opVerticalBar, swap it below // (things below an opVerticalBar become an alternation). // Otherwise, push a new vertical bar. if !p.swapVerticalBar() { p.op(opVerticalBar) } return nil } // mergeCharClass makes dst = dst|src. // The caller must ensure that dst.Op >= src.Op, // to reduce the amount of copying. func mergeCharClass(dst, src *Regexp) { switch dst.Op { case OpAnyChar: // src doesn't add anything. case OpAnyCharNotNL: // src might add \n if matchRune(src, '\n') { dst.Op = OpAnyChar } case OpCharClass: // src is simpler, so either literal or char class if src.Op == OpLiteral { dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags) } else { dst.Rune = appendClass(dst.Rune, src.Rune) } case OpLiteral: // both literal if src.Rune[0] == dst.Rune[0] && src.Flags == dst.Flags { break } dst.Op = OpCharClass dst.Rune = appendLiteral(dst.Rune[:0], dst.Rune[0], dst.Flags) dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags) } } // If the top of the stack is an element followed by an opVerticalBar // swapVerticalBar swaps the two and returns true. // Otherwise it returns false. func (p *parser) swapVerticalBar() bool { // If above and below vertical bar are literal or char class, // can merge into a single char class. n := len(p.stack) if n >= 3 && p.stack[n-2].Op == opVerticalBar && isCharClass(p.stack[n-1]) && isCharClass(p.stack[n-3]) { re1 := p.stack[n-1] re3 := p.stack[n-3] // Make re3 the more complex of the two. if re1.Op > re3.Op { re1, re3 = re3, re1 p.stack[n-3] = re3 } mergeCharClass(re3, re1) p.reuse(re1) p.stack = p.stack[:n-1] return true } if n >= 2 { re1 := p.stack[n-1] re2 := p.stack[n-2] if re2.Op == opVerticalBar { if n >= 3 { // Now out of reach. // Clean opportunistically. cleanAlt(p.stack[n-3]) } p.stack[n-2] = re1 p.stack[n-1] = re2 return true } } return false } // parseRightParen handles a ) in the input. func (p *parser) parseRightParen() error { p.concat() if p.swapVerticalBar() { // pop vertical bar p.stack = p.stack[:len(p.stack)-1] } p.alternate() n := len(p.stack) if n < 2 { return &Error{ErrUnexpectedParen, p.wholeRegexp} } re1 := p.stack[n-1] re2 := p.stack[n-2] p.stack = p.stack[:n-2] if re2.Op != opLeftParen { return &Error{ErrUnexpectedParen, p.wholeRegexp} } // Restore flags at time of paren. p.flags = re2.Flags if re2.Cap == 0 { // Just for grouping. p.push(re1) } else { re2.Op = OpCapture re2.Sub = re2.Sub0[:1] re2.Sub[0] = re1 p.push(re2) } return nil } // parseEscape parses an escape sequence at the beginning of s // and returns the rune. func (p *parser) parseEscape(s string) (r rune, rest string, err error) { t := s[1:] if t == "" { return 0, "", &Error{ErrTrailingBackslash, ""} } c, t, err := nextRune(t) if err != nil { return 0, "", err } Switch: switch c { default: if c < utf8.RuneSelf && !isalnum(c) { // Escaped non-word characters are always themselves. // PCRE is not quite so rigorous: it accepts things like // \q, but we don't. We once rejected \_, but too many // programs and people insist on using it, so allow \_. return c, t, nil } // Octal escapes. case '1', '2', '3', '4', '5', '6', '7': // Single non-zero digit is a backreference; not supported if t == "" || t[0] < '0' || t[0] > '7' { break } fallthrough case '0': // Consume up to three octal digits; already have one. r = c - '0' for i := 1; i < 3; i++ { if t == "" || t[0] < '0' || t[0] > '7' { break } r = r*8 + rune(t[0]) - '0' t = t[1:] } return r, t, nil // Hexadecimal escapes. case 'x': if t == "" { break } if c, t, err = nextRune(t); err != nil { return 0, "", err } if c == '{' { // Any number of digits in braces. // Perl accepts any text at all; it ignores all text // after the first non-hex digit. We require only hex digits, // and at least one. nhex := 0 r = 0 for { if t == "" { break Switch } if c, t, err = nextRune(t); err != nil { return 0, "", err } if c == '}' { break } v := unhex(c) if v < 0 { break Switch } r = r*16 + v if r > unicode.MaxRune { break Switch } nhex++ } if nhex == 0 { break Switch } return r, t, nil } // Easy case: two hex digits. x := unhex(c) if c, t, err = nextRune(t); err != nil { return 0, "", err } y := unhex(c) if x < 0 || y < 0 { break } return x*16 + y, t, nil // C escapes. There is no case 'b', to avoid misparsing // the Perl word-boundary \b as the C backspace \b // when in POSIX mode. In Perl, /\b/ means word-boundary // but /[\b]/ means backspace. We don't support that. // If you want a backspace, embed a literal backspace // character or use \x08. case 'a': return '\a', t, err case 'f': return '\f', t, err case 'n': return '\n', t, err case 'r': return '\r', t, err case 't': return '\t', t, err case 'v': return '\v', t, err } return 0, "", &Error{ErrInvalidEscape, s[:len(s)-len(t)]} } // parseClassChar parses a character class character at the beginning of s // and returns it. func (p *parser) parseClassChar(s, wholeClass string) (r rune, rest string, err error) { if s == "" { return 0, "", &Error{Code: ErrMissingBracket, Expr: wholeClass} } // Allow regular escape sequences even though // many need not be escaped in this context. if s[0] == '\\' { return p.parseEscape(s) } return nextRune(s) } type charGroup struct { sign int class []rune } // parsePerlClassEscape parses a leading Perl character class escape like \d // from the beginning of s. If one is present, it appends the characters to r // and returns the new slice r and the remainder of the string. func (p *parser) parsePerlClassEscape(s string, r []rune) (out []rune, rest string) { if p.flags&PerlX == 0 || len(s) < 2 || s[0] != '\\' { return } g := perlGroup[s[0:2]] if g.sign == 0 { return } return p.appendGroup(r, g), s[2:] } // parseNamedClass parses a leading POSIX named character class like [:alnum:] // from the beginning of s. If one is present, it appends the characters to r // and returns the new slice r and the remainder of the string. func (p *parser) parseNamedClass(s string, r []rune) (out []rune, rest string, err error) { if len(s) < 2 || s[0] != '[' || s[1] != ':' { return } i := strings.Index(s[2:], ":]") if i < 0 { return } i += 2 name, s := s[0:i+2], s[i+2:] g := posixGroup[name] if g.sign == 0 { return nil, "", &Error{ErrInvalidCharRange, name} } return p.appendGroup(r, g), s, nil } func (p *parser) appendGroup(r []rune, g charGroup) []rune { if p.flags&FoldCase == 0 { if g.sign < 0 { r = appendNegatedClass(r, g.class) } else { r = appendClass(r, g.class) } } else { tmp := p.tmpClass[:0] tmp = appendFoldedClass(tmp, g.class) p.tmpClass = tmp tmp = cleanClass(&p.tmpClass) if g.sign < 0 { r = appendNegatedClass(r, tmp) } else { r = appendClass(r, tmp) } } return r } var anyTable = &unicode.RangeTable{ R16: []unicode.Range16{{Lo: 0, Hi: 1<<16 - 1, Stride: 1}}, R32: []unicode.Range32{{Lo: 1 << 16, Hi: unicode.MaxRune, Stride: 1}}, } // unicodeTable returns the unicode.RangeTable identified by name // and the table of additional fold-equivalent code points. func unicodeTable(name string) (*unicode.RangeTable, *unicode.RangeTable) { // Special case: "Any" means any. if name == "Any" { return anyTable, anyTable } if t := unicode.Categories[name]; t != nil { return t, unicode.FoldCategory[name] } if t := unicode.Scripts[name]; t != nil { return t, unicode.FoldScript[name] } return nil, nil } // parseUnicodeClass parses a leading Unicode character class like \p{Han} // from the beginning of s. If one is present, it appends the characters to r // and returns the new slice r and the remainder of the string. func (p *parser) parseUnicodeClass(s string, r []rune) (out []rune, rest string, err error) { if p.flags&UnicodeGroups == 0 || len(s) < 2 || s[0] != '\\' || s[1] != 'p' && s[1] != 'P' { return } // Committed to parse or return error. sign := +1 if s[1] == 'P' { sign = -1 } t := s[2:] c, t, err := nextRune(t) if err != nil { return } var seq, name string if c != '{' { // Single-letter name. seq = s[:len(s)-len(t)] name = seq[2:] } else { // Name is in braces. end := strings.IndexRune(s, '}') if end < 0 { if err = checkUTF8(s); err != nil { return } return nil, "", &Error{ErrInvalidCharRange, s} } seq, t = s[:end+1], s[end+1:] name = s[3:end] if err = checkUTF8(name); err != nil { return } } // Group can have leading negation too. \p{^Han} == \P{Han}, \P{^Han} == \p{Han}. if name != "" && name[0] == '^' { sign = -sign name = name[1:] } tab, fold := unicodeTable(name) if tab == nil { return nil, "", &Error{ErrInvalidCharRange, seq} } if p.flags&FoldCase == 0 || fold == nil { if sign > 0 { r = appendTable(r, tab) } else { r = appendNegatedTable(r, tab) } } else { // Merge and clean tab and fold in a temporary buffer. // This is necessary for the negative case and just tidy // for the positive case. tmp := p.tmpClass[:0] tmp = appendTable(tmp, tab) tmp = appendTable(tmp, fold) p.tmpClass = tmp tmp = cleanClass(&p.tmpClass) if sign > 0 { r = appendClass(r, tmp) } else { r = appendNegatedClass(r, tmp) } } return r, t, nil } // parseClass parses a character class at the beginning of s // and pushes it onto the parse stack. func (p *parser) parseClass(s string) (rest string, err error) { t := s[1:] // chop [ re := p.newRegexp(OpCharClass) re.Flags = p.flags re.Rune = re.Rune0[:0] sign := +1 if t != "" && t[0] == '^' { sign = -1 t = t[1:] // If character class does not match \n, add it here, // so that negation later will do the right thing. if p.flags&ClassNL == 0 { re.Rune = append(re.Rune, '\n', '\n') } } class := re.Rune first := true // ] and - are okay as first char in class for t == "" || t[0] != ']' || first { // POSIX: - is only okay unescaped as first or last in class. // Perl: - is okay anywhere. if t != "" && t[0] == '-' && p.flags&PerlX == 0 && !first && (len(t) == 1 || t[1] != ']') { _, size := utf8.DecodeRuneInString(t[1:]) return "", &Error{Code: ErrInvalidCharRange, Expr: t[:1+size]} } first = false // Look for POSIX [:alnum:] etc. if len(t) > 2 && t[0] == '[' && t[1] == ':' { nclass, nt, err := p.parseNamedClass(t, class) if err != nil { return "", err } if nclass != nil { class, t = nclass, nt continue } } // Look for Unicode character group like \p{Han}. nclass, nt, err := p.parseUnicodeClass(t, class) if err != nil { return "", err } if nclass != nil { class, t = nclass, nt continue } // Look for Perl character class symbols (extension). if nclass, nt := p.parsePerlClassEscape(t, class); nclass != nil { class, t = nclass, nt continue } // Single character or simple range. rng := t var lo, hi rune if lo, t, err = p.parseClassChar(t, s); err != nil { return "", err } hi = lo // [a-] means (a|-) so check for final ]. if len(t) >= 2 && t[0] == '-' && t[1] != ']' { t = t[1:] if hi, t, err = p.parseClassChar(t, s); err != nil { return "", err } if hi < lo { rng = rng[:len(rng)-len(t)] return "", &Error{Code: ErrInvalidCharRange, Expr: rng} } } if p.flags&FoldCase == 0 { class = appendRange(class, lo, hi) } else { class = appendFoldedRange(class, lo, hi) } } t = t[1:] // chop ] // Use &re.Rune instead of &class to avoid allocation. re.Rune = class class = cleanClass(&re.Rune) if sign < 0 { class = negateClass(class) } re.Rune = class p.push(re) return t, nil } // cleanClass sorts the ranges (pairs of elements of r), // merges them, and eliminates duplicates. func cleanClass(rp *[]rune) []rune { // Sort by lo increasing, hi decreasing to break ties. sort.Sort(ranges{rp}) r := *rp if len(r) < 2 { return r } // Merge abutting, overlapping. w := 2 // write index for i := 2; i < len(r); i += 2 { lo, hi := r[i], r[i+1] if lo <= r[w-1]+1 { // merge with previous range if hi > r[w-1] { r[w-1] = hi } continue } // new disjoint range r[w] = lo r[w+1] = hi w += 2 } return r[:w] } // appendLiteral returns the result of appending the literal x to the class r. func appendLiteral(r []rune, x rune, flags Flags) []rune { if flags&FoldCase != 0 { return appendFoldedRange(r, x, x) } return appendRange(r, x, x) } // appendRange returns the result of appending the range lo-hi to the class r. func appendRange(r []rune, lo, hi rune) []rune { // Expand last range or next to last range if it overlaps or abuts. // Checking two ranges helps when appending case-folded // alphabets, so that one range can be expanding A-Z and the // other expanding a-z. n := len(r) for i := 2; i <= 4; i += 2 { // twice, using i=2, i=4 if n >= i { rlo, rhi := r[n-i], r[n-i+1] if lo <= rhi+1 && rlo <= hi+1 { if lo < rlo { r[n-i] = lo } if hi > rhi { r[n-i+1] = hi } return r } } } return append(r, lo, hi) } const ( // minimum and maximum runes involved in folding. // checked during test. minFold = 0x0041 maxFold = 0x1e943 ) // appendFoldedRange returns the result of appending the range lo-hi // and its case folding-equivalent runes to the class r. func appendFoldedRange(r []rune, lo, hi rune) []rune { // Optimizations. if lo <= minFold && hi >= maxFold { // Range is full: folding can't add more. return appendRange(r, lo, hi) } if hi < minFold || lo > maxFold { // Range is outside folding possibilities. return appendRange(r, lo, hi) } if lo < minFold { // [lo, minFold-1] needs no folding. r = appendRange(r, lo, minFold-1) lo = minFold } if hi > maxFold { // [maxFold+1, hi] needs no folding. r = appendRange(r, maxFold+1, hi) hi = maxFold } // Brute force. Depend on appendRange to coalesce ranges on the fly. for c := lo; c <= hi; c++ { r = appendRange(r, c, c) f := unicode.SimpleFold(c) for f != c { r = appendRange(r, f, f) f = unicode.SimpleFold(f) } } return r } // appendClass returns the result of appending the class x to the class r. // It assume x is clean. func appendClass(r []rune, x []rune) []rune { for i := 0; i < len(x); i += 2 { r = appendRange(r, x[i], x[i+1]) } return r } // appendFolded returns the result of appending the case folding of the class x to the class r. func appendFoldedClass(r []rune, x []rune) []rune { for i := 0; i < len(x); i += 2 { r = appendFoldedRange(r, x[i], x[i+1]) } return r } // appendNegatedClass returns the result of appending the negation of the class x to the class r. // It assumes x is clean. func appendNegatedClass(r []rune, x []rune) []rune { nextLo := '\u0000' for i := 0; i < len(x); i += 2 { lo, hi := x[i], x[i+1] if nextLo <= lo-1 { r = appendRange(r, nextLo, lo-1) } nextLo = hi + 1 } if nextLo <= unicode.MaxRune { r = appendRange(r, nextLo, unicode.MaxRune) } return r } // appendTable returns the result of appending x to the class r. func appendTable(r []rune, x *unicode.RangeTable) []rune { for _, xr := range x.R16 { lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride) if stride == 1 { r = appendRange(r, lo, hi) continue } for c := lo; c <= hi; c += stride { r = appendRange(r, c, c) } } for _, xr := range x.R32 { lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride) if stride == 1 { r = appendRange(r, lo, hi) continue } for c := lo; c <= hi; c += stride { r = appendRange(r, c, c) } } return r } // appendNegatedTable returns the result of appending the negation of x to the class r. func appendNegatedTable(r []rune, x *unicode.RangeTable) []rune { nextLo := '\u0000' // lo end of next class to add for _, xr := range x.R16 { lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride) if stride == 1 { if nextLo <= lo-1 { r = appendRange(r, nextLo, lo-1) } nextLo = hi + 1 continue } for c := lo; c <= hi; c += stride { if nextLo <= c-1 { r = appendRange(r, nextLo, c-1) } nextLo = c + 1 } } for _, xr := range x.R32 { lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride) if stride == 1 { if nextLo <= lo-1 { r = appendRange(r, nextLo, lo-1) } nextLo = hi + 1 continue } for c := lo; c <= hi; c += stride { if nextLo <= c-1 { r = appendRange(r, nextLo, c-1) } nextLo = c + 1 } } if nextLo <= unicode.MaxRune { r = appendRange(r, nextLo, unicode.MaxRune) } return r } // negateClass overwrites r and returns r's negation. // It assumes the class r is already clean. func negateClass(r []rune) []rune { nextLo := '\u0000' // lo end of next class to add w := 0 // write index for i := 0; i < len(r); i += 2 { lo, hi := r[i], r[i+1] if nextLo <= lo-1 { r[w] = nextLo r[w+1] = lo - 1 w += 2 } nextLo = hi + 1 } r = r[:w] if nextLo <= unicode.MaxRune { // It's possible for the negation to have one more // range - this one - than the original class, so use append. r = append(r, nextLo, unicode.MaxRune) } return r } // ranges implements sort.Interface on a []rune. // The choice of receiver type definition is strange // but avoids an allocation since we already have // a *[]rune. type ranges struct { p *[]rune } func (ra ranges) Less(i, j int) bool { p := *ra.p i *= 2 j *= 2 return p[i] < p[j] || p[i] == p[j] && p[i+1] > p[j+1] } func (ra ranges) Len() int { return len(*ra.p) / 2 } func (ra ranges) Swap(i, j int) { p := *ra.p i *= 2 j *= 2 p[i], p[i+1], p[j], p[j+1] = p[j], p[j+1], p[i], p[i+1] } func checkUTF8(s string) error { for s != "" { rune, size := utf8.DecodeRuneInString(s) if rune == utf8.RuneError && size == 1 { return &Error{Code: ErrInvalidUTF8, Expr: s} } s = s[size:] } return nil } func nextRune(s string) (c rune, t string, err error) { c, size := utf8.DecodeRuneInString(s) if c == utf8.RuneError && size == 1 { return 0, "", &Error{Code: ErrInvalidUTF8, Expr: s} } return c, s[size:], nil } func isalnum(c rune) bool { return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' } func unhex(c rune) rune { if '0' <= c && c <= '9' { return c - '0' } if 'a' <= c && c <= 'f' { return c - 'a' + 10 } if 'A' <= c && c <= 'F' { return c - 'A' + 10 } return -1 } binaryregexp-0.2.0/syntax/parse_test.go000066400000000000000000000346111347202265500202510ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package syntax import ( "bytes" "fmt" "testing" "unicode" ) type parseTest struct { Regexp string Dump string } var parseTests = []parseTest{ // Base cases {`a`, `lit{a}`}, {`a.`, `cat{lit{a}dot{}}`}, {`a.b`, `cat{lit{a}dot{}lit{b}}`}, {`ab`, `str{ab}`}, {`a.b.c`, `cat{lit{a}dot{}lit{b}dot{}lit{c}}`}, {`abc`, `str{abc}`}, {`a|^`, `alt{lit{a}bol{}}`}, {`a|b`, `cc{0x61-0x62}`}, {`(a)`, `cap{lit{a}}`}, {`(a)|b`, `alt{cap{lit{a}}lit{b}}`}, {`a*`, `star{lit{a}}`}, {`a+`, `plus{lit{a}}`}, {`a?`, `que{lit{a}}`}, {`a{2}`, `rep{2,2 lit{a}}`}, {`a{2,3}`, `rep{2,3 lit{a}}`}, {`a{2,}`, `rep{2,-1 lit{a}}`}, {`a*?`, `nstar{lit{a}}`}, {`a+?`, `nplus{lit{a}}`}, {`a??`, `nque{lit{a}}`}, {`a{2}?`, `nrep{2,2 lit{a}}`}, {`a{2,3}?`, `nrep{2,3 lit{a}}`}, {`a{2,}?`, `nrep{2,-1 lit{a}}`}, // Malformed { } are treated as literals. {`x{1001`, `str{x{1001}`}, {`x{9876543210`, `str{x{9876543210}`}, {`x{9876543210,`, `str{x{9876543210,}`}, {`x{2,1`, `str{x{2,1}`}, {`x{1,9876543210`, `str{x{1,9876543210}`}, {``, `emp{}`}, {`|`, `emp{}`}, // alt{emp{}emp{}} but got factored {`|x|`, `alt{emp{}lit{x}emp{}}`}, {`.`, `dot{}`}, {`^`, `bol{}`}, {`$`, `eol{}`}, {`\|`, `lit{|}`}, {`\(`, `lit{(}`}, {`\)`, `lit{)}`}, {`\*`, `lit{*}`}, {`\+`, `lit{+}`}, {`\?`, `lit{?}`}, {`{`, `lit{{}`}, {`}`, `lit{}}`}, {`\.`, `lit{.}`}, {`\^`, `lit{^}`}, {`\$`, `lit{$}`}, {`\\`, `lit{\}`}, {`[ace]`, `cc{0x61 0x63 0x65}`}, {`[abc]`, `cc{0x61-0x63}`}, {`[a-z]`, `cc{0x61-0x7a}`}, {`[a]`, `lit{a}`}, {`\-`, `lit{-}`}, {`-`, `lit{-}`}, {`\_`, `lit{_}`}, {`abc`, `str{abc}`}, {`abc|def`, `alt{str{abc}str{def}}`}, {`abc|def|ghi`, `alt{str{abc}str{def}str{ghi}}`}, // Posix and Perl extensions {`[[:lower:]]`, `cc{0x61-0x7a}`}, {`[a-z]`, `cc{0x61-0x7a}`}, {`[^[:lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`}, {`[[:^lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`}, {`(?i)[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`}, {`(?i)[a-z]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`}, {`(?i)[^[:lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`}, {`(?i)[[:^lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`}, {`\d`, `cc{0x30-0x39}`}, {`\D`, `cc{0x0-0x2f 0x3a-0x10ffff}`}, {`\s`, `cc{0x9-0xa 0xc-0xd 0x20}`}, {`\S`, `cc{0x0-0x8 0xb 0xe-0x1f 0x21-0x10ffff}`}, {`\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a}`}, {`\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x10ffff}`}, {`(?i)\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a 0x17f 0x212a}`}, {`(?i)\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`}, {`[^\\]`, `cc{0x0-0x5b 0x5d-0x10ffff}`}, {`\C`, `dot{}`}, // Unicode, negatives, and a double negative. {`\p{Braille}`, `cc{0x2800-0x28ff}`}, {`\P{Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`}, {`\p{^Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`}, {`\P{^Braille}`, `cc{0x2800-0x28ff}`}, {`\pZ`, `cc{0x20 0xa0 0x1680 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`}, {`[\p{Braille}]`, `cc{0x2800-0x28ff}`}, {`[\P{Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`}, {`[\p{^Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`}, {`[\P{^Braille}]`, `cc{0x2800-0x28ff}`}, {`[\pZ]`, `cc{0x20 0xa0 0x1680 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`}, {`\p{Lu}`, mkCharClass(unicode.IsUpper)}, {`[\p{Lu}]`, mkCharClass(unicode.IsUpper)}, {`(?i)[\p{Lu}]`, mkCharClass(isUpperFold)}, {`\p{Any}`, `dot{}`}, {`\p{^Any}`, `cc{}`}, // Hex, octal. {`[\012-\234]\141`, `cat{cc{0xa-0x9c}lit{a}}`}, {`[\x{41}-\x7a]\x61`, `cat{cc{0x41-0x7a}lit{a}}`}, // More interesting regular expressions. {`a{,2}`, `str{a{,2}}`}, {`\.\^\$\\`, `str{.^$\}`}, {`[a-zABC]`, `cc{0x41-0x43 0x61-0x7a}`}, {`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`}, {`[α-ε☺]`, `cc{0x3b1-0x3b5 0x263a}`}, // utf-8 {`a*{`, `cat{star{lit{a}}lit{{}}`}, // Test precedences {`(?:ab)*`, `star{str{ab}}`}, {`(ab)*`, `star{cap{str{ab}}}`}, {`ab|cd`, `alt{str{ab}str{cd}}`}, {`a(b|c)d`, `cat{lit{a}cap{cc{0x62-0x63}}lit{d}}`}, // Test flattening. {`(?:a)`, `lit{a}`}, {`(?:ab)(?:cd)`, `str{abcd}`}, {`(?:a+b+)(?:c+d+)`, `cat{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`}, {`(?:a+|b+)|(?:c+|d+)`, `alt{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`}, {`(?:a|b)|(?:c|d)`, `cc{0x61-0x64}`}, {`a|.`, `dot{}`}, {`.|a`, `dot{}`}, {`(?:[abc]|A|Z|hello|world)`, `alt{cc{0x41 0x5a 0x61-0x63}str{hello}str{world}}`}, {`(?:[abc]|A|Z)`, `cc{0x41 0x5a 0x61-0x63}`}, // Test Perl quoted literals {`\Q+|*?{[\E`, `str{+|*?{[}`}, {`\Q+\E+`, `plus{lit{+}}`}, {`\Qab\E+`, `cat{lit{a}plus{lit{b}}}`}, {`\Q\\E`, `lit{\}`}, {`\Q\\\E`, `str{\\}`}, // Test Perl \A and \z {`(?m)^`, `bol{}`}, {`(?m)$`, `eol{}`}, {`(?-m)^`, `bot{}`}, {`(?-m)$`, `eot{}`}, {`(?m)\A`, `bot{}`}, {`(?m)\z`, `eot{\z}`}, {`(?-m)\A`, `bot{}`}, {`(?-m)\z`, `eot{\z}`}, // Test named captures {`(?Pa)`, `cap{name:lit{a}}`}, // Case-folded literals {`[Aa]`, `litfold{A}`}, {`[\x{100}\x{101}]`, `litfold{Ā}`}, {`[Δδ]`, `litfold{Δ}`}, // Strings {`abcde`, `str{abcde}`}, {`[Aa][Bb]cd`, `cat{strfold{AB}str{cd}}`}, // Factoring. {`abc|abd|aef|bcx|bcy`, `alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}cat{str{bc}cc{0x78-0x79}}}`}, {`ax+y|ax+z|ay+w`, `cat{lit{a}alt{cat{plus{lit{x}}lit{y}}cat{plus{lit{x}}lit{z}}cat{plus{lit{y}}lit{w}}}}`}, // Bug fixes. {`(?:.)`, `dot{}`}, {`(?:x|(?:xa))`, `cat{lit{x}alt{emp{}lit{a}}}`}, {`(?:.|(?:.a))`, `cat{dot{}alt{emp{}lit{a}}}`}, {`(?:A(?:A|a))`, `cat{lit{A}litfold{A}}`}, {`(?:A|a)`, `litfold{A}`}, {`A|(?:A|a)`, `litfold{A}`}, {`(?s).`, `dot{}`}, {`(?-s).`, `dnl{}`}, {`(?:(?:^).)`, `cat{bol{}dot{}}`}, {`(?-s)(?:(?:^).)`, `cat{bol{}dnl{}}`}, // RE2 prefix_tests {`abc|abd`, `cat{str{ab}cc{0x63-0x64}}`}, {`a(?:b)c|abd`, `cat{str{ab}cc{0x63-0x64}}`}, {`abc|abd|aef|bcx|bcy`, `alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}` + `cat{str{bc}cc{0x78-0x79}}}`}, {`abc|x|abd`, `alt{str{abc}lit{x}str{abd}}`}, {`(?i)abc|ABD`, `cat{strfold{AB}cc{0x43-0x44 0x63-0x64}}`}, {`[ab]c|[ab]d`, `cat{cc{0x61-0x62}cc{0x63-0x64}}`}, {`.c|.d`, `cat{dot{}cc{0x63-0x64}}`}, {`x{2}|x{2}[0-9]`, `cat{rep{2,2 lit{x}}alt{emp{}cc{0x30-0x39}}}`}, {`x{2}y|x{2}[0-9]y`, `cat{rep{2,2 lit{x}}alt{lit{y}cat{cc{0x30-0x39}lit{y}}}}`}, {`a.*?c|a.*?b`, `cat{lit{a}alt{cat{nstar{dot{}}lit{c}}cat{nstar{dot{}}lit{b}}}}`}, // Valid repetitions. {`((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))`, ``}, {`((((((((((x{1}){2}){2}){2}){2}){2}){2}){2}){2}){2})`, ``}, } const testFlags = MatchNL | PerlX | UnicodeGroups func TestParseSimple(t *testing.T) { testParseDump(t, parseTests, testFlags) } var foldcaseTests = []parseTest{ {`AbCdE`, `strfold{ABCDE}`}, {`[Aa]`, `litfold{A}`}, {`a`, `litfold{A}`}, // 0x17F is an old English long s (looks like an f) and folds to s. // 0x212A is the Kelvin symbol and folds to k. {`A[F-g]`, `cat{litfold{A}cc{0x41-0x7a 0x17f 0x212a}}`}, // [Aa][A-z...] {`[[:upper:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`}, {`[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`}, } func TestParseFoldCase(t *testing.T) { testParseDump(t, foldcaseTests, FoldCase) } var literalTests = []parseTest{ {"(|)^$.[*+?]{5,10},\\", "str{(|)^$.[*+?]{5,10},\\}"}, } func TestParseLiteral(t *testing.T) { testParseDump(t, literalTests, Literal) } var matchnlTests = []parseTest{ {`.`, `dot{}`}, {"\n", "lit{\n}"}, {`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`}, {`[a\n]`, `cc{0xa 0x61}`}, } func TestParseMatchNL(t *testing.T) { testParseDump(t, matchnlTests, MatchNL) } var nomatchnlTests = []parseTest{ {`.`, `dnl{}`}, {"\n", "lit{\n}"}, {`[^a]`, `cc{0x0-0x9 0xb-0x60 0x62-0x10ffff}`}, {`[a\n]`, `cc{0xa 0x61}`}, } func TestParseNoMatchNL(t *testing.T) { testParseDump(t, nomatchnlTests, 0) } // Test Parse -> Dump. func testParseDump(t *testing.T, tests []parseTest, flags Flags) { for _, tt := range tests { re, err := Parse(tt.Regexp, flags) if err != nil { t.Errorf("Parse(%#q): %v", tt.Regexp, err) continue } if tt.Dump == "" { // It parsed. That's all we care about. continue } d := dump(re) if d != tt.Dump { t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump) } } } // dump prints a string representation of the regexp showing // the structure explicitly. func dump(re *Regexp) string { var b bytes.Buffer dumpRegexp(&b, re) return b.String() } var opNames = []string{ OpNoMatch: "no", OpEmptyMatch: "emp", OpLiteral: "lit", OpCharClass: "cc", OpAnyCharNotNL: "dnl", OpAnyChar: "dot", OpBeginLine: "bol", OpEndLine: "eol", OpBeginText: "bot", OpEndText: "eot", OpWordBoundary: "wb", OpNoWordBoundary: "nwb", OpCapture: "cap", OpStar: "star", OpPlus: "plus", OpQuest: "que", OpRepeat: "rep", OpConcat: "cat", OpAlternate: "alt", } // dumpRegexp writes an encoding of the syntax tree for the regexp re to b. // It is used during testing to distinguish between parses that might print // the same using re's String method. func dumpRegexp(b *bytes.Buffer, re *Regexp) { if int(re.Op) >= len(opNames) || opNames[re.Op] == "" { fmt.Fprintf(b, "op%d", re.Op) } else { switch re.Op { default: b.WriteString(opNames[re.Op]) case OpStar, OpPlus, OpQuest, OpRepeat: if re.Flags&NonGreedy != 0 { b.WriteByte('n') } b.WriteString(opNames[re.Op]) case OpLiteral: if len(re.Rune) > 1 { b.WriteString("str") } else { b.WriteString("lit") } if re.Flags&FoldCase != 0 { for _, r := range re.Rune { if unicode.SimpleFold(r) != r { b.WriteString("fold") break } } } } } b.WriteByte('{') switch re.Op { case OpEndText: if re.Flags&WasDollar == 0 { b.WriteString(`\z`) } case OpLiteral: for _, r := range re.Rune { b.WriteRune(r) } case OpConcat, OpAlternate: for _, sub := range re.Sub { dumpRegexp(b, sub) } case OpStar, OpPlus, OpQuest: dumpRegexp(b, re.Sub[0]) case OpRepeat: fmt.Fprintf(b, "%d,%d ", re.Min, re.Max) dumpRegexp(b, re.Sub[0]) case OpCapture: if re.Name != "" { b.WriteString(re.Name) b.WriteByte(':') } dumpRegexp(b, re.Sub[0]) case OpCharClass: sep := "" for i := 0; i < len(re.Rune); i += 2 { b.WriteString(sep) sep = " " lo, hi := re.Rune[i], re.Rune[i+1] if lo == hi { fmt.Fprintf(b, "%#x", lo) } else { fmt.Fprintf(b, "%#x-%#x", lo, hi) } } } b.WriteByte('}') } func mkCharClass(f func(rune) bool) string { re := &Regexp{Op: OpCharClass} lo := rune(-1) for i := rune(0); i <= unicode.MaxRune; i++ { if f(i) { if lo < 0 { lo = i } } else { if lo >= 0 { re.Rune = append(re.Rune, lo, i-1) lo = -1 } } } if lo >= 0 { re.Rune = append(re.Rune, lo, unicode.MaxRune) } return dump(re) } func isUpperFold(r rune) bool { if unicode.IsUpper(r) { return true } c := unicode.SimpleFold(r) for c != r { if unicode.IsUpper(c) { return true } c = unicode.SimpleFold(c) } return false } func TestFoldConstants(t *testing.T) { last := rune(-1) for i := rune(0); i <= unicode.MaxRune; i++ { if unicode.SimpleFold(i) == i { continue } if last == -1 && minFold != i { t.Errorf("minFold=%#U should be %#U", minFold, i) } last = i } if maxFold != last { t.Errorf("maxFold=%#U should be %#U", maxFold, last) } } func TestAppendRangeCollapse(t *testing.T) { // AppendRange should collapse each of the new ranges // into the earlier ones (it looks back two ranges), so that // the slice never grows very large. // Note that we are not calling cleanClass. var r []rune for i := rune('A'); i <= 'Z'; i++ { r = appendRange(r, i, i) r = appendRange(r, i+'a'-'A', i+'a'-'A') } if string(r) != "AZaz" { t.Errorf("appendRange interlaced A-Z a-z = %s, want AZaz", string(r)) } } var invalidRegexps = []string{ `(`, `)`, `(a`, `a)`, `(a))`, `(a|b|`, `a|b|)`, `(a|b|))`, `(a|b`, `a|b)`, `(a|b))`, `[a-z`, `([a-z)`, `[a-z)`, `([a-z]))`, `x{1001}`, `x{9876543210}`, `x{2,1}`, `x{1,9876543210}`, "\xff", // Invalid UTF-8 "[\xff]", "[\\\xff]", "\\\xff", `(?Pa`, `(?P`, `(?Pa)`, `(?P<>a)`, `[a-Z]`, `(?i)[a-Z]`, `a{100000}`, `a{100000,}`, "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})", `\Q\E*`, } var onlyPerl = []string{ `[a-b-c]`, `\Qabc\E`, `\Q*+?{[\E`, `\Q\\E`, `\Q\\\E`, `\Q\\\\E`, `\Q\\\\\E`, `(?:a)`, `(?Pa)`, } var onlyPOSIX = []string{ "a++", "a**", "a?*", "a+*", "a{1}*", ".{1}{2}.{3}", } func TestParseInvalidRegexps(t *testing.T) { for _, regexp := range invalidRegexps { if re, err := Parse(regexp, Perl); err == nil { t.Errorf("Parse(%#q, Perl) = %s, should have failed", regexp, dump(re)) } if re, err := Parse(regexp, POSIX); err == nil { t.Errorf("Parse(%#q, POSIX) = %s, should have failed", regexp, dump(re)) } } for _, regexp := range onlyPerl { if _, err := Parse(regexp, Perl); err != nil { t.Errorf("Parse(%#q, Perl): %v", regexp, err) } if re, err := Parse(regexp, POSIX); err == nil { t.Errorf("Parse(%#q, POSIX) = %s, should have failed", regexp, dump(re)) } } for _, regexp := range onlyPOSIX { if re, err := Parse(regexp, Perl); err == nil { t.Errorf("Parse(%#q, Perl) = %s, should have failed", regexp, dump(re)) } if _, err := Parse(regexp, POSIX); err != nil { t.Errorf("Parse(%#q, POSIX): %v", regexp, err) } } } func TestToStringEquivalentParse(t *testing.T) { for _, tt := range parseTests { re, err := Parse(tt.Regexp, testFlags) if err != nil { t.Errorf("Parse(%#q): %v", tt.Regexp, err) continue } if tt.Dump == "" { // It parsed. That's all we care about. continue } d := dump(re) if d != tt.Dump { t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump) continue } s := re.String() if s != tt.Regexp { // If ToString didn't return the original regexp, // it must have found one with fewer parens. // Unfortunately we can't check the length here, because // ToString produces "\\{" for a literal brace, // but "{" is a shorter equivalent in some contexts. nre, err := Parse(s, testFlags) if err != nil { t.Errorf("Parse(%#q.String() = %#q): %v", tt.Regexp, s, err) continue } nd := dump(nre) if d != nd { t.Errorf("Parse(%#q) -> %#q; %#q vs %#q", tt.Regexp, s, d, nd) } ns := nre.String() if s != ns { t.Errorf("Parse(%#q) -> %#q -> %#q", tt.Regexp, s, ns) } } } } binaryregexp-0.2.0/syntax/perl_groups.go000066400000000000000000000045431347202265500204420ustar00rootroot00000000000000// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // GENERATED BY make_perl_groups.pl; DO NOT EDIT. // make_perl_groups.pl >perl_groups.go package syntax var code1 = []rune{ /* \d */ 0x30, 0x39, } var code2 = []rune{ /* \s */ 0x9, 0xa, 0xc, 0xd, 0x20, 0x20, } var code3 = []rune{ /* \w */ 0x30, 0x39, 0x41, 0x5a, 0x5f, 0x5f, 0x61, 0x7a, } var perlGroup = map[string]charGroup{ `\d`: {+1, code1}, `\D`: {-1, code1}, `\s`: {+1, code2}, `\S`: {-1, code2}, `\w`: {+1, code3}, `\W`: {-1, code3}, } var code4 = []rune{ /* [:alnum:] */ 0x30, 0x39, 0x41, 0x5a, 0x61, 0x7a, } var code5 = []rune{ /* [:alpha:] */ 0x41, 0x5a, 0x61, 0x7a, } var code6 = []rune{ /* [:ascii:] */ 0x0, 0x7f, } var code7 = []rune{ /* [:blank:] */ 0x9, 0x9, 0x20, 0x20, } var code8 = []rune{ /* [:cntrl:] */ 0x0, 0x1f, 0x7f, 0x7f, } var code9 = []rune{ /* [:digit:] */ 0x30, 0x39, } var code10 = []rune{ /* [:graph:] */ 0x21, 0x7e, } var code11 = []rune{ /* [:lower:] */ 0x61, 0x7a, } var code12 = []rune{ /* [:print:] */ 0x20, 0x7e, } var code13 = []rune{ /* [:punct:] */ 0x21, 0x2f, 0x3a, 0x40, 0x5b, 0x60, 0x7b, 0x7e, } var code14 = []rune{ /* [:space:] */ 0x9, 0xd, 0x20, 0x20, } var code15 = []rune{ /* [:upper:] */ 0x41, 0x5a, } var code16 = []rune{ /* [:word:] */ 0x30, 0x39, 0x41, 0x5a, 0x5f, 0x5f, 0x61, 0x7a, } var code17 = []rune{ /* [:xdigit:] */ 0x30, 0x39, 0x41, 0x46, 0x61, 0x66, } var posixGroup = map[string]charGroup{ `[:alnum:]`: {+1, code4}, `[:^alnum:]`: {-1, code4}, `[:alpha:]`: {+1, code5}, `[:^alpha:]`: {-1, code5}, `[:ascii:]`: {+1, code6}, `[:^ascii:]`: {-1, code6}, `[:blank:]`: {+1, code7}, `[:^blank:]`: {-1, code7}, `[:cntrl:]`: {+1, code8}, `[:^cntrl:]`: {-1, code8}, `[:digit:]`: {+1, code9}, `[:^digit:]`: {-1, code9}, `[:graph:]`: {+1, code10}, `[:^graph:]`: {-1, code10}, `[:lower:]`: {+1, code11}, `[:^lower:]`: {-1, code11}, `[:print:]`: {+1, code12}, `[:^print:]`: {-1, code12}, `[:punct:]`: {+1, code13}, `[:^punct:]`: {-1, code13}, `[:space:]`: {+1, code14}, `[:^space:]`: {-1, code14}, `[:upper:]`: {+1, code15}, `[:^upper:]`: {-1, code15}, `[:word:]`: {+1, code16}, `[:^word:]`: {-1, code16}, `[:xdigit:]`: {+1, code17}, `[:^xdigit:]`: {-1, code17}, } binaryregexp-0.2.0/syntax/prog.go000066400000000000000000000167631347202265500170570ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package syntax import ( "bytes" "strconv" "unicode" ) // Compiled program. // May not belong in this package, but convenient for now. // A Prog is a compiled regular expression program. type Prog struct { Inst []Inst Start int // index of start instruction NumCap int // number of InstCapture insts in re } // An InstOp is an instruction opcode. type InstOp uint8 const ( InstAlt InstOp = iota InstAltMatch InstCapture InstEmptyWidth InstMatch InstFail InstNop InstRune InstRune1 InstRuneAny InstRuneAnyNotNL ) var instOpNames = []string{ "InstAlt", "InstAltMatch", "InstCapture", "InstEmptyWidth", "InstMatch", "InstFail", "InstNop", "InstRune", "InstRune1", "InstRuneAny", "InstRuneAnyNotNL", } func (i InstOp) String() string { if uint(i) >= uint(len(instOpNames)) { return "" } return instOpNames[i] } // An EmptyOp specifies a kind or mixture of zero-width assertions. type EmptyOp uint8 const ( EmptyBeginLine EmptyOp = 1 << iota EmptyEndLine EmptyBeginText EmptyEndText EmptyWordBoundary EmptyNoWordBoundary ) // EmptyOpContext returns the zero-width assertions // satisfied at the position between the runes r1 and r2. // Passing r1 == -1 indicates that the position is // at the beginning of the text. // Passing r2 == -1 indicates that the position is // at the end of the text. func EmptyOpContext(r1, r2 rune) EmptyOp { var op EmptyOp = EmptyNoWordBoundary var boundary byte switch { case IsWordChar(r1): boundary = 1 case r1 == '\n': op |= EmptyBeginLine case r1 < 0: op |= EmptyBeginText | EmptyBeginLine } switch { case IsWordChar(r2): boundary ^= 1 case r2 == '\n': op |= EmptyEndLine case r2 < 0: op |= EmptyEndText | EmptyEndLine } if boundary != 0 { // IsWordChar(r1) != IsWordChar(r2) op ^= (EmptyWordBoundary | EmptyNoWordBoundary) } return op } // IsWordChar reports whether r is consider a ``word character'' // during the evaluation of the \b and \B zero-width assertions. // These assertions are ASCII-only: the word characters are [A-Za-z0-9_]. func IsWordChar(r rune) bool { return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' || '0' <= r && r <= '9' || r == '_' } // An Inst is a single instruction in a regular expression program. type Inst struct { Op InstOp Out uint32 // all but InstMatch, InstFail Arg uint32 // InstAlt, InstAltMatch, InstCapture, InstEmptyWidth Rune []rune } func (p *Prog) String() string { var b bytes.Buffer dumpProg(&b, p) return b.String() } // skipNop follows any no-op or capturing instructions. func (p *Prog) skipNop(pc uint32) *Inst { i := &p.Inst[pc] for i.Op == InstNop || i.Op == InstCapture { i = &p.Inst[i.Out] } return i } // op returns i.Op but merges all the Rune special cases into InstRune func (i *Inst) op() InstOp { op := i.Op switch op { case InstRune1, InstRuneAny, InstRuneAnyNotNL: op = InstRune } return op } // Prefix returns a literal string that all matches for the // regexp must start with. Complete is true if the prefix // is the entire match. func (p *Prog) Prefix() (prefix string, complete bool) { i := p.skipNop(uint32(p.Start)) // Avoid allocation of buffer if prefix is empty. if i.op() != InstRune || len(i.Rune) != 1 { return "", i.Op == InstMatch } // Have prefix; gather characters. var buf bytes.Buffer for i.op() == InstRune && len(i.Rune) == 1 && i.Rune[0] <= 0xFF && Flags(i.Arg)&FoldCase == 0 { buf.WriteByte(byte(i.Rune[0])) i = p.skipNop(i.Out) } return buf.String(), i.Op == InstMatch } // StartCond returns the leading empty-width conditions that must // be true in any match. It returns ^EmptyOp(0) if no matches are possible. func (p *Prog) StartCond() EmptyOp { var flag EmptyOp pc := uint32(p.Start) i := &p.Inst[pc] Loop: for { switch i.Op { case InstEmptyWidth: flag |= EmptyOp(i.Arg) case InstFail: return ^EmptyOp(0) case InstCapture, InstNop: // skip default: break Loop } pc = i.Out i = &p.Inst[pc] } return flag } const noMatch = -1 // MatchRune reports whether the instruction matches (and consumes) r. // It should only be called when i.Op == InstRune. func (i *Inst) MatchRune(r rune) bool { return i.MatchRunePos(r) != noMatch } // MatchRunePos checks whether the instruction matches (and consumes) r. // If so, MatchRunePos returns the index of the matching rune pair // (or, when len(i.Rune) == 1, rune singleton). // If not, MatchRunePos returns -1. // MatchRunePos should only be called when i.Op == InstRune. func (i *Inst) MatchRunePos(r rune) int { rune := i.Rune switch len(rune) { case 0: return noMatch case 1: // Special case: single-rune slice is from literal string, not char class. r0 := rune[0] if r == r0 { return 0 } if Flags(i.Arg)&FoldCase != 0 { for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) { if r == r1 { return 0 } } } return noMatch case 2: if r >= rune[0] && r <= rune[1] { return 0 } return noMatch case 4, 6, 8: // Linear search for a few pairs. // Should handle ASCII well. for j := 0; j < len(rune); j += 2 { if r < rune[j] { return noMatch } if r <= rune[j+1] { return j / 2 } } return noMatch } // Otherwise binary search. lo := 0 hi := len(rune) / 2 for lo < hi { m := lo + (hi-lo)/2 if c := rune[2*m]; c <= r { if r <= rune[2*m+1] { return m } lo = m + 1 } else { hi = m } } return noMatch } // MatchEmptyWidth reports whether the instruction matches // an empty string between the runes before and after. // It should only be called when i.Op == InstEmptyWidth. func (i *Inst) MatchEmptyWidth(before rune, after rune) bool { switch EmptyOp(i.Arg) { case EmptyBeginLine: return before == '\n' || before == -1 case EmptyEndLine: return after == '\n' || after == -1 case EmptyBeginText: return before == -1 case EmptyEndText: return after == -1 case EmptyWordBoundary: return IsWordChar(before) != IsWordChar(after) case EmptyNoWordBoundary: return IsWordChar(before) == IsWordChar(after) } panic("unknown empty width arg") } func (i *Inst) String() string { var b bytes.Buffer dumpInst(&b, i) return b.String() } func bw(b *bytes.Buffer, args ...string) { for _, s := range args { b.WriteString(s) } } func dumpProg(b *bytes.Buffer, p *Prog) { for j := range p.Inst { i := &p.Inst[j] pc := strconv.Itoa(j) if len(pc) < 3 { b.WriteString(" "[len(pc):]) } if j == p.Start { pc += "*" } bw(b, pc, "\t") dumpInst(b, i) bw(b, "\n") } } func u32(i uint32) string { return strconv.FormatUint(uint64(i), 10) } func dumpInst(b *bytes.Buffer, i *Inst) { switch i.Op { case InstAlt: bw(b, "alt -> ", u32(i.Out), ", ", u32(i.Arg)) case InstAltMatch: bw(b, "altmatch -> ", u32(i.Out), ", ", u32(i.Arg)) case InstCapture: bw(b, "cap ", u32(i.Arg), " -> ", u32(i.Out)) case InstEmptyWidth: bw(b, "empty ", u32(i.Arg), " -> ", u32(i.Out)) case InstMatch: bw(b, "match") case InstFail: bw(b, "fail") case InstNop: bw(b, "nop -> ", u32(i.Out)) case InstRune: if i.Rune == nil { // shouldn't happen bw(b, "rune ") } bw(b, "rune ", strconv.QuoteToASCII(string(i.Rune))) if Flags(i.Arg)&FoldCase != 0 { bw(b, "/i") } bw(b, " -> ", u32(i.Out)) case InstRune1: bw(b, "rune1 ", strconv.QuoteToASCII(string(i.Rune)), " -> ", u32(i.Out)) case InstRuneAny: bw(b, "any -> ", u32(i.Out)) case InstRuneAnyNotNL: bw(b, "anynotnl -> ", u32(i.Out)) } } binaryregexp-0.2.0/syntax/prog_test.go000066400000000000000000000035201347202265500201010ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package syntax import "testing" var compileTests = []struct { Regexp string Prog string }{ {"a", ` 0 fail 1* rune1 "a" -> 2 2 match `}, {"[A-M][n-z]", ` 0 fail 1* rune "AM" -> 2 2 rune "nz" -> 3 3 match `}, {"", ` 0 fail 1* nop -> 2 2 match `}, {"a?", ` 0 fail 1 rune1 "a" -> 3 2* alt -> 1, 3 3 match `}, {"a??", ` 0 fail 1 rune1 "a" -> 3 2* alt -> 3, 1 3 match `}, {"a+", ` 0 fail 1* rune1 "a" -> 2 2 alt -> 1, 3 3 match `}, {"a+?", ` 0 fail 1* rune1 "a" -> 2 2 alt -> 3, 1 3 match `}, {"a*", ` 0 fail 1 rune1 "a" -> 2 2* alt -> 1, 3 3 match `}, {"a*?", ` 0 fail 1 rune1 "a" -> 2 2* alt -> 3, 1 3 match `}, {"a+b+", ` 0 fail 1* rune1 "a" -> 2 2 alt -> 1, 3 3 rune1 "b" -> 4 4 alt -> 3, 5 5 match `}, {"(a+)(b+)", ` 0 fail 1* cap 2 -> 2 2 rune1 "a" -> 3 3 alt -> 2, 4 4 cap 3 -> 5 5 cap 4 -> 6 6 rune1 "b" -> 7 7 alt -> 6, 8 8 cap 5 -> 9 9 match `}, {"a+|b+", ` 0 fail 1 rune1 "a" -> 2 2 alt -> 1, 6 3 rune1 "b" -> 4 4 alt -> 3, 6 5* alt -> 1, 3 6 match `}, {"A[Aa]", ` 0 fail 1* rune1 "A" -> 2 2 rune "A"/i -> 3 3 match `}, {"(?:(?:^).)", ` 0 fail 1* empty 4 -> 2 2 anynotnl -> 3 3 match `}, } func TestCompile(t *testing.T) { for _, tt := range compileTests { re, _ := Parse(tt.Regexp, Perl) p, _ := Compile(re) s := p.String() if s != tt.Prog { t.Errorf("compiled %#q:\n--- have\n%s---\n--- want\n%s---", tt.Regexp, s, tt.Prog) } } } func BenchmarkEmptyOpContext(b *testing.B) { for i := 0; i < b.N; i++ { var r1 rune = -1 for _, r2 := range "foo, bar, baz\nsome input text.\n" { EmptyOpContext(r1, r2) r1 = r2 } EmptyOpContext(r1, -1) } } binaryregexp-0.2.0/syntax/regexp.go000066400000000000000000000172321347202265500173720ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package syntax // Note to implementers: // In this package, re is always a *Regexp and r is always a rune. import ( "bytes" "strconv" "strings" "unicode" ) // A Regexp is a node in a regular expression syntax tree. type Regexp struct { Op Op // operator Flags Flags Sub []*Regexp // subexpressions, if any Sub0 [1]*Regexp // storage for short Sub Rune []rune // matched runes, for OpLiteral, OpCharClass Rune0 [2]rune // storage for short Rune Min, Max int // min, max for OpRepeat Cap int // capturing index, for OpCapture Name string // capturing name, for OpCapture } //go:generate stringer -type Op -trimprefix Op // An Op is a single regular expression operator. type Op uint8 // Operators are listed in precedence order, tightest binding to weakest. // Character class operators are listed simplest to most complex // (OpLiteral, OpCharClass, OpAnyCharNotNL, OpAnyChar). const ( OpNoMatch Op = 1 + iota // matches no strings OpEmptyMatch // matches empty string OpLiteral // matches Runes sequence OpCharClass // matches Runes interpreted as range pair list OpAnyCharNotNL // matches any character except newline OpAnyChar // matches any character OpBeginLine // matches empty string at beginning of line OpEndLine // matches empty string at end of line OpBeginText // matches empty string at beginning of text OpEndText // matches empty string at end of text OpWordBoundary // matches word boundary `\b` OpNoWordBoundary // matches word non-boundary `\B` OpCapture // capturing subexpression with index Cap, optional name Name OpStar // matches Sub[0] zero or more times OpPlus // matches Sub[0] one or more times OpQuest // matches Sub[0] zero or one times OpRepeat // matches Sub[0] at least Min times, at most Max (Max == -1 is no limit) OpConcat // matches concatenation of Subs OpAlternate // matches alternation of Subs ) const opPseudo Op = 128 // where pseudo-ops start // Equal reports whether x and y have identical structure. func (x *Regexp) Equal(y *Regexp) bool { if x == nil || y == nil { return x == y } if x.Op != y.Op { return false } switch x.Op { case OpEndText: // The parse flags remember whether this is \z or \Z. if x.Flags&WasDollar != y.Flags&WasDollar { return false } case OpLiteral, OpCharClass: if len(x.Rune) != len(y.Rune) { return false } for i, r := range x.Rune { if r != y.Rune[i] { return false } } case OpAlternate, OpConcat: if len(x.Sub) != len(y.Sub) { return false } for i, sub := range x.Sub { if !sub.Equal(y.Sub[i]) { return false } } case OpStar, OpPlus, OpQuest: if x.Flags&NonGreedy != y.Flags&NonGreedy || !x.Sub[0].Equal(y.Sub[0]) { return false } case OpRepeat: if x.Flags&NonGreedy != y.Flags&NonGreedy || x.Min != y.Min || x.Max != y.Max || !x.Sub[0].Equal(y.Sub[0]) { return false } case OpCapture: if x.Cap != y.Cap || x.Name != y.Name || !x.Sub[0].Equal(y.Sub[0]) { return false } } return true } // writeRegexp writes the Perl syntax for the regular expression re to b. func writeRegexp(b *bytes.Buffer, re *Regexp) { switch re.Op { default: b.WriteString("") case OpNoMatch: b.WriteString(`[^\x00-\x{10FFFF}]`) case OpEmptyMatch: b.WriteString(`(?:)`) case OpLiteral: if re.Flags&FoldCase != 0 { b.WriteString(`(?i:`) } for _, r := range re.Rune { escape(b, r, false) } if re.Flags&FoldCase != 0 { b.WriteString(`)`) } case OpCharClass: if len(re.Rune)%2 != 0 { b.WriteString(`[invalid char class]`) break } b.WriteRune('[') if len(re.Rune) == 0 { b.WriteString(`^\x00-\x{10FFFF}`) } else if re.Rune[0] == 0 && re.Rune[len(re.Rune)-1] == unicode.MaxRune { // Contains 0 and MaxRune. Probably a negated class. // Print the gaps. b.WriteRune('^') for i := 1; i < len(re.Rune)-1; i += 2 { lo, hi := re.Rune[i]+1, re.Rune[i+1]-1 escape(b, lo, lo == '-') if lo != hi { b.WriteRune('-') escape(b, hi, hi == '-') } } } else { for i := 0; i < len(re.Rune); i += 2 { lo, hi := re.Rune[i], re.Rune[i+1] escape(b, lo, lo == '-') if lo != hi { b.WriteRune('-') escape(b, hi, hi == '-') } } } b.WriteRune(']') case OpAnyCharNotNL: b.WriteString(`(?-s:.)`) case OpAnyChar: b.WriteString(`(?s:.)`) case OpBeginLine: b.WriteString(`(?m:^)`) case OpEndLine: b.WriteString(`(?m:$)`) case OpBeginText: b.WriteString(`\A`) case OpEndText: if re.Flags&WasDollar != 0 { b.WriteString(`(?-m:$)`) } else { b.WriteString(`\z`) } case OpWordBoundary: b.WriteString(`\b`) case OpNoWordBoundary: b.WriteString(`\B`) case OpCapture: if re.Name != "" { b.WriteString(`(?P<`) b.WriteString(re.Name) b.WriteRune('>') } else { b.WriteRune('(') } if re.Sub[0].Op != OpEmptyMatch { writeRegexp(b, re.Sub[0]) } b.WriteRune(')') case OpStar, OpPlus, OpQuest, OpRepeat: if sub := re.Sub[0]; sub.Op > OpCapture || sub.Op == OpLiteral && len(sub.Rune) > 1 { b.WriteString(`(?:`) writeRegexp(b, sub) b.WriteString(`)`) } else { writeRegexp(b, sub) } switch re.Op { case OpStar: b.WriteRune('*') case OpPlus: b.WriteRune('+') case OpQuest: b.WriteRune('?') case OpRepeat: b.WriteRune('{') b.WriteString(strconv.Itoa(re.Min)) if re.Max != re.Min { b.WriteRune(',') if re.Max >= 0 { b.WriteString(strconv.Itoa(re.Max)) } } b.WriteRune('}') } if re.Flags&NonGreedy != 0 { b.WriteRune('?') } case OpConcat: for _, sub := range re.Sub { if sub.Op == OpAlternate { b.WriteString(`(?:`) writeRegexp(b, sub) b.WriteString(`)`) } else { writeRegexp(b, sub) } } case OpAlternate: for i, sub := range re.Sub { if i > 0 { b.WriteRune('|') } writeRegexp(b, sub) } } } func (re *Regexp) String() string { var b bytes.Buffer writeRegexp(&b, re) return b.String() } const meta = `\.+*?()|[]{}^$` func escape(b *bytes.Buffer, r rune, force bool) { if unicode.IsPrint(r) { if strings.ContainsRune(meta, r) || force { b.WriteRune('\\') } b.WriteRune(r) return } switch r { case '\a': b.WriteString(`\a`) case '\f': b.WriteString(`\f`) case '\n': b.WriteString(`\n`) case '\r': b.WriteString(`\r`) case '\t': b.WriteString(`\t`) case '\v': b.WriteString(`\v`) default: if r < 0x100 { b.WriteString(`\x`) s := strconv.FormatInt(int64(r), 16) if len(s) == 1 { b.WriteRune('0') } b.WriteString(s) break } b.WriteString(`\x{`) b.WriteString(strconv.FormatInt(int64(r), 16)) b.WriteString(`}`) } } // MaxCap walks the regexp to find the maximum capture index. func (re *Regexp) MaxCap() int { m := 0 if re.Op == OpCapture { m = re.Cap } for _, sub := range re.Sub { if n := sub.MaxCap(); m < n { m = n } } return m } // CapNames walks the regexp to find the names of capturing groups. func (re *Regexp) CapNames() []string { names := make([]string, re.MaxCap()+1) re.capNames(names) return names } func (re *Regexp) capNames(names []string) { if re.Op == OpCapture { names[re.Cap] = re.Name } for _, sub := range re.Sub { sub.capNames(names) } } binaryregexp-0.2.0/syntax/simplify.go000066400000000000000000000103131347202265500177250ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package syntax // Simplify returns a regexp equivalent to re but without counted repetitions // and with various other simplifications, such as rewriting /(?:a+)+/ to /a+/. // The resulting regexp will execute correctly but its string representation // will not produce the same parse tree, because capturing parentheses // may have been duplicated or removed. For example, the simplified form // for /(x){1,2}/ is /(x)(x)?/ but both parentheses capture as $1. // The returned regexp may share structure with or be the original. func (re *Regexp) Simplify() *Regexp { if re == nil { return nil } switch re.Op { case OpCapture, OpConcat, OpAlternate: // Simplify children, building new Regexp if children change. nre := re for i, sub := range re.Sub { nsub := sub.Simplify() if nre == re && nsub != sub { // Start a copy. nre = new(Regexp) *nre = *re nre.Rune = nil nre.Sub = append(nre.Sub0[:0], re.Sub[:i]...) } if nre != re { nre.Sub = append(nre.Sub, nsub) } } return nre case OpStar, OpPlus, OpQuest: sub := re.Sub[0].Simplify() return simplify1(re.Op, re.Flags, sub, re) case OpRepeat: // Special special case: x{0} matches the empty string // and doesn't even need to consider x. if re.Min == 0 && re.Max == 0 { return &Regexp{Op: OpEmptyMatch} } // The fun begins. sub := re.Sub[0].Simplify() // x{n,} means at least n matches of x. if re.Max == -1 { // Special case: x{0,} is x*. if re.Min == 0 { return simplify1(OpStar, re.Flags, sub, nil) } // Special case: x{1,} is x+. if re.Min == 1 { return simplify1(OpPlus, re.Flags, sub, nil) } // General case: x{4,} is xxxx+. nre := &Regexp{Op: OpConcat} nre.Sub = nre.Sub0[:0] for i := 0; i < re.Min-1; i++ { nre.Sub = append(nre.Sub, sub) } nre.Sub = append(nre.Sub, simplify1(OpPlus, re.Flags, sub, nil)) return nre } // Special case x{0} handled above. // Special case: x{1} is just x. if re.Min == 1 && re.Max == 1 { return sub } // General case: x{n,m} means n copies of x and m copies of x? // The machine will do less work if we nest the final m copies, // so that x{2,5} = xx(x(x(x)?)?)? // Build leading prefix: xx. var prefix *Regexp if re.Min > 0 { prefix = &Regexp{Op: OpConcat} prefix.Sub = prefix.Sub0[:0] for i := 0; i < re.Min; i++ { prefix.Sub = append(prefix.Sub, sub) } } // Build and attach suffix: (x(x(x)?)?)? if re.Max > re.Min { suffix := simplify1(OpQuest, re.Flags, sub, nil) for i := re.Min + 1; i < re.Max; i++ { nre2 := &Regexp{Op: OpConcat} nre2.Sub = append(nre2.Sub0[:0], sub, suffix) suffix = simplify1(OpQuest, re.Flags, nre2, nil) } if prefix == nil { return suffix } prefix.Sub = append(prefix.Sub, suffix) } if prefix != nil { return prefix } // Some degenerate case like min > max or min < max < 0. // Handle as impossible match. return &Regexp{Op: OpNoMatch} } return re } // simplify1 implements Simplify for the unary OpStar, // OpPlus, and OpQuest operators. It returns the simple regexp // equivalent to // // Regexp{Op: op, Flags: flags, Sub: {sub}} // // under the assumption that sub is already simple, and // without first allocating that structure. If the regexp // to be returned turns out to be equivalent to re, simplify1 // returns re instead. // // simplify1 is factored out of Simplify because the implementation // for other operators generates these unary expressions. // Letting them call simplify1 makes sure the expressions they // generate are simple. func simplify1(op Op, flags Flags, sub, re *Regexp) *Regexp { // Special case: repeat the empty string as much as // you want, but it's still the empty string. if sub.Op == OpEmptyMatch { return sub } // The operators are idempotent if the flags match. if op == sub.Op && flags&NonGreedy == sub.Flags&NonGreedy { return sub } if re != nil && re.Op == op && re.Flags&NonGreedy == flags&NonGreedy && sub == re.Sub[0] { return re } re = &Regexp{Op: op, Flags: flags} re.Sub = append(re.Sub0[:0], sub) return re } binaryregexp-0.2.0/syntax/simplify_test.go000066400000000000000000000100111347202265500207570ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package syntax import "testing" var simplifyTests = []struct { Regexp string Simple string }{ // Already-simple constructs {`a`, `a`}, {`ab`, `ab`}, {`a|b`, `[a-b]`}, {`ab|cd`, `ab|cd`}, {`(ab)*`, `(ab)*`}, {`(ab)+`, `(ab)+`}, {`(ab)?`, `(ab)?`}, {`.`, `(?s:.)`}, {`^`, `(?m:^)`}, {`$`, `(?m:$)`}, {`[ac]`, `[ac]`}, {`[^ac]`, `[^ac]`}, // Posix character classes {`[[:alnum:]]`, `[0-9A-Za-z]`}, {`[[:alpha:]]`, `[A-Za-z]`}, {`[[:blank:]]`, `[\t ]`}, {`[[:cntrl:]]`, `[\x00-\x1f\x7f]`}, {`[[:digit:]]`, `[0-9]`}, {`[[:graph:]]`, `[!-~]`}, {`[[:lower:]]`, `[a-z]`}, {`[[:print:]]`, `[ -~]`}, {`[[:punct:]]`, "[!-/:-@\\[-`\\{-~]"}, {`[[:space:]]`, `[\t-\r ]`}, {`[[:upper:]]`, `[A-Z]`}, {`[[:xdigit:]]`, `[0-9A-Fa-f]`}, // Perl character classes {`\d`, `[0-9]`}, {`\s`, `[\t-\n\f-\r ]`}, {`\w`, `[0-9A-Z_a-z]`}, {`\D`, `[^0-9]`}, {`\S`, `[^\t-\n\f-\r ]`}, {`\W`, `[^0-9A-Z_a-z]`}, {`[\d]`, `[0-9]`}, {`[\s]`, `[\t-\n\f-\r ]`}, {`[\w]`, `[0-9A-Z_a-z]`}, {`[\D]`, `[^0-9]`}, {`[\S]`, `[^\t-\n\f-\r ]`}, {`[\W]`, `[^0-9A-Z_a-z]`}, // Posix repetitions {`a{1}`, `a`}, {`a{2}`, `aa`}, {`a{5}`, `aaaaa`}, {`a{0,1}`, `a?`}, // The next three are illegible because Simplify inserts (?:) // parens instead of () parens to avoid creating extra // captured subexpressions. The comments show a version with fewer parens. {`(a){0,2}`, `(?:(a)(a)?)?`}, // (aa?)? {`(a){0,4}`, `(?:(a)(?:(a)(?:(a)(a)?)?)?)?`}, // (a(a(aa?)?)?)? {`(a){2,6}`, `(a)(a)(?:(a)(?:(a)(?:(a)(a)?)?)?)?`}, // aa(a(a(aa?)?)?)? {`a{0,2}`, `(?:aa?)?`}, // (aa?)? {`a{0,4}`, `(?:a(?:a(?:aa?)?)?)?`}, // (a(a(aa?)?)?)? {`a{2,6}`, `aa(?:a(?:a(?:aa?)?)?)?`}, // aa(a(a(aa?)?)?)? {`a{0,}`, `a*`}, {`a{1,}`, `a+`}, {`a{2,}`, `aa+`}, {`a{5,}`, `aaaaa+`}, // Test that operators simplify their arguments. {`(?:a{1,}){1,}`, `a+`}, {`(a{1,}b{1,})`, `(a+b+)`}, {`a{1,}|b{1,}`, `a+|b+`}, {`(?:a{1,})*`, `(?:a+)*`}, {`(?:a{1,})+`, `a+`}, {`(?:a{1,})?`, `(?:a+)?`}, {``, `(?:)`}, {`a{0}`, `(?:)`}, // Character class simplification {`[ab]`, `[a-b]`}, {`[a-za-za-z]`, `[a-z]`}, {`[A-Za-zA-Za-z]`, `[A-Za-z]`}, {`[ABCDEFGH]`, `[A-H]`}, {`[AB-CD-EF-GH]`, `[A-H]`}, {`[W-ZP-XE-R]`, `[E-Z]`}, {`[a-ee-gg-m]`, `[a-m]`}, {`[a-ea-ha-m]`, `[a-m]`}, {`[a-ma-ha-e]`, `[a-m]`}, {`[a-zA-Z0-9 -~]`, `[ -~]`}, // Empty character classes {`[^[:cntrl:][:^cntrl:]]`, `[^\x00-\x{10FFFF}]`}, // Full character classes {`[[:cntrl:][:^cntrl:]]`, `(?s:.)`}, // Unicode case folding. {`(?i)A`, `(?i:A)`}, {`(?i)a`, `(?i:A)`}, {`(?i)[A]`, `(?i:A)`}, {`(?i)[a]`, `(?i:A)`}, {`(?i)K`, `(?i:K)`}, {`(?i)k`, `(?i:K)`}, {`(?i)\x{212a}`, "(?i:K)"}, {`(?i)[K]`, "[Kk\u212A]"}, {`(?i)[k]`, "[Kk\u212A]"}, {`(?i)[\x{212a}]`, "[Kk\u212A]"}, {`(?i)[a-z]`, "[A-Za-z\u017F\u212A]"}, {`(?i)[\x00-\x{FFFD}]`, "[\\x00-\uFFFD]"}, {`(?i)[\x00-\x{10FFFF}]`, `(?s:.)`}, // Empty string as a regular expression. // The empty string must be preserved inside parens in order // to make submatches work right, so these tests are less // interesting than they might otherwise be. String inserts // explicit (?:) in place of non-parenthesized empty strings, // to make them easier to spot for other parsers. {`(a|b|)`, `([a-b]|(?:))`}, {`(|)`, `()`}, {`a()`, `a()`}, {`(()|())`, `(()|())`}, {`(a|)`, `(a|(?:))`}, {`ab()cd()`, `ab()cd()`}, {`()`, `()`}, {`()*`, `()*`}, {`()+`, `()+`}, {`()?`, `()?`}, {`(){0}`, `(?:)`}, {`(){1}`, `()`}, {`(){1,}`, `()+`}, {`(){0,2}`, `(?:()()?)?`}, } func TestSimplify(t *testing.T) { for _, tt := range simplifyTests { re, err := Parse(tt.Regexp, MatchNL|Perl&^OneLine) if err != nil { t.Errorf("Parse(%#q) = error %v", tt.Regexp, err) continue } s := re.Simplify().String() if s != tt.Simple { t.Errorf("Simplify(%#q) = %#q, want %#q", tt.Regexp, s, tt.Simple) } } } binaryregexp-0.2.0/testdata/000077500000000000000000000000001347202265500160275ustar00rootroot00000000000000binaryregexp-0.2.0/testdata/README000066400000000000000000000016751347202265500167200ustar00rootroot00000000000000AT&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 https://github.com/google/re2/ The exhaustive file is compressed because it is huge. binaryregexp-0.2.0/testdata/basic.dat000066400000000000000000000210341347202265500176020ustar00rootroot00000000000000NOTE 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) [[]] 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[-]?c ac (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) binaryregexp-0.2.0/testdata/nullsubexpr.dat000066400000000000000000000040461347202265500211100ustar00rootroot00000000000000NOTE 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) binaryregexp-0.2.0/testdata/re2-exhaustive.txt.bz2000066400000000000000000014014401347202265500221430ustar00rootroot00000000000000BZh91AY&SYȂ;_\{xx:`cP: *Ge q٠eU[j mUl3H&5MT*VuܠLNpLkVkZ$f K2֯V 28T}BT>mh2cCV%PkÀ^ڢ%B;cv"y̒DTh )RJ4h@U" #i%HCL&P )$=O#A@*jIJ?B# RFAB# 󒖆FAB#%- .(P(D`B# P(DiPIKBvW{jaS TeޭEGJ[ࢼwjv0ۻWC T¦/^}GJ[ࢼ+ۻWEy=z 2k5! ٣!V|<]sFh\Ýhѫ9W4sFi>hѢ<8&m'c18c5sGwׇ9W4sFh\{kW4s Ij@מFh\ͤUUx>hѫ}]޻^xW4p ?XVQQXVEeD(Pj"ڊ!(-DhڊmFmEbcbj*6(6j6(,U6ъ* Ѫ4jEPl (6 ch6(fXfTllUEbEDTEDklhlUE b+(QBFmFŵhգcFѪ4jEAFE&ͤ&[CjhlBhkFmKbC4mŊ*ŭ[FƪFcFlڋV6jSmZY[ 2YVMXmbjX5 (mFPͷAFj܄dU\.NKbC4QŊ*ŭ[FմQѶ4Ecbi)*ՍLFie1[4jZ+Z(5cmZMXlj4°B՘j [Vm666=ܖR$iFރt{J0JN;%oV EFYDN$qGVV%DK&XVj2*$b*$(ڶm5-FղAYm6U62L(PlڶaIoJ9wU6 \컕Jjj2TKmJ3 jl&-BM%--,ICd YBdsuҍ9)[c%Dd lLS5Ul m){w˝;uwfmsitpM&`e۪LeK2o/ի~8ܦUY ""ն%H&$I  N [l8dCrW)N`ͩU?*߄lRk66D"!&VeLom~6u-$rw# ۵щ3Nud6l' Cio"0_~S^m6l----2z RW\mP TimmLVеh.ZsVȍ"& ls,"@+:M&RI$79dY&MVShSԝ Ja[0rjMkW#h?8ߒlUm 2, IDYlđM4Ȉrin[Imb*u @m'&YԢ,TvTֶbLP[Mg$ӡ-:,7#O"9i\M#xxG1YRyG+ÊVjLa<ۘc޾| >sobK6͜LBm&עcyO$f%79TZt89}w &BM&I9s trp"L7)X騦NK2snM,!;'xavBjilfӚ۶s==̒`+qsGĝݛ)kEV-:KYDرDU ᴂǩ6DN-l2ksmӫsiWqzW:Ev6MLǝws5ۼ]ymm)lɜvr=fJXf֝f;n5d{^#j1c5cJMEme_YmmP 0.ĵX54lɪ#+5mv 5j ۪cFmD$$IŗSJLbf;d"7BDڒCmBlwm[mS ,YUbYV+X5j6ōQ&A)NQrL[mqݼNnWj5 5jTXh5r,mJSZNtһKcfʜNrbN\'jӹ:ȶ91DF۪NXZ̬8ݎ^GV񜓳i.4%X$F;7=Ŭ67't]TٶMEMdkZ6)$FhəSF, =PKRmHնۀ鲕8λt9kd;9rC bq.* qWՏ|oJ^[1in[:.wKJ7+:FR%jDd%i+t+Lnni\ )4lS&V@d &Ubq̓h[NV1ζ+9fi+ebbL}|g$9%Qc^;uj̶ MmS2(ݷRbZ##<<3ofqb[$̩lH5kZfȈDÎyObQn]uYw{!j\z咡M r]O{Gz=W̆Y :I3 03 03 03 03 03 03 03 0lYSY I4@I$mfҔ 6lI$ $M6lJP$$HD"""4diDX$H2XִjkT״]lL͢KSmZN+FBLM)RFD"Hk &BUQ B [*~3'Ib"""""""""  DD#bDA"""""""""" A1bDDA"1 D1bDDA"1 DD#/c1cuc1cu1c7]v1c1]c1cuc1cu1c7]v1c1܌Av1c1]c1cuc1cu1c7\Db"" A1F"" v1c1]c1cuc1cu1c7]v1c1]c1cuc1cu1c7r1"""""""""""""""""""""%1c7]v1c1]c1cuc1cȈD[[[[skkyI(BIBJP$!$ %I(BIBJW1c1c1c1c1c1c m ܛmԥ)[HB[HB{{m;wormR`Mz}U1c1c1c1c1c1^^}ormR;6۩JS{&u)Jv{z~1c1c1c1c1c1/////|C k k k k k k kz뮯Uo1c1c1c1c1cTW a!瀾W֨)-+ڵGGGGGGGGD]tEGGGGGGGGD]tEsj3M7[)O}׾K[;[;>j/?]T`_9"t E*@/ӹ3 ܉a~˛I카aU4qN7lt]ֿm?E'1~yI$u]<;awϿ~( )4`"Z֬KkUM]n|~~uu$\{}E}{ 6ʗw;]cS7IJ6.ѤD)fѤf5I~>#\MFL&x&Yly!@gn`;mn3706šP< oN`^Sq',zw-mjKrU-UQ=┥)JR(PJR)B JRsk[x\TfdI-_ƫ- myi!C8;'N\Ӥdd @@;[]@32+ UmVO],lKl-WUml,N NjtƧ@ Nwj[p3zP9ћֱaBq٘MmT; sjrnX0!3cBnͶڪ^68z]ס׷mmPMoZݨ&7c٘fvMmT; sjrnX0!3cBnͶڪP @g6aBg9ݵmT9P7Yͪʁmcs1! k'6nKƫ5 xu^/J-bju؁ګ]cżv f`[ZxRU[ŽWtª-rٰYk[Ŷw r@0ko:&%#gUw;!E8od2q2 ,m;;=g({Mqvdm6\l)˕q;ufۂfۘ,BB$+Ibܚ[s]@uW5e)JR(  H H0LѶRS@EZj `eZ!djV2$"Zc F$ j2hѫ5Y-Ɇ+#(m&Mb4Z()!&k2̭#RMhR2b ֵjje F)a6تVʌU*ڍ2R3l&k%%,B SiLU36fC4&"+3Zc3􉄱hl6tpErQlEͨI&9GXK;lrgle$i;#[!f[LL;9]j4h3uݵuu3,MkV&[XJur;dF ɩM]fcw̪Uͩf;6g9D'#.Dol4:L4=n  ׹sJt:qsERX+FERhj1fk,-I[)hR[ 0lZQF6ҚKcjŴU2mba&SVvMVfD؉6U7vm P\X+V*b&mݺJcv6Q؍mtn'ʕmd[Fԧ5hAMRAL,l۬siYۮu,hÃ+cZ8$]qYaSm07]nr­ͷ`廸e56fZIj&*\ێt_Vew~]{~]zd;r<<>-bBIc>z6w1b1 ۫W]!(BIBJ!$ %I(BIpBk-P$UO?`IW"5`e! J %a(ª#R>$%JBAđIx s IO$JJ**4H 4KaLa F&Ɖ"bL2m63[mUS32 Ń̓l25Y2ʹ[-VXKSJRllfRl(%eVͪXd mJ$fX"ТO> %c1aXČaSc43 M bLU`TId3 ZbV4bI,Jd6jb4S -ffY$a4D!6$f5j 13RL`Z,K)d55-)ZLƶSKF՘c[kTȚ"Z,LeVUJFKfId-if6ͣHXơP%QHUU#-D`6mZVXf`#BɫMeBilmiFFj5f,[!!LIR&а#4V0mQM-4-IȵT2PlFUbFRmlLmb 54cc%jXژV+lVcA LeIKRRDRa-X`XDbm֑Q*}}~{|ό"[ '㗺/-dmJJY@$mm63U'?}z.P59zә-8mR)JRB$TETETE HRUI]{pd<_Wx[濜;/:N秴z>j=AWWUx{O[nM b)LpCevvUu$!$BJP$&MP+~` p^;?㻎'ipwpd<_^@!oϚC}2EIz*w{l{ȧaʠ*=pGknc)JcJcmmBII(BIBP$!$!Bl$$!'`'m6w a$Ã!线x_9Lyw<ۻmq"*Oimiۺ1JR[n wuP 8!$ %I(BIpB#eI+«Nz;zv۵Wnk/z|>/L/<=~Mmm $ @]IͶH 9$l @$ @$ A H H L/A?p56pD#tɠܶ-۲/4'(qSmKA)JRWz{@$ @$ @ N2m=Vqo^ [m6HR޽z܏yw@$ @$ "&8Dkm FiT"(p5Vu) RT[XEQ$ @$ `$ dMek%H ~@Qb GPJ _a fllRPeXIdY2ZS6LۭT)]ebXVAm;ȶh'# >DbBMabBʆjmE);wH$ 4$Gjo$ TOT*%= Ih%Oz)b0$$OFMI%TbzF$g;x(DqlI%- I)hRIKBD(KBG GhFZRФ$/FyGKGKڹq3ujRTov˓nwt;]cX9qU({W.&r.ǚm!L6jܹwN9u]cnEEdXDY+)ZR]u'מR^h\RpR6U+i8UZ<מֺ-5a$ #VUi%뻮U#i8UZU+i8UZUK I<ѫ9W4F* IŁ#i"zzp{c5sO[:Ws޻=yPPQ4@Fl@ IlTMEh$j6KQ* &hTъ*,SFQ,V2҂ X SJYbTkIj,M$QQ&ƣQ,QQ&ƫ%&ּNNe\컔reܢS Q,2TI)*+1cAKf!!Um-YJ%,M79˄N\u\ʹ1CjlĀ 3RfPU[R YlRiVhkdaQTũSbQhA6dŴb6dѴ,X,XcS"5E 4hF-j1hEVh d-y ` d Є ѣ!F6i!#fYU$H̲V`)Rf8Y f[p!SMqkaWUfzUIb xLlBf!3o{)Y<5,4aa{J Iȸij^ɰ<چ}lޤZmMڵfo14eL2Iw&ܩm5æV6SKD$ch46m\oD %$ %$$$$$/*9s \mYF>ٸm-Zm6]%u0 %NmEs *Tͨњ;[jI6H*$Fd 4d33$Ljp-l[mmSVfۯMЄmm7 m0LǦ-ymwq!cTffm#h m!y NH6ȌQ*aU|^æfc49t2Hޛg욓PESh8|*J6Mm|iS019R<d4Ru,lm^=eڎ5' qyz6K5M[Clԕb=k(ԐbJ$ 7ejl42Tꬷe\c(컗42Kt¶A!;#{ԵuӚ,wZո"ۄddmZsm/.܃ ZWYIc,d$P mَnQfP66Sj4Ͳ[]؍(m%I" 8iNk#˜F5rض6~ADc&K%@( )I)P!jDMn#LF!2KV$R EÚ:ۛwNqaTRqڅk[#nͱ:u5FhHk3Z[QWNtGj Mm5[95i2k[K+ʊJ-@nm[-Rv؊b]=[TJ]6SHKm%$lvgj)TUyƫ*;T;WY4Ӛ)̦ JK)fZj-uXTkRki5ڭd:m+]+A*1+=yN,;N33z >!ismMGBm:d#n11)66.AklsBfP4 lIke-YcƬS@Zi|w.p6.dcV*Ѫ#\ص* m]v|3Nu\w`u[Un Vmp J{V!}56t͍{xT{gTNe[i6{ksp6nesmy6 ǒxYFYǭC*{[Qu6,VK^K*N)Nbثs%g]]WtFX1&aJ;kIsz] :QJ1[6u&ohOv)X围{ET=4UMIdZe"@PDQDQlԶbm v6t 5sc3EeXŻ2nvqQvB֎Qи]qk+iZ7]r6L YsKZۢm;UIN{{S*4HȒ$ mmmb*AYK%VIγfwIۢ'bڶCU+nW62V54)MJCZ%lm"Mm2UQKE0QaV6)$0ka1+4+,HL# vCiU֥9&5e MLEHf~ՍIPZa"# KfeV5ks+l6%fhQN.fmb@42ZuCm%Q@Ų(IE"2h+(Tm 4hшblj b5Ƣ*iDDdKe&M $Hi T\. -Ujի`ߑ&DșƆM3**TMUt3iav;eq.3cb4]sTh9[ e%̖[lP֔)98IÑ{N8됱 :1wɶCsòkK.1mڃPfimh,+dѵS:;rx]F˛ CmeagnwI;S i6kMءYi4cA%/1"D8nX[[4nnj κ]tH+1Bҳ]wq ܆mB6meprkus;uqźq&LDdɑ[%f6w8촹ÂUV݇[s ut;V(-ϽŷZZDfPQ7m46n7&IJVīZƻeՊ0Z(g`hִ3sӈzN"毻\R_-~vƞvڿD9>t1m@5ϟ-`H?xmmp.|cb@hu]zzmx-!puXgʑ _ʙ K߿~>x?wSGqtED_}Q _dk ig{LOzq6<~Mn1~OW2SO|xwmU_wUUU2eƽ>?.%~{ʪ?~|࿗|r\Wr>|>?9?]G2R- rVKǏyӧX3\t9 xN~>81}5%1?ttg~ ߾JȽ,~>x?O;Bpw{{ǫx>);=qmʀqr'{Vnӹճ1HwwpZOO >- ۻt;cvR 3D{W^; Ho{T'޲:*UU^,%mycn]m`m.󍱶/xGZy@7i=y=}O(uUB3cy ۭY`λ;8omvwqw:_T[\ T-[ug/ ;,UYӧ^m'A@C@ m(_I)6mNbTq"ĒHI! Klb$)$!I! I!x#~~s&Wim9N"GP&mJR=z׮W@$ @$ @l*UA@~Fc$cS#UE0DeQj4ZڕU3"3Kj&VY*hK[26fm4IJ&-"3YmBڵXXC% SX6QKJmm66ȚeJͤ)%A26ZEf529 qgia"mBMl0S$1,S+d,[$$0ST*a㙝;Uw.$D&mMѨil )cidUiIIUٹ7csHn531!'Tb*D̩.iSfjTt\39uG.*\mw^]8WNӅuݴm!\rf䮒]J;l.tG"a:,㢲tRi( %,LEكQQkVTĉ :ɴejT:lڋRѕj#3]FQ )6R؛Űj9avtZH5[fV;E6& Vndp+)53V6;ghllm,4SiΝLft'5VƳ Vkwpxv5%6ؕJѧ/*ڭQtw;ȳ),TStmM"59Jؼݴdhm3.cf4˴wj幵JudR˩:6m'juYAlfM-ImpBei78ᥲگw.K5fdcR۫l$rXUbu:l{7c1I]Y[rΓ[EWg]rUSZWګ HQBZKSuJJJZ'Q*I_TR 0R@JE, ĔJjbVUXLU'}U3.wr{탊r}15FǶbMRS=뻶 v!Ri{n(BIBJ!$ %I(BIpBk-P$*sㄔ}TJ`(M`DP 2PȤR*QPҪjB0LJURP?AJkj̲L` 5RS4H̐Xbm1$IlM%2I2dVkUɑ)1`)|cKKeV5iU%6V>0JUQ4@ȆdB&,b0V b0,4$dJ| Uқ+hI ZĘTL[ei2m!db5HXPă&f3TeRՁQ2&efYjPKVM,66͑["2ڢkfZmk",Bd+!A285 1P>U#X6lZ2Ų6 SZ`U#$4l2fibfhYZY"*bBRYM)3J!6*5ZfֲXZXUK*FUlm4K dZ4I$M$25fY&eLX@ZڠVlaMBkZ,EWG>||q3.:Uj/^L־s{r}7?J7=TUj ]ݵJB1ݲ[w}n %I(BJP$!!(BIBJ/9]VL*5fsdNmp"Qࢯr ImiJB7wm$mWBI$!"IBJ$!$ %FF.:խx& L X"$ @$ @ H H $ ~=ghlpD#txh֊t[qE:k0QN*[cm Rm"*H H *tTMtE85[l!Beڪ @$ `H[N/w㥲klԄ! RZ[j"" H0$ _dMfry?0~@Qb qFF1At jХ#ecmJ@4JDDJBAEJ! (@T=:  Rs7Imm hi|{{AP ^s}V03on7IH%ORa4L$5*j6@d=ꢪ$QCj0G&MRmMAMI%T@@3m..W...=EKCRZ8y\ܣy\jk-nڎrϻޛ>ܣ=Tîmؠ99- Khj^;dXf@9·^-6@jHm_sҼ<95sGsҼ<95sG4jhJ>hѫ>J>Ҽ<95sGsҼ<95sG4jhJ>hѫ>J>hsF^x5sGy^xUo5}_wJ>hѫ>J pGbك7 lV6UM-6[JmE[JmiMj 3PO\PQƥf:V͊PR%1a6ڰ՛.3cfjjL6LmRM))Um%66666^df,k%Q.2BHdBAܣ\z7Cҍ2S7C{̣SbFѬ["aFʹmEF6j61\5F/JyHT=7Bíz%' r^\-mF9zW/ b)w\K ^ͯ r&IZUؒpjp7߄7M2p㛑g8DMM4LM3fDD&M6i 6&"z]Kw0 T5*,j4TXhBb,)(PtIjKk6IhsrMEQE&h[:ԥ8u&U lQMEF_3$AH d4U*!n ` $q7&mrm̭[`lZ=9$q8=R- :YKmJj**cIa6&F@UxۺUA""im mAX-RmlK+)lq1iilZ&؈qLS0MebH!j8lnMV"filc1Qc1bc1cc1cc1c(1c1F1c11c1Qc1bc1cc1cc1c1c(1c1F1c11Q1Qc1bc1cc1cc1c1c(1c1F1c11c111c1c1c1c1c1cJ(5H5H5H5H5EV c1c1c1c1c1c1UUa*1c1c1c1c1c1c@ *%V c1c1c1c1c1c1UUa*1cJ1͹6ۛV7d!$ %I(BIB9JP$!$ %Ilq@ m,` j& zq gHr"` j& qEYpVt;$U I;$U Nzq gHqEYpVpեLa"D.DLa"D*La"D.DLa"DH0m@d0m@B{k$!$ %I(^z۲ڮwPګ쒅wݻ(BIBJlE$iI)-5)H2RR[MR2ZjAI)JRR )!!m4ҫH#,"Hu$J)eV[UuJYd"&k jm7eRMRY-J2"/ꪱ"eedJhl5q|_/|_"|_/ȾE/跿x߼ˆ.m/I&ˁ$|${ I/$ Qd⹍<)"1o|aFH(i,{s_ۛ\ߓZw^W5 ֶ_ 6[B!Vi\uu7;[o =zXE|k|I|IV]+|>>|>|{˭ۻޝo~^wAoYj9IBlQv.$|-w meU߉sVU"Iwr(<"$7ۻw;P`FX$r.yw;J}~_~[;stҡܻ2&L 5{\KU~.7.{sȪ%Fߙ|U49rƢ*e~d:qAJ̔IR)DDDDA!B @;mE0%EUWy,۞P~P~ST^*9`ee'$|Dw6Qyppy-Oye^$lI.T{߿vߞ-hU-hz׻盿e{㑨q!"" """" g"X,Jr{dQ,R%RY9I=P0",h.(t !\c1Bh(#A/IYZnCr 5MI.JR (yxB>չ5UFrkl''g;Iq1"zI! ]iuIi$KIHl$IB7gI{oK HBI!·.#I{oKti,\!3!,bd y$=$;M%$}I-d3 1B,a=$Kq"liuU׋R!tKrHRj$uU׊vI6M+\!3 cR5 y$=$Ix$}I-d3 1B,a=$Kq)Hm$0B81B԰q"l>I-dI#vJ1B ! RHm$r$ik䓻I$g1c@$ik;ue7D!1Cc!,S !NzIm_N[[l%g)1Gv};mlqm薼9I6[L !8(CeO!Hm$n~}=^=%Wb׬F讠]AQx*jFc c^)(y={nBHBAb)$!I! IRHB!I!sn֬SgׯUUc&eR!A) RJ[m)B@$ @mkkk[mm戒)ATVQDIF(@jjEjK?Goidǡo"l3he?˝`°~$aB aDD8""qwnUy+I(BIBJP$!$ % 6I(BIBJsϩ <DQ0ml-a 4$ҪRm)*Rt*Rʥ*^"+ZjM# 4H6La F&Ɖ"FdI[ DLj I&hiFFSmJڴɌض6jMDjehfH0E65(b#a͍fȌhhLDm6LlBAi!miQUhʫ"M53$٢#i6MbL&m&њ"&Ɉ#F 6ę3# "dhM&bhH$͌d @h-jVF646h#m4d M ɌflnM&d$ &6$mmLf0f<31adm3$BI&2d5jVZ26Bf2Fl`df3DY`M!1F$ͶMDěM0IC4M6i`rB6J4@h@fm[2eTY[mEQ{㧎eU↢80MAUW-7$ @@B@U>*N]eKqEʪWWr2)JB) i[#uݺ H Hյh"""""$""""""H"""""$""""""Z"""""$""""""H""""""H"""""$""""""H"""""%""""""H"""""$i"""""""""""""""""""""""$""""""""""""""""""""""""""""""""""HVuפ@աN - `K5UQ|UUUf~f= a! xJ2)JvI/QTDDEQUDDATUQTDDEQUDDATAUV"#UDDATUS 3wν(w^ܩo+ [[z @S>|[E/ Wm "'1N8N88MݹWܦ{$ %I(BIBJP$(RH$ĜIBPwwniݻ:j{ ijށ, kN~>yUUW:ߗo@^InQ! xJ2)JRr@۸ 1I(BIBJP$(RH$ %I0mϝC?Zamʵoǿ`"D$ DH?m@$I I d& @$ @@$ @$ DHGr5 * r:*檮rlyW8qpT{Q@vj-Q  *j2P[ m #[Fm(Tev: <0p= `Wf;b_X2U;6=O3o`$IUH4$4iU5zR  *jIEPP `_sUmMm5%®\K=$@$PKj(%ڊ !8I%%FN5$D! mE[QAPRAQ\L]åLއKwtmks\W8Tt+Եi;pz-ќ{j ®pѴ]&a`X"L"(VHșwr'uUqF4sFh}wtWwzzWy^xyiK^ҼZRݣW>])wys$ $2I$AH^xK4jhwJ]uwy^uwyzz<.<4j[.:q{y?mJcV6ƣQQmQF5س)Y,%$Ɠ4 fTUZj5"-(P)†S- efQYc+&VjLcYRXif3im} :NeNmҘ\(t٪ѭF6)8kETltJNŢhtJNEmLC+cU-YIfmE#5"ZC61lҖ[BPQ1-)YnsrbJwqJmLW)꘬V+5F)96ճ)VRJmRd ›+S$LS6YfY(fF[)-JmةffDڋdKmmUE5"DYML&قH*4mjPBjSb,MKR"QЂYDkDbԩ1F(*ciSbQhA6dŴb6Ic*T٩cccEYM26"ŋ),XjhAFk,XcEkE% l4hѣF)m-m V+P blm5j5A#V+Z16Ta#i&J@jhC!!12B`oBHIh0HKmlL`ʤI&mFg u+VV#̨pʌ0xL$rni<#LoP 6K m34!QZCc< Лh@4!&! BgB`IyřSKH7ZxD$& }eo[fM#DF7~\uۛQ8ۥ$[j卍m_~T*&trc6<8֫h05Fh2$gLRf% I BRBBI 3$ fe3,ĝsY],VjҳIڛ*q',ѵ q.lId ,&jQ )D*l}*vꑸ7yZZ >#Fh5VURITI2dS*-}&iKֵ",BdI$[֭(6Oqjm,5^Ax1&e1F eF`^)3VUVm19&Mӎ8ecb*iH;mm+g;ql"3Jt)E+L!R>*I9j6MVV[`LV!&8YmPSmSģq1U̪`Ř8Iqɘi "Fd*Mjs!"HB$FmzSYee@ f52V-]nm$ ج+b69KP3E6(V)JpgsqrQ;l[UVm Q4fK%@(d$(dK)$WKj4L 2CL4-ZˠH$R D[uȮZحF'l*I#CiI&Hq1$IhLuF)L#Rײ aV,en#3ՍLfYVLc2V'+l1^mz>jUD9'8Ԋi #D6j A4FgI)c*v ڭu-VVmAI(\1Y[cc!D7;ITYL8ol&4$H8Éɦ"&ȃCF6g$uUFi2F3"F8̕Ki1mIh&jmC朜iq3I9>g1#fK6IY Fk&5RFm=lڹڠ4xk+^|O׽_<"hpy>:8sfrS$$9fQUX:rU6fz+UJdi4"Hh6$mҌ]-Js%u9#ZUq;9eCCU4jͫC{ǫ9f|IQ=|>>~]_~oI7߮nh[œ%mؔ |hu%>o2~Kq".yWD`msvsK}~^,!cO}TVEXK=ĮUUUUlfۻI$ lEIwv smmwR]}J2z6A>ͶO߼{}Ļ{N'߫4ГXI=$IHRwcIPݫ]>8f&LCd~<"~mw/O1 (am]ݻw"P[[DB֭j%")H2%")Ho^r=vJ\ 8?mU墽DB!gԄm'>ΒI{4Ǐ'r&1 Bks^i3K%I(BIBJP$!$BF%I(BIBߏ~U;{TzjUd|TܯPjWl jy矯~t{6'I%}UoÛpM$B";mm1YVҥu^ UD1"D"H^ʳ!Rٰ6ne)LDQA~7z"&i22h4XljM~Bk&uH&2V 6hsi$yDIDI0_ JQfVUsC!3&I$ng"""#EUchRncDF UQDQ È"d"3D'J8M&H'P.c[KRl&F$ih m)ClґRڒnO_/_"Ⱦ_/444444'pde$?XO*Gr׿e^I$q$Wk`_ݱ(j1~Z@cPW=5}ss}7>~7_߾sj3hRv?~^w+60 oXM[m?|>||>o3跘ay4,z 5R#Ji{M&^h $|ߎk4ryJPc"2O|}n@c$@c8=<.]nWww_n\Gh8~`Ƭgڌ=VZq/{_==woXD ͌4}D_7K=b}LX~zD@'pq{RA/{m0imMQ.m1^=𻼤iivbhU>D~α[%6sC(>g%Y0d ?~.{wк)d!*$>HJ┦AB!E5UEK$Np=lII _S ( /Yf14YfٌM"%Rz@kd%G2"mdfAd/Ea;̖5d[^BI$L!@k{m/wI:@ +sIcEUr @5Y6n2hdmif q_v:Wvϻ'pt+Ʉ1iBsb,i%ElDou.Ͷlԡ9ٲB=sVUQT!DrBRն-#ר:lP \c` \c|VI1sݎ|W[(ٱUTUBܤJRmPWfeέ[UEPIʡKVlP^ղB=zsVUQT!DrBRն-#ר:lP^ձUTUQ=dmԵmeέ[P[ovMMpNc@')ڻɴ59iCnW i@R@2+}[ރ O F1zUp1kkoIKmB_8oc[Iöۛakea '5MVqͶPk/7Ozpt`t $8,?ix;BzK(0)lm&6$tBK$.cms|zT.30ff"T.affl a3 30ѳ3 6fc-wqV?<ϟ/ӻw S(REx H H Ϳ0+誨+)cLF+ E2+&VeUbĬcEa0hQ)VVFLab2b+ebF LU$̓D@2Lə,V22X0#i2$BChCFh13ibVfRL0.da &ɓ7q 68ZrS)-XDB#s!2fMӎfs#8Ȏg6ÃW9qW(NV22DdF!D&997IhC8l͑ 88FSs\pI+uk[SipWxW0+<+½uu\o]q ]{1u랺H9Ii'wI<{y^sJ9I$qHB6ADAAih$!KBMXlT&jfƋb(j,ٱMYhlKj+e,L VK-j&UQ#cVEU$"6Պ̥ȄdgE`[յ&I2TmV+[L DP%EJH2D1c("ֺԭnUD8-icD5bYY,6FqX+e%FT+qN3IsSQѲFBRI8)D[R*Xpb8D+Pm4f܆QFM&aGʡ'KBByT#AKHzI$B*!O_lgMn_=|ꍦ)UVDJIdEܐ$ D$ DH E(~퇧wu tiNťe @1L""Q}{ܐ$ @$ @"URWl͏7Z[^FȚ>h 'N n=$y;O)L"SƲ]"Lp]wܷp-dzDNUJSj^UG{wwfÙfna7 ۺ~ ?}VSU-zPh@k=Ϧ>+ 'OZ$;f)L"S͵1fڇ]w.u 33afl0p36ff a bÆS8 oۻv U-x(0{y~.3uL%ݲ0LUmC N\0͆ a 33afl6ab 1M[nꪪՑ@L3 30Z֪HD.HjZ֠30ZUT)+Z H H DH?Kx:q`Yu9pfk[ʭmVUU#8gt  ݠv- ee R LRW `ff`fFfS)n]mvʷv#r$S1L"RH2,mVVBI @$ @GֹV܉8&n[,#{YN(C),",l@$ @$@$dMef@2~@Qb q }*Z6JRBmB *Jͣ5 $ kn8;{5%kTmWgUIsP(e )x /vp$H5"AѶTHSd^ޮU+Y䉱djLFjS ha0̬L_*)@Ln77vd(ƺAmd9pu(חΝj4ͱ|^xo [mj_i;lð|JwؔÌJQX}oIRhmRiKold'9E>7DۮQ;~{InX|~v7򪪪Ŷm)i@-^좹*!m"TQHh$o~{/ͶֶmD`y}y}|ꛏm|乣4AyF~|Mo5@ Ǐ""""1D$t_Mv_zzy=ԞcHݰtuC|iir /F-IwHYEVʪҫS/ppF'sjqw#m4sM i.ۇyUǏDDDDA$H6 IޒIkbczm(*zhݬիBVES\0O(O6-mmI8j,I$]{R~~>} 4A|*"1޷{޹Oy۔NWbrZ]uZ0௦ivmm̽sW dmmhqKk$׶en5W$^]MƮI*^/f(ݤRB{6wA]:ٻ  B,WApAi 28Pͼm%iu3d3]yu3Mwiu3 n\J 8m wٻ  B,WApAi 28P; 28P;BQdCV MpI†mI†m%UĐB*o6kL3osȴQpdY*z֒)K7iQpdm^ 6Ƒ%J%lm4[`fęYp (fRHUKm«mm$ˀaC6PtC;x}㻻85*m9PtC65/J4ߓODvoLxY.=oORysԶU8Pkls:Ԝgv-EU+[ HD HD H}mD 5Nj-Z߭g.dCDD dU#iKm- H HSjDDDDDD""""""֭"""""""$5mr:?1B` kWM&-S|?-g;AءA/ {N1N189[Q;{s$!$ %I(BIBJPI 8I(BIBuuXBC|c}*,=(Z %>_;~<%l im=IS8c4^ww6<m=P 8!$ %I(BIB!#eI(BIBUr wn.mm>ESo,@ߜ~<2Gb`{b>О_q8v'sGw/[}I(BIBP$!$B#e p|.\:yI?>@H H D H@$ G#@$ @$ $ SmmjMjYpUUvFj.WjZklɸ{!݉<1 p"".QVȪ[JZ$ @$ A$@_*R KdqxK^ycc1]Ue H"sUMIhP.=XqxD8Ul@$ @$ $ bL (1 p=bladcRJ,!6bV5fUTHHBTCfU!(@JEU րP`={Hl =>y>Lx TѠh$R 4JJT$P JhzMJ*D=@U/#&ffmM6#URFIdAF$j Qj" k!REj@jHX6"l$ّlDIMfm$$63DI"Ma"eJl b3Y)T6 C2YMlTSmJf©X`I"aRfIMU FlSjRUPڤJZZ"#mjU+5Hl$ShmSh̊Y)lC62Ic3R-I6jFڈZFEkFQEl([ZmDi23I"L$#IHi"A!Xm[SmC)$lj ³*1Vjڭlm+j FҶfRUMVjڥeRXa&Df$H Ym,j2X#SQhm6-ZVZ$ʭ4F&Ihh#KEf3$ڥBʴCfU)©[2Tճ1$ 31lئ(U5 lT3mIfڕ&32+6&kSaj#YijVƶaL"Z+5fLI"MșI"MIlHH#Lڙ(*([ "m-@feڭKe6HQVeYmTUJ̪ڍI"LI#+a3 ڤY&4lEm* keljV)LʹFIa6T0fE& YSSmF`-02)6ū5jL[F-JF5"FF-Dkb&6"QZ#Z#[Dhi[dZddF4A4BDia&i$bD&DHKV6֊4j+QQV+ؔŋbBVe6Sl 6ld$i2MY0i &İڙPhFj+TmhQlXdSc21Y3*fi&HH-0IH&K3VBŵcm56hA6͈5-m6"ŪMj#SB fؓI&4L%2HDd[IdlmM&ƬD+ R61&e3)6fЉAbM4kV6McmVՅmbYm!2f fUS2XkjjZlm2Z1mlF2A6IbM&f2 M6Mڬ+$C% elԶFḌ4XK%hlJlJhA52QDi"4HD2LI&IHDbIf14~ AA B ! ЃhCB"&!0RFd3gB͍!fI!,fBl-Z&cK!cf0I!a$56$i6D6ͳh3I$ r$D$ZIhFLFLFK\kD66tI$B-FMAUi$#&ٳ┦յxX6I+IMAiyRIo#b5%&`)Uo2! `z oE4cdFjJMI_ $]gD! [*kQ115Z4d),FjJMExboTgF4'Y[I[mmb 6JK%%I2RcbF [А%C!7ZV*$fmmM!VԣVI[Y-؍blb( ei%I%z] 5l$ıTg""B mIV*JKIi$dJjDj 4BD UIU&7!(C8 RI-q&gp1 # 06<[V"LBJiii,T mE"Ci++h-Z"d*%lT[%%e0øi(t$\ {4DDmB4dh%J%*I*R$Е&$A$e Vj@AY*PkJc2IS(,)fT !ALIHD$44DlM%(ٚ[$hfD$" Q,6VC)%AI$RKUd2I, JJQ$!pcLITƑiz!!㌶GJ&KUII&$FB!f겫K6D@A۪VVVRHHpp$N@d| =[Ej*ՙ#q,EIIdKjԲmZ&I)lp ڄC5b($%Ji]$4f2`.Z ,jڠ," -Ji+$I$ $i$@IH a$RDI#CuZMF)5TM[V!&DU44h,)MIlJBI%XF )$j $(D%P%%UTcD-$IaaMX""DI"DH䖕iKDDHqDwUTvImpI-IR[&ѲM[+4A m-LDHAD6EUVI&ЄM U`I%RI$I$)*$B@ bTHI$IPU $RM MI$7TK0!#\E`T(7A Vʦi$Z jI,lmd2h(h $IhJIPh*DLH8wTJ*$b܉4D488C!s[KKIjD4!1(#IKYF2 AY[,VdIlHD؉#IKY)ZU2L&m %*K[eZU6K4fD"0b2#02afFl6hdi[JVk[VhXh!&jتĆgfb8"9έjllllTmFEXdٖƱHjm[S m&̦QMlImZQAQcccQhclllXƋPTPkmFьhѩfڌhŊ-b(Qhڊjh5Mچ4ji,٪mZXѫPk-)ABfXm1c1c(1c1F1c11Q1Qc1bc1c1c1F1c11c1Vc1bc1cc1c1c(c(1c1F1c11c1Vc1bc1cc1c1cj1c1Qc1bc1c1c1F1c11b c1c1c1c1*AAAAAXc1c1F1c1cXJ%V1c1c1c1c1c1bUăTTTTRUac1c1c1c1c1c1*XJ%V1c1c1c1bUUac1c1c1c1*XMU?%I(BIBJP$!$ %I(BIBJ}Wս{ߧKzmXKzmXK.κBz뮔.zc/Wctu]tuWIBw: sPH^MRzl)Aj],uj],䗫ڱ䗫ڱ䗭{6ujIzMIzM],I(BIBww뮽$ % j],uk$ ۻ륃vջۮX7m[{U P2 (0`( ( H0`e0@$ A @`HJH) `?8 %(Xf&"  @@@A@A@0@@@$ 1$ m5@@ @$ @$ @@h fH, *7Ȧ| t~gyyyyyyyyyyyyyyyyyyy^^^^Wnunuo{ ˂M ˉ5rm/s_Iw/. $~I&߅9I$Ec~&ώU]t-{q8ޟ$xŻ{\q8ޛ{zU}8;=QmB!~i]}۞ MK?f0kAהD^n v~TITI|m'Nm/Ax9y/^m/Q0'>}wwZK>}vݴEN5&9)&~tO]]RQJiQ# "IrEs:룜2"X7 s=\P 9޺tӃsp9JriDQ5xNXQΗ]qFs):}yNXEQ/c'F4Pi(%c4$8$I$I)JRI$!|缙$TaUWy,uA\9g͞k'M|eT^$r^9NT ㅈI$KhUKhrH=9y9~5D'"MG"DQ5!~/{Uuke"T)A$I$JRD!BbDJXIc0H)K,$(1Cc''(g!B ! ]Ea"BI%C8bƩy$ BE#p#`zqw\})JWҾπ $?[e[lܚ*i;rC|k$&ӣq)"IvJMM2KOitIH&K!Gw6Fv]츄 2/uHfd$wݮ\IrGW$bXbg4(BdKKl>}\UmzFtMV;%af!1bD ,a6I5XٷyZYU츄 29$h%I. #nHZYU츒6iTUccAj ,I-oHRMV/%m}I5X11q&Jq#l6I$c[fޑI&031"PT0mzFi$vKl6I$cXbc$J*oH$U;&Ksq$m c81b@}#lMmsoI\Z^B1!1r bՍD"Nm:kk\k'7ӶѴ+.01Ccm *1ʷӶѴ+*umklT1F1%liD#[zF4+/moE56En؄n~2 Rc%RIBJP$!$ %I(PIBJP/0vyyaeSE_JV ZyTQri)rꆫ~J[uVe(2E=ᔣSԤ zJ۱_xvqc$I( %PA$d$ $X,ayK X()$_5kZ@ H HH"s.\Ha$0$3Zmkm,mmdZmk`k[ml@$I 6Bd0{j^;_wwWw8wp98n6hw9=y?XY1 !%snۺk[ml$ @$@"DH6^Z5nFj{ރL=b)H$mm339s; @$I$H6CbHd>o^]mt[]QZ{s=٭Ѧ&z RcHAi (vfww wgsZmk`k[ml@$I 6Bd0dMe*gw~@QbqLw@@ʱU%*cbKE h@EVكm`CYF[,TU nF4 HH{y&:rقICqR>4@}OwwpфxGDI)E44#LjzyH)= b0F O%*jHiIH5= iRJQꇤL4 &*wFѮyx71-<мO4yq]ٻv5s;\3:]bbcn]L&*LTFiגiRF&E$lF4H"6i6FȡF iTLHZ _M_Mh4msc6\nt4msc6\廕NqF i26B ѴL+fD[Ztmsc6\廕N=,IJ2$!&"dfDDDIDDIȌ$6hkHIM$HDI$h6M$HD&6#c|F2LSP*,YX2ѠحZ -Ŷ4j-ksmhF,XQ`5ɫ EbE6WMhd6ԒTi I!#i "ȬN[DmF5lRD[WLkXIchSjR]MIkQb)-6Jڪ9M5((mIMA4&m CgMc(PYMmE-[h#jjfVefQ-SS2Fm-ѭ5Fh֍lE &hI)*$!bXUn[vꍝث[6IFjm)-rlRvکsj쁴6JmEfT;$͕.e)PS6uJ2[2JW4m+d'j'2DfI"@۠SSbRW5Rug&6I (OrsfӹW9Y2fړdU6f)sl;[mPI1KaE*vNh+jBYR+e+ef6V1x݉·."k5s;\"Tr cɉf6ّIM62)ERM҉ H$ 5JV1-*6mEbeFmQ"ə#lKJ$M1&5gcsƌIk0S ZQ"2@2҉LVZehшUS*$YaiD6d-[V ٶږ0eLUXR-VfͪxWC)ڄsW2 -Dxjjț1 QXb1F4ЂmjZb1FlFĪlIhhRh&ɤb $i 4HIɒD&D6Ii&ViMV,XV+XblD#H4&Љ &m++FM6Z4RTIh&IdI65CkjFͤ5EFVeԍVb6mQfYڒQl#he/" 0U-6NFLFLFMc8A[f8CoSj+$m&m xLƪNV'58b0Ȯ\1L5E m(rP F mރP>eVI, ƷbJ]%,U%T6qmI-8p7rKD^ESt-"٭mjꈈ#Q̡&3)JjmQY-B!č[YU"*$#Rj,̔)mmmLRZ|DelF+)Kez͋Xb,XC[Um$p#F>8ppL؍m-fzSvμmsm5QbJq*Sb۪ګi$ 1tf>>` V5S}㱽zuxZA6|÷{©CGN::tuߙUP@%ڕA@ե@@*@YP$06[4(X6`)6 % P\ j@[SF-E@B`""" (m DBPm I @ @$ h MPA m5`mksrNNS*$>rrfkGw\z&"\ó!ɛIyCv͆N2z9'r|:)^[.[[]MvS3z9>3gt*[n}섇Ͷfc3-ənLr?}ʪUUUU] ;ccb^W/Qz^¶ϳ L["M -D4 c4 "y٭`OHHh4F%>+y];}0Ss"e_D-ԡ\w]TQE?`fbRzf ljSL(~&o)N30xGu3%sAEVFy@ہM @陈&4m},RE@.{{N}ξeUSLLgCYE6'{kb}z=G@zk$ Oq/x`Ľ 긔Ao]icYe[UUw[k;ldUy,[؋Q$}刜mzmo0UUU_=-,8=&k<ݺʌm{#׍cjLwf0< ߟJ bwznUUfٙٙO6ۻwm=yUUUUUUUUUUUK2l!B d]33;3#nN0[ٙ[spuC;:$Dzdܟ9l.K%Ӝ_UUd^ٙٙwt:{ fg޴2!fOmyw 7|@!шswe^7urzllٛﭶ[mlm5&UU~o|y~C哻f1ҜB!@Iٳ@7mɓ!2d X%mm}}/† |>UV 3$I$I"iJiJRp8z8plm1b;Bwpww3 Uewuszf6Kɾު-U}}}깘oߎY{ހ w{;ޙ檀wt!ixݒo 6Gtm:uQ۟}Pb 6zvwmJq)l$c6wUju}{f3#6lFolN;ޛ۟}Pb KG% -Uj! }7o&uܶ9mӽ۟}Pb SmJq)l Ye;:n}Pb 6zvw}m#6vd $M:-ӮMmJq)l$c7zwptル(30f?_ y #2K̈́fn,;tuǕEQTc@-B1fW0[ZF~w2AA%66RxW8'%3M!mETETETET H Yٛ~I"JY)FRc2bġKZ*V caf5*Q7`ڸ48iD܈M-ilMLXiM"e#+m-&I,ZZ*Z2&mKhYٶeV V1fTj(աkhPEmF9) ̲Pml6i8l:jI Skɴ:i27UIu\ujڱq-m*ګ\wg.VQaE8RKI$W⤒+ S SA JiQLԽ溜z`Kop$c5k>0i _%zW]J%W}J,伆I7py9^ R b4c<*m)! fd-MFU6FWYAQDUDUѰb ʦ" ʦ" ʙ#AQQSlTeSlTTDAw>'UBU$TQRD!BZUԉCU](DaIDF*$+H2)>J| !* hDdLa&T 1eRYE66٣kMmڛDҖѴ, SF1*L4--$Tf&#Fc%Fk6D6P1DTTT-i6HS0ͅLFƪfضj(X6m6H|%" Ovo[/Č`icHlVޯwwe4g%Vfq7Ն !f*"""""@$@"@J+ `}wߜl>4b?7ᄏ+#F6 @Pwd9(3f2ڐ$ @$ @$ @R}(أ fgU>][zp9J%Wg%U]$ @$ @%T?PPccOyt{]޷z}cBmRxWR㍝9,L4iܓ<$ @$ @$ @[j"""""$""""""H"""""$""""""H""""""H"""""%jDDDDDD$DDDDDIDDDDDD"""""#DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD֤DDDDDDDDDDDDDDDDDDD$$||*$4};`4'JKUlnCĖKzɶޯǯY䆌Kmu3M4cjMChNjvH໲G;t @Gݒ8.$\!#Hݒ8.$~UU*0` `'~??I{A-R9d6$ıl c2[M7n^30h0m޾ݩ4!FiI5F~|8.wdvwd $p] Hs$ vH+5>0mܴmƁ-z4f`o3D4!F<{/yQDAEDRJ"J! H"DH[m[o_>~?W :anV$Q)V8XZ3n"""#DDBRѢ!""#B@^5~>|EF3,ݻnwUꫲMt oʫ*QJu*RE*h]uZln馚iiIar[i[vBh4@Jڛv԰]u wHBig%kzv+(M)6ƶ   0ovږ+M+mwt!koj)hi^DDDFDCj{r[$caa m(+$k;:P@;n(P4QPm`DIՍ5J+mRMDH&0``SUXRJJUmh)R6lF bX5DUUkZԡ0D Gc<`Om}Ի aOZ  c R PPP^>ն#Mm [L,< I ($_Y;_`6ހn lfS!J2<5JQTT44@$J I* ɁSRJS=G^{W+:+Vuy35^FѮgtkwFθ{Ѯgtk{:c\3={wFѮgtk{:FѮgtk׽wFѮg"Uqg\vZvjvvq\35uYkTTmkmWaۺaٽz5s;\g\u LLֻ;\35i1S1S1]k\Ŗ9k9Wf6LT10ƛZLT10ƛZth2Fi/9^4msc9^4msc9^4msc6ÜMs6\据lsF69k=nth4msc6WI8W9\据lp+xx据lsF69kѵ͎h[]$6\据lNykѵ͎u$AtrK[]$rI]djgNykѵ͎h[]$EYth4msc6WI8l-tsENhiidV*QUF&U,XZ,XYj)dMd1,Z,XZ-Q,cPbeFѥ"%Z$Z"EQcHFbeFƢ-hTX hV4TX hEQQ`1Q`1Q`)-E6ѶmɵZ,X̊JT&IěVVeefVhѭ-6 0 IZ,F"#2JmM-fc,ccڍF5cQj*61JFQTm4کmE-QF1M[56V2(EEF-"-b[EEE%6kHHKifج5lɣZ4kFhmfA%E%),ԛSa-lQm3C6e6b ejڅe6bZ#*1cEE+6Pj̡Dɴda6jMɦE%,dY2[RhRR[dDj!j5!JM·SvQFQj]Ѯgtka\즴Alg;n݋mwv&LK1VQhLJim҉ZdRSJD&6Mmd&̊2 4M Y*h0V-*"-k&Tl[2؈֪5Em*66֦ M-$mfE%45Y5YKJ$M1#KIJګ$kZHX,mX mEԦkcF$ J$YlHHH3K6LDYF24Ze1cLZfQ6b6ŵFLԳ,2Ik(-el2҂]ؓ:e]݉sZDtkwFD;)&*f v5Uؚlcc1,mhd&(eKk2҉BYIfRY+U&A&Ik%&$%l``lEU*6-clFPbeFZ62kJ$Y$l$D@5Z6X6FIcjSh-1%YKiSbD ilؒe"dbJ6ѤhkF#liImQmdIL#HiBRmmc[Q.1Z(4IFQ6[kckcтڣ"Dmci4fDmU bceVe Ȗm3RVLU SfZLU hZX`*m+YaTՖ0eLUE(mLa1bړlfH,Q)XٰmhL m 13CAJ7B5 FB֦jQ F3=i%,Ro жy"ƴbZmMbCB#zV1DX֌[QhSҍЄ! oXcZSVlb,Vb-mP͵P>vSimA,+j a[PKJ12LI4ڈZ-IML=(!/PvQmmF53mElV+jmB Ԗow%sڒͿ>IcI%Ͼ$ow$}jI,$K%I~@$ߍw&0Vywɶ;srw6|΍nUnn\Z~nn9w}+~~>_O~S\ 2,Oy?b1hܤKw_}Uh)@ O뻮!B .K,dDzM (1?/L7+^*8~JLJPm<ǘW RWl2$e%򪪪'ww*dnsNxzf\9GymI턖۞P &W}}T$mI=[p +nZ>3zl. -=mIu۞޶UU@/陀뙑\ΞԟolmM>MݚIVrQEM 57`*jO޶$KEmj|o[mEa%>s7_y33#bmH$Vf$]Z+n{S3* }wLw\̎eړs7"nNnn8w"nNn8w"nNn$Mɶݨ]N4lf I{fms2.{39|*3>RI`]̒L5.gNfefkZwiYf֮lonfJ[6ۛ+7\$5USKRI6k6ٶw=M3vͶmjdmٺI2 mpUM-Kj$mIZ&mH֮I6m*L s>fُ|Ro/~i,̙}`kkD6tm޽;6擵vH<^@ݒk3&cW f^,I[#1ؔR @P!@(M 0 03$a @%  (fP!@(BP p!wBJ(L@a>(yAz ބ!)M0 0T߂uھE_#kI@9Uw7!1vlz竽6@$IlI$H%$X /_Hk#MbidXf&Zi$lV"FŪK&QJ2ek!,ff*ZJVk?,: '`fkI:44ؔqJbD܈SkI&Y3ljfʋ+QX--6f$SdmISlʖ5 [&BVfZ[jVj11S@RIP*aLZ FF44JjfLa(ZC$mm31V͠bՔ+j3[2$FŰ5kIcEe ֍M[6d*6C"٩XV%6lVSRLlLѳ2ٱMCf+ThJ[bXAYa6Q&%i1mEsQSHKtI fĚ,6Q6b6[2"&Fœ*NmkTYkZ66Jl(ƒ*Ujefl3!3JNCYB4EK+jI%RYXcnja5 X"iiE%Y($[mV-i v&Vi%)uAk`Ո攺N[lF+Fi2LI#P척NwӗV$驘M\ۺ:Wkr(̙b*iJ"ҠQ#Sl2PVlXvR]ѮawN%-t*H()"$8s37Lڐ0rUP"@D,+!J+40 J2QLSGOΧm3V[wT+mٶx_v,loƍ~4[^뙛mI2[rTUU@:ޏ]Go=#eI(B6PlB$!(B6\llB#e\UER#!"XQR,HE¡CQ!%RELPT~#o"M&M di6im$d#$i6IY$ʹDHLH625̄cJ}B_PXB1ah0I1 2UaY(c aFX4͐!BUXEB:dԭhVSZCZiiM 4+FbmPXaXd2XbVfeMXa-0fHH$e2ad3Ef5YU0ReVC `dՊ01i42lQJZ+2mdLbA!#h[ih R1C Vfj)C蔒̒)5&U jMmk[6()ZlUEMR5ըի6`ī PP!lU,i-j!KR_~I?I^Fe:e{*͹kQrkY I=sAl6@ `-,e˕I^5?36ج=@;>k2L&Z|oZfmLWm=e<Bw_|f2xJʨ㹸aF1zٶrz @ @$I$Il ,KʩWP^6^n$Ò~#մzےIyyn[^kAY4wʨKp.j%7t:Y{P HBn.@(@(J@(KP Bt(wI@(wK&@(wJ@P @ @$ %[-$_ouy晦j\}=<$Ò~#մx^!zVy^>|W{=l,ɖ̙fL$lwʨ[p,^U@UTܪwq@($ @\@7BP7tP7t!&P P LP {km!@& H󻻻H @$Il@I`$K  ,HH`6s$HK`Ip`Ilmmhm [m%%le$p\^^prKmre<m$m#`~ZLrl7g9VZ$D {mLAaBc.fͳwmwoW] @$II -%_s;\Ύ욻.]FˣWeѫg;^kwFθ{ѮgtW35]RFDI 9%4msc6u%׎HWI8ܮp[]$rI jV׷FѮgtk뎷pэms[[טэR#"H$]IjrIwu"DˬriuM.ɦ$AtrB뻮w]wrQ*"$Html1_=Q9\据lp5xx据lsF69kѵ͎hǭݮF69kѵ͏[]%据lsFlsF65\ѵ{]h4msc6wk kykF_m>#chTDDDlD[&TlFō,ch؍`ʍP$Km-!$A&Id- 6jfK҉LKm"m lHؒ̉-ZMk`T`,X,b͠`5ūFlk%k4"!!!!,3VPX$Kii0-(i+ AXm`V`M&&h٦hmM-i4m6d҉LdM&H3Sm[Q̋dR J$KmAmAV Y+Fͣh5FQZ֡Q\k\تۘ5XحZlm[hF6ѭ4p5[Ѷ[hI'Z5F sUh6lflii̦mQ"V 4$Q6QEKda,P(PBw* w*cZt:lj6kыmڹڹj QQgv16m[E[EVƣNElVtIȫmI9ѵi,]˥+Vm+fbPZKd[R[KjڊfHH̬leFֵ,m&i`ZEZ K6m-,!ilZ[ 2$aYXQڵ+&XVcSm6"kd4DŪBm؜wU[]ѮgtkaMFwjm-[fevƮbQU"iƣ%G7-ΚI9]IKJte$,:;J$Mm,]H3+g&[94$:i$۝8uӛhk5mcmMUjZdج[2TKMZ6Z6"$lZQ"ia#VfS+6jщ6ţlkM+U VJV(e2[زQ"2Y&ZQ"-FjbѭXmM*CUY+SjZCLJii-dMٶ 6ȧ*ʳEL4Չ,$b5ei2ZL0`͚э,0`j̭-Lmi,fԠV̨SfDUmJVl֋, cZKbebk֩f&#(`xlB7E7!h&%q$)5JJ m3KmPKfLiRQDXMuc$9 dB]2m' Z[S-/մyFm  "=9A&FV3䢔ρÍ ]ՙ,nm듻KI)ąZM5%ለBұ*/3d{rTM+Fh A6E_ B!B)[m[7fTYkU55ckX$6"ϒJ74xC:mmm2Bo6 lmpIh0=vö06I^mKm--kbVѨa b"ş% Smɉ30Ve+mV56ѵ+m3l37I=%5KDhH&Z i[Rk\6I$VM4BhM$$7ƴnYIA jchJm%,VfdYKPXaMe-AcmbkI['N*[(KƤJ6*"lZ#cV 5M4"TIh&8S[mMnX"X*ՠhE+cm)e\\SecZ\k\lK$I6YlSeKmDUW5E He3ReV[I`+2j%u3i;L(4DMeYl *Bfm6ijѷ #[!UU3VP6VJc`5Qin[3t(41ZMbţl-*18Ɍ)Jl+dlTclEY6`"cۭmĒDm3ٺjmF%UI$M)L9,9f4nښՈemnFq K$I\mȈ%-zٮhڻQ[$5[&!e&љfbR4dm&"h)3YU+hض[i*KkXI7rYeEpB[)LQMilpحZ66Y&fmVSmk1Eجڨ8+v37,AQVҁ%ljŶKmzfUf2Ve^Yi f`PHB"DLɶsr8irNnr$I4DP)4XŊ0&MVLY28*IF$44DFH24ʹ`UUT6Eff1fe …3(e2YXS6HZZ$Ѷ֩*[IVYK05fZ1-LTRbKJRmi* F (54DՖlZѱeHH6֮ cmswqѝ@w cmyrc;lgwFD{Nn'vi٪h Л9<ɐ`xͥ ͡- ia[6V(V1Zymm\\hjX# P̣eldljٔfMڌH6&*Jk3u)+lSlSbbJK͛ucsgiD^s=y<meR^7;mԲ]ٝ6tnn@imygO 2;mkɨZRY5/[`5jۺV65\dV cfʍ-FY-CZ٨H-Q V:ٷC"uaI̋5FdG 2hDV$ cVH 2Tb;bkpYэch *f2I-c[ɶڂ6ݡ 13j#hkWv `+` n&DD3e*VԶ,b X5VQRVÈdB  bgpgJV$5+S9b b-%wjp kajprQXEvݣF(44hXlXkf4hѤѣFFŦ4hXhѣEbXUf,Xb(EQXQDDU*"""&RdFjY"A$$ID$TБE-&mVZ]vRjՙXڙVdS4ȦA[to9lJ[8trn7 :ٵ3kgQE:PjH5;8Mh6P5wPch[ ΙwLj޷9 8aa;g&-ɭ֧"RF51Uٚu\HNMLK2L)XRi56-ktAڑEPJ[$%#I5QbErќ8@6B"JBMmČNnI%*dJ`K% h-2ƌj1VMkT[l[[mlmTmPQjCn:Z܉ ٕ R!"wd{i(b w{ P$@{y{H!J~{~oxmc1c1c1c1c1c1c1c1cϟ}[إ BD{!P$@إ BD{!P$@إ BD>H7CyXR-s,XR-s,.s@e\ B w2c)5  mz6mBХو{ԼZ^-/v\ֵwflqg-8LDGggn88v:1kem[Uڻ-Ơծs%سDKUlDE5&&*wRX6؟#W0@{}テeI$'Mgnnf~'~[nZVXsoox{/ˏU ac6~J  UUUUU_p{UUUUUUUUUUUVI$I%a֭۸q;[ wBmw^Mvǽߗ߽ ۤ=hOS|MI!;kݺMC}I ^<9qy[ O ?{}F0c}CQ#3n謽ݷ'WW{N*^;,S߹򪪪{N{򪪪{@ ~&4I$]{O~\=$Inm\q)$I!#:f~Ҕ}0`CߒCm$Q$-Ĕ$L%I0I6nl{( aü[I$I$I$rmm.mf:mm $]]pKL i$:t:pgϪ!O=R mId$P!2d$M$۝h0J |1J&KٲWdwHK~!)hdI&" 4jwϒ}!B B߿UUUUI$I!+6f[Љ&mI/mI$ KBa= q$I;' I$ snt 1 A{J>en-{twD bFcJF $N/(^$ $\MKĒLQ aȞa8^&Mܻm5Ӹ+mFrnv/Jh$wJiixI[lQƻJ +' ħnk^[{n*j0a:.guܤn)ۧ]>w/wJmn 0Ñ;#JF-ǻܛ^%mHq.ZI[mNI[m6[m/I+m8sIAEdxw9kדNVKĭI%]۠I+mII+mmI%mQGi((/-ziݒsm/%^$ '6ڜQĒNahN{gۧq+mVA$w^$I$$e$٨w4VNNsy;t%mJh$\۝ Ē $Ēl^$V5q撂)ۚrׯ'ny۶ISnI]e1٥ĒTۧ홹16.6 B 1ЛB{sE7+읺mĞabރn$ͷħnI&$8`FОᆤϧmNۦIwvu96I. Jv$lOH"pa 5'Iy_mm;'nq%à Aڭ ۉ$Xp)۠IO-ӽI&{4>[?6𞤑}jJQE J+lx+k,Mbv׮1JbHmzwzuסmz$׭6^`)! R^`)! R^`)! R^`)>w'B(b)I +eNcmy{=>ϳ{bK=ϴy6qy~?{~+|??;}lcͳڸk#Smx =I${Zk|H>NJ#qo鳫\cIUQUJ"a +Y-/[-/[-CY5CY҅:CY5FS5CY5CY^ۻwk矆۸?!8 S~ÿ9助c}~~~}:SMT>4Z~mbFHHHr\ϟxm%4WlYJʷ{ϗ@@5ARX"x{6uk|wB"xt}-Im! BHkYJ3YHkYJ3YJ3YHkYJ3YJ3YYaUf!f!f!( l߼~ttϫ}-ﯯN\m'mWsuޓǶo*)<#mD H"&+Y-/[ gq gq gq gq gq gq g};wwn""""""H""""""$"""""""H""""""$"""""""UDDDDDDD$DDDDDDIDDDDDDD$DDD6l""""""""""""""""""""""""""""""""""""""""""""""""""""""H-%i GA?_{=" .a)fC펛SC  s{o4$1 "5ARX*:{ծu)x󲊪bL"":%r[zs53Ps53Ps53Ps53S U3Ps5Awz{{aN9{jmUlw{C/HA0QU"c JțHͫ|03 03 Șfa,ϽN9{jU6W==t>8ŗ=Ϥ!'TUhaH-SN3 03 0̉afrϟ>U|N$А%yTY[Kl#:SQSg4$li oeZVb`*ַ1hoXəa%UUXcǸJK[w6U/DT(F``0EQ[jpUrfmь+P1YBA!#j)dXzi`SjuHIVLdZK%W *ţƴfeY2iVIfi:³ mB[*LҒɲMI1+y6$HbCmɸV+i!$&sqXɶm#i3ILݷ,Y9p&I&ɲc$$MfFRɂlI!6!0B D 6M5e552qͲ@"A#"f$d@"h2#l!ƪʡ $f9K)[fRIՍeZ,h5F1hEkRj%RҀ ai@1FdbZّm1Ʊm&mmE-ŭ5%j` QYPj3$lIAdYi-j66b+:붮KKsm\; yz5Ҝum\ Owp8wڹwYѮ;^kG8Rw*-H%4"S`Dդ$Y)R2*LҡAcmMYX+[kk܉jwC-N G5AsZ fSd-lR^Ps* AX6"-T+-Fa[0S ׻ds7#dhݭګ)^66fGmsK3#{[.4r8s7$bI{(ok4Ywuws<Uxb79$4mղLեղ3ۦVi9㍟lC4DlʲYbK-M[5bT, ``, ``"2T3iFi,Ѱlc&h4dEj* "hFŲXѬfR V2YV`R(5-SeMTm6(6@R*ʲ&DհmKwF$V )1F 0W dP*qUl#7muM\22بFciV6D1X!Ԉ`hb"EZJIP,D ӁaJeQ m5* A44hmmZRTŢhQbQj*-EF֢""&L,D]k1.贶1e|-()㍒!;*IǙ:::뙅8pŤ6L1 *) c4JԸupwt֮㫻%v7pJèBu\H4Vq",me QS2BM Ô+[Hg61fI*Ac$H4VQ%[i [$fMffQX$mX]w\8@6B-6-tJlչ$T[FKmmRuFrsl "uu[kr-FۢcD$Mi ɵԒ1{ ]ܥ)K9W8 lK Jm\wWidd V)A%*U$C Tw^x^Je0E2elt1Ə^Y a(.gALEjVcΖC:ٷ#HVSjD4LAufluB$ŋRZKI$c_S 2P*S&+dm2K%iֱKeilbM&ek hؖUc5-[[J&$m&Ѩ5b1 Z1%Ih Zb,QcֳTcF4h1F2Rbɨ*1df6͛-2&je3Z Ƌak2k-J $[UF4mPjlIAmb(TI D6l1c1c1F1c1bc1c1c11c1cc(c(1c1Qc1c1c1Qc1c1c1F1c1bc1cū1c11c1cc1c(1c1Qc1c1c1c1c-X1c1Qc1c1c1F1c1b֣1c1F1c1bc1c1c11c1cc1c(1c1Qc1c1c1kQc1c1c1F1c1bc1c1c1c1bc1c1c1c1c1c1c1c1c1c1%[ VUl%[ VUl%[ c1c1c1c1c1c1c1c1c%[ VUl%[ c1c1c1c1c1c%[ VUl%[ l1c1c1c1c1c1cl%[ VU1c1c1c1c1c1c1c1c1Q*Ja*Ja*c1c1c1c1c1c1c1c1c1*JcI$?!J@)BP P6Ġ! @/#UP ؔ!((bP @VIfV%!(! @(!J@)BP iP{{bIF ؔP6ĠiClJ@(bP )BP HBP BR%[$:߼cJ[eF1ZvĠ[kP -jbP -TjbP -ʽVh#UVjUV,(1Z1Z1Z1Z1[-[zmcJ[eF1Z8ݤBnc @+$Ivm ݤBn0KDwi6Д1I[qBi6ВZM&1M&Cml1M&IeWz1%WP -jbP -5a(m5](m5](m^c @+l@+lQ@+lYkP -TkP -TkP -TkP -TkP -dFBHPP6@Al$04* 04*l$ B H0)`H`!l@30D@(mꖅiLS*lDS*R$Hbo0j*eMȈ)-ڥ4jҭCPDId,[2aJi6&-ZJ-ZJ4ѬF}0MMmЍVVViXȦ)l35=򪪪N/BI=Yt/tжwK\^ӥt5$>|jI~|$o>sD$uI%pYI$>\)$լ3S E_vDDS"oȈt\seWE_dDE2"1tU{7Jܹȹ'7ߟA>v/_~=3ivI'/YY=-H(He!Bm60M/K,dD|MeM Q{ޟz[ۻw=^w]z۬ʪO{򪪪NΚ{ROXQIm<\mO^]lq-zؽgR>M] t箮6:K[m gYzؽdWCX{Gn{XϬϣ7կV.t\1e߾ {E04c}31g}Dw=c4ۍwW0""Z5ǞZu{nust}_oȽ~bml*Ye^ܽǐ TXO ~lcmvnnfmH[6?6 V߰ۙWo$~mw~]vǽ,,m{D&;(qy[eUUTJTw NwJQg.5UUZBNH-ZbTU*Tr!EZlL\r`x (+ Ǿ XEcͶmWmm (t9$""I&?_>*m݄ۘS ͙Rݍ$+nL36fmKv76fmUf޷ ݶUUUTIEwj$m͈@H #?p*bUY88!kL=c1f<GweI}e}QUUwվՋVUUUUUS]a4* KWswms9uo7eͻ -žrݖm-mn%m KW˛cv[۰\[ ݶkɼLp"]ꢪ `8/@X/YmkLp"\屻-mIh-p6mosm[p +nbZ\݄g9sln{vZ+}ͱ-cv[mJ۠*g6췹a%m[hpZjwȣ# PԵ{877vmwcy 2g9sln{vOwwaUM~m@T1-^.mosnKEqo7eͻ^ﻻlȿ}J۠*g6췹a%\$ė;7www6uKmdx41n[Cdxgvm2K6vb-UUUUUSR-S( UU`*!em;fIfb vٷi%݀ VUv,YM5UAVܱBi37r6mIf`{mK2Y}VjM +RX! ^zm̤jvfۙIվj˴1bŋU41[DDjZ!wۙIվ%侞I}.=Z[͍W @/z> |˂X%ʋoH0Hk6k@jb {ڵjubqXbUT!TК%ؽ̙fd+7zz{Н ㎐R(8t'Bt8!@(! v @(!@(! @%!P .!p^!v )Bu:íCx=xeSKfoƏƍ~4Z& #Ǘͱ-Gi-D0^[{T^lU}}+搄%!((bP R`m@(lJx B (m@%%!P6!J@)BP HBH!B w]```bĐ !f,IZmkmH@$m$HX$0I !Ha$Ha$0$6$l $HmlCmkm뮻H "k[[Zmkm @$I$H ! !d,6CbH~޺S:CY+U3i*"}{ʪ4SdQSdUUULÅMv󻶯kjAݤNY\UUUUQDKeduB0 D @$ D$D$~Y;;:mUWPL~XJG@kرbŊf!;ݷqc{m}}H @$I$H0Đ dlSuugt*{v!׽tcBNtXꪪv @$I$HĐd6$6CګjڶwKh:YY㴜d潊XUUUUUME QUUpVmH @$I$6!$0llIdMg$^7~@Qbʅq{E1* 0PR4aT"ClBU RT( BQR%2 #," t(<ophjÚGB Z@ׇnyBEJ*DqOzns͞9@ D"邥JѠ$P T@'Q&L#14)&jP*jJT2z@:JE Rf0VԴ1S1R LLLL0Yibbb-jf*f*f*f610YiL&*LTFcMK01Rcea]FѰh646FѰh6 FhlL4m`Ѵl6i&V4m`Ѵl6FѰh6 Ff`Ѵ٤h6 FhlL66ڤ Fh4m ITPH}w+:׎TgyԤ;vuiqg\v5gtkJVf\ٴi3;h35ј41֩Ib$ ].6-m^$ovV[W!)Uݮwk:.vKݮIIK]VM;riwn뻮pupūmbQbѱbhZ6-XfhXchKFX2Ѡj,ihYBiRZTJTcdZ6MhF6ѢkFmZKXQ`5dV%hѲj-ba""*12b-ƶ5FcZd"ecH[miDIm2L$mHbYP٫6+j5EFSbFƣQbVS`ō"XԶ͢-hDkF-Qhh&[EEkmmQb4IQb4hѭ5Fha,Dl`T`&F[&(P@ZR%$MYdD,kJ$EJ 5چTXEP)55Zb)P*VmE-e)2B(SX֍5Z4*&H DJDV$4kFhѭ5ETY, 6KEV54M&+--ccccF4M1DLdM&Kl--61T`VՒKm0ժmű-VcIL̒VdKHIClSQ$6ScVa[VldB @iJBQVcS3+0(&K`6ͱFlkhlM#j`MF5f6mfUF #462biXK mEY$MmKH$ 50Z[kF ZћJ()XR2ѪfEEAhVC-(dbLKfYKJ$M1&j%`)eV+IYQ"MiTcFVV4ZQ"ɒ-,͒QLDF4 fI[c)K SUYS-V#LVm҉[m#Ie3ZQ"M֣[Z-E4M"T,B&-B&j1"iKi1S5[+cMlcc&%6MiILV,[YHK6J$LM H$J$LJj֍Z6iض!-,UklZbeFIYI,6KfKJ$M1,$j(+ڱR[jRdFXFIbM%,%iDem[6dŤ4M4U!,ERVj-fԴZțj̊JKld1f̓mQF `6*b40`͘lb,0`͛m0fͫ,0`ʘfT4@+ C6ٱ"k DmXR#UFօ#U"‘)-k3EA3Vb6ɬ1V6,FZ FC$ m6sSDDYhe&d @ WQ!5( "4o&k*)CfЈF,ި2XVQHA"4hBYU\ftV+D+,)Cf >JZf궤F$щ(d @sыdV+L@+2B, )LV( DFD4-g 4mֈՌ[F-E-b E!M^SoCD^lVR<68[mVmV[[VhѬmcD[xh z6VjbYFx4h Îp qָT  hVkEm",{Ste6V+2+VlSe)CHekBJZ`L)F:ճ:V+16&ihMlFYdgǒIi $eYeY$I$KJf3m $ZBR+QU0ZkHĚ6$1&IF5M5m%Qi65m%WF-DTb4Vbk5M3J))Dp̙85mJ6Tb+Ahd6mA&cQ!hg#3iZLbm2dm3mk&-VMu(L-[hkb2Z4h+cZ-ѣ4Ticml̒$.hdyD"D 4#B4DDD\* דb̙DQ[ԕ kQF(4QX%[5b+U(XVel7Xjl̦[3FkET[Eh-d64i GDmmX:jM[ngm;jZY&uX,MXQ4M,VэZ+lklcRF,6KVƶ-QQE5VՒʴ76I4IҪ2&YEQMAmʬ "6aoI䓉"IudD3=jթ4h!p#&I$"I"DșB4!%I6FMdɉh7 j+VnwV" O)fV6C{unwW I <8pBd35UfCVP$$Ěbd5mlQi*Mhb+DmYL[dj#ZK%1mmE+m[+68Fn4JU)+ZJjͨLa$ nU2Z@h U)0\ X85l|y$6Alxra,&[&LHն)Z2dm-KlmF +UfĔPem-ڍkF F ZS1MIM6j)2[V YTZKUv[&YInjL*V-[0Taa lb&! ؊l*[&4M)5M4,1%a*11h1Z1j563 c4A d0D&[b3713thIS(L6QEbm5Tه"lmj#lfFdjZZڕ1RH)`c$aBA#i&Lqɹ &Лlmf޶2dc !c j)4H@@MkDI4ЖjM%I m)@[0JM1A#0[kV Am]mn1Z \2" +JJ VUfD̉c5 Uln14nbYRR)M5C0p1UJ+QD$hINUVg 7 Jb)AѳjMcjlŋ(6hѣFIE-V4hѣIѢf4i44Z"؋b*Rk4c؊""TT6D,DDRdU"A$$ID(ժiLR#mFj͉mҋK4R#h4 KJ-  4A UBV%htΘ\לx+QE8Mh6LcƊB*3dսm^urHK4U-[2&YC$cXtDde&Z&D3A&@Xm2de$$&lEdRY4F5"њiH"0@XibM $ZJR̖iQY-scclcF5)Z$ M(94* Ҩ5E*@RJi +2ջXQ76g6jIYJگ+msjx0 4ReijFs&IIYYJĉ6 ԭD4be+cH 8VRa,VF!JaY["YZВH-2frMQ-RMWaqg X:թTI+y3cQc֐YDDFj &ڷ&I4!bBU||~?m{}[`f,vphgsphgsp7 rûp; 9m4DD6MhId&hh̀I$4q٥$ bLIWp3u6nf1Ȉm,*&&l~͸7kƃ bBaX$&bBU&DfbR`M-IlL4),""DTX* lʃ[&`c̢e(ִ)`*VbLZa[jb#h+f%ZR6ƨ+T"@(T!W41c11c1cc1c(1c1c1c1F1c1bcc1c11c1cTc1c(1c1Qc1c1c1F1c1bI$HdI$I 2C I$Haa$I&I$C$I$M!HadI$C 0$I4!HaI$i 2C 0$I$daI$IdaI$I 2C I$I!d$I&C$0 2I$M$HadI$slaIRi 2C 0$I$daI$I0 0 I$Haa$I&I!d$I&C$0 2I$M$HadI$I $0$Ijrc1c1c1c1c1c1c1ca*Ja*J1c1c1c1c1c1c1c1Ja*Jw]saaadaa!Haaadaa!HaaaVۜ[npV6ۮCn\rm&dHdI$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I+m s୷8+m&aa!Haaadaa!Haaadaag\rum!LC$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$Vۜm\D?9#-Qw3sH2T{KICM̬) ,wkbICM̫DPj=skq B7qݥICM̫DPj= C{UC{UC{UC{UC@8יִ4ڏqpD{6sr CM\m% i6sr CM\m% i6\c-;([MwmqPm7qݵ1B`;1mM6!Pjiu1 b 6SJmM6!4ښ]LCbICM6SKc4ښmLCjb 6S(i6HL pB1mM6!Pj{ Q;昆1CMr Pj=sUAd@nic4ڏ7. % 6w5\$JmD8nic4ڏ5\$(i㹪 CMW JmGjH"Pj w5ic4ښmLCbICM1mM.!4ښmLCi(i41CM6SMm% 6S(i4ژ1CM1mM6!Pji1 bSq߷[@R6Xԍ6 I$%I0%L6YfmZZ-)6m5eiV- U`S`0`S`0`@4 `i `ШH  ,I YI$(IF6o{)JYe)JHHJ)5M46ʛ-ѣS{$I$ P-l֛HRI$!S`HC*ViR"-AU@jTRʖPI$I$DF dI$I$IAI%PYi&`6hI)e%*Q J] UT_UUUU_+WsDƀ}fffzUUUUWǽ{z'>vb޶I$p;wp?}A|N#ʪglGߛUuT@P|`$-z!W{ט }63됓49ƎsZ (|gEyKݱƚg0U^;Y> ~MR߽k?@t9h3}1wSK;t}UUUUWǽyUUUUW?׿S[wnnyv`r\^ 1ZQTWǶ|9s{ވiJi#0vI@$IsI$}/ߏO}zz[x||}nS=}򪪪*{򪪪*A>mɽ5۬oLy$1۬>{k)'^fAǘnfrqnaS)োgW3DF3ήc"c1o^{= KiHq$I$!@E΋gws-(ܴp]%=>ww_ۛnd|i.66=B{i]]uslY1w.L4fbq88}UUUUUUUUUWS׺ۢ-:N^n}ӻwn繛*mmI--J\s1o[mI$I$Hm=GviN#fmUWlUUUUUUUUUUUUUUUWԶm6Ko0WŷM}-{kӴ𴶜޽m;ў}nx/x/ E>om5% =)VB\M}mnj;|L}yxUU^'=^H[KxWT?I$I$Wyyp>~?{*m&͵ '=*mŹUUUW&0b`( %Odꔗdߨɶ}UUUUUUUUUUUUUUUUUUUUUUU_[mI6md_[}$d}6^Pm܉)Ndnt$L$To[ksm׻dXa{Fn[ݲ[0P x$)$hmnj;ȕmm.wvĥûq#fdȥȬ?zI=i 1[_Nu?!C{~UUUWM T`6mmI--[t}UUUUUUUUUUUeg&wDR݅dJ\mu-Q k)5{mGuwls1RkBI:M6I$I ]M;pI$RWarvm$6O4|):Hm͹;pI$RWmK77JzfQEQ)-f' @!GМb2hmrĒޙܤ[mjIFrmf&jI6I"&'km[mI"{hVkmrĒޗ,0 c$ I^li$.2Hpm7.U|q%YMfI5$HYe\Ci)M!kfIunfY!e!IekckئY1iBg of&fl32f66@͙c396g3a,3mfaM ((*(Umfm Ѝ3Ff@o614FlI6dѤfa#LHMm4lhd2mlml3ZZmm--P$DH̘dmvlog`}a $~o;#9yv }ǏMTmۄmm"*-m{yH H H"""E㾾(I J'"P UT'|w___wY %dJLAmUUUq6Ǐ|6Ol8>{mLCi(i4ژ1CM6SKm% 6SJmM6!4ښ]LCbICM6^кckLSCk1mM6!Pji1 b~CQ@o`,dM%9&[4gYgJYsÁ0 %m: N 9%H<n$UUUW{ʯ@'U_M{{jbi4ژ1CM6SKmmbICM6SKc4ښ]LCi(i4ژPkSږ ژPji1 bSMm% 6W8s 5?mo5[${aYfa.E})#xVs YI$I00UUUUq6|{/&Wg{ژmM6!Pjiu1 bi4Pji1 b 6SJmM6!46Cm!4ښmLCi(i4ژPjk8s 5!󿟟>wDUDU032f ֨f`#3V#3 ZV#3 Z"$ Iff`ff`#3f`ff`ff`f1@1Aff`ff`ff`P f`6\q8*>޾_vmyUUUUUUUUU]eUUUUVHBI! $ H H#k@!Hl@ wʯONx0[1DDDDt$b͕UWMZRm)Km 330 330 P =ݶsqq݈vp'rU}oKxoh-<=jB":Jm" ]eU|]ff`ff`#3f`fnݹvۛtwIH_y8T-NӼ2m!OI 퉴U|<HJ *ɋ3)5LRQTRCl( DPED %P@ QPBT(P@$Kk`f@P/(1`Um((= C谶*U%i%m[GL>|{@ }_XD#J0&ʔ*i=LR4 =RJSR4 MJI05$Id`OԗmeŲkjf hFRDU) -SL`0[FZaiKL33-0TTTTlm3f*f*f*ZcKL30Zf4cQFa Lͦf L-0 Lբ&iI( iaFЉdh2F% Fh4m I I IH Fh@h6 Fh4maI0Ѵl6FѰ٤Ѵl4@FѰ٤I+JIT`h4m YhRJJjI I I I I6ѴKѴ٤h6 FhlL65hK3FY6$`1%JY `5m6"M h 2cK-1ZbŢ-V*&if,QbB&Z6"ƖXXb-eD*"E612cZ)!lVd,֋ElmEE֍lIVŴVɉIJ$BK2$2L4ɖFh֍ѣZ4[EEl 0@IIK-IJ-XEiFQŵEcVaM"Lm4VQQFTjZ,)hRli+lDDj4bBHU1%VdRSfJ$jm٩Y,  jVe i6I5V-E%6HHHHKl-)%)%mjhiIJk$j+-՘VIHDFbŋB"қkXEQb6EHDm-EV,F֣R))f&+6Pj̡i6&lSi4҉LdM&K-(#%l Jd*U60iEHYlM*0l`kmj3FRLTͬ` Xщ61ml$"V,[YH MD&*[-(2 4M E%-$%`ڶ0ZI"hZHE!-Cl#[U5 LضRIȤm2l6L`ڴHbFdղEjcVaMce3ldI5"5V+lhĖ-IJ$YlHHHSLDY6U%!Mō[hDm2ѶkFmdY65҉ifSVl`#") -kF #&Lj`-V6Mi$4҉m0m*cUhm-lصk[ m(͔Y$Xli" 6ڒ-mf5&H52J IXm-YYSfPVfk+$ l5jڌ`fEm-lll#jЊ()ؕ3dTlJSl&1ZX`14l6*c%#21lC&3fieZ[eVVX`0֢2##E6em fȆFƦeaS4|R*׽[qoCVT)(Zs)[G6mQl oJ6z)MlnmMiVJI(hƱ* j-)UJ7B 6kZ`5k-bUgb 4!Jcljb,Tbh6m)FhBІBoZ7f۬`6 ت1,UQV6-D[zRe-"Rli+0̡Vjl5i6[Imbm64HiZK62DRJ-bTVڔg"2SmkeF4cQ&ٚ6-F"EVRC"` Q*0lU*jhl6*Vll$HnM[j[hPAho8ʹU匚1V5,c>DLzldSjFڪkGz:ѵMbl ZԶ%l-j6M&-"IJZJo C*kZs 4F֛8c)LphpmDKIFVъ1LٔcF42JCc=VJlhČ#6lvRj-h%m%, ֋X 1QE("1Z Aѓ[[UUAAƍѵ(MHT[ȣi(QhQM`ea5"$h6b`5U``Š֨0mpUJƍhb[mVJ @Ԉ`!Q!#Db7]-%%(-(QVNdM6C8#c*mU ʕl쬬%4TZ F&j-hm,E(5FRi5AEh6AUQDDɓ  RJJJZfaLI2m[(AfjS"2 cF1bњ kI(iՍjJ%d H31icJ#)I%P-dIFRTړ#VVdLEFb"5QK%ɵZhѦDCJ@Q dY4dɐ%)"RlȊ@("K%6#F"&jmk"""kve+Aֹch;[dhIj8j4LmUQUAUId4$l$i1lHQ+aBkmA&d Jl3i2cF͚S"HLR֥XXJXm-H1R-ٖV*6ն[3rDj7vUMlf-@JBT142"#,fbK%d$ 6`0cUaaEUMVdelK!b3)fkjVղщ4[- lcjf-kQZelVD3Llh1F-b*"*1FƍeJ-"mVѢ*"ʣͩMbVdl6[Ej™Ccbՠi1KQEbƂLi,k[dɬ"kkcj6ԛ֣ccb4h,C)͙ݻo!a$i 2C 0$$daI$Iv0$0 2I$LaHadI$ 0$I6ݴI$$I$i$2C $I$daI$II$$I$Haa$I&$0 2I$M$HadI$C 0$I4!aI$mc 2C 0$I$Hd!I$I 2C I$I!d$I&C$0 2I$MI$HdI$I 2C I$C %I4I$$I$i$2C $I$aHadI$nI$I I$I4!HaI$i 2C 0$I$I$HdI$I0 0 I$Haa$I&C$0 2I$M!HadI$C 0$I6ݱ!aI$i$2C $I$Hd!I$I 2C I$I!d$I$!aaI0 0 2C 0 01rkmܚw $I$I$I$I$I$I$I$I$I$¶¶daa!Haaadaa!Haaadaalۻm!wPۮCnV۹5Mm 2I 2I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$ wa[n[n$2V۸C 0 0$0 0 0 2C 0 0$0 0 0 2C 0 04pr!wPۮCn vɭraI$HdI$I$I$I$I$I$I$I$I$I$I$I$I$I$I$CnwPۻ37m_HBP BMi)BP 8ݤBhbvm %ZBq{m{om=СBi6жZ&m eBi6ВZM&m!J@)BP (bP )BP (bP @^HB^@P ؔ BR%!(! @+$IۺXVj&QؔqBi6жZvĠZvĠ[BIF%F%Yfc @+lQc @+lQc @+lQc @+lQc @+$I-lV1Z1[m@+e1[m@(lJ[kP -6Ġ%a0KUiBP HBP BR[$~ބ&m eBi6ж[@ml&m e&C;h[-! Bn1I&e!4h[- BI!4h[- BIٷyf 4@B l$ HH0`hT$0`hU @$ h X05+F 5 ͢)iDBMMoݳDDD[-I&`AĆ$L")-K+k~"$%)R3H#Kb"HlI$` 4b M&T4"SP00AMiT*d*U4,4R@)DMR5JI$hdi3)lI$I$I$H&[$&[$JLMI2A$I$I$I$-,li&f!J3`--*I&lkkk[|ձZYkKgtKeo**$Xt/tq{BI~]=[Io}ױ%_bK_bJ߾m____W_[j[دWzſ ,:.c] Fc_XFg蹍{*1}w}5oozۮKvvIDϥ痏b<^>"RLj#$HzY/e򪪪'}56 c)Dh՟_4Y7h!t,8qyGlIKf-ds**$**$+{zjl^'箮6BG] |+zΓؽgI>zh^=w"ipL8 >kN[q){G=obL~/t\7{^]DDk37t L3DtƂ"#_pvs]_'뺫w=:=gg46v_qz햅ggޏ^~W/sLX PIIRY"boβuI H6dR) C$}zRLe((~^^Yi`d,b(>?|{,YbmʱTsG͚wvwueӺ[ImUUUUUUUU{UUUUUUUUUUUUUUUUUUUUU[Mbz>y%L4헒N#d^$ "kW^v'n6I!"L-^JN> .KI$|A SovdOd; Q'-@,qw]=z9bȩe*I$I$ܒknS׺H$ w㮟t \݈}72{H?svk֬>mvw &i& @6i$I[(I2Ja&mmbh`d*"&p;KmI8.H[m@ $%%r$w7r\@$$XdOS#aKh6 E(A,1(I$Ź$I$I$ܒknSm$I'RI::{L$Hx$4Z߿|I$N(r$M۠4-DS 6nmcu&S/so.[mdA@]ovA!$$wS"G#UUU[X rIeOw7Id$I>{%"z7$@۽yĤXZI$ 7JE~Hwo8 ܒIoU4oN$QAc$I&ly8I$i$וM7E[Ӊ&[}w$-}IUbmdI$mI'rJ2oN$i$nf8z7$@븼8pnH}w(~_UXȏaWy}$de/ޜI6TU̞߼~I$MI'rJ2oN$mmNe/ޜI6TU̞ߨ7ĒI$kow$-}IvH}*t_E8xQFA@a&%h-I$zݤvJoN$mmNe/ޜI6"};c;$II$IF[-ēmI;Qྋzq$ko ,U̞ߨI$M $IF[-ēmI8/]ڥmO)+oN-ˮmRz $ŹumVޞ>>RVA$[]ڥmOuI$mnRIvHʪ_I~?u$I'I#lNηtXLvmI֤I3u鍶km nBU~I$Lvm3;T[I'I'kiܗv$nI;\vI6Pucm!7bI$uI$m:ēݭڇj{$1m0 -ԒH_oI$I;wkmڤNW̯Uݵwzws.cw3[[[}׀@ #x |)͒6$km[me |(`H m$`XL$YeYeJؠP6qqt( @.(b^P6( @(B\m{mv @[mzVޔצqƚiI"BJIi????>|ljFUUU/q vmM4ff`fC3 Q۰3foqB6FhF"@H6"hA4b1 F 1A 2l!l$mJ֛V iIŘYZp,÷V4 iL6R$RDu)Ʊ&KnI.j,&W9ڒHubI$]b$X:$]u‹9$sɨj,&(39g$sQm:S$HڙiKmZRٕf,&څښ[i H2[[2ѫX,j։Fl[6MhP4ԅd+2dʌ24lelQmͲ)Y 2S1m*3jL#l$VYkE-Sb6 Am5ThŽ2ْ65mRKieC&bLb[FŵEMT4d HQ#2dFfItS,)[3#D( Q9lJi6 &ZZ* Fm*FA [s[]6m(G[u#7Fېbld֍kVU0j$mXM5VPڱa0PڃVU,cZą-[Tb3K1%f[6me+fI6IlF2jS )ZjMmɁiQJMRɭ,iW465h&ʕJ1dNNĶMLrpDYR1")5FI4XI+p6Մq$mɜ$'$KivI*h5h5Qպ[)729#NeUBUVš+4ii4$ c&KsI$p8knp77t:1"9ӶVBӦؒչNLrsFcStLIڥeI&!@mlRT,Y[n]Ď $DssFe6HmHBSkE2ZjEmMhI$5mb6"TB @)D-HJl 0 g_گ.mGy4V޶ut5u[~Uh$H$R<[$Wgf3U]_Yx*hbP HB]%lK{n8ooonݥ\lJ/@(bݥ]۸%](bP I%2[-Id%CAU,*LJUUJDj_DJUK/A%JԉPU W#sNb1 I+qΗ*MwhYUϟ>c_;  (vݻA~$-+%WϷM$M$5}շ_Y$:uO{ļYx6ϻ/wu7d*>U}eWǽ@P B ؔ ؔ ؔP6ĠRP6Ġ%Pb Cq @(P %l>Ou6Y#kfe~Ydi5l>=$ =`| '?~I%@Yx6ϻxȩ`d*>{U|{H@)BP (bP ( ؔP6ĠRP6Ġ%P @ (6, (BP |gƯX.ZrYgiI !$!$ni????>|ǎUUVl'sUmm6`f`ff`30љyIC⫼GWVZͶ Gj/U|I {>շ_yU:Ν{{%PW}ܮ{e6@/WU|{H@)BP (bP ( ؔP6ĠRP6Ġ%P @ (BP Cq @TWm֣C+oAd`i6~U}{Ngwt:Ν_{R^* *dT _Kx*ii͆Sa 0ъl0633aal601M Samv}|ZՀYE$  wwwwu`ff`f4fa !fa0-jљf֭f(30 L f` `ff`hљ30fUUkUZT@$ D$@"@Vue%+<{򪪪m dUmlww~Q釥76y1UPWc0wۻ UU Mvmi3S30 3@!30 >펖i^l:KaHY#Ԃ$HV1 (F1!4{q!a2*^>gL330 3303o[wݱӺSu;_yUCIƁtg1&{ݷqg l^˜f)f`ffaFff^۲ջڻ>^^Wїьca; 6`AUPىӧwwN@$ D$@"@e5(.eGS*FP/XmژbFUUP#a ՘$TfQJRC!"+H̪T(U!%djkYmXV|`> <ӝ@oCgþ;9 c`|#o;>sy끩M4J44eJ)M4@TH&# z&i)(MldT-UB 3B%S+3ieVfLS0YimDʥJ[h2$HjI %%5M$$$LHa[*ڙm`գ[S0mf`i6 h4bյ3LhA1(ŭ! EJ53%YZVlvI(,ʦYffR#$͉MM4M$li$̈́I&&Ild[QLQTbŴmmaeA-Mm$E[TmV-d[*"$EJf"̩3ff"mbPlIf!#jef mE6%-ģh[+e-ж6Q3!fQLYLYC2b1ōY,j,,4j(51MډlKj(jYQ՚&`Y`YL I6lf Q-lb1Tck[-lb֊mkFэhi,[k)6ĚImI$dLIlQXؒ4&$mX,ZcVcbl`kRʦh4DHf"$Ͷ&emRMFUVm3U(mB jfa$H,#1Uf 1liRMYFbmmVB#KKZ4Z*!VLh$L&Hf$Ͷ"D#mUmTQHD(JBd"iQXZ+Xŭ!MF5f4bћMlclF lbb(ƭcآM5cQD%VԦ@HII2$"BL#F$HI3Ii4 II&LIĚLI$L4IfaElVmmmkZhԣV&[mFS4mk6Llk[l$di "D03"ę2D"h&HEcQf5f4HHm+h,mhF4m ƴVh,Z PXVkB$[XLH"$ƚH2ldDm&2F2$2"FhlfSm&)e6Ʀa&ih֣kc53(%JVڛf$m4D$CI$4I$ 6imMVա"ij!e4M5cQDыFm6-iXF-`մ`QQE!MF5f,FmZm&L"DȐ"HѴI&A&MH2bM&$bM4"dIIdIdI6چĴm4-i5mlѪmQB2ڙ@H6DFMi"H&bfS22aV5Ƭ&b%$-̡ckhVHD5mMLHLi&FͤȒ$DČ i1bVJDER-T  d46Ue6ȒdI&L"Hl$HmF#b$ș=V[MV&Y1cJV0fͣV0fͶMYamdiSZ2a5i5e %ɣk(2k(1&M$I4lI4Fi$Iњ4I&MlDFi$IYVU#icm Ej-Hfڢ6h,3XYj&$"Mid3i!$1 H,lȶ֌ Lk# h-"eYa1aXfe ,̑ɦ% a1Xe CY% imTVS%Ro㕩I$6B 4ڲI&t ҩVI-1-%%%nňŤ &zJĒ7DD!I ͋F6DhʠXB$nFhFB;ji5lcԖMb DI&؂$5II%Dj")-x*#I$nAgmU&68Zli,hűi,$6d`$;P $ۣ m 8lIZC($l m)61IJDYZXՊbB -IUъ RIi,FbKIR[5Ylf(e-+,JRl("J;PbI"!YmٷeaJl,lj՚RY6bѱXj6Kl`bCjK$KI4P $ۦ!!!7fjmJ%,S))[Mlm6؃ChRII-1F*1UBM HEmBYj&ŲU&*5& V$b4C!mf4Dё8MJ7Gphjm&ղ 6$à ' lg-Y&mAJjڍ&"jD6$OBIaF64c7QY"RR,dыQh&lAJ %IcrڔÍ4B4&DhD"27kXT0`I$Yl[@I&Ѷ$I6)$E42--SjKP[e*aY3HJ̦IFVSVlmb֋Ik%k6Y+ABIi+I6dhX+(A! "I""ʪm[kw1I*2Q*AV $E`%DRmSSb45I-2dD44S*ŕc` J$*+ K,lV%f(Ąf!ch-RY6صQ%64TkLidMpF 啅(̥44HFЇlm#ImDIclm]enCdDbm,lL'dR7Iʓ!FbWWVRH#2%D$i$phlj՚ITc4ppہ4\7  Fm JZIWp%eyIITZRVSDiʓps%T1 bFVY[6f4m%"YJVF6VSee %EfQM fYYLQP$$Ǭm%V,j5EFѭfā4HNel)8')mCVHHdLU$M1Mfx NDf,Va3*bj歖X`xG$;2 diQMFFmBM$MHIIMhI6Li1eh`M2&!YSҔSFBIdIi$jRHѴ!#D$DbU6Iқ(+jijHIV $b5%%I$ֱ&V""4!" Y $DI7)j)ik$Ac %-pKHJJR$RI&7DQJK% mH$ k%m6 hT e`$)Ij2`DdʖI*& TRI 4Dr4hFKջZFZ"mH$I76VK#fM&i5%-V#"bCHJ-YDSf&b-UP1D`Th$i$&D,jPI$JRFV̡cmbQXh545`Ii64*MR2,ȦFaLAPVh U,Ueb$HI YXDfH%3dhR"њFi4d$d&LDH4$D[44D-KeBLmRY4ԋFh mMXIZKJdH4$D%fIY&( *KnblbTVʦdBM&i0paZJNelLW qUeJDsUR6lԡD)RbD66Ti$&0le*R&HSS"42mJ[iJ匚1 +%Jl.)*ai)G 6kIň -IbM"Ilh#,5ʼ6}yw*zS0EɓUjk6,Mc- C$hdeMbYcIZVC[YjjeFfM66*6llZ-c4lh+!MCTM64h5F5ebTcZeQlc1FŊ665k%[+d±, f[F*j6RE2cTI$-b+$F֙RXִDFl[P؋b6ڢlSMm0ڋm*KAB!BB!Ba B!BD!3BB!B!3BQL&ffffdB0! Zc1c1c11c1cc1c(1c1Qc1c1Dc1F1c1bc1cŭF1c1bc1c1c11c1cc1c+c1c1F1c1b1c1ccc1c11c1cc1c(1c1Qc1c1c1F1c1bc1c1c1Zc1c1c11c1cc1c(1ۛsnm͹6Є!B![Lf!B'tntntn*۝*۲s&ffa3333333333333333333333333j[ c1c1c1c1c1c1c1c1ca*Ja*J1c1c1c1c1c1c1c1c1ca*J1c1c1cUl1c1c1c%[ c1c1c1c1c1c1c1c1ca*Ja*J1c1c1c1c1c1c1c1c1ca*JwNg#V1Z1[kpcJY%Z@%J[kP -q(jXĠfc @+$V%!(! @+U0Ie?V1Z1[jbP -kP -5](m5](m5a(mؔUؔecJ[ecJ[ecJ[ecJ[ecJY%{+4Ik!(ƛwi6ӰRqI&M씄!(o|vvPW96PUq(]z۲ڹJy޻vwJҪ>Usfٛ> |Cml}F%M-ؔUؔsBi6ж[jbP -TjbP %5a(m5a(m5a(m5a(m5a(d֐%!(J{!J{ wP @%%;@( w^HBP BR%!)oѪտ]h[e[`PC,04@$F$04* Bi$ "H$ X 6 H`hT@)@ T@,-Hf2 JH)DDAP,-@AJPA@D,Ơr"" @PahX* HX @@ ++-i[`P HJH3JkCQR H H$ H L&2K4-6H  YKRl77OϥO{ʯO{򪪪~ ~^#G I{ꤍqݕTߏ{$/9񷾎\ E2"Ɗ6zΊWs׼c{\o{㶾"9ǾZy?9}bUURTEH$W䘒${Gsϟ>m8l!P!s{9wk~f bi',1)zg t<Ň=uq/[_]lq-g+zu׼wwYw{DΆlg׮6lo׮;#v8;U1 _1gٝ]蹌 w"Ab`Kݻ_%{p뛔~@F4cKٝ]͖ҵmmd9/{zOtع\={o]nkOLpH|q(q*{wq'*'$Ve˿}=}&}޶9.{mɷwEu/'y1(`i5Yq'لLf ߚb`b]8J}X4??fB֪W?L4bcig IK$UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUW/>i]|DR6[_ybimsr 盞|sܡ/+ZMmſ<< !$ۙ8x9l!%ЌulvccE{L!(o\ ʳ2‘X6g<|i ۶aU^VUVVVO)$ILɶ.盽m <w]wSc>]wSўOhVv w,RH:d|92I=7mot$s'v6E&4 s3{8N&ݴO-̲I7/Ž8*.XU=QOv.E@Z1[;2$ݽ4ݔ<7cd0nǦ| $cd"hf >Lq̝لv=7mLq̝لv=7mot$s'v6$ި@ݷ30I<7cd$h[bE-ݴO*W,XEQ'dS@$ٖ)$],MDs'va$ݏMDܙȪr?~bsܾz;[$12wfMݴO.B;$#v>3UL~6blqnۙ$12wfI6G|$<7يܸ {BI$!$&tZ+C(cm$鐒UmǦٖHvmnːrŋQ>fB.{3ilnftRHmI7x\b(O(#t9B褑<:ۤenUdi2F[/wJ\FZ,l !\WwTn-:褑9$_[x\b(N*"@-|,J;==4Bt'=޾I=O{lqyН8!@(! 8 :@ HBJBJ@((!@(! p(JBR($m^1kxصsׯ^^4Oj0j6ij袋VOFFF1F1i:s(y$H @$I$Ha$0$H~\\}D}EXTlU`e)*Lj@҉F$4f#QM&ɊdJdMmԳm`ţ@٫S+ lQL+fٚZkUasT48FZ)LYYqR+QK4QUB\EUبEW*ԔVE "|W=FcK/vǼ[*.iBP HB^HĠRRq(P )BP )Rq(M@!(! @(!JN]uI_b(F*MP( -"KԊ UU O`{!ER+EW"QUt/ezhһnlv+?{|秧Ht u|VhOBz1cFn㻑lvEU\;H @$I $Hb6FĐH !9U==RMxeWmb^Z6l[sK[Wѿ /fn]OTSɁZ䒭c g#-фa %N׸9Kr!{eBRm@.HB^% ()BP P6Ġ%`!@$!X)BP HBP BBO,IbM}϶zSgZR)D/9q̕_c~=B0hƚSwnwwwC7f8ETG[OOOOOOK'NL}-ȇ'{ef$,F$,F,I(X!(V)$lP$!$sl&EyG#lwM[RLCMQk-X{&>uǏ<Ǟy&̠"+2c@@$I$H C ! 8so6%)JP"""""""H""""""$"""""""H""""""$VDDDDDDIDDDDDDD$DDDDDDKYDDDDDDD$DH""""""$"""""""H""""""$"""""""HjDDDDDDD$DDDDDDIDDDDDDE""""""""""""""""""""""""""""""""""""""""""""""""""""""H""""""""""""""""""""""""""""""""""""""""""+l1y߯l?zޛl7*R6OM5T^旜q2:~=^~Oh/4kW{i'n=EU33zzzzzY=wg#np}{ޖ{{!H!B@ @6Ā`! '@P ؔ! (bP b@ 6 B HBP B@ B@B}[dtfP2 5}cz~Iz)oMGKN}s߯2U}#ߒ Bs.={ޒ_m$ǼȪr>FzzzzzzY=wg#nD=={ޖ{*t!wH@)BP )B'tRq(P )BP )Rq(@!(! @(!J@)BPo ^X[~Ϗ}6 C,I#abHl6F#dl CbHBHlI@$HdlBk[mԐ5$mĺ"$D H;; Cmk`$ d,6C A$H @$I$0$H~<;:Sie:K@UW7[<nj}e_=UUU^S9TE2*ܪg'yl6 6F#a6F#dluuu6[ƫmWgtCw$OC_Mڽ9op|:p/eG@[]Vc `E"* [)l@Q"Ikl5"TP%%[cl4ű PR" 3:^k>}ݷݐv3HkM1Nkþw>8{ r5< RMbɲ$ T 0 =TH*~2 I4 =McP5I<@6JJBDL`0i6Z5Y60iHZB T,B%Lf 3L"iƣ%S+3ihŶm1Zi6f F ш4b F6֦`LhX4f4cQFa4b6-4m3h1A1(ɬkh!MF5f,J1jCFf5D&k!DM5cQD-)%iDHI$h$M$4IM$4IM$$Ii$٦I2$dI" "HѴI I2i&I2i&I2$&$bM&$I HM$li$m4IM4$LI4M$Hi!4mig3<(RTB 3Sm[R*Rʛ(PBkB2ѱbicSd[Ul&ɲQFتh؍TV6Ţhlm[B2ѱkmFE!-)!!$H$lH$ ii6 Ȓ$L6H$ D"hF43H4$H2A&KV YM666666ՍlX65f4حB$[djSjbXlV[lm!X-ijlj5EmѤ"K5bQmZ4IbI-ՖR$LIII4$I4"dMMC$Ȓ$DDi0$Ɠl"HiaX4ѴXbŵb44M4m,Xik6PB -"6ɬZ6՚ ++6VHkj5m!YL"DɒliF6"4D$#H4#"H I ii3D"EI%UXcQ) M*0l&"i!KF-60jJ-TdDM5"Xkhű#i4dI&D $LM$I3i46$H1&"DȑIM$+ 6`4E43VJZXmi"X!5 PXIdȉ$$D"H4I"Ll[V[6+f"j՚[6lU6LfR0f l$53b%bګdMjIYYVdd 3ZfjMb֍cmlIeS2̳3![mR+2R36[[$Z-ؒ˜V1R6*[)--mQZ0Vbƴթ͚M$4I-J[UR̨)F%bʩdliīc4«+a6h0%}Z2mLPh̫*(i3U*Jmɱi+PńX,ƒi i @$Mѱ6ɦdũdV2V%%%eiPUɩWMfZ`\1t\8bZ+H6[yl%ʅ(I&!y2%mB$o %mL$l%ʅ(I&,7*(mX1Mh,ѢUi,ZI%)61b)$JJh(hIR[p V$1AgUlb!DISj 5 &+ea-T)BI6! $VMmZ0`CjK$IdƱIVdղ@ᡡV(i4l7-Jj RY)$ɱJ$ML$mrS*FQZ hhm2Jʒ,YlEIhv,[e (İVF$gej*M%IlY@6(ei&"$"[TUHU*HtcX* Y%[%6I+nMIp2l%U,IS$n#D*KI("In6nM+&fp*f5%TX-Ռ1&*jdA2M"&&I$51l56$†ĘPؑfnԭU\* cnXV-ʛR.L1.!r;!e e1o93(+fXSdSjVI ᶌ\IF 8p3NUXP%pFeYMM4mQmx-IjReMbʥce4jIY(2̈)dI+ '*ڵf@ BЍ -#,&(͘ԫKm!6Mh5R2Ml6UR%JX%h6"ڭ4&MVj ifDI)&Ή͊% FI&#m%٩[lLZ ۜ4c` S$Kd0X6,YZKYAY$Q+$&V-U0҃JD)dW#"'@BJP6]vHd`0$ q uwc @+lQc @+lvĠ[kP -5](m5](m0pWlJ[eWlJ[d#XVjXVjXVjXVjX_U@FBHPP6@A` i4B F0h[m h\@( ""!A@P@ @P@ Xb$ 0 3@@@@) Hk3 l, @ ,Xbƣmh>(KPB `mmI@$ @$ @$ @$ hZm)` H  VͶU1PuV*^9]s5$~ϕUUUUUUUUUUUUUU}et^|I踽ϋ{Kl./t9wkܤ׹%^˺=^z>+/}ƽVy*7io5gkV͢\x@|$*I={ʪI:}k{ROG|zh^/[m g}G] }=JsJ&JW毼9w@p8p@87{BI#M] /tdQlsgy8<{V\9r.1cs΄qع  0 g9\98Nwv'81np9܀py\{m]ngFtaNEh@RWD W+ J㜮\U*H򤞲YUUUUUUdUdzu$IHK))j11=߿t$ ڷt-ؒI$97\\|烏M҈N,œh!dL 2$LV@i$cI C9xRO{Iu𤑽I$q~>o^G}km$ KjJi/$F5SWIߋ2t Jpx3 J0x0ӆ$@oo6<;$`C 7gH}T'Ï$H^7nܮ\m$/y(^i'I$IUUUUI'd im<6m\H[[f$6[m$I$= yɦd >-h 0P!r_ I4I$UUUUUUUUUUUUUUUUUUUUUUUUUUUUUWllt{RT 4nvm4U$-@7 AI%RLIBHɒT 4nvmc+%., ( @ @DA.%wHK}!+A KaDI$,0!3x(^I5&ml*UaUUUUUU[$ 6 w͒%w$%s&$#DFI"$I{{{UUUUUUUUUUUUgdeZa UlҬaML4۝oso%mIAIvKvI=жBjmBqoI$I$I$I$e%Ǘ6kE8$II'>wwH^aqp@C A A~om8MM ܟwt$II/w08tt۠-"JI,[ Ēa ARx,J l ĒI$v%$&n$(IF`n$(IQܒID$(;t-$I+mJ9;Q-۠I.ݤII-_&c۔ Ŋ( A $ĦIpܤSmn n$wɘv%q[mQɲJ3-۠I+mJ9$Frw$Q$0Qnv6[mI$VFrw$2۝ Ē4%^$ѥI#J9;I(d(;t-$I+mJ9;QmIv"JIݒIb0A w asPrh(I$]Hwd8ksAxVFrw$2۝ Ē4I$iG'rI%Lne^$I%miG'rJ3-۠I+mJ9;QmI[mQ$4$&IQnv6[mI$VFrw$0[sAxVFےN-i#m>Sn$I#m'Xb bd&0l<nI8.Inwv%$3Ir LaÄ Al6nOI$ t)!M훐mĒu;uz=mAI‚0L aNa9$bxAӫd;mz LۺDN&+H6I0a@A  Api=$lO &$v7ZAIݭi[;aAIpÇbh 0azzI ؞AFvִנۉ$x>E=Zlo-x).sf~gOW^;6{)I II%  %(p '"C 0޶mx %hqNwqJBRNwq ! @%!P %lP %!P )BP HBJB)B\! @%!P>[N[NWXc[Q___>sǏ)P}AI II'( !1:20!UU@<6|@$I$H @$I $@$˜.\= RIi[I TQJFdT8IT}RT"`5+RC;ݕ[cmFͭFƩmp#Yϟ<|Ϻ^]dWbL>D N2|MUTЄgSd_Yx.=.!J@)BP (bP )BP (bP @^HB^@P ؔ^)B)BP HBP BRt뮺UzaR*+%!RS2ULUN*")X@@X JW.A&b X RRU ԄW8 *IB|QD@c;-Ug7{$H @$ @$ C ! !𥉉so}~Wغ{Cҵ.گ,/%,mf|#^dROyNUM},Fz1zYHOOO^6Er{PBĒB% #e $JP989 }~oϸ>CK7ʢF+V;`܉dMyy;;z$>K0jI;/dUU6E!BIHOOO^6Eޤ! @(!J{lJ{!J{lJ@(bP )BP (bP @K%!P6!J ! !J@)BP $YI{L-};p~[ѵ֨ 0M>Pdx ьaB1gN!FUUP^ ]mi$H @$II $I[W"""""""H""""""$"""""""H""""""$VDDDDDDIDDDDDDD$DDDDDDJ"""""""H""""""$"""""""HYDDDDDDDDDQDDDDDDDR""""""$"""""""H""""""$"""""""H""""""%Z$DDDDDDIDDDDDDD$DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDJ""""""""""""""""""""""""""""""""""$V~~ߏ߿~z;|AKI 8Rٷe3Fr|>$ᗃY x`|@IcJ9$F/F3OK) Ⱦ>]({{M4ki 1ė1(B6Pė1(B6\1q' JP8窮ru[Rf }N]jP;򦖓mzz7.Mkw;y!x/Dd<& " o%ӺI;/dUU6E!i%!===x˽%{˽HBP B ؔ B ؔP6ĠRP6Ġ%JBmBR%BI-Ϸ/^ߧw^vyww~9s9ĐbHbH9q H H"ֶ C !HHa$HXؒ$Hd0$Z !-m$;wEE[ZmkdkdkmH @$I$HX$0l@$K)!,;"[<Ⱦ_{mUUU6EUSdUU6EUSdWzsۜuʚM˛rnKzRH *}, &!gwsʆAUTwtӧwwN@$ @@$|jh!ӺNXtIl"M> @Q cq愐Cq愐r2FIa $i-ZZWh,Z*KETVJ1^;v̨Z6aǁ6ͷ833ԕm[ T w6[[wWe+TY"Q#(j6fqe<4ͱgSBҒ( $Mhl[[bQ1b5PV][1FFتb6,)6ۈCJojWmm䩡F1QQh"nbP`6VmSTn0bac!0bmEYц΍j6Q*cj-)HE9><\ڵ lکd͝b(ج;6Uxy*ǚsVKlܛk]ޙMMXo pppltٱkVU-ج(jmjIj@JljI&am $k5X& 0[Ʌ,!dJ$MU3AmL!4,EUaVZ0DD` DDA""0b "# #b""`1D`DDA0F""" 1``DDA""0bA0DD`#DF A0DD``DDA""0b """"0F""""#`""""#/1c7]v1c1cwc1cu1c1v1c1cwc1cu1c1v1c1cwc1cȌD""""""""""]c1cu1c1]c1cu1c1]c1cȈc1c7q1;1c11c1nF""1`#DF A1c1nc1c;1c1D H H H/wu62' 2'Fa8a8a8a8a:0ͣ цfl0ͣ ʭjZ06UkFʭha:0͆36ff ׮1c1c1c1c1c1c1c1}/<뮯*Kme P\2H Z[HB,%ve6[HB-]u[xλc1c1c1c1c1cьc1c1gˮ--!@KiY#JY#Jm7c1c1c1c1c1c1sffцDD n%إGB i$#ŶإG,<[z1c1c1c1c1c1c1ۻ=G)i$!݆[HB,-r8 yBgSked[kбKkmbmj7$;l$i-9&@zhk}{D i$9Hu Yj#BiC }l8m >F}l{kEnUUU7 0޶{'gXfF(HA搐 ڿ{{>zmmb)mbmZ-V{Ğwm#Mkڦ+k ߦYmnkYFZb~$H$]υ$R c9I$q>^/Id-6"\_?]ӀMUw^Q_x 6xH`>Cmml.dϚA C#@H&Kp5 N!v};Kě][u!n-j!b-VŪXmnI vH }uKuݑ6ǷTr޹û{0I]$D{}Z1·FmۚFi$mamEݎWL!0 Ւ@MA1M`6H\x5rp8i%cmS E۶YmnkYFm%cmSnmdmmmdnkYKkj.m6d%v9_mܘCOUnY >6UHKp CSi'x9(x cjyȸ ,rG}"@w?m0H!!6 mHiʹt7nBCOEE$UtPkNR@/."׎*I!lK1TCdؖc\$-Cdm'^ E$UdP\6RCOEkE$4ApݸYI$L]66Hmdm$3]tI"ZmijI$6Mf5ʒH2I$6Mbu逴REWjkE$UvfI/.tYwdCdؖc\$ɱ,ƹRI[i$ɰLN0%I"f鵑Duk#i$FIe6$fuhJ\6gV$YMI+ %p톩,kn[ VXܶ$ $. i1QA*c[d$ךL$Pz j)9$JVrRjH尤ԑ)I"V@j ema2A*ۖd$י`7^{ ? 2 Ad?<[Skz]EyyE;9W]h,2ێ޿~n_ $ A H/oy篻C>`mw;#SmzF @ bI鱘 $[ أ 6 bі1dL3lLfF6 })"*HGDDDDEb+%cH%a-k %Se&ղ́EѬYFbLҙb-Kh2URV (mtpĘ#:2[D$Ha,ի&l эɶf+U9A'JAґTjQU-RZRZRYA&PI b$@| m?_gzo[:}k|3mx+P{ 2׹Ԟ0ĝ{<6@$ @ H@RJTJMUUUiKEBBSAND`H2PP '҄zٲ6Hl&6mf33 C"f46i6 1f40bb mͱf& d i"-4i6lYKKcMlmHmLPPVةjQm6llD E{vjϚX6ӣ;$zILl۱1KHE ݶE%i]|mP6f#1p``}};jM":<p9~ݦ޶^[` o~^zޯ}ݦzbyu֯W$$n ͣ ShڒI$0633h$KRIjd36fgdZ0ͼvuoXml{O~y綠h#SrKXy=u=h[iyNҺڥ;C=h &`8aI!I$I$`8aI!ڪ @$ @$ A L h% L `L b`- H H &3&m wumD`Hm8mI$Imi$nX pkάb3m%\ٷuk1 s:bcm $ A L ~5e.hJ1.i5{k$6I5vK;wm]ۛKhAݵwzci1k7& _mom(ħ7׳:@V|fb3Mu}wwZߞyy@$ A H@e5fDGSF FXTXRQ,+LȨٲPAYh}4{ɽl|'[t$^繕8H !%*h%H*{Tڨd'J)i II SC *4rgG:秽r5k+OnNrgGJΎ+:랞rgG:秽]ܬt+:f;BEm$PBE ΝgGJΎ+:/3E $PLHu{BEm%IFvzi(ٱ5E (QB2m6& +^xkks<ѵ\ѵ\ѵ\ѵ\ѵʽg+据j据j据j据j据js<ѵ\ѵ\9מcs6Wt<ѵkW4ZWMp\\\\jѶ4^yUUhě[SjmmMFѴmcieZ+I66f6` [+6jbj lU&Q` ԚرQ` V*6m&kEZբŢŋC)jmk&Qj,Z,lX҆حlMF6ѤTXYMbmCi*6Qb hصi0S+S)e2KN!LQ*e2N&lRSRl[lYMPƖQeFR UF(j0Y,e Si2lS ld,b YѩVjGh25FQgt]Dmm*6qS4JжUlIl-S0fE-53Y)cETlVhhQdFSemFSe ڙAMEP2 25TEY(+2Z5V1JXd(̡E3VDDeefIXQڊZ+Eh)j1jՍF)cLآٔ-----EEe̦DQjPڊlٛhJ6y$@jV4hmmiC VRvzJ,jm2FtI'gh@9mM)VC\hjSVhSs5Ujf򝩴ڛ9)ڊkdhFwm+YQL٘A\l͛e6)$)LSHH}&IXjbB-hT&*Fc@ 5FڋEe2+6o[QTx6fqj"^j-TZ,YmUNaYRdѲ0MEfZ-hk]JdX'ȢV)eLXH+*=a^l֍4bƌEmma JZVs-EQ,mbرTbc-" P$H33 س.кX'GǏ\f.0,]\ьF1ci-%XV+iYM1+j6?@$@3 0(PjVJoȒI3M#C+lm*ĨCBBڥmjkjȈ0`DD"# ""0b DA"" 1`1`1D`DD"# #b"" #F`"1 0DD`#DF A0`DD1`"#DF""" 1DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDF_1c1cwc1cc1c7]v1c1cwc1cc1c7q1c1v1c1cwc1cȌ0DD``DDD#b""e1c1v1c1cuc1c7]v1c1cwc1cȈc1c7\v1܈1c11c1n㱌c1c1c1c;1c1""1.1c1nc1cЍ!(B6PlfiF!)`#eF.c1c1c1c1c1c1c1c1c}.亭K޽w%o{;ᷯ{p׽mr\6No=1c1c1c1c1c1c1c1c1N8mr\6ӺN{ܗU]u[yc76ۛsnyM>߿Kd]d]d]d]dkW@$E}dv˚l%KzŹZɧJ7UVt.`$f$F`,HKw_t;@"0I"DD,ė={,bW#׽%ιeH/!Zx$||[r~]wm}|:||a@8ՂdRI.$ mf)&a@M9&4Rl>@Zu(I(I@Z==>PCM3\w._d沈\mŲ\mŲ\mŲ\mŲ5D@"P]dx{=7wqEI ċ{kg ضKضKضKضKضI$\kŲ]klklklklklj$06b.!M1BX8A.Qlc(r8 \Aѧl$dN^ 0 ^7"hMS4Omzۭ4Om.in'%^)=Wh@{sy$x)Wh4^ RR/;>I%[4Om)'{}qMi޶Mi˧s-\gidWsZb~=֘EqS璯x)Whޤ^ wN}$U ܟI*M9WhϞJSE%"Sw>I%[1l3Ų.ǣȺ?kL["Og m5Bޯ%n) zI[hӓ璯'%^) BAo˟s$xCy*X-' rOJi N\4Ai˟ʪ~+m>8A,IuSɬX$LLK5`"8qH,U!JAҔC1YKF1f! 6fffffff! 6Bm 6Bl(Q;617tK(Q$ibݶ&FnI4M$J@6"U U2FV,%Fjĥ(flIuph興"*H4ucJbXKj2K 4,K5Xla[SilJئŵ61h +eKRjVJERR@Vb[Vd$ŢZ-Im0Qm"s'.\)H\ Ċ'A IU1$j(ĥKQ!j$, ?y,@b1fiH\N)/>[n23 YqMI*I[i>26zEi|1 (6\=}m[m#|RTmTut$OPGzgYuj&\lxϟ"턒I$t"]턒I/.}}ӻknUݰa3[O{yJxCeQ?LχA}$d}eXm[:\3}߽7m{tKJ߆|.meޭJdcr]dL__Lw[B!ݵ.iZpN'3v*m_;ߟz"#ܗnݺN+ ۮҰݺƔݺ tFR)Z)I%}Լ_ i$9+mwz;=zfd'pOI%䨖ZKCw-QѥԻ;rި$6{u8nu#m۷]CnP6BvDmwzN 螒KQ-wv%XDKz{\ $%{lmEA[lѲ;zI/%mmGͷ{vGͷ{vGͷ{vF6K>6Ϲ tUCKlCh\ChIwv/4uJ.|eIg^XD|$:{,I'Tbv).%&M$R]q7Z%SuI%޾!)o_DB?} ~tYm&}B@(4; wwngt 1}_>@0$ @%V;}Wvsw7{51mc$/$ҲlaV3IdVU-[O8h H". v5"aNsl f5iZ`&k,+dUZZSaQTQ֭hU)[6IJ4ʍem4-m*k *l%6D[ڶCZb.+EhfY] aSrfvں9)ɶ6k`̓1Vu\nr%'Z%4,ۡ4( t9IU8JDz R*)VIJ QmAzTjn^D"m!fKtoDhMiue,ѻIk&kY&.Y[@8@$ @ @U$*U_B%L, JIXHb CL%%S*(Ie IKO[6l%jRT6DX+D{ T^)TbcP**X*$<.*FA)2EFbKh&VYZҦZ,ɔ0'$Ɛ5SY5*D1M),&mU*9*r㧨f^{[\ml&JW5D !c`6F[-OӴgU4w}i66i[Dt:癞N)Ik!B#|!TpB 9B6PlL 8B6P7!/VオOG@QYJ `:m6A׀Vf&VG]efn$ @s A KkWտk|m~/Ƌ6@iswZmfIG `"BI/ /1&{k0dp\3@qbcH^eݤݵ] ,YϏ7QQQQQP$DD _VEF+^{=<]|Gic`6 h=;Dm3κZ┖?b"8o!(B6P3333F!)B6PF]ήmm$ @$ `H&A I& H, h@$ @$ `H/ۿ=W=k`:nmɭnɮڰ ng:uGmݹ 6"6ϴ[mFcM$ݶڶH $ A HMVj+vAЎ[z%k$IlKvj\kp-mݸI6]{^ڹ%FK$ն@&6A K_Vn[;Өvے أM{>InѶ4KvjcmlH@& H(+$k5ͲE̛nT+bdbE$A%QJr`,(BZ}/3@=|VdDT% nat㻡ݞw\mCLe*TLzEU$ʓQOUhhh4 =R) I)*hPMIIPzP }>XH}ӳ (D,Ė"QVwWldLH)u5asĄlBBEĄ IcYҳgGHi"DG,ꪫV:" p[]5 jVѫ7"KĄ VtW$.:껃ѭjy+ǀ \\Üѵ:::<\kk:f:Ǜݜxѵ\ѵ\ѵ:+gѷlըPġl*&1lK b҉,Im#K0٨bkQdLRJ؍Vl2f#j6!)TMhZ-Qh ]q e3V:SV(mͨjef4b:i5+EX4U)+Pکj,e %Y hЛPLUvwEۻ9j5dhR hTQ VttYj:D5nV:::X+2tJ5bGM&dRRnV6Ѷc\IAYҫ"D쭜Y[9rel厸` :"  mֹj1&h֢0S(j d٫4V5-Q!65mlȤmHD&$,I[M#QJfELj C`ѭ--X XڰXEdJM-IC-(m`Z[ ҉LI- ILcML5f(P,-ej2Yebj6ډccXm*6Ѭl6+F҄ QԢ&XJDQVm,SelҚM+65DmZ()إ5VQC7mJpmX޵6xl[mسUEcUmUb&Ս֦)[1J^mlniH:JM1eH)Lݘ&l&u؛Z[ Q d)$BcRRTcp-TiblmУV mG[iJ-jE1UFQc$2ʲ!,%3VAhŢ֍[6m =B Li eB[6Yl&II;feV4Dv,6LmXت6-֋XMh֖kZ-6֖1`, cIVZ` eckmwkvlY^ieUO5[Uxr*O4a%5Kl [fTf0y7"n[-ߏ[fm[nٶۭ 횶WKfҫ\mfmc[R 5t$mRM#gmVndkm$C;lhrnUĀ*b!#hmf5+p3Ӧ2TommխֶB"""""""""""""0F0D""""0DDb" ~1c1bc1c1c111cc1c(1c1Qc1c1c1kQc1c1c1F1c1bc1c1c1Ȉc1cc1c7q1c1]c1c1cc7q1c1܈Av1c1cuc1c71c1c1c1c1c1c1c1c1%[ VU%[ VUl1c1c1c1c1c1c1c1c1cl%[ VUmc1c1go$Gmy9+o;Ӿy^|ޞs$" vַߗϾ=|}|ji@ ^/Cl }WsU۝,pW*|.Ktիd m-642@#ĊI$'IFb`3!&C_>|c}y|}ǧml~_;!I{lcn_tvP6ۻmoRO%{m=}ڶ;;p܏;0,y€-ve\zϒ\2ޤQ̹X6ȧgou* $]V$RI!4$I#rs!%x㛫 !|=Ͷcm$f7t.wtmmJK1#';0ّr||qJ8򪹀9pӗys;^'7B$Q2yNa 7o>`vpe@I$I$T`lGBs<@i%hi$583 i%ޟ\;(mѶmݔ6ۻ 0h%̴I <)${I$Ľl%)4[[g5]xҝؖ<ȷdt</ nܝ#Lȣm^ĆjxE h  [mI2I$I܂rmN$VNnwtvPnwtfnVݻ 0N:T+b${m,i"IJG$&ຒd0HVD {$$Pii;(mћLjۺ]ޝs6ܛ4:d=P#AA-0틅{n  uwwu=ʵ[^fIѡa,Q-&wI{{յjҫs 7wfff 曼_[lb{z[*-YI-da,Q䔤D퍧$=$0@; $0@;o6ݲo6wU5[^viUffd;333WssM{ݭjv1`*Aعj!3* v^ɓq`v33 qq*n^فHa׺woiHa׺wowwPz"f ֤"֥zZmtQkV5wxZu؏6lMvW.D$,w^g CwRXxIzKXO ({wvQz]f PMI;)%EJPM&QE)vtmhp[ͱmؚn\I9UUY4ug Ƴ3wxT8B6-РϏ!9#0I4a4NQ/nJح-]*ٚ5 fVԵ-KR,Rٚ5 jj%Kz4Hq S =zcI꞊&U!3 2&a 03 jHR%_2*LA,,Jm~n@i26Vm&1[F KLЮ\XMF-6KvҨUJ()HڡROBB"Q, ,,-*Q1V*}.I\i%pvu\4]mW_77Kw}6i?mUF*t- [ܑ4M7 P+* P +*PPPPUR TrRe Y"+$*,ER,D"J$@UUZT*B"E c5+*d@_O)OB`1VQ)<$65E15*̔ʖ3UbfXh6* fefYmS3aPQis,&TfxRX&m%%c)5Y-bbc0LMR 1m Ou4rؕ8@?nOͺ7B!$ ~~"a2&[k[k[k_E?OoKjͽ{[+.( br\ :Ֆܶ[sޮ]-[-@$ @$ G/-԰zڎ%-t/Z#{#;ȍUU[@ɹ"iEHEHEHEYUHEHEefVUI*U!jfffFhP a|78v|*QEMZ*x %kko""""""$" """"""$"""""""HjDDDDDDD$DDDDDDIDDDDDDDZDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDj}g|dP`~H8# \oVkuc^8:={im_y IbXoaqB@$ @$D$DR+0~ (ٱ~a:՟\@Asbr'.9Ϸp7{-_M6ۖn{+峮;۽ۮETETET@$ @$}Umo~?_9rȣVdL3 ș"dL3aC6گr#HiPxwn];@Fm?4"dL2&Dș"dL6ܮZ~MJS6TlUs<BAv'C#^m%JU|RJIP |}nfa 0̉03 7@N 1ezwu1ʚV%BH!$z?F 7{uxww"A/{>)bIo  = \0lJYXFf>z8wpgPȟ}G>(>LJ0ҪS 4ɁT$ =R5(RTP6=@5%E<UtYҳgGJΎVz9==gGJΎuO{9YҳgGJΎΝgGJΎ+:nfYҳtll:v{+::VttrFE6j据j据j捝cc3vVXk^<hh漕j捝ccccݮ66jvjv]KڝڝGi<^t;`4msW4msW4msWi;F*yV[B R*+i-iRUU$Z-EыE S)5.82fGQRSS)f…6jef5lچj:i5+EX5ҮZ*ŵXIFP(1:`Vm+X UTheUfH6IImE+im#cV+w)LQFQ3.ʋZwEQTc-6nܧhS Bl6ʦjm)vmMr he%*mE6ѶmUM&kUMr hѺZ\:i55cnVm&­ڍKe-mAfC5fE3B6țTeQkk5,[Vf1Jf+5%vV؍EETh-ljm ֩i6*ll؅cb[EFhhlj,V(0V[c( X6[Hm- m+FcbcX5K#Qm0EF҄j-kѭѨ2EY(+2+2+5[fZj50e6RTV+ŵYbB l(ZYFQe(l[emZ(2(jj-1L j-1EXZ6o5F-,61e61jF61bkڴQlQlQlQj(2EE)[[[["(m)ڊl>JD,d!FGCnZR$(*K%$KC +e[Q<)z6XkU]Lɲ+2m&lI|8DL+44,Dh %Wel-mƋcED^Q((,r (y.QVRIUWR8q1><` fh f٥Va3hMUT 6%([YkY5J44 J.wi H8h8i H8v{۹fg߾ڷ~5bWkͷǖV_9ș.BO& >OsK& 2d?u^os}}]՜__ohK^)^ml-xZnhhmxZ&f@y,K=YmvpA $I4A 4pA $I5s={;w=̵mMz22dd<<-^ówvBM8̚i!fҁE@t!>B% $K&7v_ŀ ,t׀u^n쟐coM4ݭkJv3{Y~h8i$i h8i$[ZHmri#ri#vHI$ZHܥZHܥZHܥZHܥZH+:I4ޞ{}Ii4RM$I< $YO ߯{}^i!hm6mܥZHܥZH*4$z@IIIIIImnR-$nR-$ni$IIIIIg@I gfLo7<5,}Բ_$drMyd|XbZHmri#ri#vHI$ZHܥZHܥZHܥZHܥZH+:I4f}֚Z{ޥ&1C{{̞ B ]YkOeZe<džNYkO5SvcɊ3U:i8TAM5SsXͩ N|3S,S-inl֞t^aƧa,@w^XZHnRIݙJYi#})K-$ouY56N[ybS63U:iShTAKT%}ڃyiL!փOTAM5SsXͩ N|3w^P,ٔ7ۻ2FwwfRZHn$neВ7ۻG7=RВ72[փOFjZ -A <ǓHfuqQփ{⣚փ{ f=feYYZƮ>o_ƷW|Iap SR0U(`U,WʂIHU}'+Vbcl-$)qKDJ0,BŢh0ZRbp8*RF%1QAM*T0ƓRO*>2>>|[$0ۯ+tܯH3KU_k[ 3pH<& o\罜Yιg+::Vt{w:v{랞rgG:秽r5k+OnNrgGJΎcLz6Q^+=+;{;=W#\F\rZnR*LVѭQkW669%xkkvW-pMl4nF6Y4mVѵELēSV2LbCd 4 :-UQFJ5mE6EQ`ڳM46 h*#$(6fR5Ft]MF-0j躚Vaթz ڕmx3ԕjƭ[mRڥ SlFj3P"hDۉg7nS9 L/A)1eKViE(TV,P`1s16emKd`2*JKTֶjk[kYōQccb*+EEQ**TDɑH!Dp͟ssqSHd6ʬd#$:56֦1MtXVypy 47k $zI'Y/$ٳ]ovMi}݉]oe`2zfM/T3Ǐ{I%6zzfNz'fbÆ$rI$'fn =rK6M8L>ۀ ?oM2K؛b5 8+fNŇ 8+H\IfNz&^ض_(8xI$&^zO\нȰӂ_$нziȮ1tsZb#kL["}id|7Oo*а+ADgA{yW^^{cmQ4{}qN1u]keky-HE۫M]oq9{}n(Vp,LJ弛o)ۧ8ib&~B@`feFRޱ_h}&X1 pИƚ;f2-J.QUUe&bn IRHm)$!FBF3337$)$!I! IRHX `5$@$fk髕HۻBDB`rI |H H Hm Hx@RCI Rb)YT;RO'ob4/V1!,I$XŶ3{ޝY$ZYUl0]JxڲZel;4c6BJ3330!$Bffffh[HP$!$xUG%) %2*XV))2T"b,UUF(8BR.H %)I;l[*ml[J 3(+31&Dkk1)+a* KbaK%)S eUL̤˜$&*(JY1e&aQbņXcXU)&e+mQ++Sd&hC&XĶm 9 $@$(Eȕ2qDӄdr8BI)@$ @$J)Waٶձ9;kt$$b@ވ-uZTj.]p*mڭ`Ж*}ku H H HmmmWo[DZh6hȴD`I% o=o`BFishk*ZaE)MjnTj;4c2J!$3333BJ&ffff% m"2IBJ8? GbsA]B@R#HHMBII$!$ H HVm$DDDDDDIDDDDDDD$DDDDDDMiDDDDDDDR""""""$"""""""H""""""$"""""""H""""""%Z$DDDDDDIDDDDDDD$DDDDDDDDDDDDDDDDDDDDDDDDDE$DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDKZ_oudXҋW50 Z9J+RcՒ}}w$ @mmCd Hwu]ďꪷ 5j6)ݫkv6(}{=e^cYWeZ+UZUZ+cY H H[wЄ$H  [!EZB5k$ HUIPayw$n-I"ɪ=jd=W==>5bꪶU܈T`mҐD܂Y6H!fS 56ݶ*ajWLT`knD}@lmUfڶt`Hi5=ff\1,ā 1۱U[ D*0V6H"lmA,$Sf3? 2_'o~ۀ- +hzMhb !Y1Zʠ*lҶTdigaR&X u 6% RR8n )Zl778;'OaRMHb4Oj%)!A4&FSR$ &Gϖپȡ"H"-c+&ѨѴj4mƍQh֬j4mFmKj۝;>5k"k΍r5󌳳Y,vt눚rp#]ȶD:겘[&݋kw +4W8hpHhX1!MF(JQ1&D;F5sF5yRxۚ6wkp;5n;5n;%pݮgvVCZelR-wa(űmIm-m5 F55 [1([F1mĥZ-Fm!Q&aiD[FiYH4F̦S(SK4mDZ#UhFTXZ4kFD@ADV""-%DEm Xj5m)hdb6$2LFbXfFc6Pc@ک$fS S1ZZƱmcEh0elVĆf\mH\ĶKM65e26d$! K&֔"ei*"Ȥʹdɵ$Ȥ$HPͤͺ`ձmXơFɴ3j&5fMdDV#kҥ3)&he5ډmmXSSlXmXbQVŨ [elXͲ+U+dFH5[mYC)(ԣ2ͱZFS )&Í9mՅ)ɞFufԦնε6fuQ,26m LڊI(96sR mEm]6"J56&&R4%&ȶMږ5A̬36g 2,f& j͕صmT[TVJyi5ZBKP%4XUm*4 j,+X(Nfʦ̈́KZTI-Ͳ@!LZi]eb4QEQ+jX#mmL60Y,ͫ5e+lcXJUV24ٛl̍4,XcF(RQl4hѣRlEdK#F5&Z6H,4hԛh#lE mHlX(Ɋ 6 DMDH"BEfDBC@M efYVl5d[%j6h [Յ(͞x3F a 191qWDՊՌb*kCIvFi4M"I6o_yemwwsҫmIbYĖ|`Ubr.VEݸg28F"6"BhA sZm$$I۸mtr咜SVQjN BCZEk e[*Z1Yf6U=Km1c1F1c1bc1c1c11c1cc1c(1Q1c1c1c1UF1c1bc1c1c11c1cc1cVmHaa!Hf$0 2C$!HadI!nZHd!I$I 2C I#c1c1c1c1c1c1c1cl%[ VUl%[ Zl1c1c1c1c1c1c1c1b!HmRTpaad!aaHaaaf5Mm[n$I$I$I$I$I$I$I$I$I$+m+vNݻ];um;knwH56ŭM֧v"Gmm;v[sGUr@~.Kjk$YYMfI5$k$YMfHt$ @$ @$ JJރ0M6.ϟW'']u''8$s.9껒:$k%#ZwqkSmqkSN֧#Z۹wxk5II&Y$dk5II&Y$dk5II&Y$dk5IKۻ^6Um P m h4L6YM iklQՕZZh%l+P%*ml^wR٤&bm dIEZ Lf~|wϋtmߒԲ\.ėbmyFiv>8S4}$LC=˖C֔m}םTά.ckOfML^{7MZ>x;H(ۓv[{gP@AmZfd̋7 Ќ:/M7ڴmd@mvk3LUzҖmvfP wwu䝻ZvEcݔ~`0jvzҍ8whuv[{gR mջoݽMuvöKmoqouѸTRF6ozûB3@ow Ju\x7uRϞv 篔v=_zûC3mջo|[{%l׸{l*ے!gFy݉ݭ;"JSZvY/ر۽dݶrvY/͍_,4-ܒI#cq +d: $V$I# +d: F4冀eM۔|wI>XrWlm.eImvvY]t$HH'DI[$I$Kw@'DHH4}-u@y<$XNknGZ[:wwu$H4wwwvt[r:lƕ]+*Uvn;,4jKvK`np%\ۆ[ 43uKvK`nޘL]$pȁ 'y>*zy>*zpȁ '\]D\JD=7BejI$ D=C7ey+{<w=mH+N}3[:Md^{|%݋igF.Bn 8nܭ<$ $ $ @XW|_6*QjiIyܨObjR4iZQ5[S[UdDI%.ٌ6ka[5EƋIKAbm1 3L VM uUsmȒfrmdfpTr]@ j-RD4HQZKU j*5 O\̛̲tVLg{}f<ޯ77/Ǣ0IS )ZwvQ`Zbkmɲ`i@$ @"@$ Alm0̔aVT&&U'UL%)+TTjB/H&B!Tz m4bj jVjMUM4ХjV4hЙЈ EXխhћjUBU9RQ^-/15B{Ep1{${_/'YJ|q㎶QYݳx;e|yo6z4ՑƆ1;697#5r:330 L3MfHSS30:;=_k,u㔱LL*Ԯ_I5Zwv7v, LQp-6M$ @$ "$ *`‚AC/7 X~|7^zj<;QU!E MoRY[mDDDDDDD$DDDDDDIDDDDDDDDDDDDDDDDDDDDD$DDDDDDIDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDBd|}>i/͏BZŧ;ZwM侟3.cM$5u+fԧY$k^!Yֵ)qye^嗞I&Y$dk5IR:].stɈ,k4k5IK듓oPV-Yu)+^;kvW"c^_^{jX1xii#>7 X14cvlrnGj8%72y{x^^^דYMfI5$k$I$k$YMfI*TJ$YMfI5$Ynǿ ~}},JP H H$ 5 H H H H>slmgzף2YJRI$I6I{27Bz ,خMIk ޵$5DhXh,M%6Sf$Ik٢k5̸xiffAi4@JY1lrMlW&${ [ǏAkUZV @$ @$ @k5m$mjMMӎklW&$ص낛5֚m @$ @$ @$~GdMf.ÿE~@Qb|AIM"$*%C#! V ٭HSϺ (Qhp x3F HmTSƕU%PުibB7U=# MH 4{67}el-jX-jd(LE L"E4mH"$PA"֠&YTTTlؚ4QQEETƛZ46FPFѨѴjlPhlh5i(4mF %QhFQh٤Ѵj4mFFѫQMJ cFѨjMJ FښMڰ֊UcEcEckfEcFmUYchЫAM FѭkbTEE6چPءR,TXUVUZJرQeUFP(+lQbŚlZ–--FU+4i@FciCRj5 ֋ElQQb J#k YbP5ecm ֌h֌cEXlF mZMejj))FͩCFf6aXbSmMFjPƖQV6ILj6Z[mZX )35fͫ[fjmbHKCFڍ144cUhƴM5ijMk[F-14QFMJ$[JYYYLm J$L$jllh6B&Z-)Kmj6+R ͲHjHؖfA(%5iIKIL)UcIM[fZRK&KVmkeaiklZմM1bƍcXJeS+jML4آM5Vb,M[QB)MEFjiFSJhVZ6)F+V-EbڔV2bRűR(Y(+2VecV&(,ZVD#h4FѴh6c- SUhFصj)Qڃ(eCSQi5(&6SQi(率2dlEb6#QDj-jmVe2bfS((--EEh)3f6SDƌhR6&76ԦnA *څ)BTb+dcIFMpѭՖI2Y*Di3djmh!cXi ()rfY#Mim3lN,lucP3N8ݶP528ۜKll7-n*6 Ƭ69JjjSSSxn!6- &"6b͏V2ffFzmЛQd 5Tj[E3EfYBfml lVڛd`6hm 9`3Dgm`YA6[ 1 M1 WJMUء5PV մ WUqc`mP`43' V+jdcQdLR!D63!٦ͬQ3LՊͶsFۉh6 騬jj9n ێcXKId_V>l6پ 6FC3j(552jYY2dU) jȤګ KamM+ӻۻ>f0fa3L33332!3B%Lf33332!3B%L0̺!Lf͆Y!3Lʺ333 LfffffY&aB0L&a33 ffff0̳L&a33 f!Lff&LY&aB0L&a33 WQL&ffffeBf!3 K30&a ff0!33333,0! Lf!B&a3 Bf!B]jjw2w d!333L۫UB!B!B!B!B!B!B!B!Bjj6um!\nUUBf!333333L&a33 L0&a Bffffff!Lffum6um!$b6P$bc8B6P$b6Pp$ %I(BIBJP1-m$5ֶc8[ZH $IBJ#e J&3#e J#eLg JP$!.qclJu܇mm;u[wHvt۝: ڪbʻkeuZWq Vxo^􎭷tn䫶mrWn䫍tVۺCۺCm!w%qJfw%vͺJmܕpl~LՉj55FUڀP& P`ͨi$YIjjjbҴY lD[5eVʩ$E$6heR -&ʀZZQmlwF$I}pIJ6:@"HI$ ybX{Ien ž2$|Ғϟ=ob1n# n+|1,:8nD]۪X$qޝ阤%V$ @*M1,wօ2z3iyxŚ_x#撚4nm%EJ5Ke$طe!]J5KfFWl$ 1$b4I$"@"0IwޞWt 1xweq# 3޽DvY$@bP9n*+)|1=I õr7snl Дq H[DI {3D1#&ݦblf//j4zh4| $P aL޽aLg5\oOM"&4֦ I 3|H}v@"D $D@" b.6b.6b.6b.6b"I `N}{; ]wwtJG;,J.Hғ&3'X=}'jG ͚Z=m阤$)$p#޳@IC@ Ч;-`cgHBx-H^@6b.6b.6b.6b.6b$`qqqq֮IsQI_hZNNAsvF5o9 􋒼/cvRtN'I$  HKo(mŲ\mŲ\mŲ\mŲ\mŲ5D@"EB|q4-tBHp/wf[cJw3N.:Ɲ$LӫliNw4Ⲓvint(O8^KӺXty;Z}t8$<342HlieS:x4줎+wUeN#L[%#mqv[nŲ\b<ݖ۱lVPæKԗqemt$ᙧ,:dS4⺒]5Z}9uOuI$)q]Izd(Zy/;颴`E8K:hk9nGL[%#mqv[nŲ\b<ݖ۱lL۶I'2KI='n$D\k[{I$I7)S/{ru$qӯw\J {۔e3~QRܛ6(\Gd)ynM4٥iF`Oz >wfIG{ҏYR^a˜H㢩?oYބS?Ա~ $)C&yR#bP*frL.#{SRR1(A6T!(G]SkMm6M0$l6fffn$#`I"3335 $QS\Mu6\YyQD%,I4D֥iM "" H?Zm D!F6f4 M6ld!`%8ꬮP"*H4tENuNsG]'XG]"'X舋ɮܚ舗K&-imm&IHPSdH$%3em51F6+[+([ahFV)1$iFئkfUUIF6S h"$j6ÐiV 4)i &U[%$iXTڷ m4c "VfMi@G& Fb[&,"c lnl͛8`l10lm3cMdٛ6Clm雜ڵ2mN&-"` K^/<~yЙb{ݳHqKM)HUZ:i G5K;|Q$,F#e ffff% ll$ %I(BIB]zUuzT-`l f8 6Abm0Ͷl߃67ͱ;m6l6~M@Kf/eݕbG7)ɲ$mjb׳v=SD HHDH #VA;Y1 A/ƞ)k%cō])JX:iJZcm6:iJZ-1""""1b1~Z6k=(IA[j P#1`oq+zH~m[ZD$ $4Hj$5 H H"HmLę{ͫ2G!]2lIrM#I$#}F>T-BVI$TBO{4Chj}wYin*Pv$E$mĦ(rIM%q bćeXQŨJr$jQ fsbLU (1p `a+Rha YYa& 3P]Tb - \{Tf##1!?LiUJa1U =HiѓM$jTb2hGi@D@4|km(ֶQY4PBe(H"+kZd(H""6(H"EETQSSPXڨ46FPFѨѴj4mFFѩI@hh56FQh6FQhh56FmF%Qhh56FhڍFQh6ձh6ƪm,m*m,1ichZ[hEh)YPղjRVŊVV*XTX*,hbThѫFhm   Uձbѱje2L j5%ţm5CblV6MEkhmcmh֭khMjI|dU mDj1ƭcUlj3Vj3Sb6k[&UIi4lSI !SfI[FVҍ6Eif+1E[cVцɵEf*53Y-,KH3KHؓhLIM-ͶSTPCl5lҥ,k4j1QmXhRHشE&I4҉LHaS0V6LeU ڣ`["Jf 3JddfVf}FcFkƱDQkcccQj&b65حQZ-MMEVMbV+jͱEFXj,lkmm+V+űV+QImJ+؍RSdfY(Vh֍h֍Xȉ̭j,"!LlDMFVVZ#h4FѴmFѬbeh-cV1eb(2e0ME(#b6d؍؍FlFjhDj̦QlQlehآ(QMQMPgԘKyO6ٱZR(K$MFh֍+4j""vULhæef9()+f7YjZI8pj4ԨRAbK䩭.gL՜miDMDiMQMY l1Qb+c5#k.@11 ).$%=)<4k4T4-& (5EAMDZM1,(%QlUde&DmMld1aRVU &!HO*eJm 1` M7Xر6r67UU- 7m۬V+܌pshc6QF1lU1JR#B[*UA$ ae̘ʧ 2EjlZL(akkkjfY=H}UW e)6Tm6lmFhfIflm6ZmUc  M-Vjl%gv$C$2C$I$daHd0 0 $3I$!$I&$0 2C$!HadI!C 0 C4!a$i 2C 0$2I vdaI$I0 0 $3I!d$I&C$0 2I$M!HadI!t!a$c !HadI!C 0 C7v$2C $I$Hd!I$I 2C I$C $aaaaaaaaaaaaaaaaamX»a]vۙrkmܚw&daI$I!HadI!Hd!I$I$HadI$daHd+mܚw w w&daaaaadaa!Haaa۹5ɭrkm$I$I$I$I$I$I$I$I$I$I$I$I$I+m+m+n֨$ $ $ @oxm'udwydݻ緷awydwydwydwydwydݷnٰۻ^ٰٰxm'u:ξ{%T~Sa_ X%=l7Zަ{n"{mm{36= wowl7<~fjhnHnWkx!$}rY$?[54J7ϟٚ% @Fw?z54J7ϟ6jbm\c]dmqv-u5ضF}Fu55Fu॥Fu]ז%ѷvf `%ލsK3SDF߭ٚN䔟^ٚN䔁KI;R}fji;R}{fji4۳5wr,);F6۾,vܣO3]J4:hQ7|O}H.KmƋkk|u9uoPOcc;j$lKv)յ VE$E$FB) $I#bѶlo@4:K*a]q=y©}"ŠRԉRSTPFD4@ 1+>IRGȪ\"* (Q~}]yw˭ۍn%zY`ۍbKڵگo@`? 0.,#wVF>?=rTlbٌc-u)kZ1J[bT*QI$Y$Y$I$I$Y$I$I$I$I$I$I$KuoVFݍ}=z,Et^"x^=撷-lc;,ac AI]R:ϰ@ Hw˜ `77;P_{/ e[@4:K*»lJr+h @Zoiv5r9te>>+-NzCnj[n1YlwYmuec+-6Jƛl33a)dI!l0͆$I,036b $33a{UmxЀC;p@`:ֻF n|lҖعRKi1[f1cgԥkcm)mRF1cII$I$IKdAdI$I$AdI$AdAcuۺ@$ @$ @Hh$4H H H H H H#WrA9I%LIkmI$dl[mKmI]۹T]Ɉrx@&5K(ZǵvQJ']wx$ @$ Gͷhw{kn*#kqImJ䑷.ws \%$72]D[#mqIr8IzcrI!%B H H\kŸƵλGe X"c]uy@$ @$ dMfs89~@QbqP$J"Ifk53,jf> 2FPP 粭QZ =ggI" 405$ OSiU(@H$LT44MIRDdʭ_MHU11111jѶƴM5ƱSiVș4(H"խlM2iLdՓ,BE "eK#EDhRʊ!&"D%%66FQhh56i(lP٤I@f %QhѱFѩI@X"E!Y[$++del`h͚J clcZB&j5)hc,mUQEіXF65j#MHɪEb#HY+&*,Z6XRZ*,ZQ"lI4kF(lDb1JY (SfVB&Z"6K-TcƴV66cZ,beDmIIȖ"d&Im[lSlf(4ĉ50QVD+JDэcM*)m*щjɣS"J6(4fC-(2 IBi-$jHYE[QiZE%ZQ4iic4ƅe%Ehj6ūh3UYڢ6*-HT[ EJ`M&IcQ4Ƣ5D[idDEX-j-hKD4M[e6)ŠbYU`͔YjD [ZSlV2Dڈ,*MmR>6lQL(l|]PRʵ5[kulЀMDM hFDDVi%66#[)XՋ[7lRx́lfѶ j"ָF&5,lHQ.b[UmFZMebŲZJ#vfD\.XR[I7N%aefHdmͽ,iEj42c֮f#2FYpl ihBOFHillضJ/q amBj+1D56+)ʹ(S$ŌdcAQKڅEbd1cUViq5mqFKFZ66#lj4hѣIh؋Fm,X,bFZ4hѣIh؋FmE dIlBI4f>6m٤KEXX)[Sm[L؉1bLjTpXLPV)qTCj1J%ck&ٌ*M&IFD5ҼZ0hZaC5&HjY[1,%FJ(P̰Y0+$Դ kjYZfa,0lFm6BwnOaaa0 2C 0 3Haaaf$0 2C$!Had!C 0 4!a$mc 2C 0$I$daI$I0 0 I$aa$I&0$0 2I$MI$!$I&C$0 2I$M!HadI!I$ $I$0 0 I!d$I&݌0 0 I$I!d$I!aaaHaaad!aaHaaad!aac[n۹5\»s +0wI!I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$ppppp!aaHdJw w&¶praI!I$I$I$¶۷a]?{fyws6wq sws{㻞ٷo덵gڭ .7Ic_6>^_.TI$IH\h2Ih4 $NtI4Ʒdɪ/'k.KlK.KuebuK.]% .n۵VLG$B*I?;7I$I$I$$mV1!۴)$&IM LC4 bθ wr;~~>z| {]C_%5$d4M&@{or$dd\Is hWdH[@# vݽ;;)&lII6 wtnL%.j̛5ng0x$I$I$I$H{ޢD&9'(䅴 lIrϭQ]$I$ yv>LѾ_}[@$B.Y$ur$ N zI[oU'Eꕡ)=`ގڒt^[%a5NQ9G$-[dHwS~0guk}}zOd^ӼϗJ7K w{$Nt.Y8Haz+mm IGvmm%a5NQ9G$-[dHwSv{s\_%mhikp^M H(^M #>%!=|yp|JJ%pLv0 9'amIyN|pC" )T=-e44J$BM (H'7;Mi$bssI {N|pC&9G$6Um/0 odB>:"G?m<V)켵hCـM0 $a^` mvI$s6H9m$ >vLvM}{I1>$1H}{I15ڬ8- %'/HmuE{wl'/CokvoJCokwwvoI$KnHmnHmR~xm)N^?[f{Km|,ǻN\IQsjvtb9nfasyc-VfURe--Ys0C3 a@330 =e]-\um- rTB)33"IN}$ @@@$ ڭk~` J S%JX3R3@cF0)JqYUZ@h "*H\ pFkɫT\l۝)KXXXXrw5.jY˘I&V.9j̰IJdVLMmLVekT B+I#&cFhʭ$#!44V4d *UB̶mJض(4lb16ƫjVճV65`%UcbXQfm)+\մmMёS**W23&ag#-gUdʊU[n1K2Lb9.8#]*͉X 120!Ê**PNIHJ$jULH"ʔ*PL! !(|ί>?mGmgZ`$+4 < z)$&"Ewu=eL(Wyl0͆SajI$633adI.S36ff gs㻞( a%{ )aDMQR,@$* Ԓ_rIKQ%UrEP^JH+DHHh@GoV˲ʦE)$M0jI&i>^G[썭ܣ0i{h”-Un$2)JRܶJR H HRW6Ϝ=3`͹}ߛ `w]HXT=U-S = Y3f,XahpԒI!l4ffVjիV 1Lpg f6ll"O>CIirTB)0̊%i3$$I6ߖ$U65) eߛѼƁb4p]ݩKJG鶂TEmZ! H I|'Zckb@'h RNܶW-DRt)Kr۴HEM}𢂇I|zkx[@$I "8$"I6vBU$"]dI+ضKضMm/$}=T{%;TI W%&݌FI66j*^&^?, {sX~ꓶo FmL$!>ܽmm*I h !1mv-%q-mv-I&vI$5bWjb.6b5p^~WN}$辩Z{`qɉΆKHMl m4kzITDY{r C.iKַHB=Kyy$CkvkCi$GmrUioGK]^6@m$hxWsyx|mka y[to2Sj9'6"tWǖKJsmm+m[meI&=<^2KlhQ75ݭ1llkln['6mƻͶI9+Nm[tI_OY/)͵H!qC4 !hxs5EǑ弒@ %9d6rNmE$诧,̔ۤV |-m^ۍv-mc]dab9Q9nsmsm䨗^׶խ}}o7mlql%ͤm&BU%J u ]e9hy7vohqc@2啠t! azt-!@"DH"I"@$ U__o=گ*y< (^lQ`N8$L$nWtf۩wFt6L'u8薳iI$rE$@p@pLg@p@p +od!@ H"DH#U;fȷzl86K,~m:X$\J,o+`! H"DH H ^aC)J$DDDDDDIDDDDDDD$DDDDDDIDDDDDDD*Ԉ"""""""H""""""$""""""$"""""""m"""""""HDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDADDDDDDDDDDDDDDDDDDDDDDDDDKZH==|z[ׯ^|k[ݼTؽy[ $&~zo b{opjRmRt`3[RWϟow$!$b6P$l6P$b6Pc$!$W.sws6>Xء!Fc+gYSUTu⭿@$ @$ D$ "@"D$ $@"@$ @$ D$ )niͷn4I[moIzI/[mIn n mNS Lc0iHe+)UUl@$@"@$@"@!mMHztӶoX+[i$-qU,x$ͣn $M;fպI''mI9emI$*mU{{mͷ3ژ5-)1K`4$3啔*^R$ D$ D$ >e5Ew4.WGSF &P"RVe-07Qq\ (,}c 1I!OUQMIT%7Th'PH4 4%)M7f@JOjTb0yI.}iF63fcUAlVFԆmЬ3"fJ22 2&e ",«,*I-b+a [R[*MʤQf*&ʓjCj-m)6I"̕Y(ڋkj+ke l%`+P+ eb53&cIibfU3Q6eYB 3dmXE dj*2 & !DH[3DHS YL jJ؆Yi#i[Y1$aD# &lTc&Hmm [ VjlmTeEYh-Ҷ(3$-L%6͒V6jf`M@3dF`Uf*f XX5cXi+4kōƱDZűQض-cXj665TűjƋTTh-Ʊ4mVYmUL4i2Lf4!"děI4&IL4&i3HH4"děI$&DȓH FSVRbX"RĥV,bXRFƱFk"Rōj5[kưɲղ*V+l[E$CHi !46"m"Hi #I4 dIHIhh6XEb6DmEAQXb12hfUX*Ve T(6IL&6IMl4DђD$&Hd$H4Z26#fL؍؍Dmlɑ2dlFM,ٌlccDmhэ6cf1*,MI4I6&$D&6&6&D&$$I6H"Fl ,:I%myIIIJ%ѢF*MI2I%%xmDA267YFcS[M(J8cI#5fbZFT%mVmmm4b1EƊF$$$LᛸI.lUFJV*b+mPTFԒKKi-$-5bƌF6*1Ji,KjK]J !ܭ1hXŋb,Z4KIm%[IjdȂ"BDM$pQi2+6ff!$L!66㬭Zmld̳,ΊT<2FKMZ(hceVʖV `V 4,ͭTbiڳI͖-Rfj̪bVƬ֭_[V1c11c1cc1c(1c1Qc1c1c1F1c1bc1c1c1Zc1c1c11c1cc1c(1c1U1c1c1c1c1bc1c1c11c1cc1c(1c1kc1c1F1c1c1c1c1c1c1c1c1c1c1%[ VUl%[ VUl%[ c1c1c1c1c1c1c1c1c%[ VUl%[ c1cJ1c1V1c1c1Bڤ6 CjJ1c1c1cl%](B6PlBf30!(B6P #eF!(B6P[[oWw[n۝:6Wn䫍rU۹Ck:;vն굼/=:#eF&i3Bŭw˻F!(^webwwwU%I8Bmkm1a(MmBfiI(BIBJPﮮWw#ۺCCm!m Hvڷ;u[wHvtnC[_j6FQ5Q5hlx@ M@ @KFX|@ @-@ X$F@)PmZ- YPPK@,e@mlJڔ.vgoI@"0IEtD0D[m}}/K%ݔIDInwSպަoYmU||wʦ dž_&T?z[xYmoKo'^^Fa/)w.'m֧mx$ܹw.yŲ\mŲ\mŲ\mŲ\mŲ5D@"P]dX9nc$$ϽǏz{zjvI.|.\{]{m7t}qMiBݢ{m7{wN}qMi˧U ܹWh@{w>I*M\4^]9Wh%"ϹJSEӟ<'{Nw=$-'wtw=ܺs-u#Ⱥid]qŲ.~/.4^lxwNI%^)ϞJSD{>y-{[f ܻs$x.|U/.4^lxwNI%^)ϞIVL["GG5-u#Ⱥid]q=5DX{5DX{Ôȋzs$ȋz<.|U ]ϹJSD{>y*M'Wi< MO>I*M'Wi_$֚{ /y.I0;ϒFÐ$lL9 ^RI$}}<3;ς>IBןݜŇ[+nD>^wwy%],\b|@ؤn!e-A7~rw; UH@~sρă\>vmַx,䒱h, $8|N H $D HRW> 7F6f m1lۊ( *" ?@ +i%_tx|B+,eeTw$ i h;PZrY5g٭T`-rV7Pj> -ܕ *MM @$D$ Gժri h3qC8&&3 2sw c1[Mb6LN1 1yympAcyE#q)")I6Pl3333B#e FlBka!@ D H HH H H HD H,FBF H H  Hb:二0\5mP333ffw){(rJNH6z62նMeI%[M6@$@"@$@"@$ V%9 fou{[A[d[dZmw]suD H  H  H-E*+;R62ռq$dB[hvC(kIa1Ǭ랽 mYDRIml-VӁ H  H  HdMf4XC~@Qʕq@@?N@eP$2 @22R X #Zz(@ '!"o`;b[whjU (1B|=TRQ`,rZeLT =˻tp6jPP 0DM4ɦS4E zުU@444 @&OTMzjJdhhDFM~*^,$ f66H$ :–(rn\]ܹaK^aa'XR'XXIufI:NOzo7.F]vHFuگEHU|*mv$Y"_}޻}ѹr7'dU"E,#rzHsWJF"1DX1b,ETMH1*cd[ l~w~5.Q koƹnW—\6wQ:zpuw|9޻^x6湣nk;kF4msFܯSv4msFwמhۚѷ5s\ѷ+]s\ѷ+_qp|ѷ5rKYsù;5h]s\ѷ4j-|kF4mzf21ea +fd>ߝj MډJSU61ccj%60hQ"XC &+b5F ccbThآX4mEQEQbEjƍcEF lQ`(GmUVљZ-f[lkj665+mj6h cUU-mmmhV 4[mډVձ6-lJ([Ƶ^VkO{צkk\Z6[&5m3iRl.ZfF`3U!W3*61hGMs[\#d3efY8U+jؐ$uh 4aUm[ Єä"ʏC8,X=^-vrnnrׯ{=^#TkmZ*fmZV#3i+eȯDT Ƅ {޼-QM6ؕsDGm"?4l5f̙f%ff+0b,jmJGm)Fʃa(҃b$ lG5*V lljf5XQcVِB_3Y-e[%cUV1EUk[lj+Xډ+eSiHYڨ6mDTUXo%&j-F&cE[cEcQEfkC#Q1lc[%QD1ű5bآJlQQ*V"CiT~jl2%TQX[&ʏfVLEf $ A6i jfd̘=q,KKU]{>q|r/6L+%5IIIoo$ $m6`vGc%33.qJjmhMiӊ8MjLgY|r? f1e8'aTU0 ,0_&سl>&O1}mG)MKf|-/O8 pid̾)p6m4 ~ڕ[S`VڥLa5&l?3m10\_>zG:Gyg[ndť --CÌ~Sp|eq|F-e]pϗ9CS\W؝#S>['[rS8ecJ¸SO\Ѳdd΢CX &DSe&Ҷ imTQcVl*V±cTZ5|"l3TC2fkijc21?# '6,g8w3mX;8 Uf%/N,1QK$5SfeO+2@cK:뮱]~.ch6ɕcޓmxkƇ=Cy(G/TixrgN 9.:u Ef2D}38bFkdTfIG ϜU̩͜ni zzx320fgJ6ƭ_TǻoOӿ3o ;6b=Qd1勺/KK WG\G,o3֧TTQ6'hҴ]>k>9SʘF#VhK&IwNNoKerj:{S%z;vq\Kbu>!Y8+fx>μ>34N$GW+#)>bgÉMG\9lֲͲ3Чص܅1[Yj% oTWJ2w[fƃ֩Z`@kTZݦJY 1Db0JJ2Řf3W+11EQQXآX(lQDj,Z(1F,hh`DE+S"&L",HI,Z͙?fP2ءZ[V6WF+;*_VekHX)VKeIRZiI֫jk-hlXۻ6dbfZ)7g"5^:Q2:ӺîUtzuM iLp|9X<9x8=Mr$oݓHr*P6䫡}ni3~:sO0+i2h??C|rcUIyTѽ8>ӅQ~/a"u|75g˦8y$CQy_36k6fmjjTm,@]JLc1cʼn f,,c1aee2YZlU55kT"O\&2эbe4UZ*²VXŬjkZvԫ Ղ-j-bH6WB3e6lڹssQc1cwkbt;nۡЭn۶1cc(c+b"6W9jfsMnC1 D0b"" """ 1b""1 DDDD1`D#``D#``"""" DA"19\滻]\ptW""" D#cmcj66Uwuݱ6666J]c1v1c7\3t:Mm""""""""3ccnc1nc1n"""" DA"1]c1]c1]c1]c1]c1]c1v1c7r1""""""""""""%1cu1cu1cȈ˱c11c;1c1cc1n㱌c11cF FAc1cuc1cwc1lllllcc1c1c/_}ׯoۡ%nݶܕ!u!%qܗb;mvr#wRP;۷m%HmHI@r"'`8wnZ}Vьc1c1i:NӍ (ҐmȈm׭Zc1c1c1ap'CwwH"I1c m""v{m""v{m""v{ DNq{ DNq{}kc1c1c1'ItwmȈmȈmȈ1c1c1c1xmz;m-V`8rk; DNq{ܵZmU=={ܵZc1c1c1c{Ͽ2{Cmz;m-V`8cmmlm m?????*.c1m{۱XHzqv^$o]kW~ wnj4o2 1״8um/uj{ך5 F{=p((h9:``ظ..bKaUl0 6@ Uگ@ k5`~t _o_}]mm`lx mr`I'evĝ}oyk ՜IosĚPn6Mk-+&`–'3vI'AjL# Xw#eՐjKiŴM߇6o[OzXK ןV$g/w{~߷@P !! R!Hw2TQycV#@$8۸lvcmm6mm$h5}62I4 &_?xn6LNA2sMB燉2>I>;IQgv*7U${HE,笒t<^ 4JS]n ,jH!t/][^nob"f^dDB/~rD^=w{ރNR7t=L{>3(-70^마Dyg NϿZֽ~5"j2I6 /9U,8bRBvZ.NvH7V}F߅RU!T*H٠DLCA;e2uh"l:ckzzjE5}&ڴ}"{ob 6H6 0:}$IO6*mA%gQ}$l> ϰmBLc:}$m.cVoO:s!Y}՛::oV]zVV[5h-J8{M4}"{ob {ϡЁه^I/xl*mA%gQ}$l> ϰmBLc:}$mk_o>VWlI]&I;+$ؓm_o>k_o65ljպz;f٣<[|fĺ__R۝im-6 $=dڐXdH#Xb gMMuM=MuM=,INmui$I=dH#Y>YuOg؂K6Σ aXIkk[GmnO>G--ҟuvʍWȾdN]]ϖ.x Q$y,g1^DNt1!XHcn5YdH$)E!$EHyp$imY$TU(XX$Ko "$BIIQW䄐UxDy!&@48/-$d}N^ѷƷ^mEzyiv8^W{zWpWpҍ[mVlIk\smkU%~_5kVAU}e~ɰs[׽^f5nwTj*5z[%16fYx?5]cFXK|wQyG"hF+YYsmoS2ԑ/b(z|JQ@_ؾ DY"/n ,Hۃyqe$2;7paSUP#Pj!YT\+*Er3`v'˙qʹ.:WRfB+Au VuH%#-\ib#J:YԥBX32yi(3 ]J;XxuˆCBx*KŇ,\,;.FzeKI&yf爞嗷(c3q%´+xy*RtUIٵOL0&cMqs KWrgʏT/K%R2ci'l[-\櫴jr5^"]H\G-eF7 ssrWH^Sʒzz(Vj21[95Ng}v1yS}1h&/^ʯW|ۻIzur:j^G6kn=>>j>z)fhW/7+9mͤVT{ˈ|U[B6/t+Ky)W~iDrrY]eKI§@ U %RVZ5UC8 &(RȬ+, 2JhVhAjQbbaK X +VYC(hbV%bZFQLb24 Dd#E-$dZ+Ejdi,` iI&aVBY e(QFXIa%-B҃$(FVVD2!%V*b?fpm,vތi']/MWpKc1q5ldӫ$a2Qgr2 c&ӣ:NhIatJBE*Ym{ yWBE^U)N$U^k-t!$I$Rt!"*ZBIc1c$Z1l:F"@{lw\;YzJ_᪄EfUI,dRR?Wޠ4 Ԭ5i*D$A,U,(ʨ 0+KRDJ HhVUPZT@)d(`IH`CFAQUC 2#"7E*UU0UV QpD2"X)iHU[me+PV#U@R0(8 $HEF2" !*R)`*i(ART+UH+2*POKؓ2Y1, 33I"kd̓2QM 3l4&V֪նUţb#*U\ef/-mUlg]IgG46QfFbFa>xWOx+ĿE/u qWWewUT U6Z>s)6Ul/a\/R_%'E]B\P=Ga'&b̟EORUzT)AbV 0;EȆU $Ъ  Rs%hաn,&m95 TmP)BUV J<_ ?BJM1c 5F)L*!l& U[&eYͭ*aj QĩJ,0$dRM0X†': ő B$ 1O_IZ63*2X#32T5V6VSVT}$0i &jVX0Ƙm1HL*Ox:SF$d`VT$< %`qp.Y/5+3jx#,OU.K,\ aՊA_885% K( hYHjkf8$zݞp6֔m(ؓvl6vm;6q;i:%U,,X?}ۻw^^Uޕym5)i%޶"Sm(ZQq6K]8]%%_ꉑ&DDɒDDDDDDDɓ"&L2"d"""""""HVL2"dɓ"&L[k&L2lH6L2dms99WWyGsm-7~<}"_7vͣmFb,U+(ag3z,dL`ńi؝a^tE^UmʼȈʼʼSyW9Wyc1+F-,F-HE^U뮯I'_>!9!jӹsڶ~ _ǭh@gUc-a7MN.Q4Z4{*:@1Wrլb\t110yWUxU^UUWyUW^UU^yW^yWUxc1c1c1ZkZU^UU}G~G ; (I * Kl@$le$H @$l%j޺ڀ+m^ ]n^ ( ( Wuku;n"%d@öm6ml{{l6@  nnn۽׸xnw*+yݵzyifbݎ_MxkRkryzk<5j**Ǘ-rԯp>hۚ捹nr^@AGs;V2*-B_n vDk]CeP\6ڋj)z`EEZ2+`; Wbm+O,mljyzkحm ~JV£elW2I+4faYl5-`* ZUV e&ɕ%0JC1Yf*bCjA ~⑵!AHm$mUVA) *iDs$@6[%- FJMU&@lHmR_^* @mJ[RIKͣi[Vմ-6kC#Q[bSmSbfѳjثd-eKe@bjkBlXm3TXU[cm+ŭU,ZHkkƣ[+-6 mҭlͣbKf4hVЍcU4T&m3TXؒ5V,kmhFEcbf,UlUcj$bƵ|TXѶ5m4cSF+6F-SBƥBJL1))3Qj13((6[TMֆF-j&b614EfQ%d4lccEIVSbl mbJb5cDkűDEDZIX܍Z(ն"#ZDhi4F؍FՊ-bfIEE2J*(EZbfi>']̫0b#O1ONV1fbS}H8 f.'J1z?G ''>d?C&&a d`I#i`1Y/C=d_K𸶶l6Eh-TZ6m-|pᅘbJfT0/}4{ج,^ dNř?.⼌Y\IT Y×\I;yeeq_dWrXE+kc5(([Mch6-ekfQEij,c&4QF6M2&KffŴ[E)Ɋab/j_eGbz ~pbwYKӖS$Jm]e1M3,*~1YY]uXʞbf:qUӆb8apc c1cc11X,ffLHuVUYVLʓ*#Unma,#Qڻj`[]ҪZSN(OEQN(D႘f-a&0)+#?#61p~aNfac31b2dN"Zm6O qt,mLo]N ᗍ1qҏ<+ê*bG !1/AOL38cUM3 Tf6I'|E͜W74uDž迃f+20qfcUKmC+jV+Oi=mo lɷ|񰞑YFDڤ|>'чN~ ğ ?3'~OT{FLr20p}\&_/8I2qț8ɏ//x=*OH®y/0Rz:uz^I:ck\++1&`#lٵ6x/ֳfmĔ,9ihшԤb1#c0c FƫP@B& a0 6EVjb#bƊ14h ccdXcV6YECQDj,ZiX5P P"$,)B3TԨ#F1!,T%IIIK)e]ed6UdXjM5Pknk+nT-1kX6QmWUJbthѣnQhcFY-`Vh̙2,bq ) d+)WE:={\\^[n &{:q8< eTDؔY1Xc?  l\2# DJ4M-J4ll]l% )7+vZmj9mZ[e]g]IjY2ںֻKiYAj.i2Vqin$k\kͦ5nc`5̹@ '2Yh56VeVWk5]YV#A`rokjծFUl6d6,jY1UlmVW֯QsrbݷLLLLܮr1c1vnBt:fjfnQc11c1jc1Qc11c1W.c1bc1Qc11c1F1#7ѻ7wFn-mBۅ nl[pچ-mCjPѻ 1cŷ n-[p n-mۅ n-mBۅ k۳1bc1Qc11c1F1c(1c1cF1c(1c1c1c1c1c1b6-îݮcccccccccK;66 .퍍hJ1c1c1c1chJ%Z17wn n-[pmۆ-[pmjP mBۅ hJ%Z VN2C7rۅmۇBۅ n-[pmۅ n-[pmۄnщVNUc1c1c1cU*ЕhJ%Z V1c1c1c1c V&-1'*{Ƙ{wgv1^qw݌a9W{1^S ԃW.cjj;'*8;a:j9S ԍ^֯ hm 0TU??/>ԃWAY30H5zqf)AnS ԃWw&YvnZH5zqs1L'R ^g;pNf;3͸L'R ^ސS ԃW.cjj;6^)Y;a:j;۬mVR ^qk 0w۬mVR ^ws1L'R ^wg;a:j;۬mVR ^q.mE*-Q@e2LS)ҩej~Ֆkfq\թjVܺ͠%mm宪T 5G63^=~o dYK(ϝԭO_<9o0*fRJYSa%*VZNɳ)DYRkdi*im֋jl|ě .dR; {wmlmcmm<Hww{Ia!$_""_ʾΒ|߷h9}ݫhk_gvI}Kd$R{~$b.]5I)wHt5|'~YV*UbYYYYYW6wl}oy xL7A ᷴ[IMdHm-޶R6o[Kѡ}ur`-u[$I!$LxnhCl$4gp}%+͖PqP@Ȫy^Wvͽ6wlȪʻmٵk{؀ K:CLK om ިl&5Nw/[{l[|fmiLO!} /Hѕ~}[m ,$+h4:uׯt.If{2*{;mٷە!H|ofa@j:>ٶz].K HBxN{0Qo3D(kl9{hFv[s,;k-m%vБp#v׶gvЌ1nuf'F6vap{b0mv$a:7;s ;9Q^lP;9bLc:Ct! {yt(6,C:=#ÆgX0ӒB綒hH)G8B98tw͝hm؋B]f&Q=$I"nwXNg`ag0 ;:Hx̘G6c׭c$(6,A[lf{;m(+.ٷf{;mٷf{;mٴ8WM`xGk-e[^W d'Iބ6hvPI[&#U0a[b!@!ʀJس@,EyBho2ao`l@BXIg^HzN!tYu6 )2VO QK9%EqY0LTudӪ*JT:WaE2춬$їp*G\Mݺut$x'xJqX]&Y&$u3Oc&2ppBJz:#:i/KREӮ^Œed٭y:ddW\'C|OG'560{$Q➔z*#S #+*NQATB*L*•L!RQ`1H*$ d @«%d0 2TʲF,0L,-12Ibbj5e+LaF(VS)f#V eFIY%bUmb,EaaXV@d*b"XX_Uq@J7WWֈT3 td̓I:zSg'qv1@&ڱk( 'Y$DJ!JPXDzΫQԶ""r*"'*""r*"'*""r*"'*1c1%hΑVב9Wy{ܕ2 *$2Pe"¨j, pPXJdTDT$ĪZSTA`Bi$F#Rh" jAYTb*F)#P ҫDBVY" tRCaЉNL+eEKiPEB2. (cPC"U8-)$!h$$Le(`TȩK R`FPPT ̘ı`Y*Ybb֓Y-cLb6IYXS M6M1(BԿPX+U]qq3'!Kffa0OGCҧ_(} _'||^z^G'b{Q:U/>WEuT"O0H0JF"Y) ?GT:%j)-C@jY.ѶS!LU58@-J6hT!*0jA` :' ~_E %b2 bIaDC$O2f2XXB\ } 0`*LLUbPbRGWi( IN)x#c2iLԙbI'K,aPLQ 0G$: e+ "h)JVuYd1E`qp%K!&J OBe@R,%,\1L0RrJ(kW6Ư66% K/VVi$kf8ZvX RHBBpcBeN8^GbyTUc[{wl^!b=Нm-޶(%kKִ-"I! IRHBBp$&Dɑ"%&L2dɓ&I&L2dɓ%&L2dɓ&IDDDDD$DDDDIDDDDD$DDDDIDDDDDQEQERQEQEQJQEQEQIEQEQE*DDDDIDDDDD$DDDDIDDDDD$DDDDIL""""""""""""""""""""""(((((H(((((""""""""""""""""""""mUTiJԱKo8>jҢѠϾڭݮ]vţAtUUX*Xp3ăX*Z*Uc0cʪ-cUV1-`3yk^ cUWA5zƪWjU^)XUWjU^)Xc,c$e2X1Hck Xd,jU^)Y;z_ _?bHX 2326ff`&d̴ p83--33--3lf6N'efefefefefefemL&ii讏zj{ޮ{zpxlm{]Fkwv»{k$-ymI$lL#dlm@8Bl!6N'M&f`33M&כso6ܶ(͋k/OI 0KՓ2#e&^+ d\YXѴfFfCkF5hѴm%e-6ڨ=,3 )YIzŘc*X`X*NJc/ >.+evecɓ>*v]:j扅?R;lckc1ĕ%IlmFmclVJST6IDjMQkDQF*JjY1LEI))*RA%AXԗb0 *}T.a da3<_X?LXvN{"eNc)?*'eү b080ᏩN%V%XK]D>''bd2NIa;xdT$+?D1\=QNvp)aq|X>Cge: *|Z{$a0q%DeLvEWINW̔##p8U9Ӥa0F $K]]1M.(Cem1cjj UvQ4E":]mJbR SkU~ԑx*]0s c&c)Qآ1)*KI%-l&L "` %R$MAPTFI c%E1c%F6 AQY$%SLQDDbƊ1 c%E`JE(Q2fTI!,T%IIIK)e&6*bQbQcXIY*lQ5h6B hEd bƣU&,b4Xl DmhlJd̙cEai#8a2R(` (/g q. E,F8(*m*+V)逮UC#cUeO}qJt]cK18zQ#XLx(G`ÙY3oIDHIe^ Ua 2ЦմmQbjQYSMK-&[iMi3IK2AEb-V0[mET0ҵM5%mcTZj,lfJ6YmQՖ[FFF Uk_jI$$@VH ՈH"HB*aaf0 0 0$HdI$$ I1dai$I$2I$dd$ I1I!$c C$29\78rUlrUW*UW%\rUVJJ*䫕*䫒J*%[%\rUʕrUW%Y**VW%\r\rUM˦ +78np1cc1b DkIss%Y**VW%\1cc1b$HdI$C C4!$i$C$2I$ddjUJJUW%[%\dY*d%\rUUV8nB.댒C$2I%*䫒J*%[%\rUY*eW%[%\d$HdI$I$I$ddwJΕkZJ+m5d$I$I$I$I$I$I$a[n¶ݤJ*11c1c1 U8J9UiNpZ Vnppsc1c1cqV۵Zv[nɆaaJ*䫒J*䫒J*JaJ*䫒ZJΕkΕvu݅]md$ IdJ*䫒lrUVHd*dnqV*-Uoc(80bihn㍍pc(80bihn㍍pc(8]);J!l\6v1u8]/uo Zզ` hMh5 MhAր4  @N|1-mL1-mL1-mL1-mL1-mp`(8ofFVFqdv!u0`(1R\1-ハ}Sw\BSqudedgK'nu݌bm䭌ʛofFVFqdvmdedgK'n!uRS bKhn8ofFu99vT?k`m[XQT;U,j,lkE9 a dALj0@͠+6 i@f)(MbeFWUlZ6jc0#٩ISPjCT[[3)MXh@eٰme*lmI ԩYY6ͩ0iZͬ(VkFmIlu[$ϟ?WT뮺mmlmw{{m۶ $y {۱}݂Otr{ ޶H!k|gv\d~=EiJ2{ 4:[$껺{AD<>l Nrrs{pa=P޾C4zjgw}#>Q0x;iyKiio_m+J病;w}mmlmw{iŕm[f$;޾m7}z;A{v>i>*kRV@IӅZR^/ éerLn\1ڹ< m#פl-#` zL\UӲl厯| ݵ{kZь%K{v뫔D^kTS*Ht{C1Z*J a^ry_1xexjOsc_4^'I%zzƱQzDW;lmcmm؛}}%w m6vbmi$BH< y1gubDd!m3*=J{eTPy g;ӫl_I$I@$ Вzk$$MMfmUTUUS̖{%gv63m\E(gY}$x __b=o_{I}}%&޾zKi;lmvI'z퉷I <)N6UY 'l2,ޔ_#O_mdd9`twO\cJܼxo_{I}}% I$Bp=Kw];eNfzʯd$HI:Hz{6LyGAGËo8yGK/֖oBr|{zs#|{vn^Q vX8#hʪ}(Zʫ}(.DžW]}m/(9")q$6S*&ry#kl{wJ:;hr }}}ƋXyUeoVo"__{7hTޝnܩ{kdʫOo_;]EB5M6)UUUە/md]:Uo믷m$E0`N$yAD_nQ/$qtr)-z}%_oXo޾z}%*o_{I}cezERHI'r{oImd$TL[ە,_ §{zO;k!$Up {UMvWUW]}A}|/}wݮ3_{~|@>_K߄ryblxUu۶rS"0kCe^yV׺zk%ƽ,RRЖZ疫Z%x P KB)B-,ZoǼ/u޾վZəq3V":njW6޽y<]uzǗN-k([I@-- Pд)B KBVзihZZJihR(ƱkZ+X!XWHT)B KBХ P--pqߜR%XIb$j )d03"p#$$b,BPЪ)b R&"b1J" UD% X:@V)J%T jYJD5*&J-UA8AKJQd$ĪTa**h!+JR" ED]OΑ x£KDPOU^zW+BzQzB(=ROD. U^*:Rb/SUu(G)C)ؗ!&)J.$$_JHSRUD'T cw':VشZN뻽ʋͬw<335j8113f0l͘$J1H,AdBc6c?mvy^iyemGMfXwwo4v޵[ogu]m8lc6c faٌ113f0li Uٌ113n9?C1(J(()(((((((H""""%T((""""$TY(((((JQEQEQIEh(QEQDDDDDDDDDDDIEQDEQEDDDDDDDDDDDQEQEQEEEQE*QEQEQE([dW◺Ψkl;;imWlm~,[~#WjY}{<`Kbک tm@g=wr51wuZ:mkZmImdmּV-ld7{[ׯ\e-e"mT^Qyw6+Ơ%}G*Ҏ7;l899ih0ƪbPiݥl4* WV|h>0L?'$O4}e{իkNo2FW5N:ȣy2 IMia_.CCE^f-lIv fVwmi+@X`KkJa%~R^Bw'\1. o{ֲxqN'cՔz8R:Z#GjdKʖѩxH^k+mp\YWJ:W(:XaFŘ]*bU;--E]W T$+X*kf2 fld[Mc`Š#QDb,bF*IdTI-)RTXR2"H"("Y+$RJY))4O664Qb3&fF'K&+%FjEYZ̙ƣ *_Kh #OdtH/13R= Z+0 =GyC+R?B+WŀF#UDUoztL"nDȒ&'y$L"nDȳ6ƃ5eM9ˌ !YST_?p#kQ-6Fز-6"ZekcƈƲd֬kXeH"?zc1F1c(1c1ccc1bc1Z1cc1bc1WDDDDDDDDDQUc1Qc11c1F1c(1cŨ1cF1c1c1c1cJ%Z VBU*1c1c1c1bU*Еiu1c1c]c1c1뱌c1c7]v1c1c1c1cc1c1*ЕhJ%Z c1c%hM}/.7q1*7q1*7q1*7q1*7q1*0wuFX X X {WǾ @$ G{jFڣmW$ GmmcT`-Ƒ81Fؚnq H#r@$eū;rm7巷K,[ |wܽbccZhX-jQ.A4m@5HZU5d VʠkMmUskcV{kg"V1Ʈoo.Lwl^S}>[{]z]WTxx*q_$trV}>O +{O49N=wcu ʈÜ7Tv;{aQ;E[U޸CM\  ;ުUq>ApK4QGM-UQՎ 삊iE)m6~ |aWld^i]m/DY/aW=^c\iy<}\p:0[A@ؒ-Y".m Qu9ʦI$tIuRMpY$ڭm=ki]m ڏ5%U 23].ҫ v$K`IBHțV5)\I#By+V$K_*5 $CI2DB-$EK|DDG.D{BI2DI2!p(T_q| zBh;s4dhS,c66#+TbKh`ZbɴR_$@hH4UD^8hN*u`ڪUUUTyZ^yYlTTTU8^8^%u.hdhQU\/okmm#An8:Zآ%p۲G6$J%Um%FJjE2Le2W$ $B|(0 FGǮV<_0\3[#F-.z1+sSg!`p+%.?i6 ,|ԓ+Z2iKh7Ah=aT2%eie-S{SF-Q~lͪfi>09 ( +F/#F OB_#dضh1m-elLDccHѪFV222a:,e/VY2f64L!C&)/fF22±&Q+1,L(1A&Lu)f1,0:Xbee+(bPpY0V2d%LeXd2FQ2IfTLLT¡GqPp9pFӎ*ÀOÀœfgW%͵[mݵNL>cb5F:65XI`XX pp,)`\*S.K3ILn *ÅLʹhLK# ` a1K&Pə2*&QquS+*2JbiAh늸euʌdYJ;m'&+m*fd/ ٬̔2#LNGZ:G0c>/b `ɊUdʆR06[LVeLae#'/ʸ:ke6Hb2K/^Di$RzL'4ڗ \l>36ѠŅɪ,GTq}N+q<.ux)dy9]h5Cxu r2uՖewy<Օ4xKZHh,М,.VLd֎q:]]Nγ&U{ X/<ѣT;Pv&NԮ̖k+C*6a]4 WI͇pUCfV+)JU"DR$F#H1$(I0* V QIS,$Ѝ†0EQ-TYUĆ$0C2%jLJh!,bY-IbX001R A1BLR**q'HGB"eDaV `E0XJ4$V+YX%0I SNʑiPrA +5#m uT%"o-`%# MQDDDDDDDDD H0$DDLl٘ʥ 9%"r".UtK%"8@+Q8RTB(!YBR JL4 1b1i1PP*)2`dMH J Yl-$RS%"X6WꣻcmeAҹ'r3 V6FɵF ;Xɕ hmmdbTtN'!=FҶB٭"樼$8RO$ͭW`.'IMT TU)}FFRK+C B FBʩj%GҟDO}/ZBP5Cj#J+}>C `2V,bPXIɌ$}_E*dXAV }2b>UFbK}Ua`bc œFR1*2& Lɒz{Oa5&1`$0*|>Bȇ^N2*JACJ}zT0vE55SOweMB;̒****  6ͳi $'y%6Md5R-TREVVE؍J(kB߿l+[zѱV[-)45ma_{hʫ-ඪ|זo{{Ӷd0fљVa ^jpm=yf{[ǹ={4>vhjkƎhj98hj9Khj98h999b%stc.hj9K޶:cbL6bjE (1`NOQH"m(D:3XpNG P+U@ aEPPm|\$%*44 j4ѡ5=U d'R ЍB42F22ba##~[`_[fFd=51~wC.6<UUU\/;s^U{zRB$UUUUUUUU縼^ Ԑ^b.|gb PڍZZ`l-Q\ء. /R= mRڗ&ڑm֠U[Z(ZZ׮ 9({D%Wu b8.?rUR3D2=lmBKU޴m*fE6g慴eVs%9zeE#9jl/WJKYN'`3d\Wd_JCgU|Zf4W|KUWŅ+29K݉Y!A^l"On{{|%@hDdJNF`Z4l8,ڥe98dZ[kvFfͱrf'[[hmZB|\,3a 1:JĝI"1S՘ń:IҝQEd.#*N qSEd,,2dT,jp8T8q\%fձfm[&Y+ `8W]\]UuquV%:uK3fVWeaYY&W QQh{q9mr9?̛'Pjq rTUt;r9UpIeQӻms^mĦmkVmϤ|r8#l\G8ٙR^{.#,u8kEX^sK8X,XXpc ~..1pZUi`}r2;.Y;y-&Ge)Yo4^a\ca=cgQ'j{huqz!&0|ٌVٰ)Q`SbXXX2X11eX2 %!1sKjĽ[[eZfYLJ53333PZEr9\Tԑҗ{0ٶ0EVm-/0%Wu]3 |3U[TMb2XL5J2FJ(=W].ϟJ ,b*=6:WK@[^EsncXjnjw'166✓؉*mk8ҁ[We]aebm] @B@[m$ @$ wwww]ƭhڭXI%ymFƥjj,jVbjFVj5kf56ѴlڬC(?O*K*m!NCM{k{u㺚tWj6mno{;׻wYK;;QDYmZзks{F'!&ܵۺCckyh)fn Y;p{m2)2)2)2ZMj5B!B!DB"D" ZkZk]CƆd6[)n(`l2)55c[X XՍm`5cV51AY&SY4{ۀ~ `%lݹlE@+@n|/ T!HCwRIA@hujRP I'Rj4ԡ()$j3PzOP]~W7d=z!dItKwu[5-ƨؾ_/=~ѱ}A/=躺T]Wkm(6FִZڪa6U3 Qm{hշȘd}J*jdSAˮʨM,LK#4' )%͖QDegu35s妭Zm-4GMўajb,#Off_e1:ZFhu++L5ivq\Kɂضʰae6WhGe#%Aͳ64'նf/J~-*&>_WC t,Lc4_\}x&Zjhu3dʳk>OKm)3MZB"H|Y}$V׺{f̐ 'ZKJ-Z,MEdI}&|L&>ľKTiq-CUK<[cZ34E,-!KH>O鶱RJVIL⤿><+ʫ&^a q%|eO<9<2ī&"`8.N$SXGfV_1lo%Ó ?7WimQ[KC˲CQ!Ѩe>/[u,3(oBT fֆѴ-pXLC~T=#A/24dd)0~;5I8rttvɥ-FGAї,Jzs39tr󜸝mx%ʹP홛*9GNKЗ/,1SL8Y-`LC*Yh+FE^)i%:(e05XV (,QTY)(CV#&ե#V Z0W *V(0]*0ZLqydɔ?ʇ*yN\-LYCzXXa/TS5jڴWtـM]۰&Sj""mȟzm@4YjjjjZZZZXKҵk_DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD1DF""""""1c1cuc1c1nc1c1]c1cu1c1c1b7]v1c1c1c1cu1c1c1c1c*Ub6U 1,gy3A̼SXۥFEʈ)Ջt0;8aJmZ^xFbvk ͥdqΰ&G\8V uV[T[U[Ti̫HUdj*dEȕsZjK`fȳ 3dUr*3O<.껵&掔і:2FWFWFWFWM]#jC,twcR7R:EeImRMXV$Չ5bMG *KG *Jh$efČ#,HK$ !lYjFjbJ,$eU6-JVHmRVѤT,Q]G@wU<_hѥjFVh Qʶ_4A m_U[U[~7 jG*@V(rT,5V&&lmJ$Aȫ ɢ& WjVQZ +XHPN(854Ņq2rN&,覤q.,5tZtZE4uGWW薩*⤧1cSxVNNԊj:.)KTMKʆ O M)PmLj4JʸV0>:XFƫV:tPa^GviQrWʊA_R"/.Md$ǐ9LUgMSƮF#ZaezLPe| ^1|l2fJ!J$W!_@GR2BDȠ5R(XIKRD҆4-DZZC0&J1A `F(ZUb SB 0 T UX@!M $JR$’d( (^TK #"1!hFUTԤԨ&R UJ*h+2HE<"y+X'T!pJR,B@l GyI%Ej# j#  "6"0$ 5ImgJʑKP)*`QT)i!'`*EU"U@W(l3 0E1(V--k}2fH\BQ+Xq'/+hڞŵL =Ty^{[FՌ,_+҇G3S+BtrQ𣵵[Cts?Tm.=o[֮oZx7ƭm}[[o $˯Gn5C ([Y[k| $MzT=UTUE*545SU5RUUUUSUC,E-UC,E-UC,C,C/|  %EEjj-jVEƥjZ-jVw烸W໽uUX74IJmf,W [TYb.ꪠ SsMt.GUefKoInhk4ȨQU-WUT[ZSlJmE@smB]KMW)e2Q2 TL)e2LS\ p @ @ BQ2 لZ[֙LibLvRb슷 (10,}@4fʷT%Pa@/GT~Ȫ 1ETa&"~Ԫ4Ѧ#%JzddT( ІIDJ4?'~,eL2&̵|wChm ֵY 6w/m@ @p *_ P_vRm&*}c,YY$"m/҉_ܵRQe^աm8|1c1cu1c1c1c1cuc1c1nc1c1v1c1c;1c1cwc1c1pc1c1FڣPڡCj j)}?wMO7 7cqv[[Ŷ٭ffa3R =wM7vcqv[[,;6;{{wqv8[[ۻuI\y<՞y<Χ:9 9QQQQRT%IQQX(*JFQ5FQQQXQQXEEEb|U}}k} 6 & H KZ`]WUUU %UUB `H*몮A HjPAV@*He ؓSѠLCi-HK7ms0XjjB殈NʫHU벪) U9\Ud!sWDtyJʔ$ w^d^y{*.!G]PɫĂ/e^$yS+Sڥ#=YgmO '}}y4_4̕FpbN*誰UYS*ʦCLQ LQ22KDhJ XRRr+ 6 & H KCIGSm͛26""6 DXDDD" """ DDDDDDDAb A" DUkjꐎIT\#RPt 2aJ$J@HV$*RJae+W_8œ?GG_"|C O8L^%xCO.ab%tKb90\HM +JR^RYJ(ʩVRUE=GO0FUJj1Azׯ^bebMWݽ {#LKxRuYĵ2rP̘Zm⮫_wĬs U]]{緘$I$3y$I$3u mrUn]{M+kh#6?MGGhٰ06 CFɲml1 hѥjj4TZVFbťjZ6,ZVFE:wyӻCסl- FVanVaݭ /v7&naAոm[ս#'v3MizeP`Ѱl- F" p0ڷ p0ݭ /v%gtC݄j^0*s<:BȪ Th@dJT@@Rz04%M4}jV#13-X)[bvIw[brLIkwT ,PX* @X-[kVT\c,YXcK1Vc,c1PJATCH|2.̡|*>(aIFPPmUlkժRگMVk~Ōc1c1c1c1c1c#0c11111c1c1c1c0b11F F1`1b0b1c1czDDDDnݺ""""""""ۢ""""""".""""""".""""""".ݺ""""""""ۢ""""""""""""4DEtDDDDDDDEtDDDDDDETڡCj  mPڡ^=+sE>>ճκٛeHT뭙fT*B/dmyhZ-/[3u̩ u7]lʅHUL:^; Z-E˛f뭙R!fnٕ ۹ȧγ<Ǎ{IIGnn㵩jv;[VsVjsV\ڵov;ZN֧kSfsf'k1;YNbvjv;ZN֧]su7]wi2IW3ͫ1mZs1kI]Lwj$."3f-\Zb62IvXLՓNѶѴm6CMil1 6am Azzk`ww@wwwp@wwwwwwwwp@ӈ$P!† S8$[(jć!I DCU`HCUZUjT*VJ@NE@Eb(#T*1b* ""0EX" *`0V*rHRU$]dU`)W۶& 6km W(]U c11lm68t)W9T UJp Ur` W+EPTx";ԇuHwU!U!UHtPC H Сj«$^WwjwUPUUf*<s@*`(@ 0TP@ 0W>(#6шydVj, *қ&j1 6Mk]ahQl-m[ոm[UAոmY.UaZ6aldh0 r0ڷ %ʽxKxBZKyahZ6VanVanUUVadWr'M6.t͵WKh6.t)m ( SLL0TSO 2dnS጑DPp}:0>_68Q Pt 4IJLCUI4`5?jT4i)JiFAjR5TIE5=Jt6n;f ,ed=:s{[~X0 XԄr|^ϟW~;u$/RKUUVyU^v/RH^Թv/RY[K@F-[`-Z 2V|ɭgWEp$%LSmQIP+*X *W'>ʥ5'T]BK{DIxW#'"+IXFND+KJG*WVUoh,-P 4hѶڦLcFZfg Gb`CKiڛX&bƍ-%j+jR*V1XjjچŴmTfK0pWUUDVXuW\F*X6DB%L*BWUX1UcV5[ukvjkg%2&LZYfDjb64Xb1bjɥJm""m{"#b "#b """""0DDDb""B"1 """"#DDDDF" 1e1c1cu1c1cc1c1c+1c1cwc1c1뱌c1c7]1cT6l j Uo?R[Zgs0rja#E-HYQe,1 ʝ $!öfE(I[C-[ kj$a2IcVy^wH;]tSV`ă9r8 B/fʹͱ Lc@ H/}^4޶@e0 @$ @V%Ir2f C!YVԜL UR9↣.&WI@V:]EUJG+JQN"Q5RWQ9-JZAj >>_J`eJPKPȨj>LR\S}+RGQ^*X̐10UXTrSTzU]8!)+Uc TʕT`b=*%Pp8ET@o2fG`3mމ 01{4t;x`fJjZ6)6MJYf[Fe?~fz;Mٟ׾{n=pdz]*m]9="zg2oyx4|wp |7v&4kuyud]mmm`" "?e57*Ħ;OWale GHH*@ t$t)T.6UADAml(ET4"5lPa @(@((d&2ndCM4iL %0UT OAJ*j dɓ =RT) ԪQhi%JѠh?.w߸ubM;`NI щ4;Չ4q:ts{]ڷUW4=-sP懽Z[zϧիp$Z &PI%`ls{j6>=qw>ڍϥj6z\Ls2^-iOjxu`-ąشFދҼ7K>a$49ƴmmֱZ0om*5Pյ S 0Л_Uh*l.6aX1L1LirБmkeJk5YiڽO}ӧNkVZ8p./Z`|3X61=$? Rc۪RgK%%vebpwQ)JRc)]ý:upbÇ0p\GꯧOtKWӓ{:^%/U^{ry}GKĽp9<׾^~kxj~kxj~kxj~k\ىe}EaԹU.prytK_ӓΣ]~u/Wxj'*?NN#.Ux~G \98Ur|'w\JV,U?}p%ʯǓ>Ux~=R]:+ORt9+M+SiZw>##/V//U>p+^2>=--jUp9<׾KW<׼xʮ'xʮ'Qk֭id҅dWZdE\eb+W?"+"yY~WDY~S#+Sk|kл]nbBMA6YMN-P FV0f$jY,_rQfR򸜨, 䨳+?JrYTs}YdN2f.vӣiӦDάQSY8ce̶[M[4Suddܱn>/ƵETey\NQ~2'(_̯+"*3 r!~K⯄*&I m͞l@DUihjMi^6(RGy6qGN8VU/f+bSeĦ/vp: q91l8V\imEjl|K(8&zM\Uh`ƧYYDXJ2T*lb"jJ}K1D\Q[p2*⸪ҏ]j[jZ[m"M}U\VwXg7]kͩi1 2>4*SK.lSJ]uÏ'^~bNnK@23$SRR2LTTlTJ6 MIdF-Jb,MlX(ZY$Uت" kmTU?"""""1 """#DDDDF" 1DF" 1DDDD`DDDDDDDA`A""""#b #DDDb"""""""""""""" DDDDDDDDDK11c1cu1c1cc1c1c1c1nc1c1v1c1c1c1cu1c1cc1c1]c1c11c1cu1c1c1c1cuc1c1mT8 T6ml*UaV­FڣmWg/fgrldjMR ʫ2jpWom_p;Nv޺itnu륥o{{nFkU|Zwv:wnrWڈGNrswnE|i;KiMel-r#vlɺ͙6ܙ& 2Af `dH7okI{.KZsZpwpws$aIi.{wy{ݻwy$1&瞼{{<ֽ`sfMmm͙41f0̌$0ndaI"a0]rvJݍIs\J]""WY\]5v\+"܋]JmҹJn\뺫ōr5t+NN.U\1skIp)ݷ)ݵҥݍErTr5ҲW %˛%JmVɒCja+iZ  PѠ1A@ H/$ę$qe-8K,mȤK1,KmW"(@BADE-*P- m%DD@D9s?ꔡeET8hkm(4̀##5_—ʉ>Oʯp",.y8W>54zҠNH8\*ʮWR~*tK5.rpWJ)cUq.'ľ¯* ~\/^NQpS\K®N*pUĸ_ jK]IEWRx4I)ڮWE.Uq.RNu.:K}We e:\GWgNu.(:yU\/H'TgNu.U/'ʯtďSjzG}Iy?NU}Kp?} c>j%~ʔO~=NΞ꺗Kߕ\~*)>9]=SWT}_R\G7WRp;*yU/|O,8/'zEKOS]K|%#\]aOt+ Or}<>}QS~OS_KTCœ\0]2NV_?$\GIӳڮ>i"_Z~<].#^ELWRq=TT^tt#;>].#纨֞NU}Kq>j*cOڮ%aTtrWRq>"ztޮUԺ\+$̾'z$sNgjKTKy=U}Kqj>UL̾.'zPO>yUԺ\G%#{;UԺ\G%R_?]_K"tQ{>}Kqb]IOԞJNJrD>49>jC>]sCwOwOmmV\K¨W_P(eNҌ/WUx&`ZKGKJ~a뼛7)ÕW*{A|!Y.@Y@/UGTzR/j%G}i]"/Uz].|>|Kx'Uq.@GꮥiJhʮ%:*G)BzRRP"ѥKAh(VhѥKFѥK+&VLTHLb(ZVZV!ѫV11c1j+jZ4ddbŒjUimmK%V1iFF,Yi*M, li0`ի,lʹ+SSIVik[ddbŒjSf,C[5iM& Z,ŋ%ZM23Jҵ54L5cM4mk##,KU*6YeYelKQj-!0L 221bdV4M6ֲ21bdV4M6ŋ%ZM4##&IYe[i21bdV4M6ŋ%ZM4ŋ%ZM4ŋ%ZM4ŋ%ZM4ŋ#IYeYe[fԚb,5V Z+SSILiddbŒjUiFF,Y,XƚddbŒjiZVIŋ%Zŋ%Z##,K##,K##-4M IbK$$Z4M6ֶY M& 5j-4Z!Y ŋ%J͖YekfM&IV-21bŋ%ZM4Z##Km[?tsV9\/WjZals+C&29V+^U{s\+k$:u Ħg vtN.2ؓ sE]](WDV+/¤IJ,Pu2=CRVK jq.!XIi8'+JK +T+"%Rq' 'ШǪ=E+Ih`TхFФ)0#.)qbi$%(*+%UG\Q.J5Fb(IZN *Y eTL"YbIX8+*K&C+Wq"XeXb+qK)`K%K$%,WVDST%,R2 `$)%P%u^"JrJ8Xb&D'qJ1aQd ȕK/;]J9]#ȋ*+̉[KXR°ȕ TM"BjVHS U Ԥ[;5\5k\3w;+OVT bb&QjU 41YLIIX DEVU0'aI'K)4$0Q) I&UJ2d +.+$һ]xEU⮪WjdQaY1Y2LJ)*bDYL)őLW:ZT1XHY2*]Fm1hѣEUF+mM66ڛ"<@$p+^:_R}GKĽp9<׾^~kQ/u\?NO5x'tKWӓ{:^%溎v溎v溎vOֻ8EGjQK]998ԹU/^|/|eԺ]:+ORt8E,^}!vW.vWӓ{WKt<ҽSd=Wt^%jBVF5$UQUhDE½Wꯥ~+U5Cľ*W?C 4DbiTRp/i\O򄺖]~P鏧}>ONO}=}>_ 5U-kYHj"PV%H2pꔼS?Kte0 @]JWjbe8AzzpQ{UK½&USRZ2zj^)LʒiT{+:!{8{ON)+Z>5p~'z8E/e{(%}8W}_Od// |>Q*|RW}iOӇeU?_^|N%Kc/Z58B%:*^\NӊqI^ūǧ!½:0 Y*^E/O%~ W_O〗~+HO}v\PJ!¿(+ȀkVJ¾/on"/HOI?BRNBiCm2P4T!9/Z/Z|*_2|ȶE"OU/A!_>A_IN:RNU֩%~~?!±%E _ק21ԩ)GDžI/ĂҾ~.7;&+XÜcss 򫯛]m[S .@% \kM[V%(%zx/2PQ½]\յdRxv {="ʽ:E{1HL[4 RcwvElsl,ݺ,[+Hnlh7.n4 - e- V,$ @$ umEV!6mAQ;.\p0;=GbejcZ jű6+űemFhblblC ej-*X6VclVAzG?ㄍ)R1Keū>mq3'إsT*M;aִv_Bp*#DHոg27tfNxlRX* ԕ&ZM;e.D2IR2I9^]B(F[՜ky9: mÙ% $ϗ !T ڛGUUmI,:֓NkulOmLm'6mIۛI+HLbJm%oI6 mHۛ[3mn͵p0a f1km`mn͵c6m1kpmہ lOmLm&7e{Ysq=oI6!F36+HLbJm%oI6!F36+HLbJm%oI6!F36I[LbBI[M&1Q!dMf$4;n@Q) @* IJ(@@`==mz ( U?TUCJL04~U 'Tj4zjR$C  IUj465Gz'P' 8OW 8>z' 8>z 2}__@q?\@q=\~zqqOW >'פ:]}u|]}u|]}u{@?ifͶS`VhZM@ ? 6S1mMcO@ ?̍lYڧ)ƖmVO؃~?'&ɲl&ɲE >ϟ[4 X0@ 0dȲ$m 7mkvڶDDDD`""""#b "#b #DDDbDD1DDF DDA#DDDbDD1DDF DDA#DDDb"""""""""""""""" 1c1c1c1c7q1c1c1c1cuc1c1nc1c1]c1c11c1cc1c1nc1c1]c1c1뱌c1c7]v1c1c1c1cu1c1cc1c1v1c1c;1c1cwc1c11c1cc1c1n㱌c1c7]v1c1c1c1cحjʁJJj T6mPڡCj T6 T **)al6 _wwuU3;[KΎv;86pmv;t}{kvיFQeFQ{oV-.fwC\,wW9^uyx"\l6 aUwwm;t86;tyN:@뫩RWS^SRu׫T|uu>=@z=@z'_]OPzOPI}OTRx!ET{Wű|-Ȓ㫩 \\OjP^`zOPԤ㫩ׯWڔ|uu>=z=@{R{뮮jR ER$+X# &Yffd@dɖY2eff@dLe&Yffd@dɖY2eff@dLe&Yffd@dɖY2eff@dLe&Yffd@dɖY2eff@dLe&Yffd@dɖY2eff@dLe&Yffd@dɖY2eff@dLe&Yffd@dɖY2eff@dLe&Yffd@dɖY2e@dLe&@dLe&Yfffd@dɖY2eYffd@dɓ&Yffd@~G6-f)6Chm V elj*L)JR< q@UQOA5J @2^)KU'R/ E┵QhEǐ REx)j )KUdYJZ"RE,£RhHKx 2xR^/xRYaR^<@g<,xRYaRYaRYaRYaRXXBQi*z G'<,<^ 2G@aTT<dx#RS 0*Y*dK%L0dF,e ҩChm-fIZ5K%L#)b`HZEX& L+J1FR2 Qb-%?OC8NEYQuQrY%2@t<@u)LW 8W 0Lej4Umwu]qҪ%X^ 2! ?(=) ) jACT!bU1Hb*1LR) ES"CHbA!!WqyqJX4)DŃd RqqU5UTTX* kA1A L"# H3m<^&D=<@dC 9IҐ1AHe^ RJ) %SC T!bU1Ha*0LRJ) C uHqK\*,\RZJd8HK,2N-(ZQqb Je.8㋎^V2""52""5 ib(DDQDbDDDAb "" DDDDDDD" D1b lgHz1!8NJCҐ#AC T!bU1Ha*0LRJJ"J"JIWQ&D:xȇ\R*Yqr2*qǏ8(qHb 8A蓥!ҐHzR @a@!׋x."⫊R%2`p8/K2ⰩfRT8$.8IR!!!@rҐHt8$:#CC!"."⫊R%0q/K2Ë¥Jd9H8 ^:zՐ8'zS믮:\@q>/:O?P% $H 1DOQ~"/_ȿ"E#,///E_Q}E_Q|RK/_0łJU}}vJvi %9-%< )]@=EIM-%:]r?Sz)IO||vJ@>"S|_SZQ`????%} C}>>>C}????ʥU-(?IGe)"W]qJq^SRQz)N/^<@zJzR]W^ Qz)OW\RS@|E>ϓu6lٳf͛6lٳf͛6lٳ^]%O~Ԕ|E>/RS>=IOZJ|S#}w**;̮y;}J* yev{;{|U@UUUUUTUU`1ؕxv{s?^VVVUVUVVVVVUVUO2jFy&4j |ѫmmڶVӕ˶^hԫmmѩVVJʪʪ|W^@[g״ѫhϊ^+( lW5{@^+{m^W>x">Q{8nr8t;q7wMʪWLLizCb 6(lPءV<8nr8t;q7wMʪn;>~_q}{kޥ(xWx,j*a 6(lPءCb[=mxuMnUUp8t;q7UUUUUUTwM㻺o} ]{sRj,żZYxㅘ)f-R=UUUUUW=^Ͻ{|`>w(8{@ʢiEB*Uqr磱7l;pةe]tݰ8bvUw(8 L*TT-2ZeQPʣj4^rxU L*TT-2ZeQPʢiEZeQPʢiEB*U!iEZeQbTTVnwMSvʻ`q7l;M*;tݰ87l8vlTݲnwMSvʻ`q7l;M*;tݰ87l1AY&SY1[ `MրĔ!D@HΊcÀw*%( @D  h"{" DԢd2`'JLdR7SҪ&GFIThm#?p69T9BFּ9ײ!00[Tl͒iK6If,%|W٭cjmoLf@Z24̅,́fd 3 WH' {I+āpτvlj}o8yCeMmj.>}Uʹ׮;]ǀ h6l6l h6o\w]V[UͬkLJږBy WZQ@Z|  h ZͶK6ʒh^!LYYCef2i+1Vc,YZ1~abdZG_8ύmm)Uqzjj===?Q^3Ǐv$}'}Iq83bGy\N) ؑWC1?_3ZS4kNN7dfbƍZ-%:`KiKM-՛vRD RbGf<'ؑ+!$}&cqH}u^jڶm6Aw kZ@zkI[ҮS-hj5UY-e+*?Iq7l#`J?Iv3˚#jbj ?'!hڋEѴ!DI@$lTh5;t2#S Z,)aa ʼn4ɖffmVD@@@A?MkYZַ#b "#b """"0DDDb""""""" DA0b 1 DDDA1DDF DDA#DDDbDD1DDDbDD1DDF DDA#DDDec1c1nc1c1v1c1c1c1cu1c1cc1c1]c1c11c1뱌c1c7]v1c1c1c1cc1c1n㱌c1c7]v1c1c1c1cu1c1c1c1cwc1c11c1c1cc;1c1cwc1c11c1cc1c1n[ l*UaV6l*UaVmPڡCj ʁlZjZjZmm/w*_~9^["g:vyN)<]S)g邘)` `Jclj/wWvJ,軖r5dmyMxp6<Wl({RԵ-KRԵ-KR=u:0SvyN<]S)0S4LLqmlllS\p6{* jZjZP*Uu:0SvyN<]S)0S4LL1Uojy]=u9sb{<՞yNu9Χ:s]ILXĕ]{{<ִֽՋv:]/O"Gח/ RyUU/ ļ/*@}.KRt]qr\]T>/)V^IO*&PE)(/ \\H*ץqr)cKqr\\eץ..E?\_S=}uxȧLR~J.ԑ=\\H*丹1Kqr\\eץ..E?\_S=}uxȧ?LXx%r)z.KO+9r\\~G丹SႫ~ߥqr)A=}yz^%r) CUC A(*8A29N  1\4G QF0aP†+MN#(ȣTFp8 jRddhQ#R W-UF$BQ25HjL,%LI09~J.UQ˒u%R9NTF (j!䚪'J4jPCj58Q#TFpRL)125rTkq%R5Dbe(j!ȱ)`%KEʪ9rQtTG)ʈล TIp$TF, TSUQ¸Qr35PjRbJ5DjPA媨 J5DjPQ;56sh,UrVj.J.ԔjETS,)+&a`S(# D)0U?+ZҋUIdx:2X1Lxxxq"x,./$N0e(a'Mkjm6*[Ebd6RD )^%%+jv:bE цј(\\VV+YZkEr2XfĜMUUh *K0,),*XH`JO+ Yt8:* JēNeP`t5Dc*ـ6Clm6I)I$ I%)$RIJI%)$1U^z뮧Hyey^P+vqBvJ?+.}G`>|b|>#~{Gai$Ҥ&(_Y$tQ#$8`!:-]j0`LR> Ӂ'jW=8$}Uh'zd񫁪ӕ< TZ2xAʈQ*UTSѥbbz>OG~O>|=|>{=ϩ>Jʥ%T Tj#Q5uӉPQ>OBƮATGڈ<9T>OjWʠ#Dx Th'zdPt<B/}_OW\8|_a|_|?{^kA>GƃÊPD` A:-]j0tTQl- FѰl- F辜/Y̝$ߴf 4$?<,_г{ۂ 7<؏a6SC̏ٸ9͸h6h6~*f%g<UhYeWĴZ,~*w\*|E~o[m}ph6 U(XmQOD9Dک^hklb| H?" $I6QT:Ou*^e_(§FQ :0 ;a7/p' Z[ʳj7BEnn>|~YcӷSÕ*ttjeSccT;}%}%}Qn9Yb|=*FCmmZ)ZF،(̱ $1 `{1XıF1Ucqc+&1 `ً11C W`j[;qEuą!unvgxJv ]RTW.qNZj؝ Ce-Z Cb+AT2Qd0CbC*2S!C(?xb|&S#O\>r)9s勘[9<צ͑y\Fyʽ#cղ9ղ9ղ9ղ9ղ9յl49յl49յl49ծ>epU_R-6&.[}#ǜWsj}46&1ͫeɧsjriڶ\x|Ua21dp%Ç׫˙K 25kXZ1Fˉ;rw]; \aeY.L8U侞>yWxp峳㺻NNY;' Xd{LR0~Q\M^x;Hu}g~* '||_HpF bezW ~^L8󫾪l<0uw_ȗ~b T6 {_T5K-}+5C*AmAh0 -k,akQ~/E(E"$_|>j7ZvmRi&\_E"$_~/EHIȟ7 uuRDĪUڇ"֩<&ܕin86HXclUlڇSai[ m,4fm@՗UG_TVڶRRj jjn޽gόVkZnDȒ&$$MrHDy{"H2$I"H2$~JJS"T1fAZ[J5֕,RMll@@"DF>]mmDDDD`"""""""0DDDDDb" ADb" AF""""""" DDDDDDDDDDDDDDDDDDDDDDDDDDE>c1c1v1c1c;1c1cwc1c1뱌c1c7]v1c1c1cuc1c1nc1c1]c1c1뱌c1c7]tcڣmV T66mPTm-? >/Ds&UcxppyzTiOVTn/;!%nݽo5-:@=P{erwolLܓ:avQԩ8{TAWAQHҕu]WێDԉSprVDFێs"Ü S/sY܆sYqgvmvkLYƳYR:R:^..`/@[Lgp3"g3;mD9܊m m;]5k={tZl!R:R:^..a2Fu r:jAVB `C+tZyԯգQ֩mMj6cQmW!CB߰4R]RB=4R]R 4LD5I5MUuU""@VʫmBtI5*m%/.'?yTɒRyTQ.ԺLJL*_E&K a6l.4ک2d&KI^0_2_RL2d"ɒHM--h)\if˕s6Z^*ÆL*ғM6lzӇesRz{/jW2UK"UdeJӇes!4ٲʷ%z/}E?-i̖UJ&%j)4lUqNeY/}**N͛,(ٲoIYet ,*jY-IL]ld)VqӇe^uzzOgzU~if*S?;4ٲʼE_]Ӈe^zYW^$}HrT8 8ԌF#:PLWU 5b*Ν8}>UBSzkM,΄*6l?$zkM,%__q ,S5MUhtNeyJ~첯= U]f*%:ٲʼDN;8le^DVf6YWW_qf*Ԕf*E^}oN;8{=UJgޞ==*)Wn6YV$~n6l U㳇e^~첯UE5'ؓJ*.st t|G*p58GQ8 GbTKSjh|4=wOV4>]k赫wzMaeDIR6l -bBU/KJTUI ʩI,Kʰ"deUYb2e bL͠&jYFQbbkXa&Yjٳ30R6lٳ30R6lٳ30R6lٳ30R6lٳ30R6lٳ30R6lٳ30KKK,ٳfJ--,f͛33 *T͛6l$+jjhIJLU5S)e,0ɓ,jիZֱ%JYf͙JYf͙JYf͙JYf͙JYf͙*ZZYf͛6ffTiie6lٙRlٳffeJYf͙3mRRBj)2*2bMZ&LիVkZ 2VZ0ɓ,jիZ 2VZ&LիV0ɓ,jի 2d-Z&L 2 2dֵ6•+RV 4QZj ZklͰi((իVZklͰXDT͛6l$*ke!+&L-ZjֵHTiiiie6lkZ3l0XR>8EQTV6+WyR[KnU쾞c'f1ή'f1ή'f1ή'f1ή'f1ή'f1έeɦ1έeɦ1έeɦ1έqTU/i=^DK٦1Vղiղ9l4m[.M<>cV˓Oʲ_L8|Ua21dp?uoBT%}.OOLc*}0ʼÇ*^?ktu=.׺z]' Xd{•/TW>k]RGIW}Tl%9;<>xW}T.NO >c]Ves!z(VF("JX JQ`A? rrA9 rAA9 lU=^=UUY 1I1j&@dj2iLTQbzL(xTu?'tGH^QÉQXq#uxzKګ)z)⟋EV GآUrR<<9QW84z; 9^*%QcѥQ{sP v~+c~NIW]iJ%6 ]]a+Ԕ6IC;TH:[< [[_W%U/gg{^~_*U~'''''''"99999996r{=gd2_(?.'ir'$\NU#R>Ud2T^ϯ~?!B!B _C>>>âd2HLK}f1r6l*=J$eWD͛EU%P+jmml{*wiWTKʦ\}XD5STI.*q-l-[$ѲɵY'YրRN@[J*ւ$$$$"BIDJ*ڀ:$rP9V##'_DylCv2D?rL&Io&HtLOὪ "">1;㪯=k{ݱ3 f1|!O+2 M6m6 Fl`3dرC_{ފ\,Sx!j]zޭ;vYvv7vƒ˶n$ؼ^GI՛>=͏McǦYvv7vƒ˶nIӶ- z`sTU_8fχ|z=h~{QԳ{Ϫ80vqyyڷ-Y[4][|mppp*9ם8Ts:tppm` km[vmmmۣm۷nݻmm۷nݰs9s9 2| -Ʀ S>'T (ePhk3*rJ*٭5xPhѠ Sz)FAhI꒤DJC@)(R47ε|l͒SOtd4`Am42j,lQRdmZb X[J4-lBic1)SffbOm?ʨzcfX@65k[춍Zbjl3kٟk 5BR6X52_aaW-d&"{jC֛)hG Ll/= Z{kX_^f<4<31G"_lm#T:bɵ#5UI|lWxq\.F2 \~/橵[-1/3*5|j3 Y{d^2f%4ـ/R5*/SJ<5y{2nNZn4Kbp-3Ɏ:N*r9N+hʟO0V-!i4_MSƒj1֨LI񕌩|TH|1&2KXedSdʤc取>Xaܻt2gdȽGұ=.ZEG.!2ZU9:8qK 9`+Wye6,ڭ~7ɗTѧ쥓Q&++O('mUlljccUMQ ɩ&fLaɔdYT b̲`beSL" XʲdeSFW(8R\W*GÉ-[*¸Rq,q,le\}.abbRVV"qB1G*Ⱙ8JT(p"\ciY3JnSIq S[V&YijfjɔXVPp1b Xج}1c0c0{iKQMFvbe-T:NLLN$'S)j'nPɸtY0F%Ii aNܒ,tnBrb&UIŘf}f}y-iFR2LDJL"ij+2Zy1ed6E2g:2dFƊfT<(0F+# ]MwhfeGuSblu#mL_cT3KAmfZ 0Ur5F~w3f[7?ss/'!ĜN˽.KYud,VZK]aaV%Ys;ٮu\O#/ M[%fɀVI{mϼ6i{9+wt:G#]\L5e'x:&#|Y5mlqݻ+Ɋuc߉'Lɣ|VZ(V|dC6Gp\S:5įȽJbɧjGg x4u^8zVbdrxi8!c[]<,X<) D4RKUWΊTʑ*]%:]U|A_=[5j 4[MZ6j4fBIJx D-W3fJd_\.fDaQs[XX~Q-Z0F%KH?͛6lٰ"""%1c1cu1c1cɌc1cuc1c1c1F0ٳf­[UV0ivzB4c]9:W_p鷮{֭uo+ZAž=۹o8tءVZFw=wwna1syӼ8J?% J1 $ @$ m߽p-`Z J]]].V#UP (ehQQGdNS!0XcKhՉ1d0$TMC\W"Q=WY&:!anq9dꎉR)bqsY.#&jtR=CZyI4 ¸RZʏr +riZ  ifq8!yB^ W^qW˝V'UΥyH^ R#ԍ$0*ZK=bb 0jz*&=ReGҤy=/JlUrVB콖{,]OEBWG¬>)$:)=G%̵UUa*I!|U>J( W ȮzT>YG:6#zzuz)j)6v'.P+ш+ _*0CⴠѰl[-m4" mް"[ko[oE>:ԉ*>=TWڨ|AKJG%_T򀊿hURC*!EU`R$C)BD+ ,R2bHҭ*ԁC"A2)U,eU4XE ),j HjDʡFJ`S*UV V+")d%XHʔ*C*?ԤPS)@! %"V(j FR,R2)BҴ"ЖZLaS#*( $R4ꔫvjڮ$"P#@ -@$fq%JpSJSQ2EN)tJKN W vIB"%QpG CU LQ"*?RYFF6mYjLXY&,S,&,U *Ū4(r3Vd3LʛDZƍj65cXTG.❰V+ZJMhPO ] HujUW)Kim-d$W>!ň{K*es"/Dm-6jW "^Թ!xAѵ< a*DUm +0JQG%YRBBi(YP(d_P,%DKiK+ES~?XXXY) R*Ҙ[ _Vh#zLbI"d2L_!_Z+FĘfVTd=/O]?UYTe*ҲjKbK#0WJߊ>G!O;8U."ERHѢV#fȢjMVUk1>ٗ aL K-&`*^]wmziNv{})k{{n{$H"@ Mنmh"D!!"DB! !66alml i~bL0 (1@APPH@(*t DE!( K`A 4SUPA)*2FmT 5(Q"RQiTTfM +q<1\ڄ2*xbVȫ ,riNM4\ ͚7}͎3=,FȌbZ -PeI`YC#,Iٲلɒ,(gN812r]*p; T6fcK3e#:\p:]eflٶ6k31ƱdвGK륙0YNS5&%4BڶCcr]w[[Gu`uSUŅVdxQ瞸ed8=)p֕Rw"GʉuhTmv(y6. #j/d9KM%jzxңoUG +U4 ;+*H JH/ UER+Pdũ_h#K4KLG)22c..UYj1]6])lŋ,Yh2 ejY_S?lٳfc1c1c1`c1c0F1c1c#1c c|Ȉ77"""""""".nnDDDDDDDD\܈QPڡCjGkY>;rg8`<$<*5,Қ(_2X%E^O8M~+24Q5<}>:+\E>q,^]N#@t_%")C* WŠ"CU8/I>Dʗ0quXQrE-b4\xdv|t&UN!4}!Ck&&*Ԛ5Q2%qRu6"'>|EjlfɌ&Vpf}}>zlcfi4+xٽ1v,l/p(yPCB*(O*)S2Dh *5JF CPԉ0LU5SHMJL0+%-JhjDdFTʭ$XBԋU*V jC$4iP1 E51U4(h,QC"""E QCAV(_ ֈ4ZF(ɅF FFV",DQK MQ0&LHQi@5S\4F"Bjj*W q6́P0Z2ͳ1N UbHP§QqE)Ҧ% *Ъ.PJ%$UB(WJVT(|(6֓ZbkXPڭmu6 lfL,dLX2Ij*#cme̱ `楰mK`ږ[ ) *k1p6[[YV%8Gu:+'j$'1 C٫{'Wzꧩ)FTzq4Ԝ\^5y"mml 8Ut(t)8QJUAZX*F!RhmT>>VK++CP_V# ZűC*%*ʎ12%}~ ԬZ%EV ? ~j["OUʴ2La,&YVa$X5Q̵#A4WXcff0RҖEzW%0ډh%zEGsqf٪qjjjqWIŸSifbm6Ffx?~߾ɰo[DmUUT{.&¾YŵUUR[l*f׶yqZmo|7՛v $jYaFff@ $@ $Zf&dMeH fn@Qb)z>>@$4P(0B@R1Kf 4J@j{OT4Ԥ{Ԩh RQF&M>k,%5,́]ڢp4`mVBllTIiU6m#dl-Q6EcLf̪IUDUClūkmmPI`=m'fp(_ mP$J ب=5a=|?ꇵ6z+y^ȭ*#ZX~`3kptu~wUe_5i>bfV6`yf?eFbW&HxyޞV^5<6 CjRbգPȦQcGVDXŨb%XsllYkkհͬLcqbشdeb_Y|^/ IJj2F3BZY j$V3$YcK6.=uqbu+/?K&&ن%5.VjVegܙqZ=1|qKFmjcyL͙u95ZX᢮SR{q_l|5 r;F 0/P綜wl:xpGUO)#O0] yJw$žXz_ ZѥG+ApZkѰ,i8Pҏ0+௕S)|)|RW]xǏE=J|/ O:V<OABilMjSffJN2DJ{Q/[KN:J|E/T|z(R>ȇȔ>|R~@KK$ %SF h @@F@R1HĩLEdVȣQ$TĚQ1RM@FaULJ`L( A,0TL1(ґ a  24`AFQP(` AR1JFtaU@hCP)AQ-D Rԩ%d%0QX+DL"AaR¦&""+. Jkmm' fcfekfp:E('pI%*.%5" bGJR"|FCc`PQ$661RԶV4L0eMIVUdYZ4,HqN\& 63jZkQJ6FjfjfcZU.W{lmQɭVMlm-QQc-T'A< 'ju!кRld*x/Z)ZѭѭѠE.rl6 1t9"]8j^*#6m[5 t\ݲemP!h[hPV(h)iUUUepe%ZjVRi'PI'<ԁ}1)tIhKt.dlۢr$sznhpmB\(+$k=(85p $L/Z z )А*W\Aw P%*$P@2d IU4Ќ%U?4 M =TC'jR4Q`RQ&TƠ4ikוּoz6\jFAM6l$6 `*_bm٪H)F*$l̶]mf Z& ;m _-YX wQZFSZڿ?e=U+/2Uղj2'7;rSY0 |'&^{P_{|Owmy;3ena+ g+9uY+~mG춣lOeEl6Z5wijVVaǏ]|<ϙW{reW~/l\#SSּ̮.^%U9S{VrḰZK4fUҾ1('hcmjdJ̣"12fYQaeQL1)UUL011c zcD/*cLɠ4e0Ū,YZd24j+4ÄN##S"R8ŗ "d'\,8qdXY_S d6ˎ>p5jZq(q"˄K.*8G.RRTJEq̍9J0˒.s09X+q0RJ-m_PѢLջ9d5Ug8s8̆g89ÜfCRg9RNn g9H$s5̛+0Y0iFl0ML&ԫ$ՙf>L7L8&Y ? u8hZrC9W.q.Xhe`1 tYI][wG39&^Y8gh>lnkWۄOpbhY}܃9r˥5Qm_\;wthci[J PI͝tê8z:pN/4q=*TG=Q  'Tm'h^^PA :NJاKr#bF'ҫ2eh>є}(CC_@}>>~Q$ffі&VKEdZ8$DDD1c1c.c1c1n\c1c1Qf͜pUjbS^yǞW'N-dLO_SR!Էhc$j͉jԃt٭F,Œ"""Y7LRJ1BM,c&bɌY1&1eV@hf0m+Uj!@[mm+J+UDFk5fZLk5VFSKISQZj2ML#(# b1&&(ұB0SUXI…,,(m5Ub5 j5c֣V02eVCZ1d5:(?Τ5*@E fcRV-@D&P}U`R%k0TUmcfE(UıĬDbU `,"ɕ_U,cQ**5qINrGڌFkf)QW NBVW$/)11Ae,a&U0~UiL]9u)*69jYֺ9ê vUؖkusj4nqPNԻ # RYAx%†6SMʙUeOFF*еX]暹2KR+%!wgZY%&885{VQ½+;]sj2x'C!</<%%b4І ?JŤZT]]|se=Ed\fYW) ]}gƬ{=,v=EEv;.ӡ+%WxWJ\+]6+.Uu;Vt| A)|ªX ˢrjIb-g2cTfKM^Mj/z_gWħS Ve}Wc ^=WǷC`G!Aҏt>ʞuB` b^J^ʩKD*jF@?TWTWRJ5-**F+( QE2W !j)NV42*+ 21 G1)j)a+ Z XL&bF$jJČ IjKS 0 IbKD4CJP#Z(eUFUY*&&FFP*`0 P$?+"*Jx3Dd$RBYɩZ#&4IJ99AX&c,ʬEEJaL)+bV,SE,bS e(1I3 ZI5)$ʩ)bH2*Q E:A٭M͛b\)T<R,`j<筛Z͛Y6ۂRUUҥbJ(I$v ( TTxJwH` VU2QJt4HHI+(Q`Q $`"L$WYA\-̦e3)LB#6F2e1VUD%O#V.*Q/+GKpL'rU _QK>+KҫN|$D>JJ/S*K*UN\i(%W~?O_'z_ZXʴL2ZHA2L]d4F0)3TRbbHʣ*ut̫V2Ya2*+ʵt_ej2ZbdUcEZZ/3-#I5Rƒ2˩.̆0MFET3NGMDt@ЄI >>>6jmZUj!> $! Ot H|_Wfu]#xʻ7w{y0Uٻ{uVbs;lmqKmֶZF#fm$H @$Iw1AY&SY~FZ[T~ `ـ2"("S TP$TJ(fM -(L*@ UOR#MI꒤hhMJ$$)(FmkPlFжliխA~?mmj*QRFZט m[(OmZ(hx#$x<ƀjf6ҞmӭP;)ʤu̓, {ۧÃ~uk([J{u6+wfRj)yJZvvٞ3vcff;1WEp8)~kYiO3T|řGL53^202fL) 貪"E/B/AE_ ʔ>$|TA3ebZa+nm_4DDDDDDDDDDDDDDDDDDDDDDDDDDDc1c1]c1c1뱌c1c1cjFm^ >}{ˡtw6ܮ{wvkewöjAkݻ]v;${y{d5dյc%jcbW$;fl"#Zoowwswwrwwsժ֯amI`m6m% Hcőd*Y,L,dV(b L%jV%0(L%11+I2*X Uf5̃e6iVEXVPٳEd4d6lY ]JC,*(EJEʇhU&֦P4J=)NΜ8r9+S9+եe,˜qsN\#D\(r*.vvqriӧjvJUu+tVB\rvt'h.Wj ?"Gsnܻ/J.:yEGq;T8-+BBՅcKKT!T_{ջv{N^^\y4y\ǕxPO/P. u~ Һ;axpjʞ)zQ# Ԥz(TRTZyC/_uܻ;w߅<@z=59WPW5m3l)t%m\t/(iNObKТzH%9B>REJBR Bj)N*+„W!p8HKB."#r\ʁr S)pEY(hSDXF -Ib2MJjQ5Ua# dajjiT`SU)jHґ&&Xj)ZV,XD"VA Ī]R'h- )%bIp0,p0))C1CL(0`0ZP *. L .U ;``mmr t"RL$`2Uԅ1jmVUE MP'UAK" 5)L%S$슧D8]$Ue!RH.*( HȄpU}J!eJ"JV_֌m э,KKjYj2Ʉ & ,,,PR~R Sb(Vb6UZ1mرbŋ*QR?uґW*̕+e6$j;Nϼ%v}vKCl[-SR˃!zCq?Ė^^lXRሽJx.dxeB.bGae*Tl.;U)҈E)8XDE_|'}_V` a!,S*HXF2b# KX(* Rd"2Kϟ>|x5H*ʬ*V|q>jR5F21YYPdjiy^]$|Q5jkMQ,Y;;u |+32RYS'gn/iۢS$$_gwm۷vx=w]{jWՐRHAI4OWƜfb.*ӏ ,if"Ij*یu.]oin5ufAUEm @!hZ!hZ)N4m*??@0} PQQ*)TDmԝ]JEP"@Q@H)cM(CP4 @ɐ5?jMP =RBdd4 DE4=OPhD*֠ ֋[Y3Bl-FEkZdEZm$E -LimUOmO26م>EHZ]J *HXI_1|d;d3-ʧI/g8Kѡ=*Vb/%Ƈ ByG8'BSqD0 (W R͖QiV5 +Z?j̟YLQkPW( JcURWV2ШjiG&GYc,ј1'LXeR,a31VNc+13P#&uc2ʲafLiC:Hɓ&:c"fK- )LLc&0cS 3We8 "ӎ1Ӝړj,lbaaVɗfN-r8^>,Ya2dL&QYdɂJf[ZJ&V,fjeeWі)1S,:\Pp8ጱ qŸLZ%j눸N8c,8t2.殸2酖 Zm'&uJּLIp0p8F%ݭPGF]b\qfX>Ì}x# XbʼndVY0F 21{fV4m5DFͶټӑiM V{ $Lny.ݺ[l5DA4kĈH%Luk]0ٓ ҟk)"o$3mIDʲ;\\88N.\SKVu/GLZ:4d80t4ymgۼ5M4\\.*R 2p:Yuӎ3|:c1%q'u+, Epj)prcQ=Mb e-1c2-pV^$t0`דiVXb1WQ2­FUlYJi Yhɳj- %L-ikJYXI`14񥕔VmiF5V+%+ZfS-`EKM֖YZ$*iHUi fX00+"V"(~`C))_~LhYe>+)|V|i[YO=+kkHhK`gUGHWekB5xBt+)1P)>}!2O|(_$>QO_*("$hR`j@C/>AҪWdK++,bŅ1&]興b21c1cu1c1c1c1cub1c6͛6l*Ud43$̲n^HWȅ?e*B!G a`I,4B,XXUaS(ȇ"q%'%$( p8W"p#.PrKZQdS ҋI-)5"IJ,1S2U" bīDaj)(X*ʕ&TLE0 FFQM"b (QB"Ј"U?T%T Q,@.EQ&(4U1*aL)L%P ҫ RvI("ȥ]@.0ÐH:*xRī *C%ym4 @$ @$ A H HJryEX T@ pDiJLRU҈<4IuJ @D *($+Qr)T9B")/BW#m,e̳1b+$kZAAAYXɌa*ȉ?9d̳&j9l6Sa e0$Ut&&kkk*q"WĺGlؚSڗ5V\b?k§RDWM[J\ٳV%^I#fԧTxШ RpQM!Z _O}O꾟i_CRZ4,hT5V4 aeeJeK,R`MLdƠ_OK-T,&H Zd%FĎOVU#&IU*beH'yYž#2aVL*2ćcEe2LKPԌ8(/.R"^[;4-{҇*C w몔n|+;]>T|ۻ=yU>%R^+$wwp}H,IVHK#%sb AdAdAzI&MfI5$k$YMfI5ԒAodMe2S unAQb)kA E(P(sТhB(*֔JT;xh2~T T 'U5zԥ4Hz@2Q*LOժj`5Z$RbFB٦j6`+UWť$ ?mT',m^EQMj3H.PJ}##dQTtA|Cf Rl=6`e/V_.K+ebe~vнTcj:6 Q*.$jD^D2Sn'18Wc%Y\vZcIh(M3SdͅyQY|,IebG</YQt,B:\p/]c,)eMM2&bbBVѳkK٣2Q6=jР8FLK*:bɅb(ueLKH)!ՋY&1L$QIőC T,-`bZUYjT|00°˜aVUF,0`5^& D|f,z9pkuӣ pc켇QU4LBjT\'&rrٶlri NNHddmZ,VIiM8Z*rˌSĩe)K4\mWqY3+/2V%3-k@5 i UfVWdiV22x%ZnEUq[&Ue'sh4\UdM;D$*#qp\?u^.FYef:VXɆa+2+x7I]MsSC³de8:&1çe'^ Z:0OMVaKA] puB/C˅ʒՌȏRƊVKTpAS 2L X1-44K2YXKhY'UGRcRbj+"U,1 2ZJ:6-[a-bMTV4XXؖ!_&P:-*ʯ/_ijGDŽ;3RdwU|Kb}{X/UAWVt^Ty*wx9JzO^J/|]'-S6 6|JR8 Q>RG*>& }u"$I&-J0`R*Ru)"I9*9!! TUpqT8+G8+EhR-2 b- VTRaFb ALZ%h X `,AL`&eDʉR)b1UII"&j&!B]RWRM!䢨BGJ!U#D82!C&jCHXU00#RHF:RJҺT&TV$!U#lͶƶٶU\.&RH$OOВlbmUvU/% aEI`*t)v"L Z%&R.RDST $qHI5R8$BZJGJZ RIkQ1JՆIa0@}SANAZ+k1$D&? ).dp=Q=R=U/ /A䔺t DJ\*H%M+AT*%yO*^O$Y EYVIHb20Ѫ %+LDMWji#`b LTclh%M)`02*2&2dGϟLBh1 bH\ R`r@A,GVv͌y1Κ\2y<< Uh=.7 gg= qjGgg=^7Cm>h*Ggg=;xm+kbLp ZQ 1@8{(hЦlH& (PPQJ PmVjm}P4 LҔTz@ %Eɠ HE&DBJR=C[AQi*m@mADmBU!P+|*4AmkV[+lHj}lI]K[J%l^IAy^j-BJf%꧵I{mw.֯$b-I[hY\w\:ug 9WC5қS)}6Cm-/̏-_FdǞ}^6Ǎ˦lf+Q;XEm?`MkiUjEmTBlk bY取,X|-ejzZj<Siв AеY'XkdYc5fYij,JdmYfJdmYfMTelVщPԦIef1Q0,13 CQJ ,e&`f1ATf1$GȲd\B\E J.T.Urn *PNrbZE94L\\Y)NbԘԟfg"aN9G16e>D*9?&4U&_\\S(j8B8qJ㊬T%Xd͋Xʿ0`X+``0`0~ ?{Zʖֹdj&,YLZ9ZV4#\WAem`"3Ŧ[#/,e/6jLSi -mY4 7halVqYq\Net5e/5([3)\\ח-Ѯ=93Lی=זNN4kFmvS-߼36g;~s:v{tӊ=pҜh?"Ѧ |#Z2fT'%iێ389~cn\Rw-89׎vuxY M5dc,|k..zlluayrVl*r͉SMh2LeYz^&a`˔V‡i$ҦLeurZ X%/ZZfhYU|H:Ȉc1c1nc1c1c,cu1cm-[mWn2ӷ`VL5\^ֶWsvKku9IoZnz5<ѳzMc C[[6&R=oo}jo>!]swڿf͵&d j4`1j&DM4E*Ťed1bFJae Hbb1)1CB, H`ZԳMh5Pi55,Ҭd4 UYkFe+4*Ŭ#Y4*ŬHE(Qae*mm[XZh(8议..ĖPYg8%5  ]EꨧB<8eNDi*uW& RƳs:Qtt2]U()3z#QO$x^A|O,11021,'GK>Ϟ=*U%g;錺\,"€0@ @$ rZ, 0DBH0 ! &B@[Up#G"W_pF]r-Vp,t QL-PMȦ*M-UV"t _PVIw; LǼ@)B$(&( NGx$*IH$RR P\(2d 6QU LU $JH4QRU MID)PzM4LeZnw'1WTWm֮{w]sݴCU _mzj~%r{)'⢞P^P 0RKrԡ_-.wxqSr>Y.wP{~3fq_5Vї$ҟ1!|e1xe? (> Q9j$᏶w3:0|h'ľݱ=j^ Slzzykdݶ+=.lG̽+fC}|}}kMO|eO_[hm&Qz1S(b}}V/Kd}+/}FGyS>2Od_HcF>SFrdlLO?5^{%.||5xe/)~1U>+/mfBOb0)jƖ#`c) \8Ê.\9rg UcYa45-5cэ?>"1 uz8JpxN) #p8%N]NqS)G+%MhkB֊̪Ł2`LUɑda1FLTd2e4/TJEjʯ84jX|T1qv2W9J|8S˃e\-hSwKr\orѣ,83{hrN-fV?#3%I},n#XZϸvyN20U34ߐkZ92såupx'Lec+*cx˖F0p̵^4RyQ{=ZůqE8aYqc˚0a*ejejx%d&F`Y$%=^3ne`Z%nG&aW 2FWB]R/mCIIyd\ r$WRĶRBN:q,Rؒ -Dȿ YSFF)r&hĿrYhĿrLԭof5.-mkc>6mU/}{b^z[Q:O :tN88LههههM*=U^+W+UUGQ}TBU_QJg$5eVɵXKQTqT͛6l"""""""""""""""""""(cc1c1]c1c1뱌cc1nc1c1ۮmT6P_噌gܜX\=L;q\%-^KW@k^hfe̱ẌardSXQ,F2&"X,ڤiR|44l=wyc9j;\O\W^3!Ǐ'UཐR^++ zqN.pK& |SZM.TT~IC='DN%\BwcjG|'ҫ |ПKXXȦؕ41ԭ _I%Di%Dp!YMT\UBA(9-Bp ZM(JL%IʼnC.,\gPːahJ!Y%bdVʣBj&B`i+Tb)S VQY VFF d+"EMT#HS(SUAZ VUB/PuLX)^X@P$MZL&R\\\rЪ,Z#A5(Ae@ŒTRXL%VjU,Yԣ* Y2,dS,EFEH'UG Eb-h4Tk^UmjCXDBCD0t<01C j4S`KJ"I:RJklkf)<0CJ+ZV1*t@NÁTt2*XQhBiM)% < U"*X(JE6IUh%Ȩ+ ,iR,TiHY"pFQ(_)4 |ҕАFEsMf3*K2j-2fLə3K";"8UB8qQ,J*qYWqBpGeG#<]Jk+|ea(U.a(0SF^§ZBG0%zlINa)h֨_"9GS Pϳ*?*~O?'iFʬ UV hijOŨJdTMK*2dK2LY#*}ԶɈ PdLEVV2@ʞj[J_ ̨%2`+LeExEubd%2afZe2`Ҷ&PBd3e 楰4~RWsb6U9Q ۽wmյq JjUN:K?¨[!*(Z(4ڨQAejyI~AgmiNwm@AgmiNw6E6, ۺNzҝv^ٻ yY!aeeYEFa`0 0 I$IR0)$* IRT$*bL#8 (1 B> : mf@I)7!9!TR P Ѡj8AF 4(4hdLPhFIT2h %5RHa4 J!MRzhW7׵̛̚~s?q6yU//_8.\qyF/ UWWן^zvkwJ +VFmx`0VnŠex£[ҍt!mT;N9Z'^<;6˺U+7n(d^vvpU\tr*&|LBU Tg>cûWN]-al{fkiO ˊKX<5EF>\r LJ)]Z+_i{6O==j/M,3kX-U}}>d~Y~Z}r|=c#d|ŕf8/ki%Y,hSϼֳqr| Se caYϟhdd3F[TO!jRo>Y|YC/'Z/YP?*U5SYt|0e|GڢuO<"zDz OMsץQV#Dl2sݴڌڥx_TzbU}oJ?1Ҕ~xut½R |}=ÅX!2W Tbee+HIekmY WJUbx<'Q}PYlZ/#\I$ڧ>U>|%>RTDPJIB(C((0 %5 2QTV*JXD0%Y!jCI, Z1 d V 1#,IjLPb1J$%Lƒ `+%IhS T*K)*e%L K(P`(?梈?QtU H*SBEVZR#T҅X2"-J YPh 2Dң*Z4jH4ЮV͵չ؆bb5WB*Hmstla"HEC Q)iE'RU+ `!q Q|Yaf*K2K޸5ƶ%(21'JT!q+Ң\bx."uuө]qNWW]:+wNnc8\:J1;FɳS[MAċ*VȟTv-j[3Ji9(8@!aU/qZ|C ;IH)  /|w( PQ@RPAD=vaAF 4R z*dzME=&I DJzdb=O@!Jo=-//WWusOyʷjwwZp:WkW{=z[VWj2QlBm'–IO\ $ȬtN&e+*#!Q(&XKjҲ5 jH1LjiNx64<%xȟJ홙h=AmR+byxcȵK˝5/'Tjh㇎lKihOMV^֣P^Ƥhȧڙ ̐'ŶHXPWDzdzc+ѕ a^<LX.V)1_]fYOW0ʼnU|EA%#ae>)`}Y_WeX/ "^/]ОTEz2Oʣq .t,TueYMkQb/P}XžͲJd/^p⤱0T0ΔQ=4&'dԁV@5YOfN% dʪDd !VRxOM,5e *UGJp8` b! \ie TR 0c188 p3p`p.fXΜ.8p8YG1,[,+-1 VBZ6mYDH:SQkI]_Jt T]'hHHNv)]gBǔY]gxK9CË)!Qxq~2<xqc.q\fgw!?~ztӧWWr%.Ͳ+c1hv:tx/S%8zz^XLYa#!dXL˜ k)Ծ%^*/R1 t <cr \ X$P퍇jCUR| |P> T>R9*""bEbDV(J@đb)2 VX0(TVi)h,eK(dReIX*Y*Ue(F(EbQFh U%ԪjU14BJ*Q))T1JQQTaJp#*%#KQ*F(h1eThEXET11@UU ,Qb ,J` `.QaGJֶ`Ye :@㭫l͖jlG:D'"$ʩ)M!IFSA%KAPX)dU_E ">C#VRň`WA0bڌ2a X2_kaɄV,#+ejE||@{ RR*Q<<( %*T:t*)Ph/J*ehIL1*VbXd?O>C!+CDEZ'ڵ SRU(TW)*F SDd0CfjK LL)a 1O/$e!`/LT< t/L48 l[6MmcallM9ȒAnsɳB[Ii;d(ssws^)_%.յy-E R(m哒O/_Y{2JU; lRWJ;XC8-\BқuȨ2D@mm Hي 2:X31P@)sɟJ()M(t{ h @ATgxƪ i(Ph@ Jd4 Iꔦ~j64Ԕ4oT0C>_ wu0s:4W*t'͞|޻v0:]@IVp[:۬;HE[%QVõkF[djM€OJڔQ)6U'ֶh=5JIV jWL@(UEXU,D!KM!kϾۛ[?9W`ʞȏuy Yy2iw:9HxϺ{$/KO_=~/~4}|z/Ncm׃C[6]WCe8cd#}qU}j}h+>,jZ)Ws%iOM 晗_ֆ]_+e|, d֕KjEIZ.Xn aeĝ*:/+D&D DIe^:փZ ]u۲^>^'zI5캕nU+tS88@y.]\qrx+5\u9rN`0`X00x    F&iypq3AˉV_3htXw@ϚYGJ]tGx'E]͉Yae^XՖY8:Q.%\SrOWnj,bpaqps[QYfS)F%gËrSzqO啞:yk53Suaѣe9ӈ(rS8>o^˹skj9m>~PPV)LJLTK SX`2iT+*4*YCR PQS!ZXT%YZ@iLBb+),EiR$ Z,ZR`%`%e2W? @TQZM5HLTMb%E+*$VDS$&BK*L"FL# +WK $j]%!N`;kmVjںխV1!MpTN*U$AЪbT*!-UT*A$aD}I#eIfIT[K,ٖYdYe*!Ie๬43PP S .&RQt:fbtt.WRFgGK0™Q_ 4JkU2Xd_7QruU,Ka0MI `XļG.q.]GFb'}i3ULdL &^l>sGnq.]JL B~ۜguysN*wڹwn;OK\c7szkրI!! zO4:-:3-2,.clUma}6٪614͖K&UUUUUUDUX *D UUUUUTeP@ J*D*ʠ =2d2Ͳ[61/DfcZu~w&H噖X_]U^\ܗu'rUZ"ViA<4-(#T$r.wr%Hs)_'dY",Y8U5iOC9n7w(sygsw7w, nvɳ7uܝrt?e5{R9)GሠD]n @c0 T _a)x TAQ@ɦx_%܄L1jѓHoT2bbzJy*I"2z`jh@IꔐQh& RTڍzzD4P@>Pqq{)^2ZY B*nq[jK{ xPaN7 Ђ!쮂 |z [hճ=]]ֺS]]nƌ1]c1c>:1c1mF4Wpҫ޷ַrMm͓jB؍F"("kUEDrn֢-lZ6M͹nm"e]Mڢ-6TDmlM4VɱZ[HhMڅ[ mlZŲ6Qk[[*i&ͨ6❕NUxEҕqtOm͢DZQQ"xݸGb:sI9-aV٫6hY,DyQQڤҕ> yC#3 -eEVSKa>$8;TC2]] ;EvTS2Pwu;B Y.N;^FZ Uw;iB"õ3 us[VrmEQبEcKi$ڴ13l3$Y3 6Fbjlb0KeY ղS2lbJHm(B36Mfڛ*f>e,9Yy6"G*׃dЅ/"Y1/~7 f0f&af+03eK4t7m҅#wG9F=8hbWS|;Kǃ3|ۺ/^ڟj&sꥌ ߒmI@ؐKjPئPچFԶ6&ԑD%l ,XUH{|jիWiG%$"U,Ũ!1 ҳ"nnSw.''}_^R SV2^!iO ߿Ͽfn[mݷmm}mmfomն}mmR"*I$Rs9ߜ[msI3*Fgᶈbf*a&T=&{kZֵkZƆm}F$ L]w7LLnfw7߸RfB۲[|0VF5ٲl j[TJXhYU=>޽gYUAL}&A B Aw=n{ @$%q D` D0=cƌn㱌ccȈv1]cup1DDD1"'z/Vum􈈈mF1cj{z 0'AcW.1Duc1]c7]v1cu1ncDv1""]c{{ohuc" Kmkc1뱌nc1뱌nc1뱌nc]v׌c"^]Hwd6 g%"AݐD=cj1cj^WHA؃ A}ن"E2Orw;U2g/jάiUngfffffffffffg+oR@PHU$K)C%Ħę!d!iAZhMJ  SU&ZC4d%5ReX,TO]xidž?H?QP~R!V 1Q1J&U e*L(Hʪ%(HEL)1 TIj*KHV%),(ªET0H UZH5@ LZ Q( "#^zߌvyκ @@D@AUUU^>b+XbjnoH=QI! mA"!c1B%6 H KھjM6ڑ|)[f(ae-nƶ3mgh11U;]v~4t AUUUUUWJ" ZB &A B AΗS4mToAoy?7kkEQQQ0qf+c[<0MAZAk MDq&AKIfs\qT3L&f]l*gYfbHAQy>~*ߵd@F71y<㱽=:<|xǏnQIIJ[kjŊ4V%eWϟ???;_w};B B A)U s~2 = T 0~!@P (%*M8` 8JFU)I4I5T'JSJx5*JRg;k1{1{⽞o;=q{UEݸ\Cdyo<ǕqccQeEL,\w1p3xc8cyp3xܺKO]0:(4& S3o1:7]]Uyj,V"[Q[V5EdMZ+h*(vNv[[s .좉)f;6gtwq;Ịs2I#4&bf1"Q6-cXl%5bѶ,V1[-E2ƨe/pѨTA aa4z58txjdtb8a 0f0fxp> !ʿF8`39 j>v.e*'瞞1-@ȭ3?1̜3c89%_ 1bxW6V4Ҙc<1_0hd/.|qχJr56 p!)G6٥~X/,ľi?bYjuviKYL,vlE+|8\Gǜ,~\̾PMF*+yx~hj31f`dT'V`JYaTEb6"5(1IɕdmT?ZVŭc08$ _ 0b" DDDD0D`0`1DDDE0`" D1DDDDDDDD>cȈcȈv1]c1c1v1c1cwc7]v1c1cc1cc DDD@cDD.1뱌nc @$ {1c1cj1cj1mR6jF6bf1c1cڌcڌcڍڻ@d "`a$@$ ujpWVS0k_v/جwKӡ꣪['bS3u̝Ld2'Đ\LۓC$2sU2yU+pL6dbI;4{4}Z{Ǎ;j:*V㿞}_YN==}WzL*zVTS{r3j효JEf|~`{,:izO|Et%F]X5@UUJ\wüDZ)x=g:Vte5gFY@c۹49ZϞmJڕ|)* "$@'qjCӺ*oummnU]ۗ4{[l&V0ct]H!I&_zᙌڭ4ӦpB9g ؕUURJp3316jl"3WF^ RI$UymjeJff2D$Hɂ900$$I$<{瀓Q2]l{UA*>m&jpY5+SR**qڪMJ5UUUp"˱jՄUENj{˪[-M@-->/j赚.Ov]t+栓PH@ $oy[{u<<fc^Xn7pma$UU5jUmki3ff3B(+$k$p{=-o G_ }t>UV k% %U?ڞU105OoUzTd%OH(ѐOTRf&mjT@IJC@몾ҖiH)_J!Py2XrR 8css7u[p0cF1ns,̫̫\̮g33<^,8x99xc9pu&Ufn33G9ڊl*vڛ#a-(wnMdҍfD;JlM)-mTXUGDij %&DIfim_8"cR=kY11RG0]kZYa8|5W֫w3k2y+=x?aecQ^Źo!.Ͷ2|~\12* bfVi6&bhmFeffRs21㔫1c0L&Ac&`T&bc" S1&eX3bXcRÝuONk֋xʫ ^TնgyX z[׬q\op^^tI,QϏbf&bǞ 0` 0Æ  ʩj.Խߙ<{a|x98 1xbÇb%`vYGTLvY`JGmhXYi0qxIfLJҫWM+ZR3؎q&1qe3DJ% NGWETJ‘T?H))a*`*00-J4 MTT0#1U&*ªªV  2ETEVM2@$ 0+ I_PV%,HX %SUH$!AJ&(h*i%RQԪ J_lcccfc 0#U.*UpU"*QdE aJb)Gd`լj%c+#!hc"0hXQ Us 5+1@a&T - 2*8L0TXL(pT%KUv[ YH(SvsDqhcVA`q*$ |mvֵڶs2@$m*zUbLͯx  (1P @(O8}2)@VL@@¨ڰTCꪸ} a@ j#c@4Lʨ OTMC#*$yS 4@I*FLLޯW\;΢(9unX u78npq{7WB`6@yp8y<79<1c1ss.1Q9s9ή\xc^[ʬmLEA+QV0cF1ZX֪5IFDV؍b5jCh56+_{ם^o-ڹ-Գm+e$fB-̳f͛323DKq+VQb^bڪ;T)U'6*Jlmj{"-b*$4mEhRYYHm4_Maf&3f͕K9G樹sS2MۓǜR3>wkdfph[l0Ά+C0q_Q챺 m`<|y~'ܟ|:v$fyU\͓?ʾ{vŎ1:wuWrW;'y5a]fm,4Oe;qE܋gfƤgm+[v#gL/'JS_U|[8maYNyq[mǮ%sͳ̣T4R~*xmsmhOkj#ĜDcOaQqJ,OiMԳͶ"~&h6UiZjkN2Ѭhvm?s#SXѧRSۇ-Z֓ZBkT%N S3433fEs3ff̳J ҮI ˌs9ffTᨬj̰W2,&Jr4)̓2aK1ma&&lؒNq9XRB3@ٺxLE<]U/ʩ3y./W2-i.vmc1YRǝf iveՌj&͒18UhY $zZX XaÌWIڭhSQ4&mHֻ]}xʹ~1 4-~gMmQTM\%~wk_=ʭݭe3lw8s_=4bu|yX_!e..~4Mh/Wڸ:#nͪר]j=߷<_+_5qWǽ⽗c;Ϋ'1\[Hf+tnrbKϧ<2Sbdڗ,/a/3QfK3ڄk(]vk6_,hjv9=mV+ԹUU*s ͣ2;ۗ&lqv9&+%X<^9K9yrh8\Mj*yΨi{쉫ժ)lDmrw;ӥ2BҰefS-h&di-FQJhY%iKA3 s[Vݵei7*YVI6jIԒT+YeĈɩ14N3jm+!,nj:sfLh^yyŹʙ\)_C>86w٢wTuwp\*GYKbbh8OK?*ۍiֵiwVT8qb~ɇ d[AuZeL1g>xk~"ĉm1aL4E}6Fu[[Jdj3M2IJRRZUkTɖdi-,lfCV$Y2̢$b;sf8$ zp%eW]u[yUr]Vc7u1c1cu1c1" `1 DD1b"" D.1DA D@cDD;D1뱌ncDDD1cDD1DKnc H H H1c1c11ڌc^ ^mFc1c1ccmF1mFm^nq @%꫸H#uApHU޽nq @%꫸H/k_ ֦ښdMcdI !iS;v9suuͷߧVmnf/<ڜhOlJ@$=n~-F(3hnk !n@@kcMYlss86C~4f<֙Z6 kCHM|wddڋcɓ3am{+~"'(YdB7 "=ߠ7uSmܽtE/qިmJ7VÃh[9˸]! V ̰ PN/UUYk ,e3w2s i@ NsFkEUUPUFQFAAA@&r$xI.vҢyY31-着L猍Tk.t%^ɵLd \ș+v5…5wNsZ8bFe|06!UG*GTGBJJUBHb*#S0ZDԤ$bbT`I*(R5RU -* @H1)J WU>?>W]l$ @ڪ^ W*Z$ ,Hʬ+JQ ZTXS**LDT$MHTT%,U$aBJD* *IlZ Z (ESdԤDYKj-VF 1u ̳մŨ/EJl $tB̶M0IҠ*ΠWVRFU)&e ʙR% ff*C2 UDը`YdlKbHW,̒' U/5͛L2 [4aXņ4M[YF2KfCjŨeC aIji56mT2Ic*xc 2EI` aCDMPeERRFf#EF2"3m)G*__ķwM67<<+?)ꏷ{Qo{xgx<ng3 HmUUZj~g;.[@$ zYKTMD"Jj%*dMeF 5~@QbQ@f hh[(i@65G@K`jڀ 9QGC{aFHBJѪh@[5|}L0{llƪhsSeSUw) J6-#|ӳwl3^v\u2_GYm'L|i'd/Vf}uː5ZֶVk\+3*J UJ92+Qݵ]ݲF;Ug58n:]Wbwn~f`]z=FѪ|ó2ڼéj>&}N+ ۷2O r|flVfGq..p2Қyeg3e)228||5ltƸ*JmѨ(їf}[ abs'7 NKwU,_av/{i{TvSd'mU&*ƙYkV%V`6bSZ@LhXlv+J͒L5YVʓ5m:1SG33*?5KL,S2NՕ0YֶF2jK#8:tYj0,i 6jUd'f4GW3iS:ΫH\љ )I3KXS2Sə8G 3V!a1QabY\ɁÒJ0 La`ȫ!4LdԦ?FlČJ 1 x5fԱ+ԵNm=by؝m.e /Sn~b|Ls"O-^}>u#kEm3Ås%WϹ_f1Q3!jhxpf"ƃd<|zv0fI2V(bcql1m0dKɴkECA5ir eD*iW_qSfW:k痍}%um 6bI\( 4̽a>˰7??GZ2h DBJUS%MJ*DS/GnK4kMNn\/nᷗG^Toe(\} \4^nd3Ajf ,ZFY6 nd9k}=kwb+F5ݵ}n%m3urrMs1G|-3'Y/2f>Rʘr 0Q¹k^s1+иnxjߎsLוC)szs0\.&ๆfg^c$V$) XJ#s7n>yY)uuӍh1a1ll7bC0%Tf{ 2Fws[V;(0y۸:gQUI$/A"LVZM]5۹WWQM)K:Ԓ5ۺh WVs6.{7 wPׯv;9W͒*!VxZ⪾Nym[d"7Օn[<ͶnHnΒdH2LA6yy1ݡWGo%YmI$Lٍ9[`ŹQԹu4AN 2UQ@I;òlws6rm5IJ i $I5vIR EX8[g]$KI$$I,dK $2I,d?8JB@$5u>}NKjjgvfwp5kf[t $ I  I u\%[y<pݨQ41f1VVZ2k!MVc1*aD+kiZjd2"eJTLkm[OWiT,kkڤ%8NU[K3KYuGM'̮2rꙠ惕KlGjYأ:LVȖb;JZiUq A' P鴫kaV0:N\1ˌel6,si-fSs6YNK20: nӣ:\gKӫfЙ1i-U6l%O:OX;Q#w@Ⱝ;shBf'zYjC-iW=9^M*[Q$IK0g1{FM'Ie#hL5JiWm(S4I+\t:wJ'S䝽.]Ur-Ze8˔)T SԢIJ?ɚmLαf0U+YGVD$d kʨ|IқF2NO-a|d^½瞠>4\+tZY^4V;U^窯AeNI_us3wqmˮ9M-6xF<.0QDc[||TɌ#0a|].< Vm63I9'!,|BȵYVNm[4_'£Ee;V۴ڒ(-ϼVGfҦ>&WĎ$[6 DUIЉ>U?`P( R)K*,` aF RUidT"L&4 hRM*b(QTIhDcَqm H}Z6P%Q!L"%Q2)`#(TYQ)Z*hj 9UU)Q-P4S BPj J&UZ@[66%L%&fdbY2 Um(f#a$"c$'R M-ihl6PR'*ȪڒMqQNJVk26STFCfՙJ5(D~~ JjeR $R)ҙC1m3+TfJĘS`i#-KY"ZĤ3@Vh[4VV3MYFJ!2uSZI/ʿ$~Pade e V I1cFd3R3(h)IڙK͊JC }Fj aF"lU3,X ʹɚQd klIE$+ e0bbdD؁L-6I"TKk橵v^wzGP*_oǗ<i+%[B!JP@̰?$ : HW!-_~wcَR @%! QISTE%JbL  (1P @(Qٕ46+[a*i*(| **FABZaT S2eJ15OԚJ05SҨ%d2 jJ)C@I$ꆆc{QǽkDPs]^pƔWZkʸ5+qj Wpo9s1u=wuc8y56y8y56pzs<9cu51sknQضCV"+QhF#[%daeY)TFQFhm11ձQ(بluSҝ3 K2wp];JU(6.MbVr{'p knZHZ-Эlʒ[BTMX+"m)6ȚֵS-%6ب66[!婘&ƚjj(l&fhl3K)6J6f3WTse3]Mds\ĩ{ĸ2&dN3FeMlhc%v Z56\Ҝj^I]"Ouf;?ɶҧim#{ƴ3Y+;fmm:+唴fcI^kj=6b|R[3W}cj9jolµj%{mmXd8UjW0cڟX}O5gpSAUVQkgc5 FxU=fYj<W-gl^vljqS>2 h7ۏ _O퉳QJaI&}a&a1OֻuOrAeS+fhd6Tjwғŋ1GɴV惓3DQl5Um2Wg mij}FZả6dэhJm%Qk>1])5˚ Kg陦c1v RH+5`~چ Ɨ&,Í. S2fC0O33ą x1U,GC#1 UxrHqYVdLb1R3 c %1bff]TfZ0+L߆ ueS2 Affj% VfRmL[VeYej[pn{|gYIAl/aOkhLƒ|u]{N;/zB#m1|k&8 cQevڪ읍[l\[ڴimί^lK6;ړ3XwJf9{IlڇyY{'n~uܪV,{808SJc2L*4ИSOV^ziZI׌~뾸.dt0ړm>>::3wc&ڭ#Y{;1\&v>}|tS<=qy˷ώURO1]Uz&[+nssiֵ,֏m=>ε'iC #Ke5P,b'Z2>`,af-cV[өMK^*7$ zWkmïk.Yt64SV4v*ei-$f*Nd=tS^ד.6Cpyׁfhzk0XJf31[4mj1rri*8 XAƪfɣRik+ERmA"KeU3hXEYM$/_^+Z2jE&1_/;l&m3m&FѳdѲHP(%Uڮ)ehgfhEJU֭i'4vrjTEUU9UUC%-/<=aPw?3$e!$RԴKZ?qF4٥HiDIkk)̖ZM+M+IJYIm%Ԟ6ۺ+%꫸H/~Ȉ"""""""0b" 1 DDDDDDD1"""" $ ^}1DA;1뱌ncDDDv1]c|$ @А$ _o" }1뱌c1c1c1c1c1c1c1c1nb"%7]v1$ _Kk\ KU1c1~.j6j1c1cj6o;k$ z^/U_X1flVlJؕ+bV1cQ|s/}F/{k[ow> }vs3G={|.~oiU_TmMgBjFY5ZEn皸nԢY H^#qu(𤪆=m>6bP7S 8ڧMN r=j Hk2$nI$qZHBi&p#t#&v ($4qCpB+0_ݫ: yo&bpՒeX "|Ay6GxO~[[}4!Obco4.^nrͧ4ݠg<PP[khiya[@(ۘ9[\svy5 pEZ$]DeRjh `C1q-eRYl@AAARJB$KaNfٶ.Cgm[dy rwꪂmXfzwkel`K!osuGJPR%i!Giw7w{٫(;dLRT vό_3=}ջU엯i(C}wXB(w)a(*I$BI$I$BI,sKko Hfμm66-9n4l$Nm9˓ D@2@ $$ {b0e;v5 a?ؔDAif bmlUle4,2M&Ulha"XT2fZEKZ6LaZ,Y/q6ԤlUm3m#.#0[8je8j$؍Ms5 2'.!ʰ&S]Sk LhFˎt8H(rU\RIl,88KZPAvFw7[e:;mN\#b֓]b:4jسY^0kk346K5Ng"ZjŽ^4{y̗C9ɼW%{-a9SeZtgTC{TlZVSL"qR`)1re9Shyjp詭DንWce8nJ<ZuֵfhJcgYKNf33:V$r,xYN^.<6;c^SMeqYb9sijƺlJZQV}׏Wg_.سgX™S>_RS EURy<ðkLv JOFFR5Y)93V6ٚ2U>S.(Zď.;6ȭhhTR}ШhzW*G"$H1%*aQK%H$aUV0P(j*5-MM iD%0X %d *Į뒺J$mff?PP/ RL$XQ& &UjVEI( -R utHK4)%A2TXKT_*)Oٲ[6*Le 1 a a5UHDjefRG*E\P$ tINAEQOLd2,!1XS%LL~TjIV̱e,ƥ0ʖ ,S"jTLʥU V"6f0XUSEY_Rg0O'?wsf TX3fQ]RTEJQe5i ^=GRF}9>}(h @P@7`JUbJ} :Km$hJ(]i 2 FE?H O%)5F@$IEH=M Ja4IJF4~?߲·cc\A]Ư7+uq9^㵄5+q a4SJ5pup9뻫$[s{]$ZuGTuE<}甁U*QJ66ƶɱMj"#2ڒS26&҄f Um@  l[#eս$ҖJSff>34Գfc13+sU ®˙U66*̿Ge.ZA;f*GghmCME sƐZP+2bK:VI@6VTTYkk}ko6_[T{+i+MS֌9l$2mKh4_>WI)/0;6a_4GIJϘ3%|0UO6:M̚VH>Ȏ>m+b}+.LRu~~~sjBf325~U_fisU}eCaZ#ԟmIj,:heӗalI5mҌCUfV/κb֯{om&f$Ѥ4lLh4[l ,lDL6U IKlaaYZh>%|50fe^|ƠH]dfY6fyl՚ELZfPf Zelel'cbWZnZ5U]Me R̘R(Zl2l0m3dR%fC'd;[ ka6j0#!8L0Ī1f1|KL&,2J3ALES!9<Ȏe%f5)T0KZ+ZZ xjeeA;~{<!oW^)W2x2w,м>% 0эe㕇׏ӅɓC1cfO2~LFvaCa',m5i)9,/=;of+Mͱj*ڥefY}R晭0 u4X}>xu휺u<֤smmq̮xtu˨nG[ǧ֫mn3 : =|FRTw:MfQe5j43QuUd{FfjܳBmRWmj"CXgf1h'(cm{(%P傜tBz멆UTjo|+"Ĭ ![4TmKhᆣXс5YL jHVڣ2hSjF:jH}z=` aa Ңک - F6.jlY ZaYW*flՍfFWT.w9Nsyp@'aEx"H\jsҸ<=籃*eV[m^eL9F΋ #!wi0ճ6ïvA $H\'Sq[rӋAUR{׊uzf̢a͹iDDhwn &pu@n,Yb)b)bx9".멛\Kw:ۮU]̵]_}cl6tprxѴk%y9Ü0oZ֬mm+oh$ $jmji$ԩ)(JR-DZ-IVM-X#YLfY*ZTⶵ_~kT#M,  5o``ccp1 DA0b"""""" 1 DDDDDDDDDDmF1m]$ ^1cjpcuȈcr"]cuc1c1cuc1c1cuc1c1cuc1c7]v1" DD.1DKnc H@L ]#&B8UUD@^k1cj1cj1bܗAݐ Hg%"@wyUr]VmF1cccm^|tn"%ےщPIWH/j~yr}o./_ff} UV휍p `|=v~U>!^N>_}gk+,hT32.u$[-}Siւ䏙&?x' J|h L}uU[P~~{o *.]2,$cdG nlc_UT/d;Rb-)0_׮}q=a‡ ` ʩ: +Yء̊* NW޻5piӾ(xz{d'R`[WXm{N{OCd gFlKe7nmǻf3vgHz3t铻{ ,M PPPPPP`PPPPPqGHX"Ő]ЃgI] 7c1PEfX J]&=\ٜC-* M HQEQ'Cd+5[8ipxt7D$exoBE0fݥpgw"JA??YYY]Y]vegk323232 @$md@rٞ;`@õk**`H$@%t)5Q $Qʭ*`2 1PE2)ɍFM4i4m,dRemmZfAZZRКZE.ZRTE#T.բlws;K"rUUڕ6I$2\*) kōF:ILb'q;twUuu%%%rYwl9j\kQ.mepdqa4SzZJ֒2jeޕښk 5^55e6oMe͑{]{z Qe:9WT,]^;C WvU=qػ=^L^5{ElU /Uy[Z kMԶb9H%3eIVUIcj捆Q&m6mV]sd8k^mdVFU‹Uٖ ]G(^Y.[ONvٖL^jW,uez/fӅyxM&a3Q׷$}o,,Z;\WMr}Pdr^>N|׌fٲc7 g_lf Z4SϹW3fO"Y,sp>Y\|yp'4v[,0QO>GV `H}`ap蓪m:V!ref`>}%sTl66aEUP>WH# AX%bJ U` dS !U%* &h$"XU0RJ )AbT %@# c ?UQ_%SJРʤhY !JHʔ""'(%!5BJdRS! Z *YHAJBxN)T)AH+̱Tf!P PJSY-jm +$+ҫE9]KaaM~$춉`ҒmC I9Pf Yfa S$_ d%RJRd$ʦRa"D#?)~B~PS(ҌS dL1L4֒PfIYCXTiejփM$YZ&X̆%JOƔŌ1"~~ OFfkm֢V4 Y66 ZY`U22MM3@~9.b栗CQ ,JT-$Ud0ABl%T|K0NbJI$%{5vvmpWʨ UkI' a?AK ߸%g%C:" ;Zο)]%wEɒ[kWګ6ֵ_4%STQF)U"4QJԪUQjQ2(+$k00a?o  fo}k8pVTׄHj~JOz=GhISQ&)DH A5)  )$C {q {x3y7qʸC\Y ׸665j*ab빍sws o9swwu]8:w1suw0g]zurQb&#mFV("Z[EII%=snvlGimۚ]ڐ2S13J̡Iٳ;Neۚ˲;RFhLfS0]mQ6-bl&j ch,kbQF j1j9FS 8e( 9ѨåT#(a+0у4tdÇiU\5IgfkUtis,1Wq8%96٥~X/,[2Ullg,0dYe\|q>~3g3>PMF*+yx~eE.յZ5++m Z'%W-,KK,YTEb+b4ETb$dʳJHjU_jc0꫸H/ 1"""""0`D0`D"""0`0`A"|11c1c1cc1c;1nc1c117q1DA;.1DKnc1c1c66h};8W=w3pj6;{;nڍьc1c111Q{@$ @d uZ0Iڵq&IK)D@U] &M{nW嗿yz~69{[ mu|L2w*2'5Đ\wk.D߳nCl̳jkm$4RIVҎd. Twʕ+lqyoVTSCu_sj효JEf|`e6O𤨭~;O{A:໾{'bQ %fMe ,QK/ ]F d1f!ϠRmmb["DλBjC:Umm7bWva mu`c'y:]@H|{=$<7*+C0GȪs$32.r2K!:sQooxa'4Ҫ kRn[h@<JٙnTVUtY o8``NUUUh kI%}h%WnIz0DfN.$E)wﯯ3yOmkmmҺaUuC[mmJ=j U`oͳhjiXNߕYOoOv]t+栓X$ 5&U< kK-Ww]HJZ-hXefSaɚ XeSi)lZS4Il)9qBc)a9)qUVh(afSK8Zj9fS19q,9nݯ0]rS dc9>cTA咥l)4`TFwE]*]DKʈ$zURRIBP!j hF0JEYEdFj&hEZV֤ /iih RJKHx 2 %VEZ-D (T0)FBrr+HU,*1R)" -RQJIT'[0$BK!&̖f` XŖXŖXŖXT FYYdd'Jdb1b2O*Ğ<9#W*-"*y!yQZ P*eX±04 Pȗ$O*Xjb1bF,X(YQEX#Pa*I?#&VXcXb%T?FYUbb)Lj R00S!&e$UK*ʲ1&C A B榭)m40IС(?vC{oGoWU/ AuSAtIr)R$ ڨD}>c&lIU[ڵdMe~@QbQjU@:Oc1Qa||R:FP]T2iJdJy*J@IT4hRUM )$Oiks778x툥R W*S` WWV;9 )BVh4(V9s79uo96c1s*33*3732173ܳ32S32S34]8y֢E٤طrIؕTYJֈQ7qWvjF h` 66 mVlCciT[Tbʹ +6kRDDE͚͙͘xcOcR=kY11RG0]kZYa8|5W֫sIG{;^<<}O330f9s GGsC仗K6 b>E2/M,ʂ#4#dfb,9Ṯ~8*XŌ321PfF1Xɘ11ȱfIV0ff%25FhXԾ]v.8ⓚ0+fTWOepm`/92Н ~ߎ;Ŋ9WUv$\||? ',1^\ Xa8\sfxc%Ub *~ڿ-mf&=u/w|O>qf3:fKYV><<1xs%q<yԧLh+UV 9|=rxq)90T剦H̫+BN|,cETDZ\07dmLi4Ly1XU)EG$\L1U&tٙ)ʗ8Ň8\<c3g`<9$xa!RHmYSݷ.\bĹa/~8+qWyb^ɰ6LeժuuuI<[E` E%$X؋*iMLc2ifIiRl?5kZVV!H?DDDDDb"  DDb""  1b"""""_c1bu7\0b" ; ;cu1c1c&1ccccu7\1b"%7\v1]cuȈcu7]v1АL%Uc1c1ccmF1o0;{zj61c1c66j1cj6j  H)`XkSdKVD뮀 kf̠P$ uU$ @ߏ9`UlvUԵn;gRĝ>OxC1`#ld F @WR]Jr׾[oRsu)ysfۻqdV^sywzlm ]5#JRk7 Fi%SR'-s{';jQijR!UudU\Ieջ[I1!ąݎ@I^?QK5T4UpUT ʢUUUU\U]UBQUBw<*4-_}w`Ʋ;セw-|B>ϸxk$L$MA I$5 펒ƪsRxIīZ"0b+MZZjLDi+J!Mds3b.1+EҚf2rueWHX VeaNM:q\bJ呕'EIpRIыO8r9b}\킶l= !:g'p;caڬ)J@JJ/I8SX$ @U_[[V1AY&SYAc_`{~>_T`.t=UV@@diuwW; P(@ z @QOJzjOSjTA4oR5OQ$JHRmѠԕQMh4I$UC >sy\B΋nFnFnFe'zӻCEocMokٔ%S)JRL 6vц9tam]a/woOw98{7s7999l`e=S Z&YX|1Y^&CPXeaQy2jUyjFd)j2+^1ʇ4hz'!CԎ:'#â~2D&CJjV5dVX1W3&ʗfqԫVWyY 6NCs_w2Jq<'pF!#~ܮ`e* >Ti,ʗ{T}Ϣd.1T)x:CIpг;\T28aOd? ˔BGyQp0YU&I<ՠ9(ap:eO~'/Q5ʌ#GV?#S$1aqx1aU da6V3380ccffU11?Nf,c F3 LUaf3$̫F`3̪ 8ΨLU:{$MQTuɕxÇeFk&ڝI=ew]m"{,ۺmG0DfT9RE.#Uvo=Q"OT|t;Czʇ9 4)j c.ƪŃRCS&V5LMJ[fnxM VJ\\e`Qp—+S`p YՏFLJ N-:gux[Sb&%5#iM~HeMQu(qz4hҮ5$ep0 urjSQΥ+>r]Qq._C1_:d15Mxd|s+55'ˎY,?̙^ 6T5Gʗ^&ȯ.21N1UCWQ$q]Qu9ʜYT1=FZA<4Ş>0soj~kWKThEa:'rS 98ĵ-VJlllmZxL%[HL& I [fm%48D@'JudJY琼!aZETYͬRcal]J C1Y3ʪ%VbȘ 5[ڱ\UԆ Qv#66! iMc͙a5da0jLBʭCqN1CƜTɆLX.3p.q>qc8 9 2Rqc ħ͘7m8>R kk&D7]"dI}J++++,Qj1cmhea3hTC6;tlh-ik+ 44(M_tH!o"" 1 A#=c1cuc1c1cuc1c7\1b"""""""""""""""""""""""""""""""""""""""v6Z뱌c1c1c1c1c1c1nc1c1c1c1뱌c1c1c1c1c1c1c1c1c1c1c1nc1c1c1c1뱌c1c1c1c$H$kKfʾmg[Ȼj[̇-urW?vg}ׯuql[|oAOӎyI1$x|I/؍{9}ws}ߛ{lzlm[ M,mU!㻻S垺*c=uoK,X""5b:4:[:zmkI(,F9MT0{Wywo1rŋ=tDUŌcWVbbŋ,^DDDk>o{ e[-xxz~i;zm%΃:H$oҽ[I6!5[5d,bK\̗3Ş9<ʢI%€]_sϐ7CIҭ1+s0 S30*۸H$q$?MvPu˶WlsrfaZjO%DڥT/AR֨ҋ5F6j5FB5bX#QJ["k-бM -12aL46UK,2Rb̙QffV]bF2c3!Ӫ74IʢQ)12)eQʹвFGy``ǻ!.48 JfMIe :[&mH &XW1I->R}HA_Hi6m6m6m6mcv8ݶ9.%eM&A,ZD6 #>3*I<>|? ğ3d,ħR//?P?FJ0R&(! 1*0F)4JLP,P,#ҍ(SALRKЭ XTHR P-+B DZ(`/22mI,i)JZh[iUWRgo[Gb*^0 ŠAb$bbU0E( J9UR%IM %4Eb K+$("RT%T#PE|,LDa" TG=DJO*8TAP %Jʔ %YdTVSeQ~- X5FYi#*bY#" 2CH%HUH0bBJN0J%(KJY  1VC%%c XUe akcȖ1*W 0aT L1aa*p #GV&f1a_BQ"?xg0p0ppxg0p0 0 =Æ 8`=Æ 8`?=_&ed31;wN<~p#{׀[mnW44444/I$Im]PT*6;\g .o׀hhhhh^I$ܮhhhheBP+s[mrݶkܮhhhhhhhhhhh^I$I$I/[l2S T¦2wBPTmtwK9,¡PGs3I%%KT3kiiS66ͭjڣ68i3jڌᦨͪ3kj36ͭjڣ68i3jڌᦨͪ3kj36ͭjڣ68i3jڌᦦmLdjfͭA'I;<6mm2B%KT*R\ FmQ6QTffffFpQTfk-FmQTg FmQS6fFpQTfFmmFmQ[Q͛Ta.U$* KT[I-ͩ[LfIӧI$d^d^$OϝNK"YI$;'*p ʠtYʠtYmmmm Pm_%waܹ˹"%INF%,U*$#ٳe몯IefK,hJRB H H H H0H H & OdYI$` H H H H L A LYP R;W}: MDO@zi A*#M2ɈOޕR)F?Tѧi'@&T )% RO(w~owzn>_;0[g[r0zKnX7r`8=8['ۻ ܘ8o6N mz00e Iں0&ۻjں0&ۻj}ƹ<>s>W|yl`z ll`7ƍm ]湱<>4knhg5͌]yl`zۚ60scnxmULةԶlj[-KeTQb(ՠ",EQ-bP@E5EX "Pc 00l`#lXQmEhllllڢQѪ- 1 8ݶ۶4Nl8:0N7ګZ(J0#XKZs6mdaF0kF0mhj͖e*ƢX¶f00¶6ͰJLhc"U# B0"ڿ;umMEdqU4ˆ BҲ%!ZaVVi4b˖W^e.- JGCUbbb1UuZ@XA@9exe4 􎣰 ҜG¹$vvx\_oB Jʭ&,IFZ1|5CʵZ Tq|Z(i4RNӈ224)q.#q\GN%Q/!P0IzWkjQ'*+qyt1hS§Q& _Uzlm_m h5,I_0V)R 8d ㌬2qV2UOr \8UXd.QXeLQaOqj#ŇUTA,8pյmOpUcyd5[CnnYMW7CUd6%UUjmm=9 .4{'UX9'IFO-+<gSSW42C9RLīCƕqV'ŋ*UrAҘDdS#+#ʙ^Pe:N#=*,z80vIQ,N6ԫnTllUy0L& !0LIa-m{[-mJ9D1+ibF)֥]Z5lbfkMvѰmMBrK*j%ŐcCc@ңcb۫ZʔVIMm&6R5VڋhDɄa0MmBa0j*rXcuXiLG.Z 5u.=xjW+,8*Z 5u.=xjI#mUdJAi[wwmcf P8[/]YȒ&$L#-&IѣF 41bŋJYIdjZM&/=YZiZĭ>^V ʦjֻVկ##F"""""" DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDn1c1c1c1c1c7]v1c1c1c1cu1c0c1cu1c1c1c1cuc1c1c1c1]c1c1c1c7]v1c1c1c1cu1c1c1c1cuc1c1c1c1]c1c1c1c7}o[gjz"ꯝc:nc;[|,kuowD]Y|vmoW[-qLEx<Ӵy瓻x_ J?"#J"aPJd$ĘVVVJh4HibYLTQHXTjACDd" `Tl5U⵭6SB 4͛3B ,lP$ Mm L[@ė%Oן3kg>_JW*0T02U D’R*G" ʂ5eJTU5UPdT*ȥ?IJH2+vU t0VSł4~jhƔ4# DV$e ʌXT()PFeF, Jʲ2ŋ"e# Ua2#%*ňĘ"HpjLXV K"+U_ gy]Ɗpd {J W`! +yg?N}ɞyg?ϵ3kg>ϵ3{=L6='}ɜ_}ϓ=ͯuI>ϵ3[l~ߓ9&{^{͞~g>sskoy|~L|m{6zOs}>L^S=ͯuIkg>sskoy|"x߸^yǍ^UuWUuWUuWUuWUuWUuWU>ʪo]U]ULjcSL^x_b{Û|Y^=/zzbo䨛Ǭy ޼oz R(B)E!F "@#4 44̤(-Ie)2le&Rm̤MٔIP[2)6 fRe&AlL(-L2J!ReerVvE ljljljllVlRجإser1@1LSYYJbb͕feڇ.YvYvYvYrbb͕  6l P1@ S P1@ RՓ.ږژ)_mݷoۻw[F1EUn2B&Lcoy>XWv=wp;a73w;湱<>hѱ4Whѱϫyl`zscnx|ѭcW|\۞{l2cehٕƥTZł(ŬX "TZł(-bP@E5EX "T`ڈ01aaōm60j 660Uk66666jm #E4,e7S T{< T{ջk^m[lMS`PP教+45InFUVc -a֌a[JEc j,ha000¶a6͖ٲ٭͵zF*a6F53fmTExXFT<WQj+jИLTIԲEN MC]^Rʓ>/ |RqxLLIG,jիP@r/ \L4%k?WNjc Zi$)ŒXY'/˖F,_\1.G,1\XqpFYbʿ..XFU%1b0娌Z> ˄rSœ*xjT^N@KmOUzԫ[mnnY dm!7,V/*AaCmOr('z*up XS,%'e P5KP S-P020$-SC%yF+o& g&y390Ua0%i':BuֲUX>.Ěqt.z,/ qz,e8dYu 5 =R\&ʩNENHybZ1<.& Y$]d1u¸'zR/ z &PNST9z'Z_(F) ҧ -*s]65[y1o,XbŞ"#^c?[oŋ|tͺIk^׻~,},cſ ,X1cɌcżbŋ,Xbŋ=DDIߍ7[bŋ,Xv{{A$LwL$61ۦF:moNpyk,1LO}IOkF{VղP ?h%Z#Q"0RL40ҰҰT̢eT_Z(T̩:qWLUf44RJJq%B4Ks\N]ab0RtS1(*SG" :*jzh2EL6=?~&s}|l{m>ϱg3|ϱg7}3csco{oI}=w֗ȯK}}i|S=͏q'}ߓ9>L6=3{zl{m?sO^lK/ݶݶ[k۶۶۰޶mvme2zv2=^=^zz}mzmmm׀ mymmm|<qzXPFoUTh @?U$@4@h 56HHi aLC& 6hɂdF ɀ 0Uz @ h)@4@?T2zQ4M1M@@jyN&f$M4[ *6\[u֫;׉;q:nH ^^ 0#b,XL\쫻\xKX"im!,͇Y\cc`3mMfHMfDڶ ەTilf b7Jܩ6 77*[T܋bڦ nn"&i'*]І1"cUq1҉8٘+Q(ڦ2jX:ʸ`b8b˦Lba63H͛ 8c"0Ҝa:̝ua:1c`a Ydʙf*Y R6u Jͫ2[Ce3*6',-VմFnjOQ&X*W5xHuh**j2ҁFx1x 1`2xh3d1 ac0V1&00¦1*bbŅ10Sm1aͫ5ff# 1^R!xJ].yMm mFFFҔU-./012g$"d!B&7R^_ `!a"b#cʕ,ZBFJLe@B%e&f̚1;Û>eWыMHݨ[l[mflڑYV!B!AE"DPPTD "ala1'1BALl儲)ZdʵZ Ȋ= J|ju*:9 *ghfϚJҳ0 @J$JLM:iyg{<<g<}m%@P)^Nbk%$Y EaO&"6SJ#Jj(.*)ԥ(O'66.R)Ԫ tPQ Ρ9JO&RWP]mlV!5xTTJ%jȥ.E)XXZ))& 4&FF 1(Ҕ`) P0)bx=#\BIRe((X" a ,QT;)r i(I uQuUԪJ9I)]h"(r:(uҊR]mso.zS}MM{;wn۷nݎ;3}PxBH rDf)žl'QBA#ԡ;&IFb`Y;EL6Q)J(R)BUP?y:ny8s3-`")*酺kX $EQEQEw\.]]8|q8n8/Y̳,ˇYeD=oyn.u6]qqxîYhy$=3AAtt 5UUUUU8Eo2|0 0,7ifgr*Fo+8mOVzv6]гѴnHQEQDwwwwwwwwwwwvaaqj#+-( EP `P#4 |;q?/ x[;:ǎcNynsO0y|Yפ<OCż懖;y;ܻv(1 HD*S$A0RI1ZUralYox8訄B{$I$I$I5UUUUUUUUXǏ9I$JRI%)$IJI$$RI)I$JRI%)$INL2dJbI%1 $ILBI$!$SI)I$$JbI%1 $ILE{/{I{J?$ I%gHX`ֵ?TĒH8$A$ $pI$I$I IH8$A$ $pI$I$I =88ۖmmۖmmۖmmۖmmۖmmۖmmۖmmۗUUUUUUUUI$I$I$M-+3333333330(+$k5]= {O sx v4oTM4&@L UC#&&14 1FdhiiRR& 2h=OSlUUI*hf-PB jMbhD;;sAqحlD*;,ض6&6QEUx<L=_!\89CͶlٴB`O$D-( ^O0 N(!R+J,RĆ$0*L`L!>#JA+ X R` aT0 DIQN{CrIaJJӿwok D^^SO;:/Ҏ|JR)J^d^O?俩$~w@TEeT#XN/=z|33=ޛm;:;{ x'Gqt;" regexps "\\bx\\b" -;-;-;- -;0-1;-;0-1 "^(?:\\bx\\b)$" -;-;-;- -;-;-;- "^(?:\\bx\\b)" -;-;-;- -;0-1;-;0-1 "(?:\\bx\\b)$" -;-;-;- -;-;-;- strings "" "" 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 "" "" 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 "" "8" 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 strings "abc" regexps "a.*?c|a.*?b" 0-3;0-3;0-3;0-3 binaryregexp-0.2.0/testdata/repetition.dat000066400000000000000000000151601347202265500207060ustar00rootroot00000000000000NOTE implicit vs. explicit repetitions : 2009-02-02 # Glenn Fowler # 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 binaryregexp-0.2.0/testdata/testregex.c000066400000000000000000001465351347202265500202230ustar00rootroot00000000000000#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 * 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 #else #include #endif #include #include #include #include #include #include #include #ifdef __STDC__ #include #include #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 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("\n"); H("\n"); H("\n"); H("testregex man document\n"); H("\n"); H("\n"); H("
\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 .\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  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("
\n"); H("\n"); H("\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; }