pax_global_header00006660000000000000000000000064143372365210014520gustar00rootroot0000000000000052 comment=6b5c0a4cb7fddca7a0857c0643e3f2a62527934b golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/000077500000000000000000000000001433723652100215545ustar00rootroot00000000000000golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/.gitignore000066400000000000000000000004151433723652100235440ustar00rootroot00000000000000# Binaries for programs and plugins *.exe *.exe~ *.dll *.so *.dylib # Test binary, built with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out # Dependency directories (remove the comment below to include it) # vendor/ golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/LICENSE000066400000000000000000000027071433723652100225670ustar00rootroot00000000000000Copyright (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. golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/README.md000066400000000000000000000010641433723652100230340ustar00rootroot00000000000000# Grafana Go regexp package This repo is a fork of the upstream Go `regexp` package, with some code optimisations to make it run faster. All the optimisations have been submitted upstream, but not yet merged. All semantics are the same, and the optimised code passes all tests from upstream. The `main` branch is non-optimised: switch over to [`speedup`](https://github.com/grafana/regexp/tree/speedup) branch for the improved code. ## Benchmarks: ![image](https://user-images.githubusercontent.com/8125524/152182951-856549ed-6044-4285-b799-69b31f598e32.png) golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/all_test.go000066400000000000000000000620431433723652100237170ustar00rootroot00000000000000// 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 import ( "reflect" "regexp/syntax" "strings" "testing" "unicode/utf8" ) 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 { 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\u65e5x"}, {"[^\u65e5]", "x", "abc\u65e5def", "xxx\u65e5xxx"}, // 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}, {`a\x{fffd}b`, ``, `a`, false}, {`\x{fffd}b`, ``, ``, false}, {"\ufffd", ``, ``, 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" + 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 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 != tc.literal { t.Errorf("LiteralPrefix(`%s`) = `%s`; want `%s`", tc.pattern, str, tc.literal) } } } type subexpIndex struct { name string index int } type subexpCase struct { input string num int names []string indices []subexpIndex } var emptySubexpIndices = []subexpIndex{{"", -1}, {"missing", -1}} var subexpCases = []subexpCase{ {``, 0, nil, emptySubexpIndices}, {`.*`, 0, nil, emptySubexpIndices}, {`abba`, 0, nil, emptySubexpIndices}, {`ab(b)a`, 1, []string{"", ""}, emptySubexpIndices}, {`ab(.*)a`, 1, []string{"", ""}, emptySubexpIndices}, {`(.*)ab(.*)a`, 2, []string{"", "", ""}, emptySubexpIndices}, {`(.*)(ab)(.*)a`, 3, []string{"", "", "", ""}, emptySubexpIndices}, {`(.*)((a)b)(.*)a`, 4, []string{"", "", "", "", ""}, emptySubexpIndices}, {`(.*)(\(ab)(.*)a`, 3, []string{"", "", "", ""}, emptySubexpIndices}, {`(.*)(\(a\)b)(.*)a`, 3, []string{"", "", "", ""}, emptySubexpIndices}, {`(?P.*)(?P(a)b)(?P.*)a`, 4, []string{"", "foo", "bar", "", "foo"}, []subexpIndex{{"", -1}, {"missing", -1}, {"foo", 1}, {"bar", 2}}}, } 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]) } } } for _, subexp := range c.indices { index := re.SubexpIndex(subexp.name) if index != subexp.index { t.Errorf("%q: SubexpIndex(%q) = %d, want %d", c.input, subexp.name, index, subexp.index) } } } } 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}, {`日`, 3}, } 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) } } } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/backtrack.go000066400000000000000000000214471433723652100240400ustar00rootroot00000000000000// 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 regexp import ( "regexp/syntax" "sync" ) // 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 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 } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/example_test.go000066400000000000000000000253061433723652100246030ustar00rootroot00000000000000// 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 regexp_test import ( "fmt" "regexp" "strings" ) func Example() { // Compile the expression once, usually at init time. // Use raw strings to avoid having to quote the backslashes. var validID = regexp.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 := regexp.Match(`foo.*`, []byte(`seafood`)) fmt.Println(matched, err) matched, err = regexp.Match(`bar.*`, []byte(`seafood`)) fmt.Println(matched, err) matched, err = regexp.Match(`a(b`, []byte(`seafood`)) fmt.Println(matched, err) // Output: // true // false // false error parsing regexp: missing closing ): `a(b` } func ExampleMatchString() { matched, err := regexp.MatchString(`foo.*`, "seafood") fmt.Println(matched, err) matched, err = regexp.MatchString(`bar.*`, "seafood") fmt.Println(matched, err) matched, err = regexp.MatchString(`a(b`, "seafood") fmt.Println(matched, err) // Output: // true // false // false error parsing regexp: missing closing ): `a(b` } func ExampleQuoteMeta() { fmt.Println(regexp.QuoteMeta(`Escaping symbols like: .+*?()|[]{}^$`)) // Output: // Escaping symbols like: \.\+\*\?\(\)\|\[\]\{\}\^\$ } func ExampleRegexp_Find() { re := regexp.MustCompile(`foo.?`) fmt.Printf("%q\n", re.Find([]byte(`seafood fool`))) // Output: // "food" } func ExampleRegexp_FindAll() { re := regexp.MustCompile(`foo.?`) fmt.Printf("%q\n", re.FindAll([]byte(`seafood fool`), -1)) // Output: // ["food" "fool"] } func ExampleRegexp_FindAllSubmatch() { re := regexp.MustCompile(`foo(.?)`) fmt.Printf("%q\n", re.FindAllSubmatch([]byte(`seafood fool`), -1)) // Output: // [["food" "d"] ["fool" "l"]] } func ExampleRegexp_FindSubmatch() { re := regexp.MustCompile(`foo(.?)`) fmt.Printf("%q\n", re.FindSubmatch([]byte(`seafood fool`))) // Output: // ["food" "d"] } func ExampleRegexp_Match() { re := regexp.MustCompile(`foo.?`) fmt.Println(re.Match([]byte(`seafood fool`))) fmt.Println(re.Match([]byte(`something else`))) // Output: // true // false } func ExampleRegexp_FindString() { re := regexp.MustCompile(`foo.?`) fmt.Printf("%q\n", re.FindString("seafood fool")) fmt.Printf("%q\n", re.FindString("meat")) // Output: // "food" // "" } func ExampleRegexp_FindStringIndex() { re := regexp.MustCompile(`ab?`) fmt.Println(re.FindStringIndex("tablett")) fmt.Println(re.FindStringIndex("foo") == nil) // Output: // [1 3] // true } func ExampleRegexp_FindStringSubmatch() { re := regexp.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 := regexp.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 := regexp.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 := regexp.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_FindSubmatchIndex() { re := regexp.MustCompile(`a(x*)b`) // Indices: // 01234567 012345678 // -ab-axb- -axxb-ab- fmt.Println(re.FindSubmatchIndex([]byte("-ab-"))) fmt.Println(re.FindSubmatchIndex([]byte("-axxb-"))) fmt.Println(re.FindSubmatchIndex([]byte("-ab-axb-"))) fmt.Println(re.FindSubmatchIndex([]byte("-axxb-ab-"))) fmt.Println(re.FindSubmatchIndex([]byte("-foo-"))) // Output: // [1 3 2 2] // [1 5 2 4] // [1 3 2 2] // [1 5 2 4] // [] } func ExampleRegexp_Longest() { re := regexp.MustCompile(`a(|b)`) fmt.Println(re.FindString("ab")) re.Longest() fmt.Println(re.FindString("ab")) // Output: // a // ab } func ExampleRegexp_MatchString() { re := regexp.MustCompile(`(gopher){2}`) fmt.Println(re.MatchString("gopher")) fmt.Println(re.MatchString("gophergopher")) fmt.Println(re.MatchString("gophergophergopher")) // Output: // false // true // true } func ExampleRegexp_NumSubexp() { re0 := regexp.MustCompile(`a.`) fmt.Printf("%d\n", re0.NumSubexp()) re := regexp.MustCompile(`(.*)((a)b)(.*)a`) fmt.Println(re.NumSubexp()) // Output: // 0 // 4 } func ExampleRegexp_ReplaceAll() { re := regexp.MustCompile(`a(x*)b`) fmt.Printf("%s\n", re.ReplaceAll([]byte("-ab-axxb-"), []byte("T"))) fmt.Printf("%s\n", re.ReplaceAll([]byte("-ab-axxb-"), []byte("$1"))) fmt.Printf("%s\n", re.ReplaceAll([]byte("-ab-axxb-"), []byte("$1W"))) fmt.Printf("%s\n", re.ReplaceAll([]byte("-ab-axxb-"), []byte("${1}W"))) // Output: // -T-T- // --xx- // --- // -W-xxW- } func ExampleRegexp_ReplaceAllLiteralString() { re := regexp.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 := regexp.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 := regexp.MustCompile(`[^aeiou]`) fmt.Println(re.ReplaceAllStringFunc("seafood fool", strings.ToUpper)) // Output: // SeaFooD FooL } func ExampleRegexp_SubexpNames() { re := regexp.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_SubexpIndex() { re := regexp.MustCompile(`(?P[a-zA-Z]+) (?P[a-zA-Z]+)`) fmt.Println(re.MatchString("Alan Turing")) matches := re.FindStringSubmatch("Alan Turing") lastIndex := re.SubexpIndex("last") fmt.Printf("last => %d\n", lastIndex) fmt.Println(matches[lastIndex]) // Output: // true // last => 2 // Turing } func ExampleRegexp_Split() { a := regexp.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 := regexp.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 := regexp.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 := regexp.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 := regexp.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 := regexp.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 } func ExampleRegexp_FindAllIndex() { content := []byte("London") re := regexp.MustCompile(`o.`) fmt.Println(re.FindAllIndex(content, 1)) fmt.Println(re.FindAllIndex(content, -1)) // Output: // [[1 3]] // [[1 3] [4 6]] } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/exec.go000066400000000000000000000304311433723652100230300ustar00rootroot00000000000000// 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 regexp import ( "io" "regexp/syntax" "sync" ) // 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.RuneReader) 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.RuneReader, 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 != m.re.prefixRune && 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.RuneReader, 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.RuneReader, 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.RuneReader, 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 golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/exec2_test.go000066400000000000000000000007741433723652100241600ustar00rootroot00000000000000// 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. //go:build !race package regexp 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") } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/exec_test.go000066400000000000000000000514771433723652100241040ustar00rootroot00000000000000// 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 regexp import ( "bufio" "compress/bzip2" "fmt" "io" "os" "path/filepath" "regexp/syntax" "strconv" "strings" "testing" "unicode/utf8" ) // 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) { 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 { loStr, hiStr, _ := strings.Cut(pair, "-") lo, err1 := strconv.Atoi(loStr) hi, err2 := strconv.Atoi(hiStr) 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 ':': var ok bool if _, flag, ok = strings.Cut(flag[1:], ":"); !ok { t.Logf("skip: %s", line) continue Reading } 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 := strings.HasSuffix(builder(), "-race") for _, data := range benchData { r := MustCompile(data.re) for _, size := range benchSizes { if (isRaceBuilder || testing.Short()) && 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 := strings.HasSuffix(builder(), "-race") 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 || testing.Short()) && 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!") } } }) } } func builder() string { return os.Getenv("GO_BUILDER_NAME") } 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") } } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/find_test.go000066400000000000000000000404371433723652100240720ustar00rootroot00000000000000// 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 regexp 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{ {``, ``, 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)}, {`[日本語]+`, "日本語日本語", build(1, 0, 18)}, {`日本語+`, "日本語", build(1, 0, 9)}, {`日本語+`, "日本語語語語", build(1, 0, 18)}, {`()`, "", build(1, 0, 0, 0, 0)}, {`(a)`, "a", build(1, 0, 1, 0, 1)}, {`(.)(.)`, "日a", build(1, 0, 4, 0, 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)}, {`(|a)*`, "aa", build(3, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2)}, // 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)}, {"\ufffd", "\xff", build(1, 0, 1)}, {"\ufffd", "hello\xffworld", build(1, 5, 6)}, {`.*`, "hello\xffworld", build(1, 0, 11)}, {`\x{fffd}`, "\xc2\x00", build(1, 0, 1)}, {"[\ufffd]", "\xff", build(1, 0, 1)}, {`[\x{fffd}]`, "\xc2\x00", 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) } } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/go.mod000066400000000000000000000000521433723652100226570ustar00rootroot00000000000000module github.com/grafana/regexp go 1.17 golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/onepass.go000066400000000000000000000340361433723652100235610ustar00rootroot00000000000000// 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 regexp import ( "regexp/syntax" "sort" "strings" "unicode" "unicode/utf8" ) // "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 strings.Builder for iop(i) == syntax.InstRune && len(i.Rune) == 1 && syntax.Flags(i.Arg)&syntax.FoldCase == 0 && i.Rune[0] != utf8.RuneError { buf.WriteRune(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 } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/onepass_test.go000066400000000000000000000111431433723652100246120ustar00rootroot00000000000000// 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 regexp import ( "reflect" "regexp/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,})*?)$`, false}, {`^(?:(?: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) } } } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/regexp.go000066400000000000000000001133201433723652100233750ustar00rootroot00000000000000// 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. // Following utf8.DecodeRune, each byte of an invalid UTF-8 sequence // is treated as if it encoded utf8.RuneError (U+FFFD). // // 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 is // 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+2] 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 RuneReader: // // 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 RuneReader may read arbitrarily far into the input // before returning. // // (There are a few other methods that do not match this pattern.) package regexp import ( "bytes" "io" "regexp/syntax" "strconv" "strings" "sync" "unicode" "unicode/utf8" ) // 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 prefixRune rune // first rune in prefix 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) regexp.prefixRune, _ = utf8.DecodeRuneInString(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: l := 0 for _, r := range re.Rune { if r == utf8.RuneError { l++ } else { l += utf8.RuneLen(r) } } return l 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 } // SubexpIndex returns the index of the first subexpression with the given name, // or -1 if there is no subexpression with that name. // // Note that multiple subexpressions can be written using the same name, as in // (?Pa+)(?Pb+), which declares two subexpressions named "bob". // In this case, SubexpIndex returns the index of the leftmost such subexpression // in the regular expression. func (re *Regexp) SubexpIndex(name string) int { if name != "" { for i, s := range re.subexpNames { if name == s { return i } } } return -1 } 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] if c < utf8.RuneSelf { return rune(c), 1 } return utf8.DecodeRuneInString(i.str[pos:]) } 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]) if r1 >= utf8.RuneSelf { r1, _ = utf8.DecodeLastRuneInString(i.str[:pos]) } } // 0 <= pos && pos < len(i.str) if uint(pos) < uint(len(i.str)) { r2 = rune(i.str[pos]) if r2 >= utf8.RuneSelf { r2, _ = utf8.DecodeRuneInString(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] if c < utf8.RuneSelf { return rune(c), 1 } return utf8.DecodeRune(i.str[pos:]) } 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]) if r1 >= utf8.RuneSelf { r1, _ = utf8.DecodeLastRune(i.str[:pos]) } } // 0 <= pos && pos < len(i.str) if uint(pos) < uint(len(i.str)) { r2 = rune(i.str[pos]) if r2 >= utf8.RuneSelf { r2, _ = utf8.DecodeRune(i.str[pos:]) } } return newLazyFlag(r1, r2) } // inputReader scans a RuneReader. type inputReader struct { r io.RuneReader atEOT bool pos int } func (i *inputReader) step(pos int) (rune, int) { if !i.atEOT && pos != i.pos { return endOfText, 0 } r, w, err := i.r.ReadRune() if err != nil { i.atEOT = true return endOfText, 0 } i.pos += w return r, w } 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 RuneReader // contains any match of the regular expression re. func (re *Regexp) MatchReader(r io.RuneReader) 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 RuneReader // 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.RuneReader) (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. var width int if bsrc != nil { _, width = utf8.DecodeRune(bsrc[searchPos:]) } else { _, width = utf8.DecodeRuneInString(src[searchPos:]) } if searchPos+width > a[1] { searchPos += width } else if searchPos+1 > a[1] { // This clause is only needed at the end of the input // string. In that case, DecodeRuneInString returns width=0. 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 < utf8.RuneSelf && 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 } var width int if b == nil { is := inputString{str: s} _, width = is.step(pos) } else { ib := inputBytes{str: b} _, width = ib.step(pos) } if width > 0 { pos += width } 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 RuneReader. 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.RuneReader) (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 { before, after, ok := strings.Cut(template, "$") if !ok { break } dst = append(dst, before...) template = after if template != "" && template[0] == '$' { // Treat $$ as $. dst = append(dst, '$') template = template[1:] continue } name, num, rest, ok := extract(template) if !ok { // Malformed; treat $ as raw text. dst = append(dst, '$') 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. // (The $ has already been removed by the caller.) // 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 str == "" { return } brace := false if str[0] == '{' { brace = true str = str[1:] } i := 0 for i < len(str) { rune, size := utf8.DecodeRuneInString(str[i:]) if !unicode.IsLetter(rune) && !unicode.IsDigit(rune) && rune != '_' { break } i += size } 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 RuneReader, 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.RuneReader) []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 } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/000077500000000000000000000000001433723652100231025ustar00rootroot00000000000000golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/compile.go000066400000000000000000000155171433723652100250720ustar00rootroot00000000000000// 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.head denotes // p.inst[l.head>>1].Out (l.head&1==0) or .Arg (l.head&1==1). // head == 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 struct { head, tail uint32 } func makePatchList(n uint32) patchList { return patchList{n, n} } func (l patchList) patch(p *Prog, val uint32) { head := l.head for head != 0 { i := &p.Inst[head>>1] if head&1 == 0 { head = i.Out i.Out = val } else { head = i.Arg i.Arg = val } } } func (l1 patchList) append(p *Prog, l2 patchList) patchList { if l1.head == 0 { return l2 } if l2.head == 0 { return l1 } i := &p.Inst[l1.tail>>1] if l1.tail&1 == 0 { i.Out = l2.head } else { i.Arg = l2.head } return patchList{l1.head, l2.tail} } // A frag represents a compiled program fragment. type frag struct { i uint32 // index of first instruction out patchList // where to record end instruction nullable bool // whether fragment can match empty string } 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)), nullable: true} c.p.Inst = append(c.p.Inst, Inst{Op: op}) return f } func (c *compiler) nop() frag { f := c.inst(InstNop) f.out = makePatchList(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 = makePatchList(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, f1.nullable && f2.nullable} } 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) f.nullable = f1.nullable || f2.nullable 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 = makePatchList(f.i << 1) } else { i.Out = f1.i f.out = makePatchList(f.i<<1 | 1) } f.out = f.out.append(c.p, f1.out) return f } // loop returns the fragment for the main loop of a plus or star. // For plus, it can be used after changing the entry to f1.i. // For star, it can be used directly when f1 can't match an empty string. // (When f1 can match an empty string, f1* must be implemented as (f1+)? // to get the priority match order correct.) func (c *compiler) loop(f1 frag, nongreedy bool) frag { f := c.inst(InstAlt) i := &c.p.Inst[f.i] if nongreedy { i.Arg = f1.i f.out = makePatchList(f.i << 1) } else { i.Out = f1.i f.out = makePatchList(f.i<<1 | 1) } f1.out.patch(c.p, f.i) return f } func (c *compiler) star(f1 frag, nongreedy bool) frag { if f1.nullable { // Use (f1+)? to get priority match order correct. // See golang.org/issue/46123. return c.quest(c.plus(f1, nongreedy), nongreedy) } return c.loop(f1, nongreedy) } func (c *compiler) plus(f1 frag, nongreedy bool) frag { return frag{f1.i, c.loop(f1, nongreedy).out, f1.nullable} } func (c *compiler) empty(op EmptyOp) frag { f := c.inst(InstEmptyWidth) c.p.Inst[f.i].Arg = uint32(op) f.out = makePatchList(f.i << 1) return f } func (c *compiler) rune(r []rune, flags Flags) frag { f := c.inst(InstRune) f.nullable = false 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 = makePatchList(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 } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/doc.go000066400000000000000000000124301433723652100241760ustar00rootroot00000000000000// 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 \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]) Unicode character classes are those in unicode.Categories and unicode.Scripts. */ package syntax golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/make_perl_groups.pl000077500000000000000000000045741433723652100270120ustar00rootroot00000000000000#!/usr/bin/perl # Copyright 2008 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. # Modified version of RE2's make_perl_groups.pl. # Generate table entries giving character ranges # for POSIX/Perl character classes. Rather than # figure out what the definition is, it is easier to ask # Perl about each letter from 0-128 and write down # its answer. @posixclasses = ( "[:alnum:]", "[:alpha:]", "[:ascii:]", "[:blank:]", "[:cntrl:]", "[:digit:]", "[:graph:]", "[:lower:]", "[:print:]", "[:punct:]", "[:space:]", "[:upper:]", "[:word:]", "[:xdigit:]", ); @perlclasses = ( "\\d", "\\s", "\\w", ); %overrides = ( # Prior to Perl 5.18, \s did not match vertical tab. # RE2 preserves that original behaviour. "\\s:11" => 0, ); sub ComputeClass($) { my @ranges; my ($class) = @_; my $regexp = "[$class]"; my $start = -1; for (my $i=0; $i<=129; $i++) { if ($i == 129) { $i = 256; } if ($i <= 128 && ($overrides{"$class:$i"} // chr($i) =~ $regexp)) { if ($start < 0) { $start = $i; } } else { if ($start >= 0) { push @ranges, [$start, $i-1]; } $start = -1; } } return @ranges; } sub PrintClass($$@) { my ($cname, $name, @ranges) = @_; print "var code$cname = []rune{ /* $name */\n"; for (my $i=0; $i<@ranges; $i++) { my @a = @{$ranges[$i]}; printf "\t0x%x, 0x%x,\n", $a[0], $a[1]; } print "}\n\n"; my $n = @ranges; $negname = $name; if ($negname =~ /:/) { $negname =~ s/:/:^/; } else { $negname =~ y/a-z/A-Z/; } return "\t`$name`: {+1, code$cname},\n" . "\t`$negname`: {-1, code$cname},\n"; } my $gen = 0; sub PrintClasses($@) { my ($cname, @classes) = @_; my @entries; foreach my $cl (@classes) { my @ranges = ComputeClass($cl); push @entries, PrintClass(++$gen, $cl, @ranges); } print "var ${cname}Group = map[string]charGroup{\n"; foreach my $e (@entries) { print $e; } print "}\n"; my $count = @entries; } print <perl_groups.go package syntax EOF PrintClasses("perl", @perlclasses); PrintClasses("posix", @posixclasses); golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/op_string.go000066400000000000000000000012271433723652100254370ustar00rootroot00000000000000// 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) + ")" } } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/parse.go000066400000000000000000001470371433723652100245570ustar00rootroot00000000000000// 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 )" ErrNestingDepth ErrorCode = "expression nests too deeply" ) 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 ) // maxHeight is the maximum height of a regexp parse tree. // It is somewhat arbitrarily chosen, but the idea is to be large enough // that no one will actually hit in real use but at the same time small enough // that recursion on the Regexp tree will not hit the 1GB Go stack limit. // The maximum amount of stack for a single recursive frame is probably // closer to 1kB, so this could potentially be raised, but it seems unlikely // that people have regexps nested even this deeply. // We ran a test on Google's C++ code base and turned up only // a single use case with depth > 100; it had depth 128. // Using depth 1000 should be plenty of margin. // As an optimization, we don't even bother calculating heights // until we've allocated at least maxHeight Regexp structures. const maxHeight = 1000 // maxSize is the maximum size of a compiled regexp in Insts. // It too is somewhat arbitrarily chosen, but the idea is to be large enough // to allow significant regexps while at the same time small enough that // the compiled form will not take up too much memory. // 128 MB is enough for a 3.3 million Inst structures, which roughly // corresponds to a 3.3 MB regexp. const ( maxSize = 128 << 20 / instSize instSize = 5 * 8 // byte, 2 uint32, slice is 5 64-bit words ) // maxRunes is the maximum number of runes allowed in a regexp tree // counting the runes in all the nodes. // Ignoring character classes p.numRunes is always less than the length of the regexp. // Character classes can make it much larger: each \pL adds 1292 runes. // 128 MB is enough for 32M runes, which is over 26k \pL instances. // Note that repetitions do not make copies of the rune slices, // so \pL{1000} is only one rune slice, not 1000. // We could keep a cache of character classes we've seen, // so that all the \pL we see use the same rune list, // but that doesn't remove the problem entirely: // consider something like [\pL01234][\pL01235][\pL01236]...[\pL^&*()]. // And because the Rune slice is exposed directly in the Regexp, // there is not an opportunity to change the representation to allow // partial sharing between different character classes. // So the limit is the best we can do. const ( maxRunes = 128 << 20 / runeSize runeSize = 4 // rune is int32 ) 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 numRegexp int // number of regexps allocated numRunes int // number of runes in char classes repeats int64 // product of all repetitions seen height map[*Regexp]int // regexp height, for height limit check size map[*Regexp]int64 // regexp compiled size, for size limit check } func (p *parser) newRegexp(op Op) *Regexp { re := p.free if re != nil { p.free = re.Sub0[0] *re = Regexp{} } else { re = new(Regexp) p.numRegexp++ } re.Op = op return re } func (p *parser) reuse(re *Regexp) { if p.height != nil { delete(p.height, re) } re.Sub0[0] = p.free p.free = re } func (p *parser) checkLimits(re *Regexp) { if p.numRunes > maxRunes { panic(ErrInternalError) } p.checkSize(re) p.checkHeight(re) } func (p *parser) checkSize(re *Regexp) { if p.size == nil { // We haven't started tracking size yet. // Do a relatively cheap check to see if we need to start. // Maintain the product of all the repeats we've seen // and don't track if the total number of regexp nodes // we've seen times the repeat product is in budget. if p.repeats == 0 { p.repeats = 1 } if re.Op == OpRepeat { n := re.Max if n == -1 { n = re.Min } if n <= 0 { n = 1 } if int64(n) > maxSize/p.repeats { p.repeats = maxSize } else { p.repeats *= int64(n) } } if int64(p.numRegexp) < maxSize/p.repeats { return } // We need to start tracking size. // Make the map and belatedly populate it // with info about everything we've constructed so far. p.size = make(map[*Regexp]int64) for _, re := range p.stack { p.checkSize(re) } } if p.calcSize(re, true) > maxSize { panic(ErrInternalError) } } func (p *parser) calcSize(re *Regexp, force bool) int64 { if !force { if size, ok := p.size[re]; ok { return size } } var size int64 switch re.Op { case OpLiteral: size = int64(len(re.Rune)) case OpCapture, OpStar: // star can be 1+ or 2+; assume 2 pessimistically size = 2 + p.calcSize(re.Sub[0], false) case OpPlus, OpQuest: size = 1 + p.calcSize(re.Sub[0], false) case OpConcat: for _, sub := range re.Sub { size += p.calcSize(sub, false) } case OpAlternate: for _, sub := range re.Sub { size += p.calcSize(sub, false) } if len(re.Sub) > 1 { size += int64(len(re.Sub)) - 1 } case OpRepeat: sub := p.calcSize(re.Sub[0], false) if re.Max == -1 { if re.Min == 0 { size = 2 + sub // x* } else { size = 1 + int64(re.Min)*sub // xxx+ } break } // x{2,5} = xx(x(x(x)?)?)? size = int64(re.Max)*sub + int64(re.Max-re.Min) } if size < 1 { size = 1 } p.size[re] = size return size } func (p *parser) checkHeight(re *Regexp) { if p.numRegexp < maxHeight { return } if p.height == nil { p.height = make(map[*Regexp]int) for _, re := range p.stack { p.checkHeight(re) } } if p.calcHeight(re, true) > maxHeight { panic(ErrNestingDepth) } } func (p *parser) calcHeight(re *Regexp, force bool) int { if !force { if h, ok := p.height[re]; ok { return h } } h := 1 for _, sub := range re.Sub { hsub := p.calcHeight(sub, false) if h < 1+hsub { h = 1 + hsub } } p.height[re] = h return h } // Parse stack manipulation. // push pushes the regexp re onto the parse stack and returns the regexp. func (p *parser) push(re *Regexp) *Regexp { p.numRunes += len(re.Rune) 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) p.checkLimits(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 } // literal pushes a literal regexp for the rune r on the stack. func (p *parser) literal(r rune) { re := p.newRegexp(OpLiteral) re.Flags = p.flags if p.flags&FoldCase != 0 { r = minFoldRune(r) } re.Rune0[0] = r re.Rune = re.Rune0[:1] p.push(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 } // 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 p.checkLimits(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)) p.checkLimits(sub[j]) } 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) p.checkLimits(sub[j]) } 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) { return parse(s, flags) } func parse(s string, flags Flags) (_ *Regexp, err error) { defer func() { switch r := recover(); r { default: panic(r) case nil: // ok case ErrInternalError: // too big err = &Error{Code: ErrInternalError, Expr: s} case ErrNestingDepth: err = &Error{Code: ErrNestingDepth, Expr: s} } }() 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 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 return nil, &Error{ErrInvalidEscape, t[:2]} case 'Q': // \Q ... \E: the ... is always literals var lit string lit, t, _ = strings.Cut(t[2:], `\E`) 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 } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/parse_test.go000066400000000000000000000361341433723652100256110ustar00rootroot00000000000000// 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 ( "fmt" "strings" "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`, `byte{}` }, // probably never // 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{}}`}, {`[\s\S]a`, `cat{cc{0x0-0x10ffff}lit{a}}`}, // 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})`, ``}, // Valid nesting. {strings.Repeat("(", 999) + strings.Repeat(")", 999), ``}, {strings.Repeat("(?:", 999) + strings.Repeat(")*", 999), ``}, {"(" + strings.Repeat("|", 12345) + ")", ``}, // not nested at all } 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 strings.Builder 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 *strings.Builder, 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]`, `\Q\E*`, `a{100000}`, // too much repetition `a{100000,}`, // too much repetition "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})", // too much repetition strings.Repeat("(", 1000) + strings.Repeat(")", 1000), // too deep strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000), // too deep "(" + strings.Repeat("(xx?)", 1000) + "){1000}", // too long strings.Repeat("(xx?){1000}", 1000), // too long strings.Repeat(`\pL`, 27000), // too many runes } 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) } } } } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/perl_groups.go000066400000000000000000000045431433723652100260000ustar00rootroot00000000000000// 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}, } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/prog.go000066400000000000000000000170371433723652100244100ustar00rootroot00000000000000// 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 ( "strconv" "strings" "unicode" "unicode/utf8" ) // 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 considered 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 strings.Builder 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 strings.Builder for i.op() == InstRune && len(i.Rune) == 1 && Flags(i.Arg)&FoldCase == 0 && i.Rune[0] != utf8.RuneError { buf.WriteRune(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 strings.Builder dumpInst(&b, i) return b.String() } func bw(b *strings.Builder, args ...string) { for _, s := range args { b.WriteString(s) } } func dumpProg(b *strings.Builder, 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 *strings.Builder, 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)) } } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/prog_test.go000066400000000000000000000040541433723652100254420ustar00rootroot00000000000000// 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 `}, {"(?:|a)+", ` 0 fail 1 nop -> 4 2 rune1 "a" -> 4 3* alt -> 1, 2 4 alt -> 3, 5 5 match `}, {"(?:|a)*", ` 0 fail 1 nop -> 4 2 rune1 "a" -> 4 3 alt -> 1, 2 4 alt -> 3, 6 5* alt -> 3, 6 6 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) } } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/regexp.go000066400000000000000000000172561433723652100247360ustar00rootroot00000000000000// 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 ( "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 *strings.Builder, 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 && len(re.Rune) > 2 { // 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 strings.Builder writeRegexp(&b, re) return b.String() } const meta = `\.+*?()|[]{}^$` func escape(b *strings.Builder, 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) } } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/simplify.go000066400000000000000000000103131433723652100252630ustar00rootroot00000000000000// 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 } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/syntax/simplify_test.go000066400000000000000000000100111433723652100263150ustar00rootroot00000000000000// 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) } } } golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/testdata/000077500000000000000000000000001433723652100233655ustar00rootroot00000000000000golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/testdata/README000066400000000000000000000016751433723652100242560ustar00rootroot00000000000000AT&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. golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/testdata/basic.dat000066400000000000000000000206231433723652100251430ustar00rootroot00000000000000NOTE 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)(0,0) E (a*|b)* - (0,0)(0,0) 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) 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) 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) golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/testdata/nullsubexpr.dat000066400000000000000000000035401433723652100264440ustar00rootroot00000000000000NOTE null subexpression matches : 2002-06-06 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)(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 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 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 ([^ab]*)* ccccxx (0,6)(0,6) E SAME ababab (0,0)(0,0) 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) 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) golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/testdata/re2-exhaustive.txt.bz2000066400000000000000000015043461433723652100275120ustar00rootroot00000000000000BZh91AY&SY_\{x>`cP: *Ge q٠eU[j mUl3H&5MT*VuܠLNpLkVkZ$f K2֯V 28T}BT>[j6f45cmP À^ڢ Xwcvkb>y̑DT$I *{RM&AMIQTihɐ)$ 2*jIJFi`e(P(D`B# P(Di2RP(Dqإ ҔX(Dd"2 45"2 i)h@ۂ >hѫ`V/vxP09޻^x5sO{k4j?ZkUo(EdYXjVTB ƨ,ʹHQFmFXF(,V6(6bj6j,lQPb[cmFѪ4Z5A`63blllUj*QEFXY$TEDTFƊ*-FTP)b+4ml[Qj-FZ64jFj(ThlT[mBlKhm%66ˑ&&9kᔱ$3HڍlXlZEllljl4mFmc`K66UC+ٕ5j(TՍڍV,& P@BjE LtfMJQUʢᔱ$3HllXlZElm[EmcDQ6+VX؉l͔iVSCFQbV6դU ƭA+ (mYEi6߭cccܽm%"KIFa-MlStQ61`UG+&dIOn::IfΛe(X)d2f[I9܍e ëv.kK[1df S,f3v2k4PPE(F4Q]ʊ[vim̥jM34z.+dزʫij%,Z2Mv24w.Ś&[K;ߕlXmLfkb QIHÏNM`0*-E&ەQn@miԧlLGj(FL[tR]ƱgjvT(5PQ%+$ΠtP$IZ$I T{;b{A,)uZ fɩ;W*k4v.kK+ֶͨM svՍV^͍[Q2inXwnaҳIḑŚQLi.f7kMFjMl2ͯ1M)޷bbIԛD֛Xj-VͥFڹ[kS1{Md[A棖6Xk3q%y=EMEDM)zd Hi#:Z6j+VllI-mNqalW'xǹޓSQQ4]kSb2!!+s=Tvfiz7gGAɤ=2dMW ]Hҭh"[ZԆYh"[YTm{uqlM$Yɡ)h~YDk`ȱF-i!fՔf8SraImFPn㎻kb-m69v8egIZӜ?(t!+I;94Z3%8ZsVNsq`Bc|!)9g< b$3%˘Ǟ4|&Ėm8}8MEn$ڞIK6nrܴqnsk1LM+ԓr&DnRQMUW^]$ eܛXCvN×)ͧ5m|z{] -$lW3,;7^x&>REEmr[DڦͪQ1UbU2jJ Jd-eJd99QoNz׻bɸE勝TI7Jn-3f92I@/v7JYU(9$>-]\T; a8\}_]m^esOI$03 03 03 03 03 03 03 03 i 1e$i)I$ $Mٶm)@f$@I$f$II$LJZ"""#FFKDE>n)JRI$S%kFM{E&͔KIY$6adkD$im)dM$a"hD,UU d!Ѝ i!b1?ef"""""""""" A1bDDA"1 D1b"""""""""  DD#bDA DD#bDDA"11c1]c1cuc1cu1c7]v1c1]c1cuc1cu1c7r1"""""""""""""""""""""%1c7]v1c1]c1cuc1cr A1F"" Db"%1c7]v1c1]c1cuc1cu1c7]v1c1]c1cuc1cc1cu1c7]v1c1]c1cw"#mmmmͭ$!$ %I(BIBJP$!$ %{1c1c1c1c1c1o˯yKi@Ki@n)NB(mRB(o{ܛmԥ){{m;wormSׯ[1c1c1c1c1c1r{{m ɶJR;6۩JS{_}ׯ^[c1c1c1c1c1yyyyy{ P\% P\% P\% P\% P\% P\% P]/{]uz|1c1c1c1c1c1k k k k $$!$ %I(BIBJP!yy{lIB!$ %I+o7ooo1c|ū~q ^[߼lv6.m>\ $߼D_.I%߽Wؒ_ec֠H8܏5gr="OI%Qce_pGY6ZjqRS򪪪LXק2kЂ8٫~|>||>5N/ʑK:"il ܙDeͤ\N~H 8_s_:._b㘿<$ђz:.0}}߿BDrł0X-kV%7v}>??st::|.TnceKREUUUS[UUU^nrh`yYih`F3o&#\~&[<,Ig< BP3˷06™[M\(K݅F0/)f=xSB5%L*򪨈JR)J(P)JRB)9-kp<.*xS32i$cUǏqZqvd22  Į KK}[~ګj'6ZHЖBʫmYeK'op']5:oruS'L5-8Q jhX0!8`Bik&ڪ9T9P7YͬcBf1!7mdmUGouހ={xۮ6 &7UqֱaBwlfc3 k&ڪ9T9P7YͬcBf1!7mdmUT sjrnX0!3cBnͶڪP @g6aBg9ݵm @%Uzۚj[s^T%MW[Vޖ{VNjx@U;30-w l[m^wL*+aUo׹[UVlL,[-m; 9@ZΠr@B@3쪿;w 7m286Ljx3SP=m82cm\.6ȸͳm IRXͳmB!I! IRHBB IR^&/ ys6QNƷ[l)JR" @$ @& @Ԕ~4ņcPd* #RVY%fKUR0F)%Xl4QFYmT,VL1R2d٩#I1m),5,ض+YYH#+0`V#V#S,L XZ1L3 RTfViifFi3lؔҲ2 ,&M3mTکb-fi*LDVf&ƪrabE+6$Hia,H8E-pr"HIf:bI#&sIvIŠWvI̱5XalmjűU]#HInt`ܚ,cQ'+g`ғ Q64:L4=n  ׹޺ ]{6깢ة,QQة4V5D[5EcKFK[nci4QZ6,V,&ձdF1vL+T%6&IfQ[m†Ț䤅`Z$5`ͷvI)ۭGb6G[)8Quw*V)amik NjAMRAL,l۬siYۮu,hÃ+cZ8$]qYaԦaRn[[n`廸ekS[5Hl̴2wu0qr;n9]=B刺cdgF{էfYjZ[j1C:j2knڒ3jlmN%3'0RM)y76ڪJtfkF`Hꋭdئ,ܒ,ѼpQRͷ*6{ $6kHd M"eWv6:L۷xҩ5ec&)tuԭoS]ȓl2@3%Y.e%C6XH)y9SȓLƉ8Oe!9'cyShХAHRBSBKbTQP0FĔ14F(" bcGmigw꾽~94 =wxx})[omĄ~}ߞm5c)Jc,;]uWWjB6P$!(BIBJP[!$ %I+䪟Հ~pA¦L !TA,"UD`(7}|/~}>}III"I%l߉4H 4KaLa F&Ɖ"bL2m63[mUS32 Ń̓l2f-HkVXKSJRllfRl(Хk*mUllEi6K1-Vd+ZI2b0,2+*c bC1 ш4XdJuT2K%Yj6)E6fXɪl,,iXT6Z͔II ؓ%+k`Ya3"$jTTI1jj3 f ,ԴVi2LE,McVamR1e5DX ʬD2̓&4[$ mF%BK«L4FZ62mڴU4FFV#,2T-ٲZ$ҍ1 ՘lXI3M&$UHBU2Fh%5`ڢ2&ZiZckMj,e،*=*e1lV+MFɩTc+V5bjaZY023e&XA/ J;UKeII`ea-*Ulx 7g|# x kuY)mjҒVE"** A H͵ff*?A~_N?Zs9a Qnk%)JR!J$!BEDUDUDB@$ @KU%Tϙ;{u׿}^U!oϚsH;ۍwsd-z`>{Tmc)Jc,˶jB6P$!(BIBJPA BJWz9p;vw6ߧ~\V>o~겤sH;ENޡmp=yT^'vm b)LpAILcmHHP 8!$ %I(BIpBBq{ip;}0[_ʼq |sH;Udkݶ8NWyQS' m b)LpCi[n9κBJP$!$ %I.B6B6Pl %wǿj=I2M$x~O?o]=>?yOE>n^~yo{[Cmm A H/;k[m0$I Lɀ;p$ @$ `H H H KTnMm͜54<3Bm"i;cN2r8!nZ)JUx^OxH H H,۳ܡg6p5ck:)JR1TETET@H L*!YTt1vͧqPPì-[YԤ)JRQmcDQ H H K(+$k61 [o ?/JTdXU#5l-cb*MK$jɒehYJ,6V6ŶB m5_YإE@<HV(r$8k T3SmZ)MxpA PI"<{V}$jzUH44)TԪL&A*{QOT%F)$=Oz5*jI*0&3&K?\{ǼFAB#`#e- I)hRIKBJZ'E`FZhh]u&* IjЕV [IjЕV:XJN\1U`HN, IUU{pu'ѫzu'׺<Wy]xƨj) 4d2@M&dj-F&QZQPY5EQPb5*b-((PMZեbR̛HZMFQe2lY"i65Fb65Y,F66NuNu.reܧs;.JaMAIUEX jX1 i jimJVQ-fl$ٹ\'.r˪ĨĨmDUUUfKf$e2bڕ fTeVʐ3JE[# lmbR-JbSB &-4&66ȱbōȱbŔ-hѣE64h TQkQhƫF*[EF([!m_phC!!D! D4aH 6ک%(FeQJ4 "8eP[4ۅ =znk[ 2[3*Mcb1 {QJζa C U8jL4EHRMe 6f"hZmխ{5U|7ٍiK*fYJL,mg~n۹6NnѨ5om~ 거0|ݤڝ藔Z'l$Fѡj[x%)!)!!$!$ddd|9Q˙rGl6V(ζŶmon/$فEEE(*v;j+VGiRm@|FRIAP)"5$o i3&a&Jf+Skdܠh.nwR[6}U\8ߪm6&ho[l7ɇf=6!m+l5C36omA#i8XrrDDbD_U}m2j5Mݳ4u;̭맥Fl{,Fss1jA5^{{I Rvhb_afafffffafafafaf *b$,,JRRI iJ-DUX[,I$$DY6l)֔̕6T$&IR ,$lkeT MHejcfٱ&)}WI2ZRR- Ud2BfFDZݵm"""""""""""1D1DDDF Db"" A#b"" A1"""1bDDDADb"" A1F" A#Db"" A1F"" qc1n㱌c1nc1c1c.1c1c1c1뱌c1nb DDDDDDDDDDDDDDDDDDDDDKc1nc1c1c1c1#bDDA"1c1c1c1c1뱌c1nc1c1c1c1뱌c1nb DDDDDc1c1c1c1뱌c1c1c1c1c1c1cǗ>i@i@Ki@Ki@i@Ki@Ki@Km]^1c1c1c1c1c1c^^vKi@Ki@Ki@KiJꫝu$!$ք$!$ֶZmh$$ wu]uw!$ %I(BIBJP$!$ %wu]_}c1c1c1c1c3]u@;mp@;mp@;mp@;mp@;mp@;mp@;mp@;<1cƌc1c1c9y-!v-!v-!v-!wg2)Lf7|7|7o1bq<:p_CE|q=5}kmk4$|qxcoݒf|o@d;mlkvkETWTd]w~8p|8#苢."ꏘZ#X[M?KZb|ץkuzš{猌O>KUjŏ -j/?~_}߰.Mw>v~AÏozmmƿ26_vVg?L?954i[o**-55q.;<>UU?Y++ra|>>./wr9"@oE_C"_<|S_6:2ӧXVAQV*e,m=6/r8ln{lm9wmxe:I&3 xuy@ v2]mf!cm;>uaǔ{kÏ(` ]ǯ֞P*í<+aBl1m+y[|e[Ⱥ4!C=7-ev2]mo"o4Є! sHmyʷuUB3cy ۭXm&yu&yu&G/=-S>` gS[_lSmq* p'hۭX9}wu]mw^AbOON:@[l>O爊Z2_n7Ƞ@@uEd>6vILmrvГˉ.$EIRX`F$)$!I! IRH@!##92Kn1w=6mR)ׯ^wz H HmffR"V23$ń,H%YmDDB#-ҍ MM3VB&ԭ *1Z[U4Fʴ60TEZٔ)5 iJQ1ilլ-ef AZTkliɶD-Vm&M1* 1V i+1c;K jle59j!d™[$b$5$4nGM9V3 Χګt$%!4M VukmdnCK`IKK ­LJLjɻDww9 :k-U"&eIv([Lj3TR+UJ᝶8wmQ˪9uG.R஻k^ ºp+.Ni 7%tJWݫds8 WqewEMN,]ғH41FX)bdȒ-mMSXИmՒ,$HIM-6R fZF-VQ128MM*-U\3c-A5eݝ*)6U RuΫs$'!YIQ;Ce`ԛif2ONtFd6ۤ.95Z[ñ)ĭmRW V0b2D3"0Qc"Xa&#"SuZ6[FHZ$ڦbb-Im ##fDeH҆$41,%e 2Ʃ!3+5JRZZ*iaئlMK[2mFYb&Y !ƀLa%(Cdՙf-ifZ6&1eFQ0-k3MC6Dj̲SUʒ iMQUY V0г6BŖJؚXW6ҫehXc$V(I"i ek5 3*e2ŖRl fK RjZQe**H?)~?={!u㗎Kk-ejҖ+--UU H@$@%6ڭ\ww#9ss/w{Md)JRzuPI$ @$ _kVW6~|3k S+ʡ}:xUTNi>k{ڔ!Jcet-q$$X$!(BIBJP[!$ %9`>Uzfsdk^8ﱿaQꢫUHg}jR)햗ݷwI(BIBP$!$!BJWW9yraW^5 ul}:{xUD/OkNjR)i%/un6ڸI'I JP$!$ %I.B6B6Pl!q_mA0$ `H%Q H H $ @$ @& K@ =nGkdu!;wwwwp@>U˥ێ*)YqU%mHRmR@$ @& ֹW-{⦐m)EɭaB-TET`H H@rw}N^2u5wG{/-[e!RUQQ$ @$ A H(+$k9S7Ա+oT+ 7F1AC,dtjZR6VJZ+U*;1`ʨ2 F]v6lh5cj A(m  <7O| * 8 |};8dET4Ta$JihQ$I(PڀzMRISU=@TԒQ M4v/..W...?b(jH H "}+tt^+ttttx:]:_>>ÃzlP>rϻSbTP cZ q FzjHY!#m-|9J4jh9J4jhѫ9W4z=+W4sFh=+sJ4jh9J4jhѫ9W4z=+W4sFh=+W4jy4jhWyUh}=+W4sFh=+4j mH%ڪ6ڋjU6EQ-"Ulj%Tj 3PO.sf((PSlsJcR3afaW)[BUm is[%Kh%̅3Jjڪ,Kklllll]븪TNYN%9D=Ra$*,$:åܣ\z7Cҍ2S7C{̣SbFѬ["aFʹmEF6j61\5F/JyHT=7Bíz%' r^\-mF9zW/ b)w\K ^ͯ r!ІB B Fcq6HHبUm%5iY,bȈkhX!DI@`0oU 5bX68"HI36ș2fdUT&jɶmLň h5C,!  R&%TkE&MAl,CVYk -wE1m`nЍDD1XrK cKfjI ɢ0IF*.;fV55V)ĵPmFXj- h&DDK(["RM_RR^R^m EE 6T Rb`hs&d$×%%qg.2`FRQn7 n Y+#0Lq#qm#I978ss8,ʭLU1TM4D!9!0B#ڹ0FQ[Fщ+Ju[Z%px<s,ʎ̦U:d&8G}s7s7s7s7sţ4Hթ6Si46["FYMC[XIVՋA DTlmƋQ*  űf&mlU&&IGYm4[b6-Աf6j?JQJ)l[[[[[c1F1c11c1Qc1bcF1cc1c1c1c+X1c1F1c11c1Qc1bc1cc1c1c1c(1Dc1F1c11c1Qc1bc1cc1c1c1c+1c61c1c1c1c1c1Q*X J1c1c1c1c1c1c%V U1c1c1c1c1c1Q* XJ1c1c1c1c1c1c%V U1Q*1ݭߛ!$ %I(BIBfwt$!$ %I(BIBJ 0N:mDm*% hEY([F@B2:cH46Θ* M1HM1Hla":cH46Θ*$ts b2AFIgy_yع*"J߾{ڹ%տ2!Y0I2y$$0=둆Βd>I>I !![o?|>>|>|.nzu{|~;%=vݴO۾.Vg|\7s֬ͮU/2;n'r0A~G]"<<øȉ /|"$:8܋燞x/]Һ__]:̙4|ݸ((׽{{]@$ @$ "fmf߂_tUR+REeJ+"Ta(I1Pe3?-pK&=)%fNOO>}upn{w*z'0"& S1rv^WrIBJP$!$ %I(PP$/32̲̪쪩R hJ0UJ-I"0RPM:AU R~WݙfeM! 4i4H$ѱ B Hll+(ڪBUH FSmJf3Kb15%bUc I!-[6PĘV2SK c6LlBAb0Y00FBU<)MRXIKdL)6hdLb`Ŗ&fF!4D!fLbb,a3%0UFeS02% –HV&,Xec,cm4d M ̈b\2LfX̳%YQ+ }A2bbF,ȬВlI M2mK Q2aLf0%Ic(1ĉc,21QbYEfY̕Y4LI 4MU VaLL)eKDObSQ*CjX`YIQI@m//*nzw|૤q [܂^-HHj[mm_+?[n֭͝11DJ"lWwwwsN%twwn H"DH?ŵm"""""$""""""H"""""$""""""H""""""H"""""%""""""H"""""$""""""H"""""$jȈ"""""$""""""ZDDDDDD""""""""""""""""""""""""""""""""""""""""""""""""""""""H""""&յRqQo^O ^x7I08Z߈%=&Mlٳv3{ٻCae!JaDDM<ic0]vlQTDDEQUDDATUQTDDEQUDDATAUV"#UDDATUS  3v$pm۩r{}mePL})P%Tϟ>ﻳ73ޞ ܓě nxM0)01bKʺ{{grIBJP$!$ %I(PP0 % ']f`Yλگ+ZZEEKZӟ>6zzngI=&fzwt6չw&釬61aw+{{ H HH>rr-ȭvnU b&ܡ1L"#w9νw{@$ @$ "$ 1AY&SYv!߀@{x:\D`JE@ 3hF"H mi )&VƐհ3[U QE[ Vj 3>Òp)UK`WuuIk;={H($T`I$'J00Jf(4U5LhzRFROS i=@%@=@2>(5[ Ѵږ[92Y*Ŀ=Yr@a-$ "JE[QA-RPj(<$R@a1IBPKj(%%$./j[%:^Lt{FֽW8UsMNx"=K]6Ow+7gV* ,mHUrf[0&m!R$+L"dw"wUW޼^JZjG4j揇wJ]uwy^xywzzWJV:K=+-}5yҗp]zW1 1I" b@c$DązFh\wtWwWw8{RcFhRKή=wpW]ǜvԭ|5cmQ j55Fm-Zm2+i%YLi3Lj,LY%6Z2!B҅ BL(e2ЦVeV2m1f53B)+5V`Ӯ]t6]t)bJmMmskhZ5FDZ-DV.25RإfY3R%1-#aY[+lSm)l, c2YF9q.(twmṰr.b@mQkcm[9 em-&L m)2L3m%ViU2jl+d6ڋmjhMD͵c`b"D ZM-,6U f**e`b,E5,EJ#DXDkDSB eFiًR(LQ1F)ٓъD&-kXSccccfōe4[l,XȱbŔEQZK,XcEkE% l4hѣF)m-maJFV3Qmm5j5A#V+Z16Rl1Y[cU*T!ІB B bd 21&$I#fѬaV$m-&ؙI$4Lp VVHF"a&pbyd$rni<#LoP 6K m I,0;T&xA6ЀhChMC l! 3z4gfH7ZxD$& }eo[fM#DF7~\uۛQ8ۑ%9k][l|APf3LOwdmS̎|!;6Sl8VjUY)1(8\ɘU0cHFgm$xx8D4zI]!JZ(RDȒRkҚ@3+*(k5̬mH4IAXVaY4ls4XbV1JR7 q.\WrQ;l[Uű(mDhњZ),S$S ,`ǖU$4Lլ E tEY\IحF'l*I#CiI&Hq1$IhLuF)L#9ZJT|Ftղ7j$IdDL5ߜQ&+q6ۭO TV5VS`Nfh2`s$'SkUpKFUd#3G$ tf8#9TbVհn!nj<&?$Bo͜! wT([Np LiI$q cLD 6MD \0-Ugx2VmՒL[bb6ɍ&jmC朜iq3I9>g1#fK6IY +2K6IY Fm=lڹڠ4xk+^|O׽_<"hpy_W=}}zy!نܔĶ )3lٔf7O*mOj] sm|mjy6LHfؤHi D&6$mm2I &K96" ꆲ%u9#ZUq;9WeCCUUtmPٵh|:=񈌜y3>L1s׊qdx$oh>!9Tz᷏RƤKnk]ƃT͵uq!fzdƵVdUl6"%`)k=*y=,\m];]; H$kƫh6BT+lHnRURU``Y*ʪ{J{I6[)HegMGHH!foxM"Fs$nq$h5QZRJ2œomLZ̀V4h͠Q`IPi6 EBBIY5eJma K-$&Ipj5B V8s1l+MllH[b@M U+i#k*d679FFcb(MIETkm(5%Q(HX65`ֈFJ""fjb2D`4,-)$$Hi֠ k]vŵjU7Fdd9+ H `*TP lj+DdJdDņNqq91܄Ap6bCibUě4r:[q3Nc$1mnRX(.K3AFea*J"1FhBh-= m6d!eFI5ZNyU*19aIY!LUqr;C,̄:ſ6-9n͋uNlVl4cm,Ab̬Rښ98īX@FŬcmJL۴j&I 4FjcrTƬ[K#tZR6Uk)iUVjڶ611km*[[\1c1F1c11c1Qc1bcF1cc1c1c1c+X1c1F1c11c1Qc1bIwuw\9sRֹc1bc1cc1c1c1c(1c1F1c11c1c1c1c(1c1c1c1c1c1c1c1DUa*jjjjj1c1c1c1c1c1c sL6*9F1c1c1c1c1cĪUjjjjjac1c1c1c1c1*%VᅬD-!m娉B=Q{D-([G9j"PprDm娉B=Q{% h7yo mkJIBJ^ZZfĒ$u=5!eYH-3yUx--33--33--33--3wĒ$!$ %I(BIBJP$!$ w¬DmXB=Q{% h*JJRyj"PprDm㖢% hr)B=Q{|>|?./׿owu~M뛻'>0CoN>49'bPnΤ_,~]~Kq".yWD`msvsK=Y`Cޞbl{\+om$M4;~~u/U$J2z6A>ͶU4Ks乣6Ҿq|~}b81Ǐ JPd~E~*~kN`z2T_8ڥ봯ξ} c:N'yUUUU*f45g:WUv0~~/7^{n]~YUS{^m5JBɫlVDDDDDDDDAO)EH)E14Ҩ*#ID%>ICnj""/I)m| %UUUUU.\\!N-Bud^I$3~[m"#-C⠲ty[jIH^-mmpiz9m;m[dK{mv7ت(VY@{ivdhqn:ٺr!U.mt݃x (8UmM4F[p ZqƗS:r!U6Y]yu3M cKqx(Wf9NdͶ^/ftC6(![h7M5C6C6(![h7M5C6C6(![h7M5C6=iS6mE\ o$ڴ}qm셔QUS.liƒqmi-tYeUU+y mi6qZEN9hfBPErmM4B펧I3o~~^__¹Oִyzj辁vӃ{$WГK(Hc)چm) $ IRHZm6B$)$!I! IRHBA9tζ:շY~~]4M&+ c"""RAUU[j2HBI!H H HzjKV_Q L23ḋwJ,Tc펪CVVfĘa&1)rf +W.,Xs&#ɹ̪IגUQ*JQO JQJKZ,V** A~CGtX[|Z+Xgg4c?)^l3Cަ!Ѳi)L*IjR`R1#R1$#V (LHWUQZR%*$m$fDmFS1S5**`16di$$I"JL6imX-imLX)IXe$TaEKV2cc eQ4F!f%0 C$X1f+2!B&"6I"FDQf*,)T1C,ʩR Yb12FefRĆ*e0+-$M"MBDb ))TbCcЗGeYf%M66&C$0hFM&)Yc)C2hR,Yd,dbeJ),R 3IH44&iIfMŐfYLʙa`Ŗ(RZj@Z62XbPֲUESmNHu<1Ms"""#*$!$@@B @VVϬ}1Qjg_5\n^{׉@$ @$ @$Z"""""$""""""H"""""$""""""Z"""""$""""""H-iDDDDDD$DDDDDIDDDDDD-iDDDDDD$DDDDDDDDDDDDDDDDDDDDDDDDDDDDDV"""""""""""""""""""""""""""""""""""""""""""""[[[/{(f~e]JX/y{ud$ w(am]ݲ<ݱ-j%"mmkV)HJDФ)HJDU{s6t=No{x` aLb6M&$ %I(BIBJP$(RH$ %$\rǿ]sw{ミ%?6$@"@$@"@zGr@r@$ @$w$ @$ @@$ @$ D$ Grր7.YۻmmUU[j+UUmF$I$@}6nMqؘLa)ljثQa $$D HHDrk\ܴmt&i1R%UPVZII$$ @$@"@*W [;C9i+TUBII"@$ @@(+$k2d+o * iFfF45k 5$5keĶd AXXZ&D R#F5|$]b;JAR(0Nf)jl$Zuլ5Me! bmZ6hsi$cb`7oYV ̚I$"#ṜLh=VʣFi©JmSUcDF UQDQ+03DDHL6Ҏ!I 2( Vԭ9UcRf¥"% x̍X,QE`oҶ6Z|d$V+plI2E08mhI,RefQRjR $%hE(F-Z1&"5aRUpaF U60q#1YbLIPʬ1164"i"mmDM$BMmhM$IJU[ PQQbFFFF1LFJ)2bkMF6!CQEQI֨lVKRH#8AҔ02J@$2Kkd02J@$FSg8RJ2c')e1i&$"ٯfb5cQj -lmR29ni"hE2C$Z4RHƨ5UERJ(bX4qZUJ0h%STJ'*9efT2doZԷ֒GF]+u@YiIMldI"4A4Lm4hh`F޵(1^Pɚ""!BUmm*h4hѵpud$b&&6nEb5p7q-Zj8NS *aN1NUfMq6m7r&#- xX$VeK eabe+LaYfEfJ Ɇ4hmɋ1FL*r!+$iK4Id[06$3b@TF*03 4lSmlUb11S)!`)[l#L&aɍmTQ5T؛a4a1"ԔќpsRp&J"țcsT eM6ԶRZ[Lgn8o2FILK)X,b& DhF2#c0cmH$C@h4؃PH 4RK%DM1a-F1c[,hS4% 0$ ZtRlUMfVl#nLƙ+2q2VBig#7YFTbh2kFC52j0QSjED" 903LS1Iʖ0U!̢LdҮڍJQYL dSY5*1+4Tƒc*/R @lT 6M 0&F&ۤFVKe(К-IڌUv  [n۸`t"#G4d96 $dTVC8IPIU]vdw iVK&ѨMIj6QEFjMQTɑDK))+AZkdZjZKIR P X*ڕ*J*SjgMCqDDb QJ4QM1\2$B#l9Dcpb24M#q&ȍ6L֍7-e6ւSl6&&Ƅ6"a[k!*+nIhĖj-ڶmCqn#7̢HApl#F+IS53PKHɖҍ6dFR%j@LjMd%Y2cE2ѲYLHɖ0J)Th2UCln!ĩXp&4ۉD 4[g- )aX2f#"qk4дK$ZkDdFB&"lܰΚe6ƱZ5nplQ{)A߶b"cFŌZQEY,6m"ՍUlmƖZQűbDPTFѬ`b* Z1AZŃV(+bJ[bVm+ )klmQFص&3VfJ!)??I I$I4I$I$I&C$ I$I$I$I$I$I$I$I$HdaI$I C 2I$vaHdI$II$I$I4I$I$I&I$I$I$ݷI$$I$i$I$I$M$I!$II I$I4I$I$I&C$ I$HdaI$I C 2I$vaHdI$II$I$I4I$I$I&I$I$I$ݴ$dI&I$I$I$$0$I$I$$0$I$$0$I%m n+mV+mVraHdI$I$I$I$I$I$I$I$I+mVp[mHdaI$HdaI$HdaI$HdaI$Vp[m¶ۅm n+m0$2I$I$I$I$I$I$I$I$I$I$I$+mVp$2I 0$C $VpI$I$I$I$ 33afl0͆36ff a 33afmm-)Bx;7pycNUwcNUDJ\0۸;l0JRn{% h([G9j"PprDm娉B 哷B=Q{% h-DJZ-c ʽc ʽ60% hm{wm{w-DJaۻz36ff a 33ao2P*R-([D)J娉B J]v玲UUfQE$4 DiI$HAeЖBJh&,Z""$DZ-$DDDIH- ""d"EАFbSKe7!R6f*df)a)&5* &II H$I4m B JS$m&RRe mik@@d$I$BJiiPdI$HM6I3I2ě4m$BIeI,ě*jo6V>O|_"ȾE|_- 8F~pde$?X>p߹u^{ $˄I^>nIuIvĠd o"2OhZw+60 oX5?p~|>>|>ߑE  adXIIPt4K4~h?i4R@(?HY'\n=t.SߞEQ(1`'b9&#$u]<;a`s>o| D1 D1tY(!EDyϨ>~\pVɃoK |tj.s/=kwO_>hX}|,fU|>"z/>LX],f?="RKa 8)O [zu[X4zh Ę_u{ϟ;!5) n:wCѧa}={kvެI!޷ QpB#wyǽϮ: Uo*<{y}p [8Aj[Op3M,ьc9n4<*|ikʾ4 K4c,;[}4c<;\Nrw|yAj^w|y;><㠵Urx K4cKtKT<*{.O{w;4M-;{*Ӱ;\N4F2õF1Ci;Nʾ4-;{*Ӱ3M,ьmьPNrӷ;}l/>o{/nUl>i@׷*^}Bty7܇GV[U LC7zf6x9מzeHi◼mc떗Ex/ka{*lxrI߰wNB@ rtgv 8hOPe8޻m āΓHId7mvJ%fflJ%ѱL4l a3 6faff6fazeȷ 矟>|x|{b1a Z]@$ @$ "$6f0+誨+)D#5aVL1UbʪŁaXƋaУ"ReLLV*Xa0)I2M!43&dXʱ`²Hȑ 1HƈHͥXaJ2F!2&gbhL&LDD#2&"@jeLN+DB " 6q2ms3Iq6Ds9rˊBrQI6Dl"n!͑Bn#qD8s ÈcMG8MͰnkj 0n  `zxzxxW.$ r=qu6s]I)-$'w;+rI\)$N=Դ Am-9ZZ AғV4[ بJ+f6mXejiSTPڊd ,k%DZI (h%$"6Պ̥ȄdgD[+k]k2+2+4MJ&eLV J-Ȕdc[cQEխu[UnUD8-icD5bYY,6FqX+e%FT+qN3IsSQѲFBRI8)DaPZULTYJ8bq1J\N"qmx63nCQb(&qo:&x$$ ;V jbM(6mIjƖTbbxEEDklV FԲcQ9N37(zj(ΛmEW1ZHFXh6b.QjH4G)mlBLO Ɗڴ"դLqZ ʬ82 y6Doh5d &hɹs PޥVAGWR 2 2.2U8g-Md8p0v;UBUVf-U U^lɳۛ&D#l$ْLĈ65Q!k3YCnCmC6g9q38xcѱTdJq1 ME2MMG"xGQDD^$HVeBLIZ%KDY`%GlX~K%X{ -%MN߻˩~_kU >hX$G/*DĒJQ}úNu]0&K(bUUdDHZ]@$@"@$@ٛUо1񪹅 'ьirM;10DHBB-Ujcw$ @$ @$D$ٛGo* A5>|^Y:pNq'{rxJa5Jcn[.廁o[&N[֯""r-RmW*""r-fÙfna7Ss~ ~cuYT"MW5*w'<:T>5B-}&)L"S͵1fڇ]w.uԶz a 00͆36ffa)9w?1|ΫUkMWȷUN f\b%06W͵[6ce:[mm-.l0͆ff a 33a Sal0̺[]"D$ DUUUWL3 30Z֪UR$Dr@$+Z֠30ZUT)+Z֪@$ @"@ݫwuͻ7]r 6UmjZڭ+y 38@[)Y ֏<7f)f`f Hw3  $;cr$S1L"RH2)JT@H HD#\+nQF3rqavB0IB )bibB H)YL  = DP"0$%BZi@jVZB603-4R(RE[)V1[Yfmb3}c-cBxbĭj  "2jlE [فSvpIT0TdU i#MQT )%MJ3Ph P~ITJb6H#fiRF&F0لRm! I026"5! IB+0ZM5!6¦$TԆ5&dQ$PM#dRMF6A(ZSiQѨ J` 4PiMĦJhh%0PJ @bS4j45A(h0 Ħhؔ AwڻE[[F-(Җ+h4+b"6C !$d aZ[HS)K$(JTZ-Z1EASI0cki1m mh)CɦK!EE5FdmHՊ e(51#UAma-DT+TK6Ң[b 4j1Yff@ a[ma[ 0H&-5DmlTHͲdl i3EY+*¶+bFm)!lb3,UЫh6VdR6fTR3JCajԕTҥ5H $IlBYf$U6KmE&6AlTi&6߁jjTb11F)ٓсe -XB!jbR61F(4 2b1SEI1ŵhl,XȱbDU6FdXb6ER"TkVl4hѣFEQM4hѢ6hU[ڃmQ6Em*m[J3HlTFڑVmhƈ1F($d4Ychfmŋ2ԕZF6QjeY(HM$RZHؒJKD34h8B!DiiVC ԥ1&E))6iHmda 6d.MQ%aX`mT6 5Ec A0aaK + "a0 SU8mmbDBh46|/-lmm޶#zUpojT %D hFmm$shiMm)Hdb1BБgrcb$cg8*)RGH:6ʜi xx8+[jk6ܑ61"lIԓmU_Jd 2fIE( g-}UVMMFf|Y&HKI1!h:emV[x#d$HD#q(%^6b.9Iz[2IZhm`պYKl Y&cL$lgKbchFإjjb6ɵ*fęˆXq6UD#A&4b m@%>WnA1AҤŵP$"m!&i""lџ DThJ"BQj )b(+CU64$mM#1LS1Y-Zh261i*CdX6QQVCcjjS13*ha 2)P#)$R2IھY'U$*HM$TH +kW\ )$TIfت)G;3xI$!CH+H[Q-FUI[VV!B`I$B8Gj b6hq-$f8luURhmpjri0 dR1ī֮:)n!D[:emͤ4#I 2&D#dgjվ064mjZ|AX h&[mE\,Mf$n}Xf Um%T4'^1a^gi4pI&8a4 3L 2XK!B&q0ESK a/#$ -X6EEDf4"d"JB206ҖFfDn4¨U6Ymij ƴjH[H4؈mL`**Uڙ5k(fYHY1qfǛI0&D26DamV4+V6#ͬc3%0KVmҫ%RZAքJ֑%#+m]clIUQR5UUAYVَX* Ye ʡ 4#l,(aKSj*춤beeSdL&0c ׵oPkh X2IUFI5`MAA6 &*Ie@V ,n2g"Rg$-4H[` JZʴiQ-QE EQ-J(m#FQ,)6J( TA҆I!$$I,RRk֨$Jm **b @ lI$Re+"$IF!2#c&32K)ڮF(Z N.1,'.# 66IUZ&! `6hbBS4m9s8- ["cmnM41M5VPحZ6cm)SUd,Xih&$Ԓ$%PFFZU%dՃ31Y+&-#)5Fjd&L-*RY"lC*c+cR96ʩ,YK1mİPJVea*cRL1*l6B 6 XVV-mh6˦֪dJG`m&lUUZܹ.\ 2wnJj+FŊ,QbVdi3j+JXXdlVlUJ%APmT[Fƭhlj1Z(13jJYmccXZ4I`6%&e+(2k&)Ẍ́R#,~|B!BD!B! ff0!3333"30Bf!K30!3333,ff̳3 B3332p&ffffffdBff3333332!33 s9s9Z1c1Vc1cZ9s9fffeff30&fffeL333333333332&faL30!3333.TBff3333332̳33333333333Bf&fffffa33Bffffff30&fffffa33BffffEUpmUWj 6ګ&fffffffffffffffffffffffffffffffffffffffffffmUWUn*1c1cUac1c[w]B333330ffͪ6ګj 6ګ&fffffffffffffffffffffffffffmUW\0m@d0m@d0m@d0m@d "D.DLa"D.D\ws^`+mIBJP$/svBW;(BIB*LcbDjPI%I(BIBJPI(BIBnݡtPI(BIB$D.DLa"D.DLa"D` \6 Eȉl2D` \6 Eȼ㻞 %U*UJAA(ҒH")!L MBk5 i$H6j-*6j-*iAeR CIel4&Ji,e)f`fT20)Ā &  @IA(V "2`hYjߝtC0 4Sk I$I$ $I&#$I$ii&`$ f5I VjVo[[|QmrjUlgڿL8|H l:g_oо֗I>ʪz%EcdimDIzFm::?ߎӾ|F6oo׼xxxxxxxxo <<<<< mK5u͘vNqJ?4p|ުMqVM)}m=휷lud(u'}0[3{<R/uóv/^UUUU[wq8m-(ݔW5EZ^$-J) ${߿ zH_l///>}ϯ~Sq4yF"\({|/ϒq|i[>m~~8DDDDF1"DSkOQ'lxi^.n~R/m5#?Z]uZ?!Ŷ.k0sڨ~UUUUZUaUUU[je3mV0~~__.7xmЦ.i!-%pQ*҈"D?FۃbI;I-l\qco[mYZrZhB[hkS& }%mm2\I$VppO߻ϾD&H>UTDX1{);rӺIlN[KF׍.mm8j\ۭߓn5rI}{mtdMƽj䒫k %WpK\E[B^(@/fnH+R{7{C6QEH![h7m5&V =.wCq]{#K>i =.wAP^˔Q Um{{7{C6QEH![h7m5&V &V B,WApAi 28P; 28P;BQdCV MpI†m{Y. k%O^:["%:rm?^5x. [`fX7$Uq$;-mƒqx, 8+. IJqmUmmYp (f*.9hgowwpƹE_z߭*.9hfiFi=+%gaܰ: _o.z—{ʹӺ6rg^fٛB1fٛd,RHBB$)$!I#ZۚƮ~>|<<̝(qc[l}_ H H Y(*8X1%+LFX$cId+*FI C 3&f$fH!4i#I6iHHLHi "HlH$$LY03L"!,̌aa)$dL 8$*qbc*q YbqIdq "II$"3r7ˆ,\8)aC0fUqYG*Dp3s6ۄ꣝UxxzTs G;gz<=Tr]R hB:]$rwY 딷HHdD]\-kmVE(E(E(E*䵵jՈrvڵjRRQ#Nj".EܝqNj".EܝNm:,4wWJX4#l1MTLLme[4F1Lʖm69(*K.E\56R'(rff`Y##W2;FQj6ѵ6#Z[B䙚R&Օ$ "MN94veٮ\U 8lI4`"6-תXۍ*!a"M"6֍Y" 6B KnjitIgUsSmBwtOUnƢ3$"nڛYenJ͍nm-RȜٳj kU3$a[+fJhUVFRmK6h%,pcb447)6VǜfYFӉ;aci3x7ܓiSpa*epA͝X 9lV܅3f9S: 6lrba+4fP6Λd-6 U*ɛ$ [ iҕV$*BzBUKPU?H mTLRbąXX…,(R(((/>>kcii<<25W_~{I׽qڨbҍX(>_;HR[l/lG'"qd{ڈs﻽ %I(BJP$(B6Pl6N˗>>^yxC<X??  H @$ @$H$ H H@"ܐ$q H H"#wm CY s^#nv-UWe@mKBMm97qd;8&1DE*ڙW+iKD H H$ H=k\j[!ln7ik/ի1m*bQkchQUm Z6؋DTEhhm mk%Ւi$1i fI@IlIH1!-XZ*dXѫchmFEX[bS-5 ڲYM $I$Mh6fHAd$SjfVCa-EQ[+-FѱbѓiMʬf$̩M!#d$& 1,Z S֌Qֈ١6"Զ1؊5M%kbM& F&$i3dd"IiK%m%mm6lXHFVЙ̦TFB$ mE6XѭX6Zm[Vf$dV,ɘ+VeLa)ijٴhʆ-hŶ6j"FIm4H&4[M66T6j R̐i b+m+RK12;[ia, SE))&+(FIDi"I2A$$I"m%,L1hC!!12B3B  !0,Z3$8BlhA 7TI c2fIh3,$X͸F 4YTI I$D56Q#I!mERI$,hFۑ"&f%KE2b2b2ZMk\$10qâI$j4jZI&"2mۮX7m[륃vջۮX7m[륃vջۮX7m[/Wc/Wc/[m[c륃vջ{ޛV<{ޛV9ۮX7U{}$ % ]u %I(_}}},uj],I`ݻۮX7m[륃vջۮv{(@A0@@ P@$02P@ H  H0$ A P%$ @ `>qJP ̀"LDA,1h" a  1 Hc` Hj5 J H H 4A@SP3@$ X, *UT[m[kqq|^E^Eyyyyy_wV.& ˉ5߸ۿs`R]|$KrI7I$[~)$Qd#$@Ɠg~뮗Ep9n7F (9qnW<9qoN7qN7[z]uǪ5@6j~^B!O֞wݯz|O4cyO4E+sp[_xxxxxxxxxxxxxxxxxxxxxxz-JJKmq8piz ziz8$4yV7&ʲr{hN윆>$qIyqH]hFL"Z]j9"!B;ݥn{.!1 dmY%$m7kFܑ5X11.+J*y$6W$b[fޑ$UccAg(BdKB6ͽ#oMV;%m{U{.!1 inI%IREKHے>{U{.$#U$bXbb㚭(BdKKl>TUmzFtMV;%af!1bD ,a6I5XٷmId1 3H!2U%!fޑI&6I5X11q&Jq#l6I$cNm!Fm~C!Lc8;HokxFt,ָתP c1q \BX5c|QzNIm+K"gBJliD#m+J[zF4+. Qf!&B*|QVޑM&KmߚE56EnOp>/Dǽ[lHXg(RAB$d_#=n*^U+S<뮾y =ex*6x1O)HB=Fz׻sjpwnI,2I`K X0d$ $`%d{̒X()$AwZ~UP|eTLxUUTQEʡ`je_oRc)SJ1=JBkn[!d $$ IAPAK X0d`II,2I`A}jֵϟ>|""@$ @$ %.9ΐHa$HfkHXZmkm6$6ֶZ$Ila$?W{hI#teUtIwwwp{snUƎ4Vr3Բ!1bBJ%ysӽ H HH#ۋ]F֝HۭZ/{iGR)1Z鵷\$I$H B {vI%/$$#^=XTJAe!1$R&ww wgsZmk`k[ml@$I 6Bd0f(+$k5$/o@ԫ c|UUH0)SX6b(#[chѴқ0+m40fXQ$'v:F݀7Uh /Mt;wN (* }*h_ARww:Q!N^o|7Rhh0F *Rz`&JTP($zi!TI23 @6TԔ UW5gtkwFyķ BJm6=RI$`{jŢTciSe*j )Ruo<@ )!k]n-gZV°ZRшPWn3pM-6Sia[(m򭪶YcDz+mԨ$;s8YI#n0oApbm:bRm-l`ƭԶcm][";2+2YJI4ꚸhI%n(DVT"iYPl㐴X+IcsjhY5nb¶Q-Z*[i-bR̙nLð*lUnmB2Ii),Y*Kc4Y,RE)#p6!4ڣZ]ZЦ$f,)Jjl5e!0-&HkRY,PԲXZ'T"HZD6u I HD K6ڳxJ앛7m۠*SMLV6QFՌ2[ԭn[J ,e-*Wlԥ)c5die+F m(%YFYh5i&bf"dvqIf;oIkf1ɠ֤6ŌjmS VYl[%mkmmD",maneݹSְqΖؙ)}j5[kcz6 mn !o׃UWSEEEEr::tt1ʪ,Ԩ*Rʀ! B, Hd -Z嶸[R ښ4hj*>"`!@Cma"hXH R H kAjTi [ms[srrUUUUWy'7wuUUUUW{33^PB8B91ީL2KrTU]۶l2wȹ=-n` Orlx[syϱt3>KP2u+d$>m53ənLrf[UUUUU$fXYz^Qz^F}JbM"hN1lr&*襖UIXQyUU_q>y@IY-emRI.|~X6:L[m3mUUUْϛ{NO9~nCۡo=x6w{kc=Ġ+[wYQUUVoݙko MpY;[mUUUUUUUUUU_ij&!H @{)MMos3326I }1' 7[_{;CM{+ږM]^M9EUVEݙwCΆf}C"fd@;'[wr{m>ɾvYwQ'͙mmm#Y2i^_UW>Y;kc )!B$0tvܙ2&@bZvw(bGUU`C2I$I$.0)WPxS p{ۃ#ހ'wws0Qp9ۙ\'pw]Η7cm-伛X{ٿwޫf=G{pzK c~j wHBM_qǏ=/a:ٔwMۃ^A% >ggyOO{46I-o1oN7{m{UP>[׿{c>~9B3a:۽jpt뽣齹A% xPb A*,!PoO=~oiHNm]lӛv;A% >[v{zk=p!2mZ c#;:n۾ު-U!ǟk>Vqz/{46I-o1oN6y6$xC )ƧIk|1ɛ{G[Ϳ#{~ȏ>|+%a=m[R]끖P0m-+A >fgZʠ|IKH Ze"K-T h*jDW"U0`#RR}R^ xL3Dh#"D$ʙa"ULJclbZ53MmڛDҖѴ, SF1*L4--$Tf&#Fc%YFk6D6lb2x*kY3HJ+mZZSb16 i (*cgu}_Wol64mwyfSKvrZ5ofg.3z-X`i<Hۼy@$ $ $~©׿C^wL~o}w )lWGl $vK6l-Ym$ @$ @$ @%T6(؆I<{}}$4}= HP7{KJ92d @$ @& H3l ?o6~_~֫ܳ1 ޯww)Jm/^5JS6t0i B#rHIH H H#m1$DDDDDIDDDDDD$DDDDDIDDDDDDdDDDDDIDDDDDD-kR"""""$""""""H"""""%"""""""""""""""""""""""""""""&"""""""""""""""""""&kc{V!{ީyi0me-uKzɶޯǯY䆌Kmu3M4cjMChNj7ݒ8.#@.wd $ wHwd $ U~ ?{߯(!`4#FA cmLKm0%PPvW<3 ڐ{ M!iP7}#vHn HvH໲Gݒ8]@.wd%BgoUmܴmƁ-z5Li4Hh1i{^﷩DID$QQ @!mٛ{}>>?~?j*)B,5wmwwHt# TRTR"!)h*DR$ 61З4f~Qh#Kd,;ުUU\ʠ^UvIm RJRJ*TRqQJQJY}Ϫ1W]u֛vۻiii%RmmjX\VVݯwv=oM46ݵ,.W]imm`oYZޝJ&SJE2BI ~"""#DD@Ƙ& ,k{԰]ul[m{! 'S_%k|SQLދDCHC2A{""Pk>ӽxxl6l"*/@ 2h.ۀ)#@4(4 k)PA"HDU(%JE$ " Q@TRJPh EH@UD(TDEQI$*>ab َs\p^瀶mZðp 4AJ P ^(UmV j<:@+6^ҕAbyRJTST'IQ4 )4IR*jIU4~ε=k^z:5s::ױѮgtkwFѮg;^kwFθz=y35^FѮgtkwFθ{Ѯgtk{:FѮgtk눕w\vuivvֽcn]cbڮ]bcn]bbbbcf\v35s=qZ333wZ[Uf*f6f*f*f*f*f6oukލs;\3e1S1S1u35shTfLLl]L&*LTFcMKL&*LTFcMJ4d#F4Ms6ÜMs6ÜMs6\W9\据lsF69kѵ͞rI4msc6\w++xx据lsF68s<sF69kѵ͎h4msgܮp\据lsF6z'<ѵ͎hY[: 9%ܮp[]$pmF^'<ѵ͎h4msgܮpy׬I4msc6\w+6 Y9K'4Zdppuѫ[Qm*,VM-,Z,e5k&j-,Z-Eih12hF-hDZ"eAmh12cQ[شZ*,Z+cm*,mɨlm JJC%VZ,X̊JT&IěVVeefVhѭ-6 0 IZ,F"D,H)AJJm1mFc`ڍBlFcmJXщ*6mmTċDZ"FIdƣkX+MK Mb[FkъmIQb-RZ"5$%lVVVdѭ5Fh3` `͈ڒ"%Z fͭFF*-YM±YZ6YMm2ʌFhQh ͔)(efQ-efY2*miIK6,LԬ1AfZ-hsQwC3GHRssu:j#Qj5t;uFDtkwFD;)&*fk[;9Ū;۪6wb]݉61Ul$"Em4l֙Ҥ&ɢMDmY4I"LM H$J$ kF 5F$*mF̱"5Q[`ʍKIYIM$T"bX&%PbbUY-(4č-&+ji#m`LI`54bKR@V*$jlY(e!! ,i2҉fejljK)[hm2iUFڱ֦mdR&KfI[3ZQ"[m,5feEӱ'**uʻCZЉ35s0vSZLTuAj462bYFɢM2))Q"e,,lV J$LM H$J$LIJmm1؊&Tl[2؍ʍm&el֔HH&%+6IiD%jm+ImԦ[j4bK-X$ŒA--ٱ%$J$Di3IFĔmIi6֌F-ڣ-kL4Ȓ,-F)҄dƶUt:] mWwfbQhb4l F lEZZl,يf+m©52X1XCIʲ[3i3iVfJ%Mj1V0fͣialMe SVX`1VYl+dC#FQ( 5Dc+fY m13CAJ7B5 FB֦jQ F3=i%,Ro жy"ƴbZmMbCB#zV1DX֌[QhSҍЄ! oXcZSVlb,Vb-mP͵P>vSimA,+j a[PKJ12LI4ڈZ-IML=(!77 `f5jэF*cbڛo6B pC0jg٪bf&Z5,[b"ŬZ[І̅+U-$D-a&I)}o]ʻuZ"6ڵf-,VŶVP84 ;eem+IS ScEo5792k%AMAMAMlV(dj6Kb-\[64kfS")&ZYGqM`zm[VI"ĒE3dR2[XūXժUh4ѲSPxB!m ٖ2&aJ"Q%$iزF؛k)lcU-V4chŴmY[6G8HgiKmͼhDqfD^v`F;;ۊͳ&+Is1fumU+AB@ڍAF$lPg\ZEr̡թ+[j5chu"#TȢV[)e0EhIdQVbc-MY#Yl,dXD}r$Z2!l%-I!I$RКHk2!l%-I!I$R̓ ZͯM2\c,&T JYJ ̱0$! -J W.h%"6%d,hSd+- mXlr(#DE*JITk3Wmե$$$I%Vn(K&9ݝٶg)Ve3QIXk2#kkHn[w;дPZXXT%h3 1,0*K!b V-cjhڊ(FXhEcm[XMbfUfݘjƥMm;Mم]&4eVJHu-$W AlȈȢT4&fLXȳh E2ѭ %"C k^(ysUa6I6Fi5̖K$ia ڶDmdmrB4Xe5mh+r3tچ+X,vDܤ@,9næ+mԆ5j֊+:S45 UŨ LDbQ!a&rmlq%6hU54XѪfY+KRbƑ,DTlXX1ɉ6,(F6F1ت**%RFRBlbL@cj3 *m-E-V6L,i(VسM &baF"c4Z+rXIj&F6,d(6B@`_boETbjbcP5ͷ*$`*5jRMf*/]hJ-{9 ٦i1c1c1c1c1c1ciiiդ! Y%HBK}yV%d뢭!J{cwuÇ@^4L1c1c1c1c1c1c1c1cۯEZB[{Ϯ!+$EZwK|{Ϯ!+$EZwK}yVĬ뢭!J-VĬ{}tUww[1c1c1c1c1c1c1c1aiׇ{yV%d뢭!J-EZB[{Ϯzo1c1c1c1c1c3vݷmvݷ~J;(CwN:DtUwq+$]hJ-RwtӤ{޺*;[{Ϯiik1c1c1c1ckv]@)B_+]iBVIo>*{}tU! Y%HBE\xUUUUUUUUUlxҜxҼ?q$>Í#h8/۸qJ"Cw8nI&ؒMWؒMm$&6Q0[)tsE`M}ۛ>kaܽzP7*L!V99Yt.|,Iz,Oeˋ#g-dvrn)zƪFG=ݸg?g7P)* P̭뻮!B ?ZYDNƌ}~Xve<}y}=]*}j<{ y\U`0%ES H/ #۽5{->L"v[tI93&#LFr='n-=[wv- x^j93Ɉ<293-Oz[9هsg}T{^/Wv`~Kmz6oͤ~x&c?6oϟwN7i꣤t]W}ѸLifw}wEʯ\rr2f~3jUuL7[ۗGՕefon0egL;ݴ9gfUtbS#n)ɧnBSwwD}eQ}yrQo2H)ÃN7ɦsLqqr_ lX4%> ?;LiLw8(>;fq;8;38;8)ÊIpgxs0!;38@}32?l⛜8moc c"j蹍\`#=3=dMs\ :.owtc=3p_pvϮL7\rs2陦(Yi{nZ≮?"Ye߶f6ޏ~otѷxmg.21^=ݴ9$bO>lUdmdL;&ۻ:) gFe`_^{v!<'cGнmy^W={콱{B' f?߸;w=-&23y^4Ɇ@ɇ[bQ,im/@h =u+neJ4={n+ff&u^훴Ine[m0 {}m mes;7˕UTFo+m3w!z@Jm4MMN=ېs3[co[u%m˙%f޶lݢV嶉[333s26hl.fklmov%n[h[ۙ@m̹@B3Nζ6IٝسBBBB@}R7C-7e;9rt6;1\U*ojF܍R6 ǘV 7DpqgIUUAC@}w{<`fs1=UWE{"d)) Gw}nq jMZ[zGݻn۷7n@ (lBP Cbpc1v6P CbJ (^(6!@( @%/pP CbK/@% Iy ˗/[mݻvmGss0gj )J9٬!czoMm_}6@$IlI$HK`I`$_03#1YbѦ&#k&-iKdZ2bdF6ɋYk3,+3b5& ,Tbak3lZffYu 'N,: 5un iHi)w":ĉK#X-F,MZf͕(VSK2[ib[JmB JdmISlʖ5 M-!J2K+A+ JmRf6*hb*"T56JSѬF44JjfLa(-VHXƭAj$)(Vf5dEFŰ5kIcEe ֍M[6d*6lŬIʛlmFѶ+QdSRLlLI5(l)kfdM%-J k,FV(J2XMsQj.554DimL%I[Khkl+ ڳj(E",B $**(RNFPk]ehڠ ڤQUR6ͤmC)&,ٜ3CYB4EK+jI%RYXcnja5 X"iiE%Y($[m,[L$ДU1V"S8b TbbsHm&Ii$Dl:g7jklcn5rܵ6&XR5dH%LԨm&d'r[ɍA[3bE6΅VE1Dffjف ٱͳac03L`QXPDQ$EP͛͛66L'OT5DK {ww}&Y=g[ʯ>K"YWRvJ P v]m5nʯʨzKpws{~Wwl %F!(B6P#eF˄!!(B6Pl_窻]t?رbXc46&loln3 kl66͌3  TDB mH&m&2D4i4`HFHl1ZIh͆eeejl l1m,77haF"2!6&dM&2!`i3m̈́C!"#f,hHfdh̍dž;"Љ!P쵘ZX iX" ,"H!9Mm6 (C@6&-&2f@hI,f[B[i4LD2e6BVbBQ!Ae!2ci!26 Ed,ѓSQfamɒmdLbA!#h[ih lh-MIllx͙Lͪ&EDU&Q)6ֱbm"e6QQѩ%+#QZZa Mk`DaUTmE0ٽͱ[t4U}${zks;U K&K%UG=5܀LiOdl6p l `/㮺UUUUTUUUUUUU@UTmmSKU@ C;`O{{ܪQ(JMk*(Yͧx{qχ>Efcg6l¥R&(T@@TMPIꒊU hBJR4Ѡ*jIUG#: +35t-yNLkS)TPHw:#75wFѮf*YMwZ336f6ZiLeZZ"VYMwZAkVmqђ4dK26dˇ-5)2l“&°Mitj5v]{:FѮgtk׽wEs;\U$dI" \F69k=WRQY[=mx]nt:'uNw+5m{{;^kwFθw 8hŵyz"2$H.:+w[$Lg&YL)i"DG$.pup%R+DFتa|h4msc9K4msc6\据lsF6=ntp6\据lz.4msc5sc6捯[ݮF69kѵ͏[]%laiJZ\ZR0cK,X""6#b"12cc( KfiDI6PId&Kc5MDIJF$DH5aLj3fi16KVZ,U&&X hĖ hX cF$jѶ$k"HHHHHK ն+3V6I,ZL$J$EJPV1[&f Vɤ4iM&5YMflZQ"i̓Iijmj3VّlJAiDm5m514bC6lKfmV+Q;۪5Z;۪6ѫk[s\ @JJHtI֍lkF5mGM$ h63uV cILja KKc2c+lVjQefSb[faK0:* (Pʹ¶ʹ֥[4bvcvbڱTcmhݵhmͬ[Fkmm餓[4r*FNEb4mtZK&@EprJ՛l ٘RЃJ#H҂i3Y6e6Th-kQmm $UkXdfiB"KmFZRef56ѫXѭiR&HK J$IlZN퍝t&݉·uU5wFѮf4gvfŶm1Zklj-U5QQB&j1"Ysr餓MfQBãDr%n$;riݕN쭜JJZsMӇ]9[6sV15VA[((&MM(Jѱhգi5k2))Fm%&5fj1-BflZ6ƴmbP̭dI5bS%M%,%e"IfYZ-ՌFZX4Z-A5PhՐ!64ȤDّIIm-* *cg42mX,K-%LieL+Hɖ2al֌mYa VeijcmCM5e6eD0F"lmRmkḧY*2jf֌kl&#(`xlB7E7!h&J6HIRk)B)Ijf l ̙ Ҥ-B-SIr dEE UJ&0SbRZJU("! tvv,H+jgҊS> 8˶ڳ#7AD\ܚZIJN[fIi6J7""! JV$QؤHbd)efScl!DXJmD"[ce+m+f󃃛8BlV|TVYVFѬ[EjRy3$i 6bM#HV+4#Di"fMm#$Hss"I$ʅ!I,G&)j[I&2mAM4m"L#MDDad3#LHHk!UP9mYLjm[6K)M3(V)C)dBЦITLjfm,Z՚dض2clj)1QI-( I(5$jSKVZjQkFƭ  `Z%ۖ7kFwq% m @k$dJí:uCf"jkm ̙ a%aa[ljͅlX[PhjבkfcfJ6VIFFhѭZkQbƳ7[bb66+6)XĨıQlٷ]67 R!"wd{i(b w{ P$@{y{H!J xFx\{4L1c1c1c1c1c1c1c1c|إ BD{!P$@إ BD{!P$@إ BD>H7CXR-s,XR-s,.s@e\ B w2c)5  m߿z6d""]2e50v\ֵwflqf8LDGggn88v:1kem[j wnqĵ[hj4MhUf:M|UUUUU{{FA)JR<@{}bmI$.*nnYow-Ϫ_ @{y~u| 9doU a&2͟  UUUUUU}yUUUUUUUUUUVmm=~AE}ܝ\7@3Z ַt9TN.3{Qs5wqu4=f}UDꕻ}E}iY[qP~wsẹ1 !k?YӷmzcfQ,cMvˑ=I+# >Cʅm{N{򪪪{@ ,q,i*q $q%;%dC޼/`oUI$N ~IR)lAu~?(wϹh$N$0G]{>I$>}>;߿**;0`Cߡ[ѝۚkN> %ǘn`@} yw{{q>ى).ʷ[ʪ;2Jk&oQ}ܾ})Yʪ={ʪ?ke}c=9 Sܝyk)FВd&2`scI$O;s na> pmgn~=͗m nselc816}02pI6}x6ԕW1)(2kr^1$(cLGڭI$DpFDEDķou[]tJ1*Xm[N%[k $mmbI%[o&>[rI'DĮۜfVgqNG iq踽ɸtq}z\yͳIQÅq$a}+`{mbU|'%+JmI*]\ĒJM>|N&]%9:̺J%[km6-'IzJĒ{Jj1$O-$bWIymN+m{T\ħ`6>%bbICP%a\I(A#EDm2+ؕmbU|'%+JmI*]\ĒJM>|N&]%9:̺J%[km6-'IzJĒ{Jj1$O-$bWIymN.wIm,pQ±o%$nxޑ%Ԗo!3&Rp!u]ˊW+s8f%5ŸO;{cRWIXmi8APEpI 9{=mjJĞ8pc^o6-ĒyE1+6۴I 00,#?#;='`: tMʹ].Ƕo*)<#mD H"&+Y-/[k8k8k8k8k8k8=o؈""""""$"""""""H""""""$"""""""HjDDDDDDD$DDDDDDIDDDDDDD$DDI-dDDDDDDM"""""""""""""""""""""""""""""""""""H"""""""""" ($F3=t~0b_}:Ăy[RATf{Z*P %]ܾNWܐAԭ$īU|u_{{\ǃ_knW:KnԇZ٭J3YK(f(f,:jQjQj k5 k5 i]wrNJ3Wwv~?O~wT:CY҅:CY5!S5CY҅8N(S9~NfjG3R9HjG3Ps54b98f3 03 Șfafݺ0s53Rs53SF*s53Ps5y5CYu5W\3w;]a 13S?sp\7Uų;Ӹ5m򪪾;{ǻy򪪢-rβ5ʫz-^KlP) qBP) qBPs+3+Ǣ6o{DtsRb94;:iý!ǧឮxǏ;(!"#"[*%I9999b98fy ;Rf3nja=ݡ^Ϥ OG(1dMKWfafaf03 7nY~ o{ΪBlp|q/z{HCOJ!%.[":afafH{ΠdwU^g7M4c׽wHB(0R&%jtIW\CYuu5W]03 7)܀3/  = \09xm@ XUFIRB6EkTRTU(iJ((RHA@ PJdU 3 @U("Qu|@C@DOr;5_njo_G+AJ P&%yRY[Kl#:SQSg4%TՒQ310zIk[F,Bd̰yFhncKVU%+k K5im+ #11+DczVuUrfmьgĭC$e dRia饁M1֦!&)[ 2͒i,\(kѭVe6ԭ$͸fufٶX#lI &F |6Fč3ěxrn9'7HI!ɸV+i!$rmHLf7m9fsh cdɲl, iYѭC90MI$2BF&B A iZm)m !1$"Fёd f5VUXei#12YLj2*-XXŢTi`c$Z )1,j+i*ZP-(0"H̓lKV2BH #B)B)ZY(SVűصFLSU%2FĔFIF%mFlEb6S]vqw cnqwq-Gu/:F]AS[W8:5^ukލp1('N]eܜv wCMT6&,i1I%0JU^ZɚT3H26m51V("Zƨ.t SDwP\wC#0F)U)A(T b*bۅA+Tŷ PeeŒ+` `:uwslsflkkwv Wwn˵fCgfI/cb-rƋ ]U^o! &D[j5l+5iglL镚cp8n8g"=2Xɤm)H0KX&KX 11QK(Elɴ 5QEڢdh(ѱl4k%YVR؄JV+5451jEbƱEl*օHjZYVDȚ nĘր5jҲE&(F ጘ ʪh[38ddFh ]SW* *Aac`5 V@"#FT%-m hiX2dQlʭ 4l)Vcdԕ%h"E6ƢشTmbQ&@DK)ekZmK--f+_ J-)J@dskuBIY{ּw9s\)\)\-Å\-!f T!QH[Tî뻥w]i-{KRTu.I(N q#$ӭ[GUċKKmM)FSQL 4H 2PnJh mMcX""lT1ĉ$durH(I-3I&3R(i6Z.mw mMDR[!-tJlչ$DhT\5ۂ*R֋YYDjk[&D1mq"m&4djIz.qEޫxm匐y6R6c;22+m mC*[D͡p mm[<'I)tja( `d6\^cy7ׄD&wW Cl\PQ3EjVx9Җx'Z6im[h!εpЍI&,ZZI#~jଃ++ iY6[%ɴckXF%щ4Z1&Kel%mj,AZbزT1&i5&֍FƱ(1`ZlhьD*KDMԚk1bc ʣ5V1F11MFU#61Zى1,eQh++-AlljUli$ڭ5QmThdJ kDZX QXE4L1c1c11c1cc1c(1c1Qc1c1Dc1F1c1bc1cŭF1c1bc1c1c11c1cc1c-X1c1Qc1c1c1F1c1bc1c1c11c1j1c1bc1c1c11c1c1c11c1cc1c(1c1Qc1c1c1F1c1bc1c1c1Zc1c1c11c1cc1c(1c1c1c#1c1c1c1c1c1c1c1c1c1Q*Ja*Ja*c1c1c1c1c1c1c1c1c1*Ja*c1c1c1c1c1c1*Ja*Mac1c1c1c1c1cīa*J1c1c1c1c1c1c1c1c1bVUl%[ VUl%[ V1c1c1c1c1c1c1c1c1VUl%[ ^搄%!((bP R@(lJx B (m@+$+HBP BR%!( 4I{J% (i6@P ؔ BR%!(! @/?wN=Vjьa(m5](m0AؔUؔrF1ZvĠZvĠK,5a(m5a(m5a(m5a(m/q QT:0U^c @+lqI#XVIhn&1I+ьa(d6m(bvm d҅껽I(^yץ6жZ&m eBi6ВK,tьa(mVh#UVnQc @+l@+lQ@+l*cJ[eWlJ[eWlJ[ḍXVjXVjXVjXVjXVIoK%m@4@B l$ HH0`hT$0`hU HH@@`R$ $ CB f` m- @e2LTLEJR!ʵ2ȊdDDDmRAiV$0%V̘EblMmm#M4kA[YX6meel֕ [km|CF*-bKнOE݆5JvkDC hvkDB}Z"vӻ5"!݆DD?X$}I=I/k_Fg¿f:.QcW{ݑȣ[2"1,jrFnns}9"Lj|{z5u , ;XeFO'}HS`< l`}3ܝ ~!B!6i;4DtgnJ"eŹ!UPnFܶt/Kz ?{uun*={ʪ::k=Jh4:173ZN=k@BG] |+z·ӣs5N=k$ޜlq-gWCb\m ԏ{Gn{}WD>ZoO, t\1e߾ {E04c}31g}Dw=c4ۍwW0""}k8[ykOч\wW/k;tfeUe^ ˇvܴ~8c$|#᧭l8=޸7I{vMv_<#xVrwwpwwpxZZBPk_.? =0X`c(0H1&`LCx1AD` `0"_ǂק+}9wӺw[:d>򪪪mlsM{'Oߴ_jw鶯G=[s٘l^3[fgCd{/XXX)<+pva\qRGQD҇!&[F!0΋QE T!ofg0BlM}Ӻ0@ oy~3 2 ONvI*~[YY"تV˞~_уq};`u4I z~N8}$&򪪪~m&f7kݱ+rbV`7P$@4 lJܶؕ3373 RnmE(j el3 fUUUj(%DMD(m 9ig*TJ%DBMUUQEQofb9r˔aUX 4!FL3 /Vݺ{wtVVrI$I$ (  >wr$I3#RMn׻bVc{$CMlJיoUM׻b$ts.gsL-$(I-o;aQEݶI&v`peVn @TnI$RI=$!-  ǻI$zb{O}>#1c~'tw}**x~=TUU]8U}V((9d OЊ`(*mI$};&)U9<>"/mRm29;215_o]$5#4ַz&((0zQ CI$wM5ynfF7 OwwaUM~mv ̀(^ slyݙ)xdrwfdcr }wv~MUTglU6Ǚٙ܂.dI21*UUUQEQD ֞d (*mI$s5xdrwfdcq~&Ȫlm ̀(^ slyݙ)xdrwfdcq~&Ȫlm ̀(^ slyݙ)xnI8nomv]$I#m'Qm VUZj@{.FےNvmdw$쑩}-\((6z 5UQWj-I$WdKnB ZZU*U{B[gnۯ0lI9H Uh*UQEQE'BQMl4aRܵB[$`u_vm/w]ݓ -o%Wݠ rjժ(  5*U{B/w]ݓ -o%Wݠļ/ǽ=(BQiizZ@({~=w:AYz s|~P/UUJZj-Z8y(,BԵ{Wwwwwy)aWq::qJBRNNt(!@.(b^R(!@(! @%Є.KЄ.@%!P?[NXuèyy$SM4M7rLEYtVz28c1!;nFTUUTtj:imm$H ! @l@i,K`Iۻ_= $A,WI@pDQ,#n2/~Wiuz}ʪ_Ӭt,xyT[Єg1ZǼ"[U]jM&mi6Ӳ6P$b6PlbIBlBI#d$!$ % ]]_}w$eI^P Q!UTQ"2?>=3阐"IRU/oݏ29$s;{ iǏO>J&n%&Jmzׯ^wcv6Xta!Ǐ88Кtӣ#*p} @$I$H @$BĐؒU]~""""H""""""$"""""""H""""""$"""""""UDDDDDDD$DDDDDDI"""""""H""""""$"""""""HU$DDDDDDIDDDDDDDR""""""$"""""""H""""""$"""""""H""""""%Z$DDDDDDIDDDDDDD$DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDֶa>z} IU(QK*l՗6Ej:NYԪ("` I-%G#l-B3ьci-nM}-|R馗mG$v8prKclv9/{qÍ rN6rKIpI:'* XQ~(W(o{ngowcلفAٔ1t]综/n=yTЄg3z=ʯ|%lJx B (m@/HB]% (! ؤ! @(!J@)BP $!X>KemC`@$$HlMkmI k[lIĐ !`ĐHa$Hg@$C ! !HbHa 6BĐ !I ֶ !$@"DH[lI$H @$I I !aCw{u^WY+U3i*"}{ʪ4SdQSdUUULÅMvmmsAPdv{sn'i Ӎ_].c4) xI$L]H H HD~6FyuY-{ʪdfgΩǎ88 4)w7;Zh @$I$H0Đ d3+ d+J%&EyU {,i Ǐp R*@}ʾzMc}]=s7|>!B!*Th )RQT=@44U"hIQS  "J <M52z@ڀ:R(L*5Ef*f*f*f*f6f L333-1kS1S1S1S1LLKLa1Rb4mjYI( -46FѰѴl6FѰh6 Ff`h4maI0h4m`Ѵl6FѰh645F$FѰh6 Ff`%h6 FhlLطݜrJJCήϷkYּr+=kΥ!θ3;L:㴸s;\"U26 ͦ6M7`֦`pѝ4gw FwpјdƱFJMk$dIIwxѵ͎ilj#{zڼI Jtp[]%Iwu]ntpRJJZ2riݕM$Htw]wum6ommEFŋEhصbŚZ66ڋEbՍ-cHFmeAe JiR)R4TX h6ƴmmhF%i-cEE֍ZԖkFɨFщʍ6Kj5j-"[im!%$2L%ZQ"ifC)Vfجj*1j5lcYMFcU)YM4c[R6E-XF--4m#IkE[Eb[EEV&[EEj-Fh֍ѣm@EA@FDQRbe Ƥ5lBj-HD$Y5eHHHHKm(+lP…mb1QfT j MV j%FUhhDYJe)P5EEh֍%%)B)(U ѣZ4kFhmKE ŭQUD&&hIJKFѵF66LQ"%&I,j5cִ`F6QڲYImRFV6уm6գZEf4+aL )lKKm46(lU5Jce65l̦+fH1# X)flYL̬Vda-P+6V`KZB&XZ0VYj36*cZlcc14ie%ZQ"Ț$MmM H$J$FXkTV1m-kFB&h-Ej"eTͶbV*6-dLJ1&%l%&im emJ+d$5&ͪHZԓPƖkJ$Y2Z[%J6IHƒaTl+le6)djae4JblRԭcXZQ"mi6lkJ$IKXj5QHD(JBd"iQڤ"iƣ&3X1462bYأd&EeKk2҉BYIfiDIiDXIQZуkj5kF-bM l[ZFٖ*5-h12cm֍$Y$lʹHbXH6P6V)c0ִihhĖ-d)dEd-(L+f̭M!"i HDmfZ*ՊCUk64ȤL45$JM*Sl6޵X`* j 2*C ٍ* ٶуlڲ Vh`1Z͕meZ[eZmcm E)ڰF F E"5)%6)-k3EA3Vb6ɬ1V6,FZ FC$ m6s fh`VɡԚWp󱒰%P%]DD՚o7a3AA"F,ި2XVR"VBB7[Z颬V4V1EVRD %-mJkF$щ(d @sыdV+L@+2B,U)*إለȆҳRf hڱhŲhŬA`66JjLRx" Bb(ǥmxnShifm4ARSSlR6d-S[bǥfѣ|798FDt͸b"ɰLɡJhXMh5`66EEW+EcTkFejحal1i>,hIK[aJuftQom 4DDDM$#BmȈdB2̛#> }rUUUUWǽ{z'{;v1o[mI8wp?ۇw;]}{߿glGߛUuTU |{^`$*{yz![f`Ơc>}rI3Mܱlh00< @EOtZ/vƚg0;kûzUNNOAnA7jl|Yu::o.Rw^ignUUUU|{UUUU|C{7O3sun<05nuypNfx//9ժ=UUU9s{ވiJi#vI@$IsI!Ϯ~~vi_pzz[x||}nS=}vʪ8;vʪ}ᏛnoMy$my$!'c^Ṛyיxr1yk)'naJx)ь}ȓhyxLf" o}׾H.`R~I$I$$h(L軦`w2ҌJ(9 ߧ%]v۠Y'ly 6 wu B-tJyfr-Cg:oًG}3lћ鋾Rz\nY:⪪~S׺ۢ-:N^n}ӻwn繛*mmtmow%R[.|KۘI$F$I$mۻm{mmUUWlUUUUUUUUUUUUUUUW[zԶ%+ތt>ӽixZ[N`^OI_>^^|Znk{Kez5R&ú*mwQE7#q˕IUU{\y#_**}!$I$@w;T% |kmMk$Oo}zUmgrL Ši4Qi4Ai4J 8i/Zo2m8~*tfEFI'eUtIJws$Kw%a&J zX˛m5% 6rah%QI DmsQGuDmnީuK%.ۉ3'E.GgI$6dS &mzukFQZBhUTsߧ{yv):[mξ;ü۾$mc}<+mDqdʫ㉳=Ԛdk5II&Y$7n۽w[i)M) B,IM6iK%!޻ݻfئY1iB_  & ̙((&;lba͏PQTQTw陶g4fd fmLDfę3aM!&MLM &i &14̐č4i@Ifƍ6H&M٦و6у3^k[m `DHi `67B@IH~^wFsnwox;{mLJʪ[mmUvRloā H H HUDUDWPQ;좁 $NpLXT9J>=/___w,m%I& Iڪ&{x/&Wg{Mm% 6S(i4Pjiu1 bICM6SKc4ښ]LCi(i4ژPkSИlmq;Ihmtژ1CM1mM6!PsϬlP2]YN1(JrF)lџ%g))f,xp#RFd^o{{/0UUUUq6|{/&Wg{ژmM6!Pjiu1 bi4Pji1 b 6SJmM6!46Cm!4ښmLCjbICMzPj|@0>/YHOYeaF}[{&6ji1 bSKm% 6S{M6SMm% 6S(i4Pji1 ״.!-m1 jbICM6SMy<^>Xj CPoUW0 ֨f`+Zf`P P P P P 3 ZԌ5kUZԌ5kA"$ GFff`ff`fff`ff`ff`P PFff`ff`ff`#3f`fϺl!!J9J9pW +mʪ*BII$ @$ @$ GծkTpIHy8WހIǧxecN wޗ[m̰#بưcŌ5Z3A%)1IJCl f%)1XJm6k3A!5SI"l ձA#jmLR8FjJJ6mֈ1VJMXci4l7UY[+VVYF$5F6鶭$٩"43 cJY B*XmblXbUUf"$LM#IJK5 cm*%q }I^Qj(VJ[؂F $`ee-Zm̉FHm4h#$f4Ci6Hh#M=ԑZPIF+kB4m6lRhccFQŨٛIIR[klQEKkV2&gZS(SVVڛ++mgm2nIH$$i*TMaL VTmbR#4b$* d*,b`Dcc)lXcc)bEbEEcLɣY&QXرmRlK%Y0-d[)" 15FY 7ZRMR(R"# E Da }oY[mm dlQLQFpubz`[;g.$F!6ILdHF۵mnZe)YUk%KJ[J``1+ mkz:VԖK* 11,bQE-Q,mQFƤSmXJBM,3+(ըBYmEaJIiǩ[Fnf,lheCp!&hsHHFۛ ٷcNiqSfCdb6CCb6@@^c h c0amP(44PXh0`ڌ5T%BBkTAdh$"YTXh@cRlجhK5E1F5ѬlEcV5)ZmշKRF 2b4hmZ5f pv6fյ2$cUhI[ְR1تA;fUjUi+h6[X66&نsmi 2dh00fd&#L 6fHȍsM&m-RF&Z*XUef 2CDHL"LM3m6C6d46ͣl""D4F" dMl|l骤%Z`KQ`KX%0Ac,41QDb 6A&((( Qk4QJ,F(1Qh(5 (jDI5jme&(5kT `]1IAP`jKhќl*!Z6BdCX!R!F"nZJJP2ZQ ɴɠ2mpFUSm ` lA* YY,K%hFMIZ*-Aj,X,Qj*66#cF&j-hm"*&@A$$%)))e,Z d+2 >:(,Qf I4ԦE2d1Lbţ4i%6P# 1 c4ԕ%IY*Jf$cM)-&ƕ#)*FR2K&4ZeM&5IcY"FȘ1EeFDj*lK%j"ѣMH-"0@Xiɓ!jK*REؓ%#dMQEKmB*4lFE5MDDD3+]eZVZ h5ms Eb6viLΒ#ssfp[ih&mmsLɦi6H٢Hcؐ)V…3)[bL2Jf%d#l5FDfJD[Xc )[!-Tm!mf*n훈&Ͷ9[ lUc4hdDF4Xi,KD2IAl6`ǒ)‹2elLɴ,BŔfRJ,ԭiei4[ ىj2[L֣%جYfiьb[[TEDTb1HZD1DTEF51F1RĬɲ+2lՅ3CcifūA&c[kX-ōX"$ֶɓY5D6m61FŭhѪ6YaZSU3mv 2C 0$2I$daI!I0 0 I aHadI$ 0$I1!aI$mi$I$2I$I$Hd!I$I0 0 I$I$I!I$I&$0 2I$M!HadI$I $0$I4!aI$i 2C 0$I$vdaI$I 2C I$I!d$I&C$0 2I$M$HadI$I$$I$I!d$I$!Ji$I$2I$I$Hd!I$I 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$I 2C 0 0 aad!aac[n۹5I$I$I$I$I$I$I$I$I$I%mmm0 0 0 2C 0 0$0 0 0 2C 0 0$0 0 0 3JٷwPۮCn\r7prkmܚw&ddI$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I+m+m+m+m+m!+m+v¶¶ɆHdp!aaHaaad!aaHaaad!aai[n[nCn\rwu m[n I $I$I$I$I$I$I$I$I$I$I$I$I$I$I$I% CnwVfnۿ%!(ƛwi6ӰRqI&Kp!(hMۻ)ۻ{ٙCml1M&Cm$ M BRP6ĠRP6Ġ%%% (!(! @(!J@)BP HBVIlu%F1M-5](mml@+lQ@+l&m eWlJ[eWlJ[d#XVjXVjXVjXVjXVIo,[z=c @+lQc @+$ @V&c @+$ @P ؔ1[m@(lJ[d5a(d%!(! @+$IۺM&CmlݤBn1M&qM- wi6ж[BIbvm eM-1Bi6жZ&m eBi6жZ&m=o{; Pi #`@ @HH `ШH0`Ъ H, ,R@R`jVjMESf(߻gl[!I$L$1! I(DDSke[FVDI"JSi)KMfF$1$ D%R$I$i6 M6$$iEM!#J33 `a M$`$U*,TBhXiR1F5Zkj]t2I43 , fRjI$I$I$LILIRe22I$I$I$I[-Ye$I$LMI)BB$f!13Z[U-Mfʶ+Zbפ,UUUUUUUUUUUUUUUI{^'K?.{hؒ߾bJ_}Ė}^ĕ}^$@@@@߻? , _޷޷_~Yͬ/t\7{ƿ6ϙssѺTcWj߶'i]>z힓މ-K'wK/yҼ|D",FH^UUU[UVO[}jjmRUի?7h!cn8dBYq[󽌏'qqN;Zz߾UUUUUUUUUUUUUUUI{UUUUUUUUUUUUUUUI_6/yWBIؽO]\m %뭎6BWB'髡zΒ|нgI~zxDÀ'94 p}'TRK[zů֙f_蹌osv%'W1 E0>gEoFdg{DFwo>mN;uWzu{.izl- Ͻ޽_=`" L EUUVUU{ődgp$@>' mȤRA$I|jQQo]wg/!t,> ɴY SQP|7.$YLb%bgqqqq/󻻛4wwwk4;t3**d5l}jJi/$F$[^Iy$A%D֯$L4헒N lC E$Z䕊 |A)"m\%mI '81I@m{%%r$%wADO/R4[TYmk4zsUUUVUUR@UdI$I $ݲtBH w]>n:eݎ=~9: ׭X}UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUl% "%IRL$M۠-lIT$RP!2d$M$۝hu$ɒTDM${|%rk$qr\I$@ IKKk&I.omHI=İ 8Fjm"As$(PXb8QFI'rI$I$I $ݲնozI'OutsmȘI$H i4~UUUUUUUUUUUY$I$Q"Iis@6iV[&m2Mbz^%r\$ $%%r BIHEKp{Gp**[vʞo$$I$|wwI$ 7JE]nI${HnHwo8 Wy$6w0q)w$\i/ޜI<(  0^I*M4 mq$I=nIo*n跧M $IF[-ēm_mͷĒI$koNe/ޜI=nInqÆ]nI$qy3pj$6/&Q?Y?czmI&(p_E8mʨ m;;=cy8I$mmNe/ޜI6$(p_E8mʨ m;;=cPoӉ$II$IF[-ē$6U辋zq$0 0$M 6Kd/[ͷĒI$I$ e/ޜI6$(p_E8mEU~mvws'wgI$mIܒ[Ӊ&[}w$-}IA$@@Xm;;=cP 8I$mmIܒ[Ӊ&[}qn^mJޞRVA$[]ڥmJ6IrT<||I8.mJޞnH-$U~< ޓ@~I$O[F؝n6ou$:t3I_UԒgmlیA2I$yԒI$:qfv+귺O[Nӭ/I:ݤvmh[nnBoͷĒI$vIu7%݉'qۻ[m %}RI;wkmcmha;&[$o6ߺI$vCmCI_Eԝ_9yΫkki+J.J\0fׯm F<0R=O%(m?PH$<=l-@ P0(@% =|=mm'H I_KM,,/ @(m888%lP (b]P6m@%lP (bP C @ @/=()L4M&! "D$ )s~~~~~~|9W6^mh3 330 30f303`f3`h4mЌD 6lDЂ#hhb3FA b1 dCA6$IVڕ6m[g@0IŘYn +l 'ջpiH@mID܈S%5cY MI$t\Y5MEs$ĒI$5I.MtubI#rI͜ EQdY5MEQ"fsI$ۜt$H2Җ&L+i*6Y66M 4)5!A[e@!-e-4-d+mVXխضm33Q$i#A Vdɕei*$f1آUeRJ%ebU3*f VFٴH֊[mRjѶ*5%e%&$mJj%em&ʆMĘ(j2hɚ6,-F,eQeTȍ̓6Y9cRg-g]RG4mnQ'- r%ݕ&lMUh4 U6)+m]Z涺m͠ەQ*nFn- 3jɭ-& ck`cHڱbIXjcjVa[f2X+dƵ j0Z5V6,SVfbJ͚l fdVͶl؍Fe`YARjԛ&ہңR6,[j64XҮh4m0ki+86M*cM`m&G'4&Ebc"DRkVhVkF mQm&I38HNI3Ӝ)*UpjjSfndr4F5BV3Ni$$iI$@bL$I$p7Ynnn"5cuQcsFD; smt;W(5M%;r4E(FDBmJ"FL*C[eACjXl3mJI6m6m ڑ5WBj`d2tԊ$ښГLIj56ŘlDt*NARSUT5"Z,a#f0_9]m[m,>hm X,$o?Uj4> I$I jx[zI#n6*lEvg7d*>U}eW6Ġ%lJx ؗ8qMç.5ۻK ؔ^P ۻKkpJC]kP6Ġ,Kd['QJXU ]DJQ(jR Ԉ&P"_JK#Ъ9%"/y{G2s.c YgW/o_xUUUUn/q6г/ϟ>|ϕwϞ)4Pۻwwm}6I [7WJnI4I-k~oI$;z$e.I/>:tlx<TUmw+^Yb6nU}e|ʯz%!( ( ( (m@/`! @/`m@(lJ/`(bq @(P %;Je}$m*FeAɠj٭}zI% @ {/IuO~*KTUmw{R&U}e}{RP6ĠP  (m@/`! @/`m@(lJ/`(bP (mX(bP C%/A=*ύ^\ 4M4gPBHBI0s~~~~~~|9W:2{N櫶ml3030 33fa3 30Wyޏl_(YII@|=ӫoI$;z$e.u:wKdK?* *l]z,lW^ʯRP6ĠP  (m@/`! @/`m@(lJ/`(bP Cq @(U}%W6m6m Faal4ffF)mab 1MÆ߶v H :300 330 4hC3 `Zգ3 UZ30 %Z30 4Qf`AL330 3303fa 3֪ HHD#z{-:#TKvKdWyUUUU@mTUUUP6 moJoJlcϼo;G6wK)Y1a ;w0 q n6m4mff`f C3f`}--:ӤuûyUBGIb1DQcBhNB0dUU |ςf)f`ffaf)m޶[ct^$:wI"򪇬Ӎ=/2OF1cLn9UC&ؼ30 3S30 3@!30 >wmewewY6}T{ҽ;vw=//1!úwl'q N; HHD#(+$k,PHV[nT+ k_F 0Č$X SmDFA1%"H"&̣F"(&BE VTQE$)!RBJֲڰ4mD6}@-x^; 5ݸ+(K= 8χ}ws{7>F\v}SiJhh&ʔRh%OzLFM1$JM%I0RQRxLOPFST%M*Q@ |7TPHZ$B%Lf !LJVfLͦ` LPJ$dI4)%RJJjI I $H+D"¶T16m-Z53LF`i-Z0l1hūjf `эFbQZCFUHjfJH훉QYL̥fFIM$li$3&I64I MM4ٺB*6b*"hŋiKI5id["Iljm%"ڭ[VȶT6EI0ERf"Eō6- 4-BFBڊm bKh[+e-FжV[-m(m jfB̢*d,fcEdXX-)Y-ilՊ0Pjb-Q՚5eaA4LL$f*fm$(k5m0ZTcF*ֶ0Zŭ֍1QY$SI&m46IlI4 4ٶ2%6i+j3MHڰXFƭŪ#jckAb֥mMM[`6h6DIm&2M#f,-hf&Qڅm-LLI"H2$YFb2c3+mXҥ,bFh[lUcmB#F 4$HLIm#mD2FdF cQDң0VZ1jB&j1"ihţ6cٴiŨlQQZ-EEF6)j1ƣ0fJM$i4dI&D!FH2 4fI#fi$&h$LI4M$Hi$6I&jFح!BF+hB2ѩF(&M[ڌh-mahֶ$H6D31V`fEY3*d"Dђ2MlƢ$j"ij$VXѪ!ihiIX*kXAb4Ib#m4DI4"d&ȉ "LddI"dD̦MY*R+ 5lmLm!MfѭF!MjfPJ6HDi2$&I3iHh$Hl1ȭCHD(JBd"iQmYj1ƣ0m[feV[hhZ6B&j1"Y,ڵ5$$M$D!&Dh$LM$cD"dĚLIĚi"DȓI I 464m h"h[cml!R+ 5aA2jj٣UEZ"e2[fm2$$fD#,L̦e&d,¬j-YM6ŵJH+ef[#)BѭF,j6ڛ4I&MI$H#2@c4Œ+k![MM T+i +T-d"6hlm$Ȓ$L D٢H&$FI 3Pz1jLbƕK,0`͛F5,0`͛l dҦdjj 3lK%FQE5edQEbM!I4i&i $IM4i&M$ &6$IA4lFf[BfE)lYjf62MHD&i6!fB$IbI"XMm4 %,FARш[bE0ʲb°Y#%MJc UmWWPKb"))&%$K +RIm&7VIi2#e(LR[|cR[KKJIMIe4LB$oCB3%mi-%A$څ(I&1Ќvj ,-MDHjK&ERZTFH1#!,ګRM8lq6Y6ыcY+F Hm%ePI,vJIFAxpؒh7 PI,jLRlbc[+$ąbcRZY+A$j4&DPRZVY)$Q4E$&vJĒ7DCB1 ʳ)Mh25n”"Xի4*mbţbQXmIY+IlĆԖI,R!$ivJILB B6BnڔKmpX,SRhm%[K-mlbTcYP5V 4A&Q[d(MdMTk%"M'jI#thB3B۶AJicR #xp&n մMem&I"*NcZUM,ڂ+m&$(ՕLEԈmI,DmJi1J$o,&D)BnXɣ U2M,ڂKaʒM)Ähh"LЈDdofֱ`Idض $MlI$m`RI"i ejd[d[ԖU³)fL4A&HkJ׃F,mI%VEAV  l+%RJ&VQVBDDEUY[f4b",Td,UI&2Ih0J[X1 hk%K%[Mem3RiѸ#"#Ah#h,U+ 3*4 gHUI(V$%X٨KlEfQM EEB5\Zmj"jKRlh6-$i+ QJi7 J&i 95MM&$Fb&ډ$I[d܆ȈYIII,ZOjȥM"o:"8"! &CĮm FdJI"$HѴ9Vի4DBhhRn86@ڕ[VI-% K]V""$Yy1&s&*J8!bz2I"lhJD3Ql&K̢2+)!(HIX K&XjZ#Ii8,Sp8NScrچ 6ȘI$jb$JLW23&XfT0[,W"HwVd62 ңc ,4 III$6D$$$lcHdM6B!  (4ȓ$IՖ&3qiBFHīm& j16Q[HVՉfhI%-iRj#jJK@Ib2MDE%-i-Wb dBDH4nRR I5`K%, ZPIiR%"),$Mn$K%$Ik\Jm[DU"I3$R0e1DR%,UL5"i&UI'hЍ]$Wp %vXXE-&IIfH nm̬F͚4MjKcR[PFDĆQZe(M&[b$"!b)i2b &"H$IIfL"$%JYIIVI%"&CɔeeFѴkI(ij!i+IZm1iRTS$I dYL™R#MDYJ" +$H$-̐KmfhѦD46Fh"$H2L$iHilh[IE )ڥ2i@6H""ɈiH$J̓4dMQRTŠL4M`08,ƈ6Rl)ACdSlfĉa4lm2ILa,&JTLDim(eڔҕ4clA`+RVK)i,X٘\RTR5c3cQl֓15eB[kVMĚE%ьF1ci-fYkxm:{R)WU*aVE&6h1mF2Y6Z-I,554 e-bIJƓP1&-$,ʌ5P̛AllTmش[1hHVCT%l4llhѴj4j,hY)ƴʢ1bllj5) JVm-bY,̶UF4mieZ6*6Ʃ$6I3&[2ŲV,6HE2he ٪ EmEF5)AB-aJVaDUy{9!B!"!B!,0!BBf!33333"!3B%Bf!3333 ʢ!LȄ&aB33331c11c1cc1c(1c1Qc1c1c1F1b1bc1c1c1Zc1c1c11c1cc1c(1c1V1c1bc1clc1c((-j1c1cc1c(1c1Qc1c1c1F1c1bc1c1c11c1c1c11c1cc1c(1c1Qc6ۛsnm͡B!B!3B!NVVVU:UeLfffffffffffffffffffffffffsj1c1c1c1c1c1c1c1c1%[ VUl%[ VUl%[ c1c1c1c1c1c1c1c1c%[ VUl%[ c1c1c1Da*c1c1c1JV1c1c1c1c1c1c1c1c1%[ VUl%[ VUl%[ c1c1c1c1c1c1c1c1c%[ VUl-Gc @+lQc @+l/q(m0KpJ@)1[P F{@+m#XVIj!J@)BP HBV5a(d=:>c @+lQc @+l(vĠZ1[jbP -TjbP -kP -5](m5](m0U0U0U0U0KdtVim6M>BP 6m`! @/vm %Mi)BP vslv㽒P۷e sd.vB+d/U| 6|6-\9-! BnWlJ[e!4h[-5](m5](mml(vĠZvĠK,kP -TkP -TkP -TkP -TkP -!J@)BP ) B @%J{!J{ wP @%%!(! @(!J@)BS<ߣU~ʶ X"0`i H04H0`hTAP6 HE@4* H$!l@)@ Ш R B X[30?; eRȈ( XZ !Y@ )DDA2 (& ,50 T@$ ,1hJVV[Jh ( e fֆT@@$ @$ I@$ )i@LdhZm&, R56he@UFo&EoEmlK>_KdUUUUUUUUUUUUU}m3DG#Y!%T<?^I*;I6^yטߟ>u $"uRI%㺩$qݕI%;yQ'~pb!Q:7-};F1|so}ss{kdElү{瑹y>6ع&m}Es}|לl~s{>l wvI&-o1$#Hϟ>|ps!BBNryŀ8OYrc0S5[0byDy{ͷʞ]sig}}$eW{򪪪{UUUUUUUUUUUUUW[v:Cڝ%zjl^Ԯ6zO髡zޒ|zh^^h[:ϱWCbx8;;~=9 ϯ]\m ߯]lwyvFpw7E?7Tc1. ` cϳ:s{;E( w;K/t7){/wvlhƗ:-k=nYv{Æsj_%ñr{]Ǚwغۛ>q;̘Pq/>U},%yROIgUVOY;HI+~{cL[w۽mr]oEkCo_- O!# c0P~k O)<0)5iĺq<100mzi~~̅T_hӄ| @$I𪪪}_#>|m~iM~m46vZm${y7< CKko7l^Vv<%~xyiJA%C=I3.qHfs8BK,BP޸feYDž#İmx &71hsLqْ̝Mh[dn^;{iqˍUT\bz( .\x6Xc veIezi){Exxotna$ݏMD12I$ݍD 507m| ; &zn' ; &zn'9I&8Nm IQnf`xotݘI7cv>{2$[%hUVXU(OU]ZȦeW0I w,RHY{8NI73UL~6}ww޷30I<7cd$h\12wfI6G|cg"mَ@ݷ30I<7cd̒lMDuI yo[q@'LI&BH,Mbm LVP} I!$1IۍM;,%-!j)}AUj !]gE'nB͸-/^褑<:ۤenUZb%QD9UUQE.Fr![I"xuI&˂zwVdv_fZXu Z,Y1Uj#t9B]'Z2p[uI"sI4UZb%QDUU`EZy!Bٝ':$KEo^K_KnߜrPųzڱj" KϿ"T݉iI!,:ڼcoj篯_zh amH! Ec&c4BtPcy<H @$I$HHa$Hk˜ (6C4RUm ԁHhFm,eME52ȕ,ț-h-fkieYF-F65V+lV XV ͳ4֫UUZ##f0VicgqS`W3h0h"PU)J E үzyϙ66fե|hƍ ^^s9~O_Uۙd_y%@;3UL}%0!=1_t{y3"U}-\%;@/`! @/`P HĠRRq(P ;')BP HBP Bn뫽oQ)"U`(%V 8P$ZEJA"*BؤWD^v(݊V9s#ON;_tОc/v!w#슪|w焐 @$I#abHl! C9s{{%~2lbmEhJ旜q2:~=^̻s%[I lTG[Kq&r>Cz{Ԅ!(! @/@]%lJ@(bP Rm@(lJ.)BHBR%]{xXa&ě7~ߟl7Mwq4 6δR}Z^s*${[aэ4孤nq̊F'Om6Ǽ[zO{%I(X,I(X!(XP(B6PRH$ %I(BI\5G(M6 OGrS4M4bעZ5^M|yl6$#dX$,FĐ !#dl6F@$Đؒ$!$6$I0$ֶ۩ k[lIZmkmuDH@$ wu]$w@$$H@Xl@$u$H @$I$1#bHa$HywUlt[vtzny7{ʪʦr*dUWTO<l6#dl6Fdl6F8m^Wگ:d'+=Izs>uxyWN;b8N馀I$H @$0뻽mhۚ-WwybHOvDzHz0c#ɞN:̒)"p` BH H DHyz4vSva_{{{ϾX;Wi=]$gBzьc#swrvEby}o fcP֚bv8xׇ}<9|p<>|@!;ujxS&MeJI@U%)azTOT=@d))(izƠ*jR$y( OFm3oL U) -SL`0mj0mf`ҐB%LHYlJ4f 3HDQF5JVf`ыlcl0mAh1mL`ъh"iƣ%S+3ihŶm1Zi6f F ш4b FbQX5ф"B&j1"YbԆkTFMcXCFj1ƣ0fZRJ҉" "HѴI I2i&I2i&I6I 4IM4d"HȒ "DI&Dh$A4dI&M4dI&M4dI&LIĚLI$A4I64Iili$$H1&i1&HBi$dI-fy(Q, (fڶ 2T6PBք"eb6RƦȶd6MddUB2ѱbicmmEhh"ecb6ڍhB&Z62RBC"H2H H$ 6m"A!$H$lH$ 3$"Dђ 4i$fi"H4dM#lllllmذlj"iZ4I`5ՆՊbXحX6B$[iXbj55HD,jŶFiĒ[%,H6i6i6li3iI6i"DɴIII$H0`I&&D"&$Sm"ihbŋjli,ih,Xbdm-(5fB 1[cHDmYm5 (VVlcEXkhB%4D$#H4#cHm&Di2$&IFiFD"@@ f"DJ%F !HjRT`MkQUHDQB&Z3i1m3i`F4m6[hFj1HDыcUi*Fi$Ȓ$L 6!A$HI6&fi$mH2bM!D" I#I0VmTPi!Di)f$)k* K-`EkAcm`B&j-[Y4 $ɑ4I&I #D3h D"i4D+6*lVDM5l)i1m)33+2̥YaA,IjfK5ŵVMlԓ0,f2P[fժ Xŭm*,ʦeUff 6B$ڥm*Vd+2fm5dH,[i5%c1c4lT +e%fRZZڣ`ōiSQ4I i4% [*6QfRKiF-R ViQVVUe6l$aK dMZ5ZdљVU&Pf-U,&cXY V fY$A2426II1bmMU2ɋR4Ȭ12d JKJҡR̴bpž V$lXKg PM6BefKm[($ʅ+H!#bJ5S$ڙFIXKg PM6XnTQI&vSFc@ѐYE %RYdJRl4cRIi, $QdI#xbB-%V`C 4$KM$jLV[|)$` {O>|ϒI$UUUUUUUUUUUUU}d{UUUUUUUUUUUUUU}dttCbq/tM] $н_8Bz.Lm+߭_yr8pqor /y5GZ^'zɫ{pyrԸs\c2 ws f3 = `&rr-sq؜8Npcrsqں9zΌwt Ћ<Ё~=u(0#>WA$;9\X^TI=d򪪪Ȫ%{&I$RRcF4cc.{y~NH$9n6[m$I%seŷϑo#w}׫ߍaUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUMI$A%0Ӷ^I;tMkz]|d '@$" &g@"aj *a I;t my#wsI'&#nϏ6^O6"I$}sknݹ\w>H^>'P)N-$I$*"bUUUUUUdOI$C >6xmvd#IlbI$I+{ !M |[> `B宾$iw\x}wwtHͶ2&i& @6i$I[&o;t-fJ% $&i& @q- YW6J\Y)aQA@ \JBW 0ˆ! I=XaBf4P&jMm,Uj.ªI l %w%o6J$HJLHF 6xDI$i{ꪪ(r$M۠4-уy۠٥Yn$i;tK%rk$  s}{m$ڄ4ޒI$I$I$IKumm.mftqId$O}%$|en A Ͷ6p.t> rH^aqp@[DY5;t%( A X'۠m$Iv"JIזMaI[mQܒmI[mQ$4$&IQnv6[mI$VFrw$0[sAx]H[L÷),Q@AIIL#'I``A.ݤII:/1K4df[sAxVFrI$(I$I`l ĒI$(IFe;t%miG'rJ3-۠I+mJ9$Frw$Q$0Qnv6[mI$VFrw$2۝ ĒD%[ Ēa A%f-QĒI$v%$fpn$(IFe;t%miG$HҎNJ$& -mI$JhҎNf[sAxVFrw$2۝ Ē4I$iG'rI%Ll ĒI$(IF`n$$[Gۼ|nI$FےN$FL a%yM6ܒqn]v="JHgl{fq$0Ç A   8lܞH6'AnRC;d7 ۉ$wt{Ycn$aÄIx $ 0 sI #SWvq$t)"MVmĒ` ' dzI ؞AMIIobn$ۻZҶ8vc^n$$C!E8A8aA< ݭi[;aAI |>"{ʵskx65ZSJ\>Ξ^xvmvSJA#aJ P>AOR Ea=GmdK)WН8!@(! 8 :@ HBJBJؠJBR(!@.R HBJB|NdƷZ[>>|]({]BRP6ĠRP6Ġ%%% (RlR%!(ӥ]u}¥z GTWJ2C))L*eTE\R!TOx!Q\]LMJ: Q+ʯߟq|žoŕDWlvPțk5w|wH}ᗄZ' aޒv_&ȪleB3Є l/{%{˽HBP B ؔ B ؔP6ĠRP6Ġ%JBmB@ B@ BRI,I,[P _v^mUugykQm_Ma}AI4$=GcΝB @M4mM$H @$I$0IrDDDDDDD$DDDDDDIDDDDDDD$DDDDDDIH""""""$"""""""HYDDDDDDD$DDDDDDIDDDDDDD*""""""$$VDDDDDDIDDDDDDD$DDDDDDIDDDDDDD$DDDDDDJ"""""""H""""""$""""""""""""""""""""""""""""""""""""""""""HDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDI6o~w/,myAxqK4n˙f("o|H#/n*0>@kڀ ƔrI$d_K/BfRׁM}e|PivmtJ9.c.b6Plc.b6Pl.bN$!$ %q%U\뜶"ԡ۷wkKM-&6oP]8iH[}ϾwB/^x"L>E<@Ku)ޒv_&Ȫl-B3ьJBzzz)/zJz%!( (!( (m@/`! @/`m@(lJ/`!@!(! @(!J ! 'Ԓ[-o_?O7>O__^|s9s!`Đ !`Đ !`9r@$ @$ D$ k[ml@$C ! !H$Ha$H6CZmkmHv[&[[mɢɢۤ @$I$HbH` $Iuo`S:CY)y6EɼyM}dU6"lȪlȯ@995mʛ6 孨ܗzTY,a===MB1(-Uc ܨ,ӻN; H" HCugt/t._z(Ez} (A =ӹy®UWy<$I$H @$6$Iޜ;w\nrM$( k&=e=$!Bh^ww1Uf†AU^6i$I mAB!r˜o-^+x;I!w[NwI#{˳_z(Ez > K!Q!=ӹxWly盽t$H @$I,I ! !{;s1AY&SYQg߀{p0`4zTATjŒAcCE|HلivpډOЃ(.u{|!ӆ!$<J$ $4z@()jJT5%*P=gGJΎuO{95k+W#\ΝgGJΎ+\F+W#\+::Vuw"۹(H"+k{;=Ύ+tYy(H"6+bE gQҳgYPJJ6lMTQQ)mjl((EoW^<hhy5jαVαVαV΋9]566ػ+ػ+ػػ+ػ+ػ+ػ+6^Yk4msW4msW4[据Cػ--%!lض-mFѵK,mmѴkX6AM -Z-0jkbmثbU[*,Z*X5 CPՍfE6hTUCVS6Y2Yb։fimZ+XKFjE-hZ65&FhQQb hFQQb hTXZ*mmTXZ1Z4kFhѴh0  l#DJءMJ+1fnZ-Z-Ebw))e2Lj˻cnB[ K+aKZD*H؛R6fKK(ْVFlQVh֓VwEۻ9tsQvN躻j5*:5r5\建֩õuwWw *6&EFQMiE4h֓FemK(H2LQP&ZصF[hM65cF5kѫM-XPfն֔Hm&mmZQ"ı,l̕h1%bѶ$5Y1E(f JBIdjfIiDkj&ɓj2Z+1HZ@ite6j,XQئlel,[VV(LQ0٨͕D(VefVeb2LF &(3j-1Fj-DZbQeJ-1FX&5coE6(QڊmE1E6((ٳD'K(S62JahƱMF3F`fCemIc:P iI$RHnضkSl`P*EDH-NU]asbj03Mm b֕2ԵE΅mXm-Э,fDTD.S̪Oɤ&&JU4,`lf``:e6mL2M|M#BIM#BHa&$m$Ij*ĊFmk&Um1Qdbc J1 Vwb효Z6aǁ6ͷ833ԕm[ T w6[6W[Ei3H2XٜYh 3lyjhZRESB [l&̴6Mc4j)1[jbl6U:clY#mXÛSm!f[y*hj`TTDZ[حm2@ AUdUY0]BM,hkljTmQclm%)JRNa[cV Z6 mTS2Ifα[jmlVVx^*%]xUӻv\Ղ%nM5ѮoLirX7Jt8l8An:6-j*%[eeFSm6UltKPU#cPI3 hTm$fY’`LYmfKJTX"DЉeS4fфBZKYU_mawԥ*VԥDD#b""b" 1`0F`#DF A0DD`"#0FDDA0F""" 1`"""1`1b 1`0F""""#`"#`c1cu1c1v1c1cuc1c7q1c1v1c1cuc1c7q1c1v1c1cw"1F"""""""""""""""""" v1c1cuc1c7]v1c1cuc1c7]v1c1cw""""""""""""""""""""""""""c1ccLcc1c;1c1""0bDDA0F"" 1;1c1뱌c1cc1c H H Hu]F 0Ȝ0Ȝ0Ȝ0Ȝ0ȝffцD36ffцDVUb* SeVal0ȝff a 33afmWWWWWLc1c1c1c1c1c1c1c=K<ʲlm! 7@K=a"c ]m$n-v͖@Ki]ܗUu6{tY&ϛmEnUUU7 0޶Gol3#M$ HHH~_Nڽ6Im` U m j-VmcwOw6i&cmSoMm5Mvk#zIm`-V1V?uEv$}.n~p)v~1ޜ$G{E/q$HmdG.GXJ.\&(O%bMI{ڿked[kбKkmbmj7{$;l$i%:a۪9p! >,:|CI#Dq%e6 BGTH0%Ҧ_[56nmg,`ɦk$3<|}YWpy}\y vxw_͒O"=IbTma[k#mmvk#s]ޒ[X U6GY"n+&V uY 0$L.y銳MnmZֽL֠LրS 337/@fΜЕs>6f#1o~S|[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`Hmm۶mkmmmҌJfV|fZwlۺҘ1klcm A H@Tk=^;L愣BlWmJcm$Wl v](|ĶQWzצ6[mm#r`Ǟ m6bSkٝ wt>b3кֻvͻo<Ǘ{ H@&0%(+$k:732n@*>jYVQd  "xG"DL>x`0HىS$$OU*4I*@z%M$@@RJHMIQOSM}}罜Yιg&\rr5k۹ӳܬYҳgGJ·:秽YιgWw+:=;=Ι;$P[w3E $PBEmosgYҳgGJ΋BE $S(l;$P[w3RQ{]q޵J6lMQBP&̛MCmxyמhhzk4msW4msW4msW4msW4mrYykkkkkzk4msW4msWr5据U9]54msZg\F5sF5sF5sF5mkcsUUG%&ڛ[SkFѴmmYch֊kF6FYŦmiiX$mCVͨjjkbE+EXc[chFɴTXm&,TXU@IDbVhhbe2e5ɔe(j6+j&mSjѶi+cm mS`حlPfTXZ6-ZL1e2LRSS)JLFS+wE4Vwt6:Sa1aQTjFQ ((ƣm,e 5C5C5TejD̦›!el Blf4jUfA6FQmeEFQFj3.ʍE6i-[[% i*m$mDd-fL`Gjm--YlQ[QBPSQe +eb+ EQFVe (̭h֍hՌR+F22(QLյ15YYV6Tcj+F6VZ*ŊeڌmEhڵcQj-1E1S((e2bbbbQEQk2EE)Z6((f1ҍI$)Zm"#[[xZPŃıҤqKڛLI4li[llJvuW"U7 q;#Uvڙjm6JvZ0Q}jrJThS6f,5P`3fMe44e6)$ a+4Xm,h3 !-æƍQE`+LͪƪU:;-t7Zi8VbUSVT%$l-Q`٦֪Z(mWbR4V Ūr(YhS# ʽOAj5AM+[njdqpR-j՜ƋF"TmFض,mXŋFdȂ"BT&8 CE6,˴.+IxqǗ2K*KWW4cXKIbi?3c}+XV+ҳV,bV(ՈckXu@(P J0@Z*m"J&h6D m ԆDm[U+[U7DA"" 1b" 1`0F`0F`"#DF"" 1 #0DD`#DF A0`DD"# ""0b DA"" #DF A""1`""""""""""""""""""""""""""""""""""2c1cc1c;1c1뱌c1cc1c;1c11c1n㱌c1cc1cD`DD"# #b"" #F.1c1n㱌c1c1c1뱌c1cc1cDDDDD;1c1DDDDKnDDDDDDDDe1c1v1c1cwc1cu1c1cq1c1܈v1c1cuc1c7 Sa)alY06b 1MK  Sa)nc1c1c1c1c1c1c1c1c}.亭K޽w%o{;ᷯ{p׽mr\6No=1c1c1c1c1c1c1c1c1N8mr\6ӺN{ܗU]u[ycW+Yon SeValZ WW˹.nO{1c/w H~uq#b* SdXa 33afl0͆]rX1c1c>ӺNzܗ {Kyw%mHvtVā'c1c1yw%mR{ӺNwTI}c?/D $D  `I$E}d"""I-}MI{pC>ׁLCCQX=bg7]}9>0T1s3>o`)} ޺UUUl[uWHIe/z׭9R>UM/|iBo[݀D0D  ` `$0] `$DBI%ﻻiۻ}.6b.6b.6b.6b"I `_Y(mŲ]C-r?ww68de# 2qs02}_<|o`)LHeUUU[-UUhA?൱̞w79u;Q_[UKm5Nz{ݪy33psCw@"0I"DD D[m}ݰr\>҇KׁODTDMUDQ4ÞL"?s8H|aϓ72lp}>t!{LC.[v)"g}u[-mlQD}*iUUUVhmWO :hI5&!{%wrM[%[%[%[%[#ZI$ +% ضK 7|ފ/{q*$wH vK.\Hy!xA]d]d]d]d]dHƺ[%qqqq֮ICmv-4יC%k'NJm)x=Y&L-ʪ|⸊8Mw'{}qMi޶Mi˧uZ[=Whr|U \I$4^ t|U/:>y*MԔNϹIVMis9\SDowDor)dWsZb~=֘EqG5-\g{8h4^ t|U/)ӟs$x'%^)=m76HϹJSEN|U/:s璯x/IHϹIVL["z91l3Ų.ǣȺ?[d(y+qMm[klc%Bޯ$V 4AiWhЁ[rI%^)%^)%^)x|I$4'%^ $IguM9Hnv兲[n[RmڠT,YT5TX~@"". $EIW'jҢfXڌM#$KhV%! l6 ͨFF,VʖFj8٫0ղ$[V-hKmknQ8prNB(N$Q=EPbJ$XUIF%,JZ Q!e(L /l4wǤI4S|y&a(.`ϟ6o^wFfw]מyk͛וA!06b 1M$C Sa)$I$Hal06b wm }RK4! 2$DJ$TjH @))R"$[[@ƶ11jI,YffffT Q JR`UX! #$X< S CHKTjb`5Tb%aIB$Qy;gE"9gyNr*@VVmo(fz((ͮmmtTFJ`W^yft<:/<כ7 2ВBHIlk[FaZSIDDDs9QP(|3?af}?~؏&wC ݭa6ۭnjW޷_ĕI_mhƯEDb0S0͛םљugEftHfuII$@S SdI$ f` dAcU@b/@b.>>~{wlD3ʢGF("_NytGtyE;gEȨ~ڻ [hP}4 @$ *vaߺ0:[٘uwX۵im Z[UUPx2&`ީD3 $Rmt(f=8'n8L8G37{n-Km4(]UUT|"w{3t8p.TWlwm-»$h\X$ |ʹokz1SG 3$Rmt(dMfuԠ<~@Qb @+Z(%D@A_aR Pм0#h>bڠ41; qa'pp$$OƉR4 I*CDcP%7z$II=*M40 M HI%)M/knzۦӧd]ιvy{+W\F\rr5vѮW#\F(yF\sHlcj.N;=1m]1%%%7F\rSֻIEIFE%+[Ѩ4Q6lMTQPl-U捯6kkzWMp[]5nt<9מhhzk4msW4msW4msW4mrYykknk6'995mWkhhc6%P{[[J6Ec 1i h6eFEeiJYlEMm"[*Y+%QTXmث*,Z6MQ`*,̬23)f*m(ѭ5m   1)Xb&TXEmŋƵر[QLJT֍%cm[hIJ̉#1JlTO mOt]]֭ؔSV-E賲.rpٴ컸R̮WfswE֨ch(-FE%6EQM64m&ѤѶa53 2Ț-cmkZ+F&c-j#SKc5F%-մʒSKIdRSdԙ5&MI&JU%2))R*-ƭElF+hTkm[$̣2f Mf,3Um#K`lmIE36RlehEiQEԶUDQlS[H F6ئe)mQEXƨʡ6R lllVb;6U¬SإJQJ"LmQU5TULс@CljȉfJRKblR2""R{6-R8If)fP h)؛blgsMT܌lKK)#eRҗ'vfdCBԳ\:Řs3GX\9V⳻ b/&*VfDZ4Q=F3Hb-]ZR1]C$ Z TiلYV{I $y|`"z9g#9g# eqc%cSkmVEdX+ei(SYm4cAjMjFaLPymbEQݫmi4c34fK$xBF5[Z fVCjSbě6Dة)Rڣ,ef0`ٴr󃍔[FedLoi66&XXХlfAm#b̸Rk+"ѵݭGjj%KKp"Q T|8> |-f6m[`, k3DVmWcbQeV4hj-65V4h#TlFZ"Ŋ5Ejj""&@!c,lU|081˅[mM MUX6Ff5;m֣2M6T RI*I[i>26zEi|1 (6\=}m[m#_)[}T@u !$B~B;g<;?66̜`媥=ϧ~𫡭a$I%]l*Ea$K˽m|t*۶t5l*knF{$mI2I[i>26zo`u }ml#o~o ~_~u: z~?x #}weT*"I$TUm|ݫm?/ 3,5l$I$]{6mJH IKQ$ _}ި>7`4?nprM`ϤJVa}lpQq$:FPw1_50Txg.m-1m60IJ(]w3߿PwϘymo{םv[7A{W@ݰaWC[v5 n>ʽw%Y`m& "ٵf+PT6DX+J^"L †1TVıV%`uaP6P0,d 1L1*3`[EQ2f֕2YfL8Ԥũ&4*OBYJEXʊD1idXa4RUmJ* z{uǁxux K#C`vkkͶmIJ_Ё$!Llhڠ+c`6Ei׺v[LJ&m6h6]|3^W)-t{!DqT/! ͠8B6Plffff!(B6S33333330l!HZ66_oב<FsfoC*6yi{^;YkYuef@$ ~wws@ խjZoӯƋ6@iswZmfIG `!$Dオxtݲ8i.kއ ^`811/w{^˲fnnɮI,f~o=~z$$$$""$$HL((VW=U*1^ߓ^ m3U4x~FAF6is޽ӴF<믞~G!Py|B#eFfffaB#e33333333FB5WsmkmH H $ MA&@A L @$ X% H H $ _ksnw~R^H#ؖIvmMmvMvՀm,ųs='5Ӫ;nif}ݣm3i$ն6$ A H@$ ~mMVj+vAЎ[z%k$IlKvj\kp-mݸI6]{^ڹ%FK$ն6$ `Hhk>tv46(hϴ[mFcM$ݶڶcm L @ KPVIDf`w>nWX 7{1j-b Z*MMXPYYʠc|&sk'd2JOI)JdC4 e)I4=@@=A'Q5C4 <=SS!zɂF' <6~*XH}ӳ Q,Y,Dșgs8MlSv+-uwZj%.$$\HEb.$$\HHD;+::Vtt"DHI 9gUU^t=8ܮ^+hՃD:.$$\HIY^$.:껃ѭjy+ǀ \\Üѵ;M;M;M<]\kk;MH69xѵ\ѵ\ѵ:+gvyj1(c!ck[1AXK[H56je6&`6ԭjR#cb#Um&4̙-Hڍ2C3eje2LRSS+`)w))XmMXP6P5UTXb,tkVQjWdSmYh5JYCi-65J;wbg5F; K!EPqGJΎftLPWftm;QX9HDQk+MrȤHܭmmM&c\:iYҫ"D쭜Y[9rel厹3@ANwDk\Z4ckQ2F&M([b)hccY6Ѷ̊Jl*lHě%6jmDZXʆ6 TYhD$De-Z[KKa#ZQ"i% )tYəB҅ Ņ,klVZ,SMF٦j[!Ul k,Ѵ2D+$JQXƶSQm4K#[ )XR2EE0iTډPf%)B)WhlŶt6lMVjb؍Dڱ+f)@+nZRFRlfD`Yi,E)[̈́QkKc!j3a%$l)XԹԕ U3X 5m-fUUYc)J"V,bTe2C,,bȮɲ[*[m-Z6Sm5)Xl{kٙXHHS(R4\2.ef3):0caX(Iس[H6cjQlU&ZRkFZm1$[`cH c-([m];eUTUPW"JYYMTm%Ķ؃ǎ\qFhN2M,ʪlv\jVw):1,=QEV-21F]J5a bH ]Z)J[mJڝEF ݦVۛ۲XlhEM4jlѢlQ͔Xт*""&(($I-$VHEnmeOZ~6>x$?FhϟTmWd66۩,Ku@5.ߝòm~ĒbWi1˖\\&bwq16նsoOMf]I7ǑtP #Z_Df7zfR%!C'iX0> 6-Vi8$d($DxXOĞ>}>#O}}3I ˩wp^ʼjW3™s^IK@ H6`IZ{v, $fk[mI#xR/}q?/Pio$[kòm~Ēnft\NjaLK]H],)1<^YERHrI5jwq.;N 򍶜yr+FcפFci5˗<@xI$I-wˋt1;8sm:dZ-,Ĕ~|pumvPow[{gP1A. 4i^^t73P$%]bHR[lJ.Avt)`u,2m R]2'X%v{G13b~Ԇ#wt<@ I5$mmf)%pa:KmAwm@owm@ow h;m5[[l*UuD *\I$IJVm@ؕߺJDp"PuQ $ACmytI/w[:;mշ%|FJm(ۇBa=d5[`I$Pv۶ $E&݆6۶ܚK HmN6{dmF[hܚ)#m/MhmbUE۩eZUiV[vmv^+eR[+ih H HXWo^O^gf̹[45<ձl<|{4ō6 UUUзMMDqMDD$"B$"̬D$"B$"I+**PPPPm!CH(e7nmϝ|ygy=U DAg,ř6M$DDDDDDIDA$DDDDDDIDDDDDDD*Ԉ"""""""H""""""$"""""""""""""""""""""""""""""""""""""""""%ե߿~~Y}ml}M:mnmzخwﻓīCkyO:.b(*'BCQM6M6N H"DH"DHj!Fa QCu<ޡ ׮֬%n<|Բl*4i-levl۩[-$ @$ @*/o7|{}GڌdL3 Șf2&Dșkaf6m_rěrۑ#Mfv՗MJD,d!FGCnZR$(*K%$KC +e[Q<){kdjjegwUV1 6VefRMX͉/bHIr:f&4E !쭅m"cQlhkq[&lD9YI'eU\xwpc"xRi,*AW1ƌXcVj1W-\Fp&6ujZXՊHc^8101 !8xxmM'<*ӵ,ϡC,)2F%Ii+lj"Ecd6Ke-cJXeQƒFe-*5+jֿ1c1bc1c1c1c1c1c11c1cc(c-j1c1cc1c(1c1Qc1c1c1F1c1bc1c1c11c1c1c11c1cc1c(1c1Qc1c1c1c1c1c1c1c1%[ VU1c1c(1c1c1c1cl%[ ml1c1c1c1c1c1c1c1c1cJa*Ja*J1c1c1c1c1c1c1c1c1Ja*Jߴ H  H  H#Z7)dIdCosK:$$nuIvA%mئv ئwݷuIv-jZ6jK UCd !`1M Sa)=Sa)al7uI San{݊l2Y6b 1M SammVvA%{Y{vvA%{Ym{d]uIvA%n:$su6w;wSao{'w]u1XVXb[+504kj3@43@ lҫ0&*RKZm՚MQ%w Kz޽yi H8h8i H8v{۹fg[9ow1]WsvzjwF.Y/QKI/KKr?Xv}zI>wVq}|? {\U0 7#k 5-Yk 5 kp%3K3{3z]4pI4A 4pA 4pI4A \g{3-vs3gb^"2; %sQr;>KyEILdv0L$oL%$&?~[jI6guWm&_Tm4v+coY{pA 4pI$pI4pA 4pI$IJFm۔II@I ,F-F-F-F-FYH8o1XrccReh/$s^Jjxo:=feYY-cW,mO^7Ʒڮ|yԧbb;`UK+1wV2E$E$cHHH"#@qٟX[lmaJ#EbK$'ʅ*Q$WT*~jj&@¥Wee-rj-ǜ_ bdvG;{C)JW1WReK+<|@$ @$ @$޶mk%RUHT%KT:"_ {OqZdm!&A-( IjQIUJiƂJFa4TRLjII>@_ڦnI" i"U]Y.KU_k[0@gH;`κt0@!~>)KlcmuZJcm6x1JRcm;)JR1c=]DI$I$I$I$I$I%I$I$I$I$I$I$뮺뮺뮾s0-gUhlFC~{$)JR!bK,,RHc!@$ @$ mU.%&% >^1*Ӧ6%Uua;y$ @@@$ m~""""""H""""""&$DDDDDDI""""""%Z$DDDDDDIDDDDDDD$DDDDDDIDDDDDDD*Ԉ"""""""H""""""$"""""""""""H""""""""""""""""""""""""""""""""""""""""""V>[|>J^gn@!wHO+!bdvG]NJW c)^1]J\)LW1WU[r[1M Sa)$Cal06$I$Hb 1MI$8r^m#Fx񫣼LF뭷@# g)m1EmRM1R-1NJRc뷾I$I$I$I$I$I$K I$I$I$I$I$I$I$oof h0T[E|׺u%ݖݖ$we[Lʹ- PdaUdحHۻX[]I-mJe#mZK$ob6'ےJ6UZmI-mJ9v΀ۜn5qmri alm!I!](VK +h? 2E$ۀ)# [) Pim DL-)4bPU,'G{*"I ϭGD'g@$UOLiU$`a%Jb`=I Mzjh2%)hS)a?{{Ύ랞rgGsgYЙv-55˵f\rr5k۹ӳܬYҳgX9l:v{FNr+W#\֮[4klkZx漕j据jk^<hh-ݮ69%xkksW66uuuu-ݮ6666y-p֯5txsFזҸF1VαVαVαX*P%+bTRڨ6#iP̥Y3"BX6*[Im(֪V0ifm )W2l[!ht]BwE݉NZNJD:ervw)ܧ],rr5kujalsnmجtu:6Սbc["i5b6kbU4GM&dRSR75V5,[ A\YU'M&tkGM&s%%-wil:u+gM\ î  #[ZnXj1mXJD&PX-,ZXc5dUVXbZXE%!$iibZX%J$BbM%%6"65ADV-Ql[BZFQh2-K%̒҉d&Kci҉LK$YV)XPՙMf2m[T6+jT6mUr llQec*fٙ%RWL6+il6+j"ՍEk6EEE@Z-d+j4[EFhF+EFQlMi(UlQV6(6Fɢ4i4֛ZhQQEhցEY1DLVl,"#m&Q-QEMmTV6mV*1cQZ-XUccYlcV62EE)[V)EQM֬)M ɛնZjՙJ XVdDhI*4I$Ej b- TeImf5XVI!-i2I$M3ogXՌVjهiF22c:1Y*2Fmfնh"3X[Yfs&17M[V&RjVq [lqlͫmL$72HP ڲڵWXiQbF#)4DTlEnw6$P  Z\Ҕ73DٖlPj6.$e5ێG )[q#Lm#i3HuV+llF$ 63"6!I͝*(%(FmYM4j ٔd3xVL)C.R5Ft]MF+^W0jCamJͶR>|ws68o1kg{κBk[=bz](]^Mtw"nknwH#tomkUy@{㫻#(B6Pֶ#e JP$!$6$ @$ @$ @" X5CVemZT Lm+@ lPԵkU6¨ JJk$Ml$5[*UԲl 4* Cm~WgD $D $I+M:Wd9'[{^3]1Eؕ sywwDbB03D!b̥mn$ՙ#ܘ 1fy=wo-3S|,KD%RāK`h4mWn X g5CA4bMa?iG+vR{u#iTI$9%!]@fxXI#&wt;"H@"I$dh&:fb阒)ZX=.s9r̹Kb櫖%s䘏b>J ުݻLwCרɈf-ɀ{=@@emܸ 3ٙ]ɘc0.Bof#3l)$\X/4 i{$@M9&|f5n@TPC9 p_ܞ~+ustm00I$Y+Ez!m$I$- Ckln&$Nt"$Y$\يIWwt#%jPBA1c Iܗw p 8Ψ'_ڲ1%Ku^]z%$dm$I$u=M9& aE{yy{{uضKm"dH[@[%ۉiEz$,qzHݢl {sj fHe^NIdJ1#`;wtD!>k˔LO[I$I"Z5 BBO]dq7m5Y$"+muzrDH5a;'3^W=9I$I$KuF=6x붚݉@~=m2o۱6x붚^/P=,ɵ}xvI$&^/P=,ٛO\dXpÂ_$d\Ifɳ؛p^fI{{{g/S-ϱtsZb.1ts[l9ضKG[&r,٘qI=I,ٛO\d0=rYkEG$d0=rOBwpW)z:pW޹$zO\!tsZb#kL["}idW91lø]}>z|4ul7Oo*@vzmSr? oo(Ql`o*[.]V]Iۧ7_OȻ^Uty6<[mNiǏyd͏Uty6<=z)ܟ7޶uyT>\rOoOI~-@&^=JzBIqv1 8c\fZ*+ZҔjKi’B1effffo IQI! IRHBBsmlЦوE(#mjS{@$ @$ *fafa !RLU%1BK>AU Z65ڀ55y؞ADgYĥBUTU$6Y-Yn*I٩ %FPl %F3333BDd$!$ .%) %2*XV))2T"b,UUF(8BR/bU)Mk1hŶZ1ؓblm$ɌZٛD`1f#4B6cCFd US3)0$0$Ɋ5LffH@F0жͣhmP26%LSM!#5UVmѨt(ϡ &]J ApSp{@$ @$ G[VիkpAPACkM H1?z OZkfaS+Uw-vݥ& ±WeVZ3AB H Hu~-x-T^y5y>{~i6 XT]1 gV**Im!H$ $ BjHh$4H  H[}ە̒mKVxMwmĮ[lC&&I4fk`Yvl)[Kiw EScor ɲBl*[ēfbmwmX BRFAI &>m I-lۙM'SHWcnMswt2=fE,ˋ30;vEM"UD)d!6jRY 2&ۀ- +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 @$ @$ @$~GdMeІPQa~@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 fsbLY9D (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@$ @$ dMg F]~@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۴HE@۝:mܐ$ [mm߉$bc8Bc8XP1!1!1!1!1,I(X$!$bc8Mm @$ 빔!1&ֶZmk`9m6cmqnӧsm\ӧ瞽/w]=zzLg wl{yץ s^Lg O=z{zPw{^(^^/w]ׯJm|IBpp$|1/Uzc8Bc8^{wwz$zpWsޒPׯJpWwwWwԠͣZ6Qm* 츴-@5@m `"*6{D T6¡@* @j H`fH &AP @R"l}zı`f{ G$owA$I "8${I&w-m,f+3.@|l_ܮsUnb@GԢ<ݺA:8g z{b$BBF${I#6m6#ۊb{{˜#Zx1/Sqpsij$G$+hFlBe"J2gbI{ XaCtowB&:$ADpIt=$Řŭ횲fp1\rw᫲Į` ɘwebg3%RM,w˺S7{npJbo\cBAPmԪ kLHcɘ \|,^K ,X$${ׯM/ &M\%VqEY(!aL\ƵoϓO6ݝWU>K3||} 윣"I$H8 " M]vI$?bJmv-mv-[@Dm>I:/زIY{,[mi)6b6IQR-ѻV_4{M֙l}Y$3;wuu]‰'l~kW{mvI$ȒSq$[@$B\l+1lklwAvwA2IV۴&( I'w8L:1>wWcMU;y&m jǭ3˓$ə  BmvI$5bWjb.6b5pN^ޫ%'wHma#iO7]\izfw/ B9zm$hzzV*ޭ-Chv+^ ^Mק!r<sgoz0NmE`)͵knI:+%[toGF[nfIw|,8/TezwkL['6['6۸ƻͶqŲsmNmto2SdrMmI6Ec{[g+mlAHm&==iqyo$!qC4NmE`)͵knI:+%[toۻZb9%b95ضNmۍv-mm{ym'6drMm<[mﶞ[*GYm[Ǐ?o//lh8fadIǧt]ϖ!l,mh߃9lm{CkBfy-8-Y9j/.\͝=|jb! ľC> .x̸p#\SM3kNUUTkj˩ZZ$ $E$QHHH0F)")")")")'[,]ƶow™L 6ʵU jQE!&5HY3,ŘOm٦&)d`QzJURRyTUXU]_mƓ."@m4$z_OB 8B 8L&3 8L 8L}o~>[B@$ @$ D$ "@"D$ $@"@$ @$ D$ k3,K7mۭKw[wlI$ksdnlI&$.c3 ff'Q'JnRZleZ dQHFɲ8I@$@"@$@"@As01fHezs,i)enު&HɤA%sf1c1cmf+d%m*(wwuުn%rk{$=6یę31:nNܥv[٫UQ)6G 7R HD HD"?yobLr \ (1p `b}AJJ @w.7v Ep>cp2 $"J)`4I*T#$J )L5)IJLF)%m(ֶ&Ԧblj4UhڐѭQV&dLFYfAfD̡YYeUeeI%RlEl#a+j[ eIT,U$RmBmQ[%M&3$Y2%mmBإmlMjaBڌVc$li4 2T,ʦj&̳UR3hYAfl- hc[lM[eSV`Uaa$$6hKfha+6i!mI[ګ4m$m+b4$"H2$a͚JdI Skd*BmMM̳(25Q6V[BdeI$ٲJMLLl Z][k4kƱkM5bƍcXX(ckQQض*4[űlkMFƱJ5XjűQ&1M-If4&ILf4$Li643IF$&i &c$Li64$HijjjXV+JQXؔŌV+JUأX6(5cXDJQXٍFkcbcXأX6ZEJm hĚCHiM!4F$BMBi !i4!6l"i6@I "MmFѴkhFѴhhh*+XV5F&Z-,jTV+Tj̡j&6I$&6IMfH2CHd$ldiF_&Flɑ-26#fLiś1lcc-1ccl61TcX[e6&6&$DH$"FD&$h$Dd6&6$H޳mŇUi$""""))))Q64X%I &I$  Ff53H}ՊbKbVɵpIG5uUI$fKHC3p$ͭbƌF1QHdDI3wI%ԭJHJTErP 6HZIim%XшF1bY-%mWRIkTC6aY7T4mlTcEFi-RVKi-LDHHD>8-&Zeb&c#,т4d SP0!uR̙eUC҆HiE- l¢1YRJX%UM6Vi"ٲŲ`JX4LحYLVՃZիj߻1c1F1c1bc1c1c11c1cc1c(1c1Qc1c1c1kQc1c1c1F1c1bc1c1c11c11c1c1c1Qc1c1c1F1c1bc1c1c1lc1c(1c1c1c1c1c1c1c1c1c1c1Da*Ja*Jac1c1c1c1c1c1c1c1cīa*Jac1bVF1c1*c1c1c1RT!HmR V1c1c1c~eF!(Lf#eF4lB#eFwUkwCm![sGVۺC۹*mܕqJw(vխsGVۺCt۝:VPlB0fa(B6PwwtB#e U[̬^y$ '(MmF4#e (Lэ3 %I(BIBJPb]Z;u[wHuwHum: VtnmܐH~6kFѨj5Fj5F(a (ih+(("+6٨h*mVE$ *Ji` ,mңR-]R߯ `@"@"I `_YH00Kwwvmw}}}vi~ܻ7x6_>m\z[>_-ʯcϟ.TxK{ꓶۚ@_|6?^o[x -U;q}\'#k"5/imxX[m$m5ɵ l,cG{=D0D  ` `$0$W@II%ﻻiۻ靖Brziu M Ix)%׿v&u]uI=[ѥ p4?@w:xɯ{Iz$uIm l/"D~U mU%7]x -Ym,J@(.x}:wxy/q\w/~D0D  ` `$0$W@II$  o[lklklklklj$06b.66WzvC|n&FHIh׏ (AyyOba'eI$II$I$mcIOIxYm!ľPD@PC/{v}xmŲ\mŲ\mŲ\mŲ\mŲI$i\iŲ\ml[%[%[%[%[#ZI$ +% ضK{g{>q8B@/'ތ!<Н[zܻ.ܾ7ضKضKضKضKضFtHWJklky*Mv@w.I%^)=˟y*M$^]ӹy*M'Ib;I%^)1>y*M= I*OJi=˟MIi# 6- Fu!ERMe5 8nC(h='3^|q $ASUJdA I)Sڀ4 SީR"A")L&#RTTQQG4QWbmZխmZ&Vm-EEEE[X4j5bf5f%YAPlYYYỶUedY̔̈́H6JZ[cQmĄI2XLSa[+el͕j3V1IR2ZM"DI1&$6m$B2CIf %JY )jmd"eZZkFEhֶV*YZe(Vو$L H$lFH$H2D ͘TV14jR&cj1VHDQmbإصM֌Vl[*ƶEc!MF i6"Dȑ2 &i1&M&؉"Dɉ3IcI4FM F$[VHHDbZ5KKjHAbX #VM$A$L&dI&Ih64$BDDdDR3V5 1hZ"6ŴU֩fea ƐH$3H!+VJl)m$EYe))AڡJLl2̬f"[ M&K#VbQ4DjXBBB6V+0&b1TJ•#$$F&CIC$$LMA"L$IDɉ6L2+b2( (jQAmelKim-)Ff6I"lHH"lH$D6e[#`SjVm2FF$=aIklEV11mcթ$IHDlz0ejI& YsU\IZlё 6#f -ZK)))I%&`$hV0ZF56L4H2hfgٝ M2Y2dM6mjm$! U+[QLsdFIXm#$i 2FEy Ѷ)LʳML 4 eb&pa !o!c o)ƥEFhъ5YRd"A&HgۢR(H)dDI$IiV($B#L#f۴X*,+$7 MTQmѱbƢSVč!!&č$$š+HճI!HDF7Ԧ2J7\hѣDmDZ66#llllDk-bL$2DHm&$m#(DIIZI[2"ĥ%%%,a&̪f͒H+Ljj1 Xh,TX $'2ȍ l#mfV1""1M,̳&fV37UAUA 2V-&PեZ,Չc5,f3jMZ64[imRkKldlMfڙRR)Yi ډ1I[[[c1cc1c(1c1Qc1cڨ1c1Qc1c1c1F1c1bc1c1F1c1bc1c1c11c1cc1c(1c1Qc1clc1c(1c1Qc1c1c1c1c1c1c1c1c1c1cJa*c1c1c1c1c1c1c1c1VUl%[ c1c1c1c1c1c1c1bUl%[ VUl%[ V1c1c1c1c1c1c1c$6 CjfOP$ Gknpse kgwlu{BQlu$HJhBRR$HJP{,F,I(X!(B6PlBĒBĒ$,F{ׯyκBzu҅9v{׼]tu{wF{׽e sPy(]](]sP޽]tw{κBPκBUwb<.\\! H9r9 @%k[ml$,F,I(X!(B6PlBĒBĒ$,Fz_zت5Zj@J!m@ MPV[(h[h[@A P$R,XQPJ,P0-+*T$ @-`YCe@ Z\j~߿턒I$UЋYv®Z˶I${~9w6!}}6#rMi|9IRJR'fU_[:\6m{mmm{׾ze(zl! W}|#A}ß`UDI$jHI-{/{®a$I$t"]{6m %'}-FKӦ"hhF}ww#}ww#l>CI7HHIP$$YFIf]Es}^;wti |xMeI ۶mme$ww`99)IJ1s>w^/7{aW@ݰaWC[vD[t m ۶t5l#R AQy/}c鶕x-mx/TޒOz39*s9$ӷ`m& <%&G(gO/}Ontҵ(Ng {rT{$U_ckhD0"۶}c|'j^ /I/$y/ݷnl*۶t5l*knF}6ҭmz7y*ui7m}OTw[B!ݵEv ǒI/.˯w^cI^={}&8DELp":ˤKz{{Iޒn׶5 0y-;oM{ jA $=<{I%׀Dur xI.uI$I{wu#}$F;ޚ` ޘ`7[5$[;0y,%ٯm zkm6@'pz`[mwޚI%FI%PKۻ$w]B4HNf{rEL 2Ol2s3;a ${x-{{ jn턖|}׶YoZwϞzZ3[a$޾^ooa-V-ݰ I$6n;KUv woMV܉X|=sާ>ooB#eF3330!(B6PlF/گW޾|5e:hw?}|4fQݶݶאB:bfFc]omYڬ!BHI(X,I([3330,I(X&fffobF%$JPz_%ܺ6M{q|w3[mBҒm~ DDD$DDDDDDIUH""""""$"""""""VDDDDDDD$DDDDDDIDDDDDDD$DDDDDDMm$DDDDDDIDDDDDDDDDIDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDb""""""""""mǟr \ C6בhݲ8bkmkmmxAct5|Wn @$ @H@$~-U}W}5qƣAm6Z^ m3U^-t`e!!xBUUUUU]Z1 oB#eF3330!(B6PlF/U=Wk[m h$ @$ @$@"@$ @$ @$ D$ @b4$j5$ @$ @@$}ƨ\ߜZmx :mɭ.Hm,#@73>^}RێgI-cm[vձ6$ $ $ GqF`6% ]-ϪFۻqݤ8$mnwt$ D$ D$ @E{w<ݯncnV$4Knmmݲ#4B#Ms<,mݸmq t۶6hޯMum[n@$@"@$@"@$  2G"NJ 0)* ~.-m4Hd@dd(@@FdPOBDS{$CT*@qxH(ul(B@*rM*P@:85((h"US&hd bd)R@@4hRa# M144zQSԤRQ# J"AJC#zQ@?w>/~Iߎu3RRR$QzuaK]ѹr7.Fwtn\/RN)bԓ,$ :3Raa'X'[#r.$Y#IWTNֶHu],d/]ܹvHF{dwU"Hˑ=Wd$im#b,ET1"eR&MJH1-HEe6?;(m5ѷ\ѷ+aK{;]v:zp>]< s\ѷ5Ý灣nk6湣nW޻\6湣nk;kF4mpzyhۚ捹hە|捹hە/~8Ӹ>hۚ捹^u,n~4[捹hۚ5U>}nk6=WRVF3Y`2cY32Y\oֵmMJllmD)ѱ 4 b,E[RkEEbEت4lQ`,6ڊѱEآlhFcFأ`@Amj6([Z#W+hjmA3Fh5Ekŵm4FȪj6j+ -mDcj6JڥX-kcZMEF5ʮmUͭ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[6%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_36k6fmj5*XԶŋTTVMZ&1c1b3V1Xcm* J̚ы5S XhƱc2 m*ԭAaYPVS+,b5gZjUjYSdT+!}s6m\ܹb(1c1[wv1LimVݷmqc11cF1cȈ1`G+whvݵ3t9vݷC"1`DDDA DDDD1`"""" DDDD0b"0FA0b"0FA0DbA" s]ݮrS+b"1W6ѱq*ٻccn%[ Vˮ1c;1cr fvwlllm]v1c7]v1c7\" .1c1c1c1c1c1c;1cc1nc1nc1nDDDDDDDDDDDDDDe1cc1cwc1]c1v1c7q1cc1cw#`DDDA#F ˱c1뱌c11c666661F1c1c1cu鯾׷mВpmnnJۺ{8nKMHݻm (m۶ے6$w{Cmz;m-}_ch1c1c4'IrTԄHI{{ DNq{ ~k~1c1c1c08N!$ 1m6ۑ;ǽot6ۑ;ǽot6ۑ;ǽ{Іr"'`8r"'`8w{k1c1c1cN:; DNq{ DNq{ DNqc1c1c1c߼~~܈=v6ۖ^0z{cmjǝr"'`8wnZxq{ݍ׌nZxq1c1c1c1c=ߙ}܈={{܈=v6ۖ^0|wmmݶlm ǀߟ1o6\_5ݣ+ݮ|5Gk;5d7IIAwwmw^=kF#l?=ߞqQEF4@00]va|l\YNU1%[0 Bi6歮 F&߫j6fjm@+mWlmcmm<Hfe9m $IؓbN> 5I[gՂ7M}zx&ЕI0aKd$Ԉ&dMBh5[mx&}Kom=,gik^+vIû=}w@?oʠ(lf)A$I;NC|z Zr*(A|tHwt m;m۶mmNf}$Ó~ݏzm2 e$e99 ||wĒTnIo YY$y;hi$Өܻ[YԐB^Dk[Ȉ_䈽{ow>p{]=>Ԥ0o;ٚz6},fPZn`{O n~{{>?;jDldl_]yrX(pĥr\5m티ͫn ,#xٷh4㍯oOfA=6$)5-}Ͻ;bjsHY S-HCTK ~ٶz].K HBt v$#G$ؓbNer@$%vĝvWlK+bL1n̑Pp $0q R Y!;v$-,5ީcⵈt|{V7V#0$4WZHk{yۭ=I-&`A$$AA}7t$N| #SHBBTA=S@]v veMu" DL6th>bԋ\jMYhDVmZ>=m5eauhI$m2U؂K6Σ If|A=`l;\&uhI 'Sc%[]Ƭޞu ϼCzyԃ> >|17ttެ׭&$%[5ljѶ4[mlq :ihDgM-HCgagB5mI$^2U؂K6Σ If|A=`l;\&uhI 'Sc%[}k־}jؓbMvWlI]&J}k־ljձt-vͳGIyԶ6't;f[sm:Hz !M-!YYFȐF"Ai&B> {i&B> {iYI I$zȐF}$l> ϱmG B^6\=g]w2}c떏>Z.[+y>'w׷:ku}5ȝֻrwG,]HXc!('0ybB1N $k,,I'--RBH*i^)I ²"I bQ!!kkI'VDI$$ # *BLhp^Z6Hԝ޽o5o F-pVJzw..wM%Սhflؓ6ֹ\+J0]j֬~&e[o^yuTUQ[kl046YgMP\u}Mb.򎚎FmefW!Ͷb6[ILwRGA*Em~{"po78nzd7DY"/n QN2 @ OUC@DbeRrUp̓+cSbROe؜8W.f:Q*]Jbc  uԀ]ZVT]#3+LvXr+Y +gR{] `ʍp: K+v[+Qa " I.FZ3Slpp+컸F1i-'/:I"xW^Q\ pI#W$;f=3R>j>z)fhW/7+9mͤVT{ˈ|U[B6/t+Ky)W~iDrrY]eKI§@ U %RVZ5U!UDbbYX`VEaQiUZ)Aj& XR`1X*C)2R5#QZ+3*TTeBiA*VQ2Ij M&QaViFP)&UY d% aFR5IbKBVX`-B-%VH2Q((dC%VJTLD`_٫s)6["KȮIWPDfU1Jdb aLFJ15+U1 (`~#Y.2IHO>i+>+UfژK2+ Ł31-5 E`ղA+*>aqɴU5+,AKcLa6$&bX<\QY T#2I+*ue8BWFQcFXe^wmݻ״WE^[Fzto[EBPy)XKK]w un%hflؓ6֔.LL2"&L""""""%&L2dɑ&IDDDDDDDڲdɑ&L2dY2dɓe6Dȉdɓ&țm%mu9㍜_U}#km,E2jeoDK 9g+c 2`C,$,$N bäJ*+mNU^DD^UDNU^VڜʼʼȈ%c1gIZ1hΑdZ1hDJ*"IϮgHsngH}}t\_F?\h 3+^9kjqu}ۦF>}eVG@1Wrլb\t110yWUxU^UUWyUW^UU^yW^yWUxc1c1c1ZkZU^UU}}Ww'|?/ ; (I * Kl@$le$H @$l%UguxVm;*089]ox{x (  (w[Vw^{IGY$-gup {llo;6@ dle꛻ۻۮn.)HHwUSdѱFƍ4lkl6^N I}):qDD^Me'BIвRvށr7.^ܹ#pD^[^z$#ioAz$ESYI "/D);Az$E藸Bow)yqW"uWk{:1P/q6!6wtn\𭐱]9HՉ HmdԜ zyU&hTJ[m湣nky\UehU`YZ!\cEyhۚ捹yhۚ捹hۚ}zW捹hۚzWhۚzWhۚ捹Wp>hۚ捹W~=+F4mz{ߍznk6UsFޯp>hۚ捸[/]3dllMZ0 ,FUQ`,ƍPP@APTjHRIZM*MV-Xe U6~Z6 4FŴm c[[kj=MEETTl捻mxVcZj/6Ѳؓa*hmk[m**$m""il$fT 'Um i_㍷ iy'(Krr(J 釱-E DLYN+ŜĘuOŘ~ 9}|ĝCV\eVIOx!:_R ͭ3Y5ѱ6hZ FeVb2lQcEj̓dس)2ma6l[MQ척1LI"I080VX~+ q'~' 1x' *qLTl)Mu[VfYTb$1ijı<1xt: p)჌1X,b,bb,X̘ꬪhikBZڕWC._]nFHJŖ Xj] 50Uj_T蓨&Smf+6S&Q8`XI e~:=ͱLq1GXuӁYeXLY.2qFd֛Me8}3]:1jccjxeLj\p ꇊtuu*dKe:ƕSjjpIֵu"xbW74uDž过1Vd`hڇ6V̭W^T00x{ cpzI#e.[~w| /G>~f:OyW /2d`0L |V^q/c_0dّ7q ^/_{=+UX']^a:t2,Tu1f W2IspSt}adpdf~:pq©pI OHS>p~g!cF~Su?gj"xaRJ^Ч⟋ÄY_qq{=m,N p)RqbSc3?k  l\2# D[in[i[l]l% )7+uhsl9vөNhYmuw[ %djZ:ʕ-fW-ܺʹ,(5sItֹ5+Mk\kVfa880ɒDᩲG-bʵj]ʱ[}~ڵkzŊ52(k6M%э2Lتj=TzW9\1\1jfjfjfjfsc1c\sCL ft:3S53S7LLLܣ1cc1b1c1cc1b\1c1c1cc1bcF1n;wtnѻ-mBۅ nl[pچ-mCjPwq@1c1-[pmj-[sbۅ n-[pڅ nUmvc1F1c(1c1c1cc1bc1Z1cc1bc1c1c1c1c1Eݶűu۵lllllq*wuݱlllllu۵llllfJ%Z1c1c1c1J%Z c7wFۅ n-[p n-[pچ-mCjPmjfhJ%Z VN2C7wF۶mámۅ n-[pmۅ n-[pmۄnJZwtJ c1c1c1c VBU*ЕhJ1c1c1c1chJ%U7?);{3bm݌bm:{q{3bm\C%pwѲ[e e:{wmA,5uq SoG魭_ hm 0* {W: eq+bގ8]1NYoGwkA,5%q S[wɊbގvf[/K-8-uq S[wɊbގ;5u: eyG}1NYoGqn%^ [kFm%wqź!tz8;v-ގ]6KlA,n/K-8]1NYoGwkA,n/K-888?TشXرbTvS)e2L*Y,%([6pV[[r+6,ͶזRD8" >qwʠAHʌUW|(cS~>tm Bj)$հնf0őb|ܓfR%ffٖYf١-^`TbM2m)O=O { EȢu9O19L8SM'NМqǃ£ە&ݼy ZӲtI$$B ª*}{[=*H୚l*X1bxO_@C8vIl}s AdIϡxAwqN ={ǭum<A}1%cR{Ӹ[KKzliZV|zɧހd-VIvh{ݻpt 8HIӅ:tND@^pgvwo<[UӲ5Wv zH$~_{ETS*Hr|֊ҪXU\$,ހrr<܏.vN('g2[ݤMPYW{*va>憵<6I$IB 'I'I w:6*حUUUNj4"zm='${}}RN̸M5UBGmw-rHM|r<܏)@`yMSnFN<1+RNf$fnSa'$Вzk$t#GQTUR/ xa 1BĉnݻMb[mNI 6yMSo<tX8 4P ިoI'I ĂxYPNzPf^Ya9F4#y9d!'(8#.e܏,H.#ӽ]t/VS-/mcW] оUU^T% q6ĨtIgKh[(uȒkI "cܯd gKhї.NYa ilYŖ9d0iXyS{zȷ(KYa hx=9Y8ʫpݖkhYtr{a)ͺ_*>ڗJ1] :)}m"Ce<+a(mƁm@L)#m*3ܦ܏)#mr<܏)o#mr<ڍl/ӭ%xm;kXyHI=vG4-i ([Jc@2wU3헗mziCe򊈛ȨW;$em8'"K:]@@2FR)}m"Ce<+a(mt6<+?~--yy[Yj_6";\򼪸:F3mƽZ׸F W("STi NRYPRzֵUZZPDRmikZVUj($sl@)zEzkZ֥BZQJ^- RmnWܼrWXX{{ԝ޽ݭ; RkZl`$)$!I! IRHV8IRHBC]Wwu]WWu>V$-nU;&,22x/Lx0p/OIz*EUٳg7ݫK\;  iHFITbz1E.(pfbhÉ2SvgQՓNd+P]t;ڲ F\I , :vxO:\Lqq7vВ MàL{T{a'EP*AhR@D2*C # )@ĕd Uda2TʙVUe& e dFed$F1F+mb&"`eF#VIXd[`0aF&&*XV&&_ٷrٷWߕr5"ҥ%M*XŢF؊HTWw[6 ghD@sçiZy!/pԥ!B +VW)$$JSJSJSJSJSJS5kZֵ,-) dJRmm]uw꤫S 2Ic+ +Y)AJ**p2`J`PAEHaI5BLJa0H1 jIU*H"4)DQ2U&)U)j5!+Q%jZUh*QS,L:)T!Ib0hDDI2)G Uȸ*8A P-T∴`2"UQ J5BЩjRjJC*̖d%KT蕙l[dVf3*El["ml[$b,Q:22wUj 덛6m]WZ֗*'hlI?G ?=>*GOe{P={^z^G'b{Q:U/>WEuT"O0H0JF"Y) ?GT\R1EI(P)ڋemS..Mi#m,)+!R`S :T%_Krڛl];{)2IN(H K I-;l,Yf)$!I! IRHV8I 1 !Y9q9^Uجc^UyXץնGBNtԤirZօ[8)$!I! IRHBBbBwv~2dDȉI&L2dɒDDDDDɓ&L2dI&L2dɒDDDDD*DDDDIDDDDD$DDDDIDDDDD%QEQEQEQERDDDDDQEQERQEQEQJDDDDD$DDDDIDDDDD*DDDDIDDDDDDDDDDDDDDDDDDDD"dȈ(((((""(""((((((((""""""""""""""$UU(_Rt\5zz9!ZW~6XŢ'Q!sWUr0F ڪq&$YZ(R"):JR攥$XR#a^BmA,eB%lHRލi S[Ѳލ!Jtz6[Ѥ)NYoF1kֵ5FY F5Vލ!JtnoET:*㮱q]q8g̻rѠ}[}uukth 3|ku]h κmֵ:SֽۺRmlmkZok[ezZ׭xVmk[mR[o[*[oFm%lez6[Ѳm e-mލlxYoFz6[mA,X5kZkƱkֵ5lWJލoK-o_|o|o__O@bHX 2326ff`&d̴ p83--33--3lf6N'efefefefefefemL&iiGU{W^WWW=Uxpm6pmwkyڼ+׷mK)lUVm6F6M&d p8Bl6f 330i8BlyhUVǘ"(zԖ6{۱Ԭpl-,X232323232326ff 3X'eo/_%%)I%%W]tK%kZZPVIX5[}wP"LW4jL-l̢6Y@6*if R|{Ԫ%<ڀ) (4ʽ/OI 0KՓ2#e&^+ d\IjFѶ m4mIm%[Cm0Y2KUҬx2ꮜ1*Y1¾VWkV081j%Ypᒾ*hrpmj-j+[j T%QQmZKi+-MP %5DIEE+%dY1&̤SeKhV"-cUbeeF>e 0ńR0Fc/N,\F;'Jacj2e1WÅ1Lc_LzpGG +%.w"dDGUtV2a'K$d2FOFUXȘRLʨJ8S08,OLc!N3> KbQ=08Oppqf2&fdRO+`~v+^fJj8Ji\0Lv.qҮXed!2]m~+ʘX'aDX+#Ƭ(*26[I.jM02SM#E,b*%RTK%%Zٌ&L0dDK$II$V dmeVJ1#Q(c(6J(DlhIjJōb-JJ1#Q5T P"d̩" "("BY+$RJR%%%%2"%JM6*bQbQcXIY*lQ5h6B hEd bƣU&,b4Xl FjFeTȱYR RT 0 )~Y0F~38S S pY Y^+Wڪ!1*>:.1`Á=H`(,&n[1ֹTo{W{^ :9ޝ.%;;{3@=So;ٚﭗd!}OBÏ7v}CQEcV#NN`nlm6cHww{@== b1o1nӎ!Nn6}~;A{v>i}^ †d)Or$)i!sĐ995ߵ~v\ vvkӡOF"4HHyK $#]GW>@onwYve%u "I/~~I$$<{mI$m-> b=EFI$I' f%h!ٚϥٚ&mK{xm2d=,e} 9oаq8`nlm6nlmϽ}Ͻ;`6qm/H .}m[IN%Hzt q' IlwھPb;>~{KCNNo^bAMmh޶ h9u-}m-]} { ˳^S]4vӺIyBJyY#سϽ}Ͻ;b־}kmo>m;bmSYwVt&PIvmZX7Gz=m$N}'`>0Wlez_z|B{*nztՖbϤG{vn 'k#,gSkI$I#Bk#0ϤG{tMI3nmtXH`xHz@$!tut$ބ|Y3Y7_>HHN_>}cYeI;51i _>I !{z5v ΋mμI$Oo>;tLVvII$I#H=ms>ImzXcu6!f1{c }{[${Zyk_o>cW־}l>}l>}kƯ}$-H[oٶb:Hto0«WW8}6ͥI&"b7ĄzI!bm$멷IHH}7}`K}}FszXcu6!f1{c ?pul63f26m(ʾDQ|6^Gj_j+9E"}]wty7"NGo#^Y/U,gXu c F2GHg (  (Ւ1=:FHă8 mAB@D21FX8PAE zDAEASm淑ͯ+ k^p^u)wvޡyUٹfs3f0l͘c6c ff %X͘c6b(A<(_MSVV/Ow5|sˮN6W]rm[ۺƋ*k%Y/T4j,].6bdK}\S A2i#F=N;wmi#LJQcj lljl#AUOUS(xUuםussH%"{po=75%0d pmI#Ii:kژڵjciwQu:7pmI!(KN;Ai58%؝NKʱ+I0axK p+V+3+x(bYqu$pX&63+ NB'KqZ5rhԴ'TQQ1Ta8B.p+GQTKR(Bp;N3+:KqVeY]:&0N8SNGbx;Y<^9$q:]B, v<^ /U^1ٳO+q.<%:U*s-*E#pLK UQ؜z2ԑG1$x㎅. tpYca(ECAA=R.Ռ1,qabxSœ8Cr2eFeg fgNKž(])'tUxRV[q/ cFNeGO\#Ki;űwEckM[Y1x1X藽غ0b]6mMۧX'>X1_L ԉ%|NeGON5-1Y+LeGUydpUV`R 'WGSA%蝯C&K2D:a-dU'UQr $ %X͘ʂ$Y*30 * LSȚVi fff&JHd430ff"Jd4JI 330f 6faEJ*Vi,6fe,PTgXsY=۽{l {o{©   $ %YY %Y %YYYWwzݲƭ*xW6VݯxUUU6*6**!*!*!i*T*TVJHd4[Vך6([-ѭwBHax ╥jխYjj:ffl a30a3*J*T%Yٙ~ 뻗9\71AY&SYlYu_p2N`5K)M@4c-P $_mEA@w(AM@n ҨPP%}H@ja ha=' 1*TM CFFJ)4ɠ@ =R"S&Q馦FMJj2hFiRQDJzoSC@dbc* ?o,%?^Tjf@2FTF4ei#IHkclFԚdA 4VFlEI#V72c2c2c&2c̘dfJ̫,c2,c1fU1U{6ƃ>8`ڍW Z mKlU\•f)F#m)l6k5O6ڕLe(ͅYSdl2N*3*K6TKjUYi -mU+`k 5M*llBB""f"ږbŵFlkF***Fƴ1m-Y1K5Yc23ddC65l&ŢYmccblXքbګ2fe̙2K41f̒m*LDکVLB21QD2ebZŌZ-1e,#i i%%Ie%Ԗ,~8a2̰SjQQAQV6cQ6-jKd*+V1"$h"YdFJKe%%K%)-lfa~ȲFƘE3*ڠ0_JQfQmd(M Ix-m֯+LE=E% )k)lڥo}Jʹ>빵uw!_t5-I. 퍪>qUw|1yf_DO0FY5U6zWzlmEWjIY~>}ujӶ̼ōr;Es(a6-Rt|SZXj˃fWŰY,̫4Wj1/&֒ mVu) Iz //ۙ={^Ɨ2=W\%arVKka*F_KEL;K.bʭ*aJ'-KmkbQZ;V훶KXfMfbMe&>jǏ\Ҷ#lwͲ6+b8_US8˜ #f ϻ{rz89wݲ>-E*tv4 sNyȯ*e+ʛFr˛F%8-vO.)ww:VUx=0GRtk]wڨLyR5= piK޼-er˙; iGURR+a& mY-QhAr%SU%phOJ/J6ml,ͰhɦH5j1F ,(54F"(mK%Idҕ%IIjK`KZE(Q3*b$"%J$)))eJSiSmQcEJf,2mj$ht,Ri*JJZZ4h&Uk%ɘLj:\Ы̎.fИ8GDȑC5S1F4jGpS:Ep~.Dj,5QĬ^P Њ1`++ш`+I+~7x&D7]"dIw&D7]"dY" cA&F`XSQ/H]`5f#jlYkԛUT2 cDkcY2kVJimlނ1Qc11c1F1c(1Dc1c1c1c1c1cȈ""""""""""""""""""""""""""""""""""*c11c1F1c(1c1c1c1c1c1c1bVBU*ЕhJ%Z1c1c1c1J%Z.1c1cuc뱌c1c7]v1c1c1c1cu1c1cc1c%Z VBUc1cĶ ϻwmcwmcwmcwmcwmcqlM7Tn8b qb qb *׻kU|{@$ @$wjQTm6y@$v1Fؚnin㍬cT`-۝:w$ o[_$3/~ ]ۗi}o-Yer`ko}]ZrZ-Ej eHVhY`_(QFTع"Pѵ#QhVՐ-[*!6 UͭZӻs/V1ƮK]0@2J5ݱ{O^ʖtmvӾ8꺠U;z$ޯir~m'w',mll_n}Wq49#{z5+;9n=h]z5w?z.ڭV,m]tInU\(._D| X8Y:mjpmdPM52-LmO6vO u$M5}Sܜ;=uƗoޣG˹  U].%"КY8c\dII$ZE$HˮamMSֶЪ+{yxmQU]p#5ؒ*@bK d!I8`PI5d4'&LjͤkėilLh NE$H6vA6|.^xu*JivhSO.LSK.-+e @6wK\my2rȤE.O˖x/]DU\һanu09aPnrYUm  ,KmNdR@mfD &bKc݉.5v$;-ؒY˻OO\oxQBMZm64c6.Lܧ2) 6|Kd)tLe-9I] ,U.foUrm;);H!U# JK GAT@YBF"X`F)b2RKa"LCPdAj!ZC$4b Z%1JbQFQZEa)QCH,ZU#J`A`A~ԫ?_;3e/V+Ey6#a"ұNA )=c^r3r6" " **" fffdYab" *=;2G DRUL*>GU$TŠ D-H-B!*4B+Uh(aPą`QR# B-UPU) )``I^HW)1GIJ\MZB @ H/v[D-xUF(mCp*%qBU'I)\J)4$S\ RTBQJ(@_(6d1RVUXbʬabc &je3J`6[ h6SNt*4'6aJ' DN49 ![Fɰ؃8/s*JtSd%9L %G (>bJ2RʅI,_K}/>SҖ0U*Ea*"$:bőRt}>O2UL,JMI[&jd_BAU1ĘFba(SH_Jԏ ˜MHx^}t)' RUT~_n:nێwٶWeUmTb@x9n=ѵT%MJDH( D/.p$B{;Kc!uWww\H H  H>Uo""""$"""""H""""$"""""UH""""$j"""""H""""$TDDDDDDDDDDDDDDDIY6֪ȑ2Gy&F${񾖾Q\D@Q6Cp(xyD(g3 6$D$ @$D$|U+ztDD}}3 ]5#I2M#I20"#ȋl"R4$U $HB4$U ˜ڵnD$KD$|UoA^;5cA2 ]Ws< H$ WH%ں£PLT4$H"RL4T"iȏ{9DI2!p( 6bh"Xx>8֝JBcXZ([EJ MjZDV#B@@4q'HF :m]wvyj{{9 Mꊊ8 €U,*/S_JF+ݒ9FS)-W $sh7 Tԓu\6\V'$sj#q)(gP=0#00" °ʵ-BDQDQDQDQ[v,;DVqYƳV)Fv-+i]m:aVV)VV)VV) 2h S6>JJPH  (ҟQQp :Pj F8(ih`4Jy)J h'JR42MJ"J!UԚYfTl͒YK6IfTZLf@2,́MNh6 h6l bohSB Z ڶ"VLM UV `6`-Tk[YVV6 Z 2TжѶl`5EUmiM*T1Sf4B^i` &FQSB m%(%,ٱlDSb4mb-^f`,¨mmkm >[i66ll?,^aJÊV֪ٲJ̴i }imPa \bYbTumO镦~fRQe1Tb,BOFԩC uhˁ2g\S}-5alŘʰ% X^ֈj2c,/ffb&d$~jGZ4<,_=wlއILjɝ1it^Xy:1+sSg!`p+%.?i6 ,|ԓ+Z2iKh7Ah=aT2%eie-S{SF-Q~lͪfi>09 ( 3>ZPwZ:'Y]u2)Y:EᅖRƛuɦewW*MfN͚N<3+28uq0N<< V*Ɇ VLe# KceɕfYd6FR1xqr\uzh-c!Բp"#Hk3+Ʊ1ŌK`mK_U.6M hb#8ĸWU:ˌL`2 YS<{ciԼ:˅9jy:i;j]<%ܭ_$^TG4z_ TrhNN-,+t̮Q.k\gY^*{Dh^;`ѓ'jWfKi5!FbX2WڲesnKBFR5sZ r4 ړhJTR],&KBZ WUV'],X*G&Ph)xbM`ͳHҥS)12h?T8j &dɓF(~DNf2id 9fhL`5`mi KiZU*VR2F  8O6lDDDDDDDDDDQDDDDDDDDDDDDDDDDDD1DF""""""c1c1뱌c1uc1c1nc1c1c1Qcuc1c1nc1c1]c1c1뱌c1c7]v1c1afͅ[Il*ڃaV T6tcM$!h0rNp\ ݥFESWݤGK:{@ 8ֺqG,WJGd.;0zwnUҡh *:ꂮ*꺩h]r5]΃țwy۸5Vwk;Q*=Yݩm^ z/v;+Qڳ@ګ-LhhZ:2q]hZ:qXsNYk8Dab2r4Z:N:c\-T2pGS@Qt!!ڄXdr1.NPtSI& `jHh54bA <Vj1RtpMVѩ#)QyRW sq:ˬGUxڼ:f[Ȟjoc<+.,Jz&*h-5eiZU+UHUV "$DV5lR企J*+i1ZGE|>fÍG I6nR lKR%O(R AHDR E &T` L a&hF0,Zj *PԆ$1!!+T*bTCA `&&$DJR””Hb2R b1J?C:BȔХKU ԥh ,`1RhH0*V!`J`,$)iPrBͶaY:֮G.dٳl0&DF""J"J"J"J"J"J"J"J$I@"J"J"J"Jʥ 8)p".Ut&)\ TNUAHVH? * #F6Teb`d2YL S!jUU[}ZAAALde"$PT#)Iȝmf3,dC̃e[0Pګe&0((2_-eJu$#VhV^"s5O"WjI䃙JE҄)T9JRJ E/2HIe`(ebV+L*>}I/>_& "2jI + DW000bY%S$b$`}2c&Q!WyJbdRa*C!LG}јb_UbX0FeFR1*2& LɊz$U|4f10 L$u{"$v_#" H>nszU "'ofaT/zyjjjRmʽI\=|p!@m?B#p'Xd[6LCU&ٰ1lň`[Zb*V~l+[zѱV[8-ob,l mFUYnUU&漳{ޞ%W6ƌ̪R4|UU[mUUE>k7o^=<{١CPy^v/- mժKh5m6 Uɍ Q~HS6ڥ/&ڑm֠U[Z(ZZצ 'r#ZP=J\+p2\䫘f$Bڄ̫iq%T̋8ٟG-/|Ԭsо1{^eT|H-_6yQE~iWipC؋1)dzϸL\͝eUamVorsUM g؋'ڙ^lWʵ(#W' |R5Wf}:זz‡,ёB{1m^^k}叓f[46rsB99څ7)Vl*lگȻi6~!_3FW#_j_J_z|u/a_JCgU|Zf4> 2Vd>s旷EGf3K={|%@hDdqZF0_U.Z+/p\jrqȵJ| bo'Ჶ0ѰڵMYg<*uqz!&0|2+#+mUDue_Q\ mUssW766Sku|||>R? if6.VVFcm[We]Q,56Si]BPH H@)6$hmcQZƣQj5ZF٭j#YZFZW{o{>ߍx[x:195RuӦʽ,Qks{F'!&ܵۺYtMK*Jի} v7tbrk[ݻ::>Q{f;RniS̀MP)PRd6}" z) BNQPU#M@aD@#M4h5;mEQZ6UȰ ڭxjm+FD $fQWST%W:J]uPlUBid-"f])Y=QO ).l'K(> .-5hMilY=Lzm^ Sa"~30*cv-$)T5CҺ28զq/& bڛ*§y,!^&'+UWFJfmYiQ?Ol)5_ZUM}W0SElH_Bрf1f'ߚ|;511jS4f,2EVI u͵!%}CBOUOZ'SY?IdI}&|L&>ľKTiq-CUK<[cZ34E,-!KH>O鶱RJVIL⤿><+*aC*Ɋ 9b.182$*p<1'/ (b3*a2E>1TI*J\ac2bQO2b\1UqFa QY̫2ʘT2rsq\k)S7 s$ʜR"*p'2/)q)qȾ'sy+E)}aXaL0R_ӦҘm-YmIoGh^y㣣*> yGGx$x::8‹.S<&L&L&Oɉ'ɓ+}ώW௏+28糇98A{,k m[ٍs||]uyDydi^3ӵ]]ty4|LU |Ʀ<~ 0ad9Kj_R]:'Q&G(}yzˬg.w#1c.LʶVɚ$ΦSIj,-,KAk+&ءVnv`4@SbWv&$ɔ""7r'ޯP 4KKF22244 a/PZ"""""""""""""""""""""""""""""""""""""""""""""""""""" DDDDDDD"1DF_X1c1c1c1cuc1c1nc1c1c1c1c1뱌c1c7]v1c1c1c1cu1c1cTmUBl*UeƖz3g99s.naiQeDFŷi^>{PxWKqqWrs\+7K5uٜKxZY!cjuМuꀫ껪 yiJ5#PUuȋȕcuugvfYZ^EFsNpnli.hFXeFWgq5N`UZѷ6sR[TV$Չ5bMXxH𐪒<$*)Jh$e2k& d2lMLFphKLMɰ)pjs0ФMtmFE4@mTXFh 8VVj,ej`ZloA 46UUxL/wwv0N!0ӻ;wwgnT)$0R;*%](j,QWjVQZ GNPp r8R8 ].*>jG*h\Qᒘ8GTuupᎉjJH 򤧑1cSzK:TQj+&tZP]A謻 .pƗLpJ\,2QGH"vR= "OXIqi|ō,1<\]px u2q='U+L-U4//*/<)49CE2+\Ry+W*Z|P´PecVVWUJRp:rJc(]0Th^];]jTd)>(eQ?Chl\9d$G-ͫ}J+2`JSY,[Ejt4ak^**LN+&/VOHb*4Qc"P+MhA+.N娗H4N]ȟX&*j3ѩ++Hּ!Y^^9TN֧hLW="_:)UDҢD+!HʊDФ0J(EUiCJDj -TJX!%D0#VD* 1BʅTaTe*RJ !M $JR$’d( QHXdYQPj*%bB)%0IP0LPVJ*hQY$Z(OQ,UNjDXB+4]GyI%E٤F F! DlD`Hk`$ Ҁ+rRஔ tXG ZHIX TUZ%_ RGE6 02 Tͫ}K3 8G"+X %E/'|ѵ=kSIyKmmXȾ'J У⭪s:T|(mVKO9G|fZU'99U>UmmO9§B fjzfD9":ANS0Re(*R~G,C#&PZ5%PAJ0_)~R+ QTj EUj/?'1ZdaXQF)WRSrU_?'JPĈȯuF9ΏLdʞ^yTK 4R2&HVHmmSdLeO/= ILVPSTg̟\=ڧ2c&T*PҨb}ת-|[jscZƭW7\֍^p{)J9rԻl $lywkTRmMtMzީw7UZUUUjiUQjjYZYZY۷ww7mR_HhГO6VڋcQh1Zc/+ʢ8-nws&;.Ȩ?8-o|$]{Kp4[{a-vknѕUf *Zo,o{ UU|{h}޻Km'qLS)e2LmS*&[ae2LS).LmDl--S( PVIhAw FgX k*R(*(7&CTOiU*~Ȫh=UThI꒥=@S Dy!"T= 6|sm1ikLc2CChmf@L1<]|@l h6 ˀVUUm҇%m)RmRʆ2e++"MO&,[)LW4UmE oǞ<Ӧ;w#/j{D%C<^)A_Tu2+aG 1XLC&Te#&R2BL$e0V+8LLVaLAuLbbO|9p>qaftfxIyIj=}}ϼ.ntO|Dߏ~rK\3yZ%,*g|bExM2HX%tf K` quV NK[!Yj@$^ _4 ̥Z[EZ  m-߶k]jֿDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDA""#F"" """1b""u1c1c1c1cuc1c1nc1c1]c1c11c1cc1c1n㱌c1c7qc1c16w7[ l*UaVU/_9s1'?.;.r\\˖h/Lxs9);)o^Kz[׽wnݷsZ;{{wio^Kz[׽޽v]ۭݺ.y<՞y*ڿz},͠@$ A H HVjo=m`{۶ݶm{ `Nmmf۷l$@$ _ JV* 1ZVR5j1vMeqZr*+sd0XeB닱]%v;wi*ӱR.ؼ <+]sǙO<{)x@E:^Sk4J{#S x(ubZL^m✡3&&xNNwZm[mU@nmwmͯ{mͩ׻@kUƯhj%aDMGGFѳaam6fTRhhҵJ5*-+TQbҵJ--+TQQREFJ*V V V V- ڷ p0ڷ*ȪmՌ5- anVanUUUmm^  ii(a# w! <} ЕB0` T{ iSJ =R>_Jro{s0q1K&\mDDB'!Q  WA*$` (# !a0L`+0+0Q0X+`L 0( LQX &0 +J%#! `!X,&Ia&(`P`%Q`0 ` D(`B BJBE] rm#$ A HlͶD UVmlQ&QcDb%%%"J"J"J"J"J"J3Iº PK:V$`E%Zp%D*KI'͖ͫQ TCVɊ}D :+< :8OQiP49 2CzzIU 'K Cz=(T)@=2 Ur @:$N)HOU@ҴR(MQ *RӢ|=bʪx^^]*tЪEVzzW=-m1x.g2d6d6δUEH)jV/ǶuIkG*döۮJIuGmVjVRM,m[ 1fV&ҵKllTjy۷^bQXKvmkw[]w bQXKvmkuehTw @$$Ak-IF1@,1ű%v!6Gҕl)lv[YlXvm1XQDDADQ a!ZXZYief!""F)横f!""F)横f!""f!)Yf!h~)Ѷm@ ?@0 _zԅ5;#yQ@2 9ވ FhiUF)J@1'TH 44RQJ 0 J"%M2m&&mO9s_g3DZv#Oyʷ[e:IN>[m4z9| mskş.`+FM"+j6Yhm ͍*zX]f!zj35pLi\QUOWD!tx$x/U=T*Y^DU=^+ʋ:HV\eM-_,+S6jjY]jqYjnE&MwJn v֭xenu8ffYf[ S4NJJg6C1WZ/ ڎKy1qp[dŪ j+WP>YFU2BXPEK)#ZZP5 '`ZSγ6*ZsVv PVY"Rll*eTTeMYD"[mֶꈈ"""""""0DDDDDb" Ab""DDDDDDDDD"!c1c11c;1c1cuc1c1n㱌c1c,c1c1cu1c1cTmhTm aV¯y^3K,-dDݻKeS5Ymuȓug6)yAH:^u+^ѴӦ9tdN PN۝e7Zs9vdYκ]b;nݲa I HAI$BԌHDR\HD-H \NEm[gc:9]u̮es*v29 lsCND[\T%!9msCNG%sӿ7ޒޗI/qV66Vշ((M ֭Uo{ivt- :tDv(]L$6T5Y^TUKu%ԤNe*rǔ$:baK:'BP#=rj!WBt'BPO!WV_u=)!^Gx I(S`{MawM͏k{׻܄.^HW„O@W/@=*}De2 QUAJ` 0`#&$a0L `` 00+0抯#y"0+KX+aTV00R, 0T` )LA6$$v(t R. @)@*lVp(Gjٰ@؈RH6"mSb.NR$p , Qp`RUpITS+IRQ')~(me*!] b!nfuuʾo3elUxt]$t`N0+_UIKJ1JB,O}} >OQSUR*,%CA>+B-C"he2+*C= RU\Q(^@ԁ@J ]UؠNW}V*a*R2G TCU H'uh[Sn6vi i@66ѼscZwmj$`{*^T!_sV^ڄVK:gQAK7Ɔgf`f+UZץmSm-j0cd1 l?mޯ̩uWvZhͽn=pdz]*뿮` UW4k[jʗV\fһU`7vޟ%/ԕkuyudDDDD6mmmPPD@DDJdMfWq);ҽ}{`QDj@ Mp…T(P1BDĭ`ʙPi@Y`( PV@HPP(V\r`i2b 6UHoRz1 ``$IP@5*ʪhIE4M*$I37.[lJtc>㻒.庉N\Nwkts_9;Vjj懽%j懏9[zϧիr~m"=REmbNϱu{j6>DyrCm"O޸wcڟ@Ex|â25^r zCRKJ#kFگkZVl£ZX h EF(ZP ( o iAWx;l.Zp 0` T b4hHղm5 _Ocx~ÇtkVZχgggavu|5M')OTǷTzg ċ*u#rw.r\YeUQw%ܹTUUUUUP*=' OE}]\]\>;;>G_`U?ļ yG Ծvy;/]NpKWg/RU{G Ծvy;/]N8^ʮ'sq/RWgr\5޿LK/X,@V~KNq/Wg.Uty;/RWG.Uty;/RWG;/wUvĻw;Ge]zy;Ns]ƥe+xUkC#/V//?Uvr_u2?P>--*w=@KWGv^]Uvy;G ]Uvy;GQEZsMJd~HOMF¾Z",b,_\N*0곉P.0%긜DY~S -iKh]Ch&6YMkZ*RVFV0f$jY$fC&0Kq9PYU䨳+rAfRI긜a/VbLRLZvӣiӦDάQ Las-jɊy)`fj[JZnXTkI^'(T2WETA^"*3+q9D_Raz'"TRb8PɒemCaۭ=.Ҁ$niͶRl)[[SMj"( b{2C).%1{+8\sn9a²Sj-jN>%ΔI=[SWcllZ6d1bU+KHZh1X)T5%>0\)[TqYqSVq\U\hIݮ-jZ[m59,ך7]kͩi1 d}U8hT/_ǩ1Kj*rewhbI]$ɔ$f2ʑ b#ejQfZlbL"51h5+)Za#fōZY$Uت" kmTU?"""""1 """#DDDDF" 1DF" 1DDDD`DDDDDDDA`A""""#b #DDDb"""""""""""""" DDDDDDDDDK1cwc1c1뱌c1c7q1c1c1c1cu1c1cc1c1]c1c1뱌c1c7q1c1c1c1cwc1c1뱌c1c7]v1c1c1c1cchmPT6mPڡCaV­[ l*mQffgrqt2M<(쥞^uU2->>WĜ'q|wxNwݮ];vTj8T&5ɮbm#|MKU\8wnr+ڈGNnf,sr+okL\we#]o/aK}\.΢GWvꢋgWa'F&>Ny'ߔ}_$]%#r}9Uĸ]%R]IU|Kgڮ%kH}9Uĸ]wUWh.:?U~Kv*zS\0](.x{U^hRG4rpGZH<=\._ ELiʮ%|y|ڮvG˚rtr]Q//{8{U/: QSo~>S^* }]A }sNNUq.hR^_4}=\..ELo4uUĸ]K/{>q.hw'ӕ\K9U˚}]OW_+ Z̾.'y+⠞ڮ%G.i}9Uĸ]T^\_~8j>ߴ>%G誗zSO # WUt'PsCV4[W49>\tmks|nj#w'ӪvU *E < U}BEjAU蒪X&`Z@:H HɻnO*9Ur!Y.|,*/*y$R'(WIt^W*ȋ_* ℝK'gu]vUq. 1Wy'+BOS""Щ F-T ZEKF-F-Y2eRL!2 XhLM1jXԫTclc+P1c000V jhҵ54L5j,3m+Ji0`Ս4M21bdJ͖YekfM& Z,##,KUjcM4mklXY-U4M21bi0`ի,l+Ji0`ի,mk##,KUjcLl+Ji0eM, , k&%& ##,KUjcM4mk##,KUjcM4lXY-U4M21bdV4M6i0`ի,mFF,Y,XƚiFF,Y,XƚiFF,Y,XƚiFF,Y,XƚiFF,Y,Tٲ,,ԘdV1K%V1iK%V1dZUciK%V1K%V1K%V1K%VFF,Y,FF,Y,FF,Zik[d2ĖI2IV1imm%,JM& 0jՖYefTiQ`cik[ddbői0`ի,lͲ21bŋ%ZM4Z##KUcbڹTsW+Eb~%y͵-EVG22ls#[)9qWe2\W$:u Ħg vtN.2ؓ sE]](WDV+ 'E2UbDiT0NPh䚪Vp"B,ZH\ U+qP.W*qE-U#%QMSFBF$T[&PV$M$*,%G\Q.JQFK|1|TXBrL'q,X,\ C%!•8,P1]ȕ”%d+"V\)*XɖLddE, Z(G]GH}QԧQ eX8-N*qBrLZN", bc%K ¢++qJ"^]J9]#ȋ*+D\R,LdaXTYudJ˅\)K%J#K%%5PKgvTwkFUrNjnrq^Hd(LL) Q21 YLIJ1RDEVR`E&IaR1RD 25!2?A\12W'U]]e{ui]]e& W]UWjщd(crMS%eYLV,b,"]hb%5ZZ-$> lchѣFm1hUQccm[ScamM zzzzu_bTxeN,즕tW5s@;!ZH;|y+ eiYV LX8#2m[W8e8+뫢:#&c|#Lv "ʢ"aQUZ EP2H2Ph*ꗨ\$¸sU] ]+RB,jF5I:p%cX1N8b9$ j ZA $ @,l++LN:]Wj`vU[TU\uGe]]"WEDVQ;FhLJ.8(\e8*j㢮ڟn*^?WõvvyÇI;1}x佪{;k/]NpKWg/RU{G Ծvy;/]NpKWgr\G ԹU{#=_s4(H}q#\w=8^ʮ's#\w=8^ʮ's#\w;Ge]zy;.!|U~hd$ҩ1~ &+ ,+^QSTꄺ]=9US*-^ILz|rR^˥].8:zxBbƮƲjǶWT^G`~u2+D_/-Pz/Eڂ|>O}>}8}>OIDB|=jZֲԊY@j^Z.4)KҞ.*ұ.'zUSÎ_RWtB{u I_W q=USA/*XgSB!O~~cJZ@C|J._O}>(}_OEA|>/%OJ)p{LK>'ұӉ ǎ^Zj1]8q0NK촄/WwTⒽWC{:u2`TuzbE8j|r+=_8 ~'e .K ~W~>9tG9Vr 9ۮoK_QU⇉?I@꺝H>Jla;Rދhhi֟R'YȾd_2u!^x~ⓅAHSHꫪv]j?mdejC"W22T :R:WU/Ăҿ+~9;;|m9ϖ77>_/|U[mm UGY(f,ljDJ^%҈bT0jBVxY҉}+eRr\r]Rоw0[o[-ݬ/H0[o[-ݬ,B-hm,[h7]۶\ @BA @Bն-@$ @]m|US5XPٵFCF֑B_|_lZlSQlkA[Cji [+emV!ڌ0[#cb4[#56X6emj$kirK^{oȤzNA1;\#Qc|c^D#.˖+וiQ[l]heE[rHA1;\#Qc|cY"He\ʏj䭌.leӧ*5#bDcnW 'ý׽Wyysl@o65$v\]K Kn$>9mZMP[X'Z'\֍Zv m6mہfl m6mہesiɖQD' ICI6eQ7@܄-[km䄄!mB[m$$%! mnBm!!-[krm mٶfkm6 uf\YpFl(i&PL*,-n&7s,N@6m% $(B(Frm#w92(di(i&PL*,-ICI2((m% $(B(PVIYA> Nǽ oVhVpP @ z;Ā Te=UT@TA2hR@4IꒊG"J{U?R 4)*dQ6Ciʏ_$,$eZf,%$2ՙ̵hJ3 Y2,́fd 3 YAF`ڍTjm8}qw>;] h6 h6l h6fUU*hUGqm km_qCZTea,,JYl)eRef21VeAaE%tG \:]uS|\|qqOWqq 8>z' 8>@x/|^~.?@q=\~8z' 8>z'~_||q\}qqOW\@q=\x:'@d^:|]uS'uSu* @?/ͳ0ڃY)V`Hƌ ?@ ?e3m,`֓@ ?+jVj6q[UFbm'A~?`d6Md-@@~Ϸaifd",II+-"D_mkuZ߷DDDD`""""#b "#b #DDDbDD1DDF DDA#DDDbDD1DDF DDA#DDDb""""""""""""""""0?1c1cLc1c1v1c1c1c1cu1c1c1c1cuc1c1n㱌c1c7q1c1c1c1cuc1c1nc1c1]c1c1뱌c1c7]v1c1c;1c1cwc1c11c1cc1c1n㱌c1c7q1c1cc1c1]c1c1뱌c1c7q+j y T6mPڡCj T6mPڡCjP-"E8:@pTP uRu뫩ׯW):}@zzJN:P=zz=R^^T(RxSRI䴝I'i=AJ6뎮@UR\\OjP.uu?P=zz=^^h㫩|Oh@zzO`uE*,"e@I "0P2eff@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ɖY2eff@dLe&Yd@dɖY2d@dɖY2efff@dLe&Yeff@dL2eff@d bڶj*›Cj6 %l V%XɚQHPU!  ?~j%W'^"^/ x)j+"^DQFDQD4DDF"(F1F""" 1Qb"""""""" D1b!!Ć@rD:R)JC$E) ES"CT!bU1Hb*Hb*b*b*PdJt2!D8W\UrG EYqr22*q 1#C::.>8z 8?È'' 8>z~ >''' 8>z' 8>z W?WOOW 8?\@q=\}qqLj 2qdOz_]@u>.>|__]@u:_]@Hh AJH 2'__%%%%%%~E^xE^|xE/"/"UWW++ɄV,jP)V/S S rԭ xYuאԭ z\^vV=/WZhS(ԭ z^^ @>%hS|_?)/Ÿ_ S)*=Oi /____Wx<<|| YeR҃?"/"@d]uSx^ u)+눧R/OVzȦ@u+)ׄԯKSOį)||q@|J^"Oįq!}?~?WQGxxh|~GE>E:X)^"@u+TOPz\\E=zW)"ԮWN)W)׈įq.""PSSW(fP҃o|?9wk>1-[_`Bg|88888> +1 ~_ǬC1 e8|=qqq}}}}}}zd~RW~)/PW>=BZ_aO"G?kmmmeUUS̮s;}8PUUUUUUU|snsw%TUUUUU@U_ ĬmmX˼xͷ?ys2Rʪʪʩ̚Ws@̚Ws@O4jJڶm[Miei\ѩVVO4jJڶ\NdUUU⸮+-i5sF ⸮+-i5sF ⸮+-i⸮+-i⸮+~Rc}wRv(lPءCb 6(lU87Pqzozo*q\+s8zJ{޼?_]ԷQ\Q X̩6(lPءCb n㹶8A=鼪+s8z@W=*qUӷq GPʶ=ڎڎ GDz{UUUUUWډ{'oWw]=X;J{ qMJ)A5(8Ԡ⚔SRn,W=l+=zW`q\8zP;e]A5(8Ԡ⚔SRjPqL q 㦥Ԡ⚔SRjPqMJ)A5(8(8(8Ԡ⚓[筁cUW=l+=zW`q\8zP;e]s`qC筕v[筁cUW=l+=zW`q\8zP*ol1AY&SYYI[ `MJ B ΀B(#ͥ @lt 'e0 @6@Pt (  =4)@슪C&Rɵ )ԪOJ&)('TAW|~mkz6Ч=z6|r[-K6If4%$dl;Uֱ\ַd 3 RIfBf@2+Uw^$iY$@8g;Q5>;]Ƕm>yW6>zu}m@ 4`Ph6l {5յVsk2[j/SjZQ@j} S Vի}klm"e+(c,YYK-[%,JXc)Xj-UZQ\qy5jqSMGv1P3OOqq%y}ȧ丿^ȧq~sN/Rz"^E8K뜊qz9./׮r)\_\SԸ^j/~sN/R"^E8K뜊qz9./׮r)\_\SԸ^ȧq~sN/Rzڤ_O ^9ȧ\_Ϩ/_}/Sx|.SvQv$9(O$SIJ)R^O]T^I_KR}/R./׮N./RzZWFs52f?RGq9JH(f?Hq9JRG+Pz$}fffd @T0hѣFSU0em&SR%'+ʐu$zO+!$zO+!$zO+!$zO+!?ɚ5:6:nXD͢ōZJu7kQX,-TҖ[n&c$xLǕ$zLǕ$zLǕ$zLǕ?jյm[MiMm)f6Y[4ֵȁ+I[]wU(j65ZY6k`ZmJ3N&Ml5L˱N\U[3W(OMkFZ-B%2H$#el@ۦY@MIj,3ZY$D@խfխo#b "#b """"0DDDb""""""" DA0b 1 DDDA1DDF DDA#DDDbDD1#DDDbDD1DDF DDAc1c1뱌c1c7q1c1c1c1cuc1c1n㱌c1c7]v1c1c;1c1c1cu1c1c1c1cwc1c11c1cu1c1c1c1cuc1c1nc1c1v1c1c;1c1c1cF1cc1c1v1c1c;1c1cwc1c1aV­[ lSaV­[ l*ڡCj T6T e@ϺԵ-KRԵ-KR=mlg9{Ru69x)g邘+u:vyN) ` d<ƭ80 :6+ 66k$m;jkÄeTC|ZjZjZ66vvx)g邘+u:vyN) ` d3lcgcg`.Xul5P-@T@T-KRԵ-KRԵ-BIRUUTԝvx)g邘+u:vyN) ` d1rS=米Χ;NyTbz=Χ;9SNu5C# Kowz׻[=v Lg:]KJ8O:$9UxR~yyUƨQIμ/(X./j)}K}OQ%R~uWk%IΠN.Kڤ򪗗^Iʢ?<x_ʯƨ^x^U'r\_%IDxKS^// ļ/**TMPE)YxJuqr^?:..E5,bis.KM@:ȧ u..E?ȑKļ.E<*ȧ r\\||.KOz\"i}1Js..E>'/Kļ.E<Ǘ^""G/^"R*/SA?3qr)Vg\\"U% :..E5L`\\"A=~u}KO\\#^x\ySႫ/ ^"('/qr) u..E>"Gr\\}U/qr)A=~yz^%r)tkVґ|u..C/S?읧Qx/+-+_K)ԾU%%ȧUA<}_1!򟔼/O*_ouW\\"PO/Kļ/*uZ]qr_)(R􂐿 Jh5)VUh Y2eaHedɕ+)+&VLY2b(`łXX1ciX1cVc1b2230SSJ-(bŒbŭffdS"dXkYȦ,Y,,ZffE2)K%LbŒbŭffdS"dXkYȦ,Y,,ZffE2)K%LbŒbŭffdS"dXkYȦ,Y,,ZE2)K%LbŒbŭffdS"dXkYȦ,Y,,ZffE2)K%LbŒbŭffdS"dXkYȦ,Y,,ZffE2)K%LbŒbŭffffdS"dXkYȦ,Y,,ZffE2)K%LbŒbŭfdS"dXkYȦ,Y,,ZE2)K%LbŒbőLbŒdS"dYȦ,YȦ,Y,,ZE2)ffdS"dXbŭffdS"dXkYȦ,Y,K%LbŋK%Lؿ6l4\Ŋ%' mBUm 6lds+C&29l-pc.X UU^8Rq:)v]9aK N:NG('ҡT>aH?%%V\G&UG)#SP†+`&J2(F *Pr pq#8 (b(ȣ 0aC5pa# (eTXJar\r)FTSqJ!rMUFq%R5Dbe(j!5US(ґ*#8N)CQ JLIFQJbj58)125 adXʔEU(WRQ#Djp\R W$Ti8WQ#TFR W)\IF9QqJ5)1Y%5Dae(jrTkq%5Dae(jQFM99ŊJՠ-VvQtTFB,V""$aaH1X0ģ T0TLFPߩD)0U?+Zҋ*#u)#鏧)%r)./׮r)\_\SԸ^ȧq~sN/Rz"^E8K뜊qz9./׮sڤ/.E?ĸ_SԸ9ȧq~sN/Rz"^E8K뜊qz9./׮r)\_\SԸ^>丿Sr))K~}E>_K^%" _St%)QjvM(zOK)몓Ը^8K~}O^I\_]TQO)A%*zzC/C>}}Q>~~?QTQRM*L&!1EGN%0bCb֣t##:p! Z2xN xxp! -_Op}>O}?O?OԟeeR qz` $r0j!BtZ`Ĩ{Q='\*j#Pxj~ WOUMQGʠA5p>=êzz?e}Ë}>}_O}__?HO }h=8qJA'EFJӪ|ӪP< -_9çTDxUZP|+'Ӥ(<<:*d`F(> zN:tUUUUUP*Ⱥ <1m**bJHUjI$z$ ww9zx=]UUUUUUUEU^TUWUUUUUUV* ** *ʀ*wwwwq}P=쩲Ͷ$ʤ2+Z+p$ @$ @& H K\rZ墷 ]@$ @$ `H Hmm#d62lfd[a@$ @$ A H H\6kܶ-+]@$ @$ `H HV65n H H`H H6$,PY[# H.kV5­$ @ $ @$ vUh-b]!hZ6ahZ6}8_A:I |yutĵz뷖SÕ*ttjeS'qW+mGr|CmmZ)ZFlFE FiІj004cbc1b$#V0LbÅ0c c0 >dnp8U9ۊ.*;pP;qTTqW3%;s\r*N\+8-W5lNUh2dV؊d6U C,a SeFC d2x|CeC'2{RRr!0.&;9<[6G{qyz<{:tNܿ&M4ŝչvdNܻ2hqgun]4|Ӹ.̚>iY[yrޘ15eroLlN[f4-' YXyK8\sD8믾sxG?=؎emm∈"""""""#DDDDDDD`D"D" DDDDDDD" |c1c7q1c1cc1c1v1c1c1c1cu1c1c1]c1c1뱌c1c7]v1c1c1c1cuьcjFCjԦ q͵Fڢr̚W^Hۥ@!}Q=YQ5TD硺W3p} x(nfU;9sn犯siTu=s\WJ|<&8xw."mqOpZ **:R{qȚ*yPu*{qsUU8sd sss7Vwk;{k=5W]Yݬ g{qYqn]Gi`/\]jGlkE- m&s3Lp3ȉ"mɜE6݅6`fw"mțck=3={qY B `C+vuvu\s]u]"ecR:H ,u .e :jAVB é^VFiSh+4m++ThYZk_چ  0 w~xGUU]WW"=5UWU'M=Q$RMSU]U@ٛmS(JPD1,(4UIb_=JԵlĞX%zzjj R>5M5 srٺ55-6nH MKI^ SRФѩhDVyM%eebe+k& e h驩vRmebάvk99.U9(TBa dS \ PFZRkbpoTe:P͝3nj^UHÓR\RUgܵ/6ٳ7r$:rrZQOpj\%]u&}xfMRߪu'NNKRE.^gF]vߵ쵫wzL77-7IR)d%<$G*N`\YUe/=GzRHz)뒫-FQꖢZ$j*^{ΐ+WҷbJɻʢm*؞ܘHGaJEaSt0b2DJ OUwZT9b=9_|)es R=إGÈD<'$BS*G(B{^GG+I6baqq0b}JBU.*ȤʩRY `DPʪ!b(Td*2 iS&ę@4MRԲְ&Llٳffa!Rlٳffa!Rlٳffa!Rlٳffa!Rlٳffa!Rlٳffa!Rlٳffa%JYf͙*ZZYf͛6ffTiie6lٙIV#kT4IbY&IdɖZjխ*ZZYf͛6ff*ZZYf͛6ff*ZZYf͛6ff*ZZYf͛6ff*Z&YjիVaLflٳffeJYf͙*ZZYf͛6ffTiie6lٙfڥZZ&Re&TeF$ĚaLeVZֵ2eZkXa&YjիV2eZaLeVXa&YjիVdɖZaLe2edɭk[fm+ VIXhEjՆkZٛa%a%i%QQVZkZٛaYR,elٳffa!V+Jɓ,VZ0R6lZֵfalDܪ*X~$v-6[ cw;ќvMZT.Jqkml%#jv(N y*)R "0Jdq8UL!¢aQK.⒙J0XLLBr j' )KW8 b"b0`K*E2 ˀpE2 ,S%&E™BJRTr8%\:TL++E\J\,%©4(ELMJW"W8MYV8"VWy$[.)I0QےE85$d&HSM0LU"!v;$]v )#*É".ME\,)# $X#".MEv$\tSQa$q SRF&HK)IGnIR┚$i"™"UUV,TS@X\V\<"U2&, 1T(FQ )JXC(+KLR,(*`&TIeR*>(UUJfL ~ [Wkea䒖PC(uR^2X !(dUb/ K *L*iY[fM4,˳&wwVٓG;;rɣŝչvdN[f\ MY\.[&Wŷ_b%NIt/b.]mpbj^\&upblN˳g5V暫RhMU}4tԾ:|ׯ1o*]} %꾗gi/}=:|e5f[>3Vej̵2yWՆO%Fͻ8#IG;8H%;2z|YJvvzhqgn[gwqW`+ j02j++TL)`+$ڇ PCMPCT5CT5CT5CT5C5CT5CT5CT5C'eGj}c!YF)&, 254&_&X|`NeiǴOªt)^%L,<8K^ta#$pCKƲb#FPO }/w*jcCJȢ^? X#1b/}/SK촴S9NSa$"C%SQEeG£:O\]PŔGWP,"G(GE⇥qh#ӲȢCTz颣'+ ,v?QG}O"OtܑbX}TܑbA;IS4e~/)# =RF'kv/% \H8-ZjիWdSVKVZjՋWkv]WHeUY$iJ_W4r=OS9$]P$zzr 4M4M4M4M4NQvX"J;3X_~UF$e ,,*EW}>iiiiii'TH4~HO?Ne"b!_{q*?ı\1DmT$8YC|_͛TT(tXw8;?!IvTˏƪj%eS.ڪ۪y"DwrL&IO^&D=.# wܒ/;#[v1c0]( (ԍ$4$U (ԍ$4$ȑ2Gwda2O='Ty}DIFdfDjI*daE*GR&Qd)Qd>﫻V^oȒ$wrH$z$"]ܒ$#.$IO#ȎdGQ %4$U $#04$U $ɶDEM%HCI2DRL"#PEI2DRLEQbwr""#QFZ&H&HEZ&H&Dv\)hb?'s}o>y:tjmMh5I6hj0&IlY"(r p+h ڳ{U|o{yY,;y4]y!&z)pO mY*|IedYv{[ױC0}P{{v,K.٭y-څG: uN<zmknݶ6mi)mݺ09qmv۶mݻv9s9p1AY&SYr[~ `JAE @PL(RTM*rҠ 2kfU 0q I 4@%U?d'J FjQ*a 4 J"*iK6IM>U$ 3 iR`m@mmAAF[mIMkU*cim*lжűOcLkJ33R{mIUC6Ƣm([ZEjW Wlͬ_f} /t,G 1J|QcTRD}^൐^ԉ[ ZllU22ղ?ؿH/mkAa~iyL4~Ѱ=mP&ԏ,\V$sO5]Ƴ\fup]. sAGlhľ0̪f+fYzɘc/fJԫHMO0VM*^|ߞqϋɹ9i+ӆc<^}.ՉÚ&:jx8 ʜq8Gt;%?*}<6X٤)}5Lj/K?Z1'V2MS!ƚh/aUOQ*取>Xcr]ɞޗ"YJj9i4V9jJxS$yT(VH.Xr4*(倯_k-سjM512oɗTѧ쥓QW쥓Q/QTlljccU-Q ɩ&fLaɤdZ b̲jLbd12+ʕ&)FU>ep⃊%pq\89eb},+e'Wʫ9UXX,,_K/}P,Qeb)>+ʃq8B+ ĥN+!b'%f6c1rI58"55beFfZ#-Xl-cbŌLc^ͦbe,H5~۩R5;qE98tKR,INN'n&RNܡ+p^Y0F%Iicii$&85ɕi} >Ϭϯ#ŭ(UZiIdMX%ڶVLhS-|>s&IlheK.]LF1X9~6jTq]e6&ʱ_1ji}Sl-ih6d¹VI3󼹛7>ٹ|9$u]쮧n"NK%VKe<%v]XiXg\SeFFw'P]}{睕yxW:h52|WԛkY2Z8>۟y|m4ݣrWu9r'.F:2j/O rf2u:LF!/iT$/TE*+t^U2>OyQqǎdM=^Z|f>'Ee}1a+ ()leCUoXLi h-ƭQa >:ԉ*+T> G%_T@@RUh+_%¢+Q$5J&Y`C"J(M dK!YEU`bCZ*1*hJL*djCR dJʊhQ V2MXeHj5VEQQ0%XHʔ*1Ud `«*EXZR,)ZҡiZhFU&FU&Q0INR):.83lِ#@ -@ffmg*)u6z,Q,Q6 NR\ pEDrR4SK0$1R)` }>эAAF6Yem,emT*Ņeb4U(\ 2V&eMfZƍj65bضTWihqNKddVТ'xSt*tH䫒lUlXG*9_WPh0J6MlX(W zTRbUQxAѵ< a*DUm +0PW$&Tj B jPa@A__~/+e ȨXAP2U?UeAZJ C*b *$~_VXJci&DeHQ'%y~hc) z^?UYEhFb{^QWK#0Wk[jQ=y xI^ުV~-j~TQE+T(jѢ6kl(VTeV{鿫>sru<7+p^Y-xnW{p77U;ify]{$H"D"@l3 "DBB"D!BaBchBlm$ aa  2ט 6 S}%P>@T:h(DR :% ) IBZjj 3AF 4zP2T@IꤔS&&@"*M3HZLl͒YK6-,́fd 3 SN0 h6lkk[Цm[lMFVlb*%M PVŶګb$֢Ue6RjUl̴a$lʫEFҙ5d֡6j@?mdI[&ŭmQkk͛h]Xʇ͒3PԚ S0L.֘b~-LX&*)Gl feQ=ʇ4qeŭu:ʮO]4oES5_ akHVfRL_m5W0^b*- YVE\Zx*e~jL,SN( o٫ F3 #Ut5PiK jCщzXŔ~ٙ4Xԅ>-I>,|,%=,>zqk=yM,WXer9szz.U]pl&,vWNW!s.#b8`'v_iddoEZQ}YLQ,Ke^4hՁ%^4ц%YkXZ5TX,?l3j34~}ʾ>/KOX'Ğxb:1) U V-@>Ka}6Zl02j`ұJ51/,di.Z B,2&HO 1 eX`c2+(Բ+jɒ `1&RPjZtɓ*13ɖLMK*F2dJ$bjYLʳ*:e1]:qY'NUu:Θv\:]b`d&:pÆa+ B>ϹAcjKRȭbb biU5daZ'M"b/p0bW"xb e./UpWY oi¸5xLSxvU֎#RV'Ls00cn8͎3x#IdFXbi-2ɤY`,IlldZe9}]*p; T6fcK3e#:\p:,Rڻ$DD%-x3^̚Hxt& )ydĺv_Bce\'Yg528˫LZ2,/2d]fbz,\,lYjpkLY\NNR)t\j|+xVVY`v>el]F.xYpu `<{q𸮬]#)rYm6&xNS֧U<\ )٩){4ÜK.pGZyVY\C.#җleؗuj=V<6ڣn abҏgj,b1vJb\&XDңo*BM+BJʒ8Ғ+<4+R؟j*2W4pK4&ZF_89Hɖ. iqr,ڕo^d`ŋ,Yh2 ejY_Sz"""""""""""""" DDDDDDDA1DF]1cr1c1c˘1c1c.c1c1n\c1cٳ`l*UaWjWD@1c9[9!nң]ʈ)n,GvhK8u@TqPUPTJaVnKcVQRV*MV*J(QEE%TQRQEIE%TQRƶ M4F[k(g5l +U(ʢHVVSTL"l"jr9ᩌmSqˆQsH'±eesew.*eNSr W#,I eC#qa۽]؏xƖJ8&x|W di-FgN4jx|>:+\Eឈq,^VKҧcB֪2)>|($?>6rnӬxʹf"e. zC2;mcU`],FC45DCmVMLU4 RjdJlE'|O"QVli-a_+ d/|W^fc$>0I1]C鋵Ica|+CʇE}TE*bPJЊ%Ih T5 HY4 MT0LEYZRdY,!jEPJ *T1 C$,e*ī*!LQV(Pj+ !a (Pȫ"QCPU (aE *BB54@ U( 4jjJQ+* PJd&@XJj2e(GRGIHrr4m RNmnnXflSUX9PHS(E)-HHUT\`%$UB(ED/U*bPim,ԳRK5,HAAe-c&c,$UGG6PdRYKJ\i6mK`-ȅwlmɉ[l T_#:\O('5 C٫{'Wz짨+5M^rfXԜ!xċٳjE\6W(QVPE}@,IHђi(S(e}g⬉djTMe_lT>Q-Ubءd`*1Z(S*:dLȗ?EV-XVFȲKJA}2c)J.ѓUʴ2La,&VjYFU2d󑵰)_`|#2ԍjZ_$cIeX K"iGÉZ_/yd*_mmnt)NUm3RJ(ѩ%jhԒJ4jIZ{ۮ]C巖,Y˶ɰ[ymϮ-o=pzmˈ35,zUUUUU,z79v""TM)\D@D@D@D@DL((+$k9æ{p$LӁ (*@4 P)@UP5AL@T K`PhѠ T=U!FM4zC&jJ)(T2=l͚WLf@Qk h6h+]M X6h6 ڤZ466R(R13 fU$m* bյն٨$UzOvIٵe ARb m}6I^= 1'?PfڏUTokZ"ɶW/~:(8LJq\mӃpp8#,3M̭Z{kzQWkTk()%zaBa|eZkx<iіqqL.YpZ%?(VŖM>jPƆc+Y}15Xlk=0 bf12~`j"X|,_ Kjiz-G=h,/xT,]t G'~1ehgJѪ+SU_أ~iF,5~iF,1H(|McemVҶm1JV mTaYffjH% 0e0MQ# ,0jSR)d5)S &K*jN" pp)8K:uYpZ۪KW] bXTbXİ%}%K,ľXľı/ϥ_K"SJ(`Eu"D: 蒮&m[UUa)m k-bZ65F#* #XZ4b$XX,,_K/{ EhŏG2-Z Eh-Z WYp`¶֥Y|FX-2|XŗŖ_2, e-IkB,$YfV<1&L qsUY%u\سŇIm ak++QL9Yώs33_j{'#r5-->U}36g;w\ttuM-Mjib]=ux5vZ8pTcŸi]K_HֶYhjVg>9U#C 5K;smaabGkSBk^RI;0cִiQ\,-{v־Zl5Kr;N=6l3. AXr;eҧ}(]$,:^'+ 8X&`O.ج reES ZрrUBRȋ55!zQR臋R5`h&-Q\Y)U 9ZĘ1}Ni#.kTt]IZfbSa #Lb]Z_"""""""""""""""""""""""""""""""""""(,nc1c1]c1c1뱌c1c7]v1c1c뮌cmQTm-/Ԑߞvۏ5o:v_wtn-כ{{ZUpI$,vڞv(+3l,,κkMinYUV]t41^9s9sX Y[BX%bYhQ(((0X1AjFEVhV|@%U|^޻;vww[ۻT"h%9d1hDZVJaE`4,c-#Y[[iXkZBG9:NSu(U\Xh\sz21ՕZ]TGhDGGt]JTf+Hx.IV#O>Y.c"Ϩeћ.By"<^ Î8^:p<$p/ ^?&= J,Z^RpڧS S^µkz"*{d =pzY\t))8GK]/ {UWܧ-> D) !;Hy)œsbSJb\ƢqFاS( >R((R 1|>/zC>|/_ JtJx JOT_ jm6@iee);#l)FȾUm/8)QQH""PRTʪ1*+¨Ae"RVPFR4jBSZ ԊC`j# dJ1 I4"ʩL Ah% F%R0A !4"`QFT 0 (Ԋ1J% 1JF)H T JCR e(VTTTTYCRjLBIX#)K)MR!tUV%RG$+Q#V 'pI%T\ TJ8)(j $$DJ46lml$ZhjT  KH+ebZIT+RUfU i1VTU%3S53S56*5+](.햓[XdbTTTcUeU<$'aKGH?b[f^֒+ൣZ5Z5A.rl6 1ĺ]|'WN;ک';IZѭѭT.9ml6 2T ۷'Z胥 Mh֍hօ^ qsaSNI.kFe$s:͚P#f,QXefaXRğI}/I/||z(}TG_vvmikrTva (A9ww(QUAUUUUURҪʠ5@2RJ@_[6MG" ?|@܇қni6]@r[Jnw#&mpu9 nJmÛM rN)J*??@0|j2t,TUn>RTJB$( h2OPi JUTdh IS2 @A5*hԥF LJIknm1Zki*m mTHlTH?݂?j[f" lEW2!}vmj_M}m ^Y,Gސ>lV֪}ͫ.揍TڏZ=檇^җX"L &!ԓY0'DOMa|=2+=↶mCϼ b)YĠ,0uW~}SY1_tڏmG؝͗h)ՋUEvmbYZVa_:5{vx^ڿZGSQGUe=y'ʽ+y#yZ/F&j_G晠2fY|CmV6Х+$TffeQ+2̲3 (ŒeT`+1V1V>1 `c1 1>Q ,%1ɒ2ŘbJƖX YSUM"N'T8pE㨥Ʋf\u(ӗ`eU.VE9e.9Yd/&V`Xŕse\Ν>XK_J8rE\J9%\9ĉ\'Ϊ]u]Υ`Zf:A֫Vٙ ffCUVw*s2ICfCRguI;q݃hlHv&UD6a0R[V}c 7 n9Lg>Hѧе 빚.uąP#,#cȎs[yltzs=xga|'^ۉLOSU4,>_nGYxS]bvxՆ5VmRBVN^x|boOe<(lMHi.঺ԞYWf8ĪmR1CBNఞmxmEp9%r[Rj9T^:ʏ-%3#צ3qS֔9ժ'^Q5Ej5T^="NU&IN)Q5Q25^jlؤLRK$29Zr+8,)ɧaNM?CajRIOG>UT[Eخv+_QW6'6++^+#j!Q<)G+b [ZWKbF'ҫ2eihhh!کJIEWBPRDOԒWUffі&,jO@"""^1c1c.c1c1n\c1c1Qb:Ca-m7z]mwqpim ׺I${͌%(i u-lV hăajAXl`bIY")")")+œtbVbn1d4fLbɌY1.m[!;wh iq_JlH@ m؛mA jZU[[[2dɓ&Mi2fXjV&KLVMFjF)52FQ,FbM&(ұB0S@M,L"BmUZF#X1fV1 j5c!FXd5CZO*!BVHb,ԬjJHIx`b y[5ҡ2lV٬l҈Ta# *XrXKvX&<3- Txy[Y))]@G;j1;;\Tt<%bi4 *jab PWGZ4HzgyS\%yr*qIZmF'/$@*KIJ%I0A2Aʴ-V=^IfZ̬ge[̯ۇ/dj{K^+(J'veYk(z=1薊= .SL14S4ZEE=';ez/^3,)t՗j}NhqUz{Jvbڽ%dG G{UQ{{T{@{_Q>0Rj5e5$jNdQJ,UIͫe՘vm?/˓'ĩSOe]W+ヌ`vwC\{>WNlmPxQG>QNʞ|QTXiKڤT?URj  TW%"ʥB`K(QEW*r)"J"+'8R8rG$j)j)a+ Z aXL&bF$jQZԖ 0 IbK$2CJP#Z(S)VR 5` RT*e G)TBEDC*PZ3DdEjKKU+Ia.H\U.(Pc+bdTXĦQdXXS$LXĦ"b1RZXVZ CKB"j9I^A(¨`Q@?mmlJHJ*r+mk6mf[m”@d *iRTO#Ȃ22(d4Hb$Jp< UUjUXPQxH򤕊dT(C$jIT_6F2e1VUDD_EȗxU±TrN/'>˥_J'ڑ;R}'d:H+ > K*HJE\=TSڑ{9T.K*0"XH_~>UO__~Oɦ K@%0Z%RZVXFDRbbHO ~KV2Ya2*+(ZOxlk VIQMU ⴟM#I5RƥGL0MFEH5_b@ '5LTjvZUW@'! O$ ~ C_ow{Ǻ[ܼm]=wVD*q}w+]z66րImkXl$I$H /e5: uG}"PK}ʪ*JH*JVE - m#J iU=R0@z@A5*h)PځM%)@BMj hյ"m 6ڠSZ!U#kkVDJ mZjk^`-o(PfP.GH#Q9 "y'<eO=|?V\VT–X*+.+*`g0[*J5Fl%qfVd̯\YaYlMkP bCXEmY2aiU╴ثRl05z. #,2̳Jev]3 ԭv4ɯeu1>dccOOMKkMNE:\>۟ss1ٕqtɌcӈtL*e;ʧf)d-<=6WE+b\],],ụ˅IbSVZ՗Eh8V\]D-ZZqTBưKjU$i%ڨAc5MV1TWQl[$Ҫ~*J46@_HAU{{Ւ ԯbƑO(Y¦'dcNC#+SEWB X] g|)/YU^""TJ$/|P)J?T31V-e+kknm_DDDDDDDDDDDDDDDDDDDDDDDDDDDDc1c1]c1c1뱌c1c1cjFm^ ?տ{2iͻsw+jݮkewlԃvwk,RUݓ){<욶1ZbVmmmbW$"jwrĊ $2d̹&d I -j3hP1LYLA`ee&JadVAbV)5KR,b5"QeF+SI,YِbSkk!¶5fb06lY  4VCFAR &QRr5DDZda5fXSEFBJ)NNGQqAVpjҲe8BVRT OAH;8]:9%++WG'Tէ]WS9ApP%dO]Hqxӧ'u]N;CN* JЬ.и5`iptp;UUv j^@@"ꇍVtS.;vj%%ãgyx(`:ai]D5ad^DG(/*HQ* R0z۾)x<|Le#*Ԥb_WRN|f&P+2 25@4>Q5jkMQ,Z;;u |+32RYS'gn/i۪~~Ͷn\jx=w]նU$ _'QcN31RKiDž43u$Zm:QCOnr3f[nZ[UT[H  !hZ (+$k:Vvp $L{AR)@T@J@4)TDTUBR T PjtP4 @ɐ4T%J=@ SBE%oI?H[m_ƆVZɚе` TVجj6,cZؓ&-m%-EUim/4ƘUT4c-),̀~م>EHZ]J *jmkmYx IՌlCY 5hmĬhe@/)Vb?u2lܑzJUWlMTY6ji _0g_y9"o{M &a}-Kjə.2Miֵ2+[L>-wefR t|eՋNk\1\1\:fYqSq~ ƭYafёG#VNE{2#Ğڦ1KcS3 Hk}Z%{5C٪*kQ/KǏ_sy-16^Ǐ5MƮ,3MhcVG8֭䞴^=N5.a*I'(sE0r%֑t)S6M+T4U5oC&3O*^ڭH^RzjbқK+E+321e&52VS>iFB>1񏌇twSzC9T?,K"qۙrj"\hpd'st,9+N qUqxmK6YFFҬj5 +Z?5 hfǪKY_Xj5T=0zljJj*PҎ&1M%s!WYc,ј1NWYc RuYddXf1,+UF03 2c*,F2FfL2H),' L#2``c f&Xc&U0cS 3We8 "ӎ1ӜړjL1XjZU38|fd#WՑd "edFX2&Le2S3m)35-h2*ʯ,2S&cd0Xtqb> Kq8pYSqDe]]qW e8 ,vۮNM4]]$Uz2KYp0p8F%ݭPGF]b\qfX>Ì}x# XbʼndVY0F 21{fѴQ6fuٮԫ5\j(e,c,C\9vnlӮ$DD*ek_uoRx&[2a:Seflk3mjaeงpuu]:8\8ⳮGx2:d:ѥ!VI6k1x\'nSCS M ] q Gٵhqζ2ukz&ҝXS+V1f3mjqq0;| jq\:eq8qŝgы^xf0 WXWy:0^S9V3VoMHvC%3VO1djYٯ'M9G a| \]tdx/ \Iq+\\)\4yZ+*X4VZ+CKTc d[5pV^$t0`דiVXb1WQ2­F SfJV#HbFQ0Y0*mf a'bCVRZ*4jXZLFe1FZJ]6bmi&M)ZH1ٖ-j + fȭJD0H E/}j/|L#e/cՙV|i[YO=+kkHhK`gUGHWekB5xBt+j"pC$L>d>'SԞн(/h/I) Q>'UK m٫,bŖ, XZ5dCYDDDDDDDDDDDDDDDDDDDD1c1c1c1cu1c1cc1cT6m$?mk3ZY}7Y=Ruz˞z3kZ+xʴVݻl|5wX|.2z[67^5wRʄuP`VZ61F5m`12a~7[mˍPujl͒YS2,́d)@m@ 0 D*36mR$33fk6L0$Hbɘ3c%)IMifM&RXjִkB& Qb`V(Y+YKRd+1+QaI±AQaHVQVY 3j4&ZVɃ&K2d&jLƌMYdL`ɘɪjVZLL/YTHԊW*'d bVeeXm31m E4!"Rtq8T)'"5W-ri,fۋpp\JR,((ܫs\S4-iT9PYrҳN1qarrrk˪u$쒺ET1D"Qkg4qUXc;ɓZZM.:ih;w('UںYm'FΦXfW 2ZqYv_-oW\E{@WVֵNǮO Xk$pU{^fc$NEݞ\G|A_/䄩*9* ,5RE K. (\R(JNJIpQS@pqH*EG\\ut$ȦE0 (ғId!aX V%Z#SQLEEeHCB4)h)`*4*2EQjP )&O'B.JUJ%`\R(X0U d TЦ%L00IģJAPUt<]vJ#H)(҈uF1E8%ʅ!5!T4Vm06Yk@$ @$ `H H[[]TS("b:C%JRbAQHSTXTY9)IʢQN(pU(QR_B@#oK%%F3,eOԓdKJZK,Rde VDII6[d-G0Ml6Sa ] ɰʰ*q_WWĻ%E-6&"Ncf!qrCʔvٱVT-jCҹ{E8EEyٵ)DmmmU(t*;B@E8T8(AZ}SkjjKF &ZVXT*& TLdLj /dbLd`fL_4lHei5XYa2deX&TI2w|)3,&d¬/Hp4Z S)İe HӉi TpĢ?s{tŢ womgv]o~w{|+=ORo{sU_^yy%R\VIo{{o{I I%Y$ujY$]ZVI$I$I$RI$II&Y$dk5II&ZH-)*%*??@0 ~>* I(RV7y U( Q@UR@ɐ%SRUPd$RL @RQ$ɩjZ mI)ԅѲPiZ UkUش'U 6.EQMjf6]ҡG=ZF̣`tA|Y}Cf Rl=6`e/V_%22? PGh_mjmGsFvd%]E٤-HQ>L橭ilqNfVppW_.ՒTyEkSoFjl3j'id,fdE颟Txhxhlx̫tq],,p8W2$}b'֦jOLҽeGTe+3&b^1cD~-*_|ZOŏK/K=,'x,ʏe:)в,~JdiOœ,ji5M4//yQVVѳfMMFd=jm"{XաAq.Ttœ :HueLKuXK ^,Z0Ɋa'ZN,jd2Ybf&@ }aXaL0 *ã  0SJɄɢj>c\tb pG_VS-Bj$pК'(Iɤh\EmmTˋLS,,,,hjj-$iiƢ-54QjF.1LE,E̦ѕqY2fCR-jj CP̕0fVWd2mTZde3 SS3 Rh6mRU%""lRԔɋhhd+T +%hX`RC$ !LZjSIjZFbd&,S TFL&QejVCQebq:<rU Tmdd֚`SRJ\PT"9-99Mrӗ..2UTRO)ujWWK,RR9\.quR(ER4I/"$)vVSӜ^uORdqx\]^Jz=xAxQx$ГN'RRURG DB%P=ڽ={=hbPʴ!K>ᔵT&JV%&& UIjaI+UibcEY--%KQ1&B>>>< )1 &U#s 30 KWc(_۝G̭;Xhg[RZpw̒ZB?o_ H;9]pnރR;;9]wYn AR;;9]we7UbMVdMd.h vnAQb)omP4+Mc@(XkDJ@mi6mH(}(L(J0&)P@Ԕ)(Z}t- մM6e ֭AR됭j*4AmkV+lHj}lįX/ziDȵ%Ԟ {[JJf%S$=6rWI';嶅:Ӯ38aʿrkY}6ShJmy懚[Z_mI#ދGWٶE$=yk񶼼<t͗Lqbp5j/ܚƟ,im?`[O,lٲlGf5a,ؖe*c/-_Ž,-OKSx-Gx-:Sh: $#/:̘ů孑eͤ1j,JdmYfJdmYfJT6V+em TRaYfffk L0e0kVaj0fZa0!k &iMP  (ꎫEWTEpr$1«pX՗a%NґNC(ٴlN/uHȰ",KY)Sk.8S"}|ɉVSThQŤ.9qiN:hi:]&ˮ]:EK4֑[5Xh&/ňłłabb^kX4S4sUdVikQL2Zu*i[n52FX-2|e/Y|mF*٤lKRԶ65ZJfÍVSdiZqmgFMbgMkl5fVey)Ӫe|ztVeg>3L3}+:vjf %{[K=s:9y#ghlOM8^7 )ƃ-kPg5FiyJtZ|zs~cn\Rw-89׎vuxY M5dc,|k..zlluayrVl*r͉SMh2LeYz^&a`HFVQWҦLeurZ X%R/__ /Q~ S)U 'OH(11eZ&E}mmmdDDDDDDDDDDDDDDDDDDDDDDDDE/1c1cuc1c1c1c1c#mQjثj;wN݉VZf|3p |+fg8#W^ۻRz6yۻSUVcbԛkkf֤Goo}joώB)iKG=2\̒d j4`1jiȰY1Y X,EYCE4XXJiLPб ,$©`E"ZiXdY ,-eU1K4XL 2CK5UE2F=QNR)&Ye5f6iII0!U+E]]\\\.D莒e].YbCYu*\ȕ)QtWpx]%S:QGhuʴUɦ՚^@x +=s^uORdqx\]^)x#G05;CM05Zx@5/r =o|{ίˏ8|8Wz$z^ґW]AÙu##L 엡^^ >_I^<Ҟׯ |_/8@ћiP9K5h¶C6OK#(SSȋJ{B|JZR(#`O;DeTM4vHN\ :*$8+q"q'SHp'N⚠%,T%5I0Kҙ)2T V ,bX!F b d h ,(h*+RT MTSQQE ( Q`($D?TAa))J'I #)V%DpeUbKI#QZP1 5%(1b]/"#R)ZQSkUkmAE^QOP+UR5H|fEVuWy$SICJ(Q:ꢞ@K(F)( RZ+ CDT$^ Rx&0"8Q]UQL֠***R@m`Q-S##FTE"iP +}T9MU5-,ͥĉE!mV⒱т6,@ U+[o SOt)#u#fKO ^fffffeV{UTo[սW[/S;d?QxR}T=wmfbE'ێJ.=)kZֵN.sml֪WuDz3/k6QWE:٘%8 ,V~_S2P0E0,aX_~/>dYY`-2DRԉYU~~_~_B̕*bĦK&~/felEy 15%MC*Jȼ/JO(R1b2a C)`/_2!|Yfdd``IJGKO礏JI{񈭰%bVQ(-(@(֥ֆ!jUX UVUU@{ P@P6@ #}UT"(@ na2*h !*LjQ AF@)(UzW댫+b?x+Ֆ۸]mwOz]>qϛi)#@ Ւȇr$(U=WT=Ä){Krԡ^\'!N2Ra$Tsrc 9'{2OZS{e1xe? (>j{?Zp^m>ھo?*2h_/S4֋$d*~/'ƥU\?Z,>Yzp/O;v_ (\.l>yx/|d9j>|{zZZmj|*|`12oh>b OıT}V/Gd}+/}FGyS>_JdHȾ>ƍYKϸzK Fr26S4S۞^zLЏQ۞m3MfmK_%~S괧emIMHc`0Xņ`c &i,8qTG. |11Uà `a`~ؤ~u1@^"Ҝ!+/Ä^:SBu8xN SS\+H4-(L̫2eVeV, d¬&L&NɂdY02tLLVL&&LL"~WHvĻZ]u`N]V\or՛mkm]%wǀ:<)H<)Ї|ۮtttR'hN1f 2f|fu'w.ḣ9\2yNS;%?XB,K 胷dUs%'~r*KN: mR%):ՙgZm\[ G,¾VUK=OFZk;PGU~R0lff^9̼1s9|OnêaS以L)ֹhbZKkh35*'^$M/J;U yFӗ}lZב69vh㞬:WW8-djc+^Lor)qX^zQЗFO X;N4a4iQy#l<qS,S,S—X/"^ =+* IEůSsF FK2܎MÂW 2FWQ./)j[!#IIyd\ \W BGIm%i2uJp$T)d?)ZS8SBҰqV%? ZM5? 1dYkZ1/KmfV'*/ʧv`)0r ӳM ^/V/S=^5#D蘣ϰ}}}}}0j_+WWڃ T'+R>R3331cKKK? a,KJRߺ""Hcc1c1]c1c1뱌c1c7]v1c1cmmlWrCj,c>9s:<ݓ;溯9͔'y˙=Ű8z;kt\anݹ޻w,oZnNydzܔRTQIhb%RTQIWVVֹ_V_HBm9q!spH@ $ @$ `m TebMS,ҙ0Y02LX(˜F&(4L&UX#J 0#JQ0Ƙ 1a5U4Xc1\RKVDh$ՓYY )Фy*Vkb`ҢRGp58s֧)hn\ȧ#UrE 42Ե#R.]D±&vj#(rDaЦ kN9] ]V4v7.FȮ.P2pd¼S4T\GI+:@Լ] +]NW'vaVJ#MC+/+Ʈm/p빋ʆ8<ˑd#X#vNb=thN)nԵ!5/iwB&b8GC :'DyyIrxd!Da)j8yzwmkݳ9ygG]uҽ X'4u]䩣ܹ,{z[9NZ.U/ 蘝y$Ե$MK.]DV' :G'OU^xO zz#OT'K)U|F(/ rn7x<&;^v*5s %u8&T$) "E@."AQʄ % W%qBN%Cħ0N¡HFeQJX&Td0&@AI2M*bRJ+!X& (2%`-T,0ҊUEQ` H$iH+JA_ʊ_TuM`JxԖAjB8YF*)8\.9E"j,2Z2*F,BbRddbQT-bj%aѕK!1QXe X0QL02Tj%S$0A<0eUYmzU0Db'ReEad):klkf)8<0 *i թ5RԕQpt04`KPҊ54 ]PQd.'LJFE6Jv$NUVX (QaWFH?$UQ R1(_4 c1bI&A@ R:UB8qEWJ+$:*^+tWxO8qCu:9}+ea>V1sU\l++JW>B5jG0R")>G{mԋ؎aQ #^IFѴy(s 0Dt+lTpJEU@d!+**bX#~~Ԡ ~/?'}Z(ҙUX- DK2C|Ҭbb²UцVEHʟu-e!U K"b­edeO5-3*2jX H2/5V튶 MK"bцVU,V+LXa,<Զ&͋fŷl-T*W~߯ݻۻa8!"I$ I$mwBKҨ[ZZZQKQEPY.$$]WuM6/W$nC^ETSM9#pwnj%R*lBm601e\h[#mHaaQQI%Taaaaa$IXaRI*UE$I$RI*U1AY&SY%JzF[~ `!p45 P@h@h J+;Uc;@)RѪ$Wijی/PhѠ (jgIꔩh&@`)%5J3Q}7M{njK->>C9Uؾ\| W]B\^;,U^뷛ݠ?Omm|mkՀX Vսeq~3gHÈ|:6 Ow[.`Jx ?A^b^鼹 DPx3TfMhL%;B.LЕ3zُO6]:Q<ɓ}Ջ"ս/On=ZZzQcְLRNyW1}vS|Ɗ^tTՏ'Ƣhi"Z٘E}}e%^Oɥr|4|p}z}-+,^c5\}xr,Wim ,4f)k=7.,_U-jll+4\pMSl-jU[j/)e>>OZ/ZP?*U5S)1/ OG#'2#7J|4f#g¨ʫ_- ̾;|MͪWeGSQO Qsg)9zDW/OPS*𢧌 s^ oJ]xx#8Bxxܜ*g\/?u Q=r<y玺K\9>n3Me;Si<F_YσՍ>έ売yrXb0K)t(mFP4dZM5_[']NĿDi _L\ŏʗ902e˗cfcs:he]ql.$nއ Y5^Dtx`˗<2uu&{ɭh-\>ɫM!^W2/i\&9qqbr:u({Wb8+j./Q(FJe=!v0V,LʵkUiYUbbZa1aiOT^/ASG35˥JiPv$ŪXcFV⅀3dZdTMD3 VԖ`# D.(*˃^ fmtVGSdB(U3l XmҝjvÝ:5UL\QȀ"$M4+++++,°VDDDDDDDDDDDDDDDDDDDDDDDDDDDDDA21c1nc1c1]c1c1뱌c1]c1c1FڣmQѶ$B?M9`F?V9A6wil=&.<`V8QIuT]'w'wܳ<3,t5Uŋ[wTz?ͱ"A L @$ ADUmUڅUU,mjI @>4ZQ)T ,)!U5 #''Q`G ⨹eYW qW.B>r*bYLS2qL.:A*Eʪ< '2eٙO ^$xbLBZ 4/ +M#VȲЦWr&{(ya2:אjyK=]v> A%^kGyx+#-8ZLVr<\k2܃,֮^ˏZ׃\b}#Z/xY 6*jdE1g.^%+TXX9#K宖Fye⢴^}^N;Q^R} zOTts}ݦy+9a79㨜%$\e?]^WkSjZ.'M<#Ii;/8(x^_58>Li(V%[DeQahʹ*RET>q1=Hq>&yk-)|;W)/|Vl/iW__E>ʉ}TRTC PP2TŠ,(J&$HȈʥXT,)bS(&j Ԇ`0jY+(baej*)dK*T  ʋPMUF0AKT&$ -ZbbhJ TKHВHV(  )LT b"1b0X0EŊ LDF1eA;n:hmXLjw֥6ܦUKmXLjw֡ClѶʵ-RexxMoam*vygq,XaF4Ƃ1c`  (.r.rr. ˅.rp˜\.r. ˅×9s1AY&SYۀ~ `]oJ@PP$aρ;(*@4 RuƒF@h%Oe*RMc)P&*$AԢ%=J21IDB*n~5ynusOyʷjQr A|}6mz&'x1-G_+=1^=?JeG$tv0u ՊpWWYj|5U|7>J(>Dഄ},>ե>+,_ d_ bˢZj/VF])YTx aeNŊ/NִGժ}Z>-m*zËPNJ2iRzjFMHW Ji/nPFLdFL ai'pDY$UPaxTyt C"`%ʦN Z MU)aaa 3X.Ãp q8\  e3pqc1beAYdY!Jdfl>ڳ7RGg.S4Gg.̨>NvDv~'h)]gB%UbY7qexxq~2<^_1OX˦)g79]sć_*t+SpTSd&Lм,aaw1-l:RΖrpce_e2T0Fg?Tʺ_п,ň.E|V_ 'Ë|82꫈Y{Y>CCq5dCjюi Å+471SiʾڍF4G/VpҲeҽ^ Tœ++++ X8m؜Vfœ-Q(WW|\^\, 5VM&xH\-S*x̊Ք;<«XpK+GdSIJ[A1Y$x  UI5&YZQXŒc,qةq,Rؒ ЉZЪՂ$'\9X/r:M9,G hi5ce_®Բ5ji T>?꒨+!V(VT TIDU I"*%aE bQ5Ej&X M ,bF$eIMJ&iQ2bZj-jT5*$& *!VUQj!V)P*2)P•⮂JGTR0C$2LX  aPVV $E,V )X0EUGILH9EJ;3պx G*H\um69!QN8Q N T覐TIApSA%KAPX)PUUi*A*PSPň`WA0bڌ2a X2_kaɄV,#+ejE||@{ ӆzHRzBz^A^^HUڤJHQ b BɊ,"jB2VĄ~U>C!+CPEXOd'jV #0W)*F SDd0CfjK LL)a 1O/$e!`/LT< t/L48 Rs6-&Ͷ16&͜II kn+߸eʻwqE뻥79{9ER_Q66[mbQɯƥQ6vs:w5Q7w95ƥQ|vt9I6 *{犕GM" m@ $ @dMdMK(Wʅq)w|@@ E 4HSM۰>PP j TJAAT  PPexzoL4 F LL4#L2a줪0 FLLT`CA!L&'%OHd4d jTjhPi R U*h ` mm_~G~/¨yϞ׍wZk:hՈFTjtkMoMo<:6t鋦an2bf-a3 X/R3%G+qYfB$1`,y5U7loؓz[[yʷ6%fYM5M444N4ۿ4)Fc mifCmfaF`hXa4h5eZx2ff"b1G:_g_Ff1=򙪫2yLW^f<5Zi]֖mkMFX']9eѽY՘̳ܢY5kYy#{}m{oݓk]d]ɵ~]ɵ~]Ijd|\XlY~`Œŕn9xN^3qimiY)v9po ,a66m1fTzOW߻&׶6oɵvMmv߻&mmv߻&mmvߴY)+%YԵKʾϗ1%ՁfX՜5in2,eN6ZcU>߻&׶6oɵvMmv߻&mmv߻&mmv߾)1YjZ>jHWYyCY @OWvMl]ɵ~]ɵ~]irb݄⊺&RZuyV&4JI"QZօec fAjZ*eyGH]"/"_/_jOY&{Uˀ`6cE/_PP)?T6JTKY|>HB OȲ1`|F__[vT*u%SVmm0x&?P$XfeaS 4 [i[kUu [5\EkjZ)>y I54׳nVÊ3ɦH2K7^&$$e!DZ֦֥L#Tֈ/ZKA""#Db" ADDDDDDDDDD1c1crc1c1ˉs1c1crc1c1˗1c1c1cьcrc1c1˗6jm6]o\9-f<mώmusr x;9Ur5w[>>"2s[Il.TG眨NsG{uw\NwFg./Mȷml䋜N{۫9qzNwN{۫9qzNwN@´P0)V }HxVh/\.. ݵEr0um|&\\&{۫ݵ6EnDwvפ䋜N./I.WI#rwNЎyˋv;s\^.WITS F-R/Qa4FJeTZMVꭤ_=|\\..IFLsL7[_I9Nл]'`fI3 #'ˋwN v眸'h]nG<;B{utIRhѴbŲTFؔ1j[.dV#V1ɤ&V1SnjUlE߷ʕro^(\- Vפ jyqzNл]'`fI3 #'ˋwN v眸'h]nG<;B{utCOH^r\sj6mq&#k \X.1HŨ)&'6.W#KBLJiVd%cZ]! ə3ZgQs|DRt֚f1ΫcMk3G1&ՋKkՂ:-ZeL4xeLp#.\X-XRL**'Xaj#',#+<#ǎWhv;C=DIJJJ/r<73ޙTߙYkyiuVcM6^%LJi&ՋKk~A1x$斀h5*R4Z#:Z#=H-%=Ҟ{TI H)JH ]./I.WI#wnsN (ԩ@eQR#BQhi)jE4U4ZB+ R %2ZʚmJ3,0+J3,0+J3,0+J3,0+J֚fmVV%XTԩ+Hd1CkYZVYieZVYieZVYieZVYieZVYie@ !X)b*UF2QjZl+K, Ҵ+K, Ҵ+K, Ҵ+K, ҴifjPԡ`b)+J3,0+J3,0+J3,0+J3 ҴҴjDjDiR%*hRԶfa$$ aHZZխY-4LͶԵ/ڿKSDQb٪Z)% U}} N r=HԅGaK@XihTբ,b,U5,*ih L"ŀXa,Sjh-Ji$ 01  XM aSKDX4MZ"C@XT,Mh44Mh44L"XTʩ-BԦ@*j jZ@JxLa44E𩧕y^<*gyX,EM^@7yX,EX,EԦ$L$,CJX"S<"MVb/<*o*𩼫"MVb,Th"MVb,Th"*Ԍ$ J}Ř̤Լ"V,$* $*`,*a ¦}$>Q=楥)ZvvvupLHcd]Xj4SMhR6-[ j/y+Ʃ'rE8TS=½AKTjRAAAAAAAAAAUWdv[ 8%8*bD8㍶E0ct,bjް2f (kF^5H^CNRE¦N;G`RPjzP#Uh4Th4Th4Th4Th4Th4Th2Th5*4U UJ*t\\PqqƐM *V- 3,ȒAL" keyJ)4=x!#rE.P')M%;G`*b AQҨiTh44U *F$SJ:Udpqmp.*q\lin(`RUXUE*aEʬp\rzPj'Uh44U *FJAQiTiUFFĒ;*hw**\.-P8 [J71B:PdC#)N8TQv)DEvUZt4CWC\U8PŸHQȝ "hb)NR*pQ`ȪWChPE\T1n(n(j$(.HT \r":9!HCt4S\\*qV҆-Š%hrSN9Jv]v'ކdrrqqqqT8777 )§ *v.A9)9Rp8hrrrrrrT87776T?6JB*̱VJUQ-%z^5efX hJj%hE&<%JmmOX1E8#llVkj~sc \ 8 ?8@2%0Lխ5&Zݭ5ZJViMS5r֔|'&זl]d6oMdvMdvML0Q̖fii K3vիRk%ZOϛ&זl]dvMdvMdvMdpGkoxգQ'i7kQ' {yɵݓk]dvMdvMdvME^e^ c߿I{}m{oݓk6oݓk6oݓkM.XL[]%+A#,.rOxI+ yoݒ%myys˞:FXLQ@Ĕe#QX2K$Sx_~_OV/Wz^Vz^z[^WtW *x%2R[M+6[ZRiՔ^⦵ HbTEM0k aS6§-*mO[XT ?maSl*~"BI+P(X zǯ^zz^zzo^zW^X)ijkI^6ZJЩkm Щkm ЩS km)O-?%\KQZi"~_~\*>-#MMiXIS(XTBJSt->жҔBJS km)O-?PҔBJSD,խ:ԶШ bdLQ[R,  ii)Rmm)R[[iJ~mm)Krֆej֝Jq[[h ׯpZ jViK )^a Fy]k+v譭%>)b%L Tϛ֮g1ZTDG¡͵f]} n8q強r˕zEOH<{UUm~|]{;ӽ7(blkm(lU@m]UmkEeyj**DV"V(&1-(Ҋʠ *FjjI57ջZwU-Q{*& #OM)S,T+T%ɩZV_}˄誃L73YJf:̙3--)*e Piަk1wiLYəiiLXA\ IPiަI"ҙKɚ޷B\WPŨpXɹ! @BD(DDE-PD@DD@D1AY&SYr!5[T~ `coGt | b! pO@s=@(UUUUB倨Q@Ev$@p@Qd؀@ DB);dRQ*(Q EQT%RDbE hj 0 e%)&23@U<42RoBUA4MR=M7}aff= 7ۡflvYnvw3nWQ0ؖCW\v*8$5ЂAnaiE瀼h.>U}Ĵ]>{`\a%U{h.?E;]Sx}.omA'4{ԢBG4F^*- oMFmTj @Q0PY1E lc   a0fmJp'.6JtWF~Okͳ6ark{^׵qYUo+YjH*~Iᶚmnjc1S?O͡l[MM- i4EiǪXc1~cZ[-an-հVW~=+_CCE|m[tulE|:ZVZE,VŐ,VŐ^~Wt ~/C\:\y/|/lui}~W /{.+S֭id*W6'qi ՔU(q9*2?TQ%O+8\2q%q9 "G4EPmmlX@Tfe2 k)ZXʚ4eq &2:G+rTU#T򸜢2?HEy\NRHQVdE#֨F`zf\svԔL%QirSvh-QhL-jRKiXY}/ZkqR)HTO+JHU3qRR?LTS2+*GkU/e뮫mj-l[XMЙufNS2+*S2y\N S2+*#TO+Jk%8}iE0A 28uPv&& [Qi-Q-XF&Lc6SiT%S͛mUIGF656͛[f6lRZ0)#?N2Yak'53fli+eJW' _~KK_K}/ev]v]ev]ev]e.˥t.Kt].KjZBv^Kv]e/K]%v_v]ev]v].KԺ].K tY.jZ$㮺뮺뎺뮺뮶뮽u]u֝uX뮺z_)I)3JDRDJ""6RQf eYZZ401iJIZ X"  ZZ|"""" """""""#DDDDDDD`D"D"D"D"D"1DDF"""""""""""""" DDDDDDDDDK1c11c1cc1c1n㱌c1c7q1c1c1c1cuc1c1nc1c1]c1c1뱌c1c1c1c11c1cu1c1c1c1cuc1c1nj6mPڡCj T6mPڥ' R2u*'RdAۻjvҭk &ϕSSSv bJ7aE E!FDUCcZ^Z/Z@3.^*־F7d$Ik9ȉ<0{;"Ec1եUm5AQ* RZUZƄJX ;2I$\"; x yvy6{un=FuVXK'tq\\w;Ncu cEh͓lhʗX`GssGua=P3;vT8Q\\uŽ:猝8ۮw\ǽw{{x2dduVEՓY9uZ+F^K'!iYRU/.ÂiYVʊK=_!l4Bå~%()֙brIdr~=Wq^U檪_e|/yW+TUe}z9)%4-Q.}=Kձp\ +8Rǵ!l4 -=uz2JN> ^xK6-QW"޾>IK?]^bi[ 's/G_ܕK?uz; p*Wk +$^bi^Q޾˫|/JIK?uz; pKЪ}]]J(҅/~ ~rt/P/G[ RE{׋z; abV+ 5yeJ򄗿xzTQξ=JRRWKUu̿G!l4JIg~.FCb=Wj(_eJuz; ^^V+޾ѐضVR)g|/}QFOz_.bi[)g~.Ga/_p]vqz9 arRK:ߋC|ڊ0{uz7 ajJҸ7^To<^G!l4J迃D=fJYeJ]pϹ6ߛ>a_4> 8Vh懐懙³C96i7&$8/Gض 8Q* Z"Z CBҴ jUs R bҶ  U%4, +@*꺶?l6Z*}i[RRB \%TUX UXYY2dLBE+&VL"ɕ ɕ+&VLDY2edɕTP-,LMZj Z FZmVիVZjjիVZ```YZeYm`e[fmjX0aahhaYeٛjZ XZaYefږVjJYeR CC 2,R԰` -6Ե,eYj*YeZ XZaYefږTeXHYeYJ CC KR CC 2,R԰`*STR,X0aahhaYeٛjZ XZaYefږ5MRK,CKR CC 2,R԰` -5-K ,- 0,3R԰` -5-K ,- TeXIeXHd0` KR CC 2,Ե,040,mKR CC 2,Ե,040,mKR CC 2,Ե,040,% CC 2,Y,040,% CC 2,Y,040YeYeY@ K ,- 0,d` d` d` K ,- 0d` K ,- K ,,K ,,K 0,3mKR CC% -6Ե,eYj*YeZ XXXZaYefږ XZaYe![_uQTU~N$IC l Vٲ&$$ $ć ruфmm}ة1IUx'xuuú[BʹJwA<:Wj(KԨh,K E4Q(%*)4@Vl&B jpCbd*$dAp8dqQ@ȪpX.8b(,UV+ThqTCQpRX DYT ,"%*Ŋˉ.F !]B UĔd](F(V'H+U*0qE bd*"bThp b)pdÂ\UA*wF+)K)AաQ\)CTɋ&)K BT,&!^_=zV)XRUaR285EX B W P*0HVTJ4*48p UUGbu4J1^hTn)\)CTE#YR *V+B.4Z)K #PUDuQ—T4aR28UqR *V+Ш!CIUXTW!Q—h:;puPjYV4*7q J b*2”5Jɍ bLea1bKjڲs'ap O8t\uq^%^UddL+ % UVLUb0$b* V K"dʘEd2UPU! #U2~&PW[4WVWWYl?5CܮJ<q\@xLD&0=1,J&L&HUWBz0L*dL )zYTt/KTx2&DɂdPUdX&&D2e"`JzzG )ѣF6mѵj65 lmEQh V+lm6bتOOOOQ=22E/̶huge/4RuTP(t`({,K dY,,$cDW,L#+D`+,ş+VKGqZ&Va+qqYjWduV6_+LUCUQ06@ 9)sdJ\K rIe.`l@K rU )RO}_WUuuú[BʹJwa= =UQ%`WUTebW\uuá&,bzg~GQ(d^ %Y,,z1Ldz2\Y\baNz'\@;'KQ9ÎBUT\("e.`lUrJ\تT&RW)*  UPLK%\Bb\*JW"b\*]e◫׋"$K)LY/?L "bXDbbbxJ zzzzzeVVVVUcҩLO1~OU&VVVWwT<\eT8x.U.<^:.dTx*(dXY,K%찱X6_+,&X2>W.,1Up/D㋈a:f^㋈a~hxs!~TĹUʩʗ"U06T\1.`l1.`lA1.`lȠ06 UF% JMʕKizUIʆ,xwr[p/j|'OȞb LWUCP1/)CV(.)PƤ dᇤTab ^a, vT8jE/W!QʩPK %dX=ci^/b \dȞu̻Q9ÌY8kl8 >TdEC}_WwT<\eT8x.U.<^:< 0&`1ŌXexC!RdL <^aqq.aqqWuQ! &"b&1P+{R𰰰OhQ{R 0BcCck\d6:p>Cck\d6:p>Cck\d6:p>Cck\d6:˾xl_C/>[_=ڹ.Em}ݫ|,V=ڹ.lum}ݫ|,V=ڹ.lum}ݫ|,V6K m\r[_xڹ.!/z\'rԿr[_xڹ.El|ڹ.4:ڹ.4:ڹ.4:p>!յlҶ[pumi[-E|:â>[]^r_V?֕|-ãtZë Pz, !갰6,XXC/CBp<W _;促\6:Ը !Ջaե|W%|-C^WOĘ&dPRE)&8N]D'Q: N'BqT'B~DNt'Q: Nt'Q= N'Bu4'ȟQ'?U&VB3`ZXb$*a_-+J"S=:UJ -^)Udtz+J0ъ~6/+lp&Ʌ+q8|x0'ba調d*TqeJaQX^+pхJ /+m3dqI_?OL%WQWUm6l_ ھVLY^+j\W|W꺮꺮⺮򺮫꺮ں]WUu]WUu[Vյm[W_bPD%i*0FW*:zP1LSTe%u==:j:W*\&$AWQzW|@dOjR2,|zU+|%G~~5p'<$SN) bzVgUJZ>jOq>M$ڕ_hxj6U+fRURq6_' |u^"x_~.Kt!.t.Ku:^Kt.em8JA+4*OS9q9U+ӕRZj0NR=9Riy a?'J䒹%G!+ɢUh`LV'*JOJy_?COzLpJMOI_NI+Jj~9WSOdt_E#8'*ٳJIi>Cɔ$ʩ2dя %Xpa0'"Й]NJ䒼j:' JG=WSJTIQxp'vRd&G=WyU+^'$Ou?=V8rRؤl&մeTRC?)TٳmTOE#_'TU+T8pN:tӧN:tӧN4'NUWL:tӦQm͟`Yd`I?snn̶mFݽmk=鷦55mFm/tU_%C|N:tӧN:tӧN:tӧN:t'WS+ ?WeAW>T|*/1JN+>qG~+~5UJJ|||U ~>T0%U9 Dsa\KܪrǟLUE-USJeʨzTUU b"@QUb @UkjڪmUmUUUUUTƊƊVV ޛ+df!A_)UyڍhڭX mVfSX![Q mVfSmFe1 .vM0_wu_n,l[ ?i{݀zҝϺ{dUJwsx*rQ$X\UUT=;tO_YЫ֔XE_@=G9ʋU)Hv׳0wU\mUTm`raS!}%;Kʁ=;'݈m 6U;w*w-wx ޼Lj㸇rUHN;W!6؆ۻn] 6؆w*HMv!4۹WeMK3m44fƷgc[tͻݝnΚK,Flkvv5:hM-L۱44fƷgc[4ћݝnΚK,F(+$k$P5qp $L "/T$1 p]G G`*(*EP '@("h`C@ PU@ "5:MMRiT)Q'z#djUC*& jIS@<߈~S~LkszC!Ӯ7d>O]noiC]no@@ah( @reԹ󀼪,? "H@yUYiu.y$U,>~q(*-.?b]\s*̓2f J0P a@0GƦ d0` ,)F]\8pÔÇW4ُ*v˗oRkZֵ55cUx'kZֺkZֵqqcUUjjq55>R]N8~ˇWvVVSKĸ_/H\N"Gc '#1(91f3b"z&>!H6I@U_Gccq}a@K2|O>'O'yz='~Gz?q8 0dyyNV0K9tI'Qʪ}Sdjdo+AUK56 TĹ.8$e .Iy{|!]]KґUĹ.;KƪUݧ>'$e _aĹ.8rq.KRU<\KN.\.%uI> UW%H8QS@Y]K.JF!._Ĺ*ᨪ p'/K_rZU<\KOQUK$Ҳ;RBKv]U#!ЗyĹ.1*~ߥU$Tt>\ 9p%FB/q.K8bUc]U$Tx(y .ArN'!#xR\HCPĹ*U.PQFy \/Ĺ,FB/q.K>Jun]U$TtGo\ _eĹ/R2 q.Kو^^]vIvX* 3Ի.]UHC%vq.K?J~_~/I4z39x%B\.%~*(K<\KTgnR캩&AZU>SdX" L>6 [GHfްO6V2ܸ_r\U#T(^%xQ554(x&y'XRW]<}xB554V y%9VU r\&*G%GTBb)TWT%\\UĪWq\N!q8 UK⸜Cq+8'⸜Eq8Wq\N!q8U\GWq\N!q8%8Jq pા_B1cƖ1c1c1c1cVjXdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffffdɥbŭdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffffdɥbŭdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffdɥbŭffhѥbŭffhѥbŭffhѥbŭffhѥbŭffffdɥbŭhѥbŭffhѥbŭfhѥbŭfhѥbŭhѥbŭhѥbŭhѥbţFK%FK%F&K%kY2iidXkY2iidY,,ZffLZZZY,,ZffL-[UKh[U-?뮺Uu\N'vE9bu 'QGQGaG%ⲅ'^KhT-U$Rh)4&ĔJTL(R`I-KKaUNC+dU'bH# CW)Q"Ip F$"00!r¨ˊp1$aHbXPU>mQJaڊp0\+$¨8W"0X0¹L* ap\ P`°0#C +F\+QF, P`QGԸWl*WSF'% Y&FI¸EDaJ2N&e(F8.**ĪKQEbb#ArTe¸B2`RH0aR }+vTeҸB:! Y&R$\BB0X W)p!FP9B1qRH2V!FP,TR +R.(#AD`H¡w2$˥q 2aJaXA0`Qa"aTaH`Ī.E_uUj5ij)Zj }QG'Cft Pʪ_Fev eТZRTjJQQK꧉a2 Z5U =*E}Rn+.D)`1YV+,V]DWĻqYr!N+UZ0њ3ggUjF3FhWY/%IB'%1. ʂLKdX"b\a0X%IB' Dĸ`*'* 1.J `N@pU`NTb\&%  K N˧NrtNXE4X 4M4#  0M:t # 'hF [!f1 DD@ & H Kz]+\B5ij'[[[UjeV*N%06l]U[-WIQM&AII>^%Ib,XO8%IڢV,!'Jb[*L&J9&%U9PIrTL+rLK,&r0(VXLVA&%Ra2P 1. ʂLKdX"b\a0XB&% ivZf-UeVQiiIa V]N&2`PPaCuJj֩U_J(0mhPDDDDDDDDD"$((((((+խz&$8`QHRFej[.eԕR*5%F,Xj_Rsi4҄|eE4_bR Jb\&%  $Ĺ*L&J9'8UTeTrA&%¤bB}PT@-K! DW _D*Z\ Ra1!X-G RCU/*:tGNW~ZhhhiiKM4ӥQt"Ub[[[[Zֺ֖u:UUu6Z)vL)4Tj(QQ&el[-eRh):+jTı`]MRhӅbTO2% !Ra\*L&$+rBjYi+A&¤bB#L+U0*U9&¤bB)PW*a2TrL+Ią`Bb>ZBKUIj8TLHV$* jX>._Rh옓GheMGQiijիWD+t+8U<)0] bl(Hԑ#hej[-UԕTTuZ+\M.I%bĩM+)aPL( %,+*_+|FZ&šCCM4MZi*Qv*.+kKZֺNKkkkkFaMEʭ6l(&el[-VeRiRM*I|bx,'bxV,J.K亭)šWd˜-FQM4U իVWdtTj-ʦܦU2U#i#RF-UlZԕTThBxŊ.I(HE4ԢDĞWy_aMEʭSCCCCM4MZi*Qv*.¥]u-kZu:mmmmm6ʦ$F 4lZVejZ M&$Ҥ"&%4)O ń$XDMK a2jq;<]u[rmn+9p030;*!,%|>0q*IWѼVs2V@'I6"d^mY myƭ ڿXa1 &Vae'S}W7|}>MJU}pUҚ1-Zpf?]bju׾kMN8my^ 15:X&]{6}cטupS^bju׾_?-1<8mu^ 15:X&]{6}cטupSkN 75:\6}iŷ&fN/774\6ps3kκ 73:6뭚]jzu.=:fZuKON c<996٥gZ23=?4eqٓ lO&0>XOf[{8/}cfמfnuËδ8K#*I?-2bhmU=O([U* .-1Ɣaզ!Zœ/Uz_BPT/U Ԕ)O)O[*jTV6ՙQ}tE"bD^D^D^D^D^DZW--ZmV,}D^D^D^DYD^D^D^D^D^DY)OҔS[Cm,lԫj/eIfbxlUBKǏq9Ԫd7bnmoۙmc@Uh?F>NͶo؛m` ~uٶw|smHB+{׋k;NN8 J}o昝megVaTUVSk:k;NN8RH]^NTĔB3LN6bnm_"|Jk'f۔,jͱ76@h?F~NͶDXտbni|**~kXmqgw>q ʕVSk:kcVmBA>k"տbnmJZ%Oѯm,&[RU[%Oѯm",198@R*v5bvmE[&YU|*~}oXmqgw>q}ϴUZ>'5-R+V/>"+ JE-wYQfwg{}"~i֊ʕViAj?G&Y[BY̲JPiAv5;2SeuvJJUɦRVh_P%;n~imSSM-J_(UzDH%8T$ GAĩ8\T⪸\R#pUWE\\%+G U‹Uª"Y2mMMMMI)K,M4I ”4M$)K,M4I ”4M$)K,M4I ”4M$)K,M4I ”4M$)K,M4I ”4M$$04SR4M$)K,M4I ”4M$)K,M4I ”4M$)K,M4I ”4M$̥,M4I$3)K,M4I R$M4C2I SR$M4,M4I$3)K,M4I R$M4B4M$,M4I$)K,M4I)K,M4I)K,M4I)K,M4I)K,M4I$)K,M4Ҕ4M$4M$,M4I)K,M4Ҕ4M)K,M4Ҕ4Ҕ)K,4C0,M44M$)K,M4I ”$M4C0,$M4C0{k}ll96/F]vE^Z&>/Q>*F2*K&L4h4f",B -(ԗR/KSPZG1PjdEi*\ia# T$Ӕ!FJ*k*&"0dL2eJ& 8*p$ʑ(,***' *(G\ȭ%FWXl%ZI# E8aCS\ 2$&B82)(L2U\(Bba SqIĪ2)1.Q L1JbA0#DBeW]RrG V SNp`G!)paC RIC˅ <eXw(hRb5HyrRⓅTjҔ0DԑR-DU&H+JS]P"jc%)*Q$%)%8UFR&PM*\\PD#y)NqxC*y)Mħ CJS C˒qA4PɍR JHSJLҩ0+Hݛ*g.x(iRj&$TCJiVL*F-$$GU*Wlƶ'xWr pItc]]]]^*ÇNEVN:t ]O_Up{zܼyx/4!T:e,2a2də!IԢS|EXf_Hz.┧2q)Ok*s-z9f)̶\eWت&WTɅ*ȹRE(C"IL",2.%2bd\S+&*C"TĥdĈȸE"ɠ"J"ɠ")"ɢȸT d*2.@z^+گ-8/4uS"𗄺KB&0hxJ`t@XePhtӲ_Ol0,[{{.D̾+\k8q\rp2qU,%:/T0*=@,RW^\keW.5p\ı.IttttvTIŌXeԼR&2Ldx1#1:#1ISN:R_|W.1sW.5 ֥Sd((K&L2dɓ&L)TY"̥RzJkg6[/ke_,Ju_bq{ˍxW.52ӷZtIuGGGGc*+T8tj:xvnܮ\s2W.9&L;uSd()E&L2dɓRStdR|UYbLƳ-q5INe/kT꽒</2ˌzq{ˍxd;uXItQttttv:J+:ht";w.r[.r\ם\LRe%&L2dɓ&ife(TE@jeU3/%Jl_,T[.29fRSdPzU^W.9˙{ˎuyy-SbXItIttttvĩ^UEtçME+N Zw+ƶ]ƶ'xWu!x*)NQL2d ," ,D5BLG ̽WYJq5UNe/U,Ju^/׍]v6UĺKKeY E#4I]:t)WRd W͍ qOH EM+2Y)+2%/ۆݛy6}cטupS^bju׾kMN8my^ 15:X&]{6}co;Կ~[zb4ympSν^bju׾kMN8my^ 15:X&]{כu^nju׾my^OߣnL̜^nni׾mu^g]{כu^nfu׸my[4뭚]jzu.=:fZu/=32y~rrmKNδe~fz~h3&؟L-192aie|>/=& ζ4qy^ͯ_G~m'!*I}#ӊvE_DWR71=99;===9OU:A?ggf'gggggfgggfgggggfgfWĬL*qR:T.OIazzp!Щ0CCЩ/Gz2PTHe>9JdXľtPZQ)9W&j*)/GtPCJzK>&T8('bK'EӂJ}%> #R%*8(|O8RIapPҔKaCx=%zTN*JS^W" (iJtGW#OJ}%}^bӇ"RI}W|("'*Թ-W+A)OӴ#PSj")nZWkv]k~?~?eLJ?՛VUEOU#?/O=5PvR pq|>AA=%zu=MT(y)OIz=^TGPɥ%MUEZ"/2|>S^W(cE^lm4POҔKPx),,A0U}<}?v]kv]k~?~?>u]ЪvڮaQa_?1HKrVvj~}Ab' |&lPP^8$z!8>FF- m21mHQ P"q{x*ZAbXY1@5Y5Yݷvۻ wq_ou5hH?^lHۖ3mw-hH>;I"oX͵^֪&m ۱Z{wvِv2Hk3mp30UUUUU0 e5se&BTUGD}JP$Ilth{PgNЀNotAH(bE{9) @ $R򚥄!̀z8XIMc&'J42 'OTS 0L4Ʉ)z Rj))hRoԢzhi QOT&0}~Qa%+ 鸨=&L2jaSJp  ʮUQn庄P; q  {WA k㭵@jCuۀqֺSXX@.],صxp]:0p4`vh0:cyp1c1cƴc@w }/4S6dkTfb3dT6cbHh6ш4b"5l* ֊fmmbPٴOI6m hLd[ flڣj5l(ٴMd͂أ4lAd[$fV͉l#4l*ٲdX6m5Fw]ۗj66ѴQZM6lT\UGb21Gm]j[Q6I[Q6jՠ6RZW6@ D5ŶUsX[bѭlyFU0NNUy\,G9ԜU9SɒTsʼX.xZC1^<}}}uc<x۹^3''5 ++m$Q8ֽ5rk?*5tkYQghֳk_|J/U--R[E-d)l)f VruL2d-S]-S7^fzt=Z6c^buq]QgkY5vk;FZѭglit:*ߺS&hSj3בxxu4$G{5TkYk=QghֳkY5vk;N_c[f:F% P]u[mYG|kTkY5Zj5yD涓mƒQ=˿{4ݾC')9I𧲞~ ~ ~ ~ _chZY[C V?SO?SO?x]]dI$I5c0Ux^EYΩS⎥=)O ~)⟊~)c?'ZֵDR"""/DFZִ$ !}DR"""/DFZֶ@xWԤRx觰ccc QccLlc~߿~L#9ڔqԣy)GJ8j&o~fw*RL[urq5ML͔d(EՕBm~H͌uB ^ǯ^zׯ^<r D1b 1DDDDb" Ae1n.u1cuc1]c7q1ncDv1""]cuȈ1b"""""""" DKcuc1c1c6뮯xu"nĬbbR!&JV PgtإM 9cڌcڼ܈v1"%ۮ1nc1뱌c1cucr ˱ncmQZ|Ǎ1k"ȳ3+*Q3+*Nv1]cucu7]v1]cuu7]v1]c17]uyn 9(X !͹Fbfqm6)sC311|)vHC:뮺=s^RJ+\ԭ]"bE5/7z{8pA@Vs Q]_#R,Up1eu4@ %3333333&uͤ7\̕^Y`fwݸc@"|vIKRsO}RyJ`3;빕._$G%(u"_B>kZt K-9I.IxiM)trK>kNRm1K+^9Zrmi])_q"U_$JU]!dN" `KrRJK*"G\qE.HNTQ:Ą,U1TSU#(ifi`ifi`i 4ֶUJMU&-JYImhM3L40 4M3L40 4M3hVU VL40 4M3L40 4M3L405[5[*լV0 4M3L40 4M3LLM3 45VkUM3 4M33MM߇?7W^>RKHhHtj[JdSIJxҘҙKҙR]uQs梡ReI&TerDJU*W),J*MUi)9F2T:M)Ԯ)I2qMr)e2 qMr qMr )2S bL)e2 TQuDD:PIũ15&#V!JuV2 R u*9SdN⛔N⛔LS)e1LA2SdL!U JIҌ9L)Ԯ))2JNA2S9S9SdLS)e1LA2SX*4ZQ)e:49SW)2S wܧ wܧ bL)e2 )2S b*bT*RT /rAbR%jM&ԚM)4SRi4 )}O>>VG|G|GUˇ5Iĸ)8)S )*UGаSOjҘ#tnHJL2ʓ$ Dk)I 4'JʣH_HZJHZP_+=RɪVN&rL*ҤRɅY9TY0'*9K&dRg)d¬L,UI r3aVNU&rL*Ģ}O:FFFFTcMOJc^)^)Gݶۥ%GASԡbBNo[nTReI' B|!bPi5O.)4рjB,UI r3aVNU&rL*ʤRɅY9TY0'*9K&dRg)d¬L,UI rU{zU*i11YX0LCOE?loj>AhUhhS5$XDn'tTReI "ڊiS&MSU2}!uJXCaVNU&rL*ʤRɅY9TY0'*9K&dRg)d¬L,UI r3aVNU&rL*넦\"zON==jE0z)QzhbM)bJmeI'uPʓ*O_^i V`cPKR r3aVNU&rL*ʤRɅY9TY0'*9K&dRg)d¬9TY0.U&rL*˕I !}G(Vh=F觢TA*jT|L*b)-mʓ*N >8B Bɔ>ʢI}MJSązQc˜Sq=q:q= S1MImTReI&BBɔM=u222221cXS aL)L=d'C1LSRmm&TReI'z%)Y|OS}OzQ=G1)0&L;b)jMmʓ*L5$p ,JSQ=G50šɓ&M%b)۾eI&TRjI/iH_H_H_RS&O|N#####50šQRS"_@ueZf2 YVF, UQ,T}+YL6Ll-@x/ EÏOT*&UT|l0^  E-o5^9F|tkYQghֳkY5wSmZ7RyAMډGM9M.|k(׌k#?#?#?#Wc-J;ojs_[戠 aحiZRDF/1\X`oFBJF( >8fl|u+cVBk{{A$*z@S@m@z!?j4Pz% jRM )$Uhi'=+0ȑ-b`3xsCv0C664AȡI-AC4Zlcb9ub7!O0>n0:㻹[s7x\1@ PcX80:c3뷃7wuww_t&}jڧe+jCfEUvlm `R>w!PEfDvDvNv[Aۙnivw!6**E =W2ҝ;A(fRK4YMX)F,Z-UPͱ*-mZ2Zֵ4JMAd%j-%VBefW]9hOeUGчH 2 FhjQ~)MLb';M5-n(>ov3d$>|۪kj^R!y28j> 4% h*G`>M'PKQs!GFtOs5~{ΏFc9^̢Լ混aO0F}r̥>M/OkjE˥G9'%ʋ̺_J2͌FC}.&}& *O`e*CE3QHf3ٕ,mZs03Ukf]5XQ)EXʙ 0@˜3*8aG.VY89 , s9a+,<$#,9ab,3,R`W .8!͚͙)9Y8`,0a00\00xp0aa0Æ چ36ڃ46Ceffؾ̮t-.@sW̼ammOwf2"za=7zi,9nwm͒wozys]9^y i1q1-QZfb mUܲT, rڝk Z6K^D|m m6Jlڔ̋Jh%f1 %.ZPyft̵iMI#"sbqJu&3)RH|ږүf1-1KKZd#Y@/p8fyqΎ%.339c01qxG-6A%3bSc#cρW1;m<JR9j+AJBEU|/>R*~D4)Tʉ 0 ,*C ",RRʑ#*%0%0aB0* ߹s4 K%̳3/f_$ ~* 䒪!U-2TjPZH1XT$R:U)URUaJ 0D1($@撄 OkfkkfdƓ%(4+,VS0 ,3 *K(H0R,a_XLO E \%0RE)XK E)C#YK#RU 'җҒ}!bSFVbX( İJ a`L} 2e0&dJdfe14Aac `EVd1J0`ʼn&10X,̩IE"WҊ,emmډ0ЩHC ]aG]=I('b@z$ >_Yz [o|b&pA.s-)JQQU}jͫSBH&612BGp8I4bŊ!$c][DkJ52ePa,m{o{o{UFa5ŋEuBH%U||>wtbPڑ(\U6,SJK.[cF+1I[X6-iSH-Ҧ6˔,eiB{?n{bI }6h@>(@Cn@aʽ@t4(4􀒨 JTaDSIOTjh *FM40RI%*S@ZSl +s[9OW qמ78ck1{ݸԮU50119"!Y""IbX5&1c99{s ss swu2̭sMѵif66%F`)OunٴUFvERA%ݹ[#-)̋5J\mbƢŵٲ-i%j#XbDi-5,H"l6l?cOdb8'c<04_1+ʖ=xm֬2q~+2sS4"2]gsmfee_1Us!? f'k kT&Ҩ,-bL6*U,?;U.69|>PE/ Xa. 9 'HI2m'ݷ.N1cvlE+pqqO<,~\̿>0`y||GƨTvmCiF1Gp akdD LLe5%DFFiHjY2ihfMRjRY)(jҶmmWN ֯60c1mF1mF1$ 6zj61c111Q|cDD`;v1 cccb"%7\v1""]cucu7\0` 0b"" A" #F " DDDAs1cwc1c1]c1c1v1c1c| וZڔHquH Zw%m$ @ ]i2$df@@(w @$ֿ /U{z5MZž,ޫ@7հ.{=es]SIUUUU6UUUU8ymdFd(Y4n$ն&ujUG-:3/~_#hPԗ2IHjFBUK.;-EUU|} *w]H0-3-43c8౩I{ֶmUUUTncUMd544545CSMCSC0&)\!nRGC's{$8sVZs b1XJ,`M^8m͛no|VmS{20p+s21ce(ŠI#@0@'Lwձ7s{gއ1^cɌ̻X{mm(UYNYk˽KosQ-+Ūh 6 (s32J)%zb{3rKbn/wxLWvƽZv%7|s+;Ju*UvިbtWwm-r"#UU\U# m\ջ&\U&\ջ7U~5,mUr{|[@(5*!m.NoP:;Km9xo KA& P ulUfIPH(m(Y FVVS!ii%VV(JƆZڛF*Tq8tlic9K!*dirV2ƎLtBNYV:]@: ZyOW/gL\njXIŊq\NQL1*cǂ<%K¤1L"XŌXLtV11b(C!x%yRTmcNưn9M;M̰e6mj+bX"ǃx01O\*@X**TSP1E,2SL0#1UV*+PCBBАP5V(Hbc@$ 5W[aUP*J+XX A%SH@©,) j ?TI _Ѷ"f3c Xc Q E!N +U# T)`HłXa U9,,L13T`1c0L UR1UCTa1#bb" ċa1,QLQ`J}xJ9II]ZBY!^)RH6m?*'%'ƥ*T @%OW1AY&SYv="j_{| `" }  @*ِ}']3q m&j~2ji5Pbi2Jh@Iꒊ@`5%T(L0I)Q13im~*q *U(W\!=s\c΢(9p  wTZ#9]s9:74s<:74s1c9pu1s]`ūmEF FhD@cъ1Xhک-Z5YZ"ڵV1Xpw WV6m*T|]vJ6lً43PvUM̔b^ٵ6 U檐mlhB,Ehլ55JYimV(Vfif2d316S |1s|cp .2+832Q{+^q>T2d:̻:N IUTDG$ JqIx˽&Wg<^paܻ\q~VK|;Y㙥񨳶ە;j6ڏخg? =Z)73~;]íF@ju5h:FZDΫU J@庭ݺжZݳz;~Ν:'Dw;.NNN:> &,+/g5]~+7yI\kw$r홺L{uUT,N#skML&JwĖJiYsrn$ɾhI$e{ڱyjhaqHэ j(jIyش bKb4Kf7$dA)wN뻧uտi@!RoYfliy ^#ׯW{{^HA0$ d H-wwwsPBH!@3$Lƥ1ZI`bVSVY52SJe0 M$fY2Ȓfaf+*sM˜-㹣'.+ÙQ.J49jp,SL2E28*r4Xqfähƫq\Uq/]"˚Oj%5b<ʱZ=sfEX9Ľ ؞cqj\ytyyQGLAlBb/Wj F)f EQ䀼UKmjmmrXERlYZSkb}wM<]W2myyɓ/(0mњNէNXj4Zax#ڬ<4Ҙd[WvռC4jj-9 >lI]|+VF6fZLѵbg_Rjm^\b*d6Ca,W ꣘v6A[sWBS3eSB!^T @(S!$0BQaXS0E2iĠ ",*PP")Q Q!h@B*%w?{=1 KַmmJI JjB %jVH&HE-P+$P):$I8A H)R(BSPV(}_U )B6lTFj122QI5F))b4iKVES &F)ʦiթQd#jTTTrlmjȆY ,UO ,2UQ2K*U:1bƑeLe,eLRQ2Ɛ1Y$.bJz G(X-[41Y6lV# V,LB0$1WTZjƋbfRUa2L1U d`I›RbYRJRڤ҃RImME*?7p7rsw]QBaG'Uwl9f&1 ~I8K3:WZ$ ^jd1XV )W+ = T 0^} P(Hi@TnªR`c|DPP%JPP[m(Jb EFj4J%CS 4ze5%"PɡJTz>΢(9q{:\Dfʸ6c)]QcXU4-s9λ9ѷ79λ9ѷ7;Ouc9[s]sW<]ͪC,1CRU((FcQ(Q1jŪdԖFVm` mj[Fڍ6EōhKe%l*G~}G[W^v{"F6bōmeM6IRjBvF,l+"QU%cf¶6QI=6.Ҷ(͙(ضjSeA[*T6RV"Rm*ɶ5K)٭k%%mUmO̩Uܸәx5%n{B 㻜+r ;qsOgeإۆbȩwpxŝX~iͲ_+Ӣ̘gͶw6MZ hm1jT})*1FlݱOe|ò_kjM+bxv^~>Kә۷5w3}e{O4IhW{fmn5z/Jc%K.m&Utf5^3 s9kMv0AV\y9|aiܹ)}X^4|tx;WWʜ96WmJK5mڕҒUpbmƪ9.в'Tl&.WNrRЏaMBWrZ;R"Q~hSK4x dLəYdq39eJ>TYS.YI00b唬 hZŽڭZZ6 eM7VlG9aԗ,*6ON՛m1l-/#mܛY!}%8#N'?>gpq뵊O2S4;+2=ǝ+ڄI3%!ёAcrR֨YA^ZF *3J2 RՂ6>go[;mq[>ԝL oV^{}zs\iμ5oaVG{\|<6 <pᔬ* 0q63Uph/ST73M±>sEIvҏiNJuіmh䲦2Ѩ=l) XS ee}GY >g7/ȞYm)jf󋙵9n5x}`_m>U ڪ<2Lʗa}E\fֆatܖbFf1&18Mu-pS1a9j9jk ; Uz̓2rQ2=.%9sDya{6'mYUeLlfqԍX"hҫeYXfV5X m-X%D^k-Y]4ic8MVkm5dY3 %!ْƒ-(ZՕlۉ0ɦ4YJ_ǹdiVLԷMpcBX幚%Zfjȱ2;U 34tyGfn5gj\SFC= sgqƱQK;,;f㝣dؘGwiZ+;L7a WJt3Dywu/G>Rr`ʻfј(:øG;p bʸqa«ߗ ,A(kTMYJvU ^|tφ?A5LmVC'w##yA:|eUٚi1cƬ0ƍLZ4ͳUj)e$ZU#VcZ5,i&MZM6RRiP}jNDnf96 @"" `DDDDDDAb"""" 1`DA 1DKc1c1c1c1c1c1c1c1ncDv1""]cuv1 @$ @% K1nAcucr" 1c66kQmj61cj1b6|irwQ]k@$ z Iwn+EpHU{Kir+pH/U_ cw[6lٳb㈉/$$J*a@Hʬ"W9spTמ"#MR ݕ(*@˱H{mbүٱfa%dIjfa%d6MmI]L8˼_ bLN/_\FﻖB3 (d h > }98>|˱H>5}fU_^> HsY$eM4SFX8#[ˆw.(ED*`8R lE^HV+`GT+μ{b1"'Z(\K!{w$ZZ}WOrjԾK,R/qx\suQ)3V!^|9rvYp+m[;f.0òaeŽHcE e ,i1fO1!*w{HHiH?0{/Q4Ao{j )FM1 %ǐDKWZ\$%UCmZZ7d0wu{V:҄m6KfVffUeeffffa%eeffffa&ffVffffž΢ Ht_^cE^wbٙ<M4R:WA L @ @HbS^kֺkNGRH_ՒH2Ҳ2Yj)eYfc H1KURL4iY2յamUb5+~XةKadM5%8r,\+leNru8eΕ%T sG.IҳR US@ ]k-U** Cd &]NNYq̬эsԦf]Wka̫Xa9]V.v..SXiD<ŰYlmBd].и&yfTq,Ĺ<9QG9Jh+2UG=5NO/:bΨWᖕNK5uL2ih]!ҥm))XA4[J򤧈v-eInLr,s"1ftr#>l뭦,v<Î٦D}$BR* PaJXR`4i1RbTYUEHaHa"E(1E*Q)GclR ) a!TQ0T&*ZHʩJWWJ*TUSD XJ4QB B(T]XbffFB"%)e)`I:tUa!RجJa"*Ċ &0RDH )OD0-4e3 #%0ĦBҩU 5"VֈVi1j BFJH29#4'R^ٙcX&,0X!M ƙ3H`5MVdQUL*}Q^ie*"00$Ԫ{U%V`2KBLbUjURO©[\k,T*Ogj㻔Gosuu @%VKNڪ8 arMR#EUEf:0`e5\H$4GRFjQAFlTP+K: %lb $o qgյe@@BP%ݪ S  ODJM  ?h44OTR@RRI$6G ~uAǽkDPs7^{kʸ6WAq{Ǖй\l*1ns sysy9λ9ѷ70=w9sSwֱnsw9s11k͊ƬUbEj*jEm, J0M6B(EF(h*1EEFƌ`m1jI&5hѴE6Ě-Ij-kTZ,IlʴjѬFֈ[jcEcgp]vT)mBK5G^Su;p+;U[b$cf-+Hj6SiM YJ=twt(eHnڑ Qjj56JDZD%]j Q[Aʍ0j2ID)`YLI$r/swn\jsC5J[S̾C1dLUd45Guj}/wڽ9Z*hA抯yPk*f뵲s.vfʛ*d0J&m|+2T mZ2vǍVL0+Rwaw;&d`SZK[$_0ٷ5'kqS2_AѪڧJ)k"_jJi[[Dk}~rjEdSII̯KvZC -xxcXZ3muq~-ka_vU34\ed֯ۥ^kju<aɟGy[Tu}+q|9=[6w̶F+= |[6=ZV3c[tVΚ;ckbxǒCڕ˳k+^^33圲ʽ̞]i*1Gm ӹpXGk2-M* +eS  4(l6 ;9& 3m(2+&Riٰؾ=vvejk6e'F##[SdhgvMu)&4Seٌd2EڜsVͣehkcj3.g[+ 28N1ٗ1r6mFֿefLlɚŌ>?<2ŌWZ_914|Ũ]-t7tR>j,ȯ|ћq5G%gnG[-MHX#m35jӜNl;>mm.o[GULjыQk&[Zfd5F&AfUKbŶR7ŕŚq4Kݹ{^,9N0M9ӴyF̕=sfGpʃYkw jMi1rrhsvLXWLrQ YXfZȨ Z[62`mmkdf1RD5m`Ej"ṬT_uԺP6-k$Ѥ4lѴY MWnmmG c:AZ\6mFU_幻pfll'6w.&v57/0;3={ݭÎ1աݱd\XXՋyw36syv˕ʎex78r,suXӸj6lvsݤm`}׎ؘ#fڻ,cwJVƘnqpqϚ'1+iRʾlj>= +ʣ\uXԖfg(㫸dI*ʛ;FfجeraY|u=Oߔfp>?9j~>߻Yw ,lG1֓+~o^g񟤿e(6fTƔU --ύG]#fdI)R$JJʦI+KRLeQ5,B6I+edKES4X `[Z}k/РZ_/"" `DDDDDDDDAb"""" 1= H K DDD@cuȈcr"]cuc1c1cuc1c7]v1cu1c1cu1c1]cucr"" DDDD.1DKncH/. HU_nH'۰wn+EpHUzr1c1cQcQb?}vg {F^uݙ½1c1cQcQcQ.`q0ϕ*aMsRl *ՊRJ5OzY;G9sT=azݴ@l*D.lYUCݻY5ZEI,КRd~>n^J|Wdkdek叽IYWPdz$G5z &&=l!LB[1 msϪd)hz$+%UMTX<.9d,bŃRJ]Wp}*@CvК$"zRGC*vj-Δs.=L6=jeU^3ފ)([dTDMEt,_mݻ&U^$wY[o{Cğ;7߿@BBw{Ъnnnid˘SpTխ{~m]{bժ@jI0lo10/{emm 33xױ(.hU4UmmnUO5w=י^bժ\R"p?C[v $@$I,Є$I,I,ВK4$8[q踮 Io~x|m{-}ܖڻXK54hݥ-ҕTA L @ @Hllo|\3T aYOxi }3\u2D8σJMV깯l)ngx-j^>gkG>F>'[SS Chl5 }X'\qt)Σm3{Zy"1ʒ"m6AZғ1fDY1 a a2FiT2DG fbmAhBB-ڡ% Iad*:U3%l6ѓTM[ eCP9VR[*QQVlXJdjDU~ HU$R Xd 2Ь2Tµ&[S524# c*,RDmʩ3 DkTKU1`Zkk0d.dfY$G yY̙3IX1dajҬdLc̋ Dk+21 %lFٛFʖ ֩O5+5IĚhEL3YV3bTjGI m$±$3P|BTbeJMEd6I"x(떪׿_+jOe{{vo^sT%WJĿ`{Ie R)Je3JD:ޯkpH3_O?f;WHpHg#R>*FU*5J)*jRT(+$k&rѕ@~o g>A( QKf@2P v > |RZM2֚4Q4DEUIB SO 5T4ԊihOT %DRI%* i?x #wξ㯘1r 㵄5a]yM,SJ(kM/9s.wWK%RIIds7W{pn 2Irs+\y=w]]w*+c%i,F5FkDmb!,i)5mE {nvSeK5̄WwNNmUVa ̢mE)VԠRWe6 6ѣmڪޒRh-HE-e,DD'#1'*̌+2$8V03R;[)l8 U6"+w/=mNVJQw @l-_24̬ȱYc f-4X-;6j.bҧUGpWb_r"EMTڵKgݭ k/5,_D|qUjfّWJP fR,j>M^y/4l*ݫ[5xm}X' 2fd fl6F(">R؆ʐsTU'd㊳+mTft1[A$jDEf5~GWO2SͲ|i2 E=E&#jkb2b螣)*9; 6g9mM daVGCXTZ G=s)3;LZK5-IHhԃR"k$DlfT>$kMmkZiO|]>b5uh}2>Zй12TuM-S-Di4j4ZjZ3+2QSh6jF,jf.8_m*kilʘ6`arV44+$"6ZI220,a3`Ɨ*ifU,D3LԜeLfR~IUm6Vd؛ EG!XVKD!5c̓15I)S&`y%ő9<Ȏ`Oi#fŚJ iY 53b̥YAh'd)$yUm6m[[EPnߝy.by'ڼg|rd> =ߜrrO=}*.0\w|1]JTÒyUla_~N#11v]]mbm:ƜKyE5u}_v)U_Y}.jpuK0oX#`Fosp#9_Ry3%rQ,F1Mu0^<;Nyb?&!?)3UVŧ3Kѩm!)j^r,=+:JJ3&f`IhmFY5hLěr2X^f2K,qjXM3Cmmy9,2IEHxlۃ6ΡTuܹj H<\pƋE`JJTk l6ɬm;iq`rmeeuZ, ŪhѳfIZQԍi*G a--+!YmlcE?-ڍ3(2붭+$98֕-piR:0?fv1`#'89uNMo ySw2Lw;66qr4b٣gy12tq,F(s*!2`M4su;6YN]s݇7"5:q}]vs dC8daXcBd{AyU:5(æ^"R"hwn 1Hw:x))bk[k,c6w0aܮrYk84^߼/rs16Ug[n812b|;_1j61)j)*z({ח"~E`,f3L$fJi56i%4B%)L& U&VST1[Tɖ1m"\DJw] ^ H숈0b" " DDDD1b""(F DDDOxH/^1DA D@cDDŌcuȉv1]c1c1]c1cu1]cnc1DDA.1DKncDD1뱌o H H K[@Qc1c1cQc1{vg ogvg aK۸Kڍڌc1c1cڌcڍ1ڍ}wQ KWS)fUw @$s'&jTtiRfHвIƽ/&y[OtJRs2v̲d,.~+ֿͮ=VU@}oQI8 _@K<y%F2Ysc &}Ӷ7ߝ&4>|Be Tccbfg  %d2g$0CK"áp .z%! &fԁwZ5h[-BB{mRX@٢MB9=AT@mM wl l&,! ,e;js i 5QFQkEUUPUFQkEAAA@>{'9sdi&ۓ]rW}vI MmUK]kNŻijըR]J8-Z'w񋡶(v.V(ضN%3-:3V'ϻavlٜPubj9NvrjzvS+uvk-}}f 4 i%fFIڍM>W[ȵ==xy{7xxWJG?1h,,#UX!5#edIUfSeF4LfQS4lcDSjۤ4f24뫶V.v! *s.gi\ٍM1ˍIEIh.͵1:k1WhҭklF•5WUCu16UYZrKELpu]\ghin˵]ݰXlvfea]eLk(ڙۗVU2w)4ڟi.5Ǒc&qIYm& ,F[Aw<ǭb97NdlH['jZs8-i[6Ysp|gXc}xQ<>8p#0">g9Fyx}yȻ{9ڙaZ}䏊Tc9QUYIz)}u vdŲZir{-2GOx-ɍM>}䧑#e >3m3aDGҒW/ġQ_܊V)BXQ"ĥU`R-Q  HiIMDQTb QTj`UVRR*XaZKTdH2$T~Wv˪$ _lRBbȨTZ4ZD EHC("Ȅ7U%%Q41DJRVHIOT(J 6lETf!P TXlIFE,¤XTn4A)=DjMUh MjJFRRI33E&$0J_~dM- $Z Z UвP有0XS%bRdŁ f 5%i֤X*i3C156aȵh c+)+QNҿdK(+M35V*Q9UHmЏ' mO"g ӊOj3%j&d>>:O2OQ]2wW 7jy0>^|XeG2jPccJʹCF?Xk̹fm]6aMFK m\ھs|ZfGUdWjxR6[ 2&f+.IS yݭ~)\mEQ2mZL;Pl"fjkfjkH#Obĕ:Ë\9:TVU9CV2LYiY9T1FZU9аЙeK ƥ0&YJ1K*ap ͚͙2BsffpLa00\00xp0aa0Æe ҟ:r+es(P^Zvl=6s6# WfL;[y`ݳc۳kӧ^YT=9o=TwrO{[:wsK[OyuSWa.nk/xqqN&+$/ؙ6]ڙsSZUՏ0c,eƤƢd곷+t΢O*LMIS>lFi V|eκpZ5VYC&jMJ畑npp-5Z5nһf@k"$0D&Se0 ,1+kju*rvngl\ɓKËq򳚫K.yW4a18 {KOSc#y>eU8hœKsPu`ls9y*ZUZK6[ 6,K22dm"DhM-UaRl~mZի_[KC2 H꫸H/Q 0`0`" 1`"}cw""""""""""cw""cwcw"!u1ccc DD1nccDD1뱌n" Đ`DDDDDDj1c1c1cj1cj6;WuܗknO{jmFc1c1ccmF1mFmF1c뱌c1c H@L 0xuUg]SVUuܗU] @U]q!(uT L2o{{{ X,dI)$ I_!F&Q"$F QHէbUww]ªww\PP:{]w\UDsǍ%L0V;`H@ |͜RE76-};L@2@GI |\$ǩ'zDž{}:x/&+hSJT/B;YYI G-%-%IɑɁ)Z\*<.BiQ }b * }4$ ..r!$ybJ+pv7t@{;^&@$SYjr֤o|ŋ], ,XZgRG=|`8I&wfah]'2gYz=uI88nO 5ܺa!~4Ugs%IL$I%eQUe/wəUM$7&f`I$972\5yݘxl q5ww"\J(T0CUoww]ӵS㻻UHWDdU~I$"\>ӷyUj>]K>@! Z[nH(QW$ YUYYaLL! )LTK,fYChlPKVK \.I"t˓RqTTf+ J:JqgVDZLYf 9cjUi Cdlmr !s煞x#r.EI"jdԜRʌx6R1Y:)x%xP^ *-rIwNjb1u*ZZjbا1O8꣉ǘgUq!l5\喬qXHďU%бa|yRiGs9Z=HǟJKڌɚ҇˻mxA|%|9jf,ڲ-J_J𠏊)5 iJ& Q-D KE-TC +%-%,(,(-(F# j_yfI??֕TJRh@RXJ)`L@(LJQTQ r#BY$S "IT JDL"b*DVؙ4,4-+6ReFaed- Va# & a0^)=J_ҩ8%t)ITb!UbiSKI?T}IiɊ+(5a %2Sj[0XT?UaL,&K$AL2l1U,KXUadP%0` %00eQ a*\i6kY[R2UJ^@*?҈g*ׯxoe=^տ'@J> I5J+l2hhIHf~_P' }}kYka$se5U auGRFpR@(G@*4CB[ օ چTɈa*~=I"Q5P'JR 5%Thh4zI)Pi O}ZjfU'-::ʸK`X ]s[SrAs=wsswwY-9c1cw9w8ƌhƣ8:s]pV5K0 m6B3nvEvQSXMjkhwnCjGa[QPY*h&hl-QcbE#cjSj,ަZX((ZY"""U2&EMmJj90 *yaxOVa'\c31x|d~,08gq1^^TsͶ2q~+2sS"2>0_k%_Gmfee_1Us!? f/$&3Fj6Mf*Ѳ5[FfHVPac*M1c Rc%V4cECK5 L1Lb2+,c cRT̋WNqi1;<>|3ʸ|yω8a!Br%W6ۗvܸŌYٱ,!>~>|,s2T[1r#[$m11%8٭W[a&S&S6edeb6 ,5*ťRjRY4iIIfԣQ/ƭJڵYH3$uU '""0`D1""""DA 0`b"""""_1cŌcc1c1nc1c1n㱌c1c !7\0Cn`cccu7\1c:""]cuȈcuu͛6ؕ+bV1c117]vmFmF1c1U11Q| H$ @$H4$7m^g] ڪ$ M@U]@$ 6߷oкZCP G,lИ)u4a1 $Fw׮P^UkMcm5ZM]U\N{n\<犫}QʣUU$)$L`eFT/ U[z]U~Ϛ̂J+r=>//|DŽ\"I(EݑsOwPG* 6-y]ȹʲj\q/'Tb2CHqj6+ձ3#3hÕqxٱ>!^c m5T9͛<)c >,5f,VQPڤB|@D^PU^*RC$iE `SXSAMEMEL0jY@eFQjR%CRB# P$ @UbU_T4UT TiU)LU l"#RU ȢJTCR$UO*H}ٶ"f310$&*AOQt*pGtUWE+"TTQAJRʖX PҀ Xc,2f41XL dK J1UC tc)cSGJҌHDG ı#"E/ G8s~S2Q FOws¿(%UDPmMm#oޔҥH~ ||c@$ ]U|A#PVIqZJk߆*ϹW >}lh2BP(Cz Th(HTO hCJJԩ!4S@$JJiMIԩPLB4ɦC$ERzSAz >ߡ }wkDPryQ-u\QPr!EBs-FnF\i&Ɲާvu&ں079tas9λ94s9λx79S 'c*j^sqWKF Wjc /^-5eZs/3ƑʯNEL4L+իFxiae|5Q#`U^i9_zt=CӤdtV+EXՆZŬ>WՃ(}y68Zԏ˕啟 f_G++1_~N#ேלx}ćګ_?[6ۣMPZ3pjeyx>;kBʓ}Vp}6j㘓D2Ӯ)S^=<0DWj=x|=5`У.K1G>bTk~f;5ՃS~5hӑ8L29ee^feڥ'cUQl[Hil-F1Cs\bfc>cLdqSYc2XcĘX``X04Jc k1'X9˫CqDUGmV0g yd yͶd=,gq4OS#Y.ss'g;~|+R׉x>89>+#e)Nv5\5tj[=>Q}We6X4Opjqk}UZD虢fJ`xyxLCl40OC rJppODh1|L| e^o>1_%;6"Ϭp RU>+)`'sVZs]ADRb,gBZmܘF͵r0uGX{MX JZIWml֙ ʊ:&!6~1}kel[Upʬ VnD QVYZu[3Kٍ#lفtM+93v&b꺑Bs~ƻφxE1tbҩw8ƻφxENY*bS{ rvuskqs+[rλ31?v[QOwQ7{ޓ6b%]H';}g|flm jԶJ]$1A5٥٤&"=>ğK^;[-6_?>-Ϸwuk$޽[$wϤ>bFLBOooe6_oumk_F}eClnlzFcz,Y""޾o{wS{AwMu=ztcs *UHE 5WS03LԉdDJz[>~onl,uX@+늪LQd 6ivig-dz޺Ie;,.13B񊼶<+: j%VܣtSjmMm c,XK-Ųl&lPi+>v+9bE'`)U$]h o[1۵uX¸hT l4}Oϓpl#,TRxNj8ʊ:C%m[$/J}bSE}_Ba) ؔBTbR$bUF%Tb1aR¥C$LI,F#EhAVPib4HDQ,YUj /l3 ,RuUWg8cb(OROHZ (ҩ%CHb ‘Tp% Rh)$"$eQRHY)PJJf[6 bf2c&0R??RHpI9JT8(9 \Ғ@UD*WS!#1h21 !,h4hfHdbXdL"2+"ZQp5(QK2Vje&LcXU`bXYAeCaYUK2@cRd1ELbń *+x)ƥ_T( c 1c 1c 1c ?qp800=:d=34a=ga#ޝ:d?R-A1 )0 RWʪ_Vdc1 % j$S,@@$ @$ @$ @$ @@/,RXAbZwwr%:^V ́K,; !XZ)BIC$ҥyc 00PVIC?c}߆.ϹW zD)J)UR b4b ARk*nҒ@ 0jU Ph{<%#Mz@hhOPiUQL bb# 7Rz7l26 4z IBT=@~zO\{ߧۑ;ۑ>_;0E# wE# |wanٽ{s7[ۑ>_;0W HU2$wm]`@&ۻjT&ۻj\۞fm sF捌|\۞54l`1ۚ60scnxm<6'ۚ60scnx4i憡\l2ce`Զlf5-LFQX@EFQX@EE 6ŬX "T@kmDa`FaTXQ,l`(ccF -Z͍j4V4j@F@FmhV|m14*'fw:0N7S ͳ `[A +*5k#Y ZfٶQ0Q0jь0՛5jlթVYkMj10[ ca̵͛a14125W01T# IT# jlпyLCI^K˨4_dӥ $ZDԲ%zLz`,cVZ 2ɗ/S)]M%Eu,XK@ZZ*x,+*CTy   TjSHQ$xY'%|JEЪ'REx\O_'%rF4+ VX0hу ,Lɉe .haS:Gi%yNy0N^HyOGO4 yTG~2-<ZςkM{I\_]%]#!kL/N+$GpaX)>O"$Em,+_Kի1WU:] |){d5F{NWl} wm%j cՊ4p&t.0dӦ L?.\I,|8,b.NReLK&$(Q{LKG'''(ԞNNNNIcccQn=TU\m ۛ!UssA7mRxM)mmR{:I'zfiy2 RB<-#$-# 1MMMe0ʚM4t#)lZa0ɞL!7W bmkj7ZӃV HTMR\U=&'ŋ8 O5츖%'@}u 5'_ ŖiEO`EZ4e:{<:O9KMR}N!9 jȺu!#YRk/,/FkV'K%rZ^PjL}u'* N)FO)`ʓT4qW"{=S]#E⚙VWa2Cra x#֚ž=Ne ʁ5&uscccQla0HMjUܘL&L& KV֥mR9J.s2N%9bXZZյuU&[QbfXam-Ejȩd-%4Y[|bUF4鱱$`rDSbF65[b JKu[ Ba0LBkj춻lFA.姉y2Zddʰ\#ɓej pI_ɇ\iy5N Oґ+u]]kuki-m6eUߖ~.I"H2$ݵm6JҦ&&4ae2aFHXEb~\񘖪^%Z4X ᭀYT+)&_ϭֻmk$b""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""DDDDDDDDDDDDDDDDDDDDDDDDA/1c1c1c1c1c1c1c1nc1c1c1c1뱌c1c1c1c1c1c1c1c1c1c1c1nc1c1c1c1뱌c1c1cF1c1cu1c1c1c1cuc1c1c1c1#:,_ocm7[r-a\gU|DbwEOn܍d{?elOfnc:鳶;O߶vӦ3RW+ڋή͗e+.К6^>tF1,Xg"1#>zel[ }='wNwO;wsyܼ~3,O#4XϿAƌcьcŋ,XQbŋ=DDkϾn#{{u,TX[-x'߼wtu1wMv:bI;tIttkmdӽ-^ir|1S=ǾOo+{ݼ򷝷뀈DʤՈV )25FZ"XZLd&MK0T+ETp]eXi.J咲+t9jR"꫄*q"LT)ӄKꜺ12&T\+. b֬G.hu*椵Q}e̕O8QT(|򀈯"T R5J@ԩTL ĥ0@`,(Œ -T @@T`0TF1Ue QkVj؀3f̳YlY $ @$ @$ @$ @& `$ @0KZߋmm_cwϱg7?pPP?L!01RRP0` 0VN B8QJ(&"j(Q@BJ(0J *"_jUJД%/*䂩AxJSG*TQO!,`ŕ0H~5AԚ4TiL&Y14JhRX$aa$`UVJ5 1XFhj55 *Y)&LX#I XX@L1a`Xdb) mW}{^S@@U&&{{zO~wߓ9>L6=?~&s}|l{m>~~L3|i3={Otީc}=͏q'?x߻ɜ}&{{zO~wߓ;>M{ i3=6S={g{{L6SKov7s'gigk%]{R7m+7۶85887mMƼe2zv2=^鞾ީY=oJ3۽mmL󃃃^czmnݦy1 zS*goS+y喣y|]Zo7{mkpFvvvƼo{@w9ܺ󃃃^b6XeXede{2S=^z]zt_{oTW/y|S+=|=ZR D#!*3fh}a@pY `!T"WP}ت @+ǪC 14h%7G1Mz* 4 %4)$RSfIt[aa;0E# wE# wE# -{ѫsYm͜[cg$sg5{)JRn HU2$e IYC-wm]cWFц|hhc54l`3ksF捌9[sFѭcohڹF|\۞=]<60=v-^ՆVl2ѩȵQX@EFQX@EQTX E "a`F$A 5E,l`(60j 6ScccbA+A5X #Eh #Eh #BmRV[цwtaowzFީцwup l[09fJ dk ٶmfV0[mXM210Ʃ caa01hm410ƩU^bFaB!mf߭zd9UӦөS YH`+"όZ(h˖G_,-ŪXMJ?ZD2bbb5J0ȴ*XS!2J )ʙ',,- T}zX_/*8O*/S> R'U,&Jeѐѡ_U4TZ*44TzL&%y.TKxUOT)/aM41SjE~"ψ-!ɂOWU:&C~beh5AqhWO\>MC WRz,~T/)šOʏG5 >W0ɩ_*eT\u/)W%Q=PФ3~+jwm""&ɆL}UZj:Qŕ,,/#G/ۗ,_,_Uˉ9e/e*\\ ,e,JbbJ娌Y("ä^NS"Xr/MNSllllm/P֥jY #rȒ[syd5[Gv%mz@MA;~=)ԒȾN%99Wɠ+J#`JQa2RbńdqYLYeQ: hh_bYV ^L&y3ЙɄ޵\L& mkڎ\e&ZC5I.t@_ ŋ\_/ը`2.Jg00._]Ȳ/NOǑuB4 hSҗK9MFSC_/8SYe't#GuU}ZYKbrY:R>ϱ<}}kkH|42ȱCN=hNXSrN)9MU>_/W Z1_ G1Iuy|'Z"OW/EEdZ 5JlllllZ&!0MjUܘL& L& E^B\fpV`.5+3 pmfQc4ڲTTTTdR()ʦ(F~lmő1dI~666661Kmm1 h-E]OӓL& c5kmu갪Иt+Մebrh\,^Zrh\,^Zb)=7mûnwm|Yqy`I̶ħ,ZM&IFLS)Ye4K*ȲZK%d.Qҵ4YBrm,-,7IMDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDQb""""" DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDK1c1c1c1]c1c1c1c7]v1c1c1c1cu1c1c1c1cuc1c1c1c1]c1c1c1c7]v1c1b1c1c1c1뱌c1c1c1c1c1c1c1c1c1c1c1oV߳[XD]m71:ݮbŊvV|DDu9ufY6~l7/_;w]ײt*u麚:=;kevZ(ijQS~1}Y ŋ(DDDkg޷l[;~wOwNwm{^__Xc-bŋ>""511FybŋXbŊ+興"""11{wXb,e/wptM< Ujgh olDh98[v4qt14%cLdWTЃҴj-am5/_-u}k^\*I~Jzz-uemUmYm'ٜ>OEݬ~I_R~?pTJ@`$EZF#"dUL$ $ R-I5$b2d Z+IZJ0$F#UH5T``GKR#IY-K+#F @$ @$ @$ @$ `& @$ A L:"??dɉE$A%&C*+UF XHa@ܒ+ER"jTYTT4h jVZH RʪJUJ%/QUO /x %p##BuR b ň21bMDi4)2JcSMMS jj"XFOЌdbXL&5MM4iVP2,b$ bc+,*0ړi%)`8ZBb` % I?ϩgSpzgSpy;ɜާze2Ng'&&'ަu:M'ɉNL118SNg'&&'ɉ=&rrbbpﻻ*T؀8gۘ@ݶmݶm3 Fwv͂9G<3Xcͺl8g>Umpϕ|#navmwvm@livep% tٓmnn7vm{fۙ F#na mmݱ7 WʾU#m/ 2wٰYG(kYpٷMQm.Q9Li4jm' )qOnqM@V)qOnqM@V 3R؃HHlA6mS[RD2DpϕKbT6W[Ppp>U-8fqM|v 8g68mPUUPPP {T|ɀ `E̸R~P 4ѪEG=# @diTɈ F#Aahфd C@C&@0FM4 2dh41 $RP3HU F@!h dh@ ?T d44ѐdIHQ#)J6@@h C@4~dx-`OWu*UMma˳\a:{fa[+qe Ix9͡˕Dq\;c:p[qcMq@Uynk\nsk+MKfX "Qk(lFZZ y8]sWQ֒uXTmjal!ja+Vj-kB0ƩU*UUm&f4SVHkNeqm [QmmmZMRcfcS0lTh+&Q%ٕSx] R1,b^XR홻1LaO pNV\ljӾSN2+*O&$jԸiC#+Լ]81Lj bNM0u;LaZ1ye劝iLW &fcyh5Z͌aQ\jƬj4<2w4Uަ2 Ʀ51Y]1xe/5rSjJN ]A:SwQ<ח*Ze,4kYkZ i[)L0Ux]YZ+jKuYtwtJЧI8j`5BQG ݍQJ&j\rWE8p^+WOѩEãO޴rvaٕS.+Z¦9yz 'f:4KJtpVfppp<e'N)K\1sí*fEGfQqi* 3<8S32afZP桚xsN)8L:Ӕq%sêU[h,[qYUt%%sC(9àwNyлmKU݆NZ-Ye4)l\ZkEɓ&[mgmKmַ-jˁYV$ʜ8vvc< #'+/37;?CGKOSW[_cgkosw{?GOWXBmmmmmmmm,.7b(BB)f1S0fԂ@.T<DZ _HRٳfRYe+US,2jjՏ^UF7s?Q]sw9}w9}.nÕ>jafkmZ 1b"""$c1c1c1c1"""""""s1cܸ"#DDDF\1c1c1c1c.c1c1c1c1]뽻{\6buaQCePHT"HbV"b|_3F-J̀bY02t̙"A4 Q@F[kkօd64lWLJp=Nuw{{lHD eEu* %f@=%ٻjFc tdEuη]rݫi3 )D$,dI 3],TUU(P&뮺Ӯ%%C3H-,BM֕ Ī Ma@ 0i`ijSL֚4ȕZQ|FASF3n$ A\ն[N5IA G"T\2ʎrq`ƣL\W.2Gh\5֜nV֥nW:\LHaI%]t|Y!:VbL`nN%3&qN:IƩtk(qLaˋu.Jķ|b9wGu(l-\hmҮjh՘*V2%˻{N]uӧԲ8<.3B:gC8H⦇6]]tW[%S(𗊨^(B|IDT $i$SFEIRaaeFPjJ%Z*FK%0EQjZjXUxZ}"`ȘMS݈zwΚxǃn۱??E=e1RRYED¢#(TD+ HI0Eu #:!JJ DBNp$s(JP.pP) ԆV9Xp X0`0 Jj0G >P )@]EU):£A%]EQ\J.UBCPfVbf(S2V20"4ŕ Mjj*5 &Ui$STMS VUi,3,eFZbe *Ű!d%-1-1D`$1Ha`TJpDc )'(T|{뮝:oAl35v=99ǫ]uӧN-1c1ݺIB $PUT DIB $$ BIBIB N(P&D]BIB $$ BIBIB $$ F, I3`Lƴfss7+7kwUʥKJBͲR*&QBUW%x,XZTm%RG-fF%iRHY %I%I%I!fiуDP#JQL*QHS5HUJ`^'/^|_yqϟ>NݻnǁXz;c c(*(1hdI4xϰm{=^}|۾v5mxeHH%)2I[s@$ Aʺ+m7rd0k[mlQ<߼|>z~sn8X}S<= cw1|Lov|c>\=f;ϑyGqpc>9ήi6H]DwI$G H" l $I$G  l $E$HZq~?Ĺ\? Ǐ A>}Ki#'22a#&FCb0&&C =@#@b2@4h4DOSTl?U S߽RP5)I ih2h2hhRTRh$S4QSOP4FAzڏP !dC@4#1 `n"I&P1B!(6 J@#|;ЕUQWSAmI")"j-mTmڑe#j\mCi6܈Щ*"TeNllFfPUm ,hm%js,Q[m%)8AضMeVe6Ulͅ#G#}yc 0` 0`5#G<_"\qw^!qxfcs͵+S*i{p,\3T.]\܃;FIyGH8-I9tuvwxyz{|}(V |XhxLdl w EQE#y<(8E9r2Ks9险'$N/a.ҳ˦ϱ\b} 4TT4t5=GFuzz8Xx9H23s4t5u6v7wpqr{""""""""""" QEQE:83@恚4556N{6nt7x#؝nO8c\o 7l'T9;HDf%,yAA TJD1)%- ~wYi|oVU興!B$I$Gp,r@9 H{%QԔ@$?R$!9333'&ffd̜3{s={lJ~rI$I$I$I'$I9$I$NP?Ii&"(Hgolang-github-grafana-regexp-0.0~git20221122.6b5c0a4/testdata/re2-search.txt000066400000000000000000001246621433723652100260740ustar00rootroot00000000000000# RE2 basic search tests built by make log # Wed May 12 12:13:22 EDT 2021 Regexp.SearchTests strings "" "a" regexps "a" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:a)$" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:a)" -;-;-;- 0-1;0-1;0-1;0-1 "(?:a)$" -;-;-;- 0-1;0-1;0-1;0-1 strings "" "zyzzyva" regexps "a" -;-;-;- -;6-7;-;6-7 "^(?:a)$" -;-;-;- -;-;-;- "^(?:a)" -;-;-;- -;-;-;- "(?:a)$" -;-;-;- -;6-7;-;6-7 strings "" "aa" regexps "a+" -;-;-;- 0-2;0-2;0-2;0-2 "^(?:a+)$" -;-;-;- 0-2;0-2;0-2;0-2 "^(?:a+)" -;-;-;- 0-2;0-2;0-2;0-2 "(?:a+)$" -;-;-;- 0-2;0-2;0-2;0-2 strings "" "ab" regexps "(a+|b)+" -;-;-;- 0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2 "^(?:(a+|b)+)$" -;-;-;- 0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2 "^(?:(a+|b)+)" -;-;-;- 0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2 "(?:(a+|b)+)$" -;-;-;- 0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2 strings "" "xabcdx" regexps "ab|cd" -;-;-;- -;1-3;-;1-3 "^(?:ab|cd)$" -;-;-;- -;-;-;- "^(?:ab|cd)" -;-;-;- -;-;-;- "(?:ab|cd)$" -;-;-;- -;-;-;- strings "" "hello\ngoodbye\n" regexps "h.*od?" -;-;-;- -;0-5;-;0-5 "^(?:h.*od?)$" -;-;-;- -;-;-;- "^(?:h.*od?)" -;-;-;- -;0-5;-;0-5 "(?:h.*od?)$" -;-;-;- -;-;-;- strings "" "hello\ngoodbye\n" regexps "h.*o" -;-;-;- -;0-5;-;0-5 "^(?:h.*o)$" -;-;-;- -;-;-;- "^(?:h.*o)" -;-;-;- -;0-5;-;0-5 "(?:h.*o)$" -;-;-;- -;-;-;- strings "" "goodbye\nhello\n" regexps "h.*o" -;-;-;- -;8-13;-;8-13 "^(?:h.*o)$" -;-;-;- -;-;-;- "^(?:h.*o)" -;-;-;- -;-;-;- "(?:h.*o)$" -;-;-;- -;-;-;- strings "" "hello world" regexps "h.*o" -;-;-;- -;0-8;-;0-8 "^(?:h.*o)$" -;-;-;- -;-;-;- "^(?:h.*o)" -;-;-;- -;0-8;-;0-8 "(?:h.*o)$" -;-;-;- -;-;-;- strings "" "othello, world" regexps "h.*o" -;-;-;- -;2-11;-;2-11 "^(?:h.*o)$" -;-;-;- -;-;-;- "^(?:h.*o)" -;-;-;- -;-;-;- "(?:h.*o)$" -;-;-;- -;-;-;- strings "" "aaaaaaa" regexps "[^\\s\\S]" -;-;-;- -;-;-;- "^(?:[^\\s\\S])$" -;-;-;- -;-;-;- "^(?:[^\\s\\S])" -;-;-;- -;-;-;- "(?:[^\\s\\S])$" -;-;-;- -;-;-;- strings "" "aaaaaaa" regexps "a" -;-;-;- -;0-1;-;0-1 "^(?:a)$" -;-;-;- -;-;-;- "^(?:a)" -;-;-;- -;0-1;-;0-1 "(?:a)$" -;-;-;- -;6-7;-;6-7 strings "" "aaaaaaa" regexps "a*" 0-0;0-0;0-0;0-0 0-7;0-7;0-7;0-7 "^(?:a*)$" 0-0;0-0;0-0;0-0 0-7;0-7;0-7;0-7 "^(?:a*)" 0-0;0-0;0-0;0-0 0-7;0-7;0-7;0-7 "(?:a*)$" 0-0;0-0;0-0;0-0 0-7;0-7;0-7;0-7 strings "" "" regexps "a*" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:a*)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:a*)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:a*)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "xabcdx" regexps "ab|cd" -;-;-;- -;1-3;-;1-3 "^(?:ab|cd)$" -;-;-;- -;-;-;- "^(?:ab|cd)" -;-;-;- -;-;-;- "(?:ab|cd)$" -;-;-;- -;-;-;- strings "" "cab" regexps "a" -;-;-;- -;1-2;-;1-2 "^(?:a)$" -;-;-;- -;-;-;- "^(?:a)" -;-;-;- -;-;-;- "(?:a)$" -;-;-;- -;-;-;- strings "" "cab" regexps "a*b" -;-;-;- -;1-3;-;1-3 "^(?:a*b)$" -;-;-;- -;-;-;- "^(?:a*b)" -;-;-;- -;-;-;- "(?:a*b)$" -;-;-;- -;1-3;-;1-3 strings "" "x" regexps "((((((((((((((((((((x))))))))))))))))))))" -;-;-;- 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 "^(?:((((((((((((((((((((x)))))))))))))))))))))$" -;-;-;- 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 "^(?:((((((((((((((((((((x)))))))))))))))))))))" -;-;-;- 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 "(?:((((((((((((((((((((x)))))))))))))))))))))$" -;-;-;- 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 strings "" "xxxabcdxxx" regexps "[abcd]" -;-;-;- -;3-4;-;3-4 "^(?:[abcd])$" -;-;-;- -;-;-;- "^(?:[abcd])" -;-;-;- -;-;-;- "(?:[abcd])$" -;-;-;- -;-;-;- strings "" "xxxabcdxxx" regexps "[^x]" -;-;-;- -;3-4;-;3-4 "^(?:[^x])$" -;-;-;- -;-;-;- "^(?:[^x])" -;-;-;- -;-;-;- "(?:[^x])$" -;-;-;- -;-;-;- strings "" "xxxabcdxxx" regexps "[abcd]+" -;-;-;- -;3-7;-;3-7 "^(?:[abcd]+)$" -;-;-;- -;-;-;- "^(?:[abcd]+)" -;-;-;- -;-;-;- "(?:[abcd]+)$" -;-;-;- -;-;-;- strings "" "xxxabcdxxx" regexps "[^x]+" -;-;-;- -;3-7;-;3-7 "^(?:[^x]+)$" -;-;-;- -;-;-;- "^(?:[^x]+)" -;-;-;- -;-;-;- "(?:[^x]+)$" -;-;-;- -;-;-;- strings "" "fo" regexps "(fo|foo)" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "^(?:(fo|foo))$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "^(?:(fo|foo))" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "(?:(fo|foo))$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 strings "" "foo" regexps "(foo|fo)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:(foo|fo))$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:(foo|fo))" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:(foo|fo))$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "aA" regexps "aa" -;-;-;- -;-;-;- "^(?:aa)$" -;-;-;- -;-;-;- "^(?:aa)" -;-;-;- -;-;-;- "(?:aa)$" -;-;-;- -;-;-;- strings "" "Aa" regexps "a" -;-;-;- -;1-2;-;1-2 "^(?:a)$" -;-;-;- -;-;-;- "^(?:a)" -;-;-;- -;-;-;- "(?:a)$" -;-;-;- -;1-2;-;1-2 strings "" "A" regexps "a" -;-;-;- -;-;-;- "^(?:a)$" -;-;-;- -;-;-;- "^(?:a)" -;-;-;- -;-;-;- "(?:a)$" -;-;-;- -;-;-;- strings "" "abc" regexps "ABC" -;-;-;- -;-;-;- "^(?:ABC)$" -;-;-;- -;-;-;- "^(?:ABC)" -;-;-;- -;-;-;- "(?:ABC)$" -;-;-;- -;-;-;- strings "" "XABCY" regexps "abc" -;-;-;- -;-;-;- "^(?:abc)$" -;-;-;- -;-;-;- "^(?:abc)" -;-;-;- -;-;-;- "(?:abc)$" -;-;-;- -;-;-;- strings "" "xabcy" regexps "ABC" -;-;-;- -;-;-;- "^(?:ABC)$" -;-;-;- -;-;-;- "^(?:ABC)" -;-;-;- -;-;-;- "(?:ABC)$" -;-;-;- -;-;-;- strings "" "foo" regexps "foo|bar|[A-Z]" -;-;-;- 0-3;0-3;0-3;0-3 "^(?:foo|bar|[A-Z])$" -;-;-;- 0-3;0-3;0-3;0-3 "^(?:foo|bar|[A-Z])" -;-;-;- 0-3;0-3;0-3;0-3 "(?:foo|bar|[A-Z])$" -;-;-;- 0-3;0-3;0-3;0-3 strings "" "foo" regexps "^(foo|bar|[A-Z])" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^(foo|bar|[A-Z]))$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^(foo|bar|[A-Z]))" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:^(foo|bar|[A-Z]))$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "foo\n" regexps "(foo|bar|[A-Z])$" -;-;-;- -;-;-;- "^(?:(foo|bar|[A-Z])$)$" -;-;-;- -;-;-;- "^(?:(foo|bar|[A-Z])$)" -;-;-;- -;-;-;- "(?:(foo|bar|[A-Z])$)$" -;-;-;- -;-;-;- strings "" "foo" regexps "(foo|bar|[A-Z])$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:(foo|bar|[A-Z])$)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:(foo|bar|[A-Z])$)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:(foo|bar|[A-Z])$)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "foo\n" regexps "^(foo|bar|[A-Z])$" -;-;-;- -;-;-;- "^(?:^(foo|bar|[A-Z])$)$" -;-;-;- -;-;-;- "^(?:^(foo|bar|[A-Z])$)" -;-;-;- -;-;-;- "(?:^(foo|bar|[A-Z])$)$" -;-;-;- -;-;-;- strings "" "foo" regexps "^(foo|bar|[A-Z])$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^(foo|bar|[A-Z])$)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^(foo|bar|[A-Z])$)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:^(foo|bar|[A-Z])$)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "bar" regexps "^(foo|bar|[A-Z])$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^(foo|bar|[A-Z])$)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^(foo|bar|[A-Z])$)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:^(foo|bar|[A-Z])$)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "X" regexps "^(foo|bar|[A-Z])$" -;-;-;- 0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 "^(?:^(foo|bar|[A-Z])$)$" -;-;-;- 0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 "^(?:^(foo|bar|[A-Z])$)" -;-;-;- 0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 "(?:^(foo|bar|[A-Z])$)$" -;-;-;- 0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 strings "" "XY" regexps "^(foo|bar|[A-Z])$" -;-;-;- -;-;-;- "^(?:^(foo|bar|[A-Z])$)$" -;-;-;- -;-;-;- "^(?:^(foo|bar|[A-Z])$)" -;-;-;- -;-;-;- "(?:^(foo|bar|[A-Z])$)$" -;-;-;- -;-;-;- strings "" "fo" regexps "^(fo|foo)$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "^(?:^(fo|foo)$)$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "^(?:^(fo|foo)$)" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "(?:^(fo|foo)$)$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 strings "" "foo" regexps "^(fo|foo)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^(fo|foo)$)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^(fo|foo)$)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:^(fo|foo)$)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "fo" regexps "^^(fo|foo)$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "^(?:^^(fo|foo)$)$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "^(?:^^(fo|foo)$)" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "(?:^^(fo|foo)$)$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 strings "" "foo" regexps "^^(fo|foo)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^^(fo|foo)$)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^^(fo|foo)$)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:^^(fo|foo)$)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "" regexps "^$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^$)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:^$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "^$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^$)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^$)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:^$)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "" regexps "^^$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^^$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^^$)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:^^$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "" regexps "^$$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^$$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^$$)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:^$$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "^^$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^^$)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^^$)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:^^$)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "x" regexps "^$$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^$$)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^$$)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:^$$)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "" regexps "^^$$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^^$$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^^$$)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:^^$$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "^^$$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^^$$)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^^$$)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:^^$$)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "" regexps "^^^^^^^^$$$$$$$$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^^^^^^^^$$$$$$$$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^^^^^^^^$$$$$$$$)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:^^^^^^^^$$$$$$$$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "^" 0-0;0-0;0-0;0-0 -;0-0;-;0-0 "^(?:^)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^)" 0-0;0-0;0-0;0-0 -;0-0;-;0-0 "(?:^)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "x" regexps "$" 0-0;0-0;0-0;0-0 -;1-1;-;1-1 "^(?:$)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:$)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:$)$" 0-0;0-0;0-0;0-0 -;1-1;-;1-1 strings "" "nofoo foo that" regexps "\\bfoo\\b" -;-;-;- -;6-9;-;6-9 "^(?:\\bfoo\\b)$" -;-;-;- -;-;-;- "^(?:\\bfoo\\b)" -;-;-;- -;-;-;- "(?:\\bfoo\\b)$" -;-;-;- -;-;-;- strings "" "faoa x" regexps "a\\b" -;-;-;- -;3-4;-;3-4 "^(?:a\\b)$" -;-;-;- -;-;-;- "^(?:a\\b)" -;-;-;- -;-;-;- "(?:a\\b)$" -;-;-;- -;-;-;- strings "" "bar x" regexps "\\bbar" -;-;-;- -;0-3;-;0-3 "^(?:\\bbar)$" -;-;-;- -;-;-;- "^(?:\\bbar)" -;-;-;- -;0-3;-;0-3 "(?:\\bbar)$" -;-;-;- -;-;-;- strings "" "foo\nbar x" regexps "\\bbar" -;-;-;- -;4-7;-;4-7 "^(?:\\bbar)$" -;-;-;- -;-;-;- "^(?:\\bbar)" -;-;-;- -;-;-;- "(?:\\bbar)$" -;-;-;- -;-;-;- strings "" "foobar" regexps "bar\\b" -;-;-;- -;3-6;-;3-6 "^(?:bar\\b)$" -;-;-;- -;-;-;- "^(?:bar\\b)" -;-;-;- -;-;-;- "(?:bar\\b)$" -;-;-;- -;3-6;-;3-6 strings "" "foobar\nxxx" regexps "bar\\b" -;-;-;- -;3-6;-;3-6 "^(?:bar\\b)$" -;-;-;- -;-;-;- "^(?:bar\\b)" -;-;-;- -;-;-;- "(?:bar\\b)$" -;-;-;- -;-;-;- strings "" "foo" regexps "(foo|bar|[A-Z])\\b" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:(foo|bar|[A-Z])\\b)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:(foo|bar|[A-Z])\\b)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:(foo|bar|[A-Z])\\b)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "foo\n" regexps "(foo|bar|[A-Z])\\b" -;-;-;- -;0-3 0-3;-;0-3 0-3 "^(?:(foo|bar|[A-Z])\\b)$" -;-;-;- -;-;-;- "^(?:(foo|bar|[A-Z])\\b)" -;-;-;- -;0-3 0-3;-;0-3 0-3 "(?:(foo|bar|[A-Z])\\b)$" -;-;-;- -;-;-;- strings "" "" regexps "\\b" -;-;-;- -;-;-;- "^(?:\\b)$" -;-;-;- -;-;-;- "^(?:\\b)" -;-;-;- -;-;-;- "(?:\\b)$" -;-;-;- -;-;-;- strings "" "x" regexps "\\b" -;-;-;- -;0-0;-;0-0 "^(?:\\b)$" -;-;-;- -;-;-;- "^(?:\\b)" -;-;-;- -;0-0;-;0-0 "(?:\\b)$" -;-;-;- -;1-1;-;1-1 strings "" "foo" regexps "\\b(foo|bar|[A-Z])" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:\\b(foo|bar|[A-Z]))$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:\\b(foo|bar|[A-Z]))" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:\\b(foo|bar|[A-Z]))$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "X" regexps "\\b(foo|bar|[A-Z])\\b" -;-;-;- 0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 "^(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- 0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 "^(?:\\b(foo|bar|[A-Z])\\b)" -;-;-;- 0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 "(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- 0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 strings "" "XY" regexps "\\b(foo|bar|[A-Z])\\b" -;-;-;- -;-;-;- "^(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- -;-;-;- "^(?:\\b(foo|bar|[A-Z])\\b)" -;-;-;- -;-;-;- "(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- -;-;-;- strings "" "bar" regexps "\\b(foo|bar|[A-Z])\\b" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:\\b(foo|bar|[A-Z])\\b)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "foo" regexps "\\b(foo|bar|[A-Z])\\b" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:\\b(foo|bar|[A-Z])\\b)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "foo\n" regexps "\\b(foo|bar|[A-Z])\\b" -;-;-;- -;0-3 0-3;-;0-3 0-3 "^(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- -;-;-;- "^(?:\\b(foo|bar|[A-Z])\\b)" -;-;-;- -;0-3 0-3;-;0-3 0-3 "(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- -;-;-;- strings "" "ffoo bbar N x" regexps "\\b(foo|bar|[A-Z])\\b" -;-;-;- -;10-11 10-11;-;10-11 10-11 "^(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- -;-;-;- "^(?:\\b(foo|bar|[A-Z])\\b)" -;-;-;- -;-;-;- "(?:\\b(foo|bar|[A-Z])\\b)$" -;-;-;- -;-;-;- strings "" "fo" regexps "\\b(fo|foo)\\b" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "^(?:\\b(fo|foo)\\b)$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "^(?:\\b(fo|foo)\\b)" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "(?:\\b(fo|foo)\\b)$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 strings "" "foo" regexps "\\b(fo|foo)\\b" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:\\b(fo|foo)\\b)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:\\b(fo|foo)\\b)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:\\b(fo|foo)\\b)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "" regexps "\\b\\b" -;-;-;- -;-;-;- "^(?:\\b\\b)$" -;-;-;- -;-;-;- "^(?:\\b\\b)" -;-;-;- -;-;-;- "(?:\\b\\b)$" -;-;-;- -;-;-;- strings "" "x" regexps "\\b\\b" -;-;-;- -;0-0;-;0-0 "^(?:\\b\\b)$" -;-;-;- -;-;-;- "^(?:\\b\\b)" -;-;-;- -;0-0;-;0-0 "(?:\\b\\b)$" -;-;-;- -;1-1;-;1-1 strings "" "" regexps "\\b$" -;-;-;- -;-;-;- "^(?:\\b$)$" -;-;-;- -;-;-;- "^(?:\\b$)" -;-;-;- -;-;-;- "(?:\\b$)$" -;-;-;- -;-;-;- strings "" "x" regexps "\\b$" -;-;-;- -;1-1;-;1-1 "^(?:\\b$)$" -;-;-;- -;-;-;- "^(?:\\b$)" -;-;-;- -;-;-;- "(?:\\b$)$" -;-;-;- -;1-1;-;1-1 strings "" "y x" regexps "\\b$" -;-;-;- -;3-3;-;3-3 "^(?:\\b$)$" -;-;-;- -;-;-;- "^(?:\\b$)" -;-;-;- -;-;-;- "(?:\\b$)$" -;-;-;- -;3-3;-;3-3 strings "" "x" regexps "\\b.$" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:\\b.$)$" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:\\b.$)" -;-;-;- 0-1;0-1;0-1;0-1 "(?:\\b.$)$" -;-;-;- 0-1;0-1;0-1;0-1 strings "" "fo" regexps "^\\b(fo|foo)\\b" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "^(?:^\\b(fo|foo)\\b)$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "^(?:^\\b(fo|foo)\\b)" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 "(?:^\\b(fo|foo)\\b)$" -;-;-;- 0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 strings "" "foo" regexps "^\\b(fo|foo)\\b" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^\\b(fo|foo)\\b)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "^(?:^\\b(fo|foo)\\b)" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 "(?:^\\b(fo|foo)\\b)$" -;-;-;- 0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 strings "" "" regexps "^\\b" -;-;-;- -;-;-;- "^(?:^\\b)$" -;-;-;- -;-;-;- "^(?:^\\b)" -;-;-;- -;-;-;- "(?:^\\b)$" -;-;-;- -;-;-;- strings "" "x" regexps "^\\b" -;-;-;- -;0-0;-;0-0 "^(?:^\\b)$" -;-;-;- -;-;-;- "^(?:^\\b)" -;-;-;- -;0-0;-;0-0 "(?:^\\b)$" -;-;-;- -;-;-;- strings "" "" regexps "^\\b\\b" -;-;-;- -;-;-;- "^(?:^\\b\\b)$" -;-;-;- -;-;-;- "^(?:^\\b\\b)" -;-;-;- -;-;-;- "(?:^\\b\\b)$" -;-;-;- -;-;-;- strings "" "x" regexps "^\\b\\b" -;-;-;- -;0-0;-;0-0 "^(?:^\\b\\b)$" -;-;-;- -;-;-;- "^(?:^\\b\\b)" -;-;-;- -;0-0;-;0-0 "(?:^\\b\\b)$" -;-;-;- -;-;-;- strings "" "" regexps "^\\b$" -;-;-;- -;-;-;- "^(?:^\\b$)$" -;-;-;- -;-;-;- "^(?:^\\b$)" -;-;-;- -;-;-;- "(?:^\\b$)$" -;-;-;- -;-;-;- strings "" "x" regexps "^\\b$" -;-;-;- -;-;-;- "^(?:^\\b$)$" -;-;-;- -;-;-;- "^(?:^\\b$)" -;-;-;- -;-;-;- "(?:^\\b$)$" -;-;-;- -;-;-;- strings "" "x" regexps "^\\b.$" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:^\\b.$)$" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:^\\b.$)" -;-;-;- 0-1;0-1;0-1;0-1 "(?:^\\b.$)$" -;-;-;- 0-1;0-1;0-1;0-1 strings "" "x" regexps "^\\b.\\b$" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:^\\b.\\b$)$" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:^\\b.\\b$)" -;-;-;- 0-1;0-1;0-1;0-1 "(?:^\\b.\\b$)$" -;-;-;- 0-1;0-1;0-1;0-1 strings "" "" regexps "^^^^^^^^\\b$$$$$$$" -;-;-;- -;-;-;- "^(?:^^^^^^^^\\b$$$$$$$)$" -;-;-;- -;-;-;- "^(?:^^^^^^^^\\b$$$$$$$)" -;-;-;- -;-;-;- "(?:^^^^^^^^\\b$$$$$$$)$" -;-;-;- -;-;-;- strings "" "x" regexps "^^^^^^^^\\b.$$$$$$" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:^^^^^^^^\\b.$$$$$$)$" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:^^^^^^^^\\b.$$$$$$)" -;-;-;- 0-1;0-1;0-1;0-1 "(?:^^^^^^^^\\b.$$$$$$)$" -;-;-;- 0-1;0-1;0-1;0-1 strings "" "x" regexps "^^^^^^^^\\b$$$$$$$" -;-;-;- -;-;-;- "^(?:^^^^^^^^\\b$$$$$$$)$" -;-;-;- -;-;-;- "^(?:^^^^^^^^\\b$$$$$$$)" -;-;-;- -;-;-;- "(?:^^^^^^^^\\b$$$$$$$)$" -;-;-;- -;-;-;- strings "" "n foo xfoox that" regexps "\\Bfoo\\B" -;-;-;- -;7-10;-;7-10 "^(?:\\Bfoo\\B)$" -;-;-;- -;-;-;- "^(?:\\Bfoo\\B)" -;-;-;- -;-;-;- "(?:\\Bfoo\\B)$" -;-;-;- -;-;-;- strings "" "faoa x" regexps "a\\B" -;-;-;- -;1-2;-;1-2 "^(?:a\\B)$" -;-;-;- -;-;-;- "^(?:a\\B)" -;-;-;- -;-;-;- "(?:a\\B)$" -;-;-;- -;-;-;- strings "" "bar x" regexps "\\Bbar" -;-;-;- -;-;-;- "^(?:\\Bbar)$" -;-;-;- -;-;-;- "^(?:\\Bbar)" -;-;-;- -;-;-;- "(?:\\Bbar)$" -;-;-;- -;-;-;- strings "" "foo\nbar x" regexps "\\Bbar" -;-;-;- -;-;-;- "^(?:\\Bbar)$" -;-;-;- -;-;-;- "^(?:\\Bbar)" -;-;-;- -;-;-;- "(?:\\Bbar)$" -;-;-;- -;-;-;- strings "" "foobar" regexps "bar\\B" -;-;-;- -;-;-;- "^(?:bar\\B)$" -;-;-;- -;-;-;- "^(?:bar\\B)" -;-;-;- -;-;-;- "(?:bar\\B)$" -;-;-;- -;-;-;- strings "" "foobar\nxxx" regexps "bar\\B" -;-;-;- -;-;-;- "^(?:bar\\B)$" -;-;-;- -;-;-;- "^(?:bar\\B)" -;-;-;- -;-;-;- "(?:bar\\B)$" -;-;-;- -;-;-;- strings "" "foox" regexps "(foo|bar|[A-Z])\\B" -;-;-;- -;0-3 0-3;-;0-3 0-3 "^(?:(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- "^(?:(foo|bar|[A-Z])\\B)" -;-;-;- -;0-3 0-3;-;0-3 0-3 "(?:(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- strings "" "foo\n" regexps "(foo|bar|[A-Z])\\B" -;-;-;- -;-;-;- "^(?:(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- "^(?:(foo|bar|[A-Z])\\B)" -;-;-;- -;-;-;- "(?:(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- strings "" "" regexps "\\B" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:\\B)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:\\B)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:\\B)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "\\B" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:\\B)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:\\B)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:\\B)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "foo" regexps "\\B(foo|bar|[A-Z])" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z]))$" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z]))" -;-;-;- -;-;-;- "(?:\\B(foo|bar|[A-Z]))$" -;-;-;- -;-;-;- strings "" "xXy" regexps "\\B(foo|bar|[A-Z])\\B" -;-;-;- -;1-2 1-2;-;1-2 1-2 "^(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z])\\B)" -;-;-;- -;-;-;- "(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- strings "" "XY" regexps "\\B(foo|bar|[A-Z])\\B" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z])\\B)" -;-;-;- -;-;-;- "(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- strings "" "XYZ" regexps "\\B(foo|bar|[A-Z])\\B" -;-;-;- -;1-2 1-2;-;1-2 1-2 "^(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z])\\B)" -;-;-;- -;-;-;- "(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- strings "" "abara" regexps "\\B(foo|bar|[A-Z])\\B" -;-;-;- -;1-4 1-4;-;1-4 1-4 "^(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z])\\B)" -;-;-;- -;-;-;- "(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- strings "" "xfoo_" regexps "\\B(foo|bar|[A-Z])\\B" -;-;-;- -;1-4 1-4;-;1-4 1-4 "^(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z])\\B)" -;-;-;- -;-;-;- "(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- strings "" "xfoo\n" regexps "\\B(foo|bar|[A-Z])\\B" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z])\\B)" -;-;-;- -;-;-;- "(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- strings "" "foo bar vNx" regexps "\\B(foo|bar|[A-Z])\\B" -;-;-;- -;9-10 9-10;-;9-10 9-10 "^(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- "^(?:\\B(foo|bar|[A-Z])\\B)" -;-;-;- -;-;-;- "(?:\\B(foo|bar|[A-Z])\\B)$" -;-;-;- -;-;-;- strings "" "xfoo" regexps "\\B(fo|foo)\\B" -;-;-;- -;1-3 1-3;-;1-3 1-3 "^(?:\\B(fo|foo)\\B)$" -;-;-;- -;-;-;- "^(?:\\B(fo|foo)\\B)" -;-;-;- -;-;-;- "(?:\\B(fo|foo)\\B)$" -;-;-;- -;-;-;- strings "" "xfooo" regexps "\\B(foo|fo)\\B" -;-;-;- -;1-4 1-4;-;1-4 1-4 "^(?:\\B(foo|fo)\\B)$" -;-;-;- -;-;-;- "^(?:\\B(foo|fo)\\B)" -;-;-;- -;-;-;- "(?:\\B(foo|fo)\\B)$" -;-;-;- -;-;-;- strings "" "" regexps "\\B\\B" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:\\B\\B)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:\\B\\B)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:\\B\\B)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "\\B\\B" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:\\B\\B)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:\\B\\B)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:\\B\\B)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "" regexps "\\B$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:\\B$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:\\B$)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:\\B$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "\\B$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:\\B$)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:\\B$)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:\\B$)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "y x" regexps "\\B$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:\\B$)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:\\B$)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:\\B$)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "x" regexps "\\B.$" -;-;-;- -;-;-;- "^(?:\\B.$)$" -;-;-;- -;-;-;- "^(?:\\B.$)" -;-;-;- -;-;-;- "(?:\\B.$)$" -;-;-;- -;-;-;- strings "" "fo" regexps "^\\B(fo|foo)\\B" -;-;-;- -;-;-;- "^(?:^\\B(fo|foo)\\B)$" -;-;-;- -;-;-;- "^(?:^\\B(fo|foo)\\B)" -;-;-;- -;-;-;- "(?:^\\B(fo|foo)\\B)$" -;-;-;- -;-;-;- strings "" "foo" regexps "^\\B(fo|foo)\\B" -;-;-;- -;-;-;- "^(?:^\\B(fo|foo)\\B)$" -;-;-;- -;-;-;- "^(?:^\\B(fo|foo)\\B)" -;-;-;- -;-;-;- "(?:^\\B(fo|foo)\\B)$" -;-;-;- -;-;-;- strings "" "" regexps "^\\B" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^\\B)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^\\B)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:^\\B)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "^\\B" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^\\B)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^\\B)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:^\\B)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "" regexps "^\\B\\B" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^\\B\\B)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^\\B\\B)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:^\\B\\B)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "^\\B\\B" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^\\B\\B)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^\\B\\B)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:^\\B\\B)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "" regexps "^\\B$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^\\B$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^\\B$)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:^\\B$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "^\\B$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^\\B$)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^\\B$)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:^\\B$)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "x" regexps "^\\B.$" -;-;-;- -;-;-;- "^(?:^\\B.$)$" -;-;-;- -;-;-;- "^(?:^\\B.$)" -;-;-;- -;-;-;- "(?:^\\B.$)$" -;-;-;- -;-;-;- strings "" "x" regexps "^\\B.\\B$" -;-;-;- -;-;-;- "^(?:^\\B.\\B$)$" -;-;-;- -;-;-;- "^(?:^\\B.\\B$)" -;-;-;- -;-;-;- "(?:^\\B.\\B$)$" -;-;-;- -;-;-;- strings "" "" regexps "^^^^^^^^\\B$$$$$$$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^^^^^^^^\\B$$$$$$$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "^(?:^^^^^^^^\\B$$$$$$$)" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 "(?:^^^^^^^^\\B$$$$$$$)$" 0-0;0-0;0-0;0-0 0-0;0-0;0-0;0-0 strings "" "x" regexps "^^^^^^^^\\B.$$$$$$" -;-;-;- -;-;-;- "^(?:^^^^^^^^\\B.$$$$$$)$" -;-;-;- -;-;-;- "^(?:^^^^^^^^\\B.$$$$$$)" -;-;-;- -;-;-;- "(?:^^^^^^^^\\B.$$$$$$)$" -;-;-;- -;-;-;- strings "" "x" regexps "^^^^^^^^\\B$$$$$$$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^^^^^^^^\\B$$$$$$$)$" 0-0;0-0;0-0;0-0 -;-;-;- "^(?:^^^^^^^^\\B$$$$$$$)" 0-0;0-0;0-0;0-0 -;-;-;- "(?:^^^^^^^^\\B$$$$$$$)$" 0-0;0-0;0-0;0-0 -;-;-;- strings "" "x" regexps "\\bx\\b" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:\\bx\\b)$" -;-;-;- 0-1;0-1;0-1;0-1 "^(?:\\bx\\b)" -;-;-;- 0-1;0-1;0-1;0-1 "(?:\\bx\\b)$" -;-;-;- 0-1;0-1;0-1;0-1 strings "" "x>" regexps "\\bx\\b" -;-;-;- -;0-1;-;0-1 "^(?:\\bx\\b)$" -;-;-;- -;-;-;- "^(?:\\bx\\b)" -;-;-;- -;0-1;-;0-1 "(?:\\bx\\b)$" -;-;-;- -;-;-;- strings "" "" 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 "" "a" regexps "a\\C+" -;-;-;- -;-;-;- "^(?:a\\C+)$" -;-;-;- -;-;-;- "^(?:a\\C+)" -;-;-;- -;-;-;- "(?:a\\C+)$" -;-;-;- -;-;-;- 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 "" "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 "" "a" regexps "a\\C+?" -;-;-;- -;-;-;- "^(?:a\\C+?)$" -;-;-;- -;-;-;- "^(?:a\\C+?)" -;-;-;- -;-;-;- "(?:a\\C+?)$" -;-;-;- -;-;-;- 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 "" "Inc." regexps "\\w*I\\w*" -;-;-;- -;0-3;-;0-3 "^(?:\\w*I\\w*)$" -;-;-;- -;-;-;- "^(?:\\w*I\\w*)" -;-;-;- -;0-3;-;0-3 "(?:\\w*I\\w*)$" -;-;-;- -;-;-;- strings "" "aaa" regexps "(?:|a)*" 0-0;0-0;0-0;0-0 0-3;0-0;0-3;0-3 "^(?:(?:|a)*)$" 0-0;0-0;0-0;0-0 0-3;0-3;0-3;0-3 "^(?:(?:|a)*)" 0-0;0-0;0-0;0-0 0-3;0-0;0-3;0-3 "(?:(?:|a)*)$" 0-0;0-0;0-0;0-0 0-3;0-3;0-3;0-3 strings "" "aaa" regexps "(?:|a)+" 0-0;0-0;0-0;0-0 0-3;0-0;0-3;0-3 "^(?:(?:|a)+)$" 0-0;0-0;0-0;0-0 0-3;0-3;0-3;0-3 "^(?:(?:|a)+)" 0-0;0-0;0-0;0-0 0-3;0-0;0-3;0-3 "(?:(?:|a)+)$" 0-0;0-0;0-0;0-0 0-3;0-3;0-3;0-3 golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/testdata/repetition.dat000066400000000000000000000151601433723652100262440ustar00rootroot00000000000000NOTE 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 golang-github-grafana-regexp-0.0~git20221122.6b5c0a4/testdata/testregex.c000066400000000000000000001465351433723652100255610ustar00rootroot00000000000000#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; }