From 6c7ca6e4d4e26e4c8cbe0d183966011b3b088a0a Mon Sep 17 00:00:00 2001 From: Ondřej Surý Date: Thu, 6 Oct 2011 09:35:45 +0200 Subject: Imported Upstream version 2011.09.21 --- src/cmd/8l/asm.c | 2 +- src/cmd/cgo/doc.go | 3 + src/cmd/cgo/gcc.go | 9 +- src/cmd/cgo/main.go | 17 +- src/cmd/gc/cplx.c | 3 + src/cmd/gc/go.errors | 3 + src/cmd/gc/go.y | 38 +- src/cmd/gc/obj.c | 10 +- src/cmd/gc/subr.c | 14 +- src/cmd/godoc/appinit.go | 13 +- src/cmd/godoc/codewalk.go | 6 +- src/cmd/godoc/doc.go | 3 + src/cmd/godoc/filesystem.go | 15 +- src/cmd/godoc/format.go | 2 +- src/cmd/godoc/godoc.go | 79 +- src/cmd/godoc/index.go | 61 +- src/cmd/godoc/main.go | 7 +- src/cmd/godoc/parser.go | 2 +- src/cmd/godoc/zip.go | 9 - src/cmd/gofix/Makefile | 1 + src/cmd/gofix/imagenew.go | 82 + src/cmd/gofix/imagenew_test.go | 53 + src/cmd/gofix/main.go | 30 +- src/cmd/gofmt/doc.go | 6 + src/cmd/gofmt/gofmt.go | 146 +- src/cmd/gofmt/gofmt_test.go | 46 +- src/cmd/gofmt/testdata/old.golden | 9 + src/cmd/gofmt/testdata/old.input | 8 + src/cmd/gofmt/testdata/stdin1.golden | 3 + src/cmd/gofmt/testdata/stdin1.golden.gofmt | 3 + src/cmd/gofmt/testdata/stdin1.input | 3 + src/cmd/gofmt/testdata/stdin1.input.gofmt | 3 + src/cmd/gofmt/testdata/stdin2.golden | 11 + src/cmd/gofmt/testdata/stdin2.golden.gofmt | 10 + src/cmd/gofmt/testdata/stdin2.input | 11 + src/cmd/gofmt/testdata/stdin2.input.gofmt | 11 + src/cmd/gofmt/testdata/stdin3.golden | 6 + src/cmd/gofmt/testdata/stdin3.golden.gofmt | 7 + src/cmd/gofmt/testdata/stdin3.input | 4 + src/cmd/gofmt/testdata/stdin3.input.gofmt | 7 + src/cmd/gofmt/testdata/stdin4.golden | 3 + src/cmd/gofmt/testdata/stdin4.golden.gofmt | 3 + src/cmd/gofmt/testdata/stdin4.input | 3 + src/cmd/gofmt/testdata/stdin4.input.gofmt | 3 + src/cmd/goinstall/main.go | 13 +- src/cmd/goinstall/make.go | 6 +- src/cmd/gotest/gotest.go | 2 +- src/cmd/govet/govet.go | 30 +- src/cmd/ld/dwarf.c | 26 +- src/pkg/Makefile | 1 + src/pkg/archive/tar/common.go | 51 +- src/pkg/asn1/asn1_test.go | 16 +- src/pkg/bytes/bytes.go | 19 +- src/pkg/bytes/bytes_test.go | 8 +- src/pkg/crypto/bcrypt/Makefile | 12 + src/pkg/crypto/bcrypt/base64.go | 38 + src/pkg/crypto/bcrypt/bcrypt.go | 282 + src/pkg/crypto/bcrypt/bcrypt_test.go | 195 + src/pkg/crypto/blowfish/block.go | 105 +- src/pkg/crypto/blowfish/blowfish_test.go | 18 + src/pkg/crypto/blowfish/cipher.go | 26 +- src/pkg/crypto/ocsp/ocsp_test.go | 2 +- src/pkg/crypto/rand/rand_unix.go | 2 + src/pkg/crypto/tls/cipher_suites.go | 84 +- src/pkg/crypto/tls/common.go | 7 +- src/pkg/crypto/tls/conn.go | 63 +- src/pkg/crypto/tls/handshake_client.go | 12 +- src/pkg/crypto/tls/handshake_client_test.go | 1 + src/pkg/crypto/tls/handshake_messages.go | 6 +- src/pkg/crypto/tls/handshake_messages_test.go | 13 +- src/pkg/crypto/tls/handshake_server.go | 15 +- src/pkg/crypto/tls/handshake_server_test.go | 173 +- src/pkg/crypto/tls/key_agreement.go | 16 +- src/pkg/crypto/tls/prf.go | 107 +- src/pkg/crypto/tls/prf_test.go | 21 +- src/pkg/debug/elf/file_test.go | 3 + src/pkg/exec/lp_unix.go | 2 + src/pkg/exp/gui/x11/conn.go | 2 +- src/pkg/exp/norm/Makefile | 9 +- src/pkg/exp/norm/maketables.go | 2 +- src/pkg/exp/norm/maketesttables.go | 1 + src/pkg/exp/norm/normregtest.go | 295 + src/pkg/exp/norm/tables.go | 6038 ++++++++++---------- src/pkg/exp/norm/trie.go | 83 +- src/pkg/exp/norm/trie_test.go | 39 +- src/pkg/exp/norm/triedata_test.go | 76 +- src/pkg/exp/norm/triegen.go | 159 +- src/pkg/exp/regexp/exec.go | 33 +- src/pkg/exp/regexp/exec_test.go | 458 +- src/pkg/exp/regexp/find_test.go | 9 + src/pkg/exp/regexp/re2.txt.gz | Bin 764518 -> 0 bytes src/pkg/exp/regexp/regexp.go | 66 +- src/pkg/exp/regexp/syntax/parse.go | 92 +- src/pkg/exp/regexp/syntax/parse_test.go | 199 +- src/pkg/exp/regexp/syntax/prog.go | 2 +- src/pkg/exp/regexp/syntax/regexp.go | 15 +- src/pkg/exp/regexp/syntax/simplify_test.go | 12 +- src/pkg/exp/regexp/testdata/README | 23 + src/pkg/exp/regexp/testdata/basic.dat | 221 + src/pkg/exp/regexp/testdata/nullsubexpr.dat | 79 + src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2 | Bin 0 -> 394016 bytes src/pkg/exp/regexp/testdata/re2-search.txt | 3667 ++++++++++++ src/pkg/exp/regexp/testdata/repetition.dat | 163 + src/pkg/exp/regexp/testdata/testregex.c | 2286 ++++++++ src/pkg/exp/ssh/Makefile | 16 + src/pkg/exp/ssh/channel.go | 317 + src/pkg/exp/ssh/common.go | 96 + src/pkg/exp/ssh/doc.go | 79 + src/pkg/exp/ssh/messages.go | 557 ++ src/pkg/exp/ssh/messages_test.go | 125 + src/pkg/exp/ssh/server.go | 714 +++ src/pkg/exp/ssh/server_shell.go | 399 ++ src/pkg/exp/ssh/server_shell_test.go | 134 + src/pkg/exp/ssh/transport.go | 322 ++ src/pkg/exp/ssh/transport_test.go | 37 + src/pkg/exp/template/html/Makefile | 8 + src/pkg/exp/template/html/clone.go | 90 + src/pkg/exp/template/html/clone_test.go | 90 + src/pkg/exp/template/html/content.go | 90 + src/pkg/exp/template/html/content_test.go | 222 + src/pkg/exp/template/html/context.go | 202 +- src/pkg/exp/template/html/css.go | 259 + src/pkg/exp/template/html/css_test.go | 277 + src/pkg/exp/template/html/doc.go | 190 + src/pkg/exp/template/html/error.go | 181 + src/pkg/exp/template/html/escape.go | 892 +-- src/pkg/exp/template/html/escape_test.go | 839 ++- src/pkg/exp/template/html/html.go | 243 + src/pkg/exp/template/html/html_test.go | 94 + src/pkg/exp/template/html/js.go | 59 +- src/pkg/exp/template/html/js_test.go | 2 +- src/pkg/exp/template/html/transition.go | 560 ++ src/pkg/exp/template/html/url.go | 110 + src/pkg/exp/template/html/url_test.go | 112 + src/pkg/flag/flag.go | 22 +- src/pkg/flag/flag_test.go | 3 +- src/pkg/go/build/build_test.go | 9 +- src/pkg/go/build/dir.go | 446 +- src/pkg/go/build/syslist_test.go | 4 +- src/pkg/go/printer/printer.go | 81 +- src/pkg/go/printer/printer_test.go | 14 +- src/pkg/go/token/Makefile | 1 + src/pkg/go/token/position.go | 20 +- src/pkg/go/token/serialize.go | 62 + src/pkg/go/token/serialize_test.go | 105 + src/pkg/gob/codec_test.go | 2 +- src/pkg/gob/decode.go | 76 +- src/pkg/gob/doc.go | 8 +- src/pkg/gob/encode.go | 13 +- src/pkg/gob/encoder_test.go | 52 +- src/pkg/gob/gobencdec_test.go | 39 +- src/pkg/http/cgi/host.go | 28 + src/pkg/http/cgi/host_test.go | 29 + src/pkg/http/chunked.go | 2 +- src/pkg/http/client.go | 7 +- src/pkg/http/cookie_test.go | 2 +- src/pkg/http/dump.go | 2 +- src/pkg/http/httptest/server.go | 82 +- src/pkg/http/request.go | 82 +- src/pkg/http/requestwrite_test.go | 210 +- src/pkg/http/response.go | 4 + src/pkg/http/serve_test.go | 37 + src/pkg/http/server.go | 13 +- src/pkg/http/transfer.go | 56 +- src/pkg/image/bmp/reader.go | 4 +- src/pkg/image/draw/bench_test.go | 12 +- src/pkg/image/draw/clip_test.go | 6 +- src/pkg/image/draw/draw_test.go | 18 +- src/pkg/image/gif/reader.go | 5 +- src/pkg/image/image.go | 45 +- src/pkg/image/image_test.go | 26 +- src/pkg/image/jpeg/reader.go | 2 +- src/pkg/image/jpeg/writer_test.go | 2 +- src/pkg/image/png/reader.go | 288 +- src/pkg/image/png/reader_test.go | 2 +- src/pkg/image/png/writer.go | 4 - src/pkg/image/png/writer_test.go | 8 +- src/pkg/image/tiff/reader.go | 8 +- src/pkg/index/suffixarray/qsufsort.go | 44 +- src/pkg/index/suffixarray/suffixarray.go | 86 +- src/pkg/index/suffixarray/suffixarray_test.go | 50 +- src/pkg/json/decode.go | 71 +- src/pkg/json/decode_test.go | 4 + src/pkg/json/encode.go | 28 +- src/pkg/json/encode_test.go | 2 + src/pkg/json/stream_test.go | 25 + src/pkg/mail/message_test.go | 1 - src/pkg/net/cgo_bsd.go | 2 + src/pkg/net/cgo_stub.go | 2 + src/pkg/net/cgo_unix.go | 2 + src/pkg/net/dnsclient_unix.go | 14 + src/pkg/net/dnsconfig.go | 2 + src/pkg/net/fd.go | 2 + src/pkg/net/fd_windows.go | 52 +- src/pkg/net/file.go | 2 + src/pkg/net/interface_bsd.go | 2 + src/pkg/net/interface_stub.go | 2 + src/pkg/net/iprawsock_posix.go | 2 + src/pkg/net/ipsock_posix.go | 2 + src/pkg/net/lookup_plan9.go | 5 + src/pkg/net/lookup_test.go | 18 + src/pkg/net/lookup_unix.go | 25 +- src/pkg/net/lookup_windows.go | 4 + src/pkg/net/newpollserver.go | 2 + src/pkg/net/port.go | 2 + src/pkg/net/sendfile_stub.go | 2 + src/pkg/net/sendfile_windows.go | 2 +- src/pkg/net/sock.go | 2 + src/pkg/net/sock_bsd.go | 2 + src/pkg/net/tcpsock_posix.go | 2 + src/pkg/net/textproto/reader.go | 33 +- src/pkg/net/textproto/reader_test.go | 53 + src/pkg/net/udpsock_posix.go | 2 + src/pkg/net/unixsock_posix.go | 2 + src/pkg/os/dir_unix.go | 2 + src/pkg/os/env_unix.go | 2 + src/pkg/os/error_posix.go | 2 + src/pkg/os/exec_posix.go | 2 + src/pkg/os/exec_unix.go | 2 + src/pkg/os/file_posix.go | 4 +- src/pkg/os/file_unix.go | 2 + src/pkg/os/file_windows.go | 9 - src/pkg/os/mkunixsignals.sh | 2 +- src/pkg/os/path.go | 2 +- src/pkg/os/path_unix.go | 2 + src/pkg/os/str.go | 2 + src/pkg/os/sys_bsd.go | 2 + src/pkg/os/user/lookup_stubs.go | 2 + src/pkg/os/user/lookup_unix.go | 2 + src/pkg/path/Makefile | 2 - src/pkg/path/filepath/match.go | 2 +- src/pkg/path/filepath/match_test.go | 10 + src/pkg/path/filepath/path.go | 87 +- src/pkg/path/filepath/path_test.go | 177 +- src/pkg/path/filepath/path_unix.go | 2 + src/pkg/path/filepath/path_windows.go | 35 +- src/pkg/reflect/type.go | 5 +- src/pkg/reflect/value.go | 2 + src/pkg/runtime/mgc0.c | 2 - src/pkg/runtime/mheap.c | 2 + src/pkg/runtime/pprof/pprof_test.go | 3 - src/pkg/runtime/runtime.h | 15 +- src/pkg/runtime/stack.h | 2 +- src/pkg/runtime/syscall_windows_test.go | 71 + src/pkg/runtime/windows/386/defs.h | 4 + src/pkg/runtime/windows/386/signal.c | 6 +- src/pkg/runtime/windows/386/sys.s | 67 +- src/pkg/runtime/windows/amd64/defs.h | 4 + src/pkg/runtime/windows/amd64/signal.c | 6 +- src/pkg/runtime/windows/amd64/sys.s | 42 +- src/pkg/runtime/windows/defs.c | 6 + src/pkg/runtime/windows/os.h | 5 +- src/pkg/runtime/windows/syscall.goc | 61 +- src/pkg/runtime/windows/thread.c | 178 +- src/pkg/sync/atomic/asm_386.s | 33 + src/pkg/sync/atomic/asm_amd64.s | 18 + src/pkg/sync/atomic/asm_arm.s | 24 + src/pkg/sync/atomic/asm_linux_arm.s | 12 + src/pkg/sync/atomic/atomic_test.go | 283 +- src/pkg/sync/atomic/doc.go | 14 +- src/pkg/syscall/bpf_bsd.go | 2 + src/pkg/syscall/exec_unix.go | 2 + src/pkg/syscall/mkerrors.sh | 3 +- src/pkg/syscall/mkerrors_windows.sh | 2 +- src/pkg/syscall/route_bsd.go | 2 + src/pkg/syscall/sockcmsg_unix.go | 2 + src/pkg/syscall/syscall_bsd.go | 2 + src/pkg/syscall/syscall_unix.go | 2 + src/pkg/syscall/syscall_windows.go | 38 +- src/pkg/syscall/zerrors_linux_386.go | 41 + src/pkg/syscall/zerrors_linux_amd64.go | 41 + src/pkg/syscall/zerrors_linux_arm.go | 41 + src/pkg/syscall/zerrors_windows.go | 2 +- src/pkg/syscall/zsyscall_windows_386.go | 30 +- src/pkg/syscall/zsyscall_windows_amd64.go | 30 +- src/pkg/syscall/ztypes_windows.go | 1 - src/pkg/template/Makefile | 1 + src/pkg/template/helper.go | 6 +- src/pkg/time/format.go | 12 +- src/pkg/time/sys_unix.go | 2 + src/pkg/time/time.go | 23 +- src/pkg/time/time_test.go | 48 +- src/pkg/time/zoneinfo_posix.go | 2 + src/pkg/time/zoneinfo_unix.go | 2 + src/pkg/time/zoneinfo_windows.go | 21 +- src/pkg/websocket/websocket.go | 17 +- src/pkg/websocket/websocket_test.go | 25 + 287 files changed, 22766 insertions(+), 4835 deletions(-) create mode 100644 src/cmd/gofix/imagenew.go create mode 100644 src/cmd/gofix/imagenew_test.go create mode 100644 src/cmd/gofmt/testdata/old.golden create mode 100644 src/cmd/gofmt/testdata/old.input create mode 100644 src/cmd/gofmt/testdata/stdin1.golden create mode 100644 src/cmd/gofmt/testdata/stdin1.golden.gofmt create mode 100644 src/cmd/gofmt/testdata/stdin1.input create mode 100644 src/cmd/gofmt/testdata/stdin1.input.gofmt create mode 100644 src/cmd/gofmt/testdata/stdin2.golden create mode 100644 src/cmd/gofmt/testdata/stdin2.golden.gofmt create mode 100644 src/cmd/gofmt/testdata/stdin2.input create mode 100644 src/cmd/gofmt/testdata/stdin2.input.gofmt create mode 100644 src/cmd/gofmt/testdata/stdin3.golden create mode 100644 src/cmd/gofmt/testdata/stdin3.golden.gofmt create mode 100644 src/cmd/gofmt/testdata/stdin3.input create mode 100644 src/cmd/gofmt/testdata/stdin3.input.gofmt create mode 100644 src/cmd/gofmt/testdata/stdin4.golden create mode 100644 src/cmd/gofmt/testdata/stdin4.golden.gofmt create mode 100644 src/cmd/gofmt/testdata/stdin4.input create mode 100644 src/cmd/gofmt/testdata/stdin4.input.gofmt create mode 100644 src/pkg/crypto/bcrypt/Makefile create mode 100644 src/pkg/crypto/bcrypt/base64.go create mode 100644 src/pkg/crypto/bcrypt/bcrypt.go create mode 100644 src/pkg/crypto/bcrypt/bcrypt_test.go create mode 100644 src/pkg/exp/norm/normregtest.go delete mode 100644 src/pkg/exp/regexp/re2.txt.gz create mode 100644 src/pkg/exp/regexp/testdata/README create mode 100644 src/pkg/exp/regexp/testdata/basic.dat create mode 100644 src/pkg/exp/regexp/testdata/nullsubexpr.dat create mode 100644 src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2 create mode 100644 src/pkg/exp/regexp/testdata/re2-search.txt create mode 100644 src/pkg/exp/regexp/testdata/repetition.dat create mode 100644 src/pkg/exp/regexp/testdata/testregex.c create mode 100644 src/pkg/exp/ssh/Makefile create mode 100644 src/pkg/exp/ssh/channel.go create mode 100644 src/pkg/exp/ssh/common.go create mode 100644 src/pkg/exp/ssh/doc.go create mode 100644 src/pkg/exp/ssh/messages.go create mode 100644 src/pkg/exp/ssh/messages_test.go create mode 100644 src/pkg/exp/ssh/server.go create mode 100644 src/pkg/exp/ssh/server_shell.go create mode 100644 src/pkg/exp/ssh/server_shell_test.go create mode 100644 src/pkg/exp/ssh/transport.go create mode 100644 src/pkg/exp/ssh/transport_test.go create mode 100644 src/pkg/exp/template/html/clone.go create mode 100644 src/pkg/exp/template/html/clone_test.go create mode 100644 src/pkg/exp/template/html/content.go create mode 100644 src/pkg/exp/template/html/content_test.go create mode 100644 src/pkg/exp/template/html/css.go create mode 100644 src/pkg/exp/template/html/css_test.go create mode 100644 src/pkg/exp/template/html/doc.go create mode 100644 src/pkg/exp/template/html/error.go create mode 100644 src/pkg/exp/template/html/html.go create mode 100644 src/pkg/exp/template/html/html_test.go create mode 100644 src/pkg/exp/template/html/transition.go create mode 100644 src/pkg/exp/template/html/url.go create mode 100644 src/pkg/exp/template/html/url_test.go create mode 100644 src/pkg/go/token/serialize.go create mode 100644 src/pkg/go/token/serialize_test.go (limited to 'src') diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index 518951fde..6c7f96483 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -417,7 +417,7 @@ adddynsym(Sym *s) return; if(s->dynimpname == nil) - diag("adddynsym: no dynamic name for %s", s->name, *(int32*)0); + diag("adddynsym: no dynamic name for %s", s->name); if(iself) { s->dynid = nelfsym++; diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index 7faece81c..dc9edd6fd 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -95,5 +95,8 @@ process of using cgo. See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. Cgo does not yet work with gccgo. + +See "C? Go? Cgo!" for an introduction to using cgo: +http://blog.golang.org/2011/03/c-go-cgo.html */ package documentation diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 7ec4d8ccf..04d95f0b9 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -20,7 +20,6 @@ import ( "go/parser" "go/token" "os" - "runtime" "strconv" "strings" "unicode" @@ -91,9 +90,9 @@ NextLine: case 2: k = kf[1] switch kf[0] { - case runtime.GOOS: - case runtime.GOARCH: - case runtime.GOOS + "/" + runtime.GOARCH: + case goos: + case goarch: + case goos + "/" + goarch: default: continue NextLine } @@ -688,7 +687,7 @@ func (p *Package) gccName() (ret string) { // gccMachine returns the gcc -m flag to use, either "-m32" or "-m64". func (p *Package) gccMachine() []string { - switch runtime.GOARCH { + switch goarch { case "amd64": return []string{"-m64"} case "386": diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index be9c2bc4f..106698114 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -20,6 +20,7 @@ import ( "os" "path/filepath" "reflect" + "runtime" "strings" ) @@ -122,6 +123,8 @@ var fset = token.NewFileSet() var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file") +var goarch, goos string + func main() { flag.Usage = usage flag.Parse() @@ -162,13 +165,17 @@ func main() { goFiles := args[i:] - arch := os.Getenv("GOARCH") - if arch == "" { - fatalf("$GOARCH is not set") + goarch = runtime.GOARCH + if s := os.Getenv("GOARCH"); s != "" { + goarch = s + } + goos = runtime.GOOS + if s := os.Getenv("GOOS"); s != "" { + goos = s } - ptrSize := ptrSizeMap[arch] + ptrSize := ptrSizeMap[goarch] if ptrSize == 0 { - fatalf("unknown $GOARCH %q", arch) + fatalf("unknown $GOARCH %q", goarch) } // Clear locale variables so gcc emits English errors [sic]. diff --git a/src/cmd/gc/cplx.c b/src/cmd/gc/cplx.c index 5bc8d64aa..52038e71c 100644 --- a/src/cmd/gc/cplx.c +++ b/src/cmd/gc/cplx.c @@ -133,6 +133,9 @@ complexgen(Node *n, Node *res) dump("\ncomplexgen-n", n); dump("complexgen-res", res); } + + while(n->op == OCONVNOP) + n = n->left; // pick off float/complex opcodes switch(n->op) { diff --git a/src/cmd/gc/go.errors b/src/cmd/gc/go.errors index b5af4678c..e29cfff5b 100644 --- a/src/cmd/gc/go.errors +++ b/src/cmd/gc/go.errors @@ -67,4 +67,7 @@ static struct { % loadsys package imports LFUNC LNAME '(' ')' '{' LFUNC LNAME "nested func not allowed", + + % loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header loop_body LELSE ';' + "else must be followed by if or statement block" }; diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index a5e92bd4d..0c007f5f0 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -57,7 +57,7 @@ static void fixlbrace(int); %type compound_stmt dotname embed expr complitexpr %type expr_or_type %type fndcl fnliteral -%type for_body for_header for_stmt if_header if_stmt non_dcl_stmt +%type for_body for_header for_stmt if_header if_stmt else non_dcl_stmt %type interfacedcl keyval labelname name %type name_or_type non_expr_type %type new_name dcl_name oexpr typedclname @@ -640,6 +640,7 @@ if_header: $$->ntest = $3; } +/* IF cond body (ELSE IF cond body)* (ELSE block)? */ if_stmt: LIF { @@ -652,9 +653,27 @@ if_stmt: } loop_body { + $3->nbody = $5; + } + else + { + popdcl(); $$ = $3; - $$->nbody = $5; - // no popdcl; maybe there's an LELSE + if($7 != N) + $$->nelse = list1($7); + } + +else: + { + $$ = N; + } +| LELSE if_stmt + { + $$ = $2; + } +| LELSE compound_stmt + { + $$ = $2; } switch_stmt: @@ -1474,19 +1493,6 @@ non_dcl_stmt: | switch_stmt | select_stmt | if_stmt - { - popdcl(); - $$ = $1; - } -| if_stmt LELSE stmt - { - if($3->op != OIF && $3->op != OBLOCK) - yyerror("missing { } after else"); - - popdcl(); - $$ = $1; - $$->nelse = list1($3); - } | labelname ':' { $1 = nod(OLABEL, $1, N); diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c index d6fe6f65d..730b42671 100644 --- a/src/cmd/gc/obj.c +++ b/src/cmd/gc/obj.c @@ -125,7 +125,6 @@ static void outhist(Biobuf *b) { Hist *h; - int i, depth = 0; char *p, ds[] = {'c', ':', '/', 0}; for(h = hist; h != H; h = h->link) { @@ -162,14 +161,7 @@ outhist(Biobuf *b) outzfile(b, p); } } - if(h->offset > 0) { - //line directive - depth++; - } - } else if(depth > 0) { - for(i = 0; i < depth; i++) - zhist(b, h->line, h->offset); - depth = 0; + } zhist(b, h->line, h->offset); } diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 9448c3ffe..b450b9b0e 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -548,9 +548,13 @@ maptype(Type *key, Type *val) { Type *t; - - if(key != nil && key->etype != TANY && algtype(key) == ANOEQ) { - if(key->etype == TFORW) { + if(key != nil) { + switch(key->etype) { + case TARRAY: + case TSTRUCT: + yyerror("invalid map key type %T", key); + break; + case TFORW: // map[key] used during definition of key. // postpone check until key is fully defined. // if there are multiple uses of map[key] @@ -559,8 +563,8 @@ maptype(Type *key, Type *val) // good enough. if(key->maplineno == 0) key->maplineno = lineno; - } else - yyerror("invalid map key type %T", key); + break; + } } t = typ(TMAP); t->down = key; diff --git a/src/cmd/godoc/appinit.go b/src/cmd/godoc/appinit.go index baba53fa6..8c93425f3 100644 --- a/src/cmd/godoc/appinit.go +++ b/src/cmd/godoc/appinit.go @@ -4,8 +4,9 @@ // To run godoc under app engine, substitute main.go with // this file (appinit.go), provide a .zip file containing -// the file system to serve, and adjust the configuration -// parameters in appconfig.go accordingly. +// the file system to serve, the index file (or files) +// containing the pre-computed search index and adjust +// the configuration parameters in appconfig.go accordingly. // // The current app engine SDK may be based on an older Go // release version. To correct for version skew, copy newer @@ -17,7 +18,7 @@ // // The directory structure should look as follows: // -// godoc // directory containing the app engine app +// godoc-app // directory containing the app engine app // alt // alternative packages directory to // // correct for version skew // strings // never version of the strings package @@ -32,9 +33,8 @@ // // To run app the engine emulator locally: // -// dev_appserver.py -a 0 godoc +// dev_appserver.py -a 0 godoc-app // -// godoc is the top-level "goroot" directory. // The godoc home page is served at: :8080 and localhost:8080. package main @@ -63,7 +63,7 @@ func init() { *goroot = path.Join("/", zipGoroot) // fsHttp paths are relative to '/' *indexEnabled = true *indexFiles = indexFilenames - *maxResults = 0 // save space for now + *maxResults = 100 // reduce latency by limiting the number of fulltext search results *indexThrottle = 0.3 // in case *indexFiles is empty (and thus the indexer is run) // read .zip file and set up file systems @@ -72,6 +72,7 @@ func init() { if err != nil { log.Fatalf("%s: %s\n", zipfile, err) } + // rc is never closed (app running forever) fs = NewZipFS(rc) fsHttp = NewHttpZipFS(rc, *goroot) diff --git a/src/cmd/godoc/codewalk.go b/src/cmd/godoc/codewalk.go index 602aa43a8..fb5f27596 100644 --- a/src/cmd/godoc/codewalk.go +++ b/src/cmd/godoc/codewalk.go @@ -18,7 +18,7 @@ import ( "io" "log" "os" - "regexp" + "exp/regexp" "sort" "strconv" "strings" @@ -129,7 +129,7 @@ func loadCodewalk(filename string) (*Codewalk, os.Error) { i = len(st.Src) } filename := st.Src[0:i] - data, err := fs.ReadFile(absolutePath(filename, *goroot)) + data, err := ReadFile(fs, absolutePath(filename, *goroot)) if err != nil { st.Err = err continue @@ -208,7 +208,7 @@ func codewalkDir(w http.ResponseWriter, r *http.Request, relpath, abspath string // the usual godoc HTML wrapper. func codewalkFileprint(w http.ResponseWriter, r *http.Request, f string) { abspath := absolutePath(f, *goroot) - data, err := fs.ReadFile(abspath) + data, err := ReadFile(fs, abspath) if err != nil { log.Print(err) serveError(w, r, f, err) diff --git a/src/cmd/godoc/doc.go b/src/cmd/godoc/doc.go index 813527d28..3f0b8e458 100644 --- a/src/cmd/godoc/doc.go +++ b/src/cmd/godoc/doc.go @@ -137,5 +137,8 @@ one may run godoc as follows: godoc -http=:6060 -zip=go.zip -goroot=$HOME/go + +See "Godoc: documenting Go code" for how to write good comments for godoc: +http://blog.golang.org/2011/03/godoc-documenting-go-code.html */ package documentation diff --git a/src/cmd/godoc/filesystem.go b/src/cmd/godoc/filesystem.go index a68c08592..011977af9 100644 --- a/src/cmd/godoc/filesystem.go +++ b/src/cmd/godoc/filesystem.go @@ -31,7 +31,16 @@ type FileSystem interface { Lstat(path string) (FileInfo, os.Error) Stat(path string) (FileInfo, os.Error) ReadDir(path string) ([]FileInfo, os.Error) - ReadFile(path string) ([]byte, os.Error) +} + +// ReadFile reads the file named by path from fs and returns the contents. +func ReadFile(fs FileSystem, path string) ([]byte, os.Error) { + rc, err := fs.Open(path) + if err != nil { + return nil, err + } + defer rc.Close() + return ioutil.ReadAll(rc) } // ---------------------------------------------------------------------------- @@ -98,7 +107,3 @@ func (osFS) ReadDir(path string) ([]FileInfo, os.Error) { } return l1, nil } - -func (osFS) ReadFile(path string) ([]byte, os.Error) { - return ioutil.ReadFile(path) -} diff --git a/src/cmd/godoc/format.go b/src/cmd/godoc/format.go index 78dde4166..91b746034 100644 --- a/src/cmd/godoc/format.go +++ b/src/cmd/godoc/format.go @@ -15,7 +15,7 @@ import ( "go/scanner" "go/token" "io" - "regexp" + "exp/regexp" "strconv" "template" ) diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index 6b646a1a6..3bf721bcc 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -19,7 +19,7 @@ import ( "os" "path" "path/filepath" - "regexp" + "exp/regexp" "runtime" "sort" "strings" @@ -149,7 +149,7 @@ func getPathFilter() func(string) bool { // readDirList reads a file containing a newline-separated list // of directory paths and returns the list of paths. func readDirList(filename string) ([]string, os.Error) { - contents, err := fs.ReadFile(filename) + contents, err := ReadFile(fs, filename) if err != nil { return nil, err } @@ -546,7 +546,7 @@ func readTemplate(name string) *template.Template { // use underlying file system fs to read the template file // (cannot use template ParseFile functions directly) - data, err := fs.ReadFile(path) + data, err := ReadFile(fs, path) if err != nil { log.Fatal("readTemplate: ", err) } @@ -636,7 +636,7 @@ func extractString(src []byte, rx *regexp.Regexp) (s string) { func serveHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath string) { // get HTML body contents - src, err := fs.ReadFile(abspath) + src, err := ReadFile(fs, abspath) if err != nil { log.Printf("ReadFile: %s", err) serveError(w, r, relpath, err) @@ -685,7 +685,7 @@ func redirect(w http.ResponseWriter, r *http.Request) (redirected bool) { } func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, title string) { - src, err := fs.ReadFile(abspath) + src, err := ReadFile(fs, abspath) if err != nil { log.Printf("ReadFile: %s", err) serveError(w, r, relpath, err) @@ -815,6 +815,41 @@ type httpHandler struct { isPkg bool // true if this handler serves real package documentation (as opposed to command documentation) } +// fsReadDir implements ReadDir for the go/build package. +func fsReadDir(dir string) ([]*os.FileInfo, os.Error) { + fi, err := fs.ReadDir(dir) + if err != nil { + return nil, err + } + + // Convert []FileInfo to []*os.FileInfo. + osfi := make([]*os.FileInfo, len(fi)) + for i, f := range fi { + mode := uint32(S_IFREG) + if f.IsDirectory() { + mode = S_IFDIR + } + osfi[i] = &os.FileInfo{Name: f.Name(), Size: f.Size(), Mtime_ns: f.Mtime_ns(), Mode: mode} + } + return osfi, nil +} + +// fsReadFile implements ReadFile for the go/build package. +func fsReadFile(dir, name string) (path string, data []byte, err os.Error) { + path = filepath.Join(dir, name) + data, err = ReadFile(fs, path) + return +} + +func inList(name string, list []string) bool { + for _, l := range list { + if name == l { + return true + } + } + return false +} + // getPageInfo returns the PageInfo for a package directory abspath. If the // parameter genAST is set, an AST containing only the package exports is // computed (PageInfo.PAst), otherwise package documentation (PageInfo.Doc) @@ -824,11 +859,40 @@ type httpHandler struct { // PageInfo.Err is set to the respective error but the error is not logged. // func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInfoMode) PageInfo { + var pkgFiles []string + + // If we're showing the default package, restrict to the ones + // that would be used when building the package on this + // system. This makes sure that if there are separate + // implementations for, say, Windows vs Unix, we don't + // jumble them all together. + if pkgname == "" { + // Note: Uses current binary's GOOS/GOARCH. + // To use different pair, such as if we allowed the user + // to choose, set ctxt.GOOS and ctxt.GOARCH before + // calling ctxt.ScanDir. + ctxt := build.DefaultContext + ctxt.ReadDir = fsReadDir + ctxt.ReadFile = fsReadFile + dir, err := ctxt.ScanDir(abspath) + if err == nil { + pkgFiles = append(dir.GoFiles, dir.CgoFiles...) + } + } + // filter function to select the desired .go files filter := func(d FileInfo) bool { + // Only Go files. + if !isPkgFile(d) { + return false + } // If we are looking at cmd documentation, only accept // the special fakePkgFile containing the documentation. - return isPkgFile(d) && (h.isPkg || d.Name() == fakePkgFile) + if !h.isPkg { + return d.Name() == fakePkgFile + } + // Also restrict file list to pkgFiles. + return pkgFiles == nil || inList(d.Name(), pkgFiles) } // get package ASTs @@ -1016,6 +1080,7 @@ type SearchResult struct { Alert string // error or warning message // identifier matches + Pak HitList // packages matching Query Hit *LookupResult // identifier matches of Query Alt *AltWords // alternative identifiers to look for @@ -1034,7 +1099,7 @@ func lookup(query string) (result SearchResult) { // identifier search var err os.Error - result.Hit, result.Alt, err = index.Lookup(query) + result.Pak, result.Hit, result.Alt, err = index.Lookup(query) if err != nil && *maxResults <= 0 { // ignore the error if full text search is enabled // since the query may be a valid regular expression diff --git a/src/cmd/godoc/index.go b/src/cmd/godoc/index.go index b99363491..2543f9216 100644 --- a/src/cmd/godoc/index.go +++ b/src/cmd/godoc/index.go @@ -48,7 +48,7 @@ import ( "io" "os" "path/filepath" - "regexp" + "exp/regexp" "sort" "strings" ) @@ -344,6 +344,8 @@ func reduce(h0 RunList) HitList { return h } +// filter returns a new HitList created by filtering +// all PakRuns from h that have a matching pakname. func (h HitList) filter(pakname string) HitList { var hh HitList for _, p := range h { @@ -831,34 +833,58 @@ func NewIndex(dirnames <-chan string, fulltextIndex bool, throttle float64) *Ind return &Index{x.fset, suffixes, words, alts, x.snippets, x.stats} } -type FileIndex struct { +type fileIndex struct { Words map[string]*LookupResult Alts map[string]*AltWords Snippets []*Snippet + Fulltext bool } // Write writes the index x to w. func (x *Index) Write(w io.Writer) os.Error { + fulltext := false if x.suffixes != nil { - panic("no support for writing full text index yet") + fulltext = true } - fx := FileIndex{ + fx := fileIndex{ x.words, x.alts, x.snippets, + fulltext, } - return gob.NewEncoder(w).Encode(fx) + if err := gob.NewEncoder(w).Encode(fx); err != nil { + return err + } + if fulltext { + if err := x.fset.Write(w); err != nil { + return err + } + if err := x.suffixes.Write(w); err != nil { + return err + } + } + return nil } // Read reads the index from r into x; x must not be nil. func (x *Index) Read(r io.Reader) os.Error { - var fx FileIndex + var fx fileIndex if err := gob.NewDecoder(r).Decode(&fx); err != nil { return err } x.words = fx.Words x.alts = fx.Alts x.snippets = fx.Snippets + if fx.Fulltext { + x.fset = token.NewFileSet() + if err := x.fset.Read(r); err != nil { + return err + } + x.suffixes = new(suffixarray.Index) + if err := x.suffixes.Read(r); err != nil { + return err + } + } return nil } @@ -867,7 +893,7 @@ func (x *Index) Stats() Statistics { return x.stats } -func (x *Index) LookupWord(w string) (match *LookupResult, alt *AltWords) { +func (x *Index) lookupWord(w string) (match *LookupResult, alt *AltWords) { match = x.words[w] alt = x.alts[canonical(w)] // remove current spelling from alternatives @@ -891,9 +917,10 @@ func isIdentifier(s string) bool { } // For a given query, which is either a single identifier or a qualified -// identifier, Lookup returns a LookupResult, and a list of alternative -// spellings, if any. If the query syntax is wrong, an error is reported. -func (x *Index) Lookup(query string) (match *LookupResult, alt *AltWords, err os.Error) { +// identifier, Lookup returns a list of packages, a LookupResult, and a +// list of alternative spellings, if any. Any and all results may be nil. +// If the query syntax is wrong, an error is reported. +func (x *Index) Lookup(query string) (paks HitList, match *LookupResult, alt *AltWords, err os.Error) { ss := strings.Split(query, ".") // check query syntax @@ -904,15 +931,23 @@ func (x *Index) Lookup(query string) (match *LookupResult, alt *AltWords, err os } } + // handle simple and qualified identifiers switch len(ss) { case 1: - match, alt = x.LookupWord(ss[0]) + ident := ss[0] + match, alt = x.lookupWord(ident) + if match != nil { + // found a match - filter packages with same name + // for the list of packages called ident, if any + paks = match.Others.filter(ident) + } case 2: - pakname := ss[0] - match, alt = x.LookupWord(ss[1]) + pakname, ident := ss[0], ss[1] + match, alt = x.lookupWord(ident) if match != nil { // found a match - filter by package name + // (no paks - package names are not qualified) decls := match.Decls.filter(pakname) others := match.Others.filter(pakname) match = &LookupResult{decls, others} diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go index 74d3111ff..15d70c49b 100644 --- a/src/cmd/godoc/main.go +++ b/src/cmd/godoc/main.go @@ -40,7 +40,7 @@ import ( "os" "path" "path/filepath" - "regexp" + "exp/regexp" "runtime" "strings" "time" @@ -257,11 +257,6 @@ func main() { readTemplates() initHandlers() - if (*indexEnabled || *writeIndex) && *indexFiles != "" && *maxResults > 0 { - log.Println("warning: no support for full-text index yet (setting -maxresults to 0)") - *maxResults = 0 - } - if *writeIndex { // Write search index and exit. if *indexFiles == "" { diff --git a/src/cmd/godoc/parser.go b/src/cmd/godoc/parser.go index cc1780a4b..a2920539f 100644 --- a/src/cmd/godoc/parser.go +++ b/src/cmd/godoc/parser.go @@ -18,7 +18,7 @@ import ( ) func parseFile(fset *token.FileSet, filename string, mode uint) (*ast.File, os.Error) { - src, err := fs.ReadFile(filename) + src, err := ReadFile(fs, filename) if err != nil { return nil, err } diff --git a/src/cmd/godoc/zip.go b/src/cmd/godoc/zip.go index 46d7112e5..86cd79b17 100644 --- a/src/cmd/godoc/zip.go +++ b/src/cmd/godoc/zip.go @@ -22,7 +22,6 @@ import ( "archive/zip" "fmt" "io" - "io/ioutil" "os" "path" "sort" @@ -153,14 +152,6 @@ func (fs *zipFS) ReadDir(abspath string) ([]FileInfo, os.Error) { return list, nil } -func (fs *zipFS) ReadFile(abspath string) ([]byte, os.Error) { - rc, err := fs.Open(abspath) - if err != nil { - return nil, err - } - return ioutil.ReadAll(rc) -} - func NewZipFS(rc *zip.ReadCloser) FileSystem { list := make(zipList, len(rc.File)) copy(list, rc.File) // sort a copy of rc.File diff --git a/src/cmd/gofix/Makefile b/src/cmd/gofix/Makefile index d1f3ac605..b2725c572 100644 --- a/src/cmd/gofix/Makefile +++ b/src/cmd/gofix/Makefile @@ -12,6 +12,7 @@ GOFILES=\ httpfs.go\ httpheaders.go\ httpserver.go\ + imagenew.go\ main.go\ netdial.go\ netudpgroup.go\ diff --git a/src/cmd/gofix/imagenew.go b/src/cmd/gofix/imagenew.go new file mode 100644 index 000000000..0b3c0a307 --- /dev/null +++ b/src/cmd/gofix/imagenew.go @@ -0,0 +1,82 @@ +// 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 main + +import ( + "go/ast" +) + +var imagenewFix = fix{ + "imagenew", + imagenew, + `Adapt image.NewXxx calls to pass an image.Rectangle instead of (w, h int). + +http://codereview.appspot.com/4964073 +`, +} + +func init() { + register(imagenewFix) +} + +var imagenewFuncs = map[string]bool{ + "NewRGBA": true, + "NewRGBA64": true, + "NewNRGBA": true, + "NewNRGBA64": true, + "NewAlpha": true, + "NewAlpha16": true, + "NewGray": true, + "NewGray16": true, +} + +func imagenew(f *ast.File) bool { + if !imports(f, "image") { + return false + } + + fixed := false + walk(f, func(n interface{}) { + call, ok := n.(*ast.CallExpr) + if !ok { + return + } + isNewFunc := false + for newFunc := range imagenewFuncs { + if len(call.Args) == 2 && isPkgDot(call.Fun, "image", newFunc) { + isNewFunc = true + break + } + } + if len(call.Args) == 3 && isPkgDot(call.Fun, "image", "NewPaletted") { + isNewFunc = true + } + if !isNewFunc { + return + } + // Replace image.NewXxx(w, h) with image.NewXxx(image.Rect(0, 0, w, h)). + rectArgs := []ast.Expr{ + &ast.BasicLit{Value: "0"}, + &ast.BasicLit{Value: "0"}, + } + rectArgs = append(rectArgs, call.Args[:2]...) + rect := []ast.Expr{ + &ast.CallExpr{ + Fun: &ast.SelectorExpr{ + X: &ast.Ident{ + Name: "image", + }, + Sel: &ast.Ident{ + Name: "Rect", + }, + }, + Args: rectArgs, + }, + } + call.Args = append(rect, call.Args[2:]...) + fixed = true + }) + return fixed +} diff --git a/src/cmd/gofix/imagenew_test.go b/src/cmd/gofix/imagenew_test.go new file mode 100644 index 000000000..3d40fea81 --- /dev/null +++ b/src/cmd/gofix/imagenew_test.go @@ -0,0 +1,53 @@ +// 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 main + +func init() { + addTestCases(imagenewTests) +} + +var imagenewTests = []testCase{ + { + Name: "imagenew.0", + In: `package main + +import ( + "image" +) + +func f() { + image.NewRGBA(1, 2) + image.NewRGBA64(1, 2) + image.NewNRGBA(1, 2) + image.NewNRGBA64(1, 2) + image.NewAlpha(1, 2) + image.NewAlpha16(1, 2) + image.NewGray(1, 2) + image.NewGray16(1, 2) + var m image.PalettedColorModel + image.NewPaletted(1, 2, m) +} +`, + Out: `package main + +import ( + "image" +) + +func f() { + image.NewRGBA(image.Rect(0, 0, 1, 2)) + image.NewRGBA64(image.Rect(0, 0, 1, 2)) + image.NewNRGBA(image.Rect(0, 0, 1, 2)) + image.NewNRGBA64(image.Rect(0, 0, 1, 2)) + image.NewAlpha(image.Rect(0, 0, 1, 2)) + image.NewAlpha16(image.Rect(0, 0, 1, 2)) + image.NewGray(image.Rect(0, 0, 1, 2)) + image.NewGray16(image.Rect(0, 0, 1, 2)) + var m image.PalettedColorModel + image.NewPaletted(image.Rect(0, 0, 1, 2), m) +} +`, + }, +} diff --git a/src/cmd/gofix/main.go b/src/cmd/gofix/main.go index e7e7013c5..e0709fc8b 100644 --- a/src/cmd/gofix/main.go +++ b/src/cmd/gofix/main.go @@ -198,31 +198,17 @@ func report(err os.Error) { } func walkDir(path string) { - v := make(fileVisitor) - go func() { - filepath.Walk(path, v, v) - close(v) - }() - for err := range v { - if err != nil { - report(err) - } - } -} - -type fileVisitor chan os.Error - -func (v fileVisitor) VisitDir(path string, f *os.FileInfo) bool { - return true + filepath.Walk(path, visitFile) } -func (v fileVisitor) VisitFile(path string, f *os.FileInfo) { - if isGoFile(f) { - v <- nil // synchronize error handler - if err := processFile(path, false); err != nil { - v <- err - } +func visitFile(path string, f *os.FileInfo, err os.Error) os.Error { + if err == nil && isGoFile(f) { + err = processFile(path, false) + } + if err != nil { + report(err) } + return nil } func isGoFile(f *os.FileInfo) bool { diff --git a/src/cmd/gofmt/doc.go b/src/cmd/gofmt/doc.go index fca42b76b..3a20c21e0 100644 --- a/src/cmd/gofmt/doc.go +++ b/src/cmd/gofmt/doc.go @@ -53,6 +53,12 @@ In the pattern, single-character lowercase identifiers serve as wildcards matching arbitrary sub-expressions; those expressions will be substituted for the same identifiers in the replacement. +When gofmt reads from standard input, it accepts either a full Go program +or a program fragment. A program fragment must be a syntactically +valid declaration list, statement list, or expression. When formatting +such a fragment, gofmt preserves leading indentation as well as leading +and trailing spaces, so that individual sections of a Go program can be +formatted by piping them through gofmt. Examples diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index 975ae6ac6..1c0efb6db 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -86,7 +86,7 @@ func isGoFile(f *os.FileInfo) bool { } // If in == nil, the source is the contents of the file with the given filename. -func processFile(filename string, in io.Reader, out io.Writer) os.Error { +func processFile(filename string, in io.Reader, out io.Writer, stdin bool) os.Error { if in == nil { f, err := os.Open(filename) if err != nil { @@ -101,7 +101,7 @@ func processFile(filename string, in io.Reader, out io.Writer) os.Error { return err } - file, err := parser.ParseFile(fset, filename, src, parserMode) + file, adjust, err := parse(filename, src, stdin) if err != nil { return err } @@ -119,7 +119,7 @@ func processFile(filename string, in io.Reader, out io.Writer) os.Error { if err != nil { return err } - res := buf.Bytes() + res := adjust(src, buf.Bytes()) if !bytes.Equal(src, res) { // formatting has changed @@ -149,32 +149,18 @@ func processFile(filename string, in io.Reader, out io.Writer) os.Error { return err } -type fileVisitor chan os.Error - -func (v fileVisitor) VisitDir(path string, f *os.FileInfo) bool { - return true -} - -func (v fileVisitor) VisitFile(path string, f *os.FileInfo) { - if isGoFile(f) { - v <- nil // synchronize error handler - if err := processFile(path, nil, os.Stdout); err != nil { - v <- err - } +func visitFile(path string, f *os.FileInfo, err os.Error) os.Error { + if err == nil && isGoFile(f) { + err = processFile(path, nil, os.Stdout, false) } + if err != nil { + report(err) + } + return nil } func walkDir(path string) { - v := make(fileVisitor) - go func() { - filepath.Walk(path, v, v) - close(v) - }() - for err := range v { - if err != nil { - report(err) - } - } + filepath.Walk(path, visitFile) } func main() { @@ -211,7 +197,7 @@ func gofmtMain() { initRewrite() if flag.NArg() == 0 { - if err := processFile("", os.Stdin, os.Stdout); err != nil { + if err := processFile("", os.Stdin, os.Stdout, true); err != nil { report(err) } return @@ -223,7 +209,7 @@ func gofmtMain() { case err != nil: report(err) case dir.IsRegular(): - if err := processFile(path, nil, os.Stdout); err != nil { + if err := processFile(path, nil, os.Stdout, false); err != nil { report(err) } case dir.IsDirectory(): @@ -259,3 +245,109 @@ func diff(b1, b2 []byte) (data []byte, err os.Error) { return } + +// parse parses src, which was read from filename, +// as a Go source file or statement list. +func parse(filename string, src []byte, stdin bool) (*ast.File, func(orig, src []byte) []byte, os.Error) { + // Try as whole source file. + file, err := parser.ParseFile(fset, filename, src, parserMode) + if err == nil { + adjust := func(orig, src []byte) []byte { return src } + return file, adjust, nil + } + // If the error is that the source file didn't begin with a + // package line and this is standard input, fall through to + // try as a source fragment. Stop and return on any other error. + if !stdin || !strings.Contains(err.String(), "expected 'package'") { + return nil, nil, err + } + + // If this is a declaration list, make it a source file + // by inserting a package clause. + // Insert using a ;, not a newline, so that the line numbers + // in psrc match the ones in src. + psrc := append([]byte("package p;"), src...) + file, err = parser.ParseFile(fset, filename, psrc, parserMode) + if err == nil { + adjust := func(orig, src []byte) []byte { + // Remove the package clause. + // Gofmt has turned the ; into a \n. + src = src[len("package p\n"):] + return matchSpace(orig, src) + } + return file, adjust, nil + } + // If the error is that the source file didn't begin with a + // declaration, fall through to try as a statement list. + // Stop and return on any other error. + if !strings.Contains(err.String(), "expected declaration") { + return nil, nil, err + } + + // If this is a statement list, make it a source file + // by inserting a package clause and turning the list + // into a function body. This handles expressions too. + // Insert using a ;, not a newline, so that the line numbers + // in fsrc match the ones in src. + fsrc := append(append([]byte("package p; func _() {"), src...), '}') + file, err = parser.ParseFile(fset, filename, fsrc, parserMode) + if err == nil { + adjust := func(orig, src []byte) []byte { + // Remove the wrapping. + // Gofmt has turned the ; into a \n\n. + src = src[len("package p\n\nfunc _() {"):] + src = src[:len(src)-len("}\n")] + // Gofmt has also indented the function body one level. + // Remove that indent. + src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1) + return matchSpace(orig, src) + } + return file, adjust, nil + } + + // Failed, and out of options. + return nil, nil, err +} + +func cutSpace(b []byte) (before, middle, after []byte) { + i := 0 + for i < len(b) && (b[i] == ' ' || b[i] == '\t' || b[i] == '\n') { + i++ + } + j := len(b) + for j > 0 && (b[j-1] == ' ' || b[j-1] == '\t' || b[j-1] == '\n') { + j-- + } + return b[:i], b[i:j], b[j:] +} + +// matchSpace reformats src to use the same space context as orig. +// 1) If orig begins with blank lines, matchSpace inserts them at the beginning of src. +// 2) matchSpace copies the indentation of the first non-blank line in orig +// to every non-blank line in src. +// 3) matchSpace copies the trailing space from orig and uses it in place +// of src's trailing space. +func matchSpace(orig []byte, src []byte) []byte { + before, _, after := cutSpace(orig) + i := bytes.LastIndex(before, []byte{'\n'}) + before, indent := before[:i+1], before[i+1:] + + _, src, _ = cutSpace(src) + + var b bytes.Buffer + b.Write(before) + for len(src) > 0 { + line := src + if i := bytes.IndexByte(line, '\n'); i >= 0 { + line, src = line[:i+1], line[i+1:] + } else { + src = nil + } + if len(line) > 0 && line[0] != '\n' { // not blank + b.Write(indent) + } + b.Write(line) + } + b.Write(after) + return b.Bytes() +} diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go index 2e35ce9a4..87b02dad7 100644 --- a/src/cmd/gofmt/gofmt_test.go +++ b/src/cmd/gofmt/gofmt_test.go @@ -12,13 +12,11 @@ import ( "testing" ) -func runTest(t *testing.T, dirname, in, out, flags string) { - in = filepath.Join(dirname, in) - out = filepath.Join(dirname, out) - +func runTest(t *testing.T, in, out, flags string) { // process flags *simplifyAST = false *rewriteRule = "" + stdin := false for _, flag := range strings.Split(flags, " ") { elts := strings.SplitN(flag, "=", 2) name := elts[0] @@ -33,6 +31,9 @@ func runTest(t *testing.T, dirname, in, out, flags string) { *rewriteRule = value case "-s": *simplifyAST = true + case "-stdin": + // fake flag - pretend input is from stdin + stdin = true default: t.Errorf("unrecognized flag name: %s", name) } @@ -43,7 +44,7 @@ func runTest(t *testing.T, dirname, in, out, flags string) { initRewrite() var buf bytes.Buffer - err := processFile(in, nil, &buf) + err := processFile(in, nil, &buf, stdin) if err != nil { t.Error(err) return @@ -57,23 +58,44 @@ func runTest(t *testing.T, dirname, in, out, flags string) { if got := buf.Bytes(); bytes.Compare(got, expected) != 0 { t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in) + d, err := diff(expected, got) + if err == nil { + t.Errorf("%s", d) + } ioutil.WriteFile(in+".gofmt", got, 0666) } } // TODO(gri) Add more test cases! var tests = []struct { - dirname, in, out, flags string + in, flags string }{ - {".", "gofmt.go", "gofmt.go", ""}, - {".", "gofmt_test.go", "gofmt_test.go", ""}, - {"testdata", "composites.input", "composites.golden", "-s"}, - {"testdata", "rewrite1.input", "rewrite1.golden", "-r=Foo->Bar"}, - {"testdata", "rewrite2.input", "rewrite2.golden", "-r=int->bool"}, + {"gofmt.go", ""}, + {"gofmt_test.go", ""}, + {"testdata/composites.input", "-s"}, + {"testdata/old.input", ""}, + {"testdata/rewrite1.input", "-r=Foo->Bar"}, + {"testdata/rewrite2.input", "-r=int->bool"}, + {"testdata/stdin*.input", "-stdin"}, } func TestRewrite(t *testing.T) { for _, test := range tests { - runTest(t, test.dirname, test.in, test.out, test.flags) + match, err := filepath.Glob(test.in) + if err != nil { + t.Error(err) + continue + } + for _, in := range match { + out := in + if strings.HasSuffix(in, ".input") { + out = in[:len(in)-len(".input")] + ".golden" + } + runTest(t, in, out, test.flags) + if in != out { + // Check idempotence. + runTest(t, out, out, test.flags) + } + } } } diff --git a/src/cmd/gofmt/testdata/old.golden b/src/cmd/gofmt/testdata/old.golden new file mode 100644 index 000000000..95a0b72a0 --- /dev/null +++ b/src/cmd/gofmt/testdata/old.golden @@ -0,0 +1,9 @@ +package P + +func f() { + if x { + y + } else { + z + } +} diff --git a/src/cmd/gofmt/testdata/old.input b/src/cmd/gofmt/testdata/old.input new file mode 100644 index 000000000..e24eed215 --- /dev/null +++ b/src/cmd/gofmt/testdata/old.input @@ -0,0 +1,8 @@ +package P + +func f() { + if x { + y + } else + z +} diff --git a/src/cmd/gofmt/testdata/stdin1.golden b/src/cmd/gofmt/testdata/stdin1.golden new file mode 100644 index 000000000..ff8b0b7ab --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin1.golden @@ -0,0 +1,3 @@ + if x { + y + } diff --git a/src/cmd/gofmt/testdata/stdin1.golden.gofmt b/src/cmd/gofmt/testdata/stdin1.golden.gofmt new file mode 100644 index 000000000..1f888877d --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin1.golden.gofmt @@ -0,0 +1,3 @@ + if x { + y +} diff --git a/src/cmd/gofmt/testdata/stdin1.input b/src/cmd/gofmt/testdata/stdin1.input new file mode 100644 index 000000000..ff8b0b7ab --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin1.input @@ -0,0 +1,3 @@ + if x { + y + } diff --git a/src/cmd/gofmt/testdata/stdin1.input.gofmt b/src/cmd/gofmt/testdata/stdin1.input.gofmt new file mode 100644 index 000000000..1f888877d --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin1.input.gofmt @@ -0,0 +1,3 @@ + if x { + y +} diff --git a/src/cmd/gofmt/testdata/stdin2.golden b/src/cmd/gofmt/testdata/stdin2.golden new file mode 100644 index 000000000..7eb1b54fe --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin2.golden @@ -0,0 +1,11 @@ + + +var x int + +func f() { + y := z + /* this is a comment */ + // this is a comment too +} + + diff --git a/src/cmd/gofmt/testdata/stdin2.golden.gofmt b/src/cmd/gofmt/testdata/stdin2.golden.gofmt new file mode 100644 index 000000000..85e800300 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin2.golden.gofmt @@ -0,0 +1,10 @@ + + + +var x int + +func f() { + y := z +} + + diff --git a/src/cmd/gofmt/testdata/stdin2.input b/src/cmd/gofmt/testdata/stdin2.input new file mode 100644 index 000000000..99defd2d1 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin2.input @@ -0,0 +1,11 @@ + + +var x int + + +func f() { y := z + /* this is a comment */ + // this is a comment too +} + + diff --git a/src/cmd/gofmt/testdata/stdin2.input.gofmt b/src/cmd/gofmt/testdata/stdin2.input.gofmt new file mode 100644 index 000000000..7eb1b54fe --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin2.input.gofmt @@ -0,0 +1,11 @@ + + +var x int + +func f() { + y := z + /* this is a comment */ + // this is a comment too +} + + diff --git a/src/cmd/gofmt/testdata/stdin3.golden b/src/cmd/gofmt/testdata/stdin3.golden new file mode 100644 index 000000000..1bf2f5a48 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin3.golden @@ -0,0 +1,6 @@ + + /* note: no newline at end of file */ + for i := 0; i < 10; i++ { + s += i + } + \ No newline at end of file diff --git a/src/cmd/gofmt/testdata/stdin3.golden.gofmt b/src/cmd/gofmt/testdata/stdin3.golden.gofmt new file mode 100644 index 000000000..b4d1d4663 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin3.golden.gofmt @@ -0,0 +1,7 @@ + + + /* note: no newline at end of file */ + for i := 0; i < 10; i++ { + s += i + } + \ No newline at end of file diff --git a/src/cmd/gofmt/testdata/stdin3.input b/src/cmd/gofmt/testdata/stdin3.input new file mode 100644 index 000000000..d963bd0d2 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin3.input @@ -0,0 +1,4 @@ + + /* note: no newline at end of file */ + for i := 0; i < 10; i++ { s += i } + \ No newline at end of file diff --git a/src/cmd/gofmt/testdata/stdin3.input.gofmt b/src/cmd/gofmt/testdata/stdin3.input.gofmt new file mode 100644 index 000000000..b4d1d4663 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin3.input.gofmt @@ -0,0 +1,7 @@ + + + /* note: no newline at end of file */ + for i := 0; i < 10; i++ { + s += i + } + \ No newline at end of file diff --git a/src/cmd/gofmt/testdata/stdin4.golden b/src/cmd/gofmt/testdata/stdin4.golden new file mode 100644 index 000000000..5f7343551 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin4.golden @@ -0,0 +1,3 @@ + // comment + + i := 0 diff --git a/src/cmd/gofmt/testdata/stdin4.golden.gofmt b/src/cmd/gofmt/testdata/stdin4.golden.gofmt new file mode 100644 index 000000000..5f7343551 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin4.golden.gofmt @@ -0,0 +1,3 @@ + // comment + + i := 0 diff --git a/src/cmd/gofmt/testdata/stdin4.input b/src/cmd/gofmt/testdata/stdin4.input new file mode 100644 index 000000000..f02a54fb1 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin4.input @@ -0,0 +1,3 @@ + // comment + + i := 0 diff --git a/src/cmd/gofmt/testdata/stdin4.input.gofmt b/src/cmd/gofmt/testdata/stdin4.input.gofmt new file mode 100644 index 000000000..5f7343551 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin4.input.gofmt @@ -0,0 +1,3 @@ + // comment + + i := 0 diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go index 23b26e383..478266357 100644 --- a/src/cmd/goinstall/main.go +++ b/src/cmd/goinstall/main.go @@ -13,7 +13,7 @@ import ( "go/token" "io/ioutil" "os" - "path/filepath" + "path/filepath" // use for file system paths "regexp" "runtime" "strings" @@ -190,7 +190,7 @@ func install(pkg, parent string) { }() // Don't allow trailing '/' - if _, f := filepath.Split(pkg); f == "" { + if strings.HasSuffix(pkg, "/") { errorf("%s should not have trailing '/'\n", pkg) return } @@ -225,16 +225,17 @@ func install(pkg, parent string) { terrorf(tree, "%s: %v\n", pkg, err) return } - dir := filepath.Join(tree.SrcDir(), pkg) + dir := filepath.Join(tree.SrcDir(), filepath.FromSlash(pkg)) // Install prerequisites. - dirInfo, err := build.ScanDir(dir, parent == "") + dirInfo, err := build.ScanDir(dir) if err != nil { terrorf(tree, "%s: %v\n", pkg, err) return } - if len(dirInfo.GoFiles)+len(dirInfo.CgoFiles) == 0 { - terrorf(tree, "%s: package has no files\n", pkg) + // We reserve package main to identify commands. + if parent != "" && dirInfo.Package == "main" { + terrorf(tree, "%s: found only package main in %s; cannot import", pkg, dir) return } for _, p := range dirInfo.Imports { diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go index 38a70ddfd..7f41a913f 100644 --- a/src/cmd/goinstall/make.go +++ b/src/cmd/goinstall/make.go @@ -10,7 +10,7 @@ import ( "bytes" "go/build" "os" - "path/filepath" + "path" // use for import paths "strings" "template" ) @@ -44,10 +44,10 @@ func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Err targDir := tree.PkgDir() if isCmd { // use the last part of the package name for targ - _, targ = filepath.Split(pkg) + _, targ = path.Split(pkg) targDir = tree.BinDir() } - dirInfo, err := build.ScanDir(dir, isCmd) + dirInfo, err := build.ScanDir(dir) if err != nil { return nil, err } diff --git a/src/cmd/gotest/gotest.go b/src/cmd/gotest/gotest.go index 8e3a42232..88c746c1b 100644 --- a/src/cmd/gotest/gotest.go +++ b/src/cmd/gotest/gotest.go @@ -165,7 +165,7 @@ func setEnvironment() { func getTestFileNames() { names := fileNames if len(names) == 0 { - info, err := build.ScanDir(".", true) + info, err := build.ScanDir(".") if err != nil { Fatalf("scanning directory: %v", err) } diff --git a/src/cmd/govet/govet.go b/src/cmd/govet/govet.go index 98d3d5c17..9aa97e316 100644 --- a/src/cmd/govet/govet.go +++ b/src/cmd/govet/govet.go @@ -101,34 +101,20 @@ func doFile(name string, reader io.Reader) { file.checkFile(name, parsedFile) } -// Visitor for filepath.Walk - trivial. Just calls doFile on each file. -// TODO: if govet becomes richer, might want to process -// a directory (package) at a time. -type V struct{} - -func (v V) VisitDir(path string, f *os.FileInfo) bool { - return true -} - -func (v V) VisitFile(path string, f *os.FileInfo) { - if strings.HasSuffix(path, ".go") { +func visit(path string, f *os.FileInfo, err os.Error) os.Error { + if err != nil { + errorf("walk error: %s", err) + return nil + } + if f.IsRegular() && strings.HasSuffix(path, ".go") { doFile(path, nil) } + return nil } // walkDir recursively walks the tree looking for .go files. func walkDir(root string) { - errors := make(chan os.Error) - done := make(chan bool) - go func() { - for e := range errors { - errorf("walk error: %s", e) - } - done <- true - }() - filepath.Walk(root, V{}, errors) - close(errors) - <-done + filepath.Walk(root, visit) } // error formats the error to standard error, adding program diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c index d8ca27ace..77536018a 100644 --- a/src/cmd/ld/dwarf.c +++ b/src/cmd/ld/dwarf.c @@ -1578,13 +1578,16 @@ addhistfile(char *zentry) histfile[histfilesize++] = ""; fname = decodez(zentry); +// print("addhistfile %d: %s\n", histfilesize, fname); if (fname == 0) return -1; + // Don't fill with duplicates (check only top one). if (strcmp(fname, histfile[histfilesize-1]) == 0) { free(fname); return histfilesize - 1; } + histfile[histfilesize++] = fname; return histfilesize - 1; } @@ -1608,11 +1611,13 @@ finddebugruntimepath(void) } // Go's runtime C sources are sane, and Go sources nest only 1 level, -// so 16 should be plenty. +// so a handful would be plenty, if it weren't for the fact that line +// directives can push an unlimited number of them. static struct { int file; vlong line; -} includestack[16]; +} *includestack; +static int includestacksize; static int includetop; static vlong absline; @@ -1629,17 +1634,15 @@ static Linehist *linehist; static void checknesting(void) { - int i; - if (includetop < 0) { diag("dwarf: corrupt z stack"); errorexit(); } - if (includetop >= nelem(includestack)) { - diag("dwarf: nesting too deep"); - for (i = 0; i < nelem(includestack); i++) - diag("\t%s", histfile[includestack[i].file]); - errorexit(); + if (includetop >= includestacksize) { + includestacksize += 1; + includestacksize <<= 2; +// print("checknesting: growing to %d\n", includestacksize); + includestack = realloc(includestack, includestacksize * sizeof *includestack); } } @@ -1669,6 +1672,7 @@ inithist(Auto *a) // Clear the history. clearhistfile(); includetop = 0; + checknesting(); includestack[includetop].file = 0; includestack[includetop].line = -1; absline = 0; @@ -1682,10 +1686,10 @@ inithist(Auto *a) for (; a; a = a->link) { if (a->type == D_FILE) { // 'z' int f = addhistfile(a->asym->name); - if (f < 0) { // pop file + if (f < 0) { // pop file includetop--; checknesting(); - } else if(f != includestack[includetop].file) { // pushed a new file + } else { // pushed a file (potentially same) includestack[includetop].line += a->aoffset - absline; includetop++; checknesting(); diff --git a/src/pkg/Makefile b/src/pkg/Makefile index c7e65c029..85c5031e5 100644 --- a/src/pkg/Makefile +++ b/src/pkg/Makefile @@ -33,6 +33,7 @@ DIRS=\ crypto\ crypto/aes\ crypto/blowfish\ + crypto/bcrypt\ crypto/cast5\ crypto/cipher\ crypto/des\ diff --git a/src/pkg/archive/tar/common.go b/src/pkg/archive/tar/common.go index 528858765..67355086a 100644 --- a/src/pkg/archive/tar/common.go +++ b/src/pkg/archive/tar/common.go @@ -15,36 +15,37 @@ const ( blockSize = 512 // Types - TypeReg = '0' - TypeRegA = '\x00' - TypeLink = '1' - TypeSymlink = '2' - TypeChar = '3' - TypeBlock = '4' - TypeDir = '5' - TypeFifo = '6' - TypeCont = '7' - TypeXHeader = 'x' - TypeXGlobalHeader = 'g' + TypeReg = '0' // regular file. + TypeRegA = '\x00' // regular file. + TypeLink = '1' // hard link. + TypeSymlink = '2' // symbolic link. + TypeChar = '3' // character device node. + TypeBlock = '4' // block device node. + TypeDir = '5' // directory. + TypeFifo = '6' // fifo node. + TypeCont = '7' // reserved. + TypeXHeader = 'x' // extended header. + TypeXGlobalHeader = 'g' // global extended header. ) // A Header represents a single header in a tar archive. // Some fields may not be populated. type Header struct { - Name string - Mode int64 - Uid int - Gid int - Size int64 - Mtime int64 - Typeflag byte - Linkname string - Uname string - Gname string - Devmajor int64 - Devminor int64 - Atime int64 - Ctime int64 + Name string // name of header file entry. + Mode int64 // permission and mode bits. + Uid int // user id of owner. + Gid int // group id of owner. + Size int64 // length in bytes. + Mtime int64 // modified time; seconds since epoch. + Typeflag byte // type of header entry. + Linkname string // target name of link. + Uname string // user name of owner. + Gname string // group name of owner. + Devmajor int64 // major number of character or block device. + Devminor int64 // minor number of character or block device. + Atime int64 // access time; seconds since epoch. + Ctime int64 // status change time; seconds since epoch. + } var zeroBlock = make([]byte, blockSize) diff --git a/src/pkg/asn1/asn1_test.go b/src/pkg/asn1/asn1_test.go index 9f48f7bdd..1c529bdb3 100644 --- a/src/pkg/asn1/asn1_test.go +++ b/src/pkg/asn1/asn1_test.go @@ -206,10 +206,10 @@ type timeTest struct { } var utcTestData = []timeTest{ - {"910506164540-0700", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, 0, -7 * 60 * 60, ""}}, - {"910506164540+0730", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, 0, 7*60*60 + 30*60, ""}}, - {"910506234540Z", true, &time.Time{1991, 05, 06, 23, 45, 40, 0, 0, 0, "UTC"}}, - {"9105062345Z", true, &time.Time{1991, 05, 06, 23, 45, 0, 0, 0, 0, "UTC"}}, + {"910506164540-0700", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, -7 * 60 * 60, ""}}, + {"910506164540+0730", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, 7*60*60 + 30*60, ""}}, + {"910506234540Z", true, &time.Time{1991, 05, 06, 23, 45, 40, 0, 0, "UTC"}}, + {"9105062345Z", true, &time.Time{1991, 05, 06, 23, 45, 0, 0, 0, "UTC"}}, {"a10506234540Z", false, nil}, {"91a506234540Z", false, nil}, {"9105a6234540Z", false, nil}, @@ -235,10 +235,10 @@ func TestUTCTime(t *testing.T) { } var generalizedTimeTestData = []timeTest{ - {"20100102030405Z", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, 0, "UTC"}}, + {"20100102030405Z", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, "UTC"}}, {"20100102030405", false, nil}, - {"20100102030405+0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, 6*60*60 + 7*60, ""}}, - {"20100102030405-0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, -6*60*60 - 7*60, ""}}, + {"20100102030405+0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 6*60*60 + 7*60, ""}}, + {"20100102030405-0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, -6*60*60 - 7*60, ""}}, } func TestGeneralizedTime(t *testing.T) { @@ -475,7 +475,7 @@ var derEncodedSelfSignedCert = Certificate{ RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, }, - Validity: Validity{NotBefore: &time.Time{Year: 2009, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, Weekday: 0, ZoneOffset: 0, Zone: "UTC"}, NotAfter: &time.Time{Year: 2010, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, Weekday: 0, ZoneOffset: 0, Zone: "UTC"}}, + Validity: Validity{NotBefore: &time.Time{Year: 2009, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, ZoneOffset: 0, Zone: "UTC"}, NotAfter: &time.Time{Year: 2010, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, ZoneOffset: 0, Zone: "UTC"}}, Subject: RDNSequence{ RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, diff --git a/src/pkg/bytes/bytes.go b/src/pkg/bytes/bytes.go index 5119fce94..ea6bf5ec2 100644 --- a/src/pkg/bytes/bytes.go +++ b/src/pkg/bytes/bytes.go @@ -572,13 +572,18 @@ func Runes(s []byte) []int { // non-overlapping instances of old replaced by new. // If n < 0, there is no limit on the number of replacements. func Replace(s, old, new []byte, n int) []byte { - if n == 0 { - return s // avoid allocation - } - // Compute number of replacements. - if m := Count(s, old); m == 0 { - return s // avoid allocation - } else if n <= 0 || m < n { + m := 0 + if n != 0 { + // Compute number of replacements. + m = Count(s, old) + } + if m == 0 { + // Nothing to do. Just copy. + t := make([]byte, len(s)) + copy(t, s) + return t + } + if n < 0 || m < n { n = m } diff --git a/src/pkg/bytes/bytes_test.go b/src/pkg/bytes/bytes_test.go index 9444358a8..1679279d3 100644 --- a/src/pkg/bytes/bytes_test.go +++ b/src/pkg/bytes/bytes_test.go @@ -829,9 +829,15 @@ var ReplaceTests = []ReplaceTest{ func TestReplace(t *testing.T) { for _, tt := range ReplaceTests { - if s := string(Replace([]byte(tt.in), []byte(tt.old), []byte(tt.new), tt.n)); s != tt.out { + in := append([]byte(tt.in), []byte("")...) + in = in[:len(tt.in)] + out := Replace(in, []byte(tt.old), []byte(tt.new), tt.n) + if s := string(out); s != tt.out { t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out) } + if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] { + t.Errorf("Replace(%q, %q, %q, %d) didn't copy", tt.in, tt.old, tt.new, tt.n) + } } } diff --git a/src/pkg/crypto/bcrypt/Makefile b/src/pkg/crypto/bcrypt/Makefile new file mode 100644 index 000000000..3c83d9c8a --- /dev/null +++ b/src/pkg/crypto/bcrypt/Makefile @@ -0,0 +1,12 @@ +# 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. + +include ../../../Make.inc + +TARG=crypto/bcrypt +GOFILES=\ + base64.go \ + bcrypt.go + +include ../../../Make.pkg diff --git a/src/pkg/crypto/bcrypt/base64.go b/src/pkg/crypto/bcrypt/base64.go new file mode 100644 index 000000000..ed6cea70c --- /dev/null +++ b/src/pkg/crypto/bcrypt/base64.go @@ -0,0 +1,38 @@ +// 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 bcrypt + +import ( + "encoding/base64" + "os" +) + +const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +var bcEncoding = base64.NewEncoding(alphabet) + +func base64Encode(src []byte) []byte { + n := bcEncoding.EncodedLen(len(src)) + dst := make([]byte, n) + bcEncoding.Encode(dst, src) + for dst[n-1] == '=' { + n-- + } + return dst[:n] +} + +func base64Decode(src []byte) ([]byte, os.Error) { + numOfEquals := 4 - (len(src) % 4) + for i := 0; i < numOfEquals; i++ { + src = append(src, '=') + } + + dst := make([]byte, bcEncoding.DecodedLen(len(src))) + n, err := bcEncoding.Decode(dst, src) + if err != nil { + return nil, err + } + return dst[:n], nil +} diff --git a/src/pkg/crypto/bcrypt/bcrypt.go b/src/pkg/crypto/bcrypt/bcrypt.go new file mode 100644 index 000000000..1e8ccfac1 --- /dev/null +++ b/src/pkg/crypto/bcrypt/bcrypt.go @@ -0,0 +1,282 @@ +// 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 bcrypt implements Provos and Mazières's bcrypt adapative hashing +// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf +package bcrypt + +// The code is a port of Provos and Mazières's C implementation. +import ( + "crypto/blowfish" + "crypto/rand" + "crypto/subtle" + "fmt" + "io" + "os" + "strconv" +) + +const ( + MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword + MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword + DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword +) + +// The error returned from CompareHashAndPassword when a password and hash do +// not match. +var MismatchedHashAndPasswordError = os.NewError("crypto/bcrypt: hashedPassword is not the hash of the given password") + +// The error returned from CompareHashAndPassword when a hash is too short to +// be a bcrypt hash. +var HashTooShortError = os.NewError("crypto/bcrypt: hashedSecret too short to be a bcrypted password") + +// The error returned from CompareHashAndPassword when a hash was created with +// a bcrypt algorithm newer than this implementation. +type HashVersionTooNewError byte + +func (hv HashVersionTooNewError) String() string { + return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) +} + +// The error returned from CompareHashAndPassword when a hash starts with something other than '$' +type InvalidHashPrefixError byte + +func (ih InvalidHashPrefixError) String() string { + return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) +} + +type InvalidCostError int + +func (ic InvalidCostError) String() string { + return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) +} + +const ( + majorVersion = '2' + minorVersion = 'a' + maxSaltSize = 16 + maxCryptedHashSize = 23 + encodedSaltSize = 22 + encodedHashSize = 31 + minHashSize = 59 +) + +// magicCipherData is an IV for the 64 Blowfish encryption calls in +// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes. +var magicCipherData = []byte{ + 0x4f, 0x72, 0x70, 0x68, + 0x65, 0x61, 0x6e, 0x42, + 0x65, 0x68, 0x6f, 0x6c, + 0x64, 0x65, 0x72, 0x53, + 0x63, 0x72, 0x79, 0x44, + 0x6f, 0x75, 0x62, 0x74, +} + +type hashed struct { + hash []byte + salt []byte + cost uint32 // allowed range is MinCost to MaxCost + major byte + minor byte +} + +// GenerateFromPassword returns the bcrypt hash of the password at the given +// cost. If the cost given is less than MinCost, the cost will be set to +// MinCost, instead. Use CompareHashAndPassword, as defined in this package, +// to compare the returned hashed password with its cleartext version. +func GenerateFromPassword(password []byte, cost int) ([]byte, os.Error) { + p, err := newFromPassword(password, cost) + if err != nil { + return nil, err + } + return p.Hash(), nil +} + +// CompareHashAndPassword compares a bcrypt hashed password with its possible +// plaintext equivalent. Note: Using bytes.Equal for this job is +// insecure. Returns nil on success, or an error on failure. +func CompareHashAndPassword(hashedPassword, password []byte) os.Error { + p, err := newFromHash(hashedPassword) + if err != nil { + return err + } + + otherHash, err := bcrypt(password, p.cost, p.salt) + if err != nil { + return err + } + + otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} + if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { + return nil + } + + return MismatchedHashAndPasswordError +} + +func newFromPassword(password []byte, cost int) (*hashed, os.Error) { + if cost < MinCost { + cost = DefaultCost + } + p := new(hashed) + p.major = majorVersion + p.minor = minorVersion + + err := checkCost(cost) + if err != nil { + return nil, err + } + p.cost = uint32(cost) + + unencodedSalt := make([]byte, maxSaltSize) + _, err = io.ReadFull(rand.Reader, unencodedSalt) + if err != nil { + return nil, err + } + + p.salt = base64Encode(unencodedSalt) + hash, err := bcrypt(password, p.cost, p.salt) + if err != nil { + return nil, err + } + p.hash = hash + return p, err +} + +func newFromHash(hashedSecret []byte) (*hashed, os.Error) { + if len(hashedSecret) < minHashSize { + return nil, HashTooShortError + } + p := new(hashed) + n, err := p.decodeVersion(hashedSecret) + if err != nil { + return nil, err + } + hashedSecret = hashedSecret[n:] + n, err = p.decodeCost(hashedSecret) + if err != nil { + return nil, err + } + hashedSecret = hashedSecret[n:] + + // The "+2" is here because we'll have to append at most 2 '=' to the salt + // when base64 decoding it in expensiveBlowfishSetup(). + p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) + copy(p.salt, hashedSecret[:encodedSaltSize]) + + hashedSecret = hashedSecret[encodedSaltSize:] + p.hash = make([]byte, len(hashedSecret)) + copy(p.hash, hashedSecret) + + return p, nil +} + +func bcrypt(password []byte, cost uint32, salt []byte) ([]byte, os.Error) { + cipherData := make([]byte, len(magicCipherData)) + copy(cipherData, magicCipherData) + + c, err := expensiveBlowfishSetup(password, cost, salt) + if err != nil { + return nil, err + } + + for i := 0; i < 24; i += 8 { + for j := 0; j < 64; j++ { + c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) + } + } + + // Bug compatibility with C bcrypt implementations. We only encode 23 of + // the 24 bytes encrypted. + hsh := base64Encode(cipherData[:maxCryptedHashSize]) + return hsh, nil +} + +func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, os.Error) { + + csalt, err := base64Decode(salt) + if err != nil { + return nil, err + } + + // Bug compatibility with C bcrypt implementations. They use the trailing + // NULL in the key string during expansion. + ckey := append(key, 0) + + c, err := blowfish.NewSaltedCipher(ckey, csalt) + if err != nil { + return nil, err + } + + rounds := 1 << cost + for i := 0; i < rounds; i++ { + blowfish.ExpandKey(ckey, c) + blowfish.ExpandKey(csalt, c) + } + + return c, nil +} + +func (p *hashed) Hash() []byte { + arr := make([]byte, 60) + arr[0] = '$' + arr[1] = p.major + n := 2 + if p.minor != 0 { + arr[2] = p.minor + n = 3 + } + arr[n] = '$' + n += 1 + copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) + n += 2 + arr[n] = '$' + n += 1 + copy(arr[n:], p.salt) + n += encodedSaltSize + copy(arr[n:], p.hash) + n += encodedHashSize + return arr[:n] +} + +func (p *hashed) decodeVersion(sbytes []byte) (int, os.Error) { + if sbytes[0] != '$' { + return -1, InvalidHashPrefixError(sbytes[0]) + } + if sbytes[1] > majorVersion { + return -1, HashVersionTooNewError(sbytes[1]) + } + p.major = sbytes[1] + n := 3 + if sbytes[2] != '$' { + p.minor = sbytes[2] + n++ + } + return n, nil +} + +// sbytes should begin where decodeVersion left off. +func (p *hashed) decodeCost(sbytes []byte) (int, os.Error) { + cost, err := strconv.Atoi(string(sbytes[0:2])) + if err != nil { + return -1, err + } + err = checkCost(cost) + if err != nil { + return -1, err + } + p.cost = uint32(cost) + return 3, nil +} + +func (p *hashed) String() string { + return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) +} + +func checkCost(cost int) os.Error { + if cost < MinCost || cost > MaxCost { + return InvalidCostError(cost) + } + return nil +} diff --git a/src/pkg/crypto/bcrypt/bcrypt_test.go b/src/pkg/crypto/bcrypt/bcrypt_test.go new file mode 100644 index 000000000..89eca0a44 --- /dev/null +++ b/src/pkg/crypto/bcrypt/bcrypt_test.go @@ -0,0 +1,195 @@ +// 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 bcrypt + +import ( + "bytes" + "os" + "testing" +) + +func TestBcryptingIsEasy(t *testing.T) { + pass := []byte("mypassword") + hp, err := GenerateFromPassword(pass, 0) + if err != nil { + t.Fatalf("GenerateFromPassword error: %s", err) + } + + if CompareHashAndPassword(hp, pass) != nil { + t.Errorf("%v should hash %s correctly", hp, pass) + } + + notPass := "notthepass" + err = CompareHashAndPassword(hp, []byte(notPass)) + if err != MismatchedHashAndPasswordError { + t.Errorf("%v and %s should be mismatched", hp, notPass) + } +} + +func TestBcryptingIsCorrect(t *testing.T) { + pass := []byte("allmine") + salt := []byte("XajjQvNhvvRt5GSeFk1xFe") + expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") + + hash, err := bcrypt(pass, 10, salt) + if err != nil { + t.Fatalf("bcrypt blew up: %v", err) + } + if !bytes.HasSuffix(expectedHash, hash) { + t.Errorf("%v should be the suffix of %v", hash, expectedHash) + } + + h, err := newFromHash(expectedHash) + if err != nil { + t.Errorf("Unable to parse %s: %v", string(expectedHash), err) + } + + // This is not the safe way to compare these hashes. We do this only for + // testing clarity. Use bcrypt.CompareHashAndPassword() + if err == nil && !bytes.Equal(expectedHash, h.Hash()) { + t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash) + } +} + +func TestTooLongPasswordsWork(t *testing.T) { + salt := []byte("XajjQvNhvvRt5GSeFk1xFe") + // One byte over the usual 56 byte limit that blowfish has + tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456") + tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C") + hash, err := bcrypt(tooLongPass, 10, salt) + if err != nil { + t.Fatalf("bcrypt blew up on long password: %v", err) + } + if !bytes.HasSuffix(tooLongExpected, hash) { + t.Errorf("%v should be the suffix of %v", hash, tooLongExpected) + } +} + +type InvalidHashTest struct { + err os.Error + hash []byte +} + +var invalidTests = []InvalidHashTest{ + {HashTooShortError, []byte("$2a$10$fooo")}, + {HashTooShortError, []byte("$2a")}, + {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, + {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, + {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, +} + +func TestInvalidHashErrors(t *testing.T) { + check := func(name string, expected, err os.Error) { + if err == nil { + t.Errorf("%s: Should have returned an error", name) + } + if err != nil && err != expected { + t.Errorf("%s gave err %v but should have given %v", name, err.String(), expected.String()) + } + } + for _, iht := range invalidTests { + _, err := newFromHash(iht.hash) + check("newFromHash", iht.err, err) + err = CompareHashAndPassword(iht.hash, []byte("anything")) + check("CompareHashAndPassword", iht.err, err) + } +} + +func TestUnpaddedBase64Encoding(t *testing.T) { + original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30} + encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe") + + encoded := base64Encode(original) + + if !bytes.Equal(encodedOriginal, encoded) { + t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal) + } + + decoded, err := base64Decode(encodedOriginal) + if err != nil { + t.Fatalf("base64Decode blew up: %s", err) + } + + if !bytes.Equal(decoded, original) { + t.Errorf("Decoded %v should have equaled %v", decoded, original) + } +} + +func TestCost(t *testing.T) { + if testing.Short() { + return + } + + pass := []byte("mypassword") + + for c := 0; c < MinCost; c++ { + p, _ := newFromPassword(pass, c) + if p.cost != uint32(DefaultCost) { + t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost) + } + } + + p, _ := newFromPassword(pass, 14) + if p.cost != 14 { + t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost) + } + + hp, _ := newFromHash(p.Hash()) + if p.cost != hp.cost { + t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost) + } + + _, err := newFromPassword(pass, 32) + if err == nil { + t.Fatalf("newFromPassword: should return a cost error") + } + if err != InvalidCostError(32) { + t.Errorf("newFromPassword: should return cost error, got %#v", err) + } +} + +func TestCostReturnsWithLeadingZeroes(t *testing.T) { + hp, _ := newFromPassword([]byte("abcdefgh"), 7) + cost := hp.Hash()[4:7] + expected := []byte("07$") + + if !bytes.Equal(expected, cost) { + t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected) + } +} + +func TestMinorNotRequired(t *testing.T) { + noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") + h, err := newFromHash(noMinorHash) + if err != nil { + t.Fatalf("No minor hash blew up: %s", err) + } + if h.minor != 0 { + t.Errorf("Should leave minor version at 0, but was %d", h.minor) + } + + if !bytes.Equal(noMinorHash, h.Hash()) { + t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash()) + } +} + +func BenchmarkEqual(b *testing.B) { + b.StopTimer() + passwd := []byte("somepasswordyoulike") + hash, _ := GenerateFromPassword(passwd, 10) + b.StartTimer() + for i := 0; i < b.N; i++ { + CompareHashAndPassword(hash, passwd) + } +} + +func BenchmarkGeneration(b *testing.B) { + b.StopTimer() + passwd := []byte("mylongpassword1234") + b.StartTimer() + for i := 0; i < b.N; i++ { + GenerateFromPassword(passwd, 10) + } +} diff --git a/src/pkg/crypto/blowfish/block.go b/src/pkg/crypto/blowfish/block.go index 7fbe7eefb..326292dfc 100644 --- a/src/pkg/crypto/blowfish/block.go +++ b/src/pkg/crypto/blowfish/block.go @@ -4,13 +4,12 @@ package blowfish -func expandKey(key []byte, c *Cipher) { - copy(c.p[0:], p[0:]) - copy(c.s0[0:], s0[0:]) - copy(c.s1[0:], s1[0:]) - copy(c.s2[0:], s2[0:]) - copy(c.s3[0:], s3[0:]) - +// ExpandKey performs a key expansion on the given *Cipher. Specifically, it +// performs the Blowfish algorithm's key schedule which sets up the *Cipher's +// pi and substitution tables for calls to Encrypt. This is used, primarily, +// by the bcrypt package to reuse the Blowfish key schedule during its +// set up. It's unlikely that you need to use this directly. +func ExpandKey(key []byte, c *Cipher) { j := 0 for i := 0; i < 18; i++ { var d uint32 @@ -48,6 +47,98 @@ func expandKey(key []byte, c *Cipher) { } } +// This is similar to ExpandKey, but folds the salt during the key +// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero +// salt passed in, reusing ExpandKey turns out to be a place of inefficiency +// and specializing it here is useful. +func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { + j := 0 + expandedKey := make([]uint32, 18) + for i := 0; i < 18; i++ { + var d uint32 + for k := 0; k < 4; k++ { + d = d<<8 | uint32(key[j])&0x000000FF + j++ + if j >= len(key) { + j = 0 + } + } + expandedKey[i] = d + c.p[i] ^= d + } + + j = 0 + expandedSalt := make([]uint32, 18) + for i := 0; i < 18; i++ { + var d uint32 + for k := 0; k < 4; k++ { + d = d<<8 | uint32(salt[j])&0x000000FF + j++ + if j >= len(salt) { + j = 0 + } + } + expandedSalt[i] = d + } + + var l, r uint32 + for i := 0; i < 18; i += 2 { + l ^= expandedSalt[i&2] + r ^= expandedSalt[(i&2)+1] + l, r = encryptBlock(l, r, c) + c.p[i], c.p[i+1] = l, r + } + + for i := 0; i < 256; i += 4 { + l ^= expandedSalt[2] + r ^= expandedSalt[3] + l, r = encryptBlock(l, r, c) + c.s0[i], c.s0[i+1] = l, r + + l ^= expandedSalt[0] + r ^= expandedSalt[1] + l, r = encryptBlock(l, r, c) + c.s0[i+2], c.s0[i+3] = l, r + + } + + for i := 0; i < 256; i += 4 { + l ^= expandedSalt[2] + r ^= expandedSalt[3] + l, r = encryptBlock(l, r, c) + c.s1[i], c.s1[i+1] = l, r + + l ^= expandedSalt[0] + r ^= expandedSalt[1] + l, r = encryptBlock(l, r, c) + c.s1[i+2], c.s1[i+3] = l, r + } + + for i := 0; i < 256; i += 4 { + l ^= expandedSalt[2] + r ^= expandedSalt[3] + l, r = encryptBlock(l, r, c) + c.s2[i], c.s2[i+1] = l, r + + l ^= expandedSalt[0] + r ^= expandedSalt[1] + l, r = encryptBlock(l, r, c) + c.s2[i+2], c.s2[i+3] = l, r + } + + for i := 0; i < 256; i += 4 { + l ^= expandedSalt[2] + r ^= expandedSalt[3] + l, r = encryptBlock(l, r, c) + c.s3[i], c.s3[i+1] = l, r + + l ^= expandedSalt[0] + r ^= expandedSalt[1] + l, r = encryptBlock(l, r, c) + c.s3[i+2], c.s3[i+3] = l, r + } +} + func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { xl, xr := l, r xl ^= c.p[0] diff --git a/src/pkg/crypto/blowfish/blowfish_test.go b/src/pkg/crypto/blowfish/blowfish_test.go index 3a7ab6c2a..1038d2e39 100644 --- a/src/pkg/crypto/blowfish/blowfish_test.go +++ b/src/pkg/crypto/blowfish/blowfish_test.go @@ -190,3 +190,21 @@ func TestCipherDecrypt(t *testing.T) { } } } + +func TestSaltedCipherKeyLength(t *testing.T) { + var key []byte + for i := 0; i < 4; i++ { + _, err := NewSaltedCipher(key, []byte{'a'}) + if err != KeySizeError(i) { + t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(i)) + } + key = append(key, 'a') + } + + // A 57-byte key. One over the typical blowfish restriction. + key = []byte("012345678901234567890123456789012345678901234567890123456") + _, err := NewSaltedCipher(key, []byte{'a'}) + if err != nil { + t.Errorf("NewSaltedCipher with long key, gave error %#v", err) + } +} diff --git a/src/pkg/crypto/blowfish/cipher.go b/src/pkg/crypto/blowfish/cipher.go index 6c37dfe94..3439825e8 100644 --- a/src/pkg/crypto/blowfish/cipher.go +++ b/src/pkg/crypto/blowfish/cipher.go @@ -31,12 +31,28 @@ func (k KeySizeError) String() string { // NewCipher creates and returns a Cipher. // The key argument should be the Blowfish key, 4 to 56 bytes. func NewCipher(key []byte) (*Cipher, os.Error) { + var result Cipher k := len(key) if k < 4 || k > 56 { return nil, KeySizeError(k) } + initCipher(key, &result) + ExpandKey(key, &result) + return &result, nil +} + +// NewSaltedCipher creates a returns a Cipher that folds a salt into its key +// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is +// sufficient and desirable. For bcrypt compatiblity, the key can be over 56 +// bytes. +func NewSaltedCipher(key, salt []byte) (*Cipher, os.Error) { var result Cipher - expandKey(key, &result) + k := len(key) + if k < 4 { + return nil, KeySizeError(k) + } + initCipher(key, &result) + expandKeyWithSalt(key, salt, &result) return &result, nil } @@ -77,3 +93,11 @@ func (c *Cipher) Reset() { zero(c.s2[0:]) zero(c.s3[0:]) } + +func initCipher(key []byte, c *Cipher) { + copy(c.p[0:], p[0:]) + copy(c.s0[0:], s0[0:]) + copy(c.s1[0:], s1[0:]) + copy(c.s2[0:], s2[0:]) + copy(c.s3[0:], s3[0:]) +} diff --git a/src/pkg/crypto/ocsp/ocsp_test.go b/src/pkg/crypto/ocsp/ocsp_test.go index f9889790f..7be37211c 100644 --- a/src/pkg/crypto/ocsp/ocsp_test.go +++ b/src/pkg/crypto/ocsp/ocsp_test.go @@ -15,7 +15,7 @@ func TestOCSPDecode(t *testing.T) { t.Error(err) } - expected := Response{Status: 0, SerialNumber: []byte{0x1, 0xd0, 0xfa}, RevocationReason: 0, ThisUpdate: &time.Time{Year: 2010, Month: 7, Day: 7, Hour: 15, Minute: 1, Second: 5, Weekday: 0, ZoneOffset: 0, Zone: "UTC"}, NextUpdate: &time.Time{Year: 2010, Month: 7, Day: 7, Hour: 18, Minute: 35, Second: 17, Weekday: 0, ZoneOffset: 0, Zone: "UTC"}} + expected := Response{Status: 0, SerialNumber: []byte{0x1, 0xd0, 0xfa}, RevocationReason: 0, ThisUpdate: &time.Time{Year: 2010, Month: 7, Day: 7, Hour: 15, Minute: 1, Second: 5, ZoneOffset: 0, Zone: "UTC"}, NextUpdate: &time.Time{Year: 2010, Month: 7, Day: 7, Hour: 18, Minute: 35, Second: 17, ZoneOffset: 0, Zone: "UTC"}} if !reflect.DeepEqual(resp.ThisUpdate, resp.ThisUpdate) { t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate) diff --git a/src/pkg/crypto/rand/rand_unix.go b/src/pkg/crypto/rand/rand_unix.go index 3a06aa8b1..76a7365b7 100644 --- a/src/pkg/crypto/rand/rand_unix.go +++ b/src/pkg/crypto/rand/rand_unix.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build darwin freebsd linux openbsd + // Unix cryptographically secure pseudorandom number // generator. diff --git a/src/pkg/crypto/tls/cipher_suites.go b/src/pkg/crypto/tls/cipher_suites.go index bc7b0d32f..77e712da1 100644 --- a/src/pkg/crypto/tls/cipher_suites.go +++ b/src/pkg/crypto/tls/cipher_suites.go @@ -9,6 +9,7 @@ import ( "crypto/cipher" "crypto/hmac" "crypto/rc4" + "crypto/sha1" "crypto/x509" "hash" "os" @@ -23,7 +24,7 @@ type keyAgreement interface { // ServerKeyExchange message, generateServerKeyExchange can return nil, // nil. generateServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, os.Error) - processClientKeyExchange(*Config, *clientKeyExchangeMsg) ([]byte, os.Error) + processClientKeyExchange(*Config, *clientKeyExchangeMsg, uint16) ([]byte, os.Error) // On the client side, the next two methods are called in order. @@ -46,14 +47,14 @@ type cipherSuite struct { // and point format that we can handle. elliptic bool cipher func(key, iv []byte, isRead bool) interface{} - mac func(macKey []byte) hash.Hash + mac func(version uint16, macKey []byte) macFunction } var cipherSuites = map[uint16]*cipherSuite{ - TLS_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, rsaKA, false, cipherRC4, hmacSHA1}, - TLS_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, rsaKA, false, cipherAES, hmacSHA1}, - TLS_ECDHE_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, ecdheRSAKA, true, cipherRC4, hmacSHA1}, - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, ecdheRSAKA, true, cipherAES, hmacSHA1}, + TLS_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, rsaKA, false, cipherRC4, macSHA1}, + TLS_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, rsaKA, false, cipherAES, macSHA1}, + TLS_ECDHE_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1}, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1}, } func cipherRC4(key, iv []byte, isRead bool) interface{} { @@ -69,8 +70,75 @@ func cipherAES(key, iv []byte, isRead bool) interface{} { return cipher.NewCBCEncrypter(block, iv) } -func hmacSHA1(key []byte) hash.Hash { - return hmac.NewSHA1(key) +// macSHA1 returns a macFunction for the given protocol version. +func macSHA1(version uint16, key []byte) macFunction { + if version == versionSSL30 { + mac := ssl30MAC{ + h: sha1.New(), + key: make([]byte, len(key)), + } + copy(mac.key, key) + return mac + } + return tls10MAC{hmac.NewSHA1(key)} +} + +type macFunction interface { + Size() int + MAC(seq, data []byte) []byte +} + +// ssl30MAC implements the SSLv3 MAC function, as defined in +// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 5.2.3.1 +type ssl30MAC struct { + h hash.Hash + key []byte +} + +func (s ssl30MAC) Size() int { + return s.h.Size() +} + +var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36} + +var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c} + +func (s ssl30MAC) MAC(seq, record []byte) []byte { + padLength := 48 + if s.h.Size() == 20 { + padLength = 40 + } + + s.h.Reset() + s.h.Write(s.key) + s.h.Write(ssl30Pad1[:padLength]) + s.h.Write(seq) + s.h.Write(record[:1]) + s.h.Write(record[3:5]) + s.h.Write(record[recordHeaderLen:]) + digest := s.h.Sum() + + s.h.Reset() + s.h.Write(s.key) + s.h.Write(ssl30Pad2[:padLength]) + s.h.Write(digest) + return s.h.Sum() +} + +// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3. +type tls10MAC struct { + h hash.Hash +} + +func (s tls10MAC) Size() int { + return s.h.Size() +} + +func (s tls10MAC) MAC(seq, record []byte) []byte { + s.h.Reset() + s.h.Write(seq) + s.h.Write(record) + return s.h.Sum() } func rsaKA() keyAgreement { diff --git a/src/pkg/crypto/tls/common.go b/src/pkg/crypto/tls/common.go index 3efac9c13..8fb1a8848 100644 --- a/src/pkg/crypto/tls/common.go +++ b/src/pkg/crypto/tls/common.go @@ -20,8 +20,11 @@ const ( recordHeaderLen = 5 // record header length maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) - minVersion = 0x0301 // minimum supported version - TLS 1.0 - maxVersion = 0x0301 // maximum supported version - TLS 1.0 + versionSSL30 = 0x0300 + versionTLS10 = 0x0301 + + minVersion = versionSSL30 + maxVersion = versionTLS10 ) // TLS record types. diff --git a/src/pkg/crypto/tls/conn.go b/src/pkg/crypto/tls/conn.go index fac65afd9..07199515d 100644 --- a/src/pkg/crypto/tls/conn.go +++ b/src/pkg/crypto/tls/conn.go @@ -11,7 +11,6 @@ import ( "crypto/cipher" "crypto/subtle" "crypto/x509" - "hash" "io" "net" "os" @@ -108,18 +107,20 @@ func (c *Conn) SetWriteTimeout(nsec int64) os.Error { // connection, either sending or receiving. type halfConn struct { sync.Mutex - cipher interface{} // cipher algorithm - mac hash.Hash // MAC algorithm - seq [8]byte // 64-bit sequence number - bfree *block // list of free blocks + version uint16 // protocol version + cipher interface{} // cipher algorithm + mac macFunction + seq [8]byte // 64-bit sequence number + bfree *block // list of free blocks nextCipher interface{} // next encryption state - nextMac hash.Hash // next MAC algorithm + nextMac macFunction // next MAC algorithm } // prepareCipherSpec sets the encryption and MAC states // that a subsequent changeCipherSpec will use. -func (hc *halfConn) prepareCipherSpec(cipher interface{}, mac hash.Hash) { +func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) { + hc.version = version hc.nextCipher = cipher hc.nextMac = mac } @@ -197,6 +198,22 @@ func removePadding(payload []byte) ([]byte, byte) { return payload[:len(payload)-int(toRemove)], good } +// removePaddingSSL30 is a replacement for removePadding in the case that the +// protocol version is SSLv3. In this version, the contents of the padding +// are random and cannot be checked. +func removePaddingSSL30(payload []byte) ([]byte, byte) { + if len(payload) < 1 { + return payload, 0 + } + + paddingLen := int(payload[len(payload)-1]) + 1 + if paddingLen > len(payload) { + return payload, 0 + } + + return payload[:len(payload)-paddingLen], 255 +} + func roundUp(a, b int) int { return a + (b-a%b)%b } @@ -226,7 +243,11 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) { } c.CryptBlocks(payload, payload) - payload, paddingGood = removePadding(payload) + if hc.version == versionSSL30 { + payload, paddingGood = removePaddingSSL30(payload) + } else { + payload, paddingGood = removePadding(payload) + } b.resize(recordHeaderLen + len(payload)) // note that we still have a timing side-channel in the @@ -256,13 +277,10 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) { b.data[4] = byte(n) b.resize(recordHeaderLen + n) remoteMAC := payload[n:] - - hc.mac.Reset() - hc.mac.Write(hc.seq[0:]) + localMAC := hc.mac.MAC(hc.seq[0:], b.data) hc.incSeq() - hc.mac.Write(b.data) - if subtle.ConstantTimeCompare(hc.mac.Sum(), remoteMAC) != 1 || paddingGood != 255 { + if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 { return false, alertBadRecordMAC } } @@ -291,11 +309,9 @@ func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) { func (hc *halfConn) encrypt(b *block) (bool, alert) { // mac if hc.mac != nil { - hc.mac.Reset() - hc.mac.Write(hc.seq[0:]) + mac := hc.mac.MAC(hc.seq[0:], b.data) hc.incSeq() - hc.mac.Write(b.data) - mac := hc.mac.Sum() + n := len(b.data) b.resize(n + len(mac)) copy(b.data[n:], mac) @@ -470,6 +486,19 @@ Again: if n > maxCiphertext { return c.sendAlert(alertRecordOverflow) } + if !c.haveVers { + // First message, be extra suspicious: + // this might not be a TLS client. + // Bail out before reading a full 'body', if possible. + // The current max version is 3.1. + // If the version is >= 16.0, it's probably not real. + // Similarly, a clientHello message encodes in + // well under a kilobyte. If the length is >= 12 kB, + // it's probably not real. + if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 || n >= 0x3000 { + return c.sendAlert(alertUnexpectedMessage) + } + } if err := b.readFromUntil(c.conn, recordHeaderLen+n); err != nil { if err == os.EOF { err = io.ErrUnexpectedEOF diff --git a/src/pkg/crypto/tls/handshake_client.go b/src/pkg/crypto/tls/handshake_client.go index 15604cea7..0badc39c4 100644 --- a/src/pkg/crypto/tls/handshake_client.go +++ b/src/pkg/crypto/tls/handshake_client.go @@ -14,7 +14,7 @@ import ( ) func (c *Conn) clientHandshake() os.Error { - finishedHash := newFinishedHash() + finishedHash := newFinishedHash(versionTLS10) if c.config == nil { c.config = defaultConfig() @@ -247,11 +247,11 @@ func (c *Conn) clientHandshake() os.Error { } masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := - keysFromPreMasterSecret10(preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen) + keysFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen) clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */ ) - clientHash := suite.mac(clientMAC) - c.out.prepareCipherSpec(clientCipher, clientHash) + clientHash := suite.mac(c.vers, clientMAC) + c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) if serverHello.nextProtoNeg { @@ -271,8 +271,8 @@ func (c *Conn) clientHandshake() os.Error { c.writeRecord(recordTypeHandshake, finished.marshal()) serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */ ) - serverHash := suite.mac(serverMAC) - c.in.prepareCipherSpec(serverCipher, serverHash) + serverHash := suite.mac(c.vers, serverMAC) + c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) c.readRecord(recordTypeChangeCipherSpec) if c.err != nil { return c.err diff --git a/src/pkg/crypto/tls/handshake_client_test.go b/src/pkg/crypto/tls/handshake_client_test.go index 3f91c7acf..c0abcda20 100644 --- a/src/pkg/crypto/tls/handshake_client_test.go +++ b/src/pkg/crypto/tls/handshake_client_test.go @@ -18,6 +18,7 @@ func testClientScript(t *testing.T, name string, clientScript [][]byte, config * go func() { cli.Write([]byte("hello\n")) cli.Close() + c.Close() }() defer c.Close() diff --git a/src/pkg/crypto/tls/handshake_messages.go b/src/pkg/crypto/tls/handshake_messages.go index 6645adce4..f11232d8e 100644 --- a/src/pkg/crypto/tls/handshake_messages.go +++ b/src/pkg/crypto/tls/handshake_messages.go @@ -676,9 +676,9 @@ func (m *finishedMsg) marshal() (x []byte) { return m.raw } - x = make([]byte, 16) + x = make([]byte, 4+len(m.verifyData)) x[0] = typeFinished - x[3] = 12 + x[3] = byte(len(m.verifyData)) copy(x[4:], m.verifyData) m.raw = x return @@ -686,7 +686,7 @@ func (m *finishedMsg) marshal() (x []byte) { func (m *finishedMsg) unmarshal(data []byte) bool { m.raw = data - if len(data) != 4+12 { + if len(data) < 4 { return false } m.verifyData = data[4:] diff --git a/src/pkg/crypto/tls/handshake_messages_test.go b/src/pkg/crypto/tls/handshake_messages_test.go index 23f729dd9..dc68a1223 100644 --- a/src/pkg/crypto/tls/handshake_messages_test.go +++ b/src/pkg/crypto/tls/handshake_messages_test.go @@ -14,13 +14,13 @@ import ( var tests = []interface{}{ &clientHelloMsg{}, &serverHelloMsg{}, + &finishedMsg{}, &certificateMsg{}, &certificateRequestMsg{}, &certificateVerifyMsg{}, &certificateStatusMsg{}, &clientKeyExchangeMsg{}, - &finishedMsg{}, &nextProtoMsg{}, } @@ -59,11 +59,12 @@ func TestMarshalUnmarshal(t *testing.T) { break } - if i >= 2 { - // The first two message types (ClientHello and - // ServerHello) are allowed to have parsable - // prefixes because the extension data is - // optional. + if i >= 3 { + // The first three message types (ClientHello, + // ServerHello and Finished) are allowed to + // have parsable prefixes because the extension + // data is optional and the length of the + // Finished varies across versions. for j := 0; j < len(marshaled); j++ { if m2.unmarshal(marshaled[0:j]) { t.Errorf("#%d unmarshaled a prefix of length %d of %#v", i, j, m1) diff --git a/src/pkg/crypto/tls/handshake_server.go b/src/pkg/crypto/tls/handshake_server.go index 44a324041..f083a873d 100644 --- a/src/pkg/crypto/tls/handshake_server.go +++ b/src/pkg/crypto/tls/handshake_server.go @@ -30,7 +30,7 @@ func (c *Conn) serverHandshake() os.Error { c.vers = vers c.haveVers = true - finishedHash := newFinishedHash() + finishedHash := newFinishedHash(vers) finishedHash.Write(clientHello.marshal()) hello := new(serverHelloMsg) @@ -128,7 +128,6 @@ FindCipherSuite: } keyAgreement := suite.ka() - skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello) if err != nil { c.sendAlert(alertHandshakeFailure) @@ -235,18 +234,18 @@ FindCipherSuite: finishedHash.Write(certVerify.marshal()) } - preMasterSecret, err := keyAgreement.processClientKeyExchange(config, ckx) + preMasterSecret, err := keyAgreement.processClientKeyExchange(config, ckx, c.vers) if err != nil { c.sendAlert(alertHandshakeFailure) return err } masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := - keysFromPreMasterSecret10(preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen) + keysFromPreMasterSecret(c.vers, preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen) clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */ ) - clientHash := suite.mac(clientMAC) - c.in.prepareCipherSpec(clientCipher, clientHash) + clientHash := suite.mac(c.vers, clientMAC) + c.in.prepareCipherSpec(c.vers, clientCipher, clientHash) c.readRecord(recordTypeChangeCipherSpec) if err := c.error(); err != nil { return err @@ -283,8 +282,8 @@ FindCipherSuite: finishedHash.Write(clientFinished.marshal()) serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */ ) - serverHash := suite.mac(serverMAC) - c.out.prepareCipherSpec(serverCipher, serverHash) + serverHash := suite.mac(c.vers, serverMAC) + c.out.prepareCipherSpec(c.vers, serverCipher, serverHash) c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) finished := new(finishedMsg) diff --git a/src/pkg/crypto/tls/handshake_server_test.go b/src/pkg/crypto/tls/handshake_server_test.go index b77646e43..d910eadcd 100644 --- a/src/pkg/crypto/tls/handshake_server_test.go +++ b/src/pkg/crypto/tls/handshake_server_test.go @@ -62,7 +62,7 @@ func TestSimpleError(t *testing.T) { testClientHelloFailure(t, &serverHelloDoneMsg{}, alertUnexpectedMessage) } -var badProtocolVersions = []uint16{0x0000, 0x0005, 0x0100, 0x0105, 0x0200, 0x0205, 0x0300} +var badProtocolVersions = []uint16{0x0000, 0x0005, 0x0100, 0x0105, 0x0200, 0x0205} func TestRejectBadProtocolVersion(t *testing.T) { for _, v := range badProtocolVersions { @@ -112,6 +112,7 @@ func testServerScript(t *testing.T, name string, serverScript [][]byte, config * go func() { srv.Write([]byte("hello, world\n")) srv.Close() + s.Close() }() defer c.Close() @@ -121,9 +122,9 @@ func testServerScript(t *testing.T, name string, serverScript [][]byte, config * continue } bb := make([]byte, len(b)) - _, err := io.ReadFull(c, bb) + n, err := io.ReadFull(c, bb) if err != nil { - t.Fatalf("%s #%d: %s", name, i, err) + t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", name, i, err, n, len(bb), bb[:n], b) } if !bytes.Equal(b, bb) { t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b) @@ -142,6 +143,10 @@ func TestHandshakeServerAES(t *testing.T) { testServerScript(t, "AES", aesServerScript, aesConfig) } +func TestHandshakeServerSSLv3(t *testing.T) { + testServerScript(t, "SSLv3", sslv3ServerScript, testConfig) +} + var serve = flag.Bool("serve", false, "run a TLS server on :10443") func TestRunServer(t *testing.T) { @@ -515,3 +520,165 @@ var aesServerScript = [][]byte{ 0xcd, 0x84, 0xf0, }, } + +var sslv3ServerScript = [][]byte{ + { + 0x16, 0x03, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, + 0x3d, 0x03, 0x00, 0x4e, 0x70, 0xe2, 0x18, 0x86, + 0xd6, 0xc6, 0x6f, 0xf3, 0xc8, 0xf4, 0x02, 0xd6, + 0x4d, 0xee, 0x17, 0x32, 0x4b, 0xd2, 0x78, 0xd8, + 0xa1, 0x03, 0x5d, 0x68, 0x82, 0x89, 0xbe, 0xfd, + 0x12, 0xb9, 0x06, 0x00, 0x00, 0x16, 0x00, 0x33, + 0x00, 0x39, 0x00, 0x16, 0x00, 0x32, 0x00, 0x38, + 0x00, 0x13, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, + 0x00, 0x05, 0x00, 0x04, 0x01, 0x00, + }, + + { + 0x16, 0x03, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, + 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16, + 0x03, 0x00, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, + 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, + 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, + 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, + 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, + 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, + 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, + 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, + 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, + 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, + 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, + 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, + 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, + 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, + 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, + 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, + 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, + 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, + 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, + 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, + 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, + 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, + 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, + 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, + 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, + 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, + 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, + 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, + 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, + 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, + 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, + 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, + 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, + 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, + 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, + 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, + 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, + 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, + 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, + 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, + 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, + 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, + 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, + 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, + 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, + 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, + 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, + 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, + 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, + 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, + 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, + 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, + 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, + 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, + 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, + 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, + 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, + 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, + 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, + 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, + 0xbd, 0xd9, 0x16, 0x03, 0x00, 0x00, 0x04, 0x0e, + 0x00, 0x00, 0x00, + }, + + { + 0x16, 0x03, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, + 0x80, 0x74, 0x0e, 0x3a, 0xcf, 0xba, 0x9f, 0x1a, + 0x9b, 0xb2, 0xa4, 0xc7, 0x5d, 0xf3, 0x0c, 0x80, + 0x06, 0x80, 0xf3, 0x57, 0xb2, 0xd9, 0x36, 0x24, + 0x6a, 0x06, 0x13, 0x40, 0xf9, 0x7c, 0xb9, 0x3e, + 0x4b, 0x68, 0x4f, 0x21, 0x90, 0x2d, 0xbd, 0xca, + 0xd4, 0x83, 0xf0, 0x7a, 0xeb, 0x7a, 0x74, 0x1b, + 0xcd, 0xfe, 0x69, 0xef, 0xc0, 0x86, 0xa0, 0x24, + 0x31, 0x65, 0x40, 0xd2, 0xdd, 0x6f, 0xb9, 0xd7, + 0x8d, 0xc1, 0x69, 0x60, 0x44, 0x7a, 0x75, 0xfb, + 0x42, 0x6a, 0x0f, 0x66, 0x45, 0x10, 0x73, 0xee, + 0x87, 0x28, 0x37, 0x83, 0x86, 0xd8, 0x5a, 0xc8, + 0x60, 0x87, 0xda, 0x33, 0x87, 0xaf, 0x34, 0x8b, + 0xf5, 0x61, 0x63, 0x7a, 0x5c, 0x60, 0x26, 0xb9, + 0xdb, 0xa1, 0xb7, 0xe3, 0x60, 0x38, 0x94, 0x5c, + 0x83, 0x23, 0xd6, 0x8d, 0xc2, 0x14, 0x4a, 0x0f, + 0x0e, 0x4f, 0xf9, 0x4e, 0x7b, 0x15, 0xcd, 0x18, + 0x04, 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16, + 0x03, 0x00, 0x00, 0x3c, 0xbd, 0xbc, 0xec, 0xdc, + 0x79, 0xb1, 0xae, 0x16, 0xc9, 0x26, 0x9a, 0xc0, + 0xc0, 0x2c, 0x33, 0x36, 0x13, 0x91, 0x58, 0x5d, + 0x7d, 0xee, 0x4e, 0xd8, 0x7e, 0xac, 0x88, 0x87, + 0x0a, 0x75, 0x66, 0xb1, 0x44, 0x79, 0x2f, 0x42, + 0xe8, 0x92, 0x74, 0x4c, 0xab, 0x36, 0xc8, 0x17, + 0x5f, 0x02, 0x8a, 0x20, 0x53, 0xe9, 0x1d, 0xb4, + 0xfe, 0x5c, 0x2b, 0xd9, 0x0a, 0xfb, 0xc6, 0x63, + }, + + { + 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16, 0x03, + 0x00, 0x00, 0x3c, 0xaa, 0xa1, 0x98, 0xc4, 0x6b, + 0x5a, 0x16, 0x3f, 0x5f, 0xa4, 0x96, 0x3e, 0x78, + 0xe4, 0x6f, 0x49, 0x05, 0x47, 0xc4, 0x05, 0x60, + 0xeb, 0x0b, 0x45, 0xe3, 0xbc, 0x50, 0x11, 0x24, + 0x5f, 0x01, 0xd7, 0xb8, 0x8f, 0x60, 0x63, 0x66, + 0xbd, 0x3e, 0xd9, 0xa8, 0x80, 0x43, 0x9f, 0x0b, + 0x51, 0x61, 0xed, 0x13, 0xc6, 0x21, 0xd0, 0xfe, + 0xbc, 0x17, 0x3c, 0x36, 0xb0, 0x82, 0x7f, 0x17, + 0x03, 0x00, 0x00, 0x21, 0xee, 0x44, 0xf3, 0xa6, + 0x88, 0x9d, 0x78, 0x44, 0xde, 0xdf, 0xeb, 0xc5, + 0xad, 0xc4, 0xcc, 0x56, 0x5c, 0x54, 0x96, 0x52, + 0x3f, 0xd9, 0x40, 0x6e, 0x79, 0xd8, 0x58, 0x78, + 0x4f, 0x5a, 0xe9, 0x06, 0xef, 0x15, 0x03, 0x00, + 0x00, 0x16, 0xd3, 0xc2, 0x52, 0x99, 0x2a, 0x84, + 0xc4, 0x52, 0x5f, 0x3b, 0x19, 0xe7, 0xfc, 0x65, + 0xaf, 0xd3, 0xb7, 0xa3, 0xcc, 0x4a, 0x1d, 0x2e, + }, +} diff --git a/src/pkg/crypto/tls/key_agreement.go b/src/pkg/crypto/tls/key_agreement.go index a40d18fd9..e347528b5 100644 --- a/src/pkg/crypto/tls/key_agreement.go +++ b/src/pkg/crypto/tls/key_agreement.go @@ -24,7 +24,7 @@ func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, clientHello return nil, nil } -func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg) ([]byte, os.Error) { +func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, os.Error) { preMasterSecret := make([]byte, 48) _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) if err != nil { @@ -34,11 +34,15 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKe if len(ckx.ciphertext) < 2 { return nil, os.NewError("bad ClientKeyExchange") } - ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) - if ciphertextLen != len(ckx.ciphertext)-2 { - return nil, os.NewError("bad ClientKeyExchange") + + ciphertext := ckx.ciphertext + if version != versionSSL30 { + ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) + if ciphertextLen != len(ckx.ciphertext)-2 { + return nil, os.NewError("bad ClientKeyExchange") + } + ciphertext = ckx.ciphertext[2:] } - ciphertext := ckx.ciphertext[2:] err = rsa.DecryptPKCS1v15SessionKey(config.rand(), config.Certificates[0].PrivateKey, ciphertext, preMasterSecret) if err != nil { @@ -159,7 +163,7 @@ Curve: return skx, nil } -func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg) ([]byte, os.Error) { +func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, os.Error) { if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { return nil, os.NewError("bad ClientKeyExchange") } diff --git a/src/pkg/crypto/tls/prf.go b/src/pkg/crypto/tls/prf.go index 478cf65f9..2d58dc520 100644 --- a/src/pkg/crypto/tls/prf.go +++ b/src/pkg/crypto/tls/prf.go @@ -63,6 +63,39 @@ func pRF10(result, secret, label, seed []byte) { } } +// pRF30 implements the SSL 3.0 pseudo-random function, as defined in +// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6. +func pRF30(result, secret, label, seed []byte) { + hashSHA1 := sha1.New() + hashMD5 := md5.New() + + done := 0 + i := 0 + // RFC5246 section 6.3 says that the largest PRF output needed is 128 + // bytes. Since no more ciphersuites will be added to SSLv3, this will + // remain true. Each iteration gives us 16 bytes so 10 iterations will + // be sufficient. + var b [11]byte + for done < len(result) { + for j := 0; j <= i; j++ { + b[j] = 'A' + byte(i) + } + + hashSHA1.Reset() + hashSHA1.Write(b[:i+1]) + hashSHA1.Write(secret) + hashSHA1.Write(seed) + digest := hashSHA1.Sum() + + hashMD5.Reset() + hashMD5.Write(secret) + hashMD5.Write(digest) + + done += copy(result[done:], hashMD5.Sum()) + i++ + } +} + const ( tlsRandomLength = 32 // Length of a random nonce in TLS 1.1. masterSecretLength = 48 // Length of a master secret in TLS 1.1. @@ -77,19 +110,24 @@ var serverFinishedLabel = []byte("server finished") // keysFromPreMasterSecret generates the connection keys from the pre master // secret, given the lengths of the MAC key, cipher key and IV, as defined in // RFC 2246, section 6.3. -func keysFromPreMasterSecret10(preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { +func keysFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { + prf := pRF10 + if version == versionSSL30 { + prf = pRF30 + } + var seed [tlsRandomLength * 2]byte copy(seed[0:len(clientRandom)], clientRandom) copy(seed[len(clientRandom):], serverRandom) masterSecret = make([]byte, masterSecretLength) - pRF10(masterSecret, preMasterSecret, masterSecretLabel, seed[0:]) + prf(masterSecret, preMasterSecret, masterSecretLabel, seed[0:]) copy(seed[0:len(clientRandom)], serverRandom) copy(seed[len(serverRandom):], clientRandom) n := 2*macLen + 2*keyLen + 2*ivLen keyMaterial := make([]byte, n) - pRF10(keyMaterial, masterSecret, keyExpansionLabel, seed[0:]) + prf(keyMaterial, masterSecret, keyExpansionLabel, seed[0:]) clientMAC = keyMaterial[:macLen] keyMaterial = keyMaterial[macLen:] serverMAC = keyMaterial[:macLen] @@ -104,6 +142,10 @@ func keysFromPreMasterSecret10(preMasterSecret, clientRandom, serverRandom []byt return } +func newFinishedHash(version uint16) finishedHash { + return finishedHash{md5.New(), sha1.New(), md5.New(), sha1.New(), version} +} + // A finishedHash calculates the hash of a set of handshake messages suitable // for including in a Finished message. type finishedHash struct { @@ -111,10 +153,7 @@ type finishedHash struct { clientSHA1 hash.Hash serverMD5 hash.Hash serverSHA1 hash.Hash -} - -func newFinishedHash() finishedHash { - return finishedHash{md5.New(), sha1.New(), md5.New(), sha1.New()} + version uint16 } func (h finishedHash) Write(msg []byte) (n int, err os.Error) { @@ -125,9 +164,10 @@ func (h finishedHash) Write(msg []byte) (n int, err os.Error) { return len(msg), nil } -// finishedSum calculates the contents of the verify_data member of a Finished -// message given the MD5 and SHA1 hashes of a set of handshake messages. -func finishedSum(md5, sha1, label, masterSecret []byte) []byte { +// finishedSum10 calculates the contents of the verify_data member of a TLSv1 +// Finished message given the MD5 and SHA1 hashes of a set of handshake +// messages. +func finishedSum10(md5, sha1, label, masterSecret []byte) []byte { seed := make([]byte, len(md5)+len(sha1)) copy(seed, md5) copy(seed[len(md5):], sha1) @@ -136,18 +176,61 @@ func finishedSum(md5, sha1, label, masterSecret []byte) []byte { return out } +// finishedSum30 calculates the contents of the verify_data member of a SSLv3 +// Finished message given the MD5 and SHA1 hashes of a set of handshake +// messages. +func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []byte { + md5.Write(magic[:]) + md5.Write(masterSecret) + md5.Write(ssl30Pad1[:]) + md5Digest := md5.Sum() + + md5.Reset() + md5.Write(masterSecret) + md5.Write(ssl30Pad2[:]) + md5.Write(md5Digest) + md5Digest = md5.Sum() + + sha1.Write(magic[:]) + sha1.Write(masterSecret) + sha1.Write(ssl30Pad1[:40]) + sha1Digest := sha1.Sum() + + sha1.Reset() + sha1.Write(masterSecret) + sha1.Write(ssl30Pad2[:40]) + sha1.Write(sha1Digest) + sha1Digest = sha1.Sum() + + ret := make([]byte, len(md5Digest)+len(sha1Digest)) + copy(ret, md5Digest) + copy(ret[len(md5Digest):], sha1Digest) + return ret +} + +var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54} +var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52} + // clientSum returns the contents of the verify_data member of a client's // Finished message. func (h finishedHash) clientSum(masterSecret []byte) []byte { + if h.version == versionSSL30 { + return finishedSum30(h.clientMD5, h.clientSHA1, masterSecret, ssl3ClientFinishedMagic) + } + md5 := h.clientMD5.Sum() sha1 := h.clientSHA1.Sum() - return finishedSum(md5, sha1, clientFinishedLabel, masterSecret) + return finishedSum10(md5, sha1, clientFinishedLabel, masterSecret) } // serverSum returns the contents of the verify_data member of a server's // Finished message. func (h finishedHash) serverSum(masterSecret []byte) []byte { + if h.version == versionSSL30 { + return finishedSum30(h.serverMD5, h.serverSHA1, masterSecret, ssl3ServerFinishedMagic) + } + md5 := h.serverMD5.Sum() sha1 := h.serverSHA1.Sum() - return finishedSum(md5, sha1, serverFinishedLabel, masterSecret) + return finishedSum10(md5, sha1, serverFinishedLabel, masterSecret) } diff --git a/src/pkg/crypto/tls/prf_test.go b/src/pkg/crypto/tls/prf_test.go index f8c4acb9d..a32392cef 100644 --- a/src/pkg/crypto/tls/prf_test.go +++ b/src/pkg/crypto/tls/prf_test.go @@ -34,6 +34,7 @@ func TestSplitPreMasterSecret(t *testing.T) { } type testKeysFromTest struct { + version uint16 preMasterSecret string clientRandom, serverRandom string masterSecret string @@ -47,7 +48,7 @@ func TestKeysFromPreMasterSecret(t *testing.T) { in, _ := hex.DecodeString(test.preMasterSecret) clientRandom, _ := hex.DecodeString(test.clientRandom) serverRandom, _ := hex.DecodeString(test.serverRandom) - master, clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromPreMasterSecret10(in, clientRandom, serverRandom, test.macLen, test.keyLen, 0) + master, clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromPreMasterSecret(test.version, in, clientRandom, serverRandom, test.macLen, test.keyLen, 0) masterString := hex.EncodeToString(master) clientMACString := hex.EncodeToString(clientMAC) serverMACString := hex.EncodeToString(serverMAC) @@ -58,7 +59,7 @@ func TestKeysFromPreMasterSecret(t *testing.T) { serverMACString != test.serverMAC || clientKeyString != test.clientKey || serverKeyString != test.serverKey { - t.Errorf("#%d: got: (%s, %s, %s, %s, %s) want: (%s, %s, %s, %s %s)", i, masterString, clientMACString, serverMACString, clientKeyString, serverMACString, test.masterSecret, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey) + t.Errorf("#%d: got: (%s, %s, %s, %s, %s) want: (%s, %s, %s, %s, %s)", i, masterString, clientMACString, serverMACString, clientKeyString, serverKeyString, test.masterSecret, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey) } } } @@ -66,6 +67,7 @@ func TestKeysFromPreMasterSecret(t *testing.T) { // These test vectors were generated from GnuTLS using `gnutls-cli --insecure -d 9 ` var testKeysFromTests = []testKeysFromTest{ { + versionTLS10, "0302cac83ad4b1db3b9ab49ad05957de2a504a634a386fc600889321e1a971f57479466830ac3e6f468e87f5385fa0c5", "4ae66303755184a3917fcb44880605fcc53baa01912b22ed94473fc69cebd558", "4ae663020ec16e6bb5130be918cfcafd4d765979a3136a5d50c593446e4e44db", @@ -78,6 +80,7 @@ var testKeysFromTests = []testKeysFromTest{ 16, }, { + versionTLS10, "03023f7527316bc12cbcd69e4b9e8275d62c028f27e65c745cfcddc7ce01bd3570a111378b63848127f1c36e5f9e4890", "4ae66364b5ea56b20ce4e25555aed2d7e67f42788dd03f3fee4adae0459ab106", "4ae66363ab815cbf6a248b87d6b556184e945e9b97fbdf247858b0bdafacfa1c", @@ -90,6 +93,7 @@ var testKeysFromTests = []testKeysFromTest{ 16, }, { + versionTLS10, "832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1", "4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e", "4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e", @@ -101,4 +105,17 @@ var testKeysFromTests = []testKeysFromTest{ 20, 16, }, + { + versionSSL30, + "832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1", + "4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e", + "4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e", + "a614863e56299dcffeea2938f22c2ba023768dbe4b3f6877bc9c346c6ae529b51d9cb87ff9695ea4d01f2205584405b2", + "2c450d5b6f6e2013ac6bea6a0b32200d4e1ffb94", + "7a7a7438769536f2fb1ae49a61f0703b79b2dc53", + "f8f6b26c10f12855c9aafb1e0e839ccf", + "2b9d4b4a60cb7f396780ebff50650419", + 20, + 16, + }, } diff --git a/src/pkg/debug/elf/file_test.go b/src/pkg/debug/elf/file_test.go index 451d3d514..98f2723c8 100644 --- a/src/pkg/debug/elf/file_test.go +++ b/src/pkg/debug/elf/file_test.go @@ -227,6 +227,9 @@ func TestNoSectionOverlaps(t *testing.T) { } for i, si := range f.Sections { sih := si.SectionHeader + if sih.Type == SHT_NOBITS { + continue + } for j, sj := range f.Sections { sjh := sj.SectionHeader if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 { diff --git a/src/pkg/exec/lp_unix.go b/src/pkg/exec/lp_unix.go index 008fb11a8..0cd19e7ac 100644 --- a/src/pkg/exec/lp_unix.go +++ b/src/pkg/exec/lp_unix.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build darwin freebsd linux openbsd + package exec import ( diff --git a/src/pkg/exp/gui/x11/conn.go b/src/pkg/exp/gui/x11/conn.go index 1d237816a..4645073c4 100644 --- a/src/pkg/exp/gui/x11/conn.go +++ b/src/pkg/exp/gui/x11/conn.go @@ -618,7 +618,7 @@ func NewWindowDisplay(display string) (gui.Window, os.Error) { return nil, err } - c.img = image.NewRGBA(windowWidth, windowHeight) + c.img = image.NewRGBA(image.Rect(0, 0, windowWidth, windowHeight)) c.eventc = make(chan interface{}, 16) c.flush = make(chan bool, 1) go c.readSocket() diff --git a/src/pkg/exp/norm/Makefile b/src/pkg/exp/norm/Makefile index 16239a72e..fd32f8696 100644 --- a/src/pkg/exp/norm/Makefile +++ b/src/pkg/exp/norm/Makefile @@ -25,6 +25,10 @@ maketesttables: maketesttables.go triegen.go $(GC) maketesttables.go triegen.go $(LD) -o maketesttables maketesttables.$O +normregtest: normregtest.go + $(GC) normregtest.go + $(LD) -o normregtest normregtest.$O + tables: maketables ./maketables > tables.go gofmt -w tables.go @@ -39,7 +43,10 @@ testshort: maketables maketesttables # Downloads from www.unicode.org, so not part # of standard test scripts. -test: testtables +test: testtables regtest testtables: maketables ./maketables -test -tables= + +regtest: normregtest + ./normregtest diff --git a/src/pkg/exp/norm/maketables.go b/src/pkg/exp/norm/maketables.go index dbe560618..14718c5cd 100644 --- a/src/pkg/exp/norm/maketables.go +++ b/src/pkg/exp/norm/maketables.go @@ -518,7 +518,7 @@ func completeCharFields(form int) { if JamoLBase <= i && i < JamoLEnd { f.combinesForward = true } - if JamoVBase <= i && i < JamoTEnd { + if JamoVBase <= i && i < JamoVEnd { f.quickCheck[MComposed] = QCMaybe f.combinesBackward = true f.combinesForward = true diff --git a/src/pkg/exp/norm/maketesttables.go b/src/pkg/exp/norm/maketesttables.go index c5f6a6436..fdcc114be 100644 --- a/src/pkg/exp/norm/maketesttables.go +++ b/src/pkg/exp/norm/maketesttables.go @@ -21,6 +21,7 @@ var testRunes = []int{ 0x80, 0x100, 0x7FF, // 2-byte sequences 0x800, 0x999, 0xFFFF, // 3-byte sequences 0x10000, 0x10101, 0x10FFFF, // 4-byte sequences + 0x200, 0x201, 0x202, 0x210, 0x215, // five entries in one sparse block } const fileHeader = `// Generated by running diff --git a/src/pkg/exp/norm/normregtest.go b/src/pkg/exp/norm/normregtest.go new file mode 100644 index 000000000..3ab10b77b --- /dev/null +++ b/src/pkg/exp/norm/normregtest.go @@ -0,0 +1,295 @@ +// 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 main + +import ( + "bufio" + "bytes" + "exp/norm" + "exp/regexp" + "flag" + "fmt" + "http" + "log" + "os" + "path" + "runtime" + "strings" + "strconv" + "time" + "utf8" +) + +func main() { + flag.Parse() + loadTestData() + CharacterByCharacterTests() + StandardTests() + PerformanceTest() + if errorCount == 0 { + fmt.Println("PASS") + } +} + +const file = "NormalizationTest.txt" + +var url = flag.String("url", + "http://www.unicode.org/Public/6.0.0/ucd/"+file, + "URL of Unicode database directory") +var localFiles = flag.Bool("local", + false, + "data files have been copied to the current directory; for debugging only") + +var logger = log.New(os.Stderr, "", log.Lshortfile) + +// This regression test runs the test set in NormalizationTest.txt +// (taken from http://www.unicode.org/Public/6.0.0/ucd/). +// +// NormalizationTest.txt has form: +// @Part0 # Specific cases +// # +// 1E0A;1E0A;0044 0307;1E0A;0044 0307; # (Ḋ; Ḋ; D◌̇; Ḋ; D◌̇; ) LATIN CAPITAL LETTER D WITH DOT ABOVE +// 1E0C;1E0C;0044 0323;1E0C;0044 0323; # (Ḍ; Ḍ; D◌̣; Ḍ; D◌̣; ) LATIN CAPITAL LETTER D WITH DOT BELOW +// +// Each test has 5 columns (c1, c2, c3, c4, c5), where +// (c1, c2, c3, c4, c5) == (c1, NFC(c1), NFD(c1), NFKC(c1), NFKD(c1)) +// +// CONFORMANCE: +// 1. The following invariants must be true for all conformant implementations +// +// NFC +// c2 == NFC(c1) == NFC(c2) == NFC(c3) +// c4 == NFC(c4) == NFC(c5) +// +// NFD +// c3 == NFD(c1) == NFD(c2) == NFD(c3) +// c5 == NFD(c4) == NFD(c5) +// +// NFKC +// c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5) +// +// NFKD +// c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5) +// +// 2. For every code point X assigned in this version of Unicode that is not +// specifically listed in Part 1, the following invariants must be true +// for all conformant implementations: +// +// X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X) +// + +// Column types. +const ( + cRaw = iota + cNFC + cNFD + cNFKC + cNFKD + cMaxColumns +) + +// Holds data from NormalizationTest.txt +var part []Part + +type Part struct { + name string + number int + tests []Test +} + +type Test struct { + name string + partnr int + number int + rune int // used for character by character test + cols [cMaxColumns]string // Each has 5 entries, see below. +} + +func (t Test) Name() string { + if t.number < 0 { + return part[t.partnr].name + } + return fmt.Sprintf("%s:%d", part[t.partnr].name, t.number) +} + +var partRe = regexp.MustCompile(`@Part(\d) # (.*)\n$`) +var testRe = regexp.MustCompile(`^` + strings.Repeat(`([\dA-F ]+);`, 5) + ` # (.*)\n?$`) + +var counter int + +// Load the data form NormalizationTest.txt +func loadTestData() { + if *localFiles { + pwd, _ := os.Getwd() + *url = "file://" + path.Join(pwd, file) + } + t := &http.Transport{} + t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/"))) + c := &http.Client{Transport: t} + resp, err := c.Get(*url) + if err != nil { + logger.Fatal(err) + } + if resp.StatusCode != 200 { + logger.Fatal("bad GET status for "+file, resp.Status) + } + f := resp.Body + defer f.Close() + input := bufio.NewReader(f) + for { + line, err := input.ReadString('\n') + if err != nil { + if err == os.EOF { + break + } + logger.Fatal(err) + } + if len(line) == 0 || line[0] == '#' { + continue + } + m := partRe.FindStringSubmatch(line) + if m != nil { + if len(m) < 3 { + logger.Fatal("Failed to parse Part: ", line) + } + i, err := strconv.Atoi(m[1]) + if err != nil { + logger.Fatal(err) + } + name := m[2] + part = append(part, Part{name: name[:len(name)-1], number: i}) + continue + } + m = testRe.FindStringSubmatch(line) + if m == nil || len(m) < 7 { + logger.Fatalf(`Failed to parse: "%s" result: %#v`, line, m) + } + test := Test{name: m[6], partnr: len(part) - 1, number: counter} + counter++ + for j := 1; j < len(m)-1; j++ { + for _, split := range strings.Split(m[j], " ") { + r, err := strconv.Btoui64(split, 16) + if err != nil { + logger.Fatal(err) + } + if test.rune == 0 { + // save for CharacterByCharacterTests + test.rune = int(r) + } + var buf [utf8.UTFMax]byte + sz := utf8.EncodeRune(buf[:], int(r)) + test.cols[j-1] += string(buf[:sz]) + } + } + part := &part[len(part)-1] + part.tests = append(part.tests, test) + } +} + +var fstr = []string{"NFC", "NFD", "NFKC", "NFKD"} + +var errorCount int + +func cmpResult(t *Test, name string, f norm.Form, gold, test, result string) { + if gold != result { + errorCount++ + if errorCount > 20 { + return + } + st, sr, sg := []int(test), []int(result), []int(gold) + logger.Printf("%s:%s: %s(%X)=%X; want:%X: %s", + t.Name(), name, fstr[f], st, sr, sg, t.name) + } +} + +func cmpIsNormal(t *Test, name string, f norm.Form, test string, result, want bool) { + if result != want { + errorCount++ + if errorCount > 20 { + return + } + logger.Printf("%s:%s: %s(%X)=%v; want: %v", t.Name(), name, fstr[f], []int(test), result, want) + } +} + +func doTest(t *Test, f norm.Form, gold, test string) { + result := f.Bytes([]byte(test)) + cmpResult(t, "Bytes", f, gold, test, string(result)) + for i := range test { + out := f.Append(f.Bytes([]byte(test[:i])), []byte(test[i:])...) + cmpResult(t, fmt.Sprintf(":Append:%d", i), f, gold, test, string(out)) + } + cmpIsNormal(t, "IsNormal", f, test, f.IsNormal([]byte(test)), test == gold) +} + +func doConformanceTests(t *Test, partn int) { + for i := 0; i <= 2; i++ { + doTest(t, norm.NFC, t.cols[1], t.cols[i]) + doTest(t, norm.NFD, t.cols[2], t.cols[i]) + doTest(t, norm.NFKC, t.cols[3], t.cols[i]) + doTest(t, norm.NFKD, t.cols[4], t.cols[i]) + } + for i := 3; i <= 4; i++ { + doTest(t, norm.NFC, t.cols[3], t.cols[i]) + doTest(t, norm.NFD, t.cols[4], t.cols[i]) + doTest(t, norm.NFKC, t.cols[3], t.cols[i]) + doTest(t, norm.NFKD, t.cols[4], t.cols[i]) + } +} + +func CharacterByCharacterTests() { + tests := part[1].tests + last := 0 + for i := 0; i <= len(tests); i++ { // last one is special case + var rune int + if i == len(tests) { + rune = 0x2FA1E // Don't have to go to 0x10FFFF + } else { + rune = tests[i].rune + } + for last++; last < rune; last++ { + // Check all characters that were not explicitly listed in the test. + t := &Test{partnr: 1, number: -1} + char := string(last) + doTest(t, norm.NFC, char, char) + doTest(t, norm.NFD, char, char) + doTest(t, norm.NFKC, char, char) + doTest(t, norm.NFKD, char, char) + } + if i < len(tests) { + doConformanceTests(&tests[i], 1) + } + } +} + +func StandardTests() { + for _, j := range []int{0, 2, 3} { + for _, test := range part[j].tests { + doConformanceTests(&test, j) + } + } +} + +// PerformanceTest verifies that normalization is O(n). If any of the +// code does not properly check for maxCombiningChars, normalization +// may exhibit O(n**2) behavior. +func PerformanceTest() { + runtime.GOMAXPROCS(2) + success := make(chan bool, 1) + go func() { + buf := bytes.Repeat([]byte("\u035D"), 1024*1024) + buf = append(buf, []byte("\u035B")...) + norm.NFC.Append(nil, buf...) + success <- true + }() + timeout := time.After(1e9) + select { + case <-success: + // test completed before the timeout + case <-timeout: + errorCount++ + logger.Printf(`unexpectedly long time to complete PerformanceTest`) + } +} diff --git a/src/pkg/exp/norm/tables.go b/src/pkg/exp/norm/tables.go index 36dcd5c84..55ff052dc 100644 --- a/src/pkg/exp/norm/tables.go +++ b/src/pkg/exp/norm/tables.go @@ -2490,545 +2490,632 @@ var decomps = [...]byte{ 0x98, 0x80, } -// nfcDecompValues: 4992 entries, 9984 bytes +// nfcDecompValues: 1408 entries, 2816 bytes // Block 2 is the null block. -var nfcDecompValues = [4992]uint16{ +var nfcDecompValues = [1408]uint16{ // Block 0x0, offset 0x0 // Block 0x1, offset 0x40 // Block 0x2, offset 0x80 // Block 0x3, offset 0xc0 - 0x00c0: 0x0032, 0x00c1: 0x0036, 0x00c2: 0x003a, 0x00c3: 0x003e, 0x00c4: 0x0042, 0x00c5: 0x0046, - 0x00c7: 0x004a, 0x00c8: 0x004e, 0x00c9: 0x0052, 0x00ca: 0x0056, 0x00cb: 0x005a, - 0x00cc: 0x005e, 0x00cd: 0x0062, 0x00ce: 0x0066, 0x00cf: 0x006a, 0x00d1: 0x006e, - 0x00d2: 0x0072, 0x00d3: 0x0076, 0x00d4: 0x007a, 0x00d5: 0x007e, 0x00d6: 0x0082, - 0x00d9: 0x0086, 0x00da: 0x008a, 0x00db: 0x008e, 0x00dc: 0x0092, 0x00dd: 0x0096, - 0x00e0: 0x009a, 0x00e1: 0x009e, 0x00e2: 0x00a2, 0x00e3: 0x00a6, - 0x00e4: 0x00aa, 0x00e5: 0x00ae, 0x00e7: 0x00b2, 0x00e8: 0x00b6, 0x00e9: 0x00ba, - 0x00ea: 0x00be, 0x00eb: 0x00c2, 0x00ec: 0x00c6, 0x00ed: 0x00ca, 0x00ee: 0x00ce, 0x00ef: 0x00d2, - 0x00f1: 0x00d6, 0x00f2: 0x00da, 0x00f3: 0x00de, 0x00f4: 0x00e2, 0x00f5: 0x00e6, - 0x00f6: 0x00ea, 0x00f9: 0x00ee, 0x00fa: 0x00f2, 0x00fb: 0x00f6, - 0x00fc: 0x00fa, 0x00fd: 0x00fe, 0x00ff: 0x0102, + 0x00cd: 0x02fb, 0x00ce: 0x02ff, 0x00cf: 0x0303, 0x00d0: 0x0307, 0x00d1: 0x030b, + 0x00d2: 0x030f, 0x00d3: 0x0313, 0x00d4: 0x0317, 0x00d5: 0x031b, 0x00d6: 0x0321, 0x00d7: 0x0327, + 0x00d8: 0x032d, 0x00d9: 0x0333, 0x00da: 0x0339, 0x00db: 0x033f, 0x00dc: 0x0345, + 0x00de: 0x034b, 0x00df: 0x0351, 0x00e0: 0x0357, 0x00e1: 0x035d, 0x00e2: 0x0363, 0x00e3: 0x0368, + 0x00e6: 0x036d, 0x00e7: 0x0371, 0x00e8: 0x0375, 0x00e9: 0x0379, + 0x00ea: 0x037d, 0x00eb: 0x0381, 0x00ec: 0x0385, 0x00ed: 0x038b, 0x00ee: 0x0391, 0x00ef: 0x0396, + 0x00f0: 0x039b, 0x00f4: 0x03a8, 0x00f5: 0x03ac, + 0x00f8: 0x03b0, 0x00f9: 0x03b4, 0x00fa: 0x03b8, 0x00fb: 0x03be, + 0x00fc: 0x03c4, 0x00fd: 0x03c9, 0x00fe: 0x03ce, 0x00ff: 0x03d3, // Block 0x4, offset 0x100 - 0x0100: 0x0106, 0x0101: 0x010a, 0x0102: 0x010e, 0x0103: 0x0112, 0x0104: 0x0116, 0x0105: 0x011a, - 0x0106: 0x011e, 0x0107: 0x0122, 0x0108: 0x0126, 0x0109: 0x012a, 0x010a: 0x012e, 0x010b: 0x0132, - 0x010c: 0x0136, 0x010d: 0x013a, 0x010e: 0x013e, 0x010f: 0x0142, - 0x0112: 0x0146, 0x0113: 0x014a, 0x0114: 0x014e, 0x0115: 0x0152, 0x0116: 0x0156, 0x0117: 0x015a, - 0x0118: 0x015e, 0x0119: 0x0162, 0x011a: 0x0166, 0x011b: 0x016a, 0x011c: 0x016e, 0x011d: 0x0172, - 0x011e: 0x0176, 0x011f: 0x017a, 0x0120: 0x017e, 0x0121: 0x0182, 0x0122: 0x0186, 0x0123: 0x018a, - 0x0124: 0x018e, 0x0125: 0x0192, 0x0128: 0x0196, 0x0129: 0x019a, - 0x012a: 0x019e, 0x012b: 0x01a2, 0x012c: 0x01a6, 0x012d: 0x01aa, 0x012e: 0x01ae, 0x012f: 0x01b2, - 0x0130: 0x01b6, 0x0134: 0x01c0, 0x0135: 0x01c4, - 0x0136: 0x01c8, 0x0137: 0x01cc, 0x0139: 0x01d0, 0x013a: 0x01d4, 0x013b: 0x01d8, - 0x013c: 0x01dc, 0x013d: 0x01e0, 0x013e: 0x01e4, + 0x0100: 0x0b02, 0x0101: 0x0b06, 0x0102: 0x0b0a, 0x0103: 0x0b0e, 0x0104: 0x0b12, 0x0105: 0x0b16, + 0x0106: 0x0b1a, 0x0107: 0x0b1e, 0x0108: 0x0b22, 0x0109: 0x0b26, 0x010a: 0x0b2a, 0x010b: 0x0b2e, + 0x010c: 0x0b32, 0x010d: 0x0b38, 0x010e: 0x0b3e, 0x010f: 0x0b44, 0x0110: 0x0b4a, 0x0111: 0x0b50, + 0x0112: 0x0b56, 0x0113: 0x0b5c, 0x0114: 0x0b62, 0x0115: 0x0b66, 0x0116: 0x0b6a, 0x0117: 0x0b6e, + 0x0118: 0x0b72, 0x0119: 0x0b76, 0x011a: 0x0b7a, 0x011b: 0x0b7e, 0x011c: 0x0b82, 0x011d: 0x0b88, + 0x011e: 0x0b8e, 0x011f: 0x0b92, 0x0120: 0x0b96, 0x0121: 0x0b9a, 0x0122: 0x0b9e, 0x0123: 0x0ba2, + 0x0124: 0x0ba6, 0x0125: 0x0bac, 0x0126: 0x0bb2, 0x0127: 0x0bb8, 0x0128: 0x0bbe, 0x0129: 0x0bc4, + 0x012a: 0x0bca, 0x012b: 0x0bce, 0x012c: 0x0bd2, 0x012d: 0x0bd6, 0x012e: 0x0bda, 0x012f: 0x0bde, + 0x0130: 0x0be2, 0x0131: 0x0be6, 0x0132: 0x0bea, 0x0133: 0x0bee, 0x0134: 0x0bf2, 0x0135: 0x0bf6, + 0x0136: 0x0bfa, 0x0137: 0x0bfe, 0x0138: 0x0c02, 0x0139: 0x0c08, 0x013a: 0x0c0e, 0x013b: 0x0c14, + 0x013c: 0x0c1a, 0x013d: 0x0c1e, 0x013e: 0x0c22, 0x013f: 0x0c26, // Block 0x5, offset 0x140 - 0x0143: 0x01f0, 0x0144: 0x01f4, 0x0145: 0x01f8, - 0x0146: 0x01fc, 0x0147: 0x0200, 0x0148: 0x0204, - 0x014c: 0x020c, 0x014d: 0x0210, 0x014e: 0x0214, 0x014f: 0x0218, 0x0150: 0x021c, 0x0151: 0x0220, - 0x0154: 0x0224, 0x0155: 0x0228, 0x0156: 0x022c, 0x0157: 0x0230, - 0x0158: 0x0234, 0x0159: 0x0238, 0x015a: 0x023c, 0x015b: 0x0240, 0x015c: 0x0244, 0x015d: 0x0248, - 0x015e: 0x024c, 0x015f: 0x0250, 0x0160: 0x0254, 0x0161: 0x0258, 0x0162: 0x025c, 0x0163: 0x0260, - 0x0164: 0x0264, 0x0165: 0x0268, 0x0168: 0x026c, 0x0169: 0x0270, - 0x016a: 0x0274, 0x016b: 0x0278, 0x016c: 0x027c, 0x016d: 0x0280, 0x016e: 0x0284, 0x016f: 0x0288, - 0x0170: 0x028c, 0x0171: 0x0290, 0x0172: 0x0294, 0x0173: 0x0298, 0x0174: 0x029c, 0x0175: 0x02a0, - 0x0176: 0x02a4, 0x0177: 0x02a8, 0x0178: 0x02ac, 0x0179: 0x02b0, 0x017a: 0x02b4, 0x017b: 0x02b8, - 0x017c: 0x02bc, 0x017d: 0x02c0, 0x017e: 0x02c4, + 0x0140: 0x0c2a, 0x0141: 0x0c2e, 0x0142: 0x0c32, 0x0143: 0x0c36, 0x0144: 0x0c3a, 0x0145: 0x0c3e, + 0x0146: 0x0c42, 0x0147: 0x0c46, 0x0148: 0x0c4a, 0x0149: 0x0c4e, 0x014a: 0x0c52, 0x014b: 0x0c56, + 0x014c: 0x0c5a, 0x014d: 0x0c5e, 0x014e: 0x0c62, 0x014f: 0x0c66, 0x0150: 0x0c6a, 0x0151: 0x0c6e, + 0x0152: 0x0c72, 0x0153: 0x0c76, 0x0154: 0x0c7a, 0x0155: 0x0c7e, 0x0156: 0x0c82, 0x0157: 0x0c86, + 0x0158: 0x0c8a, 0x0159: 0x0c8e, 0x015b: 0x0c96, + 0x0160: 0x0c9b, 0x0161: 0x0c9f, 0x0162: 0x0ca3, 0x0163: 0x0ca7, + 0x0164: 0x0cab, 0x0165: 0x0cb1, 0x0166: 0x0cb7, 0x0167: 0x0cbd, 0x0168: 0x0cc3, 0x0169: 0x0cc9, + 0x016a: 0x0ccf, 0x016b: 0x0cd5, 0x016c: 0x0cdb, 0x016d: 0x0ce1, 0x016e: 0x0ce7, 0x016f: 0x0ced, + 0x0170: 0x0cf3, 0x0171: 0x0cf9, 0x0172: 0x0cff, 0x0173: 0x0d05, 0x0174: 0x0d0b, 0x0175: 0x0d11, + 0x0176: 0x0d17, 0x0177: 0x0d1d, 0x0178: 0x0d23, 0x0179: 0x0d27, 0x017a: 0x0d2b, 0x017b: 0x0d2f, + 0x017c: 0x0d33, 0x017d: 0x0d37, 0x017e: 0x0d3b, 0x017f: 0x0d41, // Block 0x6, offset 0x180 - 0x01a0: 0x02ca, 0x01a1: 0x02ce, - 0x01af: 0x02d2, - 0x01b0: 0x02d6, + 0x0180: 0x0d47, 0x0181: 0x0d4d, 0x0182: 0x0d53, 0x0183: 0x0d59, 0x0184: 0x0d5f, 0x0185: 0x0d65, + 0x0186: 0x0d6b, 0x0187: 0x0d71, 0x0188: 0x0d77, 0x0189: 0x0d7b, 0x018a: 0x0d7f, 0x018b: 0x0d83, + 0x018c: 0x0d87, 0x018d: 0x0d8b, 0x018e: 0x0d8f, 0x018f: 0x0d93, 0x0190: 0x0d97, 0x0191: 0x0d9d, + 0x0192: 0x0da3, 0x0193: 0x0da9, 0x0194: 0x0daf, 0x0195: 0x0db5, 0x0196: 0x0dbb, 0x0197: 0x0dc1, + 0x0198: 0x0dc7, 0x0199: 0x0dcd, 0x019a: 0x0dd3, 0x019b: 0x0dd9, 0x019c: 0x0ddf, 0x019d: 0x0de5, + 0x019e: 0x0deb, 0x019f: 0x0df1, 0x01a0: 0x0df7, 0x01a1: 0x0dfd, 0x01a2: 0x0e03, 0x01a3: 0x0e09, + 0x01a4: 0x0e0f, 0x01a5: 0x0e13, 0x01a6: 0x0e17, 0x01a7: 0x0e1b, 0x01a8: 0x0e1f, 0x01a9: 0x0e25, + 0x01aa: 0x0e2b, 0x01ab: 0x0e31, 0x01ac: 0x0e37, 0x01ad: 0x0e3d, 0x01ae: 0x0e43, 0x01af: 0x0e49, + 0x01b0: 0x0e4f, 0x01b1: 0x0e55, 0x01b2: 0x0e5b, 0x01b3: 0x0e5f, 0x01b4: 0x0e63, 0x01b5: 0x0e67, + 0x01b6: 0x0e6b, 0x01b7: 0x0e6f, 0x01b8: 0x0e73, 0x01b9: 0x0e77, // Block 0x7, offset 0x1c0 - 0x01cd: 0x02fb, 0x01ce: 0x02ff, 0x01cf: 0x0303, 0x01d0: 0x0307, 0x01d1: 0x030b, - 0x01d2: 0x030f, 0x01d3: 0x0313, 0x01d4: 0x0317, 0x01d5: 0x031b, 0x01d6: 0x0321, 0x01d7: 0x0327, - 0x01d8: 0x032d, 0x01d9: 0x0333, 0x01da: 0x0339, 0x01db: 0x033f, 0x01dc: 0x0345, - 0x01de: 0x034b, 0x01df: 0x0351, 0x01e0: 0x0357, 0x01e1: 0x035d, 0x01e2: 0x0363, 0x01e3: 0x0368, - 0x01e6: 0x036d, 0x01e7: 0x0371, 0x01e8: 0x0375, 0x01e9: 0x0379, - 0x01ea: 0x037d, 0x01eb: 0x0381, 0x01ec: 0x0385, 0x01ed: 0x038b, 0x01ee: 0x0391, 0x01ef: 0x0396, - 0x01f0: 0x039b, 0x01f4: 0x03a8, 0x01f5: 0x03ac, - 0x01f8: 0x03b0, 0x01f9: 0x03b4, 0x01fa: 0x03b8, 0x01fb: 0x03be, - 0x01fc: 0x03c4, 0x01fd: 0x03c9, 0x01fe: 0x03ce, 0x01ff: 0x03d3, + 0x01c0: 0x0e7b, 0x01c1: 0x0e80, 0x01c2: 0x0e85, 0x01c3: 0x0e8c, 0x01c4: 0x0e93, 0x01c5: 0x0e9a, + 0x01c6: 0x0ea1, 0x01c7: 0x0ea8, 0x01c8: 0x0eaf, 0x01c9: 0x0eb4, 0x01ca: 0x0eb9, 0x01cb: 0x0ec0, + 0x01cc: 0x0ec7, 0x01cd: 0x0ece, 0x01ce: 0x0ed5, 0x01cf: 0x0edc, 0x01d0: 0x0ee3, 0x01d1: 0x0ee8, + 0x01d2: 0x0eed, 0x01d3: 0x0ef4, 0x01d4: 0x0efb, 0x01d5: 0x0f02, + 0x01d8: 0x0f09, 0x01d9: 0x0f0e, 0x01da: 0x0f13, 0x01db: 0x0f1a, 0x01dc: 0x0f21, 0x01dd: 0x0f28, + 0x01e0: 0x0f2f, 0x01e1: 0x0f34, 0x01e2: 0x0f39, 0x01e3: 0x0f40, + 0x01e4: 0x0f47, 0x01e5: 0x0f4e, 0x01e6: 0x0f55, 0x01e7: 0x0f5c, 0x01e8: 0x0f63, 0x01e9: 0x0f68, + 0x01ea: 0x0f6d, 0x01eb: 0x0f74, 0x01ec: 0x0f7b, 0x01ed: 0x0f82, 0x01ee: 0x0f89, 0x01ef: 0x0f90, + 0x01f0: 0x0f97, 0x01f1: 0x0f9c, 0x01f2: 0x0fa1, 0x01f3: 0x0fa8, 0x01f4: 0x0faf, 0x01f5: 0x0fb6, + 0x01f6: 0x0fbd, 0x01f7: 0x0fc4, 0x01f8: 0x0fcb, 0x01f9: 0x0fd0, 0x01fa: 0x0fd5, 0x01fb: 0x0fdc, + 0x01fc: 0x0fe3, 0x01fd: 0x0fea, 0x01fe: 0x0ff1, 0x01ff: 0x0ff8, // Block 0x8, offset 0x200 - 0x0200: 0x03d8, 0x0201: 0x03dc, 0x0202: 0x03e0, 0x0203: 0x03e4, 0x0204: 0x03e8, 0x0205: 0x03ec, - 0x0206: 0x03f0, 0x0207: 0x03f4, 0x0208: 0x03f8, 0x0209: 0x03fc, 0x020a: 0x0400, 0x020b: 0x0404, - 0x020c: 0x0408, 0x020d: 0x040c, 0x020e: 0x0410, 0x020f: 0x0414, 0x0210: 0x0418, 0x0211: 0x041c, - 0x0212: 0x0420, 0x0213: 0x0424, 0x0214: 0x0428, 0x0215: 0x042c, 0x0216: 0x0430, 0x0217: 0x0434, - 0x0218: 0x0438, 0x0219: 0x043c, 0x021a: 0x0440, 0x021b: 0x0444, - 0x021e: 0x0448, 0x021f: 0x044c, - 0x0226: 0x0450, 0x0227: 0x0454, 0x0228: 0x0458, 0x0229: 0x045c, - 0x022a: 0x0460, 0x022b: 0x0466, 0x022c: 0x046c, 0x022d: 0x0472, 0x022e: 0x0478, 0x022f: 0x047c, - 0x0230: 0x0480, 0x0231: 0x0486, 0x0232: 0x048c, 0x0233: 0x0490, + 0x0200: 0x0fff, 0x0201: 0x1004, 0x0202: 0x1009, 0x0203: 0x1010, 0x0204: 0x1017, 0x0205: 0x101e, + 0x0208: 0x1025, 0x0209: 0x102a, 0x020a: 0x102f, 0x020b: 0x1036, + 0x020c: 0x103d, 0x020d: 0x1044, 0x0210: 0x104b, 0x0211: 0x1050, + 0x0212: 0x1055, 0x0213: 0x105c, 0x0214: 0x1063, 0x0215: 0x106a, 0x0216: 0x1071, 0x0217: 0x1078, + 0x0219: 0x107f, 0x021b: 0x1084, 0x021d: 0x108b, + 0x021f: 0x1092, 0x0220: 0x1099, 0x0221: 0x109e, 0x0222: 0x10a3, 0x0223: 0x10aa, + 0x0224: 0x10b1, 0x0225: 0x10b8, 0x0226: 0x10bf, 0x0227: 0x10c6, 0x0228: 0x10cd, 0x0229: 0x10d2, + 0x022a: 0x10d7, 0x022b: 0x10de, 0x022c: 0x10e5, 0x022d: 0x10ec, 0x022e: 0x10f3, 0x022f: 0x10fa, + 0x0230: 0x1101, 0x0231: 0x0525, 0x0232: 0x1106, 0x0233: 0x052a, 0x0234: 0x110b, 0x0235: 0x052f, + 0x0236: 0x1110, 0x0237: 0x0534, 0x0238: 0x1115, 0x0239: 0x054a, 0x023a: 0x111a, 0x023b: 0x054f, + 0x023c: 0x111f, 0x023d: 0x0554, // Block 0x9, offset 0x240 - 0x0240: 0x04cc, 0x0241: 0x04cf, 0x0243: 0x04d2, 0x0244: 0x04d5, - 0x0274: 0x04da, - 0x027e: 0x04e1, + 0x0240: 0x1124, 0x0241: 0x112b, 0x0242: 0x1132, 0x0243: 0x113b, 0x0244: 0x1144, 0x0245: 0x114d, + 0x0246: 0x1156, 0x0247: 0x115f, 0x0248: 0x1168, 0x0249: 0x116f, 0x024a: 0x1176, 0x024b: 0x117f, + 0x024c: 0x1188, 0x024d: 0x1191, 0x024e: 0x119a, 0x024f: 0x11a3, 0x0250: 0x11ac, 0x0251: 0x11b3, + 0x0252: 0x11ba, 0x0253: 0x11c3, 0x0254: 0x11cc, 0x0255: 0x11d5, 0x0256: 0x11de, 0x0257: 0x11e7, + 0x0258: 0x11f0, 0x0259: 0x11f7, 0x025a: 0x11fe, 0x025b: 0x1207, 0x025c: 0x1210, 0x025d: 0x1219, + 0x025e: 0x1222, 0x025f: 0x122b, 0x0260: 0x1234, 0x0261: 0x123b, 0x0262: 0x1242, 0x0263: 0x124b, + 0x0264: 0x1254, 0x0265: 0x125d, 0x0266: 0x1266, 0x0267: 0x126f, 0x0268: 0x1278, 0x0269: 0x127f, + 0x026a: 0x1286, 0x026b: 0x128f, 0x026c: 0x1298, 0x026d: 0x12a1, 0x026e: 0x12aa, 0x026f: 0x12b3, + 0x0270: 0x12bc, 0x0271: 0x12c1, 0x0272: 0x12c6, 0x0273: 0x12cd, 0x0274: 0x12d2, + 0x0276: 0x12d9, 0x0277: 0x12de, 0x0278: 0x12e5, 0x0279: 0x12ea, 0x027a: 0x12ef, 0x027b: 0x04ee, + 0x027c: 0x12f4, 0x027e: 0x12fd, // Block 0xa, offset 0x280 - 0x0285: 0x04e3, - 0x0286: 0x04ee, 0x0287: 0x04f3, 0x0288: 0x04f6, 0x0289: 0x04fb, 0x028a: 0x0500, - 0x028c: 0x0505, 0x028e: 0x050a, 0x028f: 0x050f, 0x0290: 0x0514, - 0x02aa: 0x051b, 0x02ab: 0x0520, 0x02ac: 0x0525, 0x02ad: 0x052a, 0x02ae: 0x052f, 0x02af: 0x0534, - 0x02b0: 0x0539, + 0x0281: 0x1304, 0x0282: 0x130f, 0x0283: 0x1316, 0x0284: 0x131b, + 0x0286: 0x1322, 0x0287: 0x1327, 0x0288: 0x132e, 0x0289: 0x04f6, 0x028a: 0x1333, 0x028b: 0x04fb, + 0x028c: 0x1338, 0x028d: 0x133d, 0x028e: 0x1349, 0x028f: 0x1355, 0x0290: 0x1361, 0x0291: 0x1366, + 0x0292: 0x136b, 0x0293: 0x0514, 0x0296: 0x1372, 0x0297: 0x1377, + 0x0298: 0x137e, 0x0299: 0x1383, 0x029a: 0x1388, 0x029b: 0x0500, 0x029d: 0x138d, + 0x029e: 0x1399, 0x029f: 0x13a5, 0x02a0: 0x13b1, 0x02a1: 0x13b6, 0x02a2: 0x13bb, 0x02a3: 0x0539, + 0x02a4: 0x13c2, 0x02a5: 0x13c7, 0x02a6: 0x13cc, 0x02a7: 0x13d1, 0x02a8: 0x13d8, 0x02a9: 0x13dd, + 0x02aa: 0x13e2, 0x02ab: 0x050a, 0x02ac: 0x13e7, 0x02ad: 0x13ec, 0x02ae: 0x04e3, 0x02af: 0x13f7, + 0x02b2: 0x13f9, 0x02b3: 0x1400, 0x02b4: 0x1405, + 0x02b6: 0x140c, 0x02b7: 0x1411, 0x02b8: 0x1418, 0x02b9: 0x0505, 0x02ba: 0x141d, 0x02bb: 0x050f, + 0x02bc: 0x1422, 0x02bd: 0x1427, // Block 0xb, offset 0x2c0 - 0x02ca: 0x0540, 0x02cb: 0x0545, - 0x02cc: 0x054a, 0x02cd: 0x054f, 0x02ce: 0x0554, - 0x02d3: 0x0562, 0x02d4: 0x0567, + 0x02cc: 0x1b8a, 0x02ce: 0x1b91, 0x02d0: 0x1b98, + 0x02d2: 0x1b9f, 0x02d4: 0x1ba6, 0x02d6: 0x1bad, + 0x02d8: 0x1bb4, 0x02da: 0x1bbb, 0x02dc: 0x1bc2, + 0x02de: 0x1bc9, 0x02e0: 0x1bd0, 0x02e2: 0x1bd7, + 0x02e5: 0x1bde, 0x02e7: 0x1be5, 0x02e9: 0x1bec, + 0x02f0: 0x1bf3, 0x02f1: 0x1bfa, 0x02f3: 0x1c01, 0x02f4: 0x1c08, + 0x02f6: 0x1c0f, 0x02f7: 0x1c16, 0x02f9: 0x1c1d, 0x02fa: 0x1c24, + 0x02fc: 0x1c2b, 0x02fd: 0x1c32, // Block 0xc, offset 0x300 - 0x0300: 0x0584, 0x0301: 0x0589, 0x0303: 0x058e, - 0x0307: 0x0593, - 0x030c: 0x0598, 0x030d: 0x059d, 0x030e: 0x05a2, - 0x0319: 0x05a7, - 0x0339: 0x05ac, + 0x0300: 0x2fce, 0x0301: 0x2fd2, 0x0302: 0x2fd6, 0x0303: 0x2fda, 0x0304: 0x2fde, 0x0305: 0x2fe2, + 0x0306: 0x2fe6, 0x0307: 0x2fea, 0x0308: 0x2fee, 0x0309: 0x2eed, 0x030a: 0x2ff2, 0x030b: 0x2ef1, + 0x030c: 0x2ff6, 0x030d: 0x2ffa, 0x030e: 0x2ffe, 0x030f: 0x3002, 0x0310: 0x3006, 0x0311: 0x2e6d, + 0x0312: 0x2b15, 0x0313: 0x300a, 0x0314: 0x300e, 0x0315: 0x195a, 0x0316: 0x2c25, 0x0317: 0x2d71, + 0x0318: 0x3012, 0x0319: 0x3016, 0x031a: 0x2f0d, 0x031b: 0x301a, 0x031c: 0x2f11, 0x031d: 0x301e, + 0x031e: 0x3022, 0x031f: 0x3026, 0x0320: 0x2e75, 0x0321: 0x302a, 0x0322: 0x302e, 0x0323: 0x3032, + 0x0324: 0x3036, 0x0325: 0x303a, 0x0326: 0x2e79, 0x0327: 0x303e, 0x0328: 0x3042, 0x0329: 0x3046, + 0x032a: 0x304a, 0x032b: 0x304e, 0x032c: 0x3052, 0x032d: 0x2f41, 0x032e: 0x3056, 0x032f: 0x305a, + 0x0330: 0x2cb1, 0x0331: 0x305e, 0x0332: 0x2f51, 0x0333: 0x3062, 0x0334: 0x3066, 0x0335: 0x306a, + 0x0336: 0x306e, 0x0337: 0x3072, 0x0338: 0x2f65, 0x0339: 0x3076, 0x033a: 0x2e99, 0x033b: 0x307a, + 0x033c: 0x2f69, 0x033d: 0x2bd9, 0x033e: 0x307e, 0x033f: 0x2f6d, // Block 0xd, offset 0x340 - 0x0350: 0x05b1, 0x0351: 0x05b6, - 0x0353: 0x05bb, 0x0357: 0x05c0, - 0x035c: 0x05c5, 0x035d: 0x05ca, - 0x035e: 0x05cf, - 0x0376: 0x05d4, 0x0377: 0x05d9, + 0x0340: 0x3082, 0x0341: 0x2f75, 0x0342: 0x3086, 0x0343: 0x308a, 0x0344: 0x308e, 0x0345: 0x3092, + 0x0346: 0x3096, 0x0347: 0x2f7d, 0x0348: 0x2e8d, 0x0349: 0x309a, 0x034a: 0x2f81, 0x034b: 0x309e, + 0x034c: 0x2f85, 0x034d: 0x30a2, 0x034e: 0x1b76, 0x034f: 0x30a6, 0x0350: 0x30ab, 0x0351: 0x30b0, + 0x0352: 0x30b5, 0x0353: 0x30b9, 0x0354: 0x30bd, 0x0355: 0x30c1, 0x0356: 0x30c6, 0x0357: 0x30cb, + 0x0358: 0x30d0, 0x0359: 0x30d4, // Block 0xe, offset 0x380 - 0x0381: 0x05de, 0x0382: 0x05e3, - 0x0390: 0x05e8, 0x0391: 0x05ed, - 0x0392: 0x05f2, 0x0393: 0x05f7, 0x0396: 0x05fc, 0x0397: 0x0601, - 0x039a: 0x0606, 0x039b: 0x060b, 0x039c: 0x0610, 0x039d: 0x0615, - 0x039e: 0x061a, 0x039f: 0x061f, 0x03a2: 0x0624, 0x03a3: 0x0629, - 0x03a4: 0x062e, 0x03a5: 0x0633, 0x03a6: 0x0638, 0x03a7: 0x063d, - 0x03aa: 0x0642, 0x03ab: 0x0647, 0x03ac: 0x064c, 0x03ad: 0x0651, 0x03ae: 0x0656, 0x03af: 0x065b, - 0x03b0: 0x0660, 0x03b1: 0x0665, 0x03b2: 0x066a, 0x03b3: 0x066f, 0x03b4: 0x0674, 0x03b5: 0x0679, - 0x03b8: 0x067e, 0x03b9: 0x0683, + 0x0380: 0x3d23, 0x0381: 0x3d27, 0x0382: 0x3d2b, 0x0383: 0x3d2f, 0x0384: 0x3d34, 0x0385: 0x2eb5, + 0x0386: 0x3d38, 0x0387: 0x3d3c, 0x0388: 0x3d40, 0x0389: 0x3d44, 0x038a: 0x2eb9, 0x038b: 0x3d48, + 0x038c: 0x3d4c, 0x038d: 0x3d50, 0x038e: 0x2ebd, 0x038f: 0x3d55, 0x0390: 0x3d59, 0x0391: 0x3d5d, + 0x0392: 0x3d61, 0x0393: 0x3d66, 0x0394: 0x3d6a, 0x0395: 0x3c71, 0x0396: 0x3d6e, 0x0397: 0x3d73, + 0x0398: 0x3d77, 0x0399: 0x3d7b, 0x039a: 0x3d7f, 0x039b: 0x2f9a, 0x039c: 0x3d83, 0x039d: 0x1866, + 0x039e: 0x3d88, 0x039f: 0x3d8c, 0x03a0: 0x3d90, 0x03a1: 0x3d94, 0x03a2: 0x3cb9, 0x03a3: 0x3d98, + 0x03a4: 0x3d9c, 0x03a5: 0x2fae, 0x03a6: 0x2ec1, 0x03a7: 0x2ec5, 0x03a8: 0x2fb2, 0x03a9: 0x3da0, + 0x03aa: 0x3da4, 0x03ab: 0x2bf1, 0x03ac: 0x3da8, 0x03ad: 0x2ec9, 0x03ae: 0x3dac, 0x03af: 0x3db0, + 0x03b0: 0x3db4, 0x03b1: 0x3db8, 0x03b2: 0x3db8, 0x03b3: 0x3db8, 0x03b4: 0x3dbc, 0x03b5: 0x3dc1, + 0x03b6: 0x3dc5, 0x03b7: 0x3dc9, 0x03b8: 0x3dcd, 0x03b9: 0x3dd2, 0x03ba: 0x3dd6, 0x03bb: 0x3dda, + 0x03bc: 0x3dde, 0x03bd: 0x3de2, 0x03be: 0x3de6, 0x03bf: 0x3dea, // Block 0xf, offset 0x3c0 - 0x03e2: 0x068d, 0x03e3: 0x0692, - 0x03e4: 0x0697, 0x03e5: 0x069c, 0x03e6: 0x06a1, + 0x03c0: 0x3dee, 0x03c1: 0x3df2, 0x03c2: 0x3df6, 0x03c3: 0x3dfa, 0x03c4: 0x3dfe, 0x03c5: 0x3e02, + 0x03c6: 0x3e02, 0x03c7: 0x2fba, 0x03c8: 0x3e06, 0x03c9: 0x3e0a, 0x03ca: 0x3e0e, 0x03cb: 0x3e12, + 0x03cc: 0x2ed1, 0x03cd: 0x3e16, 0x03ce: 0x3e1a, 0x03cf: 0x3e1e, 0x03d0: 0x2e39, 0x03d1: 0x3e22, + 0x03d2: 0x3e26, 0x03d3: 0x3e2a, 0x03d4: 0x3e2e, 0x03d5: 0x3e32, 0x03d6: 0x3e36, 0x03d7: 0x3e3a, + 0x03d8: 0x3e3e, 0x03d9: 0x3e42, 0x03da: 0x3e47, 0x03db: 0x3e4b, 0x03dc: 0x3e4f, 0x03dd: 0x3c55, + 0x03de: 0x3e53, 0x03df: 0x3e57, 0x03e0: 0x3e5b, 0x03e1: 0x3e60, 0x03e2: 0x3e65, 0x03e3: 0x3e69, + 0x03e4: 0x3e6d, 0x03e5: 0x3e71, 0x03e6: 0x3e75, 0x03e7: 0x3e79, 0x03e8: 0x3e7d, 0x03e9: 0x3e81, + 0x03ea: 0x3e85, 0x03eb: 0x3e85, 0x03ec: 0x3e89, 0x03ed: 0x3e8e, 0x03ee: 0x3e92, 0x03ef: 0x2be1, + 0x03f0: 0x3e96, 0x03f1: 0x3e9a, 0x03f2: 0x3e9f, 0x03f3: 0x3ea3, 0x03f4: 0x3ea7, 0x03f5: 0x18ce, + 0x03f6: 0x3eab, 0x03f7: 0x3eaf, 0x03f8: 0x18d6, 0x03f9: 0x3eb3, 0x03fa: 0x3eb7, 0x03fb: 0x3ebb, + 0x03fc: 0x3ec0, 0x03fd: 0x3ec4, 0x03fe: 0x3ec9, 0x03ff: 0x3ecd, // Block 0x10, offset 0x400 - 0x0400: 0x06ba, 0x0402: 0x06bf, - 0x0413: 0x06c4, + 0x0400: 0x3ed1, 0x0401: 0x3ed5, 0x0402: 0x3ed9, 0x0403: 0x3edd, 0x0404: 0x3ee1, 0x0405: 0x3ee5, + 0x0406: 0x3ee9, 0x0407: 0x3eed, 0x0408: 0x3ef1, 0x0409: 0x3ef5, 0x040a: 0x3efa, 0x040b: 0x3efe, + 0x040c: 0x3f02, 0x040d: 0x3f06, 0x040e: 0x2b11, 0x040f: 0x3f0a, 0x0410: 0x18fe, 0x0411: 0x3f0f, + 0x0412: 0x3f0f, 0x0413: 0x3f14, 0x0414: 0x3f18, 0x0415: 0x3f18, 0x0416: 0x3f1c, 0x0417: 0x3f20, + 0x0418: 0x3f25, 0x0419: 0x3f2a, 0x041a: 0x3f2e, 0x041b: 0x3f32, 0x041c: 0x3f36, 0x041d: 0x3f3a, + 0x041e: 0x3f3e, 0x041f: 0x3f42, 0x0420: 0x3f46, 0x0421: 0x3f4a, 0x0422: 0x3f4e, 0x0423: 0x2ee5, + 0x0424: 0x3f52, 0x0425: 0x3f57, 0x0426: 0x3f5b, 0x0427: 0x3f5f, 0x0428: 0x2fea, 0x0429: 0x3f5f, + 0x042a: 0x3f63, 0x042b: 0x2eed, 0x042c: 0x3f67, 0x042d: 0x3f6b, 0x042e: 0x3f6f, 0x042f: 0x3f73, + 0x0430: 0x2ef1, 0x0431: 0x2aa5, 0x0432: 0x3f77, 0x0433: 0x3f7b, 0x0434: 0x3f7f, 0x0435: 0x3f83, + 0x0436: 0x3f87, 0x0437: 0x3f8b, 0x0438: 0x3f8f, 0x0439: 0x3f94, 0x043a: 0x3f98, 0x043b: 0x3f9c, + 0x043c: 0x3fa0, 0x043d: 0x3fa4, 0x043e: 0x3fa8, 0x043f: 0x3fad, // Block 0x11, offset 0x440 - 0x0469: 0x06c9, - 0x0471: 0x06d0, 0x0474: 0x06d7, + 0x0440: 0x3fb1, 0x0441: 0x3fb5, 0x0442: 0x3fb9, 0x0443: 0x3fbd, 0x0444: 0x3fc1, 0x0445: 0x3fc5, + 0x0446: 0x3fc9, 0x0447: 0x3fcd, 0x0448: 0x2ef5, 0x0449: 0x3fd1, 0x044a: 0x3fd5, 0x044b: 0x3fda, + 0x044c: 0x3fde, 0x044d: 0x3fe2, 0x044e: 0x3fe6, 0x044f: 0x2efd, 0x0450: 0x3fea, 0x0451: 0x3fee, + 0x0452: 0x3ff2, 0x0453: 0x3ff6, 0x0454: 0x3ffa, 0x0455: 0x3ffe, 0x0456: 0x4002, 0x0457: 0x4006, + 0x0458: 0x2b15, 0x0459: 0x300a, 0x045a: 0x400a, 0x045b: 0x400e, 0x045c: 0x4012, 0x045d: 0x4016, + 0x045e: 0x401b, 0x045f: 0x401f, 0x0460: 0x4023, 0x0461: 0x4027, 0x0462: 0x2f01, 0x0463: 0x402b, + 0x0464: 0x4030, 0x0465: 0x4034, 0x0466: 0x4038, 0x0467: 0x30b5, 0x0468: 0x403c, 0x0469: 0x4040, + 0x046a: 0x4044, 0x046b: 0x4048, 0x046c: 0x404c, 0x046d: 0x4051, 0x046e: 0x4055, 0x046f: 0x4059, + 0x0470: 0x405d, 0x0471: 0x4062, 0x0472: 0x4066, 0x0473: 0x406a, 0x0474: 0x406e, 0x0475: 0x2c25, + 0x0476: 0x4072, 0x0477: 0x4076, 0x0478: 0x407b, 0x0479: 0x4080, 0x047a: 0x4085, 0x047b: 0x4089, + 0x047c: 0x408e, 0x047d: 0x4092, 0x047e: 0x4096, 0x047f: 0x409a, // Block 0x12, offset 0x480 - 0x0498: 0x06de, 0x0499: 0x06e5, 0x049a: 0x06ec, 0x049b: 0x06f3, 0x049c: 0x06fa, 0x049d: 0x0701, - 0x049e: 0x0708, 0x049f: 0x070f, + 0x0480: 0x409e, 0x0481: 0x2f05, 0x0482: 0x2d71, 0x0483: 0x40a2, 0x0484: 0x40a6, 0x0485: 0x40aa, + 0x0486: 0x40ae, 0x0487: 0x40b3, 0x0488: 0x40b7, 0x0489: 0x40bb, 0x048a: 0x40bf, 0x048b: 0x3016, + 0x048c: 0x40c3, 0x048d: 0x40c7, 0x048e: 0x40cc, 0x048f: 0x40d0, 0x0490: 0x40d4, 0x0491: 0x40d9, + 0x0492: 0x40de, 0x0493: 0x40e2, 0x0494: 0x301a, 0x0495: 0x40e6, 0x0496: 0x40ea, 0x0497: 0x40ee, + 0x0498: 0x40f2, 0x0499: 0x40f6, 0x049a: 0x40fa, 0x049b: 0x40fe, 0x049c: 0x4103, 0x049d: 0x4107, + 0x049e: 0x410c, 0x049f: 0x4110, 0x04a0: 0x4115, 0x04a1: 0x3022, 0x04a2: 0x4119, 0x04a3: 0x411d, + 0x04a4: 0x4122, 0x04a5: 0x4126, 0x04a6: 0x412a, 0x04a7: 0x412f, 0x04a8: 0x4134, 0x04a9: 0x4138, + 0x04aa: 0x413c, 0x04ab: 0x4140, 0x04ac: 0x4144, 0x04ad: 0x4144, 0x04ae: 0x4148, 0x04af: 0x414c, + 0x04b0: 0x302a, 0x04b1: 0x4150, 0x04b2: 0x4154, 0x04b3: 0x4158, 0x04b4: 0x415c, 0x04b5: 0x4160, + 0x04b6: 0x4165, 0x04b7: 0x4169, 0x04b8: 0x2bed, 0x04b9: 0x416e, 0x04ba: 0x4173, 0x04bb: 0x4177, + 0x04bc: 0x417c, 0x04bd: 0x4181, 0x04be: 0x4186, 0x04bf: 0x418a, // Block 0x13, offset 0x4c0 - 0x04cb: 0x0716, - 0x04cc: 0x071d, - 0x04dc: 0x0724, 0x04dd: 0x072b, - 0x04df: 0x0732, + 0x04c0: 0x3042, 0x04c1: 0x418e, 0x04c2: 0x4193, 0x04c3: 0x4198, 0x04c4: 0x419d, 0x04c5: 0x41a2, + 0x04c6: 0x41a6, 0x04c7: 0x41a6, 0x04c8: 0x3046, 0x04c9: 0x30bd, 0x04ca: 0x41aa, 0x04cb: 0x41ae, + 0x04cc: 0x41b2, 0x04cd: 0x41b6, 0x04ce: 0x41bb, 0x04cf: 0x2b59, 0x04d0: 0x304e, 0x04d1: 0x41bf, + 0x04d2: 0x41c3, 0x04d3: 0x2f2d, 0x04d4: 0x41c8, 0x04d5: 0x41cd, 0x04d6: 0x2e89, 0x04d7: 0x41d2, + 0x04d8: 0x41d6, 0x04d9: 0x2f39, 0x04da: 0x41da, 0x04db: 0x41de, 0x04dc: 0x41e2, 0x04dd: 0x41e7, + 0x04de: 0x41e7, 0x04df: 0x41ec, 0x04e0: 0x41f0, 0x04e1: 0x41f4, 0x04e2: 0x41f9, 0x04e3: 0x41fd, + 0x04e4: 0x4201, 0x04e5: 0x4205, 0x04e6: 0x420a, 0x04e7: 0x420e, 0x04e8: 0x4212, 0x04e9: 0x4216, + 0x04ea: 0x421a, 0x04eb: 0x421e, 0x04ec: 0x4223, 0x04ed: 0x4227, 0x04ee: 0x422b, 0x04ef: 0x422f, + 0x04f0: 0x4233, 0x04f1: 0x4237, 0x04f2: 0x423b, 0x04f3: 0x4240, 0x04f4: 0x4245, 0x04f5: 0x4249, + 0x04f6: 0x424e, 0x04f7: 0x4252, 0x04f8: 0x4257, 0x04f9: 0x425b, 0x04fa: 0x2f51, 0x04fb: 0x425f, + 0x04fc: 0x4264, 0x04fd: 0x4269, 0x04fe: 0x426d, 0x04ff: 0x4272, // Block 0x14, offset 0x500 - 0x0533: 0x0739, - 0x0536: 0x0740, + 0x0500: 0x4276, 0x0501: 0x427b, 0x0502: 0x427f, 0x0503: 0x4283, 0x0504: 0x4287, 0x0505: 0x428b, + 0x0506: 0x428f, 0x0507: 0x4293, 0x0508: 0x4298, 0x0509: 0x429d, 0x050a: 0x42a2, 0x050b: 0x3f14, + 0x050c: 0x42a7, 0x050d: 0x42ab, 0x050e: 0x42af, 0x050f: 0x42b3, 0x0510: 0x42b7, 0x0511: 0x42bb, + 0x0512: 0x42bf, 0x0513: 0x42c3, 0x0514: 0x42c7, 0x0515: 0x42cb, 0x0516: 0x42cf, 0x0517: 0x42d3, + 0x0518: 0x2c31, 0x0519: 0x42d8, 0x051a: 0x42dc, 0x051b: 0x42e0, 0x051c: 0x42e4, 0x051d: 0x42e8, + 0x051e: 0x42ec, 0x051f: 0x2f5d, 0x0520: 0x42f0, 0x0521: 0x42f4, 0x0522: 0x42f8, 0x0523: 0x42fc, + 0x0524: 0x4300, 0x0525: 0x4305, 0x0526: 0x430a, 0x0527: 0x430f, 0x0528: 0x4313, 0x0529: 0x4317, + 0x052a: 0x431b, 0x052b: 0x431f, 0x052c: 0x4324, 0x052d: 0x4328, 0x052e: 0x432d, 0x052f: 0x4331, + 0x0530: 0x4335, 0x0531: 0x433a, 0x0532: 0x433f, 0x0533: 0x4343, 0x0534: 0x2b45, 0x0535: 0x4347, + 0x0536: 0x434b, 0x0537: 0x434f, 0x0538: 0x4353, 0x0539: 0x4357, 0x053a: 0x435b, 0x053b: 0x306a, + 0x053c: 0x435f, 0x053d: 0x4363, 0x053e: 0x4367, 0x053f: 0x436b, // Block 0x15, offset 0x540 - 0x0559: 0x0747, 0x055a: 0x074e, 0x055b: 0x0755, - 0x055e: 0x075c, - // Block 0x16, offset 0x580 - 0x0588: 0x0763, 0x058b: 0x076a, - 0x058c: 0x0771, - 0x059c: 0x0778, 0x059d: 0x077f, - // Block 0x17, offset 0x5c0 - 0x05d4: 0x0786, - // Block 0x18, offset 0x600 - 0x060a: 0x078d, 0x060b: 0x0794, - 0x060c: 0x079b, - // Block 0x19, offset 0x640 - 0x0648: 0x07a2, - // Block 0x1a, offset 0x680 - 0x0680: 0x07a9, - 0x0687: 0x07b0, 0x0688: 0x07b7, 0x068a: 0x07be, 0x068b: 0x07c5, - // Block 0x1b, offset 0x6c0 - 0x06ca: 0x07cf, 0x06cb: 0x07d6, - 0x06cc: 0x07dd, - // Block 0x1c, offset 0x700 - 0x071a: 0x07e4, 0x071c: 0x07eb, 0x071d: 0x07f2, - 0x071e: 0x07fc, - // Block 0x1d, offset 0x740 - 0x0743: 0x0823, - 0x074d: 0x082a, - 0x0752: 0x0831, 0x0757: 0x0838, - 0x075c: 0x083f, - 0x0769: 0x0846, - 0x0773: 0x084d, 0x0775: 0x0854, - 0x0776: 0x085b, 0x0778: 0x086c, - // Block 0x1e, offset 0x780 - 0x0781: 0x087d, - 0x0793: 0x0884, - 0x079d: 0x088b, - 0x07a2: 0x0892, - 0x07a7: 0x0899, - 0x07ac: 0x08a0, - 0x07b9: 0x08a7, - // Block 0x1f, offset 0x7c0 - 0x07e6: 0x08ae, - // Block 0x20, offset 0x800 - 0x0806: 0x08b9, 0x0808: 0x08c0, 0x080a: 0x08c7, - 0x080c: 0x08ce, 0x080e: 0x08d5, - 0x0812: 0x08dc, - 0x083b: 0x08e3, - 0x083d: 0x08ea, - // Block 0x21, offset 0x840 - 0x0840: 0x08f1, 0x0841: 0x08f8, 0x0843: 0x08ff, - // Block 0x22, offset 0x880 - 0x0880: 0x09ea, 0x0881: 0x09ee, 0x0882: 0x09f2, 0x0883: 0x09f6, 0x0884: 0x09fa, 0x0885: 0x09fe, - 0x0886: 0x0a02, 0x0887: 0x0a06, 0x0888: 0x0a0a, 0x0889: 0x0a10, 0x088a: 0x0a16, 0x088b: 0x0a1a, - 0x088c: 0x0a1e, 0x088d: 0x0a22, 0x088e: 0x0a26, 0x088f: 0x0a2a, 0x0890: 0x0a2e, 0x0891: 0x0a32, - 0x0892: 0x0a36, 0x0893: 0x0a3a, 0x0894: 0x0a3e, 0x0895: 0x0a44, 0x0896: 0x0a4a, 0x0897: 0x0a50, - 0x0898: 0x0a56, 0x0899: 0x0a5a, 0x089a: 0x0a5e, 0x089b: 0x0a62, 0x089c: 0x0a66, 0x089d: 0x0a6c, - 0x089e: 0x0a72, 0x089f: 0x0a76, 0x08a0: 0x0a7a, 0x08a1: 0x0a7e, 0x08a2: 0x0a82, 0x08a3: 0x0a86, - 0x08a4: 0x0a8a, 0x08a5: 0x0a8e, 0x08a6: 0x0a92, 0x08a7: 0x0a96, 0x08a8: 0x0a9a, 0x08a9: 0x0a9e, - 0x08aa: 0x0aa2, 0x08ab: 0x0aa6, 0x08ac: 0x0aaa, 0x08ad: 0x0aae, 0x08ae: 0x0ab2, 0x08af: 0x0ab8, - 0x08b0: 0x0abe, 0x08b1: 0x0ac2, 0x08b2: 0x0ac6, 0x08b3: 0x0aca, 0x08b4: 0x0ace, 0x08b5: 0x0ad2, - 0x08b6: 0x0ad6, 0x08b7: 0x0ada, 0x08b8: 0x0ade, 0x08b9: 0x0ae4, 0x08ba: 0x0aea, 0x08bb: 0x0aee, - 0x08bc: 0x0af2, 0x08bd: 0x0af6, 0x08be: 0x0afa, 0x08bf: 0x0afe, - // Block 0x23, offset 0x8c0 - 0x08c0: 0x0b02, 0x08c1: 0x0b06, 0x08c2: 0x0b0a, 0x08c3: 0x0b0e, 0x08c4: 0x0b12, 0x08c5: 0x0b16, - 0x08c6: 0x0b1a, 0x08c7: 0x0b1e, 0x08c8: 0x0b22, 0x08c9: 0x0b26, 0x08ca: 0x0b2a, 0x08cb: 0x0b2e, - 0x08cc: 0x0b32, 0x08cd: 0x0b38, 0x08ce: 0x0b3e, 0x08cf: 0x0b44, 0x08d0: 0x0b4a, 0x08d1: 0x0b50, - 0x08d2: 0x0b56, 0x08d3: 0x0b5c, 0x08d4: 0x0b62, 0x08d5: 0x0b66, 0x08d6: 0x0b6a, 0x08d7: 0x0b6e, - 0x08d8: 0x0b72, 0x08d9: 0x0b76, 0x08da: 0x0b7a, 0x08db: 0x0b7e, 0x08dc: 0x0b82, 0x08dd: 0x0b88, - 0x08de: 0x0b8e, 0x08df: 0x0b92, 0x08e0: 0x0b96, 0x08e1: 0x0b9a, 0x08e2: 0x0b9e, 0x08e3: 0x0ba2, - 0x08e4: 0x0ba6, 0x08e5: 0x0bac, 0x08e6: 0x0bb2, 0x08e7: 0x0bb8, 0x08e8: 0x0bbe, 0x08e9: 0x0bc4, - 0x08ea: 0x0bca, 0x08eb: 0x0bce, 0x08ec: 0x0bd2, 0x08ed: 0x0bd6, 0x08ee: 0x0bda, 0x08ef: 0x0bde, - 0x08f0: 0x0be2, 0x08f1: 0x0be6, 0x08f2: 0x0bea, 0x08f3: 0x0bee, 0x08f4: 0x0bf2, 0x08f5: 0x0bf6, - 0x08f6: 0x0bfa, 0x08f7: 0x0bfe, 0x08f8: 0x0c02, 0x08f9: 0x0c08, 0x08fa: 0x0c0e, 0x08fb: 0x0c14, - 0x08fc: 0x0c1a, 0x08fd: 0x0c1e, 0x08fe: 0x0c22, 0x08ff: 0x0c26, - // Block 0x24, offset 0x900 - 0x0900: 0x0c2a, 0x0901: 0x0c2e, 0x0902: 0x0c32, 0x0903: 0x0c36, 0x0904: 0x0c3a, 0x0905: 0x0c3e, - 0x0906: 0x0c42, 0x0907: 0x0c46, 0x0908: 0x0c4a, 0x0909: 0x0c4e, 0x090a: 0x0c52, 0x090b: 0x0c56, - 0x090c: 0x0c5a, 0x090d: 0x0c5e, 0x090e: 0x0c62, 0x090f: 0x0c66, 0x0910: 0x0c6a, 0x0911: 0x0c6e, - 0x0912: 0x0c72, 0x0913: 0x0c76, 0x0914: 0x0c7a, 0x0915: 0x0c7e, 0x0916: 0x0c82, 0x0917: 0x0c86, - 0x0918: 0x0c8a, 0x0919: 0x0c8e, 0x091b: 0x0c96, - 0x0920: 0x0c9b, 0x0921: 0x0c9f, 0x0922: 0x0ca3, 0x0923: 0x0ca7, - 0x0924: 0x0cab, 0x0925: 0x0cb1, 0x0926: 0x0cb7, 0x0927: 0x0cbd, 0x0928: 0x0cc3, 0x0929: 0x0cc9, - 0x092a: 0x0ccf, 0x092b: 0x0cd5, 0x092c: 0x0cdb, 0x092d: 0x0ce1, 0x092e: 0x0ce7, 0x092f: 0x0ced, - 0x0930: 0x0cf3, 0x0931: 0x0cf9, 0x0932: 0x0cff, 0x0933: 0x0d05, 0x0934: 0x0d0b, 0x0935: 0x0d11, - 0x0936: 0x0d17, 0x0937: 0x0d1d, 0x0938: 0x0d23, 0x0939: 0x0d27, 0x093a: 0x0d2b, 0x093b: 0x0d2f, - 0x093c: 0x0d33, 0x093d: 0x0d37, 0x093e: 0x0d3b, 0x093f: 0x0d41, - // Block 0x25, offset 0x940 - 0x0940: 0x0d47, 0x0941: 0x0d4d, 0x0942: 0x0d53, 0x0943: 0x0d59, 0x0944: 0x0d5f, 0x0945: 0x0d65, - 0x0946: 0x0d6b, 0x0947: 0x0d71, 0x0948: 0x0d77, 0x0949: 0x0d7b, 0x094a: 0x0d7f, 0x094b: 0x0d83, - 0x094c: 0x0d87, 0x094d: 0x0d8b, 0x094e: 0x0d8f, 0x094f: 0x0d93, 0x0950: 0x0d97, 0x0951: 0x0d9d, - 0x0952: 0x0da3, 0x0953: 0x0da9, 0x0954: 0x0daf, 0x0955: 0x0db5, 0x0956: 0x0dbb, 0x0957: 0x0dc1, - 0x0958: 0x0dc7, 0x0959: 0x0dcd, 0x095a: 0x0dd3, 0x095b: 0x0dd9, 0x095c: 0x0ddf, 0x095d: 0x0de5, - 0x095e: 0x0deb, 0x095f: 0x0df1, 0x0960: 0x0df7, 0x0961: 0x0dfd, 0x0962: 0x0e03, 0x0963: 0x0e09, - 0x0964: 0x0e0f, 0x0965: 0x0e13, 0x0966: 0x0e17, 0x0967: 0x0e1b, 0x0968: 0x0e1f, 0x0969: 0x0e25, - 0x096a: 0x0e2b, 0x096b: 0x0e31, 0x096c: 0x0e37, 0x096d: 0x0e3d, 0x096e: 0x0e43, 0x096f: 0x0e49, - 0x0970: 0x0e4f, 0x0971: 0x0e55, 0x0972: 0x0e5b, 0x0973: 0x0e5f, 0x0974: 0x0e63, 0x0975: 0x0e67, - 0x0976: 0x0e6b, 0x0977: 0x0e6f, 0x0978: 0x0e73, 0x0979: 0x0e77, - // Block 0x26, offset 0x980 - 0x0980: 0x0e7b, 0x0981: 0x0e80, 0x0982: 0x0e85, 0x0983: 0x0e8c, 0x0984: 0x0e93, 0x0985: 0x0e9a, - 0x0986: 0x0ea1, 0x0987: 0x0ea8, 0x0988: 0x0eaf, 0x0989: 0x0eb4, 0x098a: 0x0eb9, 0x098b: 0x0ec0, - 0x098c: 0x0ec7, 0x098d: 0x0ece, 0x098e: 0x0ed5, 0x098f: 0x0edc, 0x0990: 0x0ee3, 0x0991: 0x0ee8, - 0x0992: 0x0eed, 0x0993: 0x0ef4, 0x0994: 0x0efb, 0x0995: 0x0f02, - 0x0998: 0x0f09, 0x0999: 0x0f0e, 0x099a: 0x0f13, 0x099b: 0x0f1a, 0x099c: 0x0f21, 0x099d: 0x0f28, - 0x09a0: 0x0f2f, 0x09a1: 0x0f34, 0x09a2: 0x0f39, 0x09a3: 0x0f40, - 0x09a4: 0x0f47, 0x09a5: 0x0f4e, 0x09a6: 0x0f55, 0x09a7: 0x0f5c, 0x09a8: 0x0f63, 0x09a9: 0x0f68, - 0x09aa: 0x0f6d, 0x09ab: 0x0f74, 0x09ac: 0x0f7b, 0x09ad: 0x0f82, 0x09ae: 0x0f89, 0x09af: 0x0f90, - 0x09b0: 0x0f97, 0x09b1: 0x0f9c, 0x09b2: 0x0fa1, 0x09b3: 0x0fa8, 0x09b4: 0x0faf, 0x09b5: 0x0fb6, - 0x09b6: 0x0fbd, 0x09b7: 0x0fc4, 0x09b8: 0x0fcb, 0x09b9: 0x0fd0, 0x09ba: 0x0fd5, 0x09bb: 0x0fdc, - 0x09bc: 0x0fe3, 0x09bd: 0x0fea, 0x09be: 0x0ff1, 0x09bf: 0x0ff8, - // Block 0x27, offset 0x9c0 - 0x09c0: 0x0fff, 0x09c1: 0x1004, 0x09c2: 0x1009, 0x09c3: 0x1010, 0x09c4: 0x1017, 0x09c5: 0x101e, - 0x09c8: 0x1025, 0x09c9: 0x102a, 0x09ca: 0x102f, 0x09cb: 0x1036, - 0x09cc: 0x103d, 0x09cd: 0x1044, 0x09d0: 0x104b, 0x09d1: 0x1050, - 0x09d2: 0x1055, 0x09d3: 0x105c, 0x09d4: 0x1063, 0x09d5: 0x106a, 0x09d6: 0x1071, 0x09d7: 0x1078, - 0x09d9: 0x107f, 0x09db: 0x1084, 0x09dd: 0x108b, - 0x09df: 0x1092, 0x09e0: 0x1099, 0x09e1: 0x109e, 0x09e2: 0x10a3, 0x09e3: 0x10aa, - 0x09e4: 0x10b1, 0x09e5: 0x10b8, 0x09e6: 0x10bf, 0x09e7: 0x10c6, 0x09e8: 0x10cd, 0x09e9: 0x10d2, - 0x09ea: 0x10d7, 0x09eb: 0x10de, 0x09ec: 0x10e5, 0x09ed: 0x10ec, 0x09ee: 0x10f3, 0x09ef: 0x10fa, - 0x09f0: 0x1101, 0x09f1: 0x0525, 0x09f2: 0x1106, 0x09f3: 0x052a, 0x09f4: 0x110b, 0x09f5: 0x052f, - 0x09f6: 0x1110, 0x09f7: 0x0534, 0x09f8: 0x1115, 0x09f9: 0x054a, 0x09fa: 0x111a, 0x09fb: 0x054f, - 0x09fc: 0x111f, 0x09fd: 0x0554, - // Block 0x28, offset 0xa00 - 0x0a00: 0x1124, 0x0a01: 0x112b, 0x0a02: 0x1132, 0x0a03: 0x113b, 0x0a04: 0x1144, 0x0a05: 0x114d, - 0x0a06: 0x1156, 0x0a07: 0x115f, 0x0a08: 0x1168, 0x0a09: 0x116f, 0x0a0a: 0x1176, 0x0a0b: 0x117f, - 0x0a0c: 0x1188, 0x0a0d: 0x1191, 0x0a0e: 0x119a, 0x0a0f: 0x11a3, 0x0a10: 0x11ac, 0x0a11: 0x11b3, - 0x0a12: 0x11ba, 0x0a13: 0x11c3, 0x0a14: 0x11cc, 0x0a15: 0x11d5, 0x0a16: 0x11de, 0x0a17: 0x11e7, - 0x0a18: 0x11f0, 0x0a19: 0x11f7, 0x0a1a: 0x11fe, 0x0a1b: 0x1207, 0x0a1c: 0x1210, 0x0a1d: 0x1219, - 0x0a1e: 0x1222, 0x0a1f: 0x122b, 0x0a20: 0x1234, 0x0a21: 0x123b, 0x0a22: 0x1242, 0x0a23: 0x124b, - 0x0a24: 0x1254, 0x0a25: 0x125d, 0x0a26: 0x1266, 0x0a27: 0x126f, 0x0a28: 0x1278, 0x0a29: 0x127f, - 0x0a2a: 0x1286, 0x0a2b: 0x128f, 0x0a2c: 0x1298, 0x0a2d: 0x12a1, 0x0a2e: 0x12aa, 0x0a2f: 0x12b3, - 0x0a30: 0x12bc, 0x0a31: 0x12c1, 0x0a32: 0x12c6, 0x0a33: 0x12cd, 0x0a34: 0x12d2, - 0x0a36: 0x12d9, 0x0a37: 0x12de, 0x0a38: 0x12e5, 0x0a39: 0x12ea, 0x0a3a: 0x12ef, 0x0a3b: 0x04ee, - 0x0a3c: 0x12f4, 0x0a3e: 0x12fd, - // Block 0x29, offset 0xa40 - 0x0a41: 0x1304, 0x0a42: 0x130f, 0x0a43: 0x1316, 0x0a44: 0x131b, - 0x0a46: 0x1322, 0x0a47: 0x1327, 0x0a48: 0x132e, 0x0a49: 0x04f6, 0x0a4a: 0x1333, 0x0a4b: 0x04fb, - 0x0a4c: 0x1338, 0x0a4d: 0x133d, 0x0a4e: 0x1349, 0x0a4f: 0x1355, 0x0a50: 0x1361, 0x0a51: 0x1366, - 0x0a52: 0x136b, 0x0a53: 0x0514, 0x0a56: 0x1372, 0x0a57: 0x1377, - 0x0a58: 0x137e, 0x0a59: 0x1383, 0x0a5a: 0x1388, 0x0a5b: 0x0500, 0x0a5d: 0x138d, - 0x0a5e: 0x1399, 0x0a5f: 0x13a5, 0x0a60: 0x13b1, 0x0a61: 0x13b6, 0x0a62: 0x13bb, 0x0a63: 0x0539, - 0x0a64: 0x13c2, 0x0a65: 0x13c7, 0x0a66: 0x13cc, 0x0a67: 0x13d1, 0x0a68: 0x13d8, 0x0a69: 0x13dd, - 0x0a6a: 0x13e2, 0x0a6b: 0x050a, 0x0a6c: 0x13e7, 0x0a6d: 0x13ec, 0x0a6e: 0x04e3, 0x0a6f: 0x13f7, - 0x0a72: 0x13f9, 0x0a73: 0x1400, 0x0a74: 0x1405, - 0x0a76: 0x140c, 0x0a77: 0x1411, 0x0a78: 0x1418, 0x0a79: 0x0505, 0x0a7a: 0x141d, 0x0a7b: 0x050f, - 0x0a7c: 0x1422, 0x0a7d: 0x1427, - // Block 0x2a, offset 0xa80 - 0x0a80: 0x142e, 0x0a81: 0x1432, - // Block 0x2b, offset 0xac0 - 0x0ae6: 0x14d6, - 0x0aea: 0x091c, 0x0aeb: 0x0046, - // Block 0x2c, offset 0xb00 - 0x0b1a: 0x159f, 0x0b1b: 0x15a5, - 0x0b2e: 0x15ab, - // Block 0x2d, offset 0xb40 - 0x0b4d: 0x15b1, 0x0b4e: 0x15b7, 0x0b4f: 0x15bd, - // Block 0x2e, offset 0xb80 - 0x0b84: 0x15c3, - 0x0b89: 0x15c9, - 0x0b8c: 0x15cf, - 0x0ba4: 0x15d5, 0x0ba6: 0x15db, - // Block 0x2f, offset 0xbc0 - 0x0bc1: 0x1603, 0x0bc4: 0x1609, - 0x0bc7: 0x160f, 0x0bc9: 0x1615, - 0x0be0: 0x161b, 0x0be2: 0x161f, - 0x0bed: 0x1625, 0x0bee: 0x162b, 0x0bef: 0x162f, - 0x0bf0: 0x1633, 0x0bf1: 0x1639, 0x0bf4: 0x163f, 0x0bf5: 0x1645, - 0x0bf8: 0x164b, 0x0bf9: 0x1651, - // Block 0x30, offset 0xc00 - 0x0c00: 0x1657, 0x0c01: 0x165d, 0x0c04: 0x1663, 0x0c05: 0x1669, - 0x0c08: 0x166f, 0x0c09: 0x1675, - 0x0c2c: 0x167b, 0x0c2d: 0x1681, 0x0c2e: 0x1687, 0x0c2f: 0x168d, - // Block 0x31, offset 0xc40 - 0x0c60: 0x1693, 0x0c61: 0x1699, 0x0c62: 0x169f, 0x0c63: 0x16a5, - 0x0c6a: 0x16ab, 0x0c6b: 0x16b1, 0x0c6c: 0x16b7, 0x0c6d: 0x16bd, - // Block 0x32, offset 0xc80 - 0x0ca9: 0x16c3, - 0x0caa: 0x16c7, - // Block 0x33, offset 0xcc0 - 0x0cdc: 0x1814, - // Block 0x34, offset 0xd00 - 0x0d0c: 0x1b8a, 0x0d0e: 0x1b91, 0x0d10: 0x1b98, - 0x0d12: 0x1b9f, 0x0d14: 0x1ba6, 0x0d16: 0x1bad, - 0x0d18: 0x1bb4, 0x0d1a: 0x1bbb, 0x0d1c: 0x1bc2, - 0x0d1e: 0x1bc9, 0x0d20: 0x1bd0, 0x0d22: 0x1bd7, - 0x0d25: 0x1bde, 0x0d27: 0x1be5, 0x0d29: 0x1bec, - 0x0d30: 0x1bf3, 0x0d31: 0x1bfa, 0x0d33: 0x1c01, 0x0d34: 0x1c08, - 0x0d36: 0x1c0f, 0x0d37: 0x1c16, 0x0d39: 0x1c1d, 0x0d3a: 0x1c24, - 0x0d3c: 0x1c2b, 0x0d3d: 0x1c32, - // Block 0x35, offset 0xd40 - 0x0d54: 0x1c39, - 0x0d5e: 0x1c4a, - 0x0d6c: 0x1c58, 0x0d6e: 0x1c5f, - 0x0d70: 0x1c66, 0x0d72: 0x1c6d, 0x0d74: 0x1c74, - 0x0d76: 0x1c7b, 0x0d78: 0x1c82, 0x0d7a: 0x1c89, - 0x0d7c: 0x1c90, 0x0d7e: 0x1c97, - // Block 0x36, offset 0xd80 - 0x0d80: 0x1c9e, 0x0d82: 0x1ca5, 0x0d85: 0x1cac, - 0x0d87: 0x1cb3, 0x0d89: 0x1cba, - 0x0d90: 0x1cc1, 0x0d91: 0x1cc8, - 0x0d93: 0x1ccf, 0x0d94: 0x1cd6, 0x0d96: 0x1cdd, 0x0d97: 0x1ce4, - 0x0d99: 0x1ceb, 0x0d9a: 0x1cf2, 0x0d9c: 0x1cf9, 0x0d9d: 0x1d00, - 0x0db4: 0x1d07, - 0x0db7: 0x1d0e, 0x0db8: 0x1d15, 0x0db9: 0x1d1c, 0x0dba: 0x1d23, - 0x0dbe: 0x1d2a, - // Block 0x37, offset 0xdc0 - 0x0dc0: 0x2a81, 0x0dc1: 0x2a85, 0x0dc2: 0x1a9e, 0x0dc3: 0x2a89, 0x0dc4: 0x2a8d, 0x0dc5: 0x2a91, - 0x0dc6: 0x2a95, 0x0dc7: 0x1b76, 0x0dc8: 0x1b76, 0x0dc9: 0x2a99, 0x0dca: 0x1abe, 0x0dcb: 0x2a9d, - 0x0dcc: 0x2aa1, 0x0dcd: 0x2aa5, 0x0dce: 0x2aa9, 0x0dcf: 0x2aad, 0x0dd0: 0x2ab1, 0x0dd1: 0x2ab5, - 0x0dd2: 0x2ab9, 0x0dd3: 0x2abd, 0x0dd4: 0x2ac1, 0x0dd5: 0x2ac5, 0x0dd6: 0x2ac9, 0x0dd7: 0x2acd, - 0x0dd8: 0x2ad1, 0x0dd9: 0x2ad5, 0x0dda: 0x2ad9, 0x0ddb: 0x2add, 0x0ddc: 0x2ae1, 0x0ddd: 0x2ae5, - 0x0dde: 0x2ae9, 0x0ddf: 0x2aed, 0x0de0: 0x2af1, 0x0de1: 0x2af5, 0x0de2: 0x2af9, 0x0de3: 0x2afd, - 0x0de4: 0x2b01, 0x0de5: 0x2b05, 0x0de6: 0x2b09, 0x0de7: 0x2b0d, 0x0de8: 0x2b11, 0x0de9: 0x2b15, - 0x0dea: 0x2b19, 0x0deb: 0x2b1d, 0x0dec: 0x2b21, 0x0ded: 0x2b25, 0x0dee: 0x2b29, 0x0def: 0x2b2d, - 0x0df0: 0x2b31, 0x0df1: 0x2b35, 0x0df2: 0x2b39, 0x0df3: 0x2b3d, 0x0df4: 0x1a16, 0x0df5: 0x2b41, - 0x0df6: 0x2b45, 0x0df7: 0x2b49, 0x0df8: 0x2b4d, 0x0df9: 0x2b51, 0x0dfa: 0x2b55, 0x0dfb: 0x2b59, - 0x0dfc: 0x2b5d, 0x0dfd: 0x2b61, 0x0dfe: 0x2b65, 0x0dff: 0x2b69, - // Block 0x38, offset 0xe00 - 0x0e00: 0x1b3a, 0x0e01: 0x2b6d, 0x0e02: 0x2b71, 0x0e03: 0x2b75, 0x0e04: 0x2b79, 0x0e05: 0x2b7d, - 0x0e06: 0x2b81, 0x0e07: 0x2b85, 0x0e08: 0x2b89, 0x0e09: 0x2b8d, 0x0e0a: 0x2b91, 0x0e0b: 0x2b95, - 0x0e0c: 0x2b99, 0x0e0d: 0x2b9d, 0x0e0e: 0x2ba1, 0x0e0f: 0x2ba5, 0x0e10: 0x2ba9, 0x0e11: 0x2bad, - 0x0e12: 0x2bb1, 0x0e13: 0x2bb5, 0x0e14: 0x2bb9, 0x0e15: 0x2bbd, 0x0e16: 0x2bc1, 0x0e17: 0x2bc5, - 0x0e18: 0x2bc9, 0x0e19: 0x2bcd, 0x0e1a: 0x2bd1, 0x0e1b: 0x2bd5, 0x0e1c: 0x2ac1, 0x0e1d: 0x2bd9, - 0x0e1e: 0x2bdd, 0x0e1f: 0x2be1, 0x0e20: 0x2be5, 0x0e21: 0x2be9, 0x0e22: 0x2bed, 0x0e23: 0x2bf1, - 0x0e24: 0x2bf5, 0x0e25: 0x2bf9, 0x0e26: 0x2bfd, 0x0e27: 0x2c01, 0x0e28: 0x2c05, 0x0e29: 0x2c09, - 0x0e2a: 0x2c0d, 0x0e2b: 0x2c11, 0x0e2c: 0x2c15, 0x0e2d: 0x2c19, 0x0e2e: 0x2c1d, 0x0e2f: 0x2c21, - 0x0e30: 0x2c25, 0x0e31: 0x1aa6, 0x0e32: 0x2c29, 0x0e33: 0x2c2d, 0x0e34: 0x2c31, 0x0e35: 0x2c35, - 0x0e36: 0x2c39, 0x0e37: 0x2c3d, 0x0e38: 0x2c41, 0x0e39: 0x2c45, 0x0e3a: 0x2c49, 0x0e3b: 0x2c4d, - 0x0e3c: 0x2c51, 0x0e3d: 0x2c55, 0x0e3e: 0x2c59, 0x0e3f: 0x2c5d, - // Block 0x39, offset 0xe40 - 0x0e40: 0x2c61, 0x0e41: 0x18ba, 0x0e42: 0x2c65, 0x0e43: 0x2c69, 0x0e44: 0x2c6d, 0x0e45: 0x2c71, - 0x0e46: 0x2c75, 0x0e47: 0x2c79, 0x0e48: 0x2c7d, 0x0e49: 0x2c81, 0x0e4a: 0x186e, 0x0e4b: 0x2c85, - 0x0e4c: 0x2c89, 0x0e4d: 0x2c8d, 0x0e4e: 0x2c91, 0x0e4f: 0x2c95, 0x0e50: 0x2c99, 0x0e51: 0x2c9d, - 0x0e52: 0x2ca1, 0x0e53: 0x2ca5, 0x0e54: 0x2ca9, 0x0e55: 0x2cad, 0x0e56: 0x2cb1, 0x0e57: 0x2cb5, - 0x0e58: 0x2cb9, 0x0e59: 0x2cbd, 0x0e5a: 0x2cc1, 0x0e5b: 0x2cc5, 0x0e5c: 0x2cc9, 0x0e5d: 0x2ccd, - 0x0e5e: 0x2cd1, 0x0e5f: 0x2cd5, 0x0e60: 0x2cd9, 0x0e61: 0x2c21, 0x0e62: 0x2cdd, 0x0e63: 0x2ce1, - 0x0e64: 0x2ce5, 0x0e65: 0x2ce9, 0x0e66: 0x2ced, 0x0e67: 0x2cf1, 0x0e68: 0x2cf5, 0x0e69: 0x2cf9, - 0x0e6a: 0x2be1, 0x0e6b: 0x2cfd, 0x0e6c: 0x2d01, 0x0e6d: 0x2d05, 0x0e6e: 0x2d09, 0x0e6f: 0x2d0d, - 0x0e70: 0x2d11, 0x0e71: 0x2d15, 0x0e72: 0x2d19, 0x0e73: 0x2d1d, 0x0e74: 0x2d21, 0x0e75: 0x2d25, - 0x0e76: 0x2d29, 0x0e77: 0x2d2d, 0x0e78: 0x2d31, 0x0e79: 0x2d35, 0x0e7a: 0x2d39, 0x0e7b: 0x2d3d, - 0x0e7c: 0x2d41, 0x0e7d: 0x2d45, 0x0e7e: 0x2d49, 0x0e7f: 0x2ac1, - // Block 0x3a, offset 0xe80 - 0x0e80: 0x2d4d, 0x0e81: 0x2d51, 0x0e82: 0x2d55, 0x0e83: 0x2d59, 0x0e84: 0x1b72, 0x0e85: 0x2d5d, - 0x0e86: 0x2d61, 0x0e87: 0x2d65, 0x0e88: 0x2d69, 0x0e89: 0x2d6d, 0x0e8a: 0x2d71, 0x0e8b: 0x2d75, - 0x0e8c: 0x2d79, 0x0e8d: 0x2d7d, 0x0e8e: 0x2d81, 0x0e8f: 0x2d85, 0x0e90: 0x2d89, 0x0e91: 0x2173, - 0x0e92: 0x2d8d, 0x0e93: 0x2d91, 0x0e94: 0x2d95, 0x0e95: 0x2d99, 0x0e96: 0x2d9d, 0x0e97: 0x2da1, - 0x0e98: 0x2da5, 0x0e99: 0x2da9, 0x0e9a: 0x2dad, 0x0e9b: 0x2be9, 0x0e9c: 0x2db1, 0x0e9d: 0x2db5, - 0x0e9e: 0x2db9, 0x0e9f: 0x2dbd, 0x0ea0: 0x2dc1, 0x0ea1: 0x2dc5, 0x0ea2: 0x2dc9, 0x0ea3: 0x2dcd, - 0x0ea4: 0x2dd1, 0x0ea5: 0x2dd5, 0x0ea6: 0x2dd9, 0x0ea7: 0x2ddd, 0x0ea8: 0x2de1, 0x0ea9: 0x1aba, - 0x0eaa: 0x2de5, 0x0eab: 0x2de9, 0x0eac: 0x2ded, 0x0ead: 0x2df1, 0x0eae: 0x2df5, 0x0eaf: 0x2df9, - 0x0eb0: 0x2dfd, 0x0eb1: 0x2e01, 0x0eb2: 0x2e05, 0x0eb3: 0x2e09, 0x0eb4: 0x2e0d, 0x0eb5: 0x2e11, - 0x0eb6: 0x2e15, 0x0eb7: 0x19f6, 0x0eb8: 0x2e19, 0x0eb9: 0x2e1d, 0x0eba: 0x2e21, 0x0ebb: 0x2e25, - 0x0ebc: 0x2e29, 0x0ebd: 0x2e2d, 0x0ebe: 0x2e31, 0x0ebf: 0x2e35, - // Block 0x3b, offset 0xec0 - 0x0ec0: 0x2e39, 0x0ec1: 0x2e3d, 0x0ec2: 0x2e41, 0x0ec3: 0x2e45, 0x0ec4: 0x2e49, 0x0ec5: 0x2e4d, - 0x0ec6: 0x2e51, 0x0ec7: 0x2e55, 0x0ec8: 0x1a62, 0x0ec9: 0x2e59, 0x0eca: 0x1a6e, 0x0ecb: 0x2e5d, - 0x0ecc: 0x2e61, 0x0ecd: 0x2e65, 0x0ed0: 0x2e69, - 0x0ed2: 0x2e6d, 0x0ed5: 0x2e71, 0x0ed6: 0x2e75, 0x0ed7: 0x2e79, - 0x0ed8: 0x2e7d, 0x0ed9: 0x2e81, 0x0eda: 0x2e85, 0x0edb: 0x2e89, 0x0edc: 0x2e8d, 0x0edd: 0x2e91, - 0x0ede: 0x1a12, 0x0ee0: 0x2e95, 0x0ee2: 0x2e99, - 0x0ee5: 0x2e9d, 0x0ee6: 0x2ea1, - 0x0eea: 0x2ea5, 0x0eeb: 0x2ea9, 0x0eec: 0x2ead, 0x0eed: 0x2eb1, - 0x0ef0: 0x2eb5, 0x0ef1: 0x2eb9, 0x0ef2: 0x2ebd, 0x0ef3: 0x2ec1, 0x0ef4: 0x2ec5, 0x0ef5: 0x2ec9, - 0x0ef6: 0x2ecd, 0x0ef7: 0x2ed1, 0x0ef8: 0x2ed5, 0x0ef9: 0x2ed9, 0x0efa: 0x2edd, 0x0efb: 0x2ee1, - 0x0efc: 0x18d6, 0x0efd: 0x2ee5, 0x0efe: 0x2ee9, 0x0eff: 0x2eed, - // Block 0x3c, offset 0xf00 - 0x0f00: 0x2ef1, 0x0f01: 0x2ef5, 0x0f02: 0x2ef9, 0x0f03: 0x2efd, 0x0f04: 0x2f01, 0x0f05: 0x2f05, - 0x0f06: 0x2f09, 0x0f07: 0x2f0d, 0x0f08: 0x2f11, 0x0f09: 0x2f15, 0x0f0a: 0x2f19, 0x0f0b: 0x2f1d, - 0x0f0c: 0x2187, 0x0f0d: 0x2f21, 0x0f0e: 0x2f25, 0x0f0f: 0x2f29, 0x0f10: 0x2f2d, 0x0f11: 0x2197, - 0x0f12: 0x2f31, 0x0f13: 0x2f35, 0x0f14: 0x2f39, 0x0f15: 0x2f3d, 0x0f16: 0x2f41, 0x0f17: 0x2cb1, - 0x0f18: 0x2f45, 0x0f19: 0x2f49, 0x0f1a: 0x2f4d, 0x0f1b: 0x2f51, 0x0f1c: 0x2f55, 0x0f1d: 0x2f59, - 0x0f1e: 0x2f59, 0x0f1f: 0x2f5d, 0x0f20: 0x2f61, 0x0f21: 0x2f65, 0x0f22: 0x2f69, 0x0f23: 0x2f6d, - 0x0f24: 0x2f71, 0x0f25: 0x2f75, 0x0f26: 0x2f79, 0x0f27: 0x2e9d, 0x0f28: 0x2f7d, 0x0f29: 0x2f81, - 0x0f2a: 0x2f85, 0x0f2b: 0x2f89, 0x0f2c: 0x2f8d, 0x0f2d: 0x2f92, - 0x0f30: 0x2f96, 0x0f31: 0x2f9a, 0x0f32: 0x2f9e, 0x0f33: 0x2fa2, 0x0f34: 0x2fa6, 0x0f35: 0x2faa, - 0x0f36: 0x2fae, 0x0f37: 0x2fb2, 0x0f38: 0x2ecd, 0x0f39: 0x2fb6, 0x0f3a: 0x2fba, 0x0f3b: 0x2fbe, - 0x0f3c: 0x2e69, 0x0f3d: 0x2fc2, 0x0f3e: 0x2fc6, 0x0f3f: 0x2fca, - // Block 0x3d, offset 0xf40 - 0x0f40: 0x2fce, 0x0f41: 0x2fd2, 0x0f42: 0x2fd6, 0x0f43: 0x2fda, 0x0f44: 0x2fde, 0x0f45: 0x2fe2, - 0x0f46: 0x2fe6, 0x0f47: 0x2fea, 0x0f48: 0x2fee, 0x0f49: 0x2eed, 0x0f4a: 0x2ff2, 0x0f4b: 0x2ef1, - 0x0f4c: 0x2ff6, 0x0f4d: 0x2ffa, 0x0f4e: 0x2ffe, 0x0f4f: 0x3002, 0x0f50: 0x3006, 0x0f51: 0x2e6d, - 0x0f52: 0x2b15, 0x0f53: 0x300a, 0x0f54: 0x300e, 0x0f55: 0x195a, 0x0f56: 0x2c25, 0x0f57: 0x2d71, - 0x0f58: 0x3012, 0x0f59: 0x3016, 0x0f5a: 0x2f0d, 0x0f5b: 0x301a, 0x0f5c: 0x2f11, 0x0f5d: 0x301e, - 0x0f5e: 0x3022, 0x0f5f: 0x3026, 0x0f60: 0x2e75, 0x0f61: 0x302a, 0x0f62: 0x302e, 0x0f63: 0x3032, - 0x0f64: 0x3036, 0x0f65: 0x303a, 0x0f66: 0x2e79, 0x0f67: 0x303e, 0x0f68: 0x3042, 0x0f69: 0x3046, - 0x0f6a: 0x304a, 0x0f6b: 0x304e, 0x0f6c: 0x3052, 0x0f6d: 0x2f41, 0x0f6e: 0x3056, 0x0f6f: 0x305a, - 0x0f70: 0x2cb1, 0x0f71: 0x305e, 0x0f72: 0x2f51, 0x0f73: 0x3062, 0x0f74: 0x3066, 0x0f75: 0x306a, - 0x0f76: 0x306e, 0x0f77: 0x3072, 0x0f78: 0x2f65, 0x0f79: 0x3076, 0x0f7a: 0x2e99, 0x0f7b: 0x307a, - 0x0f7c: 0x2f69, 0x0f7d: 0x2bd9, 0x0f7e: 0x307e, 0x0f7f: 0x2f6d, - // Block 0x3e, offset 0xf80 - 0x0f80: 0x3082, 0x0f81: 0x2f75, 0x0f82: 0x3086, 0x0f83: 0x308a, 0x0f84: 0x308e, 0x0f85: 0x3092, - 0x0f86: 0x3096, 0x0f87: 0x2f7d, 0x0f88: 0x2e8d, 0x0f89: 0x309a, 0x0f8a: 0x2f81, 0x0f8b: 0x309e, - 0x0f8c: 0x2f85, 0x0f8d: 0x30a2, 0x0f8e: 0x1b76, 0x0f8f: 0x30a6, 0x0f90: 0x30ab, 0x0f91: 0x30b0, - 0x0f92: 0x30b5, 0x0f93: 0x30b9, 0x0f94: 0x30bd, 0x0f95: 0x30c1, 0x0f96: 0x30c6, 0x0f97: 0x30cb, - 0x0f98: 0x30d0, 0x0f99: 0x30d4, - // Block 0x3f, offset 0xfc0 - 0x0fdd: 0x3105, - 0x0fdf: 0x310a, - 0x0fea: 0x3124, 0x0feb: 0x3129, 0x0fec: 0x312e, 0x0fed: 0x3135, 0x0fee: 0x313c, 0x0fef: 0x3141, - 0x0ff0: 0x3146, 0x0ff1: 0x314b, 0x0ff2: 0x3150, 0x0ff3: 0x3155, 0x0ff4: 0x315a, 0x0ff5: 0x315f, - 0x0ff6: 0x3164, 0x0ff8: 0x3169, 0x0ff9: 0x316e, 0x0ffa: 0x3173, 0x0ffb: 0x3178, - 0x0ffc: 0x317d, 0x0ffe: 0x3182, - // Block 0x40, offset 0x1000 - 0x1000: 0x3187, 0x1001: 0x318c, 0x1003: 0x3191, 0x1004: 0x3196, - 0x1006: 0x319b, 0x1007: 0x31a0, 0x1008: 0x31a5, 0x1009: 0x31aa, 0x100a: 0x31af, 0x100b: 0x31b4, - 0x100c: 0x31b9, 0x100d: 0x31be, 0x100e: 0x31c3, - // Block 0x41, offset 0x1040 - 0x105a: 0x3a73, 0x105c: 0x3a7c, - 0x106b: 0x3a85, - // Block 0x42, offset 0x1080 - 0x109e: 0x3a8e, 0x109f: 0x3a97, 0x10a0: 0x3aa0, 0x10a1: 0x3aad, 0x10a2: 0x3aba, 0x10a3: 0x3ac7, - 0x10a4: 0x3ad4, - // Block 0x43, offset 0x10c0 - 0x10fb: 0x3ae1, - 0x10fc: 0x3aea, 0x10fd: 0x3af3, 0x10fe: 0x3b00, 0x10ff: 0x3b0d, - // Block 0x44, offset 0x1100 - 0x1100: 0x3b1a, - // Block 0x45, offset 0x1140 - 0x1140: 0x3d23, 0x1141: 0x3d27, 0x1142: 0x3d2b, 0x1143: 0x3d2f, 0x1144: 0x3d34, 0x1145: 0x2eb5, - 0x1146: 0x3d38, 0x1147: 0x3d3c, 0x1148: 0x3d40, 0x1149: 0x3d44, 0x114a: 0x2eb9, 0x114b: 0x3d48, - 0x114c: 0x3d4c, 0x114d: 0x3d50, 0x114e: 0x2ebd, 0x114f: 0x3d55, 0x1150: 0x3d59, 0x1151: 0x3d5d, - 0x1152: 0x3d61, 0x1153: 0x3d66, 0x1154: 0x3d6a, 0x1155: 0x3c71, 0x1156: 0x3d6e, 0x1157: 0x3d73, - 0x1158: 0x3d77, 0x1159: 0x3d7b, 0x115a: 0x3d7f, 0x115b: 0x2f9a, 0x115c: 0x3d83, 0x115d: 0x1866, - 0x115e: 0x3d88, 0x115f: 0x3d8c, 0x1160: 0x3d90, 0x1161: 0x3d94, 0x1162: 0x3cb9, 0x1163: 0x3d98, - 0x1164: 0x3d9c, 0x1165: 0x2fae, 0x1166: 0x2ec1, 0x1167: 0x2ec5, 0x1168: 0x2fb2, 0x1169: 0x3da0, - 0x116a: 0x3da4, 0x116b: 0x2bf1, 0x116c: 0x3da8, 0x116d: 0x2ec9, 0x116e: 0x3dac, 0x116f: 0x3db0, - 0x1170: 0x3db4, 0x1171: 0x3db8, 0x1172: 0x3db8, 0x1173: 0x3db8, 0x1174: 0x3dbc, 0x1175: 0x3dc1, - 0x1176: 0x3dc5, 0x1177: 0x3dc9, 0x1178: 0x3dcd, 0x1179: 0x3dd2, 0x117a: 0x3dd6, 0x117b: 0x3dda, - 0x117c: 0x3dde, 0x117d: 0x3de2, 0x117e: 0x3de6, 0x117f: 0x3dea, - // Block 0x46, offset 0x1180 - 0x1180: 0x3dee, 0x1181: 0x3df2, 0x1182: 0x3df6, 0x1183: 0x3dfa, 0x1184: 0x3dfe, 0x1185: 0x3e02, - 0x1186: 0x3e02, 0x1187: 0x2fba, 0x1188: 0x3e06, 0x1189: 0x3e0a, 0x118a: 0x3e0e, 0x118b: 0x3e12, - 0x118c: 0x2ed1, 0x118d: 0x3e16, 0x118e: 0x3e1a, 0x118f: 0x3e1e, 0x1190: 0x2e39, 0x1191: 0x3e22, - 0x1192: 0x3e26, 0x1193: 0x3e2a, 0x1194: 0x3e2e, 0x1195: 0x3e32, 0x1196: 0x3e36, 0x1197: 0x3e3a, - 0x1198: 0x3e3e, 0x1199: 0x3e42, 0x119a: 0x3e47, 0x119b: 0x3e4b, 0x119c: 0x3e4f, 0x119d: 0x3c55, - 0x119e: 0x3e53, 0x119f: 0x3e57, 0x11a0: 0x3e5b, 0x11a1: 0x3e60, 0x11a2: 0x3e65, 0x11a3: 0x3e69, - 0x11a4: 0x3e6d, 0x11a5: 0x3e71, 0x11a6: 0x3e75, 0x11a7: 0x3e79, 0x11a8: 0x3e7d, 0x11a9: 0x3e81, - 0x11aa: 0x3e85, 0x11ab: 0x3e85, 0x11ac: 0x3e89, 0x11ad: 0x3e8e, 0x11ae: 0x3e92, 0x11af: 0x2be1, - 0x11b0: 0x3e96, 0x11b1: 0x3e9a, 0x11b2: 0x3e9f, 0x11b3: 0x3ea3, 0x11b4: 0x3ea7, 0x11b5: 0x18ce, - 0x11b6: 0x3eab, 0x11b7: 0x3eaf, 0x11b8: 0x18d6, 0x11b9: 0x3eb3, 0x11ba: 0x3eb7, 0x11bb: 0x3ebb, - 0x11bc: 0x3ec0, 0x11bd: 0x3ec4, 0x11be: 0x3ec9, 0x11bf: 0x3ecd, - // Block 0x47, offset 0x11c0 - 0x11c0: 0x3ed1, 0x11c1: 0x3ed5, 0x11c2: 0x3ed9, 0x11c3: 0x3edd, 0x11c4: 0x3ee1, 0x11c5: 0x3ee5, - 0x11c6: 0x3ee9, 0x11c7: 0x3eed, 0x11c8: 0x3ef1, 0x11c9: 0x3ef5, 0x11ca: 0x3efa, 0x11cb: 0x3efe, - 0x11cc: 0x3f02, 0x11cd: 0x3f06, 0x11ce: 0x2b11, 0x11cf: 0x3f0a, 0x11d0: 0x18fe, 0x11d1: 0x3f0f, - 0x11d2: 0x3f0f, 0x11d3: 0x3f14, 0x11d4: 0x3f18, 0x11d5: 0x3f18, 0x11d6: 0x3f1c, 0x11d7: 0x3f20, - 0x11d8: 0x3f25, 0x11d9: 0x3f2a, 0x11da: 0x3f2e, 0x11db: 0x3f32, 0x11dc: 0x3f36, 0x11dd: 0x3f3a, - 0x11de: 0x3f3e, 0x11df: 0x3f42, 0x11e0: 0x3f46, 0x11e1: 0x3f4a, 0x11e2: 0x3f4e, 0x11e3: 0x2ee5, - 0x11e4: 0x3f52, 0x11e5: 0x3f57, 0x11e6: 0x3f5b, 0x11e7: 0x3f5f, 0x11e8: 0x2fea, 0x11e9: 0x3f5f, - 0x11ea: 0x3f63, 0x11eb: 0x2eed, 0x11ec: 0x3f67, 0x11ed: 0x3f6b, 0x11ee: 0x3f6f, 0x11ef: 0x3f73, - 0x11f0: 0x2ef1, 0x11f1: 0x2aa5, 0x11f2: 0x3f77, 0x11f3: 0x3f7b, 0x11f4: 0x3f7f, 0x11f5: 0x3f83, - 0x11f6: 0x3f87, 0x11f7: 0x3f8b, 0x11f8: 0x3f8f, 0x11f9: 0x3f94, 0x11fa: 0x3f98, 0x11fb: 0x3f9c, - 0x11fc: 0x3fa0, 0x11fd: 0x3fa4, 0x11fe: 0x3fa8, 0x11ff: 0x3fad, - // Block 0x48, offset 0x1200 - 0x1200: 0x3fb1, 0x1201: 0x3fb5, 0x1202: 0x3fb9, 0x1203: 0x3fbd, 0x1204: 0x3fc1, 0x1205: 0x3fc5, - 0x1206: 0x3fc9, 0x1207: 0x3fcd, 0x1208: 0x2ef5, 0x1209: 0x3fd1, 0x120a: 0x3fd5, 0x120b: 0x3fda, - 0x120c: 0x3fde, 0x120d: 0x3fe2, 0x120e: 0x3fe6, 0x120f: 0x2efd, 0x1210: 0x3fea, 0x1211: 0x3fee, - 0x1212: 0x3ff2, 0x1213: 0x3ff6, 0x1214: 0x3ffa, 0x1215: 0x3ffe, 0x1216: 0x4002, 0x1217: 0x4006, - 0x1218: 0x2b15, 0x1219: 0x300a, 0x121a: 0x400a, 0x121b: 0x400e, 0x121c: 0x4012, 0x121d: 0x4016, - 0x121e: 0x401b, 0x121f: 0x401f, 0x1220: 0x4023, 0x1221: 0x4027, 0x1222: 0x2f01, 0x1223: 0x402b, - 0x1224: 0x4030, 0x1225: 0x4034, 0x1226: 0x4038, 0x1227: 0x30b5, 0x1228: 0x403c, 0x1229: 0x4040, - 0x122a: 0x4044, 0x122b: 0x4048, 0x122c: 0x404c, 0x122d: 0x4051, 0x122e: 0x4055, 0x122f: 0x4059, - 0x1230: 0x405d, 0x1231: 0x4062, 0x1232: 0x4066, 0x1233: 0x406a, 0x1234: 0x406e, 0x1235: 0x2c25, - 0x1236: 0x4072, 0x1237: 0x4076, 0x1238: 0x407b, 0x1239: 0x4080, 0x123a: 0x4085, 0x123b: 0x4089, - 0x123c: 0x408e, 0x123d: 0x4092, 0x123e: 0x4096, 0x123f: 0x409a, - // Block 0x49, offset 0x1240 - 0x1240: 0x409e, 0x1241: 0x2f05, 0x1242: 0x2d71, 0x1243: 0x40a2, 0x1244: 0x40a6, 0x1245: 0x40aa, - 0x1246: 0x40ae, 0x1247: 0x40b3, 0x1248: 0x40b7, 0x1249: 0x40bb, 0x124a: 0x40bf, 0x124b: 0x3016, - 0x124c: 0x40c3, 0x124d: 0x40c7, 0x124e: 0x40cc, 0x124f: 0x40d0, 0x1250: 0x40d4, 0x1251: 0x40d9, - 0x1252: 0x40de, 0x1253: 0x40e2, 0x1254: 0x301a, 0x1255: 0x40e6, 0x1256: 0x40ea, 0x1257: 0x40ee, - 0x1258: 0x40f2, 0x1259: 0x40f6, 0x125a: 0x40fa, 0x125b: 0x40fe, 0x125c: 0x4103, 0x125d: 0x4107, - 0x125e: 0x410c, 0x125f: 0x4110, 0x1260: 0x4115, 0x1261: 0x3022, 0x1262: 0x4119, 0x1263: 0x411d, - 0x1264: 0x4122, 0x1265: 0x4126, 0x1266: 0x412a, 0x1267: 0x412f, 0x1268: 0x4134, 0x1269: 0x4138, - 0x126a: 0x413c, 0x126b: 0x4140, 0x126c: 0x4144, 0x126d: 0x4144, 0x126e: 0x4148, 0x126f: 0x414c, - 0x1270: 0x302a, 0x1271: 0x4150, 0x1272: 0x4154, 0x1273: 0x4158, 0x1274: 0x415c, 0x1275: 0x4160, - 0x1276: 0x4165, 0x1277: 0x4169, 0x1278: 0x2bed, 0x1279: 0x416e, 0x127a: 0x4173, 0x127b: 0x4177, - 0x127c: 0x417c, 0x127d: 0x4181, 0x127e: 0x4186, 0x127f: 0x418a, - // Block 0x4a, offset 0x1280 - 0x1280: 0x3042, 0x1281: 0x418e, 0x1282: 0x4193, 0x1283: 0x4198, 0x1284: 0x419d, 0x1285: 0x41a2, - 0x1286: 0x41a6, 0x1287: 0x41a6, 0x1288: 0x3046, 0x1289: 0x30bd, 0x128a: 0x41aa, 0x128b: 0x41ae, - 0x128c: 0x41b2, 0x128d: 0x41b6, 0x128e: 0x41bb, 0x128f: 0x2b59, 0x1290: 0x304e, 0x1291: 0x41bf, - 0x1292: 0x41c3, 0x1293: 0x2f2d, 0x1294: 0x41c8, 0x1295: 0x41cd, 0x1296: 0x2e89, 0x1297: 0x41d2, - 0x1298: 0x41d6, 0x1299: 0x2f39, 0x129a: 0x41da, 0x129b: 0x41de, 0x129c: 0x41e2, 0x129d: 0x41e7, - 0x129e: 0x41e7, 0x129f: 0x41ec, 0x12a0: 0x41f0, 0x12a1: 0x41f4, 0x12a2: 0x41f9, 0x12a3: 0x41fd, - 0x12a4: 0x4201, 0x12a5: 0x4205, 0x12a6: 0x420a, 0x12a7: 0x420e, 0x12a8: 0x4212, 0x12a9: 0x4216, - 0x12aa: 0x421a, 0x12ab: 0x421e, 0x12ac: 0x4223, 0x12ad: 0x4227, 0x12ae: 0x422b, 0x12af: 0x422f, - 0x12b0: 0x4233, 0x12b1: 0x4237, 0x12b2: 0x423b, 0x12b3: 0x4240, 0x12b4: 0x4245, 0x12b5: 0x4249, - 0x12b6: 0x424e, 0x12b7: 0x4252, 0x12b8: 0x4257, 0x12b9: 0x425b, 0x12ba: 0x2f51, 0x12bb: 0x425f, - 0x12bc: 0x4264, 0x12bd: 0x4269, 0x12be: 0x426d, 0x12bf: 0x4272, - // Block 0x4b, offset 0x12c0 - 0x12c0: 0x4276, 0x12c1: 0x427b, 0x12c2: 0x427f, 0x12c3: 0x4283, 0x12c4: 0x4287, 0x12c5: 0x428b, - 0x12c6: 0x428f, 0x12c7: 0x4293, 0x12c8: 0x4298, 0x12c9: 0x429d, 0x12ca: 0x42a2, 0x12cb: 0x3f14, - 0x12cc: 0x42a7, 0x12cd: 0x42ab, 0x12ce: 0x42af, 0x12cf: 0x42b3, 0x12d0: 0x42b7, 0x12d1: 0x42bb, - 0x12d2: 0x42bf, 0x12d3: 0x42c3, 0x12d4: 0x42c7, 0x12d5: 0x42cb, 0x12d6: 0x42cf, 0x12d7: 0x42d3, - 0x12d8: 0x2c31, 0x12d9: 0x42d8, 0x12da: 0x42dc, 0x12db: 0x42e0, 0x12dc: 0x42e4, 0x12dd: 0x42e8, - 0x12de: 0x42ec, 0x12df: 0x2f5d, 0x12e0: 0x42f0, 0x12e1: 0x42f4, 0x12e2: 0x42f8, 0x12e3: 0x42fc, - 0x12e4: 0x4300, 0x12e5: 0x4305, 0x12e6: 0x430a, 0x12e7: 0x430f, 0x12e8: 0x4313, 0x12e9: 0x4317, - 0x12ea: 0x431b, 0x12eb: 0x431f, 0x12ec: 0x4324, 0x12ed: 0x4328, 0x12ee: 0x432d, 0x12ef: 0x4331, - 0x12f0: 0x4335, 0x12f1: 0x433a, 0x12f2: 0x433f, 0x12f3: 0x4343, 0x12f4: 0x2b45, 0x12f5: 0x4347, - 0x12f6: 0x434b, 0x12f7: 0x434f, 0x12f8: 0x4353, 0x12f9: 0x4357, 0x12fa: 0x435b, 0x12fb: 0x306a, - 0x12fc: 0x435f, 0x12fd: 0x4363, 0x12fe: 0x4367, 0x12ff: 0x436b, - // Block 0x4c, offset 0x1300 - 0x1300: 0x436f, 0x1301: 0x4373, 0x1302: 0x4377, 0x1303: 0x437b, 0x1304: 0x1a66, 0x1305: 0x437f, - 0x1306: 0x4384, 0x1307: 0x4388, 0x1308: 0x438c, 0x1309: 0x4390, 0x130a: 0x4394, 0x130b: 0x4398, - 0x130c: 0x439d, 0x130d: 0x43a2, 0x130e: 0x43a6, 0x130f: 0x43aa, 0x1310: 0x307e, 0x1311: 0x3082, - 0x1312: 0x1a82, 0x1313: 0x43ae, 0x1314: 0x43b3, 0x1315: 0x43b7, 0x1316: 0x43bb, 0x1317: 0x43bf, - 0x1318: 0x43c3, 0x1319: 0x43c8, 0x131a: 0x43cd, 0x131b: 0x43d1, 0x131c: 0x43d5, 0x131d: 0x43d9, - 0x131e: 0x43de, 0x131f: 0x3086, 0x1320: 0x43e2, 0x1321: 0x43e7, 0x1322: 0x43ec, 0x1323: 0x43f0, - 0x1324: 0x43f4, 0x1325: 0x43f8, 0x1326: 0x43fd, 0x1327: 0x4401, 0x1328: 0x4405, 0x1329: 0x4409, - 0x132a: 0x440d, 0x132b: 0x4411, 0x132c: 0x4415, 0x132d: 0x4419, 0x132e: 0x441e, 0x132f: 0x4422, - 0x1330: 0x4426, 0x1331: 0x442a, 0x1332: 0x442f, 0x1333: 0x4433, 0x1334: 0x4437, 0x1335: 0x443b, - 0x1336: 0x443f, 0x1337: 0x4444, 0x1338: 0x4449, 0x1339: 0x444d, 0x133a: 0x4451, 0x133b: 0x4455, - 0x133c: 0x445a, 0x133d: 0x445e, 0x133e: 0x309e, 0x133f: 0x309e, - // Block 0x4d, offset 0x1340 - 0x1340: 0x4463, 0x1341: 0x4467, 0x1342: 0x446c, 0x1343: 0x4470, 0x1344: 0x4474, 0x1345: 0x4478, - 0x1346: 0x447c, 0x1347: 0x4480, 0x1348: 0x4484, 0x1349: 0x4488, 0x134a: 0x30a2, 0x134b: 0x448d, - 0x134c: 0x4491, 0x134d: 0x4495, 0x134e: 0x4499, 0x134f: 0x449d, 0x1350: 0x44a1, 0x1351: 0x44a6, - 0x1352: 0x44aa, 0x1353: 0x44af, 0x1354: 0x44b4, 0x1355: 0x1b42, 0x1356: 0x44b9, 0x1357: 0x1b52, - 0x1358: 0x44bd, 0x1359: 0x44c1, 0x135a: 0x44c5, 0x135b: 0x44c9, 0x135c: 0x1b66, 0x135d: 0x44cd, + 0x0540: 0x436f, 0x0541: 0x4373, 0x0542: 0x4377, 0x0543: 0x437b, 0x0544: 0x1a66, 0x0545: 0x437f, + 0x0546: 0x4384, 0x0547: 0x4388, 0x0548: 0x438c, 0x0549: 0x4390, 0x054a: 0x4394, 0x054b: 0x4398, + 0x054c: 0x439d, 0x054d: 0x43a2, 0x054e: 0x43a6, 0x054f: 0x43aa, 0x0550: 0x307e, 0x0551: 0x3082, + 0x0552: 0x1a82, 0x0553: 0x43ae, 0x0554: 0x43b3, 0x0555: 0x43b7, 0x0556: 0x43bb, 0x0557: 0x43bf, + 0x0558: 0x43c3, 0x0559: 0x43c8, 0x055a: 0x43cd, 0x055b: 0x43d1, 0x055c: 0x43d5, 0x055d: 0x43d9, + 0x055e: 0x43de, 0x055f: 0x3086, 0x0560: 0x43e2, 0x0561: 0x43e7, 0x0562: 0x43ec, 0x0563: 0x43f0, + 0x0564: 0x43f4, 0x0565: 0x43f8, 0x0566: 0x43fd, 0x0567: 0x4401, 0x0568: 0x4405, 0x0569: 0x4409, + 0x056a: 0x440d, 0x056b: 0x4411, 0x056c: 0x4415, 0x056d: 0x4419, 0x056e: 0x441e, 0x056f: 0x4422, + 0x0570: 0x4426, 0x0571: 0x442a, 0x0572: 0x442f, 0x0573: 0x4433, 0x0574: 0x4437, 0x0575: 0x443b, + 0x0576: 0x443f, 0x0577: 0x4444, 0x0578: 0x4449, 0x0579: 0x444d, 0x057a: 0x4451, 0x057b: 0x4455, + 0x057c: 0x445a, 0x057d: 0x445e, 0x057e: 0x309e, 0x057f: 0x309e, +} + +// nfcDecompSparseOffset: 56 entries, 112 bytes +var nfcDecompSparseOffset = []uint16{0x0, 0xa, 0x10, 0x15, 0x18, 0x22, 0x27, 0x2e, 0x31, 0x38, 0x3e, 0x46, 0x48, 0x4c, 0x50, 0x52, 0x56, 0x59, 0x5c, 0x60, 0x62, 0x64, 0x66, 0x6a, 0x6c, 0x70, 0x7a, 0x82, 0x84, 0x8d, 0x90, 0x9e, 0xa0, 0xa4, 0xa7, 0xa9, 0xaf, 0xbb, 0xc0, 0xc3, 0xc5, 0xc7, 0xd4, 0xe2, 0xed, 0xf4, 0xff, 0x10b, 0x11c, 0x12d, 0x135, 0x139, 0x13d, 0x141, 0x145, 0x147} + +// nfcDecompSparseValues: 341 entries, 1364 bytes +var nfcDecompSparseValues = [341]valueRange{ + // Block 0x0, offset 0x1 + {value: 0x0004, lo: 0x09}, + {value: 0x0032, lo: 0x80, hi: 0x85}, + {value: 0x004a, lo: 0x87, hi: 0x8f}, + {value: 0x006e, lo: 0x91, hi: 0x96}, + {value: 0x0086, lo: 0x99, hi: 0x9d}, + {value: 0x009a, lo: 0xa0, hi: 0xa5}, + {value: 0x00b2, lo: 0xa7, hi: 0xaf}, + {value: 0x00d6, lo: 0xb1, hi: 0xb6}, + {value: 0x00ee, lo: 0xb9, hi: 0xbd}, + {value: 0x0102, lo: 0xbf, hi: 0xbf}, + // Block 0x1, offset 0x2 + {value: 0x0004, lo: 0x05}, + {value: 0x0106, lo: 0x80, hi: 0x8f}, + {value: 0x0146, lo: 0x92, hi: 0xa5}, + {value: 0x0196, lo: 0xa8, hi: 0xb0}, + {value: 0x01c0, lo: 0xb4, hi: 0xb7}, + {value: 0x01d0, lo: 0xb9, hi: 0xbe}, + // Block 0x2, offset 0x3 + {value: 0x0004, lo: 0x04}, + {value: 0x01f0, lo: 0x83, hi: 0x88}, + {value: 0x020c, lo: 0x8c, hi: 0x91}, + {value: 0x0224, lo: 0x94, hi: 0xa5}, + {value: 0x026c, lo: 0xa8, hi: 0xbe}, + // Block 0x3, offset 0x4 + {value: 0x0004, lo: 0x02}, + {value: 0x02ca, lo: 0xa0, hi: 0xa1}, + {value: 0x02d2, lo: 0xaf, hi: 0xb0}, + // Block 0x4, offset 0x5 + {value: 0x0004, lo: 0x09}, + {value: 0x03d8, lo: 0x80, hi: 0x9b}, + {value: 0x0448, lo: 0x9e, hi: 0x9f}, + {value: 0x0450, lo: 0xa6, hi: 0xaa}, + {value: 0x0466, lo: 0xab, hi: 0xab}, + {value: 0x046c, lo: 0xac, hi: 0xac}, + {value: 0x0472, lo: 0xad, hi: 0xad}, + {value: 0x0478, lo: 0xae, hi: 0xb0}, + {value: 0x0486, lo: 0xb1, hi: 0xb1}, + {value: 0x048c, lo: 0xb2, hi: 0xb3}, + // Block 0x5, offset 0x6 + {value: 0x0003, lo: 0x04}, + {value: 0x04cc, lo: 0x80, hi: 0x81}, + {value: 0x04d2, lo: 0x83, hi: 0x84}, + {value: 0x04da, lo: 0xb4, hi: 0xb4}, + {value: 0x04e1, lo: 0xbe, hi: 0xbe}, + // Block 0x6, offset 0x7 + {value: 0x0005, lo: 0x06}, + {value: 0x04e3, lo: 0x85, hi: 0x85}, + {value: 0x04ee, lo: 0x86, hi: 0x87}, + {value: 0x04f6, lo: 0x88, hi: 0x8a}, + {value: 0x0505, lo: 0x8c, hi: 0x8c}, + {value: 0x050a, lo: 0x8e, hi: 0x90}, + {value: 0x051b, lo: 0xaa, hi: 0xb0}, + // Block 0x7, offset 0x8 + {value: 0x0005, lo: 0x02}, + {value: 0x0540, lo: 0x8a, hi: 0x8e}, + {value: 0x0562, lo: 0x93, hi: 0x94}, + // Block 0x8, offset 0x9 + {value: 0x0005, lo: 0x06}, + {value: 0x0584, lo: 0x80, hi: 0x81}, + {value: 0x058e, lo: 0x83, hi: 0x83}, + {value: 0x0593, lo: 0x87, hi: 0x87}, + {value: 0x0598, lo: 0x8c, hi: 0x8e}, + {value: 0x05a7, lo: 0x99, hi: 0x99}, + {value: 0x05ac, lo: 0xb9, hi: 0xb9}, + // Block 0x9, offset 0xa + {value: 0x0005, lo: 0x05}, + {value: 0x05b1, lo: 0x90, hi: 0x91}, + {value: 0x05bb, lo: 0x93, hi: 0x93}, + {value: 0x05c0, lo: 0x97, hi: 0x97}, + {value: 0x05c5, lo: 0x9c, hi: 0x9e}, + {value: 0x05d4, lo: 0xb6, hi: 0xb7}, + // Block 0xa, offset 0xb + {value: 0x0005, lo: 0x07}, + {value: 0x05de, lo: 0x81, hi: 0x82}, + {value: 0x05e8, lo: 0x90, hi: 0x93}, + {value: 0x05fc, lo: 0x96, hi: 0x97}, + {value: 0x0606, lo: 0x9a, hi: 0x9f}, + {value: 0x0624, lo: 0xa2, hi: 0xa7}, + {value: 0x0642, lo: 0xaa, hi: 0xb5}, + {value: 0x067e, lo: 0xb8, hi: 0xb9}, + // Block 0xb, offset 0xc + {value: 0x0005, lo: 0x01}, + {value: 0x068d, lo: 0xa2, hi: 0xa6}, + // Block 0xc, offset 0xd + {value: 0x0005, lo: 0x03}, + {value: 0x06ba, lo: 0x80, hi: 0x80}, + {value: 0x06bf, lo: 0x82, hi: 0x82}, + {value: 0x06c4, lo: 0x93, hi: 0x93}, + // Block 0xd, offset 0xe + {value: 0x0007, lo: 0x03}, + {value: 0x06c9, lo: 0xa9, hi: 0xa9}, + {value: 0x06d0, lo: 0xb1, hi: 0xb1}, + {value: 0x06d7, lo: 0xb4, hi: 0xb4}, + // Block 0xe, offset 0xf + {value: 0x0007, lo: 0x01}, + {value: 0x06de, lo: 0x98, hi: 0x9f}, + // Block 0xf, offset 0x10 + {value: 0x0007, lo: 0x03}, + {value: 0x0716, lo: 0x8b, hi: 0x8c}, + {value: 0x0724, lo: 0x9c, hi: 0x9d}, + {value: 0x0732, lo: 0x9f, hi: 0x9f}, + // Block 0x10, offset 0x11 + {value: 0x0007, lo: 0x02}, + {value: 0x0739, lo: 0xb3, hi: 0xb3}, + {value: 0x0740, lo: 0xb6, hi: 0xb6}, + // Block 0x11, offset 0x12 + {value: 0x0007, lo: 0x02}, + {value: 0x0747, lo: 0x99, hi: 0x9b}, + {value: 0x075c, lo: 0x9e, hi: 0x9e}, + // Block 0x12, offset 0x13 + {value: 0x0007, lo: 0x03}, + {value: 0x0763, lo: 0x88, hi: 0x88}, + {value: 0x076a, lo: 0x8b, hi: 0x8c}, + {value: 0x0778, lo: 0x9c, hi: 0x9d}, + // Block 0x13, offset 0x14 + {value: 0x0000, lo: 0x01}, + {value: 0x0786, lo: 0x94, hi: 0x94}, + // Block 0x14, offset 0x15 + {value: 0x0007, lo: 0x01}, + {value: 0x078d, lo: 0x8a, hi: 0x8c}, + // Block 0x15, offset 0x16 + {value: 0x0000, lo: 0x01}, + {value: 0x07a2, lo: 0x88, hi: 0x88}, + // Block 0x16, offset 0x17 + {value: 0x0007, lo: 0x03}, + {value: 0x07a9, lo: 0x80, hi: 0x80}, + {value: 0x07b0, lo: 0x87, hi: 0x88}, + {value: 0x07be, lo: 0x8a, hi: 0x8b}, + // Block 0x17, offset 0x18 + {value: 0x0007, lo: 0x01}, + {value: 0x07cf, lo: 0x8a, hi: 0x8c}, + // Block 0x18, offset 0x19 + {value: 0x0007, lo: 0x03}, + {value: 0x07e4, lo: 0x9a, hi: 0x9a}, + {value: 0x07eb, lo: 0x9c, hi: 0x9d}, + {value: 0x07fc, lo: 0x9e, hi: 0x9e}, + // Block 0x19, offset 0x1a + {value: 0x0007, lo: 0x09}, + {value: 0x0823, lo: 0x83, hi: 0x83}, + {value: 0x082a, lo: 0x8d, hi: 0x8d}, + {value: 0x0831, lo: 0x92, hi: 0x92}, + {value: 0x0838, lo: 0x97, hi: 0x97}, + {value: 0x083f, lo: 0x9c, hi: 0x9c}, + {value: 0x0846, lo: 0xa9, hi: 0xa9}, + {value: 0x084d, lo: 0xb3, hi: 0xb3}, + {value: 0x0854, lo: 0xb5, hi: 0xb6}, + {value: 0x086c, lo: 0xb8, hi: 0xb8}, + // Block 0x1a, offset 0x1b + {value: 0x0007, lo: 0x07}, + {value: 0x087d, lo: 0x81, hi: 0x81}, + {value: 0x0884, lo: 0x93, hi: 0x93}, + {value: 0x088b, lo: 0x9d, hi: 0x9d}, + {value: 0x0892, lo: 0xa2, hi: 0xa2}, + {value: 0x0899, lo: 0xa7, hi: 0xa7}, + {value: 0x08a0, lo: 0xac, hi: 0xac}, + {value: 0x08a7, lo: 0xb9, hi: 0xb9}, + // Block 0x1b, offset 0x1c + {value: 0x0000, lo: 0x01}, + {value: 0x08ae, lo: 0xa6, hi: 0xa6}, + // Block 0x1c, offset 0x1d + {value: 0x0007, lo: 0x08}, + {value: 0x08b9, lo: 0x86, hi: 0x86}, + {value: 0x08c0, lo: 0x88, hi: 0x88}, + {value: 0x08c7, lo: 0x8a, hi: 0x8a}, + {value: 0x08ce, lo: 0x8c, hi: 0x8c}, + {value: 0x08d5, lo: 0x8e, hi: 0x8e}, + {value: 0x08dc, lo: 0x92, hi: 0x92}, + {value: 0x08e3, lo: 0xbb, hi: 0xbb}, + {value: 0x08ea, lo: 0xbd, hi: 0xbd}, + // Block 0x1d, offset 0x1e + {value: 0x0007, lo: 0x02}, + {value: 0x08f1, lo: 0x80, hi: 0x81}, + {value: 0x08ff, lo: 0x83, hi: 0x83}, + // Block 0x1e, offset 0x1f + {value: 0x0004, lo: 0x0d}, + {value: 0x09ea, lo: 0x80, hi: 0x88}, + {value: 0x0a10, lo: 0x89, hi: 0x89}, + {value: 0x0a16, lo: 0x8a, hi: 0x94}, + {value: 0x0a44, lo: 0x95, hi: 0x95}, + {value: 0x0a4a, lo: 0x96, hi: 0x96}, + {value: 0x0a50, lo: 0x97, hi: 0x97}, + {value: 0x0a56, lo: 0x98, hi: 0x9c}, + {value: 0x0a6c, lo: 0x9d, hi: 0x9d}, + {value: 0x0a72, lo: 0x9e, hi: 0xae}, + {value: 0x0ab8, lo: 0xaf, hi: 0xaf}, + {value: 0x0abe, lo: 0xb0, hi: 0xb8}, + {value: 0x0ae4, lo: 0xb9, hi: 0xb9}, + {value: 0x0aea, lo: 0xba, hi: 0xbf}, + // Block 0x1f, offset 0x20 + {value: 0x0004, lo: 0x01}, + {value: 0x142e, lo: 0x80, hi: 0x81}, + // Block 0x20, offset 0x21 + {value: 0x0000, lo: 0x03}, + {value: 0x14d6, lo: 0xa6, hi: 0xa6}, + {value: 0x091c, lo: 0xaa, hi: 0xaa}, + {value: 0x0046, lo: 0xab, hi: 0xab}, + // Block 0x21, offset 0x22 + {value: 0x0006, lo: 0x02}, + {value: 0x159f, lo: 0x9a, hi: 0x9b}, + {value: 0x15ab, lo: 0xae, hi: 0xae}, + // Block 0x22, offset 0x23 + {value: 0x0006, lo: 0x01}, + {value: 0x15b1, lo: 0x8d, hi: 0x8f}, + // Block 0x23, offset 0x24 + {value: 0x0006, lo: 0x05}, + {value: 0x15c3, lo: 0x84, hi: 0x84}, + {value: 0x15c9, lo: 0x89, hi: 0x89}, + {value: 0x15cf, lo: 0x8c, hi: 0x8c}, + {value: 0x15d5, lo: 0xa4, hi: 0xa4}, + {value: 0x15db, lo: 0xa6, hi: 0xa6}, + // Block 0x24, offset 0x25 + {value: 0x0006, lo: 0x0b}, + {value: 0x1603, lo: 0x81, hi: 0x81}, + {value: 0x1609, lo: 0x84, hi: 0x84}, + {value: 0x160f, lo: 0x87, hi: 0x87}, + {value: 0x1615, lo: 0x89, hi: 0x89}, + {value: 0x161b, lo: 0xa0, hi: 0xa0}, + {value: 0x161f, lo: 0xa2, hi: 0xa2}, + {value: 0x1625, lo: 0xad, hi: 0xae}, + {value: 0x162f, lo: 0xaf, hi: 0xaf}, + {value: 0x1633, lo: 0xb0, hi: 0xb1}, + {value: 0x163f, lo: 0xb4, hi: 0xb5}, + {value: 0x164b, lo: 0xb8, hi: 0xb9}, + // Block 0x25, offset 0x26 + {value: 0x0006, lo: 0x04}, + {value: 0x1657, lo: 0x80, hi: 0x81}, + {value: 0x1663, lo: 0x84, hi: 0x85}, + {value: 0x166f, lo: 0x88, hi: 0x89}, + {value: 0x167b, lo: 0xac, hi: 0xaf}, + // Block 0x26, offset 0x27 + {value: 0x0006, lo: 0x02}, + {value: 0x1693, lo: 0xa0, hi: 0xa3}, + {value: 0x16ab, lo: 0xaa, hi: 0xad}, + // Block 0x27, offset 0x28 + {value: 0x0004, lo: 0x01}, + {value: 0x16c3, lo: 0xa9, hi: 0xaa}, + // Block 0x28, offset 0x29 + {value: 0x0000, lo: 0x01}, + {value: 0x1814, lo: 0x9c, hi: 0x9c}, + // Block 0x29, offset 0x2a + {value: 0x0007, lo: 0x0c}, + {value: 0x1c39, lo: 0x94, hi: 0x94}, + {value: 0x1c4a, lo: 0x9e, hi: 0x9e}, + {value: 0x1c58, lo: 0xac, hi: 0xac}, + {value: 0x1c5f, lo: 0xae, hi: 0xae}, + {value: 0x1c66, lo: 0xb0, hi: 0xb0}, + {value: 0x1c6d, lo: 0xb2, hi: 0xb2}, + {value: 0x1c74, lo: 0xb4, hi: 0xb4}, + {value: 0x1c7b, lo: 0xb6, hi: 0xb6}, + {value: 0x1c82, lo: 0xb8, hi: 0xb8}, + {value: 0x1c89, lo: 0xba, hi: 0xba}, + {value: 0x1c90, lo: 0xbc, hi: 0xbc}, + {value: 0x1c97, lo: 0xbe, hi: 0xbe}, + // Block 0x2a, offset 0x2b + {value: 0x0007, lo: 0x0d}, + {value: 0x1c9e, lo: 0x80, hi: 0x80}, + {value: 0x1ca5, lo: 0x82, hi: 0x82}, + {value: 0x1cac, lo: 0x85, hi: 0x85}, + {value: 0x1cb3, lo: 0x87, hi: 0x87}, + {value: 0x1cba, lo: 0x89, hi: 0x89}, + {value: 0x1cc1, lo: 0x90, hi: 0x91}, + {value: 0x1ccf, lo: 0x93, hi: 0x94}, + {value: 0x1cdd, lo: 0x96, hi: 0x97}, + {value: 0x1ceb, lo: 0x99, hi: 0x9a}, + {value: 0x1cf9, lo: 0x9c, hi: 0x9d}, + {value: 0x1d07, lo: 0xb4, hi: 0xb4}, + {value: 0x1d0e, lo: 0xb7, hi: 0xba}, + {value: 0x1d2a, lo: 0xbe, hi: 0xbe}, + // Block 0x2b, offset 0x2c + {value: 0x0004, lo: 0x0a}, + {value: 0x2a81, lo: 0x80, hi: 0x81}, + {value: 0x1a9e, lo: 0x82, hi: 0x82}, + {value: 0x2a89, lo: 0x83, hi: 0x86}, + {value: 0x1b76, lo: 0x87, hi: 0x87}, + {value: 0x1b76, lo: 0x88, hi: 0x88}, + {value: 0x2a99, lo: 0x89, hi: 0x89}, + {value: 0x1abe, lo: 0x8a, hi: 0x8a}, + {value: 0x2a9d, lo: 0x8b, hi: 0xb3}, + {value: 0x1a16, lo: 0xb4, hi: 0xb4}, + {value: 0x2b41, lo: 0xb5, hi: 0xbf}, + // Block 0x2c, offset 0x2d + {value: 0x0004, lo: 0x06}, + {value: 0x1b3a, lo: 0x80, hi: 0x80}, + {value: 0x2b6d, lo: 0x81, hi: 0x9b}, + {value: 0x2ac1, lo: 0x9c, hi: 0x9c}, + {value: 0x2bd9, lo: 0x9d, hi: 0xb0}, + {value: 0x1aa6, lo: 0xb1, hi: 0xb1}, + {value: 0x2c29, lo: 0xb2, hi: 0xbf}, + // Block 0x2d, offset 0x2e + {value: 0x0004, lo: 0x0a}, + {value: 0x2c61, lo: 0x80, hi: 0x80}, + {value: 0x18ba, lo: 0x81, hi: 0x81}, + {value: 0x2c65, lo: 0x82, hi: 0x89}, + {value: 0x186e, lo: 0x8a, hi: 0x8a}, + {value: 0x2c85, lo: 0x8b, hi: 0xa0}, + {value: 0x2c21, lo: 0xa1, hi: 0xa1}, + {value: 0x2cdd, lo: 0xa2, hi: 0xa9}, + {value: 0x2be1, lo: 0xaa, hi: 0xaa}, + {value: 0x2cfd, lo: 0xab, hi: 0xbe}, + {value: 0x2ac1, lo: 0xbf, hi: 0xbf}, + // Block 0x2e, offset 0x2f + {value: 0x0004, lo: 0x0b}, + {value: 0x2d4d, lo: 0x80, hi: 0x83}, + {value: 0x1b72, lo: 0x84, hi: 0x84}, + {value: 0x2d5d, lo: 0x85, hi: 0x90}, + {value: 0x2173, lo: 0x91, hi: 0x91}, + {value: 0x2d8d, lo: 0x92, hi: 0x9a}, + {value: 0x2be9, lo: 0x9b, hi: 0x9b}, + {value: 0x2db1, lo: 0x9c, hi: 0xa8}, + {value: 0x1aba, lo: 0xa9, hi: 0xa9}, + {value: 0x2de5, lo: 0xaa, hi: 0xb6}, + {value: 0x19f6, lo: 0xb7, hi: 0xb7}, + {value: 0x2e19, lo: 0xb8, hi: 0xbf}, + // Block 0x2f, offset 0x30 + {value: 0x0004, lo: 0x10}, + {value: 0x2e39, lo: 0x80, hi: 0x87}, + {value: 0x1a62, lo: 0x88, hi: 0x88}, + {value: 0x2e59, lo: 0x89, hi: 0x89}, + {value: 0x1a6e, lo: 0x8a, hi: 0x8a}, + {value: 0x2e5d, lo: 0x8b, hi: 0x8d}, + {value: 0x2e69, lo: 0x90, hi: 0x90}, + {value: 0x2e6d, lo: 0x92, hi: 0x92}, + {value: 0x2e71, lo: 0x95, hi: 0x9d}, + {value: 0x1a12, lo: 0x9e, hi: 0x9e}, + {value: 0x2e95, lo: 0xa0, hi: 0xa0}, + {value: 0x2e99, lo: 0xa2, hi: 0xa2}, + {value: 0x2e9d, lo: 0xa5, hi: 0xa6}, + {value: 0x2ea5, lo: 0xaa, hi: 0xad}, + {value: 0x2eb5, lo: 0xb0, hi: 0xbb}, + {value: 0x18d6, lo: 0xbc, hi: 0xbc}, + {value: 0x2ee5, lo: 0xbd, hi: 0xbf}, + // Block 0x30, offset 0x31 + {value: 0x0004, lo: 0x10}, + {value: 0x2ef1, lo: 0x80, hi: 0x8b}, + {value: 0x2187, lo: 0x8c, hi: 0x8c}, + {value: 0x2f21, lo: 0x8d, hi: 0x90}, + {value: 0x2197, lo: 0x91, hi: 0x91}, + {value: 0x2f31, lo: 0x92, hi: 0x96}, + {value: 0x2cb1, lo: 0x97, hi: 0x97}, + {value: 0x2f45, lo: 0x98, hi: 0x9d}, + {value: 0x2f59, lo: 0x9e, hi: 0xa6}, + {value: 0x2e9d, lo: 0xa7, hi: 0xa7}, + {value: 0x2f7d, lo: 0xa8, hi: 0xac}, + {value: 0x2f92, lo: 0xad, hi: 0xad}, + {value: 0x2f96, lo: 0xb0, hi: 0xb7}, + {value: 0x2ecd, lo: 0xb8, hi: 0xb8}, + {value: 0x2fb6, lo: 0xb9, hi: 0xbb}, + {value: 0x2e69, lo: 0xbc, hi: 0xbc}, + {value: 0x2fc2, lo: 0xbd, hi: 0xbf}, + // Block 0x31, offset 0x32 + {value: 0x0005, lo: 0x07}, + {value: 0x3105, lo: 0x9d, hi: 0x9d}, + {value: 0x310a, lo: 0x9f, hi: 0x9f}, + {value: 0x3124, lo: 0xaa, hi: 0xac}, + {value: 0x3135, lo: 0xad, hi: 0xad}, + {value: 0x313c, lo: 0xae, hi: 0xb6}, + {value: 0x3169, lo: 0xb8, hi: 0xbc}, + {value: 0x3182, lo: 0xbe, hi: 0xbe}, + // Block 0x32, offset 0x33 + {value: 0x0005, lo: 0x03}, + {value: 0x3187, lo: 0x80, hi: 0x81}, + {value: 0x3191, lo: 0x83, hi: 0x84}, + {value: 0x319b, lo: 0x86, hi: 0x8e}, + // Block 0x33, offset 0x34 + {value: 0x0009, lo: 0x03}, + {value: 0x3a73, lo: 0x9a, hi: 0x9a}, + {value: 0x3a7c, lo: 0x9c, hi: 0x9c}, + {value: 0x3a85, lo: 0xab, hi: 0xab}, + // Block 0x34, offset 0x35 + {value: 0x000d, lo: 0x03}, + {value: 0x3a8e, lo: 0x9e, hi: 0x9e}, + {value: 0x3a97, lo: 0x9f, hi: 0x9f}, + {value: 0x3aa0, lo: 0xa0, hi: 0xa4}, + // Block 0x35, offset 0x36 + {value: 0x0009, lo: 0x03}, + {value: 0x3ae1, lo: 0xbb, hi: 0xbd}, + {value: 0x3b00, lo: 0xbe, hi: 0xbe}, + {value: 0x3b0d, lo: 0xbf, hi: 0xbf}, + // Block 0x36, offset 0x37 + {value: 0x0000, lo: 0x01}, + {value: 0x3b1a, lo: 0x80, hi: 0x80}, + // Block 0x37, offset 0x38 + {value: 0x0004, lo: 0x0d}, + {value: 0x4463, lo: 0x80, hi: 0x81}, + {value: 0x446c, lo: 0x82, hi: 0x89}, + {value: 0x30a2, lo: 0x8a, hi: 0x8a}, + {value: 0x448d, lo: 0x8b, hi: 0x90}, + {value: 0x44a6, lo: 0x91, hi: 0x92}, + {value: 0x44af, lo: 0x93, hi: 0x93}, + {value: 0x44b4, lo: 0x94, hi: 0x94}, + {value: 0x1b42, lo: 0x95, hi: 0x95}, + {value: 0x44b9, lo: 0x96, hi: 0x96}, + {value: 0x1b52, lo: 0x97, hi: 0x97}, + {value: 0x44bd, lo: 0x98, hi: 0x9b}, + {value: 0x1b66, lo: 0x9c, hi: 0x9c}, + {value: 0x44cd, lo: 0x9d, hi: 0x9d}, } // nfcDecompLookup: 832 bytes @@ -3038,37 +3125,37 @@ var nfcDecompLookup = [832]uint8{ // Block 0x1, offset 0x40 // Block 0x2, offset 0x80 // Block 0x3, offset 0xc0 - 0x0c3: 0x03, 0x0c4: 0x04, 0x0c5: 0x05, 0x0c6: 0x06, 0x0c7: 0x07, - 0x0c8: 0x08, 0x0cd: 0x09, 0x0ce: 0x0a, 0x0cf: 0x0b, - 0x0d0: 0x0c, 0x0d1: 0x0d, 0x0d3: 0x0e, - 0x0d8: 0x0f, 0x0db: 0x10, + 0x0c3: 0x16, 0x0c4: 0x17, 0x0c5: 0x18, 0x0c6: 0x19, 0x0c7: 0x03, + 0x0c8: 0x1a, 0x0cd: 0x1b, 0x0ce: 0x1c, 0x0cf: 0x1d, + 0x0d0: 0x1e, 0x0d1: 0x1f, 0x0d3: 0x20, + 0x0d8: 0x21, 0x0db: 0x22, 0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07, 0x0ef: 0x08, 0x0f0: 0x0c, // Block 0x4, offset 0x100 - 0x124: 0x11, 0x125: 0x12, 0x127: 0x13, - 0x128: 0x14, 0x129: 0x15, 0x12d: 0x16, 0x12e: 0x17, 0x12f: 0x18, - 0x131: 0x19, 0x133: 0x1a, 0x135: 0x1b, 0x137: 0x1c, - 0x13d: 0x1d, 0x13e: 0x1e, + 0x124: 0x23, 0x125: 0x24, 0x127: 0x25, + 0x128: 0x26, 0x129: 0x27, 0x12d: 0x28, 0x12e: 0x29, 0x12f: 0x2a, + 0x131: 0x2b, 0x133: 0x2c, 0x135: 0x2d, 0x137: 0x2e, + 0x13d: 0x2f, 0x13e: 0x30, // Block 0x5, offset 0x140 - 0x140: 0x1f, - 0x16c: 0x20, 0x16d: 0x21, - 0x178: 0x22, 0x179: 0x23, 0x17a: 0x24, 0x17b: 0x25, 0x17c: 0x26, 0x17d: 0x27, 0x17e: 0x28, 0x17f: 0x29, + 0x140: 0x31, + 0x16c: 0x32, 0x16d: 0x33, + 0x178: 0x34, 0x179: 0x04, 0x17a: 0x05, 0x17b: 0x06, 0x17c: 0x07, 0x17d: 0x08, 0x17e: 0x09, 0x17f: 0x0a, // Block 0x6, offset 0x180 - 0x180: 0x2a, 0x184: 0x2b, 0x186: 0x2c, 0x187: 0x2d, - 0x188: 0x2e, 0x189: 0x2f, 0x18a: 0x30, 0x18b: 0x31, 0x18c: 0x32, - 0x1ab: 0x33, + 0x180: 0x35, 0x184: 0x36, 0x186: 0x37, 0x187: 0x38, + 0x188: 0x39, 0x189: 0x3a, 0x18a: 0x3b, 0x18b: 0x3c, 0x18c: 0x3d, + 0x1ab: 0x3e, // Block 0x7, offset 0x1c0 - 0x1c1: 0x34, 0x1c2: 0x35, 0x1c3: 0x36, + 0x1c1: 0x0b, 0x1c2: 0x3f, 0x1c3: 0x40, // Block 0x8, offset 0x200 - 0x224: 0x37, 0x225: 0x38, 0x226: 0x39, 0x227: 0x3a, - 0x228: 0x3b, 0x229: 0x3c, 0x22a: 0x3d, 0x22b: 0x3e, 0x22c: 0x3f, 0x22d: 0x40, + 0x224: 0x41, 0x225: 0x42, 0x226: 0x43, 0x227: 0x44, + 0x228: 0x45, 0x229: 0x46, 0x22a: 0x0c, 0x22b: 0x0d, 0x22c: 0x47, 0x22d: 0x48, // Block 0x9, offset 0x240 - 0x242: 0x41, + 0x242: 0x49, // Block 0xa, offset 0x280 - 0x285: 0x42, 0x286: 0x43, 0x287: 0x44, + 0x285: 0x4a, 0x286: 0x4b, 0x287: 0x4c, // Block 0xb, offset 0x2c0 - 0x2e0: 0x45, 0x2e1: 0x46, 0x2e2: 0x47, 0x2e3: 0x48, 0x2e4: 0x49, 0x2e5: 0x4a, 0x2e6: 0x4b, 0x2e7: 0x4c, + 0x2e0: 0x0e, 0x2e1: 0x0f, 0x2e2: 0x10, 0x2e3: 0x11, 0x2e4: 0x12, 0x2e5: 0x13, 0x2e6: 0x14, 0x2e7: 0x15, 0x2e8: 0x4d, // Block 0xc, offset 0x300 0x311: 0x09, @@ -3076,1288 +3163,1442 @@ var nfcDecompLookup = [832]uint8{ 0x32f: 0x0b, } -var nfcDecompTrie = trie{nfcDecompLookup[:], nfcDecompValues[:]} +var nfcDecompTrie = trie{nfcDecompLookup[:], nfcDecompValues[:], nfcDecompSparseValues[:], nfcDecompSparseOffset[:], 22} -// nfkcDecompValues: 10176 entries, 20352 bytes +// nfkcDecompValues: 4224 entries, 8448 bytes // Block 2 is the null block. -var nfkcDecompValues = [10176]uint16{ +var nfkcDecompValues = [4224]uint16{ // Block 0x0, offset 0x0 // Block 0x1, offset 0x40 // Block 0x2, offset 0x80 // Block 0x3, offset 0xc0 - 0x00e0: 0x0001, - 0x00e8: 0x0003, - 0x00ea: 0x0007, 0x00ef: 0x0009, - 0x00f2: 0x000d, 0x00f3: 0x000f, 0x00f4: 0x0011, 0x00f5: 0x0015, - 0x00f8: 0x0018, 0x00f9: 0x001c, 0x00fa: 0x001e, - 0x00fc: 0x0020, 0x00fd: 0x0026, 0x00fe: 0x002c, + 0x00c4: 0x02da, 0x00c5: 0x02df, + 0x00c6: 0x02e4, 0x00c7: 0x02e9, 0x00c8: 0x02ec, 0x00c9: 0x02ef, 0x00ca: 0x02f2, 0x00cb: 0x02f5, + 0x00cc: 0x02f8, 0x00cd: 0x02fb, 0x00ce: 0x02ff, 0x00cf: 0x0303, 0x00d0: 0x0307, 0x00d1: 0x030b, + 0x00d2: 0x030f, 0x00d3: 0x0313, 0x00d4: 0x0317, 0x00d5: 0x031b, 0x00d6: 0x0321, 0x00d7: 0x0327, + 0x00d8: 0x032d, 0x00d9: 0x0333, 0x00da: 0x0339, 0x00db: 0x033f, 0x00dc: 0x0345, + 0x00de: 0x034b, 0x00df: 0x0351, 0x00e0: 0x0357, 0x00e1: 0x035d, 0x00e2: 0x0363, 0x00e3: 0x0368, + 0x00e6: 0x036d, 0x00e7: 0x0371, 0x00e8: 0x0375, 0x00e9: 0x0379, + 0x00ea: 0x037d, 0x00eb: 0x0381, 0x00ec: 0x0385, 0x00ed: 0x038b, 0x00ee: 0x0391, 0x00ef: 0x0396, + 0x00f0: 0x039b, 0x00f1: 0x039f, 0x00f2: 0x03a2, 0x00f3: 0x03a5, 0x00f4: 0x03a8, 0x00f5: 0x03ac, + 0x00f8: 0x03b0, 0x00f9: 0x03b4, 0x00fa: 0x03b8, 0x00fb: 0x03be, + 0x00fc: 0x03c4, 0x00fd: 0x03c9, 0x00fe: 0x03ce, 0x00ff: 0x03d3, // Block 0x4, offset 0x100 - 0x0100: 0x0032, 0x0101: 0x0036, 0x0102: 0x003a, 0x0103: 0x003e, 0x0104: 0x0042, 0x0105: 0x0046, - 0x0107: 0x004a, 0x0108: 0x004e, 0x0109: 0x0052, 0x010a: 0x0056, 0x010b: 0x005a, - 0x010c: 0x005e, 0x010d: 0x0062, 0x010e: 0x0066, 0x010f: 0x006a, 0x0111: 0x006e, - 0x0112: 0x0072, 0x0113: 0x0076, 0x0114: 0x007a, 0x0115: 0x007e, 0x0116: 0x0082, - 0x0119: 0x0086, 0x011a: 0x008a, 0x011b: 0x008e, 0x011c: 0x0092, 0x011d: 0x0096, - 0x0120: 0x009a, 0x0121: 0x009e, 0x0122: 0x00a2, 0x0123: 0x00a6, - 0x0124: 0x00aa, 0x0125: 0x00ae, 0x0127: 0x00b2, 0x0128: 0x00b6, 0x0129: 0x00ba, - 0x012a: 0x00be, 0x012b: 0x00c2, 0x012c: 0x00c6, 0x012d: 0x00ca, 0x012e: 0x00ce, 0x012f: 0x00d2, - 0x0131: 0x00d6, 0x0132: 0x00da, 0x0133: 0x00de, 0x0134: 0x00e2, 0x0135: 0x00e6, - 0x0136: 0x00ea, 0x0139: 0x00ee, 0x013a: 0x00f2, 0x013b: 0x00f6, - 0x013c: 0x00fa, 0x013d: 0x00fe, 0x013f: 0x0102, + 0x0100: 0x092d, 0x0101: 0x092f, 0x0102: 0x0931, 0x0103: 0x0007, 0x0104: 0x0933, 0x0105: 0x0936, + 0x0106: 0x0939, 0x0107: 0x093d, 0x0108: 0x093f, 0x0109: 0x0941, 0x010a: 0x0943, 0x010b: 0x0946, + 0x010c: 0x0949, 0x010d: 0x094c, 0x010f: 0x094e, 0x0110: 0x0950, 0x0111: 0x0952, + 0x0112: 0x001e, 0x0113: 0x0955, 0x0114: 0x0958, 0x0115: 0x095c, 0x0116: 0x0960, 0x0117: 0x0962, + 0x0118: 0x0964, 0x0119: 0x0966, 0x011a: 0x096a, 0x011b: 0x096d, 0x011c: 0x096f, 0x011d: 0x0559, + 0x011e: 0x0973, 0x011f: 0x0976, 0x0120: 0x056c, 0x0121: 0x0979, 0x0122: 0x097c, 0x0123: 0x049b, + 0x0124: 0x0964, 0x0125: 0x096d, 0x0126: 0x0559, 0x0127: 0x0973, 0x0128: 0x0575, 0x0129: 0x056c, + 0x012a: 0x0979, + 0x0138: 0x097e, // Block 0x5, offset 0x140 - 0x0140: 0x0106, 0x0141: 0x010a, 0x0142: 0x010e, 0x0143: 0x0112, 0x0144: 0x0116, 0x0145: 0x011a, - 0x0146: 0x011e, 0x0147: 0x0122, 0x0148: 0x0126, 0x0149: 0x012a, 0x014a: 0x012e, 0x014b: 0x0132, - 0x014c: 0x0136, 0x014d: 0x013a, 0x014e: 0x013e, 0x014f: 0x0142, - 0x0152: 0x0146, 0x0153: 0x014a, 0x0154: 0x014e, 0x0155: 0x0152, 0x0156: 0x0156, 0x0157: 0x015a, - 0x0158: 0x015e, 0x0159: 0x0162, 0x015a: 0x0166, 0x015b: 0x016a, 0x015c: 0x016e, 0x015d: 0x0172, - 0x015e: 0x0176, 0x015f: 0x017a, 0x0160: 0x017e, 0x0161: 0x0182, 0x0162: 0x0186, 0x0163: 0x018a, - 0x0164: 0x018e, 0x0165: 0x0192, 0x0168: 0x0196, 0x0169: 0x019a, - 0x016a: 0x019e, 0x016b: 0x01a2, 0x016c: 0x01a6, 0x016d: 0x01aa, 0x016e: 0x01ae, 0x016f: 0x01b2, - 0x0170: 0x01b6, 0x0172: 0x01ba, 0x0173: 0x01bd, 0x0174: 0x01c0, 0x0175: 0x01c4, - 0x0176: 0x01c8, 0x0177: 0x01cc, 0x0179: 0x01d0, 0x017a: 0x01d4, 0x017b: 0x01d8, - 0x017c: 0x01dc, 0x017d: 0x01e0, 0x017e: 0x01e4, 0x017f: 0x01e8, + 0x0140: 0x0b02, 0x0141: 0x0b06, 0x0142: 0x0b0a, 0x0143: 0x0b0e, 0x0144: 0x0b12, 0x0145: 0x0b16, + 0x0146: 0x0b1a, 0x0147: 0x0b1e, 0x0148: 0x0b22, 0x0149: 0x0b26, 0x014a: 0x0b2a, 0x014b: 0x0b2e, + 0x014c: 0x0b32, 0x014d: 0x0b38, 0x014e: 0x0b3e, 0x014f: 0x0b44, 0x0150: 0x0b4a, 0x0151: 0x0b50, + 0x0152: 0x0b56, 0x0153: 0x0b5c, 0x0154: 0x0b62, 0x0155: 0x0b66, 0x0156: 0x0b6a, 0x0157: 0x0b6e, + 0x0158: 0x0b72, 0x0159: 0x0b76, 0x015a: 0x0b7a, 0x015b: 0x0b7e, 0x015c: 0x0b82, 0x015d: 0x0b88, + 0x015e: 0x0b8e, 0x015f: 0x0b92, 0x0160: 0x0b96, 0x0161: 0x0b9a, 0x0162: 0x0b9e, 0x0163: 0x0ba2, + 0x0164: 0x0ba6, 0x0165: 0x0bac, 0x0166: 0x0bb2, 0x0167: 0x0bb8, 0x0168: 0x0bbe, 0x0169: 0x0bc4, + 0x016a: 0x0bca, 0x016b: 0x0bce, 0x016c: 0x0bd2, 0x016d: 0x0bd6, 0x016e: 0x0bda, 0x016f: 0x0bde, + 0x0170: 0x0be2, 0x0171: 0x0be6, 0x0172: 0x0bea, 0x0173: 0x0bee, 0x0174: 0x0bf2, 0x0175: 0x0bf6, + 0x0176: 0x0bfa, 0x0177: 0x0bfe, 0x0178: 0x0c02, 0x0179: 0x0c08, 0x017a: 0x0c0e, 0x017b: 0x0c14, + 0x017c: 0x0c1a, 0x017d: 0x0c1e, 0x017e: 0x0c22, 0x017f: 0x0c26, // Block 0x6, offset 0x180 - 0x0180: 0x01ec, 0x0183: 0x01f0, 0x0184: 0x01f4, 0x0185: 0x01f8, - 0x0186: 0x01fc, 0x0187: 0x0200, 0x0188: 0x0204, 0x0189: 0x0208, - 0x018c: 0x020c, 0x018d: 0x0210, 0x018e: 0x0214, 0x018f: 0x0218, 0x0190: 0x021c, 0x0191: 0x0220, - 0x0194: 0x0224, 0x0195: 0x0228, 0x0196: 0x022c, 0x0197: 0x0230, - 0x0198: 0x0234, 0x0199: 0x0238, 0x019a: 0x023c, 0x019b: 0x0240, 0x019c: 0x0244, 0x019d: 0x0248, - 0x019e: 0x024c, 0x019f: 0x0250, 0x01a0: 0x0254, 0x01a1: 0x0258, 0x01a2: 0x025c, 0x01a3: 0x0260, - 0x01a4: 0x0264, 0x01a5: 0x0268, 0x01a8: 0x026c, 0x01a9: 0x0270, - 0x01aa: 0x0274, 0x01ab: 0x0278, 0x01ac: 0x027c, 0x01ad: 0x0280, 0x01ae: 0x0284, 0x01af: 0x0288, - 0x01b0: 0x028c, 0x01b1: 0x0290, 0x01b2: 0x0294, 0x01b3: 0x0298, 0x01b4: 0x029c, 0x01b5: 0x02a0, - 0x01b6: 0x02a4, 0x01b7: 0x02a8, 0x01b8: 0x02ac, 0x01b9: 0x02b0, 0x01ba: 0x02b4, 0x01bb: 0x02b8, - 0x01bc: 0x02bc, 0x01bd: 0x02c0, 0x01be: 0x02c4, 0x01bf: 0x02c8, + 0x0180: 0x0c2a, 0x0181: 0x0c2e, 0x0182: 0x0c32, 0x0183: 0x0c36, 0x0184: 0x0c3a, 0x0185: 0x0c3e, + 0x0186: 0x0c42, 0x0187: 0x0c46, 0x0188: 0x0c4a, 0x0189: 0x0c4e, 0x018a: 0x0c52, 0x018b: 0x0c56, + 0x018c: 0x0c5a, 0x018d: 0x0c5e, 0x018e: 0x0c62, 0x018f: 0x0c66, 0x0190: 0x0c6a, 0x0191: 0x0c6e, + 0x0192: 0x0c72, 0x0193: 0x0c76, 0x0194: 0x0c7a, 0x0195: 0x0c7e, 0x0196: 0x0c82, 0x0197: 0x0c86, + 0x0198: 0x0c8a, 0x0199: 0x0c8e, 0x019a: 0x0c92, 0x019b: 0x0b9a, + 0x01a0: 0x0c9b, 0x01a1: 0x0c9f, 0x01a2: 0x0ca3, 0x01a3: 0x0ca7, + 0x01a4: 0x0cab, 0x01a5: 0x0cb1, 0x01a6: 0x0cb7, 0x01a7: 0x0cbd, 0x01a8: 0x0cc3, 0x01a9: 0x0cc9, + 0x01aa: 0x0ccf, 0x01ab: 0x0cd5, 0x01ac: 0x0cdb, 0x01ad: 0x0ce1, 0x01ae: 0x0ce7, 0x01af: 0x0ced, + 0x01b0: 0x0cf3, 0x01b1: 0x0cf9, 0x01b2: 0x0cff, 0x01b3: 0x0d05, 0x01b4: 0x0d0b, 0x01b5: 0x0d11, + 0x01b6: 0x0d17, 0x01b7: 0x0d1d, 0x01b8: 0x0d23, 0x01b9: 0x0d27, 0x01ba: 0x0d2b, 0x01bb: 0x0d2f, + 0x01bc: 0x0d33, 0x01bd: 0x0d37, 0x01be: 0x0d3b, 0x01bf: 0x0d41, // Block 0x7, offset 0x1c0 - 0x01e0: 0x02ca, 0x01e1: 0x02ce, - 0x01ef: 0x02d2, - 0x01f0: 0x02d6, + 0x01c0: 0x0d47, 0x01c1: 0x0d4d, 0x01c2: 0x0d53, 0x01c3: 0x0d59, 0x01c4: 0x0d5f, 0x01c5: 0x0d65, + 0x01c6: 0x0d6b, 0x01c7: 0x0d71, 0x01c8: 0x0d77, 0x01c9: 0x0d7b, 0x01ca: 0x0d7f, 0x01cb: 0x0d83, + 0x01cc: 0x0d87, 0x01cd: 0x0d8b, 0x01ce: 0x0d8f, 0x01cf: 0x0d93, 0x01d0: 0x0d97, 0x01d1: 0x0d9d, + 0x01d2: 0x0da3, 0x01d3: 0x0da9, 0x01d4: 0x0daf, 0x01d5: 0x0db5, 0x01d6: 0x0dbb, 0x01d7: 0x0dc1, + 0x01d8: 0x0dc7, 0x01d9: 0x0dcd, 0x01da: 0x0dd3, 0x01db: 0x0dd9, 0x01dc: 0x0ddf, 0x01dd: 0x0de5, + 0x01de: 0x0deb, 0x01df: 0x0df1, 0x01e0: 0x0df7, 0x01e1: 0x0dfd, 0x01e2: 0x0e03, 0x01e3: 0x0e09, + 0x01e4: 0x0e0f, 0x01e5: 0x0e13, 0x01e6: 0x0e17, 0x01e7: 0x0e1b, 0x01e8: 0x0e1f, 0x01e9: 0x0e25, + 0x01ea: 0x0e2b, 0x01eb: 0x0e31, 0x01ec: 0x0e37, 0x01ed: 0x0e3d, 0x01ee: 0x0e43, 0x01ef: 0x0e49, + 0x01f0: 0x0e4f, 0x01f1: 0x0e55, 0x01f2: 0x0e5b, 0x01f3: 0x0e5f, 0x01f4: 0x0e63, 0x01f5: 0x0e67, + 0x01f6: 0x0e6b, 0x01f7: 0x0e6f, 0x01f8: 0x0e73, 0x01f9: 0x0e77, // Block 0x8, offset 0x200 - 0x0204: 0x02da, 0x0205: 0x02df, - 0x0206: 0x02e4, 0x0207: 0x02e9, 0x0208: 0x02ec, 0x0209: 0x02ef, 0x020a: 0x02f2, 0x020b: 0x02f5, - 0x020c: 0x02f8, 0x020d: 0x02fb, 0x020e: 0x02ff, 0x020f: 0x0303, 0x0210: 0x0307, 0x0211: 0x030b, - 0x0212: 0x030f, 0x0213: 0x0313, 0x0214: 0x0317, 0x0215: 0x031b, 0x0216: 0x0321, 0x0217: 0x0327, - 0x0218: 0x032d, 0x0219: 0x0333, 0x021a: 0x0339, 0x021b: 0x033f, 0x021c: 0x0345, - 0x021e: 0x034b, 0x021f: 0x0351, 0x0220: 0x0357, 0x0221: 0x035d, 0x0222: 0x0363, 0x0223: 0x0368, - 0x0226: 0x036d, 0x0227: 0x0371, 0x0228: 0x0375, 0x0229: 0x0379, - 0x022a: 0x037d, 0x022b: 0x0381, 0x022c: 0x0385, 0x022d: 0x038b, 0x022e: 0x0391, 0x022f: 0x0396, - 0x0230: 0x039b, 0x0231: 0x039f, 0x0232: 0x03a2, 0x0233: 0x03a5, 0x0234: 0x03a8, 0x0235: 0x03ac, - 0x0238: 0x03b0, 0x0239: 0x03b4, 0x023a: 0x03b8, 0x023b: 0x03be, - 0x023c: 0x03c4, 0x023d: 0x03c9, 0x023e: 0x03ce, 0x023f: 0x03d3, + 0x0200: 0x0e7b, 0x0201: 0x0e80, 0x0202: 0x0e85, 0x0203: 0x0e8c, 0x0204: 0x0e93, 0x0205: 0x0e9a, + 0x0206: 0x0ea1, 0x0207: 0x0ea8, 0x0208: 0x0eaf, 0x0209: 0x0eb4, 0x020a: 0x0eb9, 0x020b: 0x0ec0, + 0x020c: 0x0ec7, 0x020d: 0x0ece, 0x020e: 0x0ed5, 0x020f: 0x0edc, 0x0210: 0x0ee3, 0x0211: 0x0ee8, + 0x0212: 0x0eed, 0x0213: 0x0ef4, 0x0214: 0x0efb, 0x0215: 0x0f02, + 0x0218: 0x0f09, 0x0219: 0x0f0e, 0x021a: 0x0f13, 0x021b: 0x0f1a, 0x021c: 0x0f21, 0x021d: 0x0f28, + 0x0220: 0x0f2f, 0x0221: 0x0f34, 0x0222: 0x0f39, 0x0223: 0x0f40, + 0x0224: 0x0f47, 0x0225: 0x0f4e, 0x0226: 0x0f55, 0x0227: 0x0f5c, 0x0228: 0x0f63, 0x0229: 0x0f68, + 0x022a: 0x0f6d, 0x022b: 0x0f74, 0x022c: 0x0f7b, 0x022d: 0x0f82, 0x022e: 0x0f89, 0x022f: 0x0f90, + 0x0230: 0x0f97, 0x0231: 0x0f9c, 0x0232: 0x0fa1, 0x0233: 0x0fa8, 0x0234: 0x0faf, 0x0235: 0x0fb6, + 0x0236: 0x0fbd, 0x0237: 0x0fc4, 0x0238: 0x0fcb, 0x0239: 0x0fd0, 0x023a: 0x0fd5, 0x023b: 0x0fdc, + 0x023c: 0x0fe3, 0x023d: 0x0fea, 0x023e: 0x0ff1, 0x023f: 0x0ff8, // Block 0x9, offset 0x240 - 0x0240: 0x03d8, 0x0241: 0x03dc, 0x0242: 0x03e0, 0x0243: 0x03e4, 0x0244: 0x03e8, 0x0245: 0x03ec, - 0x0246: 0x03f0, 0x0247: 0x03f4, 0x0248: 0x03f8, 0x0249: 0x03fc, 0x024a: 0x0400, 0x024b: 0x0404, - 0x024c: 0x0408, 0x024d: 0x040c, 0x024e: 0x0410, 0x024f: 0x0414, 0x0250: 0x0418, 0x0251: 0x041c, - 0x0252: 0x0420, 0x0253: 0x0424, 0x0254: 0x0428, 0x0255: 0x042c, 0x0256: 0x0430, 0x0257: 0x0434, - 0x0258: 0x0438, 0x0259: 0x043c, 0x025a: 0x0440, 0x025b: 0x0444, - 0x025e: 0x0448, 0x025f: 0x044c, - 0x0266: 0x0450, 0x0267: 0x0454, 0x0268: 0x0458, 0x0269: 0x045c, - 0x026a: 0x0460, 0x026b: 0x0466, 0x026c: 0x046c, 0x026d: 0x0472, 0x026e: 0x0478, 0x026f: 0x047c, - 0x0270: 0x0480, 0x0271: 0x0486, 0x0272: 0x048c, 0x0273: 0x0490, + 0x0240: 0x0fff, 0x0241: 0x1004, 0x0242: 0x1009, 0x0243: 0x1010, 0x0244: 0x1017, 0x0245: 0x101e, + 0x0248: 0x1025, 0x0249: 0x102a, 0x024a: 0x102f, 0x024b: 0x1036, + 0x024c: 0x103d, 0x024d: 0x1044, 0x0250: 0x104b, 0x0251: 0x1050, + 0x0252: 0x1055, 0x0253: 0x105c, 0x0254: 0x1063, 0x0255: 0x106a, 0x0256: 0x1071, 0x0257: 0x1078, + 0x0259: 0x107f, 0x025b: 0x1084, 0x025d: 0x108b, + 0x025f: 0x1092, 0x0260: 0x1099, 0x0261: 0x109e, 0x0262: 0x10a3, 0x0263: 0x10aa, + 0x0264: 0x10b1, 0x0265: 0x10b8, 0x0266: 0x10bf, 0x0267: 0x10c6, 0x0268: 0x10cd, 0x0269: 0x10d2, + 0x026a: 0x10d7, 0x026b: 0x10de, 0x026c: 0x10e5, 0x026d: 0x10ec, 0x026e: 0x10f3, 0x026f: 0x10fa, + 0x0270: 0x1101, 0x0271: 0x0525, 0x0272: 0x1106, 0x0273: 0x052a, 0x0274: 0x110b, 0x0275: 0x052f, + 0x0276: 0x1110, 0x0277: 0x0534, 0x0278: 0x1115, 0x0279: 0x054a, 0x027a: 0x111a, 0x027b: 0x054f, + 0x027c: 0x111f, 0x027d: 0x0554, // Block 0xa, offset 0x280 - 0x02b0: 0x0494, 0x02b1: 0x0496, 0x02b2: 0x0499, 0x02b3: 0x049b, 0x02b4: 0x049d, 0x02b5: 0x04a0, - 0x02b6: 0x04a3, 0x02b7: 0x04a6, 0x02b8: 0x04a8, + 0x0280: 0x1124, 0x0281: 0x112b, 0x0282: 0x1132, 0x0283: 0x113b, 0x0284: 0x1144, 0x0285: 0x114d, + 0x0286: 0x1156, 0x0287: 0x115f, 0x0288: 0x1168, 0x0289: 0x116f, 0x028a: 0x1176, 0x028b: 0x117f, + 0x028c: 0x1188, 0x028d: 0x1191, 0x028e: 0x119a, 0x028f: 0x11a3, 0x0290: 0x11ac, 0x0291: 0x11b3, + 0x0292: 0x11ba, 0x0293: 0x11c3, 0x0294: 0x11cc, 0x0295: 0x11d5, 0x0296: 0x11de, 0x0297: 0x11e7, + 0x0298: 0x11f0, 0x0299: 0x11f7, 0x029a: 0x11fe, 0x029b: 0x1207, 0x029c: 0x1210, 0x029d: 0x1219, + 0x029e: 0x1222, 0x029f: 0x122b, 0x02a0: 0x1234, 0x02a1: 0x123b, 0x02a2: 0x1242, 0x02a3: 0x124b, + 0x02a4: 0x1254, 0x02a5: 0x125d, 0x02a6: 0x1266, 0x02a7: 0x126f, 0x02a8: 0x1278, 0x02a9: 0x127f, + 0x02aa: 0x1286, 0x02ab: 0x128f, 0x02ac: 0x1298, 0x02ad: 0x12a1, 0x02ae: 0x12aa, 0x02af: 0x12b3, + 0x02b0: 0x12bc, 0x02b1: 0x12c1, 0x02b2: 0x12c6, 0x02b3: 0x12cd, 0x02b4: 0x12d2, + 0x02b6: 0x12d9, 0x02b7: 0x12de, 0x02b8: 0x12e5, 0x02b9: 0x12ea, 0x02ba: 0x12ef, 0x02bb: 0x04ee, + 0x02bc: 0x12f4, 0x02bd: 0x12f9, 0x02be: 0x12fd, 0x02bf: 0x12f9, // Block 0xb, offset 0x2c0 - 0x02d8: 0x04aa, 0x02d9: 0x04ae, 0x02da: 0x04b2, 0x02db: 0x04b6, 0x02dc: 0x04ba, 0x02dd: 0x04be, - 0x02e0: 0x04c2, 0x02e1: 0x04c5, 0x02e2: 0x02c8, 0x02e3: 0x04c7, - 0x02e4: 0x04c9, + 0x02c0: 0x1300, 0x02c1: 0x1309, 0x02c2: 0x130f, 0x02c3: 0x1316, 0x02c4: 0x131b, + 0x02c6: 0x1322, 0x02c7: 0x1327, 0x02c8: 0x132e, 0x02c9: 0x04f6, 0x02ca: 0x1333, 0x02cb: 0x04fb, + 0x02cc: 0x1338, 0x02cd: 0x1343, 0x02ce: 0x134f, 0x02cf: 0x135b, 0x02d0: 0x1361, 0x02d1: 0x1366, + 0x02d2: 0x136b, 0x02d3: 0x0514, 0x02d6: 0x1372, 0x02d7: 0x1377, + 0x02d8: 0x137e, 0x02d9: 0x1383, 0x02da: 0x1388, 0x02db: 0x0500, 0x02dd: 0x1393, + 0x02de: 0x139f, 0x02df: 0x13ab, 0x02e0: 0x13b1, 0x02e1: 0x13b6, 0x02e2: 0x13bb, 0x02e3: 0x0539, + 0x02e4: 0x13c2, 0x02e5: 0x13c7, 0x02e6: 0x13cc, 0x02e7: 0x13d1, 0x02e8: 0x13d8, 0x02e9: 0x13dd, + 0x02ea: 0x13e2, 0x02eb: 0x050a, 0x02ec: 0x13e7, 0x02ed: 0x13f1, 0x02ee: 0x04e8, 0x02ef: 0x13f7, + 0x02f2: 0x13f9, 0x02f3: 0x1400, 0x02f4: 0x1405, + 0x02f6: 0x140c, 0x02f7: 0x1411, 0x02f8: 0x1418, 0x02f9: 0x0505, 0x02fa: 0x141d, 0x02fb: 0x050f, + 0x02fc: 0x1422, 0x02fd: 0x0011, 0x02fe: 0x142a, // Block 0xc, offset 0x300 - 0x0300: 0x04cc, 0x0301: 0x04cf, 0x0303: 0x04d2, 0x0304: 0x04d5, - 0x0334: 0x04da, - 0x033a: 0x04dd, - 0x033e: 0x04e1, + 0x0300: 0x1486, 0x0301: 0x001c, 0x0302: 0x000d, 0x0303: 0x000f, 0x0304: 0x1488, 0x0305: 0x148a, + 0x0306: 0x148c, 0x0307: 0x148e, 0x0308: 0x1490, 0x0309: 0x1492, 0x030a: 0x1494, 0x030b: 0x1496, + 0x030c: 0x149a, 0x030d: 0x149c, 0x030e: 0x149e, 0x0310: 0x0007, 0x0311: 0x0941, + 0x0312: 0x001e, 0x0313: 0x04c7, 0x0314: 0x0943, 0x0315: 0x0494, 0x0316: 0x094e, 0x0317: 0x04c5, + 0x0318: 0x0950, 0x0319: 0x14a0, 0x031a: 0x0960, 0x031b: 0x02c8, 0x031c: 0x0962, + 0x0328: 0x14a2, // Block 0xd, offset 0x340 - 0x0344: 0x0011, 0x0345: 0x04e8, - 0x0346: 0x04ee, 0x0347: 0x04f3, 0x0348: 0x04f6, 0x0349: 0x04fb, 0x034a: 0x0500, - 0x034c: 0x0505, 0x034e: 0x050a, 0x034f: 0x050f, 0x0350: 0x0514, - 0x036a: 0x051b, 0x036b: 0x0520, 0x036c: 0x0525, 0x036d: 0x052a, 0x036e: 0x052f, 0x036f: 0x0534, - 0x0370: 0x0539, + 0x0340: 0x14a5, 0x0341: 0x14a9, 0x0342: 0x14ad, 0x0343: 0x14af, 0x0345: 0x14b3, + 0x0346: 0x14b7, 0x0347: 0x14bb, 0x0349: 0x14be, 0x034a: 0x094c, 0x034b: 0x0916, + 0x034c: 0x0916, 0x034d: 0x0916, 0x034e: 0x0494, 0x034f: 0x14c2, 0x0350: 0x0918, 0x0351: 0x0918, + 0x0352: 0x091e, 0x0353: 0x04c5, 0x0355: 0x0922, 0x0356: 0x14c5, + 0x0359: 0x0929, 0x035a: 0x14c8, 0x035b: 0x092b, 0x035c: 0x092b, 0x035d: 0x092b, + 0x0360: 0x14ca, 0x0361: 0x14cd, 0x0362: 0x14d1, + 0x0364: 0x14d4, 0x0366: 0x14d6, 0x0368: 0x14d4, + 0x036a: 0x091c, 0x036b: 0x0046, 0x036c: 0x090b, 0x036d: 0x14ad, 0x036f: 0x0941, + 0x0370: 0x090f, 0x0371: 0x14d9, 0x0373: 0x0920, 0x0374: 0x001e, 0x0375: 0x14db, + 0x0376: 0x14de, 0x0377: 0x14e1, 0x0378: 0x14e4, 0x0379: 0x097c, 0x037b: 0x14e7, + 0x037c: 0x056f, 0x037d: 0x0973, 0x037e: 0x14eb, 0x037f: 0x14ee, // Block 0xe, offset 0x380 - 0x038a: 0x0540, 0x038b: 0x0545, - 0x038c: 0x054a, 0x038d: 0x054f, 0x038e: 0x0554, 0x0390: 0x0559, 0x0391: 0x055c, - 0x0392: 0x055f, 0x0393: 0x050a, 0x0394: 0x0520, 0x0395: 0x056c, 0x0396: 0x056f, - 0x03b0: 0x0572, 0x03b1: 0x0575, 0x03b2: 0x0578, 0x03b4: 0x057b, 0x03b5: 0x057e, - 0x03b9: 0x0581, + 0x0380: 0x14f1, 0x0385: 0x090d, + 0x0386: 0x093f, 0x0387: 0x0941, 0x0388: 0x097c, 0x0389: 0x0499, + 0x0390: 0x14f5, 0x0391: 0x14fb, + 0x0392: 0x1501, 0x0393: 0x1508, 0x0394: 0x150e, 0x0395: 0x1514, 0x0396: 0x151a, 0x0397: 0x1520, + 0x0398: 0x1526, 0x0399: 0x152c, 0x039a: 0x1532, 0x039b: 0x1538, 0x039c: 0x153e, 0x039d: 0x1544, + 0x039e: 0x154a, 0x039f: 0x1550, 0x03a0: 0x0918, 0x03a1: 0x1555, 0x03a2: 0x1558, 0x03a3: 0x155c, + 0x03a4: 0x155f, 0x03a5: 0x1561, 0x03a6: 0x1564, 0x03a7: 0x1568, 0x03a8: 0x156d, 0x03a9: 0x1570, + 0x03aa: 0x1572, 0x03ab: 0x1575, 0x03ac: 0x091e, 0x03ad: 0x14ad, 0x03ae: 0x090d, 0x03af: 0x0920, + 0x03b0: 0x097c, 0x03b1: 0x1579, 0x03b2: 0x157c, 0x03b3: 0x1580, 0x03b4: 0x096d, 0x03b5: 0x1583, + 0x03b6: 0x1586, 0x03b7: 0x158a, 0x03b8: 0x158f, 0x03b9: 0x04c7, 0x03ba: 0x1592, 0x03bb: 0x1595, + 0x03bc: 0x04c5, 0x03bd: 0x0984, 0x03be: 0x093f, 0x03bf: 0x0950, // Block 0xf, offset 0x3c0 - 0x03c0: 0x0584, 0x03c1: 0x0589, 0x03c3: 0x058e, - 0x03c7: 0x0593, - 0x03cc: 0x0598, 0x03cd: 0x059d, 0x03ce: 0x05a2, - 0x03d9: 0x05a7, - 0x03f9: 0x05ac, + 0x03e0: 0x001c, 0x03e1: 0x000d, 0x03e2: 0x000f, 0x03e3: 0x1488, + 0x03e4: 0x148a, 0x03e5: 0x148c, 0x03e6: 0x148e, 0x03e7: 0x1490, 0x03e8: 0x1492, 0x03e9: 0x16cb, + 0x03ea: 0x16ce, 0x03eb: 0x16d1, 0x03ec: 0x16d4, 0x03ed: 0x16d7, 0x03ee: 0x16da, 0x03ef: 0x16dd, + 0x03f0: 0x16e0, 0x03f1: 0x16e3, 0x03f2: 0x16e6, 0x03f3: 0x16e9, 0x03f4: 0x16ec, 0x03f5: 0x16f0, + 0x03f6: 0x16f4, 0x03f7: 0x16f8, 0x03f8: 0x16fc, 0x03f9: 0x1700, 0x03fa: 0x1704, 0x03fb: 0x1708, + 0x03fc: 0x170c, 0x03fd: 0x1710, 0x03fe: 0x1715, 0x03ff: 0x171a, // Block 0x10, offset 0x400 - 0x0410: 0x05b1, 0x0411: 0x05b6, - 0x0413: 0x05bb, 0x0417: 0x05c0, - 0x041c: 0x05c5, 0x041d: 0x05ca, - 0x041e: 0x05cf, - 0x0436: 0x05d4, 0x0437: 0x05d9, + 0x0400: 0x171f, 0x0401: 0x1724, 0x0402: 0x1729, 0x0403: 0x172e, 0x0404: 0x1733, 0x0405: 0x1738, + 0x0406: 0x173d, 0x0407: 0x1742, 0x0408: 0x1747, 0x0409: 0x174a, 0x040a: 0x174d, 0x040b: 0x1750, + 0x040c: 0x1753, 0x040d: 0x1756, 0x040e: 0x1759, 0x040f: 0x175c, 0x0410: 0x175f, 0x0411: 0x1762, + 0x0412: 0x1766, 0x0413: 0x176a, 0x0414: 0x176e, 0x0415: 0x1772, 0x0416: 0x1776, 0x0417: 0x177a, + 0x0418: 0x177e, 0x0419: 0x1782, 0x041a: 0x1786, 0x041b: 0x178a, 0x041c: 0x178e, 0x041d: 0x1792, + 0x041e: 0x1796, 0x041f: 0x179a, 0x0420: 0x179e, 0x0421: 0x17a2, 0x0422: 0x17a6, 0x0423: 0x17aa, + 0x0424: 0x17ae, 0x0425: 0x17b2, 0x0426: 0x17b6, 0x0427: 0x17ba, 0x0428: 0x17be, 0x0429: 0x17c2, + 0x042a: 0x17c6, 0x042b: 0x17ca, 0x042c: 0x17ce, 0x042d: 0x17d2, 0x042e: 0x17d6, 0x042f: 0x17da, + 0x0430: 0x17de, 0x0431: 0x17e2, 0x0432: 0x17e6, 0x0433: 0x17ea, 0x0434: 0x17ee, 0x0435: 0x17f2, + 0x0436: 0x0906, 0x0437: 0x090b, 0x0438: 0x14ad, 0x0439: 0x090d, 0x043a: 0x090f, 0x043b: 0x14d9, + 0x043c: 0x0914, 0x043d: 0x0916, 0x043e: 0x0918, 0x043f: 0x091a, // Block 0x11, offset 0x440 - 0x0441: 0x05de, 0x0442: 0x05e3, - 0x0450: 0x05e8, 0x0451: 0x05ed, - 0x0452: 0x05f2, 0x0453: 0x05f7, 0x0456: 0x05fc, 0x0457: 0x0601, - 0x045a: 0x0606, 0x045b: 0x060b, 0x045c: 0x0610, 0x045d: 0x0615, - 0x045e: 0x061a, 0x045f: 0x061f, 0x0462: 0x0624, 0x0463: 0x0629, - 0x0464: 0x062e, 0x0465: 0x0633, 0x0466: 0x0638, 0x0467: 0x063d, - 0x046a: 0x0642, 0x046b: 0x0647, 0x046c: 0x064c, 0x046d: 0x0651, 0x046e: 0x0656, 0x046f: 0x065b, - 0x0470: 0x0660, 0x0471: 0x0665, 0x0472: 0x066a, 0x0473: 0x066f, 0x0474: 0x0674, 0x0475: 0x0679, - 0x0478: 0x067e, 0x0479: 0x0683, + 0x0440: 0x091c, 0x0441: 0x091e, 0x0442: 0x0920, 0x0443: 0x0922, 0x0444: 0x0924, 0x0445: 0x0929, + 0x0446: 0x14c8, 0x0447: 0x092b, 0x0448: 0x17f6, 0x0449: 0x092d, 0x044a: 0x092f, 0x044b: 0x155f, + 0x044c: 0x0931, 0x044d: 0x1570, 0x044e: 0x17f8, 0x044f: 0x14d4, 0x0450: 0x0007, 0x0451: 0x093d, + 0x0452: 0x0984, 0x0453: 0x093f, 0x0454: 0x0941, 0x0455: 0x098c, 0x0456: 0x094c, 0x0457: 0x0494, + 0x0458: 0x097c, 0x0459: 0x0499, 0x045a: 0x094e, 0x045b: 0x04c5, 0x045c: 0x0950, 0x045d: 0x14a0, + 0x045e: 0x001e, 0x045f: 0x0960, 0x0460: 0x17fa, 0x0461: 0x049b, 0x0462: 0x02c8, 0x0463: 0x0962, + 0x0464: 0x0964, 0x0465: 0x096d, 0x0466: 0x04a6, 0x0467: 0x04c7, 0x0468: 0x04a8, 0x0469: 0x09df, + 0x046a: 0x1486, // Block 0x12, offset 0x480 - 0x0487: 0x0688, + 0x048c: 0x1b8a, 0x048e: 0x1b91, 0x0490: 0x1b98, + 0x0492: 0x1b9f, 0x0494: 0x1ba6, 0x0496: 0x1bad, + 0x0498: 0x1bb4, 0x049a: 0x1bbb, 0x049c: 0x1bc2, + 0x049e: 0x1bc9, 0x04a0: 0x1bd0, 0x04a2: 0x1bd7, + 0x04a5: 0x1bde, 0x04a7: 0x1be5, 0x04a9: 0x1bec, + 0x04b0: 0x1bf3, 0x04b1: 0x1bfa, 0x04b3: 0x1c01, 0x04b4: 0x1c08, + 0x04b6: 0x1c0f, 0x04b7: 0x1c16, 0x04b9: 0x1c1d, 0x04ba: 0x1c24, + 0x04bc: 0x1c2b, 0x04bd: 0x1c32, // Block 0x13, offset 0x4c0 - 0x04e2: 0x068d, 0x04e3: 0x0692, - 0x04e4: 0x0697, 0x04e5: 0x069c, 0x04e6: 0x06a1, + 0x04c0: 0x1ed8, 0x04c1: 0x1ede, 0x04c2: 0x1ee4, 0x04c3: 0x1eea, 0x04c4: 0x1ef0, 0x04c5: 0x1ef6, + 0x04c6: 0x1efc, 0x04c7: 0x1f02, 0x04c8: 0x1f08, 0x04c9: 0x1f0e, 0x04ca: 0x1f14, 0x04cb: 0x1f1a, + 0x04cc: 0x1f20, 0x04cd: 0x1f26, 0x04ce: 0x1f2c, 0x04cf: 0x1f35, 0x04d0: 0x1f3e, 0x04d1: 0x1f47, + 0x04d2: 0x1f50, 0x04d3: 0x1f59, 0x04d4: 0x1f62, 0x04d5: 0x1f6b, 0x04d6: 0x1f74, 0x04d7: 0x1f7d, + 0x04d8: 0x1f86, 0x04d9: 0x1f8f, 0x04da: 0x1f98, 0x04db: 0x1fa1, 0x04dc: 0x1faa, 0x04dd: 0x1fb3, + 0x04de: 0x1fc5, 0x04e0: 0x1fd4, 0x04e1: 0x1fda, 0x04e2: 0x1fe0, 0x04e3: 0x1fe6, + 0x04e4: 0x1fec, 0x04e5: 0x1ff2, 0x04e6: 0x1ff8, 0x04e7: 0x1ffe, 0x04e8: 0x2004, 0x04e9: 0x200a, + 0x04ea: 0x2010, 0x04eb: 0x2016, 0x04ec: 0x201c, 0x04ed: 0x2022, 0x04ee: 0x2028, 0x04ef: 0x202e, + 0x04f0: 0x2034, 0x04f1: 0x203a, 0x04f2: 0x2040, 0x04f3: 0x2046, 0x04f4: 0x204c, 0x04f5: 0x2052, + 0x04f6: 0x2058, 0x04f7: 0x205e, 0x04f8: 0x2064, 0x04f9: 0x206a, 0x04fa: 0x2070, 0x04fb: 0x2076, + 0x04fc: 0x207c, 0x04fd: 0x2082, 0x04fe: 0x2088, 0x04ff: 0x208e, // Block 0x14, offset 0x500 - 0x0535: 0x06a6, - 0x0536: 0x06ab, 0x0537: 0x06b0, 0x0538: 0x06b5, + 0x0500: 0x2094, 0x0501: 0x209a, 0x0502: 0x20a0, 0x0503: 0x20a6, 0x0504: 0x20ac, 0x0505: 0x20b0, + 0x0506: 0x192e, 0x0507: 0x20b4, + 0x0510: 0x20b8, 0x0511: 0x20bc, + 0x0512: 0x20bf, 0x0513: 0x20c2, 0x0514: 0x20c5, 0x0515: 0x20c8, 0x0516: 0x20cb, 0x0517: 0x20ce, + 0x0518: 0x20d1, 0x0519: 0x20d4, 0x051a: 0x20d7, 0x051b: 0x20da, 0x051c: 0x20dd, 0x051d: 0x20e0, + 0x051e: 0x20e3, 0x051f: 0x20e6, 0x0520: 0x1d38, 0x0521: 0x1d44, 0x0522: 0x1d50, 0x0523: 0x1d58, + 0x0524: 0x1d78, 0x0525: 0x1d7c, 0x0526: 0x1d88, 0x0527: 0x1d90, 0x0528: 0x1d94, 0x0529: 0x1d9c, + 0x052a: 0x1da0, 0x052b: 0x1da4, 0x052c: 0x1da8, 0x052d: 0x1dac, 0x052e: 0x20e9, 0x052f: 0x20f0, + 0x0530: 0x20f7, 0x0531: 0x20fe, 0x0532: 0x2105, 0x0533: 0x210c, 0x0534: 0x2113, 0x0535: 0x211a, + 0x0536: 0x2121, 0x0537: 0x2128, 0x0538: 0x212f, 0x0539: 0x2136, 0x053a: 0x213d, 0x053b: 0x2144, + 0x053c: 0x214b, 0x053d: 0x215b, 0x053e: 0x2168, // Block 0x15, offset 0x540 - 0x0540: 0x06ba, 0x0542: 0x06bf, - 0x0553: 0x06c4, + 0x0540: 0x1826, 0x0541: 0x183e, 0x0542: 0x1eb0, 0x0543: 0x1eb4, 0x0544: 0x216f, 0x0545: 0x2173, + 0x0546: 0x2177, 0x0547: 0x1852, 0x0548: 0x217b, 0x0549: 0x1882, 0x054a: 0x194a, 0x054b: 0x197a, + 0x054c: 0x1976, 0x054d: 0x194e, 0x054e: 0x1abe, 0x054f: 0x18a2, 0x0550: 0x1942, 0x0551: 0x217f, + 0x0552: 0x2183, 0x0553: 0x2187, 0x0554: 0x218b, 0x0555: 0x218f, 0x0556: 0x2193, 0x0557: 0x2197, + 0x0558: 0x219b, 0x0559: 0x219f, 0x055a: 0x21a3, 0x055b: 0x18ba, 0x055c: 0x21a7, 0x055d: 0x21ab, + 0x055e: 0x21af, 0x055f: 0x21b3, 0x0560: 0x21b7, 0x0561: 0x21bb, 0x0562: 0x21bf, 0x0563: 0x21c3, + 0x0564: 0x1eb8, 0x0565: 0x1ebc, 0x0566: 0x1ec0, 0x0567: 0x21c7, 0x0568: 0x21cb, 0x0569: 0x21cf, + 0x056a: 0x21d3, 0x056b: 0x21d7, 0x056c: 0x21db, 0x056d: 0x21df, 0x056e: 0x21e3, 0x056f: 0x21e7, + 0x0570: 0x21eb, 0x0571: 0x21ef, 0x0572: 0x21f2, 0x0573: 0x21f5, 0x0574: 0x21f8, 0x0575: 0x21fb, + 0x0576: 0x21fe, 0x0577: 0x2201, 0x0578: 0x2204, 0x0579: 0x2207, 0x057a: 0x220a, 0x057b: 0x220d, + 0x057c: 0x2210, 0x057d: 0x2213, 0x057e: 0x2216, 0x057f: 0x2219, // Block 0x16, offset 0x580 - 0x05a9: 0x06c9, - 0x05b1: 0x06d0, 0x05b4: 0x06d7, + 0x0580: 0x2325, 0x0581: 0x2335, 0x0582: 0x2342, 0x0583: 0x2352, 0x0584: 0x235c, 0x0585: 0x236c, + 0x0586: 0x2376, 0x0587: 0x2380, 0x0588: 0x2393, 0x0589: 0x23a0, 0x058a: 0x23aa, 0x058b: 0x23b4, + 0x058c: 0x23be, 0x058d: 0x23cb, 0x058e: 0x23d8, 0x058f: 0x23e5, 0x0590: 0x23f2, 0x0591: 0x23ff, + 0x0592: 0x240c, 0x0593: 0x2419, 0x0594: 0x242c, 0x0595: 0x2433, 0x0596: 0x2446, 0x0597: 0x2459, + 0x0598: 0x2469, 0x0599: 0x2476, 0x059a: 0x2489, 0x059b: 0x249c, 0x059c: 0x24a9, 0x059d: 0x24b3, + 0x059e: 0x24bd, 0x059f: 0x24ca, 0x05a0: 0x24d7, 0x05a1: 0x24e7, 0x05a2: 0x24f7, 0x05a3: 0x2501, + 0x05a4: 0x250b, 0x05a5: 0x2518, 0x05a6: 0x2522, 0x05a7: 0x252c, 0x05a8: 0x2533, 0x05a9: 0x253a, + 0x05aa: 0x2544, 0x05ab: 0x254e, 0x05ac: 0x2561, 0x05ad: 0x256e, 0x05ae: 0x257e, 0x05af: 0x2591, + 0x05b0: 0x259e, 0x05b1: 0x25a8, 0x05b2: 0x25b2, 0x05b3: 0x25c5, 0x05b4: 0x25d2, 0x05b5: 0x25e5, + 0x05b6: 0x25ef, 0x05b7: 0x25ff, 0x05b8: 0x2609, 0x05b9: 0x2616, 0x05ba: 0x2620, 0x05bb: 0x262d, + 0x05bc: 0x263d, 0x05bd: 0x264a, 0x05be: 0x265a, 0x05bf: 0x2667, // Block 0x17, offset 0x5c0 - 0x05d8: 0x06de, 0x05d9: 0x06e5, 0x05da: 0x06ec, 0x05db: 0x06f3, 0x05dc: 0x06fa, 0x05dd: 0x0701, - 0x05de: 0x0708, 0x05df: 0x070f, + 0x05c0: 0x266e, 0x05c1: 0x267e, 0x05c2: 0x2688, 0x05c3: 0x2692, 0x05c4: 0x269f, 0x05c5: 0x26a9, + 0x05c6: 0x26b3, 0x05c7: 0x26bd, 0x05c8: 0x26cd, 0x05c9: 0x26da, 0x05ca: 0x26e1, 0x05cb: 0x26f4, + 0x05cc: 0x26fe, 0x05cd: 0x270e, 0x05ce: 0x271b, 0x05cf: 0x2728, 0x05d0: 0x2732, 0x05d1: 0x273c, + 0x05d2: 0x2749, 0x05d3: 0x2750, 0x05d4: 0x275d, 0x05d5: 0x276d, 0x05d6: 0x2774, 0x05d7: 0x2787, + 0x05d8: 0x2791, 0x05d9: 0x2796, 0x05da: 0x279b, 0x05db: 0x27a0, 0x05dc: 0x27a5, 0x05dd: 0x27aa, + 0x05de: 0x27af, 0x05df: 0x27b4, 0x05e0: 0x27b9, 0x05e1: 0x27be, 0x05e2: 0x27c3, 0x05e3: 0x27c9, + 0x05e4: 0x27cf, 0x05e5: 0x27d5, 0x05e6: 0x27db, 0x05e7: 0x27e1, 0x05e8: 0x27e7, 0x05e9: 0x27ed, + 0x05ea: 0x27f3, 0x05eb: 0x27f9, 0x05ec: 0x27ff, 0x05ed: 0x2805, 0x05ee: 0x280b, 0x05ef: 0x2811, + 0x05f0: 0x2817, 0x05f1: 0x281d, 0x05f2: 0x2821, 0x05f3: 0x2824, 0x05f4: 0x2827, 0x05f5: 0x282b, + 0x05f6: 0x282e, 0x05f7: 0x2831, 0x05f8: 0x2834, 0x05f9: 0x2838, 0x05fa: 0x283c, 0x05fb: 0x283f, + 0x05fc: 0x2846, 0x05fd: 0x284d, 0x05fe: 0x2854, 0x05ff: 0x285b, // Block 0x18, offset 0x600 - 0x060b: 0x0716, - 0x060c: 0x071d, - 0x061c: 0x0724, 0x061d: 0x072b, - 0x061f: 0x0732, + 0x0600: 0x2868, 0x0601: 0x286b, 0x0602: 0x286e, 0x0603: 0x2872, 0x0604: 0x2875, 0x0605: 0x2878, + 0x0606: 0x287b, 0x0607: 0x287e, 0x0608: 0x2881, 0x0609: 0x2885, 0x060a: 0x288a, 0x060b: 0x288d, + 0x060c: 0x2890, 0x060d: 0x2894, 0x060e: 0x2898, 0x060f: 0x289b, 0x0610: 0x289e, 0x0611: 0x28a1, + 0x0612: 0x28a5, 0x0613: 0x28a9, 0x0614: 0x28ad, 0x0615: 0x28b1, 0x0616: 0x28b5, 0x0617: 0x28b8, + 0x0618: 0x28bb, 0x0619: 0x28be, 0x061a: 0x28c1, 0x061b: 0x28c4, 0x061c: 0x28c8, 0x061d: 0x28cb, + 0x061e: 0x28ce, 0x061f: 0x28d1, 0x0620: 0x28d5, 0x0621: 0x28d9, 0x0622: 0x28dc, 0x0623: 0x28e0, + 0x0624: 0x28e4, 0x0625: 0x28e8, 0x0626: 0x28eb, 0x0627: 0x28ef, 0x0628: 0x28f5, 0x0629: 0x28fc, + 0x062a: 0x28ff, 0x062b: 0x2903, 0x062c: 0x2907, 0x062d: 0x290b, 0x062e: 0x290f, 0x062f: 0x2917, + 0x0630: 0x2920, 0x0631: 0x2923, 0x0632: 0x2926, 0x0633: 0x292a, 0x0634: 0x292d, 0x0635: 0x2930, + 0x0636: 0x2933, 0x0637: 0x2937, 0x0638: 0x293a, 0x0639: 0x293d, 0x063a: 0x2940, 0x063b: 0x2943, + 0x063c: 0x2946, 0x063d: 0x294a, 0x063e: 0x294d, 0x063f: 0x2950, // Block 0x19, offset 0x640 - 0x0673: 0x0739, - 0x0676: 0x0740, + 0x0640: 0x2953, 0x0641: 0x2957, 0x0642: 0x295b, 0x0643: 0x2960, 0x0644: 0x2963, 0x0645: 0x2966, + 0x0646: 0x2969, 0x0647: 0x2970, 0x0648: 0x2974, 0x0649: 0x2977, 0x064a: 0x297a, 0x064b: 0x297d, + 0x064c: 0x2980, 0x064d: 0x2983, 0x064e: 0x2986, 0x064f: 0x2989, 0x0650: 0x298c, 0x0651: 0x298f, + 0x0652: 0x2992, 0x0653: 0x2996, 0x0654: 0x2999, 0x0655: 0x299c, 0x0656: 0x29a0, 0x0657: 0x29a4, + 0x0658: 0x29a7, 0x0659: 0x29ac, 0x065a: 0x29b0, 0x065b: 0x29b3, 0x065c: 0x29b6, 0x065d: 0x29b9, + 0x065e: 0x29bc, 0x065f: 0x29c2, 0x0660: 0x29c8, 0x0661: 0x29cd, 0x0662: 0x29d2, 0x0663: 0x29d7, + 0x0664: 0x29dc, 0x0665: 0x29e1, 0x0666: 0x29e6, 0x0667: 0x29eb, 0x0668: 0x29f0, 0x0669: 0x29f5, + 0x066a: 0x29fb, 0x066b: 0x2a01, 0x066c: 0x2a07, 0x066d: 0x2a0d, 0x066e: 0x2a13, 0x066f: 0x2a19, + 0x0670: 0x2a1f, 0x0671: 0x2a25, 0x0672: 0x2a2b, 0x0673: 0x2a31, 0x0674: 0x2a37, 0x0675: 0x2a3d, + 0x0676: 0x2a43, 0x0677: 0x2a49, 0x0678: 0x2a4f, 0x0679: 0x2a55, 0x067a: 0x2a5b, 0x067b: 0x2a61, + 0x067c: 0x2a67, 0x067d: 0x2a6d, 0x067e: 0x2a73, 0x067f: 0x2a79, // Block 0x1a, offset 0x680 - 0x0699: 0x0747, 0x069a: 0x074e, 0x069b: 0x0755, - 0x069e: 0x075c, + 0x0680: 0x2fce, 0x0681: 0x2fd2, 0x0682: 0x2fd6, 0x0683: 0x2fda, 0x0684: 0x2fde, 0x0685: 0x2fe2, + 0x0686: 0x2fe6, 0x0687: 0x2fea, 0x0688: 0x2fee, 0x0689: 0x2eed, 0x068a: 0x2ff2, 0x068b: 0x2ef1, + 0x068c: 0x2ff6, 0x068d: 0x2ffa, 0x068e: 0x2ffe, 0x068f: 0x3002, 0x0690: 0x3006, 0x0691: 0x2e6d, + 0x0692: 0x2b15, 0x0693: 0x300a, 0x0694: 0x300e, 0x0695: 0x195a, 0x0696: 0x2c25, 0x0697: 0x2d71, + 0x0698: 0x3012, 0x0699: 0x3016, 0x069a: 0x2f0d, 0x069b: 0x301a, 0x069c: 0x2f11, 0x069d: 0x301e, + 0x069e: 0x3022, 0x069f: 0x3026, 0x06a0: 0x2e75, 0x06a1: 0x302a, 0x06a2: 0x302e, 0x06a3: 0x3032, + 0x06a4: 0x3036, 0x06a5: 0x303a, 0x06a6: 0x2e79, 0x06a7: 0x303e, 0x06a8: 0x3042, 0x06a9: 0x3046, + 0x06aa: 0x304a, 0x06ab: 0x304e, 0x06ac: 0x3052, 0x06ad: 0x2f41, 0x06ae: 0x3056, 0x06af: 0x305a, + 0x06b0: 0x2cb1, 0x06b1: 0x305e, 0x06b2: 0x2f51, 0x06b3: 0x3062, 0x06b4: 0x3066, 0x06b5: 0x306a, + 0x06b6: 0x306e, 0x06b7: 0x3072, 0x06b8: 0x2f65, 0x06b9: 0x3076, 0x06ba: 0x2e99, 0x06bb: 0x307a, + 0x06bc: 0x2f69, 0x06bd: 0x2bd9, 0x06be: 0x307e, 0x06bf: 0x2f6d, // Block 0x1b, offset 0x6c0 - 0x06c8: 0x0763, 0x06cb: 0x076a, - 0x06cc: 0x0771, - 0x06dc: 0x0778, 0x06dd: 0x077f, + 0x06c0: 0x3082, 0x06c1: 0x2f75, 0x06c2: 0x3086, 0x06c3: 0x308a, 0x06c4: 0x308e, 0x06c5: 0x3092, + 0x06c6: 0x3096, 0x06c7: 0x2f7d, 0x06c8: 0x2e8d, 0x06c9: 0x309a, 0x06ca: 0x2f81, 0x06cb: 0x309e, + 0x06cc: 0x2f85, 0x06cd: 0x30a2, 0x06ce: 0x1b76, 0x06cf: 0x30a6, 0x06d0: 0x30ab, 0x06d1: 0x30b0, + 0x06d2: 0x30b5, 0x06d3: 0x30b9, 0x06d4: 0x30bd, 0x06d5: 0x30c1, 0x06d6: 0x30c6, 0x06d7: 0x30cb, + 0x06d8: 0x30d0, 0x06d9: 0x30d4, // Block 0x1c, offset 0x700 - 0x0714: 0x0786, + 0x0700: 0x30d8, 0x0701: 0x30db, 0x0702: 0x30de, 0x0703: 0x30e1, 0x0704: 0x30e5, 0x0705: 0x30e9, + 0x0706: 0x30e9, + 0x0713: 0x30ec, 0x0714: 0x30f1, 0x0715: 0x30f6, 0x0716: 0x30fb, 0x0717: 0x3100, + 0x071d: 0x3105, + 0x071f: 0x310a, 0x0720: 0x310f, 0x0721: 0x14db, 0x0722: 0x14e4, 0x0723: 0x3112, + 0x0724: 0x3115, 0x0725: 0x3118, 0x0726: 0x311b, 0x0727: 0x311e, 0x0728: 0x3121, 0x0729: 0x1494, + 0x072a: 0x3124, 0x072b: 0x3129, 0x072c: 0x312e, 0x072d: 0x3135, 0x072e: 0x313c, 0x072f: 0x3141, + 0x0730: 0x3146, 0x0731: 0x314b, 0x0732: 0x3150, 0x0733: 0x3155, 0x0734: 0x315a, 0x0735: 0x315f, + 0x0736: 0x3164, 0x0738: 0x3169, 0x0739: 0x316e, 0x073a: 0x3173, 0x073b: 0x3178, + 0x073c: 0x317d, 0x073e: 0x3182, // Block 0x1d, offset 0x740 - 0x074a: 0x078d, 0x074b: 0x0794, - 0x074c: 0x079b, + 0x0740: 0x3187, 0x0741: 0x318c, 0x0743: 0x3191, 0x0744: 0x3196, + 0x0746: 0x319b, 0x0747: 0x31a0, 0x0748: 0x31a5, 0x0749: 0x31aa, 0x074a: 0x31af, 0x074b: 0x31b4, + 0x074c: 0x31b9, 0x074d: 0x31be, 0x074e: 0x31c3, 0x074f: 0x31c8, 0x0750: 0x31cd, 0x0751: 0x31cd, + 0x0752: 0x31d0, 0x0753: 0x31d0, 0x0754: 0x31d0, 0x0755: 0x31d0, 0x0756: 0x31d3, 0x0757: 0x31d3, + 0x0758: 0x31d3, 0x0759: 0x31d3, 0x075a: 0x31d6, 0x075b: 0x31d6, 0x075c: 0x31d6, 0x075d: 0x31d6, + 0x075e: 0x31d9, 0x075f: 0x31d9, 0x0760: 0x31d9, 0x0761: 0x31d9, 0x0762: 0x31dc, 0x0763: 0x31dc, + 0x0764: 0x31dc, 0x0765: 0x31dc, 0x0766: 0x31df, 0x0767: 0x31df, 0x0768: 0x31df, 0x0769: 0x31df, + 0x076a: 0x31e2, 0x076b: 0x31e2, 0x076c: 0x31e2, 0x076d: 0x31e2, 0x076e: 0x31e5, 0x076f: 0x31e5, + 0x0770: 0x31e5, 0x0771: 0x31e5, 0x0772: 0x31e8, 0x0773: 0x31e8, 0x0774: 0x31e8, 0x0775: 0x31e8, + 0x0776: 0x31eb, 0x0777: 0x31eb, 0x0778: 0x31eb, 0x0779: 0x31eb, 0x077a: 0x31ee, 0x077b: 0x31ee, + 0x077c: 0x31ee, 0x077d: 0x31ee, 0x077e: 0x31f1, 0x077f: 0x31f1, // Block 0x1e, offset 0x780 - 0x0788: 0x07a2, + 0x0780: 0x31f1, 0x0781: 0x31f1, 0x0782: 0x31f4, 0x0783: 0x31f4, 0x0784: 0x31f7, 0x0785: 0x31f7, + 0x0786: 0x31fa, 0x0787: 0x31fa, 0x0788: 0x31fd, 0x0789: 0x31fd, 0x078a: 0x3200, 0x078b: 0x3200, + 0x078c: 0x3203, 0x078d: 0x3203, 0x078e: 0x3206, 0x078f: 0x3206, 0x0790: 0x3206, 0x0791: 0x3206, + 0x0792: 0x3209, 0x0793: 0x3209, 0x0794: 0x3209, 0x0795: 0x3209, 0x0796: 0x320c, 0x0797: 0x320c, + 0x0798: 0x320c, 0x0799: 0x320c, 0x079a: 0x320f, 0x079b: 0x320f, 0x079c: 0x320f, 0x079d: 0x320f, + 0x079e: 0x3212, 0x079f: 0x3212, 0x07a0: 0x3215, 0x07a1: 0x3215, 0x07a2: 0x3215, 0x07a3: 0x3215, + 0x07a4: 0x06ba, 0x07a5: 0x06ba, 0x07a6: 0x3218, 0x07a7: 0x3218, 0x07a8: 0x3218, 0x07a9: 0x3218, + 0x07aa: 0x321b, 0x07ab: 0x321b, 0x07ac: 0x321b, 0x07ad: 0x321b, 0x07ae: 0x321e, 0x07af: 0x321e, + 0x07b0: 0x06c4, 0x07b1: 0x06c4, // Block 0x1f, offset 0x7c0 - 0x07c0: 0x07a9, - 0x07c7: 0x07b0, 0x07c8: 0x07b7, 0x07ca: 0x07be, 0x07cb: 0x07c5, + 0x07d3: 0x3221, 0x07d4: 0x3221, 0x07d5: 0x3221, 0x07d6: 0x3221, 0x07d7: 0x3224, + 0x07d8: 0x3224, 0x07d9: 0x3227, 0x07da: 0x3227, 0x07db: 0x322a, 0x07dc: 0x322a, 0x07dd: 0x06b0, + 0x07de: 0x322d, 0x07df: 0x322d, 0x07e0: 0x3230, 0x07e1: 0x3230, 0x07e2: 0x3233, 0x07e3: 0x3233, + 0x07e4: 0x3236, 0x07e5: 0x3236, 0x07e6: 0x3236, 0x07e7: 0x3236, 0x07e8: 0x3239, 0x07e9: 0x3239, + 0x07ea: 0x323c, 0x07eb: 0x323c, 0x07ec: 0x3243, 0x07ed: 0x3243, 0x07ee: 0x324a, 0x07ef: 0x324a, + 0x07f0: 0x3251, 0x07f1: 0x3251, 0x07f2: 0x3258, 0x07f3: 0x3258, 0x07f4: 0x325f, 0x07f5: 0x325f, + 0x07f6: 0x3266, 0x07f7: 0x3266, 0x07f8: 0x3266, 0x07f9: 0x326d, 0x07fa: 0x326d, 0x07fb: 0x326d, + 0x07fc: 0x3274, 0x07fd: 0x3274, 0x07fe: 0x3274, 0x07ff: 0x3274, // Block 0x20, offset 0x800 - 0x080a: 0x07cf, 0x080b: 0x07d6, - 0x080c: 0x07dd, + 0x0800: 0x33ba, 0x0801: 0x33bf, 0x0802: 0x33c4, 0x0803: 0x33c9, 0x0804: 0x33ce, 0x0805: 0x33d3, + 0x0806: 0x33d8, 0x0807: 0x33dd, 0x0808: 0x33e2, 0x0809: 0x33e7, 0x080a: 0x33ec, 0x080b: 0x33f1, + 0x080c: 0x33f6, 0x080d: 0x33fb, 0x080e: 0x3400, 0x080f: 0x3405, 0x0810: 0x340a, 0x0811: 0x340f, + 0x0812: 0x3414, 0x0813: 0x3419, 0x0814: 0x341e, 0x0815: 0x3423, 0x0816: 0x3428, 0x0817: 0x342d, + 0x0818: 0x3432, 0x0819: 0x3437, 0x081a: 0x343c, 0x081b: 0x3441, 0x081c: 0x3446, 0x081d: 0x344b, + 0x081e: 0x3450, 0x081f: 0x3456, 0x0820: 0x345c, 0x0821: 0x3462, 0x0822: 0x3468, 0x0823: 0x346e, + 0x0824: 0x3474, 0x0825: 0x347b, 0x0826: 0x3285, 0x0827: 0x3482, 0x0828: 0x326d, 0x0829: 0x328c, + 0x082a: 0x3489, 0x082b: 0x348e, 0x082c: 0x32a2, 0x082d: 0x3493, 0x082e: 0x32a7, 0x082f: 0x32ac, + 0x0830: 0x3498, 0x0831: 0x349d, 0x0832: 0x32c0, 0x0833: 0x34a2, 0x0834: 0x32c5, 0x0835: 0x32ca, + 0x0836: 0x34a7, 0x0837: 0x34ac, 0x0838: 0x32d4, 0x0839: 0x34b1, 0x083a: 0x32d9, 0x083b: 0x32de, + 0x083c: 0x336f, 0x083d: 0x3374, 0x083e: 0x3383, 0x083f: 0x3388, // Block 0x21, offset 0x840 - 0x085a: 0x07e4, 0x085c: 0x07eb, 0x085d: 0x07f2, - 0x085e: 0x07fc, + 0x0840: 0x338d, 0x0841: 0x33a1, 0x0842: 0x33a6, 0x0843: 0x33ab, 0x0844: 0x33b0, 0x0845: 0x33c4, + 0x0846: 0x33c9, 0x0847: 0x33ce, 0x0848: 0x34b6, 0x0849: 0x33e2, 0x084a: 0x34bb, 0x084b: 0x34c0, + 0x084c: 0x3400, 0x084d: 0x34c5, 0x084e: 0x3405, 0x084f: 0x340a, 0x0850: 0x344b, 0x0851: 0x34ca, + 0x0852: 0x34cf, 0x0853: 0x3432, 0x0854: 0x34d4, 0x0855: 0x3437, 0x0856: 0x343c, 0x0857: 0x3277, + 0x0858: 0x327e, 0x0859: 0x34d9, 0x085a: 0x3285, 0x085b: 0x34e0, 0x085c: 0x3293, 0x085d: 0x3298, + 0x085e: 0x329d, 0x085f: 0x32a2, 0x0860: 0x34e7, 0x0861: 0x32b1, 0x0862: 0x32b6, 0x0863: 0x32bb, + 0x0864: 0x32c0, 0x0865: 0x34ec, 0x0866: 0x32d4, 0x0867: 0x32e3, 0x0868: 0x32e8, 0x0869: 0x32ed, + 0x086a: 0x32f2, 0x086b: 0x32f7, 0x086c: 0x3301, 0x086d: 0x3306, 0x086e: 0x330b, 0x086f: 0x3310, + 0x0870: 0x3315, 0x0871: 0x331a, 0x0872: 0x34f1, 0x0873: 0x331f, 0x0874: 0x3324, 0x0875: 0x3329, + 0x0876: 0x332e, 0x0877: 0x3333, 0x0878: 0x3338, 0x0879: 0x3342, 0x087a: 0x3347, 0x087b: 0x334c, + 0x087c: 0x3351, 0x087d: 0x3356, 0x087e: 0x335b, 0x087f: 0x3360, // Block 0x22, offset 0x880 - 0x08b3: 0x0803, + 0x0880: 0x3365, 0x0881: 0x336a, 0x0882: 0x3379, 0x0883: 0x337e, 0x0884: 0x3392, 0x0885: 0x3397, + 0x0886: 0x339c, 0x0887: 0x33a1, 0x0888: 0x33a6, 0x0889: 0x33b5, 0x088a: 0x33ba, 0x088b: 0x33bf, + 0x088c: 0x33c4, 0x088d: 0x34f6, 0x088e: 0x33d3, 0x088f: 0x33d8, 0x0890: 0x33dd, 0x0891: 0x33e2, + 0x0892: 0x33f1, 0x0893: 0x33f6, 0x0894: 0x33fb, 0x0895: 0x3400, 0x0896: 0x34fb, 0x0897: 0x340f, + 0x0898: 0x3414, 0x0899: 0x3500, 0x089a: 0x3423, 0x089b: 0x3428, 0x089c: 0x342d, 0x089d: 0x3432, + 0x089e: 0x3505, 0x089f: 0x3285, 0x08a0: 0x34e0, 0x08a1: 0x32a2, 0x08a2: 0x34e7, 0x08a3: 0x32c0, + 0x08a4: 0x34ec, 0x08a5: 0x32d4, 0x08a6: 0x350a, 0x08a7: 0x3315, 0x08a8: 0x350f, 0x08a9: 0x3514, + 0x08aa: 0x3519, 0x08ab: 0x33a1, 0x08ac: 0x33a6, 0x08ad: 0x33c4, 0x08ae: 0x3400, 0x08af: 0x34fb, + 0x08b0: 0x3432, 0x08b1: 0x3505, 0x08b2: 0x351e, 0x08b3: 0x3525, 0x08b4: 0x352c, 0x08b5: 0x3533, + 0x08b6: 0x3538, 0x08b7: 0x353d, 0x08b8: 0x3542, 0x08b9: 0x3547, 0x08ba: 0x354c, 0x08bb: 0x3551, + 0x08bc: 0x3556, 0x08bd: 0x355b, 0x08be: 0x3560, 0x08bf: 0x3565, // Block 0x23, offset 0x8c0 - 0x08f3: 0x080a, + 0x08c0: 0x16c7, 0x08c1: 0x391e, 0x08c2: 0x3922, 0x08c3: 0x3926, 0x08c4: 0x392a, + 0x08c7: 0x392e, 0x08c8: 0x3930, 0x08c9: 0x146c, 0x08ca: 0x146c, 0x08cb: 0x146c, + 0x08cc: 0x146c, 0x08cd: 0x3900, 0x08ce: 0x3900, 0x08cf: 0x3900, 0x08d0: 0x38e0, 0x08d1: 0x38e2, + 0x08d2: 0x143e, 0x08d4: 0x04e1, 0x08d5: 0x38ea, 0x08d6: 0x38ee, 0x08d7: 0x38ec, + 0x08d8: 0x38f8, 0x08d9: 0x149c, 0x08da: 0x149e, 0x08db: 0x3902, 0x08dc: 0x3904, 0x08dd: 0x3906, + 0x08de: 0x390a, 0x08df: 0x3932, 0x08e0: 0x3934, 0x08e1: 0x3936, 0x08e2: 0x1494, 0x08e3: 0x3938, + 0x08e4: 0x393a, 0x08e5: 0x393c, 0x08e6: 0x149a, 0x08e8: 0x393e, 0x08e9: 0x3940, + 0x08ea: 0x3942, 0x08eb: 0x3944, + 0x08f0: 0x3946, 0x08f1: 0x394a, 0x08f2: 0x394f, 0x08f4: 0x3953, + 0x08f6: 0x3957, 0x08f7: 0x395b, 0x08f8: 0x3960, 0x08f9: 0x3964, 0x08fa: 0x3969, 0x08fb: 0x396d, + 0x08fc: 0x3972, 0x08fd: 0x3976, 0x08fe: 0x397b, 0x08ff: 0x397f, // Block 0x24, offset 0x900 - 0x091c: 0x0811, 0x091d: 0x0818, + 0x0900: 0x3984, 0x0901: 0x068d, 0x0902: 0x068d, 0x0903: 0x0692, 0x0904: 0x0692, 0x0905: 0x0697, + 0x0906: 0x0697, 0x0907: 0x069c, 0x0908: 0x069c, 0x0909: 0x06a1, 0x090a: 0x06a1, 0x090b: 0x06a1, + 0x090c: 0x06a1, 0x090d: 0x3987, 0x090e: 0x3987, 0x090f: 0x398a, 0x0910: 0x398a, 0x0911: 0x398a, + 0x0912: 0x398a, 0x0913: 0x398d, 0x0914: 0x398d, 0x0915: 0x3990, 0x0916: 0x3990, 0x0917: 0x3990, + 0x0918: 0x3990, 0x0919: 0x3993, 0x091a: 0x3993, 0x091b: 0x3993, 0x091c: 0x3993, 0x091d: 0x3996, + 0x091e: 0x3996, 0x091f: 0x3996, 0x0920: 0x3996, 0x0921: 0x3999, 0x0922: 0x3999, 0x0923: 0x3999, + 0x0924: 0x3999, 0x0925: 0x399c, 0x0926: 0x399c, 0x0927: 0x399c, 0x0928: 0x399c, 0x0929: 0x399f, + 0x092a: 0x399f, 0x092b: 0x39a2, 0x092c: 0x39a2, 0x092d: 0x39a5, 0x092e: 0x39a5, 0x092f: 0x39a8, + 0x0930: 0x39a8, 0x0931: 0x39ab, 0x0932: 0x39ab, 0x0933: 0x39ab, 0x0934: 0x39ab, 0x0935: 0x39ae, + 0x0936: 0x39ae, 0x0937: 0x39ae, 0x0938: 0x39ae, 0x0939: 0x39b1, 0x093a: 0x39b1, 0x093b: 0x39b1, + 0x093c: 0x39b1, 0x093d: 0x39b4, 0x093e: 0x39b4, 0x093f: 0x39b4, // Block 0x25, offset 0x940 - 0x094c: 0x081f, + 0x0940: 0x39b4, 0x0941: 0x39b7, 0x0942: 0x39b7, 0x0943: 0x39b7, 0x0944: 0x39b7, 0x0945: 0x39ba, + 0x0946: 0x39ba, 0x0947: 0x39ba, 0x0948: 0x39ba, 0x0949: 0x39bd, 0x094a: 0x39bd, 0x094b: 0x39bd, + 0x094c: 0x39bd, 0x094d: 0x39c0, 0x094e: 0x39c0, 0x094f: 0x39c0, 0x0950: 0x39c0, 0x0951: 0x39c3, + 0x0952: 0x39c3, 0x0953: 0x39c3, 0x0954: 0x39c3, 0x0955: 0x39c6, 0x0956: 0x39c6, 0x0957: 0x39c6, + 0x0958: 0x39c6, 0x0959: 0x39c9, 0x095a: 0x39c9, 0x095b: 0x39c9, 0x095c: 0x39c9, 0x095d: 0x39cc, + 0x095e: 0x39cc, 0x095f: 0x39cc, 0x0960: 0x39cc, 0x0961: 0x39cf, 0x0962: 0x39cf, 0x0963: 0x39cf, + 0x0964: 0x39cf, 0x0965: 0x39d2, 0x0966: 0x39d2, 0x0967: 0x39d2, 0x0968: 0x39d2, 0x0969: 0x39d5, + 0x096a: 0x39d5, 0x096b: 0x39d5, 0x096c: 0x39d5, 0x096d: 0x39d8, 0x096e: 0x39d8, 0x096f: 0x3239, + 0x0970: 0x3239, 0x0971: 0x39db, 0x0972: 0x39db, 0x0973: 0x39db, 0x0974: 0x39db, 0x0975: 0x39de, + 0x0976: 0x39de, 0x0977: 0x39e5, 0x0978: 0x39e5, 0x0979: 0x39ec, 0x097a: 0x39ec, 0x097b: 0x39f3, + 0x097c: 0x39f3, // Block 0x26, offset 0x980 - 0x0983: 0x0823, - 0x098d: 0x082a, - 0x0992: 0x0831, 0x0997: 0x0838, - 0x099c: 0x083f, - 0x09a9: 0x0846, - 0x09b3: 0x084d, 0x09b5: 0x0854, - 0x09b6: 0x085b, 0x09b7: 0x0862, 0x09b8: 0x086c, 0x09b9: 0x0873, + 0x0981: 0x38ec, 0x0982: 0x39f8, 0x0983: 0x3932, 0x0984: 0x3940, 0x0985: 0x3942, + 0x0986: 0x3934, 0x0987: 0x39fa, 0x0988: 0x149c, 0x0989: 0x149e, 0x098a: 0x3936, 0x098b: 0x1494, + 0x098c: 0x38e0, 0x098d: 0x3938, 0x098e: 0x143e, 0x098f: 0x39fc, 0x0990: 0x1486, 0x0991: 0x001c, + 0x0992: 0x000d, 0x0993: 0x000f, 0x0994: 0x1488, 0x0995: 0x148a, 0x0996: 0x148c, 0x0997: 0x148e, + 0x0998: 0x1490, 0x0999: 0x1492, 0x099a: 0x38ea, 0x099b: 0x04e1, 0x099c: 0x393a, 0x099d: 0x149a, + 0x099e: 0x393c, 0x099f: 0x38ee, 0x09a0: 0x3944, 0x09a1: 0x0906, 0x09a2: 0x090b, 0x09a3: 0x14ad, + 0x09a4: 0x090d, 0x09a5: 0x090f, 0x09a6: 0x14d9, 0x09a7: 0x0914, 0x09a8: 0x0916, 0x09a9: 0x0918, + 0x09aa: 0x091a, 0x09ab: 0x091c, 0x09ac: 0x091e, 0x09ad: 0x0920, 0x09ae: 0x0922, 0x09af: 0x0924, + 0x09b0: 0x0929, 0x09b1: 0x14c8, 0x09b2: 0x092b, 0x09b3: 0x17f6, 0x09b4: 0x092d, 0x09b5: 0x092f, + 0x09b6: 0x155f, 0x09b7: 0x0931, 0x09b8: 0x1570, 0x09b9: 0x17f8, 0x09ba: 0x14d4, 0x09bb: 0x392e, + 0x09bc: 0x393e, 0x09bd: 0x3930, 0x09be: 0x39fe, 0x09bf: 0x3900, // Block 0x27, offset 0x9c0 - 0x09c1: 0x087d, - 0x09d3: 0x0884, - 0x09dd: 0x088b, - 0x09e2: 0x0892, - 0x09e7: 0x0899, - 0x09ec: 0x08a0, - 0x09f9: 0x08a7, + 0x09c0: 0x13f7, 0x09c1: 0x0007, 0x09c2: 0x093d, 0x09c3: 0x0984, 0x09c4: 0x093f, 0x09c5: 0x0941, + 0x09c6: 0x098c, 0x09c7: 0x094c, 0x09c8: 0x0494, 0x09c9: 0x097c, 0x09ca: 0x0499, 0x09cb: 0x094e, + 0x09cc: 0x04c5, 0x09cd: 0x0950, 0x09ce: 0x14a0, 0x09cf: 0x001e, 0x09d0: 0x0960, 0x09d1: 0x17fa, + 0x09d2: 0x049b, 0x09d3: 0x02c8, 0x09d4: 0x0962, 0x09d5: 0x0964, 0x09d6: 0x096d, 0x09d7: 0x04a6, + 0x09d8: 0x04c7, 0x09d9: 0x04a8, 0x09da: 0x09df, 0x09db: 0x3902, 0x09dc: 0x3a00, 0x09dd: 0x3904, + 0x09de: 0x3a02, 0x09df: 0x3a04, 0x09e0: 0x3a08, 0x09e1: 0x38e6, 0x09e2: 0x391e, 0x09e3: 0x3922, + 0x09e4: 0x38e2, 0x09e5: 0x3a0c, 0x09e6: 0x2321, 0x09e7: 0x3a10, 0x09e8: 0x3a14, 0x09e9: 0x3a18, + 0x09ea: 0x3a1c, 0x09eb: 0x3a20, 0x09ec: 0x3a24, 0x09ed: 0x3a28, 0x09ee: 0x3a2c, 0x09ef: 0x3a30, + 0x09f0: 0x3a34, 0x09f1: 0x2269, 0x09f2: 0x226d, 0x09f3: 0x2271, 0x09f4: 0x2275, 0x09f5: 0x2279, + 0x09f6: 0x227d, 0x09f7: 0x2281, 0x09f8: 0x2285, 0x09f9: 0x2289, 0x09fa: 0x228d, 0x09fb: 0x2291, + 0x09fc: 0x2295, 0x09fd: 0x2299, 0x09fe: 0x229d, 0x09ff: 0x22a1, // Block 0x28, offset 0xa00 - 0x0a26: 0x08ae, + 0x0a00: 0x0906, 0x0a01: 0x090b, 0x0a02: 0x14ad, 0x0a03: 0x090d, 0x0a04: 0x090f, 0x0a05: 0x14d9, + 0x0a06: 0x0914, 0x0a07: 0x0916, 0x0a08: 0x0918, 0x0a09: 0x091a, 0x0a0a: 0x091c, 0x0a0b: 0x091e, + 0x0a0c: 0x0920, 0x0a0d: 0x0922, 0x0a0e: 0x0924, 0x0a0f: 0x0929, 0x0a10: 0x14c8, 0x0a11: 0x092b, + 0x0a12: 0x17f6, 0x0a13: 0x092d, 0x0a14: 0x092f, 0x0a15: 0x155f, 0x0a16: 0x0931, 0x0a17: 0x1570, + 0x0a18: 0x17f8, 0x0a19: 0x14d4, 0x0a1a: 0x0007, 0x0a1b: 0x093d, 0x0a1c: 0x0984, 0x0a1d: 0x093f, + 0x0a1e: 0x0941, 0x0a1f: 0x098c, 0x0a20: 0x094c, 0x0a21: 0x0494, 0x0a22: 0x097c, 0x0a23: 0x0499, + 0x0a24: 0x094e, 0x0a25: 0x04c5, 0x0a26: 0x0950, 0x0a27: 0x14a0, 0x0a28: 0x001e, 0x0a29: 0x0960, + 0x0a2a: 0x17fa, 0x0a2b: 0x049b, 0x0a2c: 0x02c8, 0x0a2d: 0x0962, 0x0a2e: 0x0964, 0x0a2f: 0x096d, + 0x0a30: 0x04a6, 0x0a31: 0x04c7, 0x0a32: 0x04a8, 0x0a33: 0x09df, 0x0a34: 0x0906, 0x0a35: 0x090b, + 0x0a36: 0x14ad, 0x0a37: 0x090d, 0x0a38: 0x090f, 0x0a39: 0x14d9, 0x0a3a: 0x0914, 0x0a3b: 0x0916, + 0x0a3c: 0x0918, 0x0a3d: 0x091a, 0x0a3e: 0x091c, 0x0a3f: 0x091e, // Block 0x29, offset 0xa40 - 0x0a7c: 0x08b5, + 0x0a40: 0x0920, 0x0a41: 0x0922, 0x0a42: 0x0924, 0x0a43: 0x0929, 0x0a44: 0x14c8, 0x0a45: 0x092b, + 0x0a46: 0x17f6, 0x0a47: 0x092d, 0x0a48: 0x092f, 0x0a49: 0x155f, 0x0a4a: 0x0931, 0x0a4b: 0x1570, + 0x0a4c: 0x17f8, 0x0a4d: 0x14d4, 0x0a4e: 0x0007, 0x0a4f: 0x093d, 0x0a50: 0x0984, 0x0a51: 0x093f, + 0x0a52: 0x0941, 0x0a53: 0x098c, 0x0a54: 0x094c, 0x0a56: 0x097c, 0x0a57: 0x0499, + 0x0a58: 0x094e, 0x0a59: 0x04c5, 0x0a5a: 0x0950, 0x0a5b: 0x14a0, 0x0a5c: 0x001e, 0x0a5d: 0x0960, + 0x0a5e: 0x17fa, 0x0a5f: 0x049b, 0x0a60: 0x02c8, 0x0a61: 0x0962, 0x0a62: 0x0964, 0x0a63: 0x096d, + 0x0a64: 0x04a6, 0x0a65: 0x04c7, 0x0a66: 0x04a8, 0x0a67: 0x09df, 0x0a68: 0x0906, 0x0a69: 0x090b, + 0x0a6a: 0x14ad, 0x0a6b: 0x090d, 0x0a6c: 0x090f, 0x0a6d: 0x14d9, 0x0a6e: 0x0914, 0x0a6f: 0x0916, + 0x0a70: 0x0918, 0x0a71: 0x091a, 0x0a72: 0x091c, 0x0a73: 0x091e, 0x0a74: 0x0920, 0x0a75: 0x0922, + 0x0a76: 0x0924, 0x0a77: 0x0929, 0x0a78: 0x14c8, 0x0a79: 0x092b, 0x0a7a: 0x17f6, 0x0a7b: 0x092d, + 0x0a7c: 0x092f, 0x0a7d: 0x155f, 0x0a7e: 0x0931, 0x0a7f: 0x1570, // Block 0x2a, offset 0xa80 - 0x0a86: 0x08b9, 0x0a88: 0x08c0, 0x0a8a: 0x08c7, - 0x0a8c: 0x08ce, 0x0a8e: 0x08d5, - 0x0a92: 0x08dc, - 0x0abb: 0x08e3, - 0x0abd: 0x08ea, + 0x0a80: 0x17f8, 0x0a81: 0x14d4, 0x0a82: 0x0007, 0x0a83: 0x093d, 0x0a84: 0x0984, 0x0a85: 0x093f, + 0x0a86: 0x0941, 0x0a87: 0x098c, 0x0a88: 0x094c, 0x0a89: 0x0494, 0x0a8a: 0x097c, 0x0a8b: 0x0499, + 0x0a8c: 0x094e, 0x0a8d: 0x04c5, 0x0a8e: 0x0950, 0x0a8f: 0x14a0, 0x0a90: 0x001e, 0x0a91: 0x0960, + 0x0a92: 0x17fa, 0x0a93: 0x049b, 0x0a94: 0x02c8, 0x0a95: 0x0962, 0x0a96: 0x0964, 0x0a97: 0x096d, + 0x0a98: 0x04a6, 0x0a99: 0x04c7, 0x0a9a: 0x04a8, 0x0a9b: 0x09df, 0x0a9c: 0x0906, + 0x0a9e: 0x14ad, 0x0a9f: 0x090d, 0x0aa2: 0x0914, + 0x0aa5: 0x091a, 0x0aa6: 0x091c, 0x0aa9: 0x0922, + 0x0aaa: 0x0924, 0x0aab: 0x0929, 0x0aac: 0x14c8, 0x0aae: 0x17f6, 0x0aaf: 0x092d, + 0x0ab0: 0x092f, 0x0ab1: 0x155f, 0x0ab2: 0x0931, 0x0ab3: 0x1570, 0x0ab4: 0x17f8, 0x0ab5: 0x14d4, + 0x0ab6: 0x0007, 0x0ab7: 0x093d, 0x0ab8: 0x0984, 0x0ab9: 0x093f, 0x0abb: 0x098c, + 0x0abd: 0x0494, 0x0abe: 0x097c, 0x0abf: 0x0499, // Block 0x2b, offset 0xac0 - 0x0ac0: 0x08f1, 0x0ac1: 0x08f8, 0x0ac3: 0x08ff, + 0x0ac0: 0x094e, 0x0ac1: 0x04c5, 0x0ac2: 0x0950, 0x0ac3: 0x14a0, 0x0ac5: 0x0960, + 0x0ac6: 0x17fa, 0x0ac7: 0x049b, 0x0ac8: 0x02c8, 0x0ac9: 0x0962, 0x0aca: 0x0964, 0x0acb: 0x096d, + 0x0acc: 0x04a6, 0x0acd: 0x04c7, 0x0ace: 0x04a8, 0x0acf: 0x09df, 0x0ad0: 0x0906, 0x0ad1: 0x090b, + 0x0ad2: 0x14ad, 0x0ad3: 0x090d, 0x0ad4: 0x090f, 0x0ad5: 0x14d9, 0x0ad6: 0x0914, 0x0ad7: 0x0916, + 0x0ad8: 0x0918, 0x0ad9: 0x091a, 0x0ada: 0x091c, 0x0adb: 0x091e, 0x0adc: 0x0920, 0x0add: 0x0922, + 0x0ade: 0x0924, 0x0adf: 0x0929, 0x0ae0: 0x14c8, 0x0ae1: 0x092b, 0x0ae2: 0x17f6, 0x0ae3: 0x092d, + 0x0ae4: 0x092f, 0x0ae5: 0x155f, 0x0ae6: 0x0931, 0x0ae7: 0x1570, 0x0ae8: 0x17f8, 0x0ae9: 0x14d4, + 0x0aea: 0x0007, 0x0aeb: 0x093d, 0x0aec: 0x0984, 0x0aed: 0x093f, 0x0aee: 0x0941, 0x0aef: 0x098c, + 0x0af0: 0x094c, 0x0af1: 0x0494, 0x0af2: 0x097c, 0x0af3: 0x0499, 0x0af4: 0x094e, 0x0af5: 0x04c5, + 0x0af6: 0x0950, 0x0af7: 0x14a0, 0x0af8: 0x001e, 0x0af9: 0x0960, 0x0afa: 0x17fa, 0x0afb: 0x049b, + 0x0afc: 0x02c8, 0x0afd: 0x0962, 0x0afe: 0x0964, 0x0aff: 0x096d, // Block 0x2c, offset 0xb00 - 0x0b2c: 0x0906, 0x0b2d: 0x0908, 0x0b2e: 0x090b, - 0x0b30: 0x090d, 0x0b31: 0x090f, 0x0b32: 0x0911, 0x0b33: 0x0914, 0x0b34: 0x0916, 0x0b35: 0x0918, - 0x0b36: 0x091a, 0x0b37: 0x091c, 0x0b38: 0x091e, 0x0b39: 0x0920, 0x0b3a: 0x0922, - 0x0b3c: 0x0924, 0x0b3d: 0x0926, 0x0b3e: 0x0929, 0x0b3f: 0x092b, + 0x0b00: 0x04a6, 0x0b01: 0x04c7, 0x0b02: 0x04a8, 0x0b03: 0x09df, 0x0b04: 0x0906, 0x0b05: 0x090b, + 0x0b07: 0x090d, 0x0b08: 0x090f, 0x0b09: 0x14d9, 0x0b0a: 0x0914, + 0x0b0d: 0x091a, 0x0b0e: 0x091c, 0x0b0f: 0x091e, 0x0b10: 0x0920, 0x0b11: 0x0922, + 0x0b12: 0x0924, 0x0b13: 0x0929, 0x0b14: 0x14c8, 0x0b16: 0x17f6, 0x0b17: 0x092d, + 0x0b18: 0x092f, 0x0b19: 0x155f, 0x0b1a: 0x0931, 0x0b1b: 0x1570, 0x0b1c: 0x17f8, + 0x0b1e: 0x0007, 0x0b1f: 0x093d, 0x0b20: 0x0984, 0x0b21: 0x093f, 0x0b22: 0x0941, 0x0b23: 0x098c, + 0x0b24: 0x094c, 0x0b25: 0x0494, 0x0b26: 0x097c, 0x0b27: 0x0499, 0x0b28: 0x094e, 0x0b29: 0x04c5, + 0x0b2a: 0x0950, 0x0b2b: 0x14a0, 0x0b2c: 0x001e, 0x0b2d: 0x0960, 0x0b2e: 0x17fa, 0x0b2f: 0x049b, + 0x0b30: 0x02c8, 0x0b31: 0x0962, 0x0b32: 0x0964, 0x0b33: 0x096d, 0x0b34: 0x04a6, 0x0b35: 0x04c7, + 0x0b36: 0x04a8, 0x0b37: 0x09df, 0x0b38: 0x0906, 0x0b39: 0x090b, 0x0b3b: 0x090d, + 0x0b3c: 0x090f, 0x0b3d: 0x14d9, 0x0b3e: 0x0914, // Block 0x2d, offset 0xb40 - 0x0b40: 0x092d, 0x0b41: 0x092f, 0x0b42: 0x0931, 0x0b43: 0x0007, 0x0b44: 0x0933, 0x0b45: 0x0936, - 0x0b46: 0x0939, 0x0b47: 0x093d, 0x0b48: 0x093f, 0x0b49: 0x0941, 0x0b4a: 0x0943, 0x0b4b: 0x0946, - 0x0b4c: 0x0949, 0x0b4d: 0x094c, 0x0b4f: 0x094e, 0x0b50: 0x0950, 0x0b51: 0x0952, - 0x0b52: 0x001e, 0x0b53: 0x0955, 0x0b54: 0x0958, 0x0b55: 0x095c, 0x0b56: 0x0960, 0x0b57: 0x0962, - 0x0b58: 0x0964, 0x0b59: 0x0966, 0x0b5a: 0x096a, 0x0b5b: 0x096d, 0x0b5c: 0x096f, 0x0b5d: 0x0559, - 0x0b5e: 0x0973, 0x0b5f: 0x0976, 0x0b60: 0x056c, 0x0b61: 0x0979, 0x0b62: 0x097c, 0x0b63: 0x049b, - 0x0b64: 0x0964, 0x0b65: 0x096d, 0x0b66: 0x0559, 0x0b67: 0x0973, 0x0b68: 0x0575, 0x0b69: 0x056c, - 0x0b6a: 0x0979, - 0x0b78: 0x097e, + 0x0b40: 0x0918, 0x0b41: 0x091a, 0x0b42: 0x091c, 0x0b43: 0x091e, 0x0b44: 0x0920, + 0x0b46: 0x0924, 0x0b4a: 0x17f6, 0x0b4b: 0x092d, + 0x0b4c: 0x092f, 0x0b4d: 0x155f, 0x0b4e: 0x0931, 0x0b4f: 0x1570, 0x0b50: 0x17f8, + 0x0b52: 0x0007, 0x0b53: 0x093d, 0x0b54: 0x0984, 0x0b55: 0x093f, 0x0b56: 0x0941, 0x0b57: 0x098c, + 0x0b58: 0x094c, 0x0b59: 0x0494, 0x0b5a: 0x097c, 0x0b5b: 0x0499, 0x0b5c: 0x094e, 0x0b5d: 0x04c5, + 0x0b5e: 0x0950, 0x0b5f: 0x14a0, 0x0b60: 0x001e, 0x0b61: 0x0960, 0x0b62: 0x17fa, 0x0b63: 0x049b, + 0x0b64: 0x02c8, 0x0b65: 0x0962, 0x0b66: 0x0964, 0x0b67: 0x096d, 0x0b68: 0x04a6, 0x0b69: 0x04c7, + 0x0b6a: 0x04a8, 0x0b6b: 0x09df, 0x0b6c: 0x0906, 0x0b6d: 0x090b, 0x0b6e: 0x14ad, 0x0b6f: 0x090d, + 0x0b70: 0x090f, 0x0b71: 0x14d9, 0x0b72: 0x0914, 0x0b73: 0x0916, 0x0b74: 0x0918, 0x0b75: 0x091a, + 0x0b76: 0x091c, 0x0b77: 0x091e, 0x0b78: 0x0920, 0x0b79: 0x0922, 0x0b7a: 0x0924, 0x0b7b: 0x0929, + 0x0b7c: 0x14c8, 0x0b7d: 0x092b, 0x0b7e: 0x17f6, 0x0b7f: 0x092d, // Block 0x2e, offset 0xb80 - 0x0b9b: 0x0981, 0x0b9c: 0x0984, 0x0b9d: 0x0986, - 0x0b9e: 0x0989, 0x0b9f: 0x0949, 0x0ba0: 0x098c, 0x0ba1: 0x098e, 0x0ba2: 0x0991, 0x0ba3: 0x0994, - 0x0ba4: 0x0997, 0x0ba5: 0x099a, 0x0ba6: 0x099d, 0x0ba7: 0x09a0, 0x0ba8: 0x09a4, 0x0ba9: 0x09a7, - 0x0baa: 0x09aa, 0x0bab: 0x09ae, 0x0bac: 0x09b1, 0x0bad: 0x09b4, 0x0bae: 0x09b7, 0x0baf: 0x09ba, - 0x0bb0: 0x09bd, 0x0bb1: 0x09c0, 0x0bb2: 0x09c3, 0x0bb3: 0x09c6, 0x0bb4: 0x09c9, 0x0bb5: 0x09cc, - 0x0bb6: 0x09cf, 0x0bb7: 0x09d2, 0x0bb8: 0x09d5, 0x0bb9: 0x09d9, 0x0bba: 0x09dc, 0x0bbb: 0x09df, - 0x0bbc: 0x09e1, 0x0bbd: 0x09e4, 0x0bbe: 0x09e7, 0x0bbf: 0x055c, + 0x0b80: 0x092f, 0x0b81: 0x155f, 0x0b82: 0x0931, 0x0b83: 0x1570, 0x0b84: 0x17f8, 0x0b85: 0x14d4, + 0x0b86: 0x0007, 0x0b87: 0x093d, 0x0b88: 0x0984, 0x0b89: 0x093f, 0x0b8a: 0x0941, 0x0b8b: 0x098c, + 0x0b8c: 0x094c, 0x0b8d: 0x0494, 0x0b8e: 0x097c, 0x0b8f: 0x0499, 0x0b90: 0x094e, 0x0b91: 0x04c5, + 0x0b92: 0x0950, 0x0b93: 0x14a0, 0x0b94: 0x001e, 0x0b95: 0x0960, 0x0b96: 0x17fa, 0x0b97: 0x049b, + 0x0b98: 0x02c8, 0x0b99: 0x0962, 0x0b9a: 0x0964, 0x0b9b: 0x096d, 0x0b9c: 0x04a6, 0x0b9d: 0x04c7, + 0x0b9e: 0x04a8, 0x0b9f: 0x09df, 0x0ba0: 0x0906, 0x0ba1: 0x090b, 0x0ba2: 0x14ad, 0x0ba3: 0x090d, + 0x0ba4: 0x090f, 0x0ba5: 0x14d9, 0x0ba6: 0x0914, 0x0ba7: 0x0916, 0x0ba8: 0x0918, 0x0ba9: 0x091a, + 0x0baa: 0x091c, 0x0bab: 0x091e, 0x0bac: 0x0920, 0x0bad: 0x0922, 0x0bae: 0x0924, 0x0baf: 0x0929, + 0x0bb0: 0x14c8, 0x0bb1: 0x092b, 0x0bb2: 0x17f6, 0x0bb3: 0x092d, 0x0bb4: 0x092f, 0x0bb5: 0x155f, + 0x0bb6: 0x0931, 0x0bb7: 0x1570, 0x0bb8: 0x17f8, 0x0bb9: 0x14d4, 0x0bba: 0x0007, 0x0bbb: 0x093d, + 0x0bbc: 0x0984, 0x0bbd: 0x093f, 0x0bbe: 0x0941, 0x0bbf: 0x098c, // Block 0x2f, offset 0xbc0 - 0x0bc0: 0x09ea, 0x0bc1: 0x09ee, 0x0bc2: 0x09f2, 0x0bc3: 0x09f6, 0x0bc4: 0x09fa, 0x0bc5: 0x09fe, - 0x0bc6: 0x0a02, 0x0bc7: 0x0a06, 0x0bc8: 0x0a0a, 0x0bc9: 0x0a10, 0x0bca: 0x0a16, 0x0bcb: 0x0a1a, - 0x0bcc: 0x0a1e, 0x0bcd: 0x0a22, 0x0bce: 0x0a26, 0x0bcf: 0x0a2a, 0x0bd0: 0x0a2e, 0x0bd1: 0x0a32, - 0x0bd2: 0x0a36, 0x0bd3: 0x0a3a, 0x0bd4: 0x0a3e, 0x0bd5: 0x0a44, 0x0bd6: 0x0a4a, 0x0bd7: 0x0a50, - 0x0bd8: 0x0a56, 0x0bd9: 0x0a5a, 0x0bda: 0x0a5e, 0x0bdb: 0x0a62, 0x0bdc: 0x0a66, 0x0bdd: 0x0a6c, - 0x0bde: 0x0a72, 0x0bdf: 0x0a76, 0x0be0: 0x0a7a, 0x0be1: 0x0a7e, 0x0be2: 0x0a82, 0x0be3: 0x0a86, - 0x0be4: 0x0a8a, 0x0be5: 0x0a8e, 0x0be6: 0x0a92, 0x0be7: 0x0a96, 0x0be8: 0x0a9a, 0x0be9: 0x0a9e, - 0x0bea: 0x0aa2, 0x0beb: 0x0aa6, 0x0bec: 0x0aaa, 0x0bed: 0x0aae, 0x0bee: 0x0ab2, 0x0bef: 0x0ab8, - 0x0bf0: 0x0abe, 0x0bf1: 0x0ac2, 0x0bf2: 0x0ac6, 0x0bf3: 0x0aca, 0x0bf4: 0x0ace, 0x0bf5: 0x0ad2, - 0x0bf6: 0x0ad6, 0x0bf7: 0x0ada, 0x0bf8: 0x0ade, 0x0bf9: 0x0ae4, 0x0bfa: 0x0aea, 0x0bfb: 0x0aee, - 0x0bfc: 0x0af2, 0x0bfd: 0x0af6, 0x0bfe: 0x0afa, 0x0bff: 0x0afe, + 0x0bc0: 0x094c, 0x0bc1: 0x0494, 0x0bc2: 0x097c, 0x0bc3: 0x0499, 0x0bc4: 0x094e, 0x0bc5: 0x04c5, + 0x0bc6: 0x0950, 0x0bc7: 0x14a0, 0x0bc8: 0x001e, 0x0bc9: 0x0960, 0x0bca: 0x17fa, 0x0bcb: 0x049b, + 0x0bcc: 0x02c8, 0x0bcd: 0x0962, 0x0bce: 0x0964, 0x0bcf: 0x096d, 0x0bd0: 0x04a6, 0x0bd1: 0x04c7, + 0x0bd2: 0x04a8, 0x0bd3: 0x09df, 0x0bd4: 0x0906, 0x0bd5: 0x090b, 0x0bd6: 0x14ad, 0x0bd7: 0x090d, + 0x0bd8: 0x090f, 0x0bd9: 0x14d9, 0x0bda: 0x0914, 0x0bdb: 0x0916, 0x0bdc: 0x0918, 0x0bdd: 0x091a, + 0x0bde: 0x091c, 0x0bdf: 0x091e, 0x0be0: 0x0920, 0x0be1: 0x0922, 0x0be2: 0x0924, 0x0be3: 0x0929, + 0x0be4: 0x14c8, 0x0be5: 0x092b, 0x0be6: 0x17f6, 0x0be7: 0x092d, 0x0be8: 0x092f, 0x0be9: 0x155f, + 0x0bea: 0x0931, 0x0beb: 0x1570, 0x0bec: 0x17f8, 0x0bed: 0x14d4, 0x0bee: 0x0007, 0x0bef: 0x093d, + 0x0bf0: 0x0984, 0x0bf1: 0x093f, 0x0bf2: 0x0941, 0x0bf3: 0x098c, 0x0bf4: 0x094c, 0x0bf5: 0x0494, + 0x0bf6: 0x097c, 0x0bf7: 0x0499, 0x0bf8: 0x094e, 0x0bf9: 0x04c5, 0x0bfa: 0x0950, 0x0bfb: 0x14a0, + 0x0bfc: 0x001e, 0x0bfd: 0x0960, 0x0bfe: 0x17fa, 0x0bff: 0x049b, // Block 0x30, offset 0xc00 - 0x0c00: 0x0b02, 0x0c01: 0x0b06, 0x0c02: 0x0b0a, 0x0c03: 0x0b0e, 0x0c04: 0x0b12, 0x0c05: 0x0b16, - 0x0c06: 0x0b1a, 0x0c07: 0x0b1e, 0x0c08: 0x0b22, 0x0c09: 0x0b26, 0x0c0a: 0x0b2a, 0x0c0b: 0x0b2e, - 0x0c0c: 0x0b32, 0x0c0d: 0x0b38, 0x0c0e: 0x0b3e, 0x0c0f: 0x0b44, 0x0c10: 0x0b4a, 0x0c11: 0x0b50, - 0x0c12: 0x0b56, 0x0c13: 0x0b5c, 0x0c14: 0x0b62, 0x0c15: 0x0b66, 0x0c16: 0x0b6a, 0x0c17: 0x0b6e, - 0x0c18: 0x0b72, 0x0c19: 0x0b76, 0x0c1a: 0x0b7a, 0x0c1b: 0x0b7e, 0x0c1c: 0x0b82, 0x0c1d: 0x0b88, - 0x0c1e: 0x0b8e, 0x0c1f: 0x0b92, 0x0c20: 0x0b96, 0x0c21: 0x0b9a, 0x0c22: 0x0b9e, 0x0c23: 0x0ba2, - 0x0c24: 0x0ba6, 0x0c25: 0x0bac, 0x0c26: 0x0bb2, 0x0c27: 0x0bb8, 0x0c28: 0x0bbe, 0x0c29: 0x0bc4, - 0x0c2a: 0x0bca, 0x0c2b: 0x0bce, 0x0c2c: 0x0bd2, 0x0c2d: 0x0bd6, 0x0c2e: 0x0bda, 0x0c2f: 0x0bde, - 0x0c30: 0x0be2, 0x0c31: 0x0be6, 0x0c32: 0x0bea, 0x0c33: 0x0bee, 0x0c34: 0x0bf2, 0x0c35: 0x0bf6, - 0x0c36: 0x0bfa, 0x0c37: 0x0bfe, 0x0c38: 0x0c02, 0x0c39: 0x0c08, 0x0c3a: 0x0c0e, 0x0c3b: 0x0c14, - 0x0c3c: 0x0c1a, 0x0c3d: 0x0c1e, 0x0c3e: 0x0c22, 0x0c3f: 0x0c26, + 0x0c00: 0x02c8, 0x0c01: 0x0962, 0x0c02: 0x0964, 0x0c03: 0x096d, 0x0c04: 0x04a6, 0x0c05: 0x04c7, + 0x0c06: 0x04a8, 0x0c07: 0x09df, 0x0c08: 0x0906, 0x0c09: 0x090b, 0x0c0a: 0x14ad, 0x0c0b: 0x090d, + 0x0c0c: 0x090f, 0x0c0d: 0x14d9, 0x0c0e: 0x0914, 0x0c0f: 0x0916, 0x0c10: 0x0918, 0x0c11: 0x091a, + 0x0c12: 0x091c, 0x0c13: 0x091e, 0x0c14: 0x0920, 0x0c15: 0x0922, 0x0c16: 0x0924, 0x0c17: 0x0929, + 0x0c18: 0x14c8, 0x0c19: 0x092b, 0x0c1a: 0x17f6, 0x0c1b: 0x092d, 0x0c1c: 0x092f, 0x0c1d: 0x155f, + 0x0c1e: 0x0931, 0x0c1f: 0x1570, 0x0c20: 0x17f8, 0x0c21: 0x14d4, 0x0c22: 0x0007, 0x0c23: 0x093d, + 0x0c24: 0x0984, 0x0c25: 0x093f, 0x0c26: 0x0941, 0x0c27: 0x098c, 0x0c28: 0x094c, 0x0c29: 0x0494, + 0x0c2a: 0x097c, 0x0c2b: 0x0499, 0x0c2c: 0x094e, 0x0c2d: 0x04c5, 0x0c2e: 0x0950, 0x0c2f: 0x14a0, + 0x0c30: 0x001e, 0x0c31: 0x0960, 0x0c32: 0x17fa, 0x0c33: 0x049b, 0x0c34: 0x02c8, 0x0c35: 0x0962, + 0x0c36: 0x0964, 0x0c37: 0x096d, 0x0c38: 0x04a6, 0x0c39: 0x04c7, 0x0c3a: 0x04a8, 0x0c3b: 0x09df, + 0x0c3c: 0x0906, 0x0c3d: 0x090b, 0x0c3e: 0x14ad, 0x0c3f: 0x090d, // Block 0x31, offset 0xc40 - 0x0c40: 0x0c2a, 0x0c41: 0x0c2e, 0x0c42: 0x0c32, 0x0c43: 0x0c36, 0x0c44: 0x0c3a, 0x0c45: 0x0c3e, - 0x0c46: 0x0c42, 0x0c47: 0x0c46, 0x0c48: 0x0c4a, 0x0c49: 0x0c4e, 0x0c4a: 0x0c52, 0x0c4b: 0x0c56, - 0x0c4c: 0x0c5a, 0x0c4d: 0x0c5e, 0x0c4e: 0x0c62, 0x0c4f: 0x0c66, 0x0c50: 0x0c6a, 0x0c51: 0x0c6e, - 0x0c52: 0x0c72, 0x0c53: 0x0c76, 0x0c54: 0x0c7a, 0x0c55: 0x0c7e, 0x0c56: 0x0c82, 0x0c57: 0x0c86, - 0x0c58: 0x0c8a, 0x0c59: 0x0c8e, 0x0c5a: 0x0c92, 0x0c5b: 0x0b9a, - 0x0c60: 0x0c9b, 0x0c61: 0x0c9f, 0x0c62: 0x0ca3, 0x0c63: 0x0ca7, - 0x0c64: 0x0cab, 0x0c65: 0x0cb1, 0x0c66: 0x0cb7, 0x0c67: 0x0cbd, 0x0c68: 0x0cc3, 0x0c69: 0x0cc9, - 0x0c6a: 0x0ccf, 0x0c6b: 0x0cd5, 0x0c6c: 0x0cdb, 0x0c6d: 0x0ce1, 0x0c6e: 0x0ce7, 0x0c6f: 0x0ced, - 0x0c70: 0x0cf3, 0x0c71: 0x0cf9, 0x0c72: 0x0cff, 0x0c73: 0x0d05, 0x0c74: 0x0d0b, 0x0c75: 0x0d11, - 0x0c76: 0x0d17, 0x0c77: 0x0d1d, 0x0c78: 0x0d23, 0x0c79: 0x0d27, 0x0c7a: 0x0d2b, 0x0c7b: 0x0d2f, - 0x0c7c: 0x0d33, 0x0c7d: 0x0d37, 0x0c7e: 0x0d3b, 0x0c7f: 0x0d41, + 0x0c40: 0x090f, 0x0c41: 0x14d9, 0x0c42: 0x0914, 0x0c43: 0x0916, 0x0c44: 0x0918, 0x0c45: 0x091a, + 0x0c46: 0x091c, 0x0c47: 0x091e, 0x0c48: 0x0920, 0x0c49: 0x0922, 0x0c4a: 0x0924, 0x0c4b: 0x0929, + 0x0c4c: 0x14c8, 0x0c4d: 0x092b, 0x0c4e: 0x17f6, 0x0c4f: 0x092d, 0x0c50: 0x092f, 0x0c51: 0x155f, + 0x0c52: 0x0931, 0x0c53: 0x1570, 0x0c54: 0x17f8, 0x0c55: 0x14d4, 0x0c56: 0x0007, 0x0c57: 0x093d, + 0x0c58: 0x0984, 0x0c59: 0x093f, 0x0c5a: 0x0941, 0x0c5b: 0x098c, 0x0c5c: 0x094c, 0x0c5d: 0x0494, + 0x0c5e: 0x097c, 0x0c5f: 0x0499, 0x0c60: 0x094e, 0x0c61: 0x04c5, 0x0c62: 0x0950, 0x0c63: 0x14a0, + 0x0c64: 0x001e, 0x0c65: 0x0960, 0x0c66: 0x17fa, 0x0c67: 0x049b, 0x0c68: 0x02c8, 0x0c69: 0x0962, + 0x0c6a: 0x0964, 0x0c6b: 0x096d, 0x0c6c: 0x04a6, 0x0c6d: 0x04c7, 0x0c6e: 0x04a8, 0x0c6f: 0x09df, + 0x0c70: 0x0906, 0x0c71: 0x090b, 0x0c72: 0x14ad, 0x0c73: 0x090d, 0x0c74: 0x090f, 0x0c75: 0x14d9, + 0x0c76: 0x0914, 0x0c77: 0x0916, 0x0c78: 0x0918, 0x0c79: 0x091a, 0x0c7a: 0x091c, 0x0c7b: 0x091e, + 0x0c7c: 0x0920, 0x0c7d: 0x0922, 0x0c7e: 0x0924, 0x0c7f: 0x0929, // Block 0x32, offset 0xc80 - 0x0c80: 0x0d47, 0x0c81: 0x0d4d, 0x0c82: 0x0d53, 0x0c83: 0x0d59, 0x0c84: 0x0d5f, 0x0c85: 0x0d65, - 0x0c86: 0x0d6b, 0x0c87: 0x0d71, 0x0c88: 0x0d77, 0x0c89: 0x0d7b, 0x0c8a: 0x0d7f, 0x0c8b: 0x0d83, - 0x0c8c: 0x0d87, 0x0c8d: 0x0d8b, 0x0c8e: 0x0d8f, 0x0c8f: 0x0d93, 0x0c90: 0x0d97, 0x0c91: 0x0d9d, - 0x0c92: 0x0da3, 0x0c93: 0x0da9, 0x0c94: 0x0daf, 0x0c95: 0x0db5, 0x0c96: 0x0dbb, 0x0c97: 0x0dc1, - 0x0c98: 0x0dc7, 0x0c99: 0x0dcd, 0x0c9a: 0x0dd3, 0x0c9b: 0x0dd9, 0x0c9c: 0x0ddf, 0x0c9d: 0x0de5, - 0x0c9e: 0x0deb, 0x0c9f: 0x0df1, 0x0ca0: 0x0df7, 0x0ca1: 0x0dfd, 0x0ca2: 0x0e03, 0x0ca3: 0x0e09, - 0x0ca4: 0x0e0f, 0x0ca5: 0x0e13, 0x0ca6: 0x0e17, 0x0ca7: 0x0e1b, 0x0ca8: 0x0e1f, 0x0ca9: 0x0e25, - 0x0caa: 0x0e2b, 0x0cab: 0x0e31, 0x0cac: 0x0e37, 0x0cad: 0x0e3d, 0x0cae: 0x0e43, 0x0caf: 0x0e49, - 0x0cb0: 0x0e4f, 0x0cb1: 0x0e55, 0x0cb2: 0x0e5b, 0x0cb3: 0x0e5f, 0x0cb4: 0x0e63, 0x0cb5: 0x0e67, - 0x0cb6: 0x0e6b, 0x0cb7: 0x0e6f, 0x0cb8: 0x0e73, 0x0cb9: 0x0e77, + 0x0c80: 0x14c8, 0x0c81: 0x092b, 0x0c82: 0x17f6, 0x0c83: 0x092d, 0x0c84: 0x092f, 0x0c85: 0x155f, + 0x0c86: 0x0931, 0x0c87: 0x1570, 0x0c88: 0x17f8, 0x0c89: 0x14d4, 0x0c8a: 0x0007, 0x0c8b: 0x093d, + 0x0c8c: 0x0984, 0x0c8d: 0x093f, 0x0c8e: 0x0941, 0x0c8f: 0x098c, 0x0c90: 0x094c, 0x0c91: 0x0494, + 0x0c92: 0x097c, 0x0c93: 0x0499, 0x0c94: 0x094e, 0x0c95: 0x04c5, 0x0c96: 0x0950, 0x0c97: 0x14a0, + 0x0c98: 0x001e, 0x0c99: 0x0960, 0x0c9a: 0x17fa, 0x0c9b: 0x049b, 0x0c9c: 0x02c8, 0x0c9d: 0x0962, + 0x0c9e: 0x0964, 0x0c9f: 0x096d, 0x0ca0: 0x04a6, 0x0ca1: 0x04c7, 0x0ca2: 0x04a8, 0x0ca3: 0x09df, + 0x0ca4: 0x3b27, 0x0ca5: 0x3b2a, 0x0ca8: 0x3b2d, 0x0ca9: 0x3b30, + 0x0caa: 0x14eb, 0x0cab: 0x3b33, 0x0cac: 0x3b36, 0x0cad: 0x3b39, 0x0cae: 0x3b3c, 0x0caf: 0x057b, + 0x0cb0: 0x3b3f, 0x0cb1: 0x3b42, 0x0cb2: 0x3b45, 0x0cb3: 0x3b48, 0x0cb4: 0x3b4b, 0x0cb5: 0x3b4e, + 0x0cb6: 0x3b51, 0x0cb7: 0x14ee, 0x0cb8: 0x3b54, 0x0cb9: 0x057b, 0x0cba: 0x0581, 0x0cbb: 0x3b57, + 0x0cbc: 0x055f, 0x0cbd: 0x3b5a, 0x0cbe: 0x3b5d, 0x0cbf: 0x3b60, // Block 0x33, offset 0xcc0 - 0x0cc0: 0x0e7b, 0x0cc1: 0x0e80, 0x0cc2: 0x0e85, 0x0cc3: 0x0e8c, 0x0cc4: 0x0e93, 0x0cc5: 0x0e9a, - 0x0cc6: 0x0ea1, 0x0cc7: 0x0ea8, 0x0cc8: 0x0eaf, 0x0cc9: 0x0eb4, 0x0cca: 0x0eb9, 0x0ccb: 0x0ec0, - 0x0ccc: 0x0ec7, 0x0ccd: 0x0ece, 0x0cce: 0x0ed5, 0x0ccf: 0x0edc, 0x0cd0: 0x0ee3, 0x0cd1: 0x0ee8, - 0x0cd2: 0x0eed, 0x0cd3: 0x0ef4, 0x0cd4: 0x0efb, 0x0cd5: 0x0f02, - 0x0cd8: 0x0f09, 0x0cd9: 0x0f0e, 0x0cda: 0x0f13, 0x0cdb: 0x0f1a, 0x0cdc: 0x0f21, 0x0cdd: 0x0f28, - 0x0ce0: 0x0f2f, 0x0ce1: 0x0f34, 0x0ce2: 0x0f39, 0x0ce3: 0x0f40, - 0x0ce4: 0x0f47, 0x0ce5: 0x0f4e, 0x0ce6: 0x0f55, 0x0ce7: 0x0f5c, 0x0ce8: 0x0f63, 0x0ce9: 0x0f68, - 0x0cea: 0x0f6d, 0x0ceb: 0x0f74, 0x0cec: 0x0f7b, 0x0ced: 0x0f82, 0x0cee: 0x0f89, 0x0cef: 0x0f90, - 0x0cf0: 0x0f97, 0x0cf1: 0x0f9c, 0x0cf2: 0x0fa1, 0x0cf3: 0x0fa8, 0x0cf4: 0x0faf, 0x0cf5: 0x0fb6, - 0x0cf6: 0x0fbd, 0x0cf7: 0x0fc4, 0x0cf8: 0x0fcb, 0x0cf9: 0x0fd0, 0x0cfa: 0x0fd5, 0x0cfb: 0x0fdc, - 0x0cfc: 0x0fe3, 0x0cfd: 0x0fea, 0x0cfe: 0x0ff1, 0x0cff: 0x0ff8, + 0x0cc0: 0x14d6, 0x0cc1: 0x3b63, 0x0cc2: 0x3b67, 0x0cc3: 0x0559, 0x0cc4: 0x0973, 0x0cc5: 0x0976, + 0x0cc6: 0x057e, 0x0cc7: 0x3b6a, 0x0cc8: 0x3b6d, 0x0cc9: 0x055c, 0x0cca: 0x12fd, 0x0ccb: 0x0572, + 0x0ccc: 0x3b70, 0x0ccd: 0x0015, 0x0cce: 0x3b73, 0x0ccf: 0x3b76, 0x0cd0: 0x3b79, 0x0cd1: 0x056f, + 0x0cd2: 0x0575, 0x0cd3: 0x0578, 0x0cd4: 0x3b7c, 0x0cd5: 0x3b7f, 0x0cd6: 0x3b82, 0x0cd7: 0x056c, + 0x0cd8: 0x0979, 0x0cd9: 0x3b85, 0x0cda: 0x3b88, 0x0cdb: 0x3b8b, 0x0cdc: 0x057e, 0x0cdd: 0x055c, + 0x0cde: 0x0572, 0x0cdf: 0x056c, 0x0ce0: 0x0575, 0x0ce1: 0x056f, 0x0ce2: 0x3b2d, 0x0ce3: 0x3b30, + 0x0ce4: 0x14eb, 0x0ce5: 0x3b33, 0x0ce6: 0x3b36, 0x0ce7: 0x3b39, 0x0ce8: 0x3b3c, 0x0ce9: 0x057b, + 0x0cea: 0x3b3f, 0x0ceb: 0x3b42, 0x0cec: 0x3b45, 0x0ced: 0x3b48, 0x0cee: 0x3b4b, 0x0cef: 0x3b4e, + 0x0cf0: 0x3b51, 0x0cf1: 0x14ee, 0x0cf2: 0x3b54, 0x0cf3: 0x057b, 0x0cf4: 0x0581, 0x0cf5: 0x3b57, + 0x0cf6: 0x055f, 0x0cf7: 0x3b5a, 0x0cf8: 0x3b5d, 0x0cf9: 0x3b60, 0x0cfa: 0x14d6, 0x0cfb: 0x3b63, + 0x0cfc: 0x3b67, 0x0cfd: 0x0559, 0x0cfe: 0x0973, 0x0cff: 0x0976, // Block 0x34, offset 0xd00 - 0x0d00: 0x0fff, 0x0d01: 0x1004, 0x0d02: 0x1009, 0x0d03: 0x1010, 0x0d04: 0x1017, 0x0d05: 0x101e, - 0x0d08: 0x1025, 0x0d09: 0x102a, 0x0d0a: 0x102f, 0x0d0b: 0x1036, - 0x0d0c: 0x103d, 0x0d0d: 0x1044, 0x0d10: 0x104b, 0x0d11: 0x1050, - 0x0d12: 0x1055, 0x0d13: 0x105c, 0x0d14: 0x1063, 0x0d15: 0x106a, 0x0d16: 0x1071, 0x0d17: 0x1078, - 0x0d19: 0x107f, 0x0d1b: 0x1084, 0x0d1d: 0x108b, - 0x0d1f: 0x1092, 0x0d20: 0x1099, 0x0d21: 0x109e, 0x0d22: 0x10a3, 0x0d23: 0x10aa, - 0x0d24: 0x10b1, 0x0d25: 0x10b8, 0x0d26: 0x10bf, 0x0d27: 0x10c6, 0x0d28: 0x10cd, 0x0d29: 0x10d2, - 0x0d2a: 0x10d7, 0x0d2b: 0x10de, 0x0d2c: 0x10e5, 0x0d2d: 0x10ec, 0x0d2e: 0x10f3, 0x0d2f: 0x10fa, - 0x0d30: 0x1101, 0x0d31: 0x0525, 0x0d32: 0x1106, 0x0d33: 0x052a, 0x0d34: 0x110b, 0x0d35: 0x052f, - 0x0d36: 0x1110, 0x0d37: 0x0534, 0x0d38: 0x1115, 0x0d39: 0x054a, 0x0d3a: 0x111a, 0x0d3b: 0x054f, - 0x0d3c: 0x111f, 0x0d3d: 0x0554, + 0x0d00: 0x057e, 0x0d01: 0x3b6a, 0x0d02: 0x3b6d, 0x0d03: 0x055c, 0x0d04: 0x12fd, 0x0d05: 0x0572, + 0x0d06: 0x3b70, 0x0d07: 0x0015, 0x0d08: 0x3b73, 0x0d09: 0x3b76, 0x0d0a: 0x3b79, 0x0d0b: 0x056f, + 0x0d0c: 0x0575, 0x0d0d: 0x0578, 0x0d0e: 0x3b7c, 0x0d0f: 0x3b7f, 0x0d10: 0x3b82, 0x0d11: 0x056c, + 0x0d12: 0x0979, 0x0d13: 0x3b85, 0x0d14: 0x3b88, 0x0d15: 0x3b8b, 0x0d16: 0x057e, 0x0d17: 0x055c, + 0x0d18: 0x0572, 0x0d19: 0x056c, 0x0d1a: 0x0575, 0x0d1b: 0x056f, 0x0d1c: 0x3b2d, 0x0d1d: 0x3b30, + 0x0d1e: 0x14eb, 0x0d1f: 0x3b33, 0x0d20: 0x3b36, 0x0d21: 0x3b39, 0x0d22: 0x3b3c, 0x0d23: 0x057b, + 0x0d24: 0x3b3f, 0x0d25: 0x3b42, 0x0d26: 0x3b45, 0x0d27: 0x3b48, 0x0d28: 0x3b4b, 0x0d29: 0x3b4e, + 0x0d2a: 0x3b51, 0x0d2b: 0x14ee, 0x0d2c: 0x3b54, 0x0d2d: 0x057b, 0x0d2e: 0x0581, 0x0d2f: 0x3b57, + 0x0d30: 0x055f, 0x0d31: 0x3b5a, 0x0d32: 0x3b5d, 0x0d33: 0x3b60, 0x0d34: 0x14d6, 0x0d35: 0x3b63, + 0x0d36: 0x3b67, 0x0d37: 0x0559, 0x0d38: 0x0973, 0x0d39: 0x0976, 0x0d3a: 0x057e, 0x0d3b: 0x3b6a, + 0x0d3c: 0x3b6d, 0x0d3d: 0x055c, 0x0d3e: 0x12fd, 0x0d3f: 0x0572, // Block 0x35, offset 0xd40 - 0x0d40: 0x1124, 0x0d41: 0x112b, 0x0d42: 0x1132, 0x0d43: 0x113b, 0x0d44: 0x1144, 0x0d45: 0x114d, - 0x0d46: 0x1156, 0x0d47: 0x115f, 0x0d48: 0x1168, 0x0d49: 0x116f, 0x0d4a: 0x1176, 0x0d4b: 0x117f, - 0x0d4c: 0x1188, 0x0d4d: 0x1191, 0x0d4e: 0x119a, 0x0d4f: 0x11a3, 0x0d50: 0x11ac, 0x0d51: 0x11b3, - 0x0d52: 0x11ba, 0x0d53: 0x11c3, 0x0d54: 0x11cc, 0x0d55: 0x11d5, 0x0d56: 0x11de, 0x0d57: 0x11e7, - 0x0d58: 0x11f0, 0x0d59: 0x11f7, 0x0d5a: 0x11fe, 0x0d5b: 0x1207, 0x0d5c: 0x1210, 0x0d5d: 0x1219, - 0x0d5e: 0x1222, 0x0d5f: 0x122b, 0x0d60: 0x1234, 0x0d61: 0x123b, 0x0d62: 0x1242, 0x0d63: 0x124b, - 0x0d64: 0x1254, 0x0d65: 0x125d, 0x0d66: 0x1266, 0x0d67: 0x126f, 0x0d68: 0x1278, 0x0d69: 0x127f, - 0x0d6a: 0x1286, 0x0d6b: 0x128f, 0x0d6c: 0x1298, 0x0d6d: 0x12a1, 0x0d6e: 0x12aa, 0x0d6f: 0x12b3, - 0x0d70: 0x12bc, 0x0d71: 0x12c1, 0x0d72: 0x12c6, 0x0d73: 0x12cd, 0x0d74: 0x12d2, - 0x0d76: 0x12d9, 0x0d77: 0x12de, 0x0d78: 0x12e5, 0x0d79: 0x12ea, 0x0d7a: 0x12ef, 0x0d7b: 0x04ee, - 0x0d7c: 0x12f4, 0x0d7d: 0x12f9, 0x0d7e: 0x12fd, 0x0d7f: 0x12f9, + 0x0d40: 0x3b70, 0x0d41: 0x0015, 0x0d42: 0x3b73, 0x0d43: 0x3b76, 0x0d44: 0x3b79, 0x0d45: 0x056f, + 0x0d46: 0x0575, 0x0d47: 0x0578, 0x0d48: 0x3b7c, 0x0d49: 0x3b7f, 0x0d4a: 0x3b82, 0x0d4b: 0x056c, + 0x0d4c: 0x0979, 0x0d4d: 0x3b85, 0x0d4e: 0x3b88, 0x0d4f: 0x3b8b, 0x0d50: 0x057e, 0x0d51: 0x055c, + 0x0d52: 0x0572, 0x0d53: 0x056c, 0x0d54: 0x0575, 0x0d55: 0x056f, 0x0d56: 0x3b2d, 0x0d57: 0x3b30, + 0x0d58: 0x14eb, 0x0d59: 0x3b33, 0x0d5a: 0x3b36, 0x0d5b: 0x3b39, 0x0d5c: 0x3b3c, 0x0d5d: 0x057b, + 0x0d5e: 0x3b3f, 0x0d5f: 0x3b42, 0x0d60: 0x3b45, 0x0d61: 0x3b48, 0x0d62: 0x3b4b, 0x0d63: 0x3b4e, + 0x0d64: 0x3b51, 0x0d65: 0x14ee, 0x0d66: 0x3b54, 0x0d67: 0x057b, 0x0d68: 0x0581, 0x0d69: 0x3b57, + 0x0d6a: 0x055f, 0x0d6b: 0x3b5a, 0x0d6c: 0x3b5d, 0x0d6d: 0x3b60, 0x0d6e: 0x14d6, 0x0d6f: 0x3b63, + 0x0d70: 0x3b67, 0x0d71: 0x0559, 0x0d72: 0x0973, 0x0d73: 0x0976, 0x0d74: 0x057e, 0x0d75: 0x3b6a, + 0x0d76: 0x3b6d, 0x0d77: 0x055c, 0x0d78: 0x12fd, 0x0d79: 0x0572, 0x0d7a: 0x3b70, 0x0d7b: 0x0015, + 0x0d7c: 0x3b73, 0x0d7d: 0x3b76, 0x0d7e: 0x3b79, 0x0d7f: 0x056f, // Block 0x36, offset 0xd80 - 0x0d80: 0x1300, 0x0d81: 0x1309, 0x0d82: 0x130f, 0x0d83: 0x1316, 0x0d84: 0x131b, - 0x0d86: 0x1322, 0x0d87: 0x1327, 0x0d88: 0x132e, 0x0d89: 0x04f6, 0x0d8a: 0x1333, 0x0d8b: 0x04fb, - 0x0d8c: 0x1338, 0x0d8d: 0x1343, 0x0d8e: 0x134f, 0x0d8f: 0x135b, 0x0d90: 0x1361, 0x0d91: 0x1366, - 0x0d92: 0x136b, 0x0d93: 0x0514, 0x0d96: 0x1372, 0x0d97: 0x1377, - 0x0d98: 0x137e, 0x0d99: 0x1383, 0x0d9a: 0x1388, 0x0d9b: 0x0500, 0x0d9d: 0x1393, - 0x0d9e: 0x139f, 0x0d9f: 0x13ab, 0x0da0: 0x13b1, 0x0da1: 0x13b6, 0x0da2: 0x13bb, 0x0da3: 0x0539, - 0x0da4: 0x13c2, 0x0da5: 0x13c7, 0x0da6: 0x13cc, 0x0da7: 0x13d1, 0x0da8: 0x13d8, 0x0da9: 0x13dd, - 0x0daa: 0x13e2, 0x0dab: 0x050a, 0x0dac: 0x13e7, 0x0dad: 0x13f1, 0x0dae: 0x04e8, 0x0daf: 0x13f7, - 0x0db2: 0x13f9, 0x0db3: 0x1400, 0x0db4: 0x1405, - 0x0db6: 0x140c, 0x0db7: 0x1411, 0x0db8: 0x1418, 0x0db9: 0x0505, 0x0dba: 0x141d, 0x0dbb: 0x050f, - 0x0dbc: 0x1422, 0x0dbd: 0x0011, 0x0dbe: 0x142a, + 0x0d80: 0x0575, 0x0d81: 0x0578, 0x0d82: 0x3b7c, 0x0d83: 0x3b7f, 0x0d84: 0x3b82, 0x0d85: 0x056c, + 0x0d86: 0x0979, 0x0d87: 0x3b85, 0x0d88: 0x3b88, 0x0d89: 0x3b8b, 0x0d8a: 0x057e, 0x0d8b: 0x055c, + 0x0d8c: 0x0572, 0x0d8d: 0x056c, 0x0d8e: 0x0575, 0x0d8f: 0x056f, 0x0d90: 0x3b2d, 0x0d91: 0x3b30, + 0x0d92: 0x14eb, 0x0d93: 0x3b33, 0x0d94: 0x3b36, 0x0d95: 0x3b39, 0x0d96: 0x3b3c, 0x0d97: 0x057b, + 0x0d98: 0x3b3f, 0x0d99: 0x3b42, 0x0d9a: 0x3b45, 0x0d9b: 0x3b48, 0x0d9c: 0x3b4b, 0x0d9d: 0x3b4e, + 0x0d9e: 0x3b51, 0x0d9f: 0x14ee, 0x0da0: 0x3b54, 0x0da1: 0x057b, 0x0da2: 0x0581, 0x0da3: 0x3b57, + 0x0da4: 0x055f, 0x0da5: 0x3b5a, 0x0da6: 0x3b5d, 0x0da7: 0x3b60, 0x0da8: 0x14d6, 0x0da9: 0x3b63, + 0x0daa: 0x3b67, 0x0dab: 0x0559, 0x0dac: 0x0973, 0x0dad: 0x0976, 0x0dae: 0x057e, 0x0daf: 0x3b6a, + 0x0db0: 0x3b6d, 0x0db1: 0x055c, 0x0db2: 0x12fd, 0x0db3: 0x0572, 0x0db4: 0x3b70, 0x0db5: 0x0015, + 0x0db6: 0x3b73, 0x0db7: 0x3b76, 0x0db8: 0x3b79, 0x0db9: 0x056f, 0x0dba: 0x0575, 0x0dbb: 0x0578, + 0x0dbc: 0x3b7c, 0x0dbd: 0x3b7f, 0x0dbe: 0x3b82, 0x0dbf: 0x056c, // Block 0x37, offset 0xdc0 - 0x0dc0: 0x0001, 0x0dc1: 0x0001, 0x0dc2: 0x0001, 0x0dc3: 0x0001, 0x0dc4: 0x0001, 0x0dc5: 0x0001, - 0x0dc6: 0x0001, 0x0dc7: 0x0001, 0x0dc8: 0x0001, 0x0dc9: 0x0001, 0x0dca: 0x0001, - 0x0dd1: 0x1436, - 0x0dd7: 0x143a, - 0x0de4: 0x143e, 0x0de5: 0x1440, 0x0de6: 0x1443, - 0x0def: 0x0001, - 0x0df3: 0x1447, 0x0df4: 0x144e, - 0x0df6: 0x1458, 0x0df7: 0x145f, - 0x0dfc: 0x1469, 0x0dfe: 0x146c, + 0x0dc0: 0x0979, 0x0dc1: 0x3b85, 0x0dc2: 0x3b88, 0x0dc3: 0x3b8b, 0x0dc4: 0x057e, 0x0dc5: 0x055c, + 0x0dc6: 0x0572, 0x0dc7: 0x056c, 0x0dc8: 0x0575, 0x0dc9: 0x056f, 0x0dca: 0x3b8f, 0x0dcb: 0x3b92, + 0x0dce: 0x1486, 0x0dcf: 0x001c, 0x0dd0: 0x000d, 0x0dd1: 0x000f, + 0x0dd2: 0x1488, 0x0dd3: 0x148a, 0x0dd4: 0x148c, 0x0dd5: 0x148e, 0x0dd6: 0x1490, 0x0dd7: 0x1492, + 0x0dd8: 0x1486, 0x0dd9: 0x001c, 0x0dda: 0x000d, 0x0ddb: 0x000f, 0x0ddc: 0x1488, 0x0ddd: 0x148a, + 0x0dde: 0x148c, 0x0ddf: 0x148e, 0x0de0: 0x1490, 0x0de1: 0x1492, 0x0de2: 0x1486, 0x0de3: 0x001c, + 0x0de4: 0x000d, 0x0de5: 0x000f, 0x0de6: 0x1488, 0x0de7: 0x148a, 0x0de8: 0x148c, 0x0de9: 0x148e, + 0x0dea: 0x1490, 0x0deb: 0x1492, 0x0dec: 0x1486, 0x0ded: 0x001c, 0x0dee: 0x000d, 0x0def: 0x000f, + 0x0df0: 0x1488, 0x0df1: 0x148a, 0x0df2: 0x148c, 0x0df3: 0x148e, 0x0df4: 0x1490, 0x0df5: 0x1492, + 0x0df6: 0x1486, 0x0df7: 0x001c, 0x0df8: 0x000d, 0x0df9: 0x000f, 0x0dfa: 0x1488, 0x0dfb: 0x148a, + 0x0dfc: 0x148c, 0x0dfd: 0x148e, 0x0dfe: 0x1490, 0x0dff: 0x1492, // Block 0x38, offset 0xe00 - 0x0e07: 0x1470, 0x0e08: 0x1473, 0x0e09: 0x1476, - 0x0e17: 0x1479, - 0x0e1f: 0x0001, - 0x0e30: 0x1486, 0x0e31: 0x097c, 0x0e34: 0x1488, 0x0e35: 0x148a, - 0x0e36: 0x148c, 0x0e37: 0x148e, 0x0e38: 0x1490, 0x0e39: 0x1492, 0x0e3a: 0x1494, 0x0e3b: 0x1496, - 0x0e3c: 0x149a, 0x0e3d: 0x149c, 0x0e3e: 0x149e, 0x0e3f: 0x14a0, + 0x0e00: 0x3b95, 0x0e01: 0x3b98, 0x0e02: 0x3b9b, 0x0e03: 0x3b9e, 0x0e04: 0x3ba1, 0x0e05: 0x3ba4, + 0x0e06: 0x3ba7, 0x0e07: 0x3baa, 0x0e08: 0x3bad, 0x0e09: 0x3bb0, 0x0e0a: 0x3bb3, + 0x0e10: 0x3bb6, 0x0e11: 0x3bba, + 0x0e12: 0x3bbe, 0x0e13: 0x3bc2, 0x0e14: 0x3bc6, 0x0e15: 0x3bca, 0x0e16: 0x3bce, 0x0e17: 0x3bd2, + 0x0e18: 0x3bd6, 0x0e19: 0x3bda, 0x0e1a: 0x3bde, 0x0e1b: 0x3be2, 0x0e1c: 0x3be6, 0x0e1d: 0x3bea, + 0x0e1e: 0x3bee, 0x0e1f: 0x3bf2, 0x0e20: 0x3bf6, 0x0e21: 0x3bfa, 0x0e22: 0x3bfe, 0x0e23: 0x3c02, + 0x0e24: 0x3c06, 0x0e25: 0x3c0a, 0x0e26: 0x3c0e, 0x0e27: 0x3c12, 0x0e28: 0x3c16, 0x0e29: 0x3c1a, + 0x0e2a: 0x3c1e, 0x0e2b: 0x14ad, 0x0e2c: 0x092b, 0x0e2d: 0x3c26, 0x0e2e: 0x3c29, + 0x0e30: 0x0906, 0x0e31: 0x090b, 0x0e32: 0x14ad, 0x0e33: 0x090d, 0x0e34: 0x090f, 0x0e35: 0x14d9, + 0x0e36: 0x0914, 0x0e37: 0x0916, 0x0e38: 0x0918, 0x0e39: 0x091a, 0x0e3a: 0x091c, 0x0e3b: 0x091e, + 0x0e3c: 0x0920, 0x0e3d: 0x0922, 0x0e3e: 0x0924, 0x0e3f: 0x0929, // Block 0x39, offset 0xe40 - 0x0e40: 0x1486, 0x0e41: 0x001c, 0x0e42: 0x000d, 0x0e43: 0x000f, 0x0e44: 0x1488, 0x0e45: 0x148a, - 0x0e46: 0x148c, 0x0e47: 0x148e, 0x0e48: 0x1490, 0x0e49: 0x1492, 0x0e4a: 0x1494, 0x0e4b: 0x1496, - 0x0e4c: 0x149a, 0x0e4d: 0x149c, 0x0e4e: 0x149e, 0x0e50: 0x0007, 0x0e51: 0x0941, - 0x0e52: 0x001e, 0x0e53: 0x04c7, 0x0e54: 0x0943, 0x0e55: 0x0494, 0x0e56: 0x094e, 0x0e57: 0x04c5, - 0x0e58: 0x0950, 0x0e59: 0x14a0, 0x0e5a: 0x0960, 0x0e5b: 0x02c8, 0x0e5c: 0x0962, - 0x0e68: 0x14a2, + 0x0e40: 0x3c3f, 0x0e41: 0x3c46, 0x0e42: 0x2291, + 0x0e50: 0x1922, 0x0e51: 0x3c4d, + 0x0e52: 0x3c51, 0x0e53: 0x1cb3, 0x0e54: 0x183e, 0x0e55: 0x3c55, 0x0e56: 0x3c59, 0x0e57: 0x1ed0, + 0x0e58: 0x3c5d, 0x0e59: 0x3c61, 0x0e5a: 0x3c65, 0x0e5b: 0x2d49, 0x0e5c: 0x3c69, 0x0e5d: 0x3c6d, + 0x0e5e: 0x3c71, 0x0e5f: 0x3c75, 0x0e60: 0x3c79, 0x0e61: 0x3c7d, 0x0e62: 0x19b2, 0x0e63: 0x3c81, + 0x0e64: 0x3c85, 0x0e65: 0x3c89, 0x0e66: 0x3c8d, 0x0e67: 0x3c91, 0x0e68: 0x3c95, 0x0e69: 0x1826, + 0x0e6a: 0x1eb0, 0x0e6b: 0x3c99, 0x0e6c: 0x21c7, 0x0e6d: 0x1ebc, 0x0e6e: 0x21cb, 0x0e6f: 0x3c9d, + 0x0e70: 0x1a92, 0x0e71: 0x3ca1, 0x0e72: 0x3ca5, 0x0e73: 0x3ca9, 0x0e74: 0x3cad, 0x0e75: 0x3cb1, + 0x0e76: 0x2183, 0x0e77: 0x194a, 0x0e78: 0x3cb5, 0x0e79: 0x3cb9, 0x0e7a: 0x3cbd, // Block 0x3a, offset 0xe80 - 0x0e80: 0x14a5, 0x0e81: 0x14a9, 0x0e82: 0x14ad, 0x0e83: 0x14af, 0x0e85: 0x14b3, - 0x0e86: 0x14b7, 0x0e87: 0x14bb, 0x0e89: 0x14be, 0x0e8a: 0x094c, 0x0e8b: 0x0916, - 0x0e8c: 0x0916, 0x0e8d: 0x0916, 0x0e8e: 0x0494, 0x0e8f: 0x14c2, 0x0e90: 0x0918, 0x0e91: 0x0918, - 0x0e92: 0x091e, 0x0e93: 0x04c5, 0x0e95: 0x0922, 0x0e96: 0x14c5, - 0x0e99: 0x0929, 0x0e9a: 0x14c8, 0x0e9b: 0x092b, 0x0e9c: 0x092b, 0x0e9d: 0x092b, - 0x0ea0: 0x14ca, 0x0ea1: 0x14cd, 0x0ea2: 0x14d1, - 0x0ea4: 0x14d4, 0x0ea6: 0x14d6, 0x0ea8: 0x14d4, - 0x0eaa: 0x091c, 0x0eab: 0x0046, 0x0eac: 0x090b, 0x0ead: 0x14ad, 0x0eaf: 0x0941, - 0x0eb0: 0x090f, 0x0eb1: 0x14d9, 0x0eb3: 0x0920, 0x0eb4: 0x001e, 0x0eb5: 0x14db, - 0x0eb6: 0x14de, 0x0eb7: 0x14e1, 0x0eb8: 0x14e4, 0x0eb9: 0x097c, 0x0ebb: 0x14e7, - 0x0ebc: 0x056f, 0x0ebd: 0x0973, 0x0ebe: 0x14eb, 0x0ebf: 0x14ee, + 0x0e80: 0x3d23, 0x0e81: 0x3d27, 0x0e82: 0x3d2b, 0x0e83: 0x3d2f, 0x0e84: 0x3d34, 0x0e85: 0x2eb5, + 0x0e86: 0x3d38, 0x0e87: 0x3d3c, 0x0e88: 0x3d40, 0x0e89: 0x3d44, 0x0e8a: 0x2eb9, 0x0e8b: 0x3d48, + 0x0e8c: 0x3d4c, 0x0e8d: 0x3d50, 0x0e8e: 0x2ebd, 0x0e8f: 0x3d55, 0x0e90: 0x3d59, 0x0e91: 0x3d5d, + 0x0e92: 0x3d61, 0x0e93: 0x3d66, 0x0e94: 0x3d6a, 0x0e95: 0x3c71, 0x0e96: 0x3d6e, 0x0e97: 0x3d73, + 0x0e98: 0x3d77, 0x0e99: 0x3d7b, 0x0e9a: 0x3d7f, 0x0e9b: 0x2f9a, 0x0e9c: 0x3d83, 0x0e9d: 0x1866, + 0x0e9e: 0x3d88, 0x0e9f: 0x3d8c, 0x0ea0: 0x3d90, 0x0ea1: 0x3d94, 0x0ea2: 0x3cb9, 0x0ea3: 0x3d98, + 0x0ea4: 0x3d9c, 0x0ea5: 0x2fae, 0x0ea6: 0x2ec1, 0x0ea7: 0x2ec5, 0x0ea8: 0x2fb2, 0x0ea9: 0x3da0, + 0x0eaa: 0x3da4, 0x0eab: 0x2bf1, 0x0eac: 0x3da8, 0x0ead: 0x2ec9, 0x0eae: 0x3dac, 0x0eaf: 0x3db0, + 0x0eb0: 0x3db4, 0x0eb1: 0x3db8, 0x0eb2: 0x3db8, 0x0eb3: 0x3db8, 0x0eb4: 0x3dbc, 0x0eb5: 0x3dc1, + 0x0eb6: 0x3dc5, 0x0eb7: 0x3dc9, 0x0eb8: 0x3dcd, 0x0eb9: 0x3dd2, 0x0eba: 0x3dd6, 0x0ebb: 0x3dda, + 0x0ebc: 0x3dde, 0x0ebd: 0x3de2, 0x0ebe: 0x3de6, 0x0ebf: 0x3dea, // Block 0x3b, offset 0xec0 - 0x0ec0: 0x14f1, 0x0ec5: 0x090d, - 0x0ec6: 0x093f, 0x0ec7: 0x0941, 0x0ec8: 0x097c, 0x0ec9: 0x0499, - 0x0ed0: 0x14f5, 0x0ed1: 0x14fb, - 0x0ed2: 0x1501, 0x0ed3: 0x1508, 0x0ed4: 0x150e, 0x0ed5: 0x1514, 0x0ed6: 0x151a, 0x0ed7: 0x1520, - 0x0ed8: 0x1526, 0x0ed9: 0x152c, 0x0eda: 0x1532, 0x0edb: 0x1538, 0x0edc: 0x153e, 0x0edd: 0x1544, - 0x0ede: 0x154a, 0x0edf: 0x1550, 0x0ee0: 0x0918, 0x0ee1: 0x1555, 0x0ee2: 0x1558, 0x0ee3: 0x155c, - 0x0ee4: 0x155f, 0x0ee5: 0x1561, 0x0ee6: 0x1564, 0x0ee7: 0x1568, 0x0ee8: 0x156d, 0x0ee9: 0x1570, - 0x0eea: 0x1572, 0x0eeb: 0x1575, 0x0eec: 0x091e, 0x0eed: 0x14ad, 0x0eee: 0x090d, 0x0eef: 0x0920, - 0x0ef0: 0x097c, 0x0ef1: 0x1579, 0x0ef2: 0x157c, 0x0ef3: 0x1580, 0x0ef4: 0x096d, 0x0ef5: 0x1583, - 0x0ef6: 0x1586, 0x0ef7: 0x158a, 0x0ef8: 0x158f, 0x0ef9: 0x04c7, 0x0efa: 0x1592, 0x0efb: 0x1595, - 0x0efc: 0x04c5, 0x0efd: 0x0984, 0x0efe: 0x093f, 0x0eff: 0x0950, + 0x0ec0: 0x3dee, 0x0ec1: 0x3df2, 0x0ec2: 0x3df6, 0x0ec3: 0x3dfa, 0x0ec4: 0x3dfe, 0x0ec5: 0x3e02, + 0x0ec6: 0x3e02, 0x0ec7: 0x2fba, 0x0ec8: 0x3e06, 0x0ec9: 0x3e0a, 0x0eca: 0x3e0e, 0x0ecb: 0x3e12, + 0x0ecc: 0x2ed1, 0x0ecd: 0x3e16, 0x0ece: 0x3e1a, 0x0ecf: 0x3e1e, 0x0ed0: 0x2e39, 0x0ed1: 0x3e22, + 0x0ed2: 0x3e26, 0x0ed3: 0x3e2a, 0x0ed4: 0x3e2e, 0x0ed5: 0x3e32, 0x0ed6: 0x3e36, 0x0ed7: 0x3e3a, + 0x0ed8: 0x3e3e, 0x0ed9: 0x3e42, 0x0eda: 0x3e47, 0x0edb: 0x3e4b, 0x0edc: 0x3e4f, 0x0edd: 0x3c55, + 0x0ede: 0x3e53, 0x0edf: 0x3e57, 0x0ee0: 0x3e5b, 0x0ee1: 0x3e60, 0x0ee2: 0x3e65, 0x0ee3: 0x3e69, + 0x0ee4: 0x3e6d, 0x0ee5: 0x3e71, 0x0ee6: 0x3e75, 0x0ee7: 0x3e79, 0x0ee8: 0x3e7d, 0x0ee9: 0x3e81, + 0x0eea: 0x3e85, 0x0eeb: 0x3e85, 0x0eec: 0x3e89, 0x0eed: 0x3e8e, 0x0eee: 0x3e92, 0x0eef: 0x2be1, + 0x0ef0: 0x3e96, 0x0ef1: 0x3e9a, 0x0ef2: 0x3e9f, 0x0ef3: 0x3ea3, 0x0ef4: 0x3ea7, 0x0ef5: 0x18ce, + 0x0ef6: 0x3eab, 0x0ef7: 0x3eaf, 0x0ef8: 0x18d6, 0x0ef9: 0x3eb3, 0x0efa: 0x3eb7, 0x0efb: 0x3ebb, + 0x0efc: 0x3ec0, 0x0efd: 0x3ec4, 0x0efe: 0x3ec9, 0x0eff: 0x3ecd, // Block 0x3c, offset 0xf00 - 0x0f09: 0x1599, - 0x0f1a: 0x159f, 0x0f1b: 0x15a5, - 0x0f2e: 0x15ab, + 0x0f00: 0x3ed1, 0x0f01: 0x3ed5, 0x0f02: 0x3ed9, 0x0f03: 0x3edd, 0x0f04: 0x3ee1, 0x0f05: 0x3ee5, + 0x0f06: 0x3ee9, 0x0f07: 0x3eed, 0x0f08: 0x3ef1, 0x0f09: 0x3ef5, 0x0f0a: 0x3efa, 0x0f0b: 0x3efe, + 0x0f0c: 0x3f02, 0x0f0d: 0x3f06, 0x0f0e: 0x2b11, 0x0f0f: 0x3f0a, 0x0f10: 0x18fe, 0x0f11: 0x3f0f, + 0x0f12: 0x3f0f, 0x0f13: 0x3f14, 0x0f14: 0x3f18, 0x0f15: 0x3f18, 0x0f16: 0x3f1c, 0x0f17: 0x3f20, + 0x0f18: 0x3f25, 0x0f19: 0x3f2a, 0x0f1a: 0x3f2e, 0x0f1b: 0x3f32, 0x0f1c: 0x3f36, 0x0f1d: 0x3f3a, + 0x0f1e: 0x3f3e, 0x0f1f: 0x3f42, 0x0f20: 0x3f46, 0x0f21: 0x3f4a, 0x0f22: 0x3f4e, 0x0f23: 0x2ee5, + 0x0f24: 0x3f52, 0x0f25: 0x3f57, 0x0f26: 0x3f5b, 0x0f27: 0x3f5f, 0x0f28: 0x2fea, 0x0f29: 0x3f5f, + 0x0f2a: 0x3f63, 0x0f2b: 0x2eed, 0x0f2c: 0x3f67, 0x0f2d: 0x3f6b, 0x0f2e: 0x3f6f, 0x0f2f: 0x3f73, + 0x0f30: 0x2ef1, 0x0f31: 0x2aa5, 0x0f32: 0x3f77, 0x0f33: 0x3f7b, 0x0f34: 0x3f7f, 0x0f35: 0x3f83, + 0x0f36: 0x3f87, 0x0f37: 0x3f8b, 0x0f38: 0x3f8f, 0x0f39: 0x3f94, 0x0f3a: 0x3f98, 0x0f3b: 0x3f9c, + 0x0f3c: 0x3fa0, 0x0f3d: 0x3fa4, 0x0f3e: 0x3fa8, 0x0f3f: 0x3fad, // Block 0x3d, offset 0xf40 - 0x0f4d: 0x15b1, 0x0f4e: 0x15b7, 0x0f4f: 0x15bd, + 0x0f40: 0x3fb1, 0x0f41: 0x3fb5, 0x0f42: 0x3fb9, 0x0f43: 0x3fbd, 0x0f44: 0x3fc1, 0x0f45: 0x3fc5, + 0x0f46: 0x3fc9, 0x0f47: 0x3fcd, 0x0f48: 0x2ef5, 0x0f49: 0x3fd1, 0x0f4a: 0x3fd5, 0x0f4b: 0x3fda, + 0x0f4c: 0x3fde, 0x0f4d: 0x3fe2, 0x0f4e: 0x3fe6, 0x0f4f: 0x2efd, 0x0f50: 0x3fea, 0x0f51: 0x3fee, + 0x0f52: 0x3ff2, 0x0f53: 0x3ff6, 0x0f54: 0x3ffa, 0x0f55: 0x3ffe, 0x0f56: 0x4002, 0x0f57: 0x4006, + 0x0f58: 0x2b15, 0x0f59: 0x300a, 0x0f5a: 0x400a, 0x0f5b: 0x400e, 0x0f5c: 0x4012, 0x0f5d: 0x4016, + 0x0f5e: 0x401b, 0x0f5f: 0x401f, 0x0f60: 0x4023, 0x0f61: 0x4027, 0x0f62: 0x2f01, 0x0f63: 0x402b, + 0x0f64: 0x4030, 0x0f65: 0x4034, 0x0f66: 0x4038, 0x0f67: 0x30b5, 0x0f68: 0x403c, 0x0f69: 0x4040, + 0x0f6a: 0x4044, 0x0f6b: 0x4048, 0x0f6c: 0x404c, 0x0f6d: 0x4051, 0x0f6e: 0x4055, 0x0f6f: 0x4059, + 0x0f70: 0x405d, 0x0f71: 0x4062, 0x0f72: 0x4066, 0x0f73: 0x406a, 0x0f74: 0x406e, 0x0f75: 0x2c25, + 0x0f76: 0x4072, 0x0f77: 0x4076, 0x0f78: 0x407b, 0x0f79: 0x4080, 0x0f7a: 0x4085, 0x0f7b: 0x4089, + 0x0f7c: 0x408e, 0x0f7d: 0x4092, 0x0f7e: 0x4096, 0x0f7f: 0x409a, // Block 0x3e, offset 0xf80 - 0x0f84: 0x15c3, - 0x0f89: 0x15c9, - 0x0f8c: 0x15cf, - 0x0fa4: 0x15d5, 0x0fa6: 0x15db, - 0x0fac: 0x15e1, 0x0fad: 0x15e8, 0x0faf: 0x15f2, - 0x0fb0: 0x15f9, + 0x0f80: 0x409e, 0x0f81: 0x2f05, 0x0f82: 0x2d71, 0x0f83: 0x40a2, 0x0f84: 0x40a6, 0x0f85: 0x40aa, + 0x0f86: 0x40ae, 0x0f87: 0x40b3, 0x0f88: 0x40b7, 0x0f89: 0x40bb, 0x0f8a: 0x40bf, 0x0f8b: 0x3016, + 0x0f8c: 0x40c3, 0x0f8d: 0x40c7, 0x0f8e: 0x40cc, 0x0f8f: 0x40d0, 0x0f90: 0x40d4, 0x0f91: 0x40d9, + 0x0f92: 0x40de, 0x0f93: 0x40e2, 0x0f94: 0x301a, 0x0f95: 0x40e6, 0x0f96: 0x40ea, 0x0f97: 0x40ee, + 0x0f98: 0x40f2, 0x0f99: 0x40f6, 0x0f9a: 0x40fa, 0x0f9b: 0x40fe, 0x0f9c: 0x4103, 0x0f9d: 0x4107, + 0x0f9e: 0x410c, 0x0f9f: 0x4110, 0x0fa0: 0x4115, 0x0fa1: 0x3022, 0x0fa2: 0x4119, 0x0fa3: 0x411d, + 0x0fa4: 0x4122, 0x0fa5: 0x4126, 0x0fa6: 0x412a, 0x0fa7: 0x412f, 0x0fa8: 0x4134, 0x0fa9: 0x4138, + 0x0faa: 0x413c, 0x0fab: 0x4140, 0x0fac: 0x4144, 0x0fad: 0x4144, 0x0fae: 0x4148, 0x0faf: 0x414c, + 0x0fb0: 0x302a, 0x0fb1: 0x4150, 0x0fb2: 0x4154, 0x0fb3: 0x4158, 0x0fb4: 0x415c, 0x0fb5: 0x4160, + 0x0fb6: 0x4165, 0x0fb7: 0x4169, 0x0fb8: 0x2bed, 0x0fb9: 0x416e, 0x0fba: 0x4173, 0x0fbb: 0x4177, + 0x0fbc: 0x417c, 0x0fbd: 0x4181, 0x0fbe: 0x4186, 0x0fbf: 0x418a, // Block 0x3f, offset 0xfc0 - 0x0fc1: 0x1603, 0x0fc4: 0x1609, - 0x0fc7: 0x160f, 0x0fc9: 0x1615, - 0x0fe0: 0x161b, 0x0fe2: 0x161f, - 0x0fed: 0x1625, 0x0fee: 0x162b, 0x0fef: 0x162f, - 0x0ff0: 0x1633, 0x0ff1: 0x1639, 0x0ff4: 0x163f, 0x0ff5: 0x1645, - 0x0ff8: 0x164b, 0x0ff9: 0x1651, + 0x0fc0: 0x3042, 0x0fc1: 0x418e, 0x0fc2: 0x4193, 0x0fc3: 0x4198, 0x0fc4: 0x419d, 0x0fc5: 0x41a2, + 0x0fc6: 0x41a6, 0x0fc7: 0x41a6, 0x0fc8: 0x3046, 0x0fc9: 0x30bd, 0x0fca: 0x41aa, 0x0fcb: 0x41ae, + 0x0fcc: 0x41b2, 0x0fcd: 0x41b6, 0x0fce: 0x41bb, 0x0fcf: 0x2b59, 0x0fd0: 0x304e, 0x0fd1: 0x41bf, + 0x0fd2: 0x41c3, 0x0fd3: 0x2f2d, 0x0fd4: 0x41c8, 0x0fd5: 0x41cd, 0x0fd6: 0x2e89, 0x0fd7: 0x41d2, + 0x0fd8: 0x41d6, 0x0fd9: 0x2f39, 0x0fda: 0x41da, 0x0fdb: 0x41de, 0x0fdc: 0x41e2, 0x0fdd: 0x41e7, + 0x0fde: 0x41e7, 0x0fdf: 0x41ec, 0x0fe0: 0x41f0, 0x0fe1: 0x41f4, 0x0fe2: 0x41f9, 0x0fe3: 0x41fd, + 0x0fe4: 0x4201, 0x0fe5: 0x4205, 0x0fe6: 0x420a, 0x0fe7: 0x420e, 0x0fe8: 0x4212, 0x0fe9: 0x4216, + 0x0fea: 0x421a, 0x0feb: 0x421e, 0x0fec: 0x4223, 0x0fed: 0x4227, 0x0fee: 0x422b, 0x0fef: 0x422f, + 0x0ff0: 0x4233, 0x0ff1: 0x4237, 0x0ff2: 0x423b, 0x0ff3: 0x4240, 0x0ff4: 0x4245, 0x0ff5: 0x4249, + 0x0ff6: 0x424e, 0x0ff7: 0x4252, 0x0ff8: 0x4257, 0x0ff9: 0x425b, 0x0ffa: 0x2f51, 0x0ffb: 0x425f, + 0x0ffc: 0x4264, 0x0ffd: 0x4269, 0x0ffe: 0x426d, 0x0fff: 0x4272, // Block 0x40, offset 0x1000 - 0x1000: 0x1657, 0x1001: 0x165d, 0x1004: 0x1663, 0x1005: 0x1669, - 0x1008: 0x166f, 0x1009: 0x1675, - 0x102c: 0x167b, 0x102d: 0x1681, 0x102e: 0x1687, 0x102f: 0x168d, + 0x1000: 0x4276, 0x1001: 0x427b, 0x1002: 0x427f, 0x1003: 0x4283, 0x1004: 0x4287, 0x1005: 0x428b, + 0x1006: 0x428f, 0x1007: 0x4293, 0x1008: 0x4298, 0x1009: 0x429d, 0x100a: 0x42a2, 0x100b: 0x3f14, + 0x100c: 0x42a7, 0x100d: 0x42ab, 0x100e: 0x42af, 0x100f: 0x42b3, 0x1010: 0x42b7, 0x1011: 0x42bb, + 0x1012: 0x42bf, 0x1013: 0x42c3, 0x1014: 0x42c7, 0x1015: 0x42cb, 0x1016: 0x42cf, 0x1017: 0x42d3, + 0x1018: 0x2c31, 0x1019: 0x42d8, 0x101a: 0x42dc, 0x101b: 0x42e0, 0x101c: 0x42e4, 0x101d: 0x42e8, + 0x101e: 0x42ec, 0x101f: 0x2f5d, 0x1020: 0x42f0, 0x1021: 0x42f4, 0x1022: 0x42f8, 0x1023: 0x42fc, + 0x1024: 0x4300, 0x1025: 0x4305, 0x1026: 0x430a, 0x1027: 0x430f, 0x1028: 0x4313, 0x1029: 0x4317, + 0x102a: 0x431b, 0x102b: 0x431f, 0x102c: 0x4324, 0x102d: 0x4328, 0x102e: 0x432d, 0x102f: 0x4331, + 0x1030: 0x4335, 0x1031: 0x433a, 0x1032: 0x433f, 0x1033: 0x4343, 0x1034: 0x2b45, 0x1035: 0x4347, + 0x1036: 0x434b, 0x1037: 0x434f, 0x1038: 0x4353, 0x1039: 0x4357, 0x103a: 0x435b, 0x103b: 0x306a, + 0x103c: 0x435f, 0x103d: 0x4363, 0x103e: 0x4367, 0x103f: 0x436b, // Block 0x41, offset 0x1040 - 0x1060: 0x1693, 0x1061: 0x1699, 0x1062: 0x169f, 0x1063: 0x16a5, - 0x106a: 0x16ab, 0x106b: 0x16b1, 0x106c: 0x16b7, 0x106d: 0x16bd, - // Block 0x42, offset 0x1080 - 0x10a9: 0x16c3, - 0x10aa: 0x16c7, - // Block 0x43, offset 0x10c0 - 0x10e0: 0x001c, 0x10e1: 0x000d, 0x10e2: 0x000f, 0x10e3: 0x1488, - 0x10e4: 0x148a, 0x10e5: 0x148c, 0x10e6: 0x148e, 0x10e7: 0x1490, 0x10e8: 0x1492, 0x10e9: 0x16cb, - 0x10ea: 0x16ce, 0x10eb: 0x16d1, 0x10ec: 0x16d4, 0x10ed: 0x16d7, 0x10ee: 0x16da, 0x10ef: 0x16dd, - 0x10f0: 0x16e0, 0x10f1: 0x16e3, 0x10f2: 0x16e6, 0x10f3: 0x16e9, 0x10f4: 0x16ec, 0x10f5: 0x16f0, - 0x10f6: 0x16f4, 0x10f7: 0x16f8, 0x10f8: 0x16fc, 0x10f9: 0x1700, 0x10fa: 0x1704, 0x10fb: 0x1708, - 0x10fc: 0x170c, 0x10fd: 0x1710, 0x10fe: 0x1715, 0x10ff: 0x171a, - // Block 0x44, offset 0x1100 - 0x1100: 0x171f, 0x1101: 0x1724, 0x1102: 0x1729, 0x1103: 0x172e, 0x1104: 0x1733, 0x1105: 0x1738, - 0x1106: 0x173d, 0x1107: 0x1742, 0x1108: 0x1747, 0x1109: 0x174a, 0x110a: 0x174d, 0x110b: 0x1750, - 0x110c: 0x1753, 0x110d: 0x1756, 0x110e: 0x1759, 0x110f: 0x175c, 0x1110: 0x175f, 0x1111: 0x1762, - 0x1112: 0x1766, 0x1113: 0x176a, 0x1114: 0x176e, 0x1115: 0x1772, 0x1116: 0x1776, 0x1117: 0x177a, - 0x1118: 0x177e, 0x1119: 0x1782, 0x111a: 0x1786, 0x111b: 0x178a, 0x111c: 0x178e, 0x111d: 0x1792, - 0x111e: 0x1796, 0x111f: 0x179a, 0x1120: 0x179e, 0x1121: 0x17a2, 0x1122: 0x17a6, 0x1123: 0x17aa, - 0x1124: 0x17ae, 0x1125: 0x17b2, 0x1126: 0x17b6, 0x1127: 0x17ba, 0x1128: 0x17be, 0x1129: 0x17c2, - 0x112a: 0x17c6, 0x112b: 0x17ca, 0x112c: 0x17ce, 0x112d: 0x17d2, 0x112e: 0x17d6, 0x112f: 0x17da, - 0x1130: 0x17de, 0x1131: 0x17e2, 0x1132: 0x17e6, 0x1133: 0x17ea, 0x1134: 0x17ee, 0x1135: 0x17f2, - 0x1136: 0x0906, 0x1137: 0x090b, 0x1138: 0x14ad, 0x1139: 0x090d, 0x113a: 0x090f, 0x113b: 0x14d9, - 0x113c: 0x0914, 0x113d: 0x0916, 0x113e: 0x0918, 0x113f: 0x091a, - // Block 0x45, offset 0x1140 - 0x1140: 0x091c, 0x1141: 0x091e, 0x1142: 0x0920, 0x1143: 0x0922, 0x1144: 0x0924, 0x1145: 0x0929, - 0x1146: 0x14c8, 0x1147: 0x092b, 0x1148: 0x17f6, 0x1149: 0x092d, 0x114a: 0x092f, 0x114b: 0x155f, - 0x114c: 0x0931, 0x114d: 0x1570, 0x114e: 0x17f8, 0x114f: 0x14d4, 0x1150: 0x0007, 0x1151: 0x093d, - 0x1152: 0x0984, 0x1153: 0x093f, 0x1154: 0x0941, 0x1155: 0x098c, 0x1156: 0x094c, 0x1157: 0x0494, - 0x1158: 0x097c, 0x1159: 0x0499, 0x115a: 0x094e, 0x115b: 0x04c5, 0x115c: 0x0950, 0x115d: 0x14a0, - 0x115e: 0x001e, 0x115f: 0x0960, 0x1160: 0x17fa, 0x1161: 0x049b, 0x1162: 0x02c8, 0x1163: 0x0962, - 0x1164: 0x0964, 0x1165: 0x096d, 0x1166: 0x04a6, 0x1167: 0x04c7, 0x1168: 0x04a8, 0x1169: 0x09df, - 0x116a: 0x1486, - // Block 0x46, offset 0x1180 - 0x118c: 0x17fc, - // Block 0x47, offset 0x11c0 - 0x11f4: 0x1809, 0x11f5: 0x180d, - 0x11f6: 0x1810, - // Block 0x48, offset 0x1200 - 0x121c: 0x1814, - // Block 0x49, offset 0x1240 - 0x127c: 0x0499, 0x127d: 0x155f, - // Block 0x4a, offset 0x1280 - 0x12af: 0x181a, - // Block 0x4b, offset 0x12c0 - 0x12df: 0x181e, - // Block 0x4c, offset 0x1300 - 0x1333: 0x1822, - // Block 0x4d, offset 0x1340 - 0x1340: 0x1826, 0x1341: 0x182a, 0x1342: 0x182e, 0x1343: 0x1832, 0x1344: 0x1836, 0x1345: 0x183a, - 0x1346: 0x183e, 0x1347: 0x1842, 0x1348: 0x1846, 0x1349: 0x184a, 0x134a: 0x184e, 0x134b: 0x1852, - 0x134c: 0x1856, 0x134d: 0x185a, 0x134e: 0x185e, 0x134f: 0x1862, 0x1350: 0x1866, 0x1351: 0x186a, - 0x1352: 0x186e, 0x1353: 0x1872, 0x1354: 0x1876, 0x1355: 0x187a, 0x1356: 0x187e, 0x1357: 0x1882, - 0x1358: 0x1886, 0x1359: 0x188a, 0x135a: 0x188e, 0x135b: 0x1892, 0x135c: 0x1896, 0x135d: 0x189a, - 0x135e: 0x189e, 0x135f: 0x18a2, 0x1360: 0x18a6, 0x1361: 0x18aa, 0x1362: 0x18ae, 0x1363: 0x18b2, - 0x1364: 0x18b6, 0x1365: 0x18ba, 0x1366: 0x18be, 0x1367: 0x18c2, 0x1368: 0x18c6, 0x1369: 0x18ca, - 0x136a: 0x18ce, 0x136b: 0x18d2, 0x136c: 0x18d6, 0x136d: 0x18da, 0x136e: 0x18de, 0x136f: 0x18e2, - 0x1370: 0x18e6, 0x1371: 0x18ea, 0x1372: 0x18ee, 0x1373: 0x18f2, 0x1374: 0x18f6, 0x1375: 0x18fa, - 0x1376: 0x18fe, 0x1377: 0x1902, 0x1378: 0x1906, 0x1379: 0x190a, 0x137a: 0x190e, 0x137b: 0x1912, - 0x137c: 0x1916, 0x137d: 0x191a, 0x137e: 0x191e, 0x137f: 0x1922, - // Block 0x4e, offset 0x1380 - 0x1380: 0x1926, 0x1381: 0x192a, 0x1382: 0x192e, 0x1383: 0x1932, 0x1384: 0x1936, 0x1385: 0x193a, - 0x1386: 0x193e, 0x1387: 0x1942, 0x1388: 0x1946, 0x1389: 0x194a, 0x138a: 0x194e, 0x138b: 0x1952, - 0x138c: 0x1956, 0x138d: 0x195a, 0x138e: 0x195e, 0x138f: 0x1962, 0x1390: 0x1966, 0x1391: 0x196a, - 0x1392: 0x196e, 0x1393: 0x1972, 0x1394: 0x1976, 0x1395: 0x197a, 0x1396: 0x197e, 0x1397: 0x1982, - 0x1398: 0x1986, 0x1399: 0x198a, 0x139a: 0x198e, 0x139b: 0x1992, 0x139c: 0x1996, 0x139d: 0x199a, - 0x139e: 0x199e, 0x139f: 0x19a2, 0x13a0: 0x19a6, 0x13a1: 0x19aa, 0x13a2: 0x19ae, 0x13a3: 0x19b2, - 0x13a4: 0x19b6, 0x13a5: 0x19ba, 0x13a6: 0x19be, 0x13a7: 0x19c2, 0x13a8: 0x19c6, 0x13a9: 0x19ca, - 0x13aa: 0x19ce, 0x13ab: 0x19d2, 0x13ac: 0x19d6, 0x13ad: 0x19da, 0x13ae: 0x19de, 0x13af: 0x19e2, - 0x13b0: 0x19e6, 0x13b1: 0x19ea, 0x13b2: 0x19ee, 0x13b3: 0x19f2, 0x13b4: 0x19f6, 0x13b5: 0x19fa, - 0x13b6: 0x19fe, 0x13b7: 0x1a02, 0x13b8: 0x1a06, 0x13b9: 0x1a0a, 0x13ba: 0x1a0e, 0x13bb: 0x1a12, - 0x13bc: 0x1a16, 0x13bd: 0x1a1a, 0x13be: 0x1a1e, 0x13bf: 0x1a22, - // Block 0x4f, offset 0x13c0 - 0x13c0: 0x1a26, 0x13c1: 0x1a2a, 0x13c2: 0x1a2e, 0x13c3: 0x1a32, 0x13c4: 0x1a36, 0x13c5: 0x1a3a, - 0x13c6: 0x1a3e, 0x13c7: 0x1a42, 0x13c8: 0x1a46, 0x13c9: 0x1a4a, 0x13ca: 0x1a4e, 0x13cb: 0x1a52, - 0x13cc: 0x1a56, 0x13cd: 0x1a5a, 0x13ce: 0x1a5e, 0x13cf: 0x1a62, 0x13d0: 0x1a66, 0x13d1: 0x1a6a, - 0x13d2: 0x1a6e, 0x13d3: 0x1a72, 0x13d4: 0x1a76, 0x13d5: 0x1a7a, 0x13d6: 0x1a7e, 0x13d7: 0x1a82, - 0x13d8: 0x1a86, 0x13d9: 0x1a8a, 0x13da: 0x1a8e, 0x13db: 0x1a92, 0x13dc: 0x1a96, 0x13dd: 0x1a9a, - 0x13de: 0x1a9e, 0x13df: 0x1aa2, 0x13e0: 0x1aa6, 0x13e1: 0x1aaa, 0x13e2: 0x1aae, 0x13e3: 0x1ab2, - 0x13e4: 0x1ab6, 0x13e5: 0x1aba, 0x13e6: 0x1abe, 0x13e7: 0x1ac2, 0x13e8: 0x1ac6, 0x13e9: 0x1aca, - 0x13ea: 0x1ace, 0x13eb: 0x1ad2, 0x13ec: 0x1ad6, 0x13ed: 0x1ada, 0x13ee: 0x1ade, 0x13ef: 0x1ae2, - 0x13f0: 0x1ae6, 0x13f1: 0x1aea, 0x13f2: 0x1aee, 0x13f3: 0x1af2, 0x13f4: 0x1af6, 0x13f5: 0x1afa, - 0x13f6: 0x1afe, 0x13f7: 0x1b02, 0x13f8: 0x1b06, 0x13f9: 0x1b0a, 0x13fa: 0x1b0e, 0x13fb: 0x1b12, - 0x13fc: 0x1b16, 0x13fd: 0x1b1a, 0x13fe: 0x1b1e, 0x13ff: 0x1b22, - // Block 0x50, offset 0x1400 - 0x1400: 0x1b26, 0x1401: 0x1b2a, 0x1402: 0x1b2e, 0x1403: 0x1b32, 0x1404: 0x1b36, 0x1405: 0x1b3a, - 0x1406: 0x1b3e, 0x1407: 0x1b42, 0x1408: 0x1b46, 0x1409: 0x1b4a, 0x140a: 0x1b4e, 0x140b: 0x1b52, - 0x140c: 0x1b56, 0x140d: 0x1b5a, 0x140e: 0x1b5e, 0x140f: 0x1b62, 0x1410: 0x1b66, 0x1411: 0x1b6a, - 0x1412: 0x1b6e, 0x1413: 0x1b72, 0x1414: 0x1b76, 0x1415: 0x1b7a, - // Block 0x51, offset 0x1440 - 0x1440: 0x0001, - 0x1476: 0x1b7e, 0x1478: 0x1882, 0x1479: 0x1b82, 0x147a: 0x1b86, - // Block 0x52, offset 0x1480 - 0x148c: 0x1b8a, 0x148e: 0x1b91, 0x1490: 0x1b98, - 0x1492: 0x1b9f, 0x1494: 0x1ba6, 0x1496: 0x1bad, - 0x1498: 0x1bb4, 0x149a: 0x1bbb, 0x149c: 0x1bc2, - 0x149e: 0x1bc9, 0x14a0: 0x1bd0, 0x14a2: 0x1bd7, - 0x14a5: 0x1bde, 0x14a7: 0x1be5, 0x14a9: 0x1bec, - 0x14b0: 0x1bf3, 0x14b1: 0x1bfa, 0x14b3: 0x1c01, 0x14b4: 0x1c08, - 0x14b6: 0x1c0f, 0x14b7: 0x1c16, 0x14b9: 0x1c1d, 0x14ba: 0x1c24, - 0x14bc: 0x1c2b, 0x14bd: 0x1c32, - // Block 0x53, offset 0x14c0 - 0x14d4: 0x1c39, - 0x14db: 0x1c40, 0x14dc: 0x1c45, - 0x14de: 0x1c4a, 0x14df: 0x1c51, - 0x14ec: 0x1c58, 0x14ee: 0x1c5f, - 0x14f0: 0x1c66, 0x14f2: 0x1c6d, 0x14f4: 0x1c74, - 0x14f6: 0x1c7b, 0x14f8: 0x1c82, 0x14fa: 0x1c89, - 0x14fc: 0x1c90, 0x14fe: 0x1c97, - // Block 0x54, offset 0x1500 - 0x1500: 0x1c9e, 0x1502: 0x1ca5, 0x1505: 0x1cac, - 0x1507: 0x1cb3, 0x1509: 0x1cba, - 0x1510: 0x1cc1, 0x1511: 0x1cc8, - 0x1513: 0x1ccf, 0x1514: 0x1cd6, 0x1516: 0x1cdd, 0x1517: 0x1ce4, - 0x1519: 0x1ceb, 0x151a: 0x1cf2, 0x151c: 0x1cf9, 0x151d: 0x1d00, - 0x1534: 0x1d07, - 0x1537: 0x1d0e, 0x1538: 0x1d15, 0x1539: 0x1d1c, 0x153a: 0x1d23, - 0x153e: 0x1d2a, 0x153f: 0x1d31, - // Block 0x55, offset 0x1540 - 0x1571: 0x1d38, 0x1572: 0x1d3c, 0x1573: 0x1d40, 0x1574: 0x1d44, 0x1575: 0x1d48, - 0x1576: 0x1d4c, 0x1577: 0x1d50, 0x1578: 0x1d54, 0x1579: 0x1d58, 0x157a: 0x1d5c, 0x157b: 0x1d60, - 0x157c: 0x1d64, 0x157d: 0x1d68, 0x157e: 0x1d6c, 0x157f: 0x1d70, - // Block 0x56, offset 0x1580 - 0x1580: 0x1d74, 0x1581: 0x1d78, 0x1582: 0x1d7c, 0x1583: 0x1d80, 0x1584: 0x1d84, 0x1585: 0x1d88, - 0x1586: 0x1d8c, 0x1587: 0x1d90, 0x1588: 0x1d94, 0x1589: 0x1d98, 0x158a: 0x1d9c, 0x158b: 0x1da0, - 0x158c: 0x1da4, 0x158d: 0x1da8, 0x158e: 0x1dac, 0x158f: 0x1db0, 0x1590: 0x1db4, 0x1591: 0x1db8, - 0x1592: 0x1dbc, 0x1593: 0x1dc0, 0x1594: 0x1dc4, 0x1595: 0x1dc8, 0x1596: 0x1dcc, 0x1597: 0x1dd0, - 0x1598: 0x1dd4, 0x1599: 0x1dd8, 0x159a: 0x1ddc, 0x159b: 0x1de0, 0x159c: 0x1de4, 0x159d: 0x1de8, - 0x159e: 0x1dec, 0x159f: 0x1df0, 0x15a0: 0x1df4, 0x15a1: 0x1df8, 0x15a2: 0x1dfc, 0x15a3: 0x1e00, - 0x15a4: 0x1e04, 0x15a5: 0x1e08, 0x15a6: 0x1e0c, 0x15a7: 0x1e10, 0x15a8: 0x1e14, 0x15a9: 0x1e18, - 0x15aa: 0x1e1c, 0x15ab: 0x1e20, 0x15ac: 0x1e24, 0x15ad: 0x1e28, 0x15ae: 0x1e2c, 0x15af: 0x1e30, - 0x15b0: 0x1e34, 0x15b1: 0x1e38, 0x15b2: 0x1e3c, 0x15b3: 0x1e40, 0x15b4: 0x1e44, 0x15b5: 0x1e48, - 0x15b6: 0x1e4c, 0x15b7: 0x1e50, 0x15b8: 0x1e54, 0x15b9: 0x1e58, 0x15ba: 0x1e5c, 0x15bb: 0x1e60, - 0x15bc: 0x1e64, 0x15bd: 0x1e68, 0x15be: 0x1e6c, 0x15bf: 0x1e70, - // Block 0x57, offset 0x15c0 - 0x15c0: 0x1e74, 0x15c1: 0x1e78, 0x15c2: 0x1e7c, 0x15c3: 0x1e80, 0x15c4: 0x1e84, 0x15c5: 0x1e88, - 0x15c6: 0x1e8c, 0x15c7: 0x1e90, 0x15c8: 0x1e94, 0x15c9: 0x1e98, 0x15ca: 0x1e9c, 0x15cb: 0x1ea0, - 0x15cc: 0x1ea4, 0x15cd: 0x1ea8, 0x15ce: 0x1eac, - 0x15d2: 0x1826, 0x15d3: 0x183e, 0x15d4: 0x1eb0, 0x15d5: 0x1eb4, 0x15d6: 0x1eb8, 0x15d7: 0x1ebc, - 0x15d8: 0x1ec0, 0x15d9: 0x1ec4, 0x15da: 0x1836, 0x15db: 0x1ec8, 0x15dc: 0x1ecc, 0x15dd: 0x1ed0, - 0x15de: 0x1ed4, 0x15df: 0x1846, - // Block 0x58, offset 0x1600 - 0x1600: 0x1ed8, 0x1601: 0x1ede, 0x1602: 0x1ee4, 0x1603: 0x1eea, 0x1604: 0x1ef0, 0x1605: 0x1ef6, - 0x1606: 0x1efc, 0x1607: 0x1f02, 0x1608: 0x1f08, 0x1609: 0x1f0e, 0x160a: 0x1f14, 0x160b: 0x1f1a, - 0x160c: 0x1f20, 0x160d: 0x1f26, 0x160e: 0x1f2c, 0x160f: 0x1f35, 0x1610: 0x1f3e, 0x1611: 0x1f47, - 0x1612: 0x1f50, 0x1613: 0x1f59, 0x1614: 0x1f62, 0x1615: 0x1f6b, 0x1616: 0x1f74, 0x1617: 0x1f7d, - 0x1618: 0x1f86, 0x1619: 0x1f8f, 0x161a: 0x1f98, 0x161b: 0x1fa1, 0x161c: 0x1faa, 0x161d: 0x1fb3, - 0x161e: 0x1fc5, 0x1620: 0x1fd4, 0x1621: 0x1fda, 0x1622: 0x1fe0, 0x1623: 0x1fe6, - 0x1624: 0x1fec, 0x1625: 0x1ff2, 0x1626: 0x1ff8, 0x1627: 0x1ffe, 0x1628: 0x2004, 0x1629: 0x200a, - 0x162a: 0x2010, 0x162b: 0x2016, 0x162c: 0x201c, 0x162d: 0x2022, 0x162e: 0x2028, 0x162f: 0x202e, - 0x1630: 0x2034, 0x1631: 0x203a, 0x1632: 0x2040, 0x1633: 0x2046, 0x1634: 0x204c, 0x1635: 0x2052, - 0x1636: 0x2058, 0x1637: 0x205e, 0x1638: 0x2064, 0x1639: 0x206a, 0x163a: 0x2070, 0x163b: 0x2076, - 0x163c: 0x207c, 0x163d: 0x2082, 0x163e: 0x2088, 0x163f: 0x208e, - // Block 0x59, offset 0x1640 - 0x1640: 0x2094, 0x1641: 0x209a, 0x1642: 0x20a0, 0x1643: 0x20a6, 0x1644: 0x20ac, 0x1645: 0x20b0, - 0x1646: 0x192e, 0x1647: 0x20b4, - 0x1650: 0x20b8, 0x1651: 0x20bc, - 0x1652: 0x20bf, 0x1653: 0x20c2, 0x1654: 0x20c5, 0x1655: 0x20c8, 0x1656: 0x20cb, 0x1657: 0x20ce, - 0x1658: 0x20d1, 0x1659: 0x20d4, 0x165a: 0x20d7, 0x165b: 0x20da, 0x165c: 0x20dd, 0x165d: 0x20e0, - 0x165e: 0x20e3, 0x165f: 0x20e6, 0x1660: 0x1d38, 0x1661: 0x1d44, 0x1662: 0x1d50, 0x1663: 0x1d58, - 0x1664: 0x1d78, 0x1665: 0x1d7c, 0x1666: 0x1d88, 0x1667: 0x1d90, 0x1668: 0x1d94, 0x1669: 0x1d9c, - 0x166a: 0x1da0, 0x166b: 0x1da4, 0x166c: 0x1da8, 0x166d: 0x1dac, 0x166e: 0x20e9, 0x166f: 0x20f0, - 0x1670: 0x20f7, 0x1671: 0x20fe, 0x1672: 0x2105, 0x1673: 0x210c, 0x1674: 0x2113, 0x1675: 0x211a, - 0x1676: 0x2121, 0x1677: 0x2128, 0x1678: 0x212f, 0x1679: 0x2136, 0x167a: 0x213d, 0x167b: 0x2144, - 0x167c: 0x214b, 0x167d: 0x215b, 0x167e: 0x2168, - // Block 0x5a, offset 0x1680 - 0x1680: 0x1826, 0x1681: 0x183e, 0x1682: 0x1eb0, 0x1683: 0x1eb4, 0x1684: 0x216f, 0x1685: 0x2173, - 0x1686: 0x2177, 0x1687: 0x1852, 0x1688: 0x217b, 0x1689: 0x1882, 0x168a: 0x194a, 0x168b: 0x197a, - 0x168c: 0x1976, 0x168d: 0x194e, 0x168e: 0x1abe, 0x168f: 0x18a2, 0x1690: 0x1942, 0x1691: 0x217f, - 0x1692: 0x2183, 0x1693: 0x2187, 0x1694: 0x218b, 0x1695: 0x218f, 0x1696: 0x2193, 0x1697: 0x2197, - 0x1698: 0x219b, 0x1699: 0x219f, 0x169a: 0x21a3, 0x169b: 0x18ba, 0x169c: 0x21a7, 0x169d: 0x21ab, - 0x169e: 0x21af, 0x169f: 0x21b3, 0x16a0: 0x21b7, 0x16a1: 0x21bb, 0x16a2: 0x21bf, 0x16a3: 0x21c3, - 0x16a4: 0x1eb8, 0x16a5: 0x1ebc, 0x16a6: 0x1ec0, 0x16a7: 0x21c7, 0x16a8: 0x21cb, 0x16a9: 0x21cf, - 0x16aa: 0x21d3, 0x16ab: 0x21d7, 0x16ac: 0x21db, 0x16ad: 0x21df, 0x16ae: 0x21e3, 0x16af: 0x21e7, - 0x16b0: 0x21eb, 0x16b1: 0x21ef, 0x16b2: 0x21f2, 0x16b3: 0x21f5, 0x16b4: 0x21f8, 0x16b5: 0x21fb, - 0x16b6: 0x21fe, 0x16b7: 0x2201, 0x16b8: 0x2204, 0x16b9: 0x2207, 0x16ba: 0x220a, 0x16bb: 0x220d, - 0x16bc: 0x2210, 0x16bd: 0x2213, 0x16be: 0x2216, 0x16bf: 0x2219, - // Block 0x5b, offset 0x16c0 - 0x16c0: 0x221c, 0x16c1: 0x2221, 0x16c2: 0x2226, 0x16c3: 0x222b, 0x16c4: 0x2230, 0x16c5: 0x2235, - 0x16c6: 0x223a, 0x16c7: 0x223f, 0x16c8: 0x2244, 0x16c9: 0x2249, 0x16ca: 0x224f, 0x16cb: 0x2255, - 0x16cc: 0x225b, 0x16cd: 0x225e, 0x16ce: 0x2262, 0x16cf: 0x2265, 0x16d0: 0x2269, 0x16d1: 0x226d, - 0x16d2: 0x2271, 0x16d3: 0x2275, 0x16d4: 0x2279, 0x16d5: 0x227d, 0x16d6: 0x2281, 0x16d7: 0x2285, - 0x16d8: 0x2289, 0x16d9: 0x228d, 0x16da: 0x2291, 0x16db: 0x2295, 0x16dc: 0x2299, 0x16dd: 0x229d, - 0x16de: 0x22a1, 0x16df: 0x22a5, 0x16e0: 0x22a9, 0x16e1: 0x22ad, 0x16e2: 0x22b1, 0x16e3: 0x22b5, - 0x16e4: 0x22b9, 0x16e5: 0x22bd, 0x16e6: 0x22c1, 0x16e7: 0x22c5, 0x16e8: 0x22c9, 0x16e9: 0x22cd, - 0x16ea: 0x22d1, 0x16eb: 0x22d5, 0x16ec: 0x22d9, 0x16ed: 0x22dd, 0x16ee: 0x22e1, 0x16ef: 0x22e5, - 0x16f0: 0x22e9, 0x16f1: 0x22ed, 0x16f2: 0x22f1, 0x16f3: 0x22f5, 0x16f4: 0x22f9, 0x16f5: 0x22fd, - 0x16f6: 0x2301, 0x16f7: 0x2305, 0x16f8: 0x2309, 0x16f9: 0x230d, 0x16fa: 0x2311, 0x16fb: 0x2315, - 0x16fc: 0x2319, 0x16fd: 0x231d, 0x16fe: 0x2321, - // Block 0x5c, offset 0x1700 - 0x1700: 0x2325, 0x1701: 0x2335, 0x1702: 0x2342, 0x1703: 0x2352, 0x1704: 0x235c, 0x1705: 0x236c, - 0x1706: 0x2376, 0x1707: 0x2380, 0x1708: 0x2393, 0x1709: 0x23a0, 0x170a: 0x23aa, 0x170b: 0x23b4, - 0x170c: 0x23be, 0x170d: 0x23cb, 0x170e: 0x23d8, 0x170f: 0x23e5, 0x1710: 0x23f2, 0x1711: 0x23ff, - 0x1712: 0x240c, 0x1713: 0x2419, 0x1714: 0x242c, 0x1715: 0x2433, 0x1716: 0x2446, 0x1717: 0x2459, - 0x1718: 0x2469, 0x1719: 0x2476, 0x171a: 0x2489, 0x171b: 0x249c, 0x171c: 0x24a9, 0x171d: 0x24b3, - 0x171e: 0x24bd, 0x171f: 0x24ca, 0x1720: 0x24d7, 0x1721: 0x24e7, 0x1722: 0x24f7, 0x1723: 0x2501, - 0x1724: 0x250b, 0x1725: 0x2518, 0x1726: 0x2522, 0x1727: 0x252c, 0x1728: 0x2533, 0x1729: 0x253a, - 0x172a: 0x2544, 0x172b: 0x254e, 0x172c: 0x2561, 0x172d: 0x256e, 0x172e: 0x257e, 0x172f: 0x2591, - 0x1730: 0x259e, 0x1731: 0x25a8, 0x1732: 0x25b2, 0x1733: 0x25c5, 0x1734: 0x25d2, 0x1735: 0x25e5, - 0x1736: 0x25ef, 0x1737: 0x25ff, 0x1738: 0x2609, 0x1739: 0x2616, 0x173a: 0x2620, 0x173b: 0x262d, - 0x173c: 0x263d, 0x173d: 0x264a, 0x173e: 0x265a, 0x173f: 0x2667, - // Block 0x5d, offset 0x1740 - 0x1740: 0x266e, 0x1741: 0x267e, 0x1742: 0x2688, 0x1743: 0x2692, 0x1744: 0x269f, 0x1745: 0x26a9, - 0x1746: 0x26b3, 0x1747: 0x26bd, 0x1748: 0x26cd, 0x1749: 0x26da, 0x174a: 0x26e1, 0x174b: 0x26f4, - 0x174c: 0x26fe, 0x174d: 0x270e, 0x174e: 0x271b, 0x174f: 0x2728, 0x1750: 0x2732, 0x1751: 0x273c, - 0x1752: 0x2749, 0x1753: 0x2750, 0x1754: 0x275d, 0x1755: 0x276d, 0x1756: 0x2774, 0x1757: 0x2787, - 0x1758: 0x2791, 0x1759: 0x2796, 0x175a: 0x279b, 0x175b: 0x27a0, 0x175c: 0x27a5, 0x175d: 0x27aa, - 0x175e: 0x27af, 0x175f: 0x27b4, 0x1760: 0x27b9, 0x1761: 0x27be, 0x1762: 0x27c3, 0x1763: 0x27c9, - 0x1764: 0x27cf, 0x1765: 0x27d5, 0x1766: 0x27db, 0x1767: 0x27e1, 0x1768: 0x27e7, 0x1769: 0x27ed, - 0x176a: 0x27f3, 0x176b: 0x27f9, 0x176c: 0x27ff, 0x176d: 0x2805, 0x176e: 0x280b, 0x176f: 0x2811, - 0x1770: 0x2817, 0x1771: 0x281d, 0x1772: 0x2821, 0x1773: 0x2824, 0x1774: 0x2827, 0x1775: 0x282b, - 0x1776: 0x282e, 0x1777: 0x2831, 0x1778: 0x2834, 0x1779: 0x2838, 0x177a: 0x283c, 0x177b: 0x283f, - 0x177c: 0x2846, 0x177d: 0x284d, 0x177e: 0x2854, 0x177f: 0x285b, - // Block 0x5e, offset 0x1780 - 0x1780: 0x2868, 0x1781: 0x286b, 0x1782: 0x286e, 0x1783: 0x2872, 0x1784: 0x2875, 0x1785: 0x2878, - 0x1786: 0x287b, 0x1787: 0x287e, 0x1788: 0x2881, 0x1789: 0x2885, 0x178a: 0x288a, 0x178b: 0x288d, - 0x178c: 0x2890, 0x178d: 0x2894, 0x178e: 0x2898, 0x178f: 0x289b, 0x1790: 0x289e, 0x1791: 0x28a1, - 0x1792: 0x28a5, 0x1793: 0x28a9, 0x1794: 0x28ad, 0x1795: 0x28b1, 0x1796: 0x28b5, 0x1797: 0x28b8, - 0x1798: 0x28bb, 0x1799: 0x28be, 0x179a: 0x28c1, 0x179b: 0x28c4, 0x179c: 0x28c8, 0x179d: 0x28cb, - 0x179e: 0x28ce, 0x179f: 0x28d1, 0x17a0: 0x28d5, 0x17a1: 0x28d9, 0x17a2: 0x28dc, 0x17a3: 0x28e0, - 0x17a4: 0x28e4, 0x17a5: 0x28e8, 0x17a6: 0x28eb, 0x17a7: 0x28ef, 0x17a8: 0x28f5, 0x17a9: 0x28fc, - 0x17aa: 0x28ff, 0x17ab: 0x2903, 0x17ac: 0x2907, 0x17ad: 0x290b, 0x17ae: 0x290f, 0x17af: 0x2917, - 0x17b0: 0x2920, 0x17b1: 0x2923, 0x17b2: 0x2926, 0x17b3: 0x292a, 0x17b4: 0x292d, 0x17b5: 0x2930, - 0x17b6: 0x2933, 0x17b7: 0x2937, 0x17b8: 0x293a, 0x17b9: 0x293d, 0x17ba: 0x2940, 0x17bb: 0x2943, - 0x17bc: 0x2946, 0x17bd: 0x294a, 0x17be: 0x294d, 0x17bf: 0x2950, - // Block 0x5f, offset 0x17c0 - 0x17c0: 0x2953, 0x17c1: 0x2957, 0x17c2: 0x295b, 0x17c3: 0x2960, 0x17c4: 0x2963, 0x17c5: 0x2966, - 0x17c6: 0x2969, 0x17c7: 0x2970, 0x17c8: 0x2974, 0x17c9: 0x2977, 0x17ca: 0x297a, 0x17cb: 0x297d, - 0x17cc: 0x2980, 0x17cd: 0x2983, 0x17ce: 0x2986, 0x17cf: 0x2989, 0x17d0: 0x298c, 0x17d1: 0x298f, - 0x17d2: 0x2992, 0x17d3: 0x2996, 0x17d4: 0x2999, 0x17d5: 0x299c, 0x17d6: 0x29a0, 0x17d7: 0x29a4, - 0x17d8: 0x29a7, 0x17d9: 0x29ac, 0x17da: 0x29b0, 0x17db: 0x29b3, 0x17dc: 0x29b6, 0x17dd: 0x29b9, - 0x17de: 0x29bc, 0x17df: 0x29c2, 0x17e0: 0x29c8, 0x17e1: 0x29cd, 0x17e2: 0x29d2, 0x17e3: 0x29d7, - 0x17e4: 0x29dc, 0x17e5: 0x29e1, 0x17e6: 0x29e6, 0x17e7: 0x29eb, 0x17e8: 0x29f0, 0x17e9: 0x29f5, - 0x17ea: 0x29fb, 0x17eb: 0x2a01, 0x17ec: 0x2a07, 0x17ed: 0x2a0d, 0x17ee: 0x2a13, 0x17ef: 0x2a19, - 0x17f0: 0x2a1f, 0x17f1: 0x2a25, 0x17f2: 0x2a2b, 0x17f3: 0x2a31, 0x17f4: 0x2a37, 0x17f5: 0x2a3d, - 0x17f6: 0x2a43, 0x17f7: 0x2a49, 0x17f8: 0x2a4f, 0x17f9: 0x2a55, 0x17fa: 0x2a5b, 0x17fb: 0x2a61, - 0x17fc: 0x2a67, 0x17fd: 0x2a6d, 0x17fe: 0x2a73, 0x17ff: 0x2a79, - // Block 0x60, offset 0x1800 - 0x1830: 0x2a7d, - // Block 0x61, offset 0x1840 - 0x1840: 0x2a81, 0x1841: 0x2a85, 0x1842: 0x1a9e, 0x1843: 0x2a89, 0x1844: 0x2a8d, 0x1845: 0x2a91, - 0x1846: 0x2a95, 0x1847: 0x1b76, 0x1848: 0x1b76, 0x1849: 0x2a99, 0x184a: 0x1abe, 0x184b: 0x2a9d, - 0x184c: 0x2aa1, 0x184d: 0x2aa5, 0x184e: 0x2aa9, 0x184f: 0x2aad, 0x1850: 0x2ab1, 0x1851: 0x2ab5, - 0x1852: 0x2ab9, 0x1853: 0x2abd, 0x1854: 0x2ac1, 0x1855: 0x2ac5, 0x1856: 0x2ac9, 0x1857: 0x2acd, - 0x1858: 0x2ad1, 0x1859: 0x2ad5, 0x185a: 0x2ad9, 0x185b: 0x2add, 0x185c: 0x2ae1, 0x185d: 0x2ae5, - 0x185e: 0x2ae9, 0x185f: 0x2aed, 0x1860: 0x2af1, 0x1861: 0x2af5, 0x1862: 0x2af9, 0x1863: 0x2afd, - 0x1864: 0x2b01, 0x1865: 0x2b05, 0x1866: 0x2b09, 0x1867: 0x2b0d, 0x1868: 0x2b11, 0x1869: 0x2b15, - 0x186a: 0x2b19, 0x186b: 0x2b1d, 0x186c: 0x2b21, 0x186d: 0x2b25, 0x186e: 0x2b29, 0x186f: 0x2b2d, - 0x1870: 0x2b31, 0x1871: 0x2b35, 0x1872: 0x2b39, 0x1873: 0x2b3d, 0x1874: 0x1a16, 0x1875: 0x2b41, - 0x1876: 0x2b45, 0x1877: 0x2b49, 0x1878: 0x2b4d, 0x1879: 0x2b51, 0x187a: 0x2b55, 0x187b: 0x2b59, - 0x187c: 0x2b5d, 0x187d: 0x2b61, 0x187e: 0x2b65, 0x187f: 0x2b69, - // Block 0x62, offset 0x1880 - 0x1880: 0x1b3a, 0x1881: 0x2b6d, 0x1882: 0x2b71, 0x1883: 0x2b75, 0x1884: 0x2b79, 0x1885: 0x2b7d, - 0x1886: 0x2b81, 0x1887: 0x2b85, 0x1888: 0x2b89, 0x1889: 0x2b8d, 0x188a: 0x2b91, 0x188b: 0x2b95, - 0x188c: 0x2b99, 0x188d: 0x2b9d, 0x188e: 0x2ba1, 0x188f: 0x2ba5, 0x1890: 0x2ba9, 0x1891: 0x2bad, - 0x1892: 0x2bb1, 0x1893: 0x2bb5, 0x1894: 0x2bb9, 0x1895: 0x2bbd, 0x1896: 0x2bc1, 0x1897: 0x2bc5, - 0x1898: 0x2bc9, 0x1899: 0x2bcd, 0x189a: 0x2bd1, 0x189b: 0x2bd5, 0x189c: 0x2ac1, 0x189d: 0x2bd9, - 0x189e: 0x2bdd, 0x189f: 0x2be1, 0x18a0: 0x2be5, 0x18a1: 0x2be9, 0x18a2: 0x2bed, 0x18a3: 0x2bf1, - 0x18a4: 0x2bf5, 0x18a5: 0x2bf9, 0x18a6: 0x2bfd, 0x18a7: 0x2c01, 0x18a8: 0x2c05, 0x18a9: 0x2c09, - 0x18aa: 0x2c0d, 0x18ab: 0x2c11, 0x18ac: 0x2c15, 0x18ad: 0x2c19, 0x18ae: 0x2c1d, 0x18af: 0x2c21, - 0x18b0: 0x2c25, 0x18b1: 0x1aa6, 0x18b2: 0x2c29, 0x18b3: 0x2c2d, 0x18b4: 0x2c31, 0x18b5: 0x2c35, - 0x18b6: 0x2c39, 0x18b7: 0x2c3d, 0x18b8: 0x2c41, 0x18b9: 0x2c45, 0x18ba: 0x2c49, 0x18bb: 0x2c4d, - 0x18bc: 0x2c51, 0x18bd: 0x2c55, 0x18be: 0x2c59, 0x18bf: 0x2c5d, - // Block 0x63, offset 0x18c0 - 0x18c0: 0x2c61, 0x18c1: 0x18ba, 0x18c2: 0x2c65, 0x18c3: 0x2c69, 0x18c4: 0x2c6d, 0x18c5: 0x2c71, - 0x18c6: 0x2c75, 0x18c7: 0x2c79, 0x18c8: 0x2c7d, 0x18c9: 0x2c81, 0x18ca: 0x186e, 0x18cb: 0x2c85, - 0x18cc: 0x2c89, 0x18cd: 0x2c8d, 0x18ce: 0x2c91, 0x18cf: 0x2c95, 0x18d0: 0x2c99, 0x18d1: 0x2c9d, - 0x18d2: 0x2ca1, 0x18d3: 0x2ca5, 0x18d4: 0x2ca9, 0x18d5: 0x2cad, 0x18d6: 0x2cb1, 0x18d7: 0x2cb5, - 0x18d8: 0x2cb9, 0x18d9: 0x2cbd, 0x18da: 0x2cc1, 0x18db: 0x2cc5, 0x18dc: 0x2cc9, 0x18dd: 0x2ccd, - 0x18de: 0x2cd1, 0x18df: 0x2cd5, 0x18e0: 0x2cd9, 0x18e1: 0x2c21, 0x18e2: 0x2cdd, 0x18e3: 0x2ce1, - 0x18e4: 0x2ce5, 0x18e5: 0x2ce9, 0x18e6: 0x2ced, 0x18e7: 0x2cf1, 0x18e8: 0x2cf5, 0x18e9: 0x2cf9, - 0x18ea: 0x2be1, 0x18eb: 0x2cfd, 0x18ec: 0x2d01, 0x18ed: 0x2d05, 0x18ee: 0x2d09, 0x18ef: 0x2d0d, - 0x18f0: 0x2d11, 0x18f1: 0x2d15, 0x18f2: 0x2d19, 0x18f3: 0x2d1d, 0x18f4: 0x2d21, 0x18f5: 0x2d25, - 0x18f6: 0x2d29, 0x18f7: 0x2d2d, 0x18f8: 0x2d31, 0x18f9: 0x2d35, 0x18fa: 0x2d39, 0x18fb: 0x2d3d, - 0x18fc: 0x2d41, 0x18fd: 0x2d45, 0x18fe: 0x2d49, 0x18ff: 0x2ac1, - // Block 0x64, offset 0x1900 - 0x1900: 0x2d4d, 0x1901: 0x2d51, 0x1902: 0x2d55, 0x1903: 0x2d59, 0x1904: 0x1b72, 0x1905: 0x2d5d, - 0x1906: 0x2d61, 0x1907: 0x2d65, 0x1908: 0x2d69, 0x1909: 0x2d6d, 0x190a: 0x2d71, 0x190b: 0x2d75, - 0x190c: 0x2d79, 0x190d: 0x2d7d, 0x190e: 0x2d81, 0x190f: 0x2d85, 0x1910: 0x2d89, 0x1911: 0x2173, - 0x1912: 0x2d8d, 0x1913: 0x2d91, 0x1914: 0x2d95, 0x1915: 0x2d99, 0x1916: 0x2d9d, 0x1917: 0x2da1, - 0x1918: 0x2da5, 0x1919: 0x2da9, 0x191a: 0x2dad, 0x191b: 0x2be9, 0x191c: 0x2db1, 0x191d: 0x2db5, - 0x191e: 0x2db9, 0x191f: 0x2dbd, 0x1920: 0x2dc1, 0x1921: 0x2dc5, 0x1922: 0x2dc9, 0x1923: 0x2dcd, - 0x1924: 0x2dd1, 0x1925: 0x2dd5, 0x1926: 0x2dd9, 0x1927: 0x2ddd, 0x1928: 0x2de1, 0x1929: 0x1aba, - 0x192a: 0x2de5, 0x192b: 0x2de9, 0x192c: 0x2ded, 0x192d: 0x2df1, 0x192e: 0x2df5, 0x192f: 0x2df9, - 0x1930: 0x2dfd, 0x1931: 0x2e01, 0x1932: 0x2e05, 0x1933: 0x2e09, 0x1934: 0x2e0d, 0x1935: 0x2e11, - 0x1936: 0x2e15, 0x1937: 0x19f6, 0x1938: 0x2e19, 0x1939: 0x2e1d, 0x193a: 0x2e21, 0x193b: 0x2e25, - 0x193c: 0x2e29, 0x193d: 0x2e2d, 0x193e: 0x2e31, 0x193f: 0x2e35, - // Block 0x65, offset 0x1940 - 0x1940: 0x2e39, 0x1941: 0x2e3d, 0x1942: 0x2e41, 0x1943: 0x2e45, 0x1944: 0x2e49, 0x1945: 0x2e4d, - 0x1946: 0x2e51, 0x1947: 0x2e55, 0x1948: 0x1a62, 0x1949: 0x2e59, 0x194a: 0x1a6e, 0x194b: 0x2e5d, - 0x194c: 0x2e61, 0x194d: 0x2e65, 0x1950: 0x2e69, - 0x1952: 0x2e6d, 0x1955: 0x2e71, 0x1956: 0x2e75, 0x1957: 0x2e79, - 0x1958: 0x2e7d, 0x1959: 0x2e81, 0x195a: 0x2e85, 0x195b: 0x2e89, 0x195c: 0x2e8d, 0x195d: 0x2e91, - 0x195e: 0x1a12, 0x1960: 0x2e95, 0x1962: 0x2e99, - 0x1965: 0x2e9d, 0x1966: 0x2ea1, - 0x196a: 0x2ea5, 0x196b: 0x2ea9, 0x196c: 0x2ead, 0x196d: 0x2eb1, - 0x1970: 0x2eb5, 0x1971: 0x2eb9, 0x1972: 0x2ebd, 0x1973: 0x2ec1, 0x1974: 0x2ec5, 0x1975: 0x2ec9, - 0x1976: 0x2ecd, 0x1977: 0x2ed1, 0x1978: 0x2ed5, 0x1979: 0x2ed9, 0x197a: 0x2edd, 0x197b: 0x2ee1, - 0x197c: 0x18d6, 0x197d: 0x2ee5, 0x197e: 0x2ee9, 0x197f: 0x2eed, - // Block 0x66, offset 0x1980 - 0x1980: 0x2ef1, 0x1981: 0x2ef5, 0x1982: 0x2ef9, 0x1983: 0x2efd, 0x1984: 0x2f01, 0x1985: 0x2f05, - 0x1986: 0x2f09, 0x1987: 0x2f0d, 0x1988: 0x2f11, 0x1989: 0x2f15, 0x198a: 0x2f19, 0x198b: 0x2f1d, - 0x198c: 0x2187, 0x198d: 0x2f21, 0x198e: 0x2f25, 0x198f: 0x2f29, 0x1990: 0x2f2d, 0x1991: 0x2197, - 0x1992: 0x2f31, 0x1993: 0x2f35, 0x1994: 0x2f39, 0x1995: 0x2f3d, 0x1996: 0x2f41, 0x1997: 0x2cb1, - 0x1998: 0x2f45, 0x1999: 0x2f49, 0x199a: 0x2f4d, 0x199b: 0x2f51, 0x199c: 0x2f55, 0x199d: 0x2f59, - 0x199e: 0x2f59, 0x199f: 0x2f5d, 0x19a0: 0x2f61, 0x19a1: 0x2f65, 0x19a2: 0x2f69, 0x19a3: 0x2f6d, - 0x19a4: 0x2f71, 0x19a5: 0x2f75, 0x19a6: 0x2f79, 0x19a7: 0x2e9d, 0x19a8: 0x2f7d, 0x19a9: 0x2f81, - 0x19aa: 0x2f85, 0x19ab: 0x2f89, 0x19ac: 0x2f8d, 0x19ad: 0x2f92, - 0x19b0: 0x2f96, 0x19b1: 0x2f9a, 0x19b2: 0x2f9e, 0x19b3: 0x2fa2, 0x19b4: 0x2fa6, 0x19b5: 0x2faa, - 0x19b6: 0x2fae, 0x19b7: 0x2fb2, 0x19b8: 0x2ecd, 0x19b9: 0x2fb6, 0x19ba: 0x2fba, 0x19bb: 0x2fbe, - 0x19bc: 0x2e69, 0x19bd: 0x2fc2, 0x19be: 0x2fc6, 0x19bf: 0x2fca, - // Block 0x67, offset 0x19c0 - 0x19c0: 0x2fce, 0x19c1: 0x2fd2, 0x19c2: 0x2fd6, 0x19c3: 0x2fda, 0x19c4: 0x2fde, 0x19c5: 0x2fe2, - 0x19c6: 0x2fe6, 0x19c7: 0x2fea, 0x19c8: 0x2fee, 0x19c9: 0x2eed, 0x19ca: 0x2ff2, 0x19cb: 0x2ef1, - 0x19cc: 0x2ff6, 0x19cd: 0x2ffa, 0x19ce: 0x2ffe, 0x19cf: 0x3002, 0x19d0: 0x3006, 0x19d1: 0x2e6d, - 0x19d2: 0x2b15, 0x19d3: 0x300a, 0x19d4: 0x300e, 0x19d5: 0x195a, 0x19d6: 0x2c25, 0x19d7: 0x2d71, - 0x19d8: 0x3012, 0x19d9: 0x3016, 0x19da: 0x2f0d, 0x19db: 0x301a, 0x19dc: 0x2f11, 0x19dd: 0x301e, - 0x19de: 0x3022, 0x19df: 0x3026, 0x19e0: 0x2e75, 0x19e1: 0x302a, 0x19e2: 0x302e, 0x19e3: 0x3032, - 0x19e4: 0x3036, 0x19e5: 0x303a, 0x19e6: 0x2e79, 0x19e7: 0x303e, 0x19e8: 0x3042, 0x19e9: 0x3046, - 0x19ea: 0x304a, 0x19eb: 0x304e, 0x19ec: 0x3052, 0x19ed: 0x2f41, 0x19ee: 0x3056, 0x19ef: 0x305a, - 0x19f0: 0x2cb1, 0x19f1: 0x305e, 0x19f2: 0x2f51, 0x19f3: 0x3062, 0x19f4: 0x3066, 0x19f5: 0x306a, - 0x19f6: 0x306e, 0x19f7: 0x3072, 0x19f8: 0x2f65, 0x19f9: 0x3076, 0x19fa: 0x2e99, 0x19fb: 0x307a, - 0x19fc: 0x2f69, 0x19fd: 0x2bd9, 0x19fe: 0x307e, 0x19ff: 0x2f6d, - // Block 0x68, offset 0x1a00 - 0x1a00: 0x3082, 0x1a01: 0x2f75, 0x1a02: 0x3086, 0x1a03: 0x308a, 0x1a04: 0x308e, 0x1a05: 0x3092, - 0x1a06: 0x3096, 0x1a07: 0x2f7d, 0x1a08: 0x2e8d, 0x1a09: 0x309a, 0x1a0a: 0x2f81, 0x1a0b: 0x309e, - 0x1a0c: 0x2f85, 0x1a0d: 0x30a2, 0x1a0e: 0x1b76, 0x1a0f: 0x30a6, 0x1a10: 0x30ab, 0x1a11: 0x30b0, - 0x1a12: 0x30b5, 0x1a13: 0x30b9, 0x1a14: 0x30bd, 0x1a15: 0x30c1, 0x1a16: 0x30c6, 0x1a17: 0x30cb, - 0x1a18: 0x30d0, 0x1a19: 0x30d4, - // Block 0x69, offset 0x1a40 - 0x1a40: 0x30d8, 0x1a41: 0x30db, 0x1a42: 0x30de, 0x1a43: 0x30e1, 0x1a44: 0x30e5, 0x1a45: 0x30e9, - 0x1a46: 0x30e9, - 0x1a53: 0x30ec, 0x1a54: 0x30f1, 0x1a55: 0x30f6, 0x1a56: 0x30fb, 0x1a57: 0x3100, - 0x1a5d: 0x3105, - 0x1a5f: 0x310a, 0x1a60: 0x310f, 0x1a61: 0x14db, 0x1a62: 0x14e4, 0x1a63: 0x3112, - 0x1a64: 0x3115, 0x1a65: 0x3118, 0x1a66: 0x311b, 0x1a67: 0x311e, 0x1a68: 0x3121, 0x1a69: 0x1494, - 0x1a6a: 0x3124, 0x1a6b: 0x3129, 0x1a6c: 0x312e, 0x1a6d: 0x3135, 0x1a6e: 0x313c, 0x1a6f: 0x3141, - 0x1a70: 0x3146, 0x1a71: 0x314b, 0x1a72: 0x3150, 0x1a73: 0x3155, 0x1a74: 0x315a, 0x1a75: 0x315f, - 0x1a76: 0x3164, 0x1a78: 0x3169, 0x1a79: 0x316e, 0x1a7a: 0x3173, 0x1a7b: 0x3178, - 0x1a7c: 0x317d, 0x1a7e: 0x3182, - // Block 0x6a, offset 0x1a80 - 0x1a80: 0x3187, 0x1a81: 0x318c, 0x1a83: 0x3191, 0x1a84: 0x3196, - 0x1a86: 0x319b, 0x1a87: 0x31a0, 0x1a88: 0x31a5, 0x1a89: 0x31aa, 0x1a8a: 0x31af, 0x1a8b: 0x31b4, - 0x1a8c: 0x31b9, 0x1a8d: 0x31be, 0x1a8e: 0x31c3, 0x1a8f: 0x31c8, 0x1a90: 0x31cd, 0x1a91: 0x31cd, - 0x1a92: 0x31d0, 0x1a93: 0x31d0, 0x1a94: 0x31d0, 0x1a95: 0x31d0, 0x1a96: 0x31d3, 0x1a97: 0x31d3, - 0x1a98: 0x31d3, 0x1a99: 0x31d3, 0x1a9a: 0x31d6, 0x1a9b: 0x31d6, 0x1a9c: 0x31d6, 0x1a9d: 0x31d6, - 0x1a9e: 0x31d9, 0x1a9f: 0x31d9, 0x1aa0: 0x31d9, 0x1aa1: 0x31d9, 0x1aa2: 0x31dc, 0x1aa3: 0x31dc, - 0x1aa4: 0x31dc, 0x1aa5: 0x31dc, 0x1aa6: 0x31df, 0x1aa7: 0x31df, 0x1aa8: 0x31df, 0x1aa9: 0x31df, - 0x1aaa: 0x31e2, 0x1aab: 0x31e2, 0x1aac: 0x31e2, 0x1aad: 0x31e2, 0x1aae: 0x31e5, 0x1aaf: 0x31e5, - 0x1ab0: 0x31e5, 0x1ab1: 0x31e5, 0x1ab2: 0x31e8, 0x1ab3: 0x31e8, 0x1ab4: 0x31e8, 0x1ab5: 0x31e8, - 0x1ab6: 0x31eb, 0x1ab7: 0x31eb, 0x1ab8: 0x31eb, 0x1ab9: 0x31eb, 0x1aba: 0x31ee, 0x1abb: 0x31ee, - 0x1abc: 0x31ee, 0x1abd: 0x31ee, 0x1abe: 0x31f1, 0x1abf: 0x31f1, - // Block 0x6b, offset 0x1ac0 - 0x1ac0: 0x31f1, 0x1ac1: 0x31f1, 0x1ac2: 0x31f4, 0x1ac3: 0x31f4, 0x1ac4: 0x31f7, 0x1ac5: 0x31f7, - 0x1ac6: 0x31fa, 0x1ac7: 0x31fa, 0x1ac8: 0x31fd, 0x1ac9: 0x31fd, 0x1aca: 0x3200, 0x1acb: 0x3200, - 0x1acc: 0x3203, 0x1acd: 0x3203, 0x1ace: 0x3206, 0x1acf: 0x3206, 0x1ad0: 0x3206, 0x1ad1: 0x3206, - 0x1ad2: 0x3209, 0x1ad3: 0x3209, 0x1ad4: 0x3209, 0x1ad5: 0x3209, 0x1ad6: 0x320c, 0x1ad7: 0x320c, - 0x1ad8: 0x320c, 0x1ad9: 0x320c, 0x1ada: 0x320f, 0x1adb: 0x320f, 0x1adc: 0x320f, 0x1add: 0x320f, - 0x1ade: 0x3212, 0x1adf: 0x3212, 0x1ae0: 0x3215, 0x1ae1: 0x3215, 0x1ae2: 0x3215, 0x1ae3: 0x3215, - 0x1ae4: 0x06ba, 0x1ae5: 0x06ba, 0x1ae6: 0x3218, 0x1ae7: 0x3218, 0x1ae8: 0x3218, 0x1ae9: 0x3218, - 0x1aea: 0x321b, 0x1aeb: 0x321b, 0x1aec: 0x321b, 0x1aed: 0x321b, 0x1aee: 0x321e, 0x1aef: 0x321e, - 0x1af0: 0x06c4, 0x1af1: 0x06c4, - // Block 0x6c, offset 0x1b00 - 0x1b13: 0x3221, 0x1b14: 0x3221, 0x1b15: 0x3221, 0x1b16: 0x3221, 0x1b17: 0x3224, - 0x1b18: 0x3224, 0x1b19: 0x3227, 0x1b1a: 0x3227, 0x1b1b: 0x322a, 0x1b1c: 0x322a, 0x1b1d: 0x06b0, - 0x1b1e: 0x322d, 0x1b1f: 0x322d, 0x1b20: 0x3230, 0x1b21: 0x3230, 0x1b22: 0x3233, 0x1b23: 0x3233, - 0x1b24: 0x3236, 0x1b25: 0x3236, 0x1b26: 0x3236, 0x1b27: 0x3236, 0x1b28: 0x3239, 0x1b29: 0x3239, - 0x1b2a: 0x323c, 0x1b2b: 0x323c, 0x1b2c: 0x3243, 0x1b2d: 0x3243, 0x1b2e: 0x324a, 0x1b2f: 0x324a, - 0x1b30: 0x3251, 0x1b31: 0x3251, 0x1b32: 0x3258, 0x1b33: 0x3258, 0x1b34: 0x325f, 0x1b35: 0x325f, - 0x1b36: 0x3266, 0x1b37: 0x3266, 0x1b38: 0x3266, 0x1b39: 0x326d, 0x1b3a: 0x326d, 0x1b3b: 0x326d, - 0x1b3c: 0x3274, 0x1b3d: 0x3274, 0x1b3e: 0x3274, 0x1b3f: 0x3274, - // Block 0x6d, offset 0x1b40 - 0x1b40: 0x3277, 0x1b41: 0x327e, 0x1b42: 0x3285, 0x1b43: 0x326d, 0x1b44: 0x328c, 0x1b45: 0x3293, - 0x1b46: 0x3298, 0x1b47: 0x329d, 0x1b48: 0x32a2, 0x1b49: 0x32a7, 0x1b4a: 0x32ac, 0x1b4b: 0x32b1, - 0x1b4c: 0x32b6, 0x1b4d: 0x32bb, 0x1b4e: 0x32c0, 0x1b4f: 0x32c5, 0x1b50: 0x32ca, 0x1b51: 0x32cf, - 0x1b52: 0x32d4, 0x1b53: 0x32d9, 0x1b54: 0x32de, 0x1b55: 0x32e3, 0x1b56: 0x32e8, 0x1b57: 0x32ed, - 0x1b58: 0x32f2, 0x1b59: 0x32f7, 0x1b5a: 0x32fc, 0x1b5b: 0x3301, 0x1b5c: 0x3306, 0x1b5d: 0x330b, - 0x1b5e: 0x3310, 0x1b5f: 0x3315, 0x1b60: 0x331a, 0x1b61: 0x331f, 0x1b62: 0x3324, 0x1b63: 0x3329, - 0x1b64: 0x332e, 0x1b65: 0x3333, 0x1b66: 0x3338, 0x1b67: 0x333d, 0x1b68: 0x3342, 0x1b69: 0x3347, - 0x1b6a: 0x334c, 0x1b6b: 0x3351, 0x1b6c: 0x3356, 0x1b6d: 0x335b, 0x1b6e: 0x3360, 0x1b6f: 0x3365, - 0x1b70: 0x336a, 0x1b71: 0x336f, 0x1b72: 0x3374, 0x1b73: 0x3379, 0x1b74: 0x337e, 0x1b75: 0x3383, - 0x1b76: 0x3388, 0x1b77: 0x338d, 0x1b78: 0x3392, 0x1b79: 0x3397, 0x1b7a: 0x339c, 0x1b7b: 0x33a1, - 0x1b7c: 0x33a6, 0x1b7d: 0x33ab, 0x1b7e: 0x33b0, 0x1b7f: 0x33b5, - // Block 0x6e, offset 0x1b80 - 0x1b80: 0x33ba, 0x1b81: 0x33bf, 0x1b82: 0x33c4, 0x1b83: 0x33c9, 0x1b84: 0x33ce, 0x1b85: 0x33d3, - 0x1b86: 0x33d8, 0x1b87: 0x33dd, 0x1b88: 0x33e2, 0x1b89: 0x33e7, 0x1b8a: 0x33ec, 0x1b8b: 0x33f1, - 0x1b8c: 0x33f6, 0x1b8d: 0x33fb, 0x1b8e: 0x3400, 0x1b8f: 0x3405, 0x1b90: 0x340a, 0x1b91: 0x340f, - 0x1b92: 0x3414, 0x1b93: 0x3419, 0x1b94: 0x341e, 0x1b95: 0x3423, 0x1b96: 0x3428, 0x1b97: 0x342d, - 0x1b98: 0x3432, 0x1b99: 0x3437, 0x1b9a: 0x343c, 0x1b9b: 0x3441, 0x1b9c: 0x3446, 0x1b9d: 0x344b, - 0x1b9e: 0x3450, 0x1b9f: 0x3456, 0x1ba0: 0x345c, 0x1ba1: 0x3462, 0x1ba2: 0x3468, 0x1ba3: 0x346e, - 0x1ba4: 0x3474, 0x1ba5: 0x347b, 0x1ba6: 0x3285, 0x1ba7: 0x3482, 0x1ba8: 0x326d, 0x1ba9: 0x328c, - 0x1baa: 0x3489, 0x1bab: 0x348e, 0x1bac: 0x32a2, 0x1bad: 0x3493, 0x1bae: 0x32a7, 0x1baf: 0x32ac, - 0x1bb0: 0x3498, 0x1bb1: 0x349d, 0x1bb2: 0x32c0, 0x1bb3: 0x34a2, 0x1bb4: 0x32c5, 0x1bb5: 0x32ca, - 0x1bb6: 0x34a7, 0x1bb7: 0x34ac, 0x1bb8: 0x32d4, 0x1bb9: 0x34b1, 0x1bba: 0x32d9, 0x1bbb: 0x32de, - 0x1bbc: 0x336f, 0x1bbd: 0x3374, 0x1bbe: 0x3383, 0x1bbf: 0x3388, - // Block 0x6f, offset 0x1bc0 - 0x1bc0: 0x338d, 0x1bc1: 0x33a1, 0x1bc2: 0x33a6, 0x1bc3: 0x33ab, 0x1bc4: 0x33b0, 0x1bc5: 0x33c4, - 0x1bc6: 0x33c9, 0x1bc7: 0x33ce, 0x1bc8: 0x34b6, 0x1bc9: 0x33e2, 0x1bca: 0x34bb, 0x1bcb: 0x34c0, - 0x1bcc: 0x3400, 0x1bcd: 0x34c5, 0x1bce: 0x3405, 0x1bcf: 0x340a, 0x1bd0: 0x344b, 0x1bd1: 0x34ca, - 0x1bd2: 0x34cf, 0x1bd3: 0x3432, 0x1bd4: 0x34d4, 0x1bd5: 0x3437, 0x1bd6: 0x343c, 0x1bd7: 0x3277, - 0x1bd8: 0x327e, 0x1bd9: 0x34d9, 0x1bda: 0x3285, 0x1bdb: 0x34e0, 0x1bdc: 0x3293, 0x1bdd: 0x3298, - 0x1bde: 0x329d, 0x1bdf: 0x32a2, 0x1be0: 0x34e7, 0x1be1: 0x32b1, 0x1be2: 0x32b6, 0x1be3: 0x32bb, - 0x1be4: 0x32c0, 0x1be5: 0x34ec, 0x1be6: 0x32d4, 0x1be7: 0x32e3, 0x1be8: 0x32e8, 0x1be9: 0x32ed, - 0x1bea: 0x32f2, 0x1beb: 0x32f7, 0x1bec: 0x3301, 0x1bed: 0x3306, 0x1bee: 0x330b, 0x1bef: 0x3310, - 0x1bf0: 0x3315, 0x1bf1: 0x331a, 0x1bf2: 0x34f1, 0x1bf3: 0x331f, 0x1bf4: 0x3324, 0x1bf5: 0x3329, - 0x1bf6: 0x332e, 0x1bf7: 0x3333, 0x1bf8: 0x3338, 0x1bf9: 0x3342, 0x1bfa: 0x3347, 0x1bfb: 0x334c, - 0x1bfc: 0x3351, 0x1bfd: 0x3356, 0x1bfe: 0x335b, 0x1bff: 0x3360, - // Block 0x70, offset 0x1c00 - 0x1c00: 0x3365, 0x1c01: 0x336a, 0x1c02: 0x3379, 0x1c03: 0x337e, 0x1c04: 0x3392, 0x1c05: 0x3397, - 0x1c06: 0x339c, 0x1c07: 0x33a1, 0x1c08: 0x33a6, 0x1c09: 0x33b5, 0x1c0a: 0x33ba, 0x1c0b: 0x33bf, - 0x1c0c: 0x33c4, 0x1c0d: 0x34f6, 0x1c0e: 0x33d3, 0x1c0f: 0x33d8, 0x1c10: 0x33dd, 0x1c11: 0x33e2, - 0x1c12: 0x33f1, 0x1c13: 0x33f6, 0x1c14: 0x33fb, 0x1c15: 0x3400, 0x1c16: 0x34fb, 0x1c17: 0x340f, - 0x1c18: 0x3414, 0x1c19: 0x3500, 0x1c1a: 0x3423, 0x1c1b: 0x3428, 0x1c1c: 0x342d, 0x1c1d: 0x3432, - 0x1c1e: 0x3505, 0x1c1f: 0x3285, 0x1c20: 0x34e0, 0x1c21: 0x32a2, 0x1c22: 0x34e7, 0x1c23: 0x32c0, - 0x1c24: 0x34ec, 0x1c25: 0x32d4, 0x1c26: 0x350a, 0x1c27: 0x3315, 0x1c28: 0x350f, 0x1c29: 0x3514, - 0x1c2a: 0x3519, 0x1c2b: 0x33a1, 0x1c2c: 0x33a6, 0x1c2d: 0x33c4, 0x1c2e: 0x3400, 0x1c2f: 0x34fb, - 0x1c30: 0x3432, 0x1c31: 0x3505, 0x1c32: 0x351e, 0x1c33: 0x3525, 0x1c34: 0x352c, 0x1c35: 0x3533, - 0x1c36: 0x3538, 0x1c37: 0x353d, 0x1c38: 0x3542, 0x1c39: 0x3547, 0x1c3a: 0x354c, 0x1c3b: 0x3551, - 0x1c3c: 0x3556, 0x1c3d: 0x355b, 0x1c3e: 0x3560, 0x1c3f: 0x3565, - // Block 0x71, offset 0x1c40 - 0x1c40: 0x356a, 0x1c41: 0x356f, 0x1c42: 0x3574, 0x1c43: 0x3579, 0x1c44: 0x357e, 0x1c45: 0x3583, - 0x1c46: 0x3588, 0x1c47: 0x358d, 0x1c48: 0x3592, 0x1c49: 0x3597, 0x1c4a: 0x359c, 0x1c4b: 0x35a1, - 0x1c4c: 0x3514, 0x1c4d: 0x35a6, 0x1c4e: 0x35ab, 0x1c4f: 0x35b0, 0x1c50: 0x35b5, 0x1c51: 0x3533, - 0x1c52: 0x3538, 0x1c53: 0x353d, 0x1c54: 0x3542, 0x1c55: 0x3547, 0x1c56: 0x354c, 0x1c57: 0x3551, - 0x1c58: 0x3556, 0x1c59: 0x355b, 0x1c5a: 0x3560, 0x1c5b: 0x3565, 0x1c5c: 0x356a, 0x1c5d: 0x356f, - 0x1c5e: 0x3574, 0x1c5f: 0x3579, 0x1c60: 0x357e, 0x1c61: 0x3583, 0x1c62: 0x3588, 0x1c63: 0x358d, - 0x1c64: 0x3592, 0x1c65: 0x3597, 0x1c66: 0x359c, 0x1c67: 0x35a1, 0x1c68: 0x3514, 0x1c69: 0x35a6, - 0x1c6a: 0x35ab, 0x1c6b: 0x35b0, 0x1c6c: 0x35b5, 0x1c6d: 0x3597, 0x1c6e: 0x359c, 0x1c6f: 0x35a1, - 0x1c70: 0x3514, 0x1c71: 0x350f, 0x1c72: 0x3519, 0x1c73: 0x333d, 0x1c74: 0x3306, 0x1c75: 0x330b, - 0x1c76: 0x3310, 0x1c77: 0x3597, 0x1c78: 0x359c, 0x1c79: 0x35a1, 0x1c7a: 0x333d, 0x1c7b: 0x3342, - 0x1c7c: 0x35ba, 0x1c7d: 0x35ba, - // Block 0x72, offset 0x1c80 - 0x1c90: 0x35bf, 0x1c91: 0x35c6, - 0x1c92: 0x35c6, 0x1c93: 0x35cd, 0x1c94: 0x35d4, 0x1c95: 0x35db, 0x1c96: 0x35e2, 0x1c97: 0x35e9, - 0x1c98: 0x35f0, 0x1c99: 0x35f0, 0x1c9a: 0x35f7, 0x1c9b: 0x35fe, 0x1c9c: 0x3605, 0x1c9d: 0x360c, - 0x1c9e: 0x3613, 0x1c9f: 0x361a, 0x1ca0: 0x361a, 0x1ca1: 0x3621, 0x1ca2: 0x3628, 0x1ca3: 0x3628, - 0x1ca4: 0x362f, 0x1ca5: 0x362f, 0x1ca6: 0x3636, 0x1ca7: 0x363d, 0x1ca8: 0x363d, 0x1ca9: 0x3644, - 0x1caa: 0x364b, 0x1cab: 0x364b, 0x1cac: 0x3652, 0x1cad: 0x3652, 0x1cae: 0x3659, 0x1caf: 0x3660, - 0x1cb0: 0x3660, 0x1cb1: 0x3667, 0x1cb2: 0x3667, 0x1cb3: 0x366e, 0x1cb4: 0x3675, 0x1cb5: 0x367c, - 0x1cb6: 0x3683, 0x1cb7: 0x3683, 0x1cb8: 0x368a, 0x1cb9: 0x3691, 0x1cba: 0x3698, 0x1cbb: 0x369f, - 0x1cbc: 0x36a6, 0x1cbd: 0x36a6, 0x1cbe: 0x36ad, 0x1cbf: 0x36b4, - // Block 0x73, offset 0x1cc0 - 0x1cc0: 0x36bb, 0x1cc1: 0x36c2, 0x1cc2: 0x36c9, 0x1cc3: 0x36d0, 0x1cc4: 0x36d0, 0x1cc5: 0x36d7, - 0x1cc6: 0x36d7, 0x1cc7: 0x36de, 0x1cc8: 0x36de, 0x1cc9: 0x36e5, 0x1cca: 0x36ec, 0x1ccb: 0x36f3, - 0x1ccc: 0x36fa, 0x1ccd: 0x3701, 0x1cce: 0x3708, 0x1ccf: 0x370f, - 0x1cd2: 0x3716, 0x1cd3: 0x371d, 0x1cd4: 0x3724, 0x1cd5: 0x372b, 0x1cd6: 0x3732, 0x1cd7: 0x3739, - 0x1cd8: 0x3739, 0x1cd9: 0x3740, 0x1cda: 0x3747, 0x1cdb: 0x374e, 0x1cdc: 0x3755, 0x1cdd: 0x3755, - 0x1cde: 0x375c, 0x1cdf: 0x3763, 0x1ce0: 0x376a, 0x1ce1: 0x3771, 0x1ce2: 0x3778, 0x1ce3: 0x377f, - 0x1ce4: 0x3786, 0x1ce5: 0x378d, 0x1ce6: 0x3794, 0x1ce7: 0x379b, 0x1ce8: 0x37a2, 0x1ce9: 0x37a9, - 0x1cea: 0x37b0, 0x1ceb: 0x37b7, 0x1cec: 0x37be, 0x1ced: 0x37c5, 0x1cee: 0x37cc, 0x1cef: 0x37d3, - 0x1cf0: 0x37da, 0x1cf1: 0x37e1, 0x1cf2: 0x37e8, 0x1cf3: 0x37ef, 0x1cf4: 0x36ad, 0x1cf5: 0x36bb, - 0x1cf6: 0x37f6, 0x1cf7: 0x37fd, 0x1cf8: 0x3804, 0x1cf9: 0x380b, 0x1cfa: 0x3812, 0x1cfb: 0x3819, - 0x1cfc: 0x3812, 0x1cfd: 0x3804, 0x1cfe: 0x3820, 0x1cff: 0x3827, - // Block 0x74, offset 0x1d00 - 0x1d00: 0x382e, 0x1d01: 0x3835, 0x1d02: 0x383c, 0x1d03: 0x3819, 0x1d04: 0x367c, 0x1d05: 0x3636, - 0x1d06: 0x3843, 0x1d07: 0x384a, - 0x1d30: 0x3851, 0x1d31: 0x3858, 0x1d32: 0x385f, 0x1d33: 0x3868, 0x1d34: 0x3871, 0x1d35: 0x387a, - 0x1d36: 0x3883, 0x1d37: 0x388c, 0x1d38: 0x3895, 0x1d39: 0x389e, 0x1d3a: 0x38a5, 0x1d3b: 0x38c7, - 0x1d3c: 0x38d7, - // Block 0x75, offset 0x1d40 - 0x1d50: 0x38e0, 0x1d51: 0x38e2, - 0x1d52: 0x38e6, 0x1d53: 0x38ea, 0x1d54: 0x04e1, 0x1d55: 0x38ec, 0x1d56: 0x38ee, 0x1d57: 0x38f0, - 0x1d58: 0x38f4, 0x1d59: 0x1443, - 0x1d70: 0x1440, 0x1d71: 0x38f8, 0x1d72: 0x38fc, 0x1d73: 0x3900, 0x1d74: 0x3900, 0x1d75: 0x149c, - 0x1d76: 0x149e, 0x1d77: 0x3902, 0x1d78: 0x3904, 0x1d79: 0x3906, 0x1d7a: 0x390a, 0x1d7b: 0x390e, - 0x1d7c: 0x3912, 0x1d7d: 0x3916, 0x1d7e: 0x391a, 0x1d7f: 0x16c3, - // Block 0x76, offset 0x1d80 - 0x1d80: 0x16c7, 0x1d81: 0x391e, 0x1d82: 0x3922, 0x1d83: 0x3926, 0x1d84: 0x392a, - 0x1d87: 0x392e, 0x1d88: 0x3930, 0x1d89: 0x146c, 0x1d8a: 0x146c, 0x1d8b: 0x146c, - 0x1d8c: 0x146c, 0x1d8d: 0x3900, 0x1d8e: 0x3900, 0x1d8f: 0x3900, 0x1d90: 0x38e0, 0x1d91: 0x38e2, - 0x1d92: 0x143e, 0x1d94: 0x04e1, 0x1d95: 0x38ea, 0x1d96: 0x38ee, 0x1d97: 0x38ec, - 0x1d98: 0x38f8, 0x1d99: 0x149c, 0x1d9a: 0x149e, 0x1d9b: 0x3902, 0x1d9c: 0x3904, 0x1d9d: 0x3906, - 0x1d9e: 0x390a, 0x1d9f: 0x3932, 0x1da0: 0x3934, 0x1da1: 0x3936, 0x1da2: 0x1494, 0x1da3: 0x3938, - 0x1da4: 0x393a, 0x1da5: 0x393c, 0x1da6: 0x149a, 0x1da8: 0x393e, 0x1da9: 0x3940, - 0x1daa: 0x3942, 0x1dab: 0x3944, - 0x1db0: 0x3946, 0x1db1: 0x394a, 0x1db2: 0x394f, 0x1db4: 0x3953, - 0x1db6: 0x3957, 0x1db7: 0x395b, 0x1db8: 0x3960, 0x1db9: 0x3964, 0x1dba: 0x3969, 0x1dbb: 0x396d, - 0x1dbc: 0x3972, 0x1dbd: 0x3976, 0x1dbe: 0x397b, 0x1dbf: 0x397f, - // Block 0x77, offset 0x1dc0 - 0x1dc0: 0x3984, 0x1dc1: 0x068d, 0x1dc2: 0x068d, 0x1dc3: 0x0692, 0x1dc4: 0x0692, 0x1dc5: 0x0697, - 0x1dc6: 0x0697, 0x1dc7: 0x069c, 0x1dc8: 0x069c, 0x1dc9: 0x06a1, 0x1dca: 0x06a1, 0x1dcb: 0x06a1, - 0x1dcc: 0x06a1, 0x1dcd: 0x3987, 0x1dce: 0x3987, 0x1dcf: 0x398a, 0x1dd0: 0x398a, 0x1dd1: 0x398a, - 0x1dd2: 0x398a, 0x1dd3: 0x398d, 0x1dd4: 0x398d, 0x1dd5: 0x3990, 0x1dd6: 0x3990, 0x1dd7: 0x3990, - 0x1dd8: 0x3990, 0x1dd9: 0x3993, 0x1dda: 0x3993, 0x1ddb: 0x3993, 0x1ddc: 0x3993, 0x1ddd: 0x3996, - 0x1dde: 0x3996, 0x1ddf: 0x3996, 0x1de0: 0x3996, 0x1de1: 0x3999, 0x1de2: 0x3999, 0x1de3: 0x3999, - 0x1de4: 0x3999, 0x1de5: 0x399c, 0x1de6: 0x399c, 0x1de7: 0x399c, 0x1de8: 0x399c, 0x1de9: 0x399f, - 0x1dea: 0x399f, 0x1deb: 0x39a2, 0x1dec: 0x39a2, 0x1ded: 0x39a5, 0x1dee: 0x39a5, 0x1def: 0x39a8, - 0x1df0: 0x39a8, 0x1df1: 0x39ab, 0x1df2: 0x39ab, 0x1df3: 0x39ab, 0x1df4: 0x39ab, 0x1df5: 0x39ae, - 0x1df6: 0x39ae, 0x1df7: 0x39ae, 0x1df8: 0x39ae, 0x1df9: 0x39b1, 0x1dfa: 0x39b1, 0x1dfb: 0x39b1, - 0x1dfc: 0x39b1, 0x1dfd: 0x39b4, 0x1dfe: 0x39b4, 0x1dff: 0x39b4, - // Block 0x78, offset 0x1e00 - 0x1e00: 0x39b4, 0x1e01: 0x39b7, 0x1e02: 0x39b7, 0x1e03: 0x39b7, 0x1e04: 0x39b7, 0x1e05: 0x39ba, - 0x1e06: 0x39ba, 0x1e07: 0x39ba, 0x1e08: 0x39ba, 0x1e09: 0x39bd, 0x1e0a: 0x39bd, 0x1e0b: 0x39bd, - 0x1e0c: 0x39bd, 0x1e0d: 0x39c0, 0x1e0e: 0x39c0, 0x1e0f: 0x39c0, 0x1e10: 0x39c0, 0x1e11: 0x39c3, - 0x1e12: 0x39c3, 0x1e13: 0x39c3, 0x1e14: 0x39c3, 0x1e15: 0x39c6, 0x1e16: 0x39c6, 0x1e17: 0x39c6, - 0x1e18: 0x39c6, 0x1e19: 0x39c9, 0x1e1a: 0x39c9, 0x1e1b: 0x39c9, 0x1e1c: 0x39c9, 0x1e1d: 0x39cc, - 0x1e1e: 0x39cc, 0x1e1f: 0x39cc, 0x1e20: 0x39cc, 0x1e21: 0x39cf, 0x1e22: 0x39cf, 0x1e23: 0x39cf, - 0x1e24: 0x39cf, 0x1e25: 0x39d2, 0x1e26: 0x39d2, 0x1e27: 0x39d2, 0x1e28: 0x39d2, 0x1e29: 0x39d5, - 0x1e2a: 0x39d5, 0x1e2b: 0x39d5, 0x1e2c: 0x39d5, 0x1e2d: 0x39d8, 0x1e2e: 0x39d8, 0x1e2f: 0x3239, - 0x1e30: 0x3239, 0x1e31: 0x39db, 0x1e32: 0x39db, 0x1e33: 0x39db, 0x1e34: 0x39db, 0x1e35: 0x39de, - 0x1e36: 0x39de, 0x1e37: 0x39e5, 0x1e38: 0x39e5, 0x1e39: 0x39ec, 0x1e3a: 0x39ec, 0x1e3b: 0x39f3, - 0x1e3c: 0x39f3, - // Block 0x79, offset 0x1e40 - 0x1e41: 0x38ec, 0x1e42: 0x39f8, 0x1e43: 0x3932, 0x1e44: 0x3940, 0x1e45: 0x3942, - 0x1e46: 0x3934, 0x1e47: 0x39fa, 0x1e48: 0x149c, 0x1e49: 0x149e, 0x1e4a: 0x3936, 0x1e4b: 0x1494, - 0x1e4c: 0x38e0, 0x1e4d: 0x3938, 0x1e4e: 0x143e, 0x1e4f: 0x39fc, 0x1e50: 0x1486, 0x1e51: 0x001c, - 0x1e52: 0x000d, 0x1e53: 0x000f, 0x1e54: 0x1488, 0x1e55: 0x148a, 0x1e56: 0x148c, 0x1e57: 0x148e, - 0x1e58: 0x1490, 0x1e59: 0x1492, 0x1e5a: 0x38ea, 0x1e5b: 0x04e1, 0x1e5c: 0x393a, 0x1e5d: 0x149a, - 0x1e5e: 0x393c, 0x1e5f: 0x38ee, 0x1e60: 0x3944, 0x1e61: 0x0906, 0x1e62: 0x090b, 0x1e63: 0x14ad, - 0x1e64: 0x090d, 0x1e65: 0x090f, 0x1e66: 0x14d9, 0x1e67: 0x0914, 0x1e68: 0x0916, 0x1e69: 0x0918, - 0x1e6a: 0x091a, 0x1e6b: 0x091c, 0x1e6c: 0x091e, 0x1e6d: 0x0920, 0x1e6e: 0x0922, 0x1e6f: 0x0924, - 0x1e70: 0x0929, 0x1e71: 0x14c8, 0x1e72: 0x092b, 0x1e73: 0x17f6, 0x1e74: 0x092d, 0x1e75: 0x092f, - 0x1e76: 0x155f, 0x1e77: 0x0931, 0x1e78: 0x1570, 0x1e79: 0x17f8, 0x1e7a: 0x14d4, 0x1e7b: 0x392e, - 0x1e7c: 0x393e, 0x1e7d: 0x3930, 0x1e7e: 0x39fe, 0x1e7f: 0x3900, - // Block 0x7a, offset 0x1e80 - 0x1e80: 0x13f7, 0x1e81: 0x0007, 0x1e82: 0x093d, 0x1e83: 0x0984, 0x1e84: 0x093f, 0x1e85: 0x0941, - 0x1e86: 0x098c, 0x1e87: 0x094c, 0x1e88: 0x0494, 0x1e89: 0x097c, 0x1e8a: 0x0499, 0x1e8b: 0x094e, - 0x1e8c: 0x04c5, 0x1e8d: 0x0950, 0x1e8e: 0x14a0, 0x1e8f: 0x001e, 0x1e90: 0x0960, 0x1e91: 0x17fa, - 0x1e92: 0x049b, 0x1e93: 0x02c8, 0x1e94: 0x0962, 0x1e95: 0x0964, 0x1e96: 0x096d, 0x1e97: 0x04a6, - 0x1e98: 0x04c7, 0x1e99: 0x04a8, 0x1e9a: 0x09df, 0x1e9b: 0x3902, 0x1e9c: 0x3a00, 0x1e9d: 0x3904, - 0x1e9e: 0x3a02, 0x1e9f: 0x3a04, 0x1ea0: 0x3a08, 0x1ea1: 0x38e6, 0x1ea2: 0x391e, 0x1ea3: 0x3922, - 0x1ea4: 0x38e2, 0x1ea5: 0x3a0c, 0x1ea6: 0x2321, 0x1ea7: 0x3a10, 0x1ea8: 0x3a14, 0x1ea9: 0x3a18, - 0x1eaa: 0x3a1c, 0x1eab: 0x3a20, 0x1eac: 0x3a24, 0x1ead: 0x3a28, 0x1eae: 0x3a2c, 0x1eaf: 0x3a30, - 0x1eb0: 0x3a34, 0x1eb1: 0x2269, 0x1eb2: 0x226d, 0x1eb3: 0x2271, 0x1eb4: 0x2275, 0x1eb5: 0x2279, - 0x1eb6: 0x227d, 0x1eb7: 0x2281, 0x1eb8: 0x2285, 0x1eb9: 0x2289, 0x1eba: 0x228d, 0x1ebb: 0x2291, - 0x1ebc: 0x2295, 0x1ebd: 0x2299, 0x1ebe: 0x229d, 0x1ebf: 0x22a1, - // Block 0x7b, offset 0x1ec0 - 0x1ec0: 0x22a5, 0x1ec1: 0x22a9, 0x1ec2: 0x22ad, 0x1ec3: 0x22b1, 0x1ec4: 0x22b5, 0x1ec5: 0x22b9, - 0x1ec6: 0x22bd, 0x1ec7: 0x22c1, 0x1ec8: 0x22c5, 0x1ec9: 0x22c9, 0x1eca: 0x22cd, 0x1ecb: 0x22d1, - 0x1ecc: 0x22d5, 0x1ecd: 0x22d9, 0x1ece: 0x22dd, 0x1ecf: 0x22e1, 0x1ed0: 0x22e5, 0x1ed1: 0x22e9, - 0x1ed2: 0x22ed, 0x1ed3: 0x22f1, 0x1ed4: 0x22f5, 0x1ed5: 0x22f9, 0x1ed6: 0x22fd, 0x1ed7: 0x2301, - 0x1ed8: 0x2305, 0x1ed9: 0x2309, 0x1eda: 0x230d, 0x1edb: 0x2311, 0x1edc: 0x2315, 0x1edd: 0x3a38, - 0x1ede: 0x3a3c, 0x1edf: 0x3a40, 0x1ee0: 0x1e04, 0x1ee1: 0x1d38, 0x1ee2: 0x1d3c, 0x1ee3: 0x1d40, - 0x1ee4: 0x1d44, 0x1ee5: 0x1d48, 0x1ee6: 0x1d4c, 0x1ee7: 0x1d50, 0x1ee8: 0x1d54, 0x1ee9: 0x1d58, - 0x1eea: 0x1d5c, 0x1eeb: 0x1d60, 0x1eec: 0x1d64, 0x1eed: 0x1d68, 0x1eee: 0x1d6c, 0x1eef: 0x1d70, - 0x1ef0: 0x1d74, 0x1ef1: 0x1d78, 0x1ef2: 0x1d7c, 0x1ef3: 0x1d80, 0x1ef4: 0x1d84, 0x1ef5: 0x1d88, - 0x1ef6: 0x1d8c, 0x1ef7: 0x1d90, 0x1ef8: 0x1d94, 0x1ef9: 0x1d98, 0x1efa: 0x1d9c, 0x1efb: 0x1da0, - 0x1efc: 0x1da4, 0x1efd: 0x1da8, 0x1efe: 0x1dac, - // Block 0x7c, offset 0x1f00 - 0x1f02: 0x1db0, 0x1f03: 0x1db4, 0x1f04: 0x1db8, 0x1f05: 0x1dbc, - 0x1f06: 0x1dc0, 0x1f07: 0x1dc4, 0x1f0a: 0x1dc8, 0x1f0b: 0x1dcc, - 0x1f0c: 0x1dd0, 0x1f0d: 0x1dd4, 0x1f0e: 0x1dd8, 0x1f0f: 0x1ddc, - 0x1f12: 0x1de0, 0x1f13: 0x1de4, 0x1f14: 0x1de8, 0x1f15: 0x1dec, 0x1f16: 0x1df0, 0x1f17: 0x1df4, - 0x1f1a: 0x1df8, 0x1f1b: 0x1dfc, 0x1f1c: 0x1e00, - 0x1f20: 0x3a44, 0x1f21: 0x3a47, 0x1f22: 0x3a4a, 0x1f23: 0x0009, - 0x1f24: 0x3a4d, 0x1f25: 0x3a50, 0x1f26: 0x3a53, 0x1f28: 0x3a57, 0x1f29: 0x3a5b, - 0x1f2a: 0x3a5f, 0x1f2b: 0x3a63, 0x1f2c: 0x3a67, 0x1f2d: 0x3a6b, 0x1f2e: 0x3a6f, - // Block 0x7d, offset 0x1f40 - 0x1f5a: 0x3a73, 0x1f5c: 0x3a7c, - 0x1f6b: 0x3a85, - // Block 0x7e, offset 0x1f80 - 0x1f9e: 0x3a8e, 0x1f9f: 0x3a97, 0x1fa0: 0x3aa0, 0x1fa1: 0x3aad, 0x1fa2: 0x3aba, 0x1fa3: 0x3ac7, - 0x1fa4: 0x3ad4, - // Block 0x7f, offset 0x1fc0 - 0x1ffb: 0x3ae1, - 0x1ffc: 0x3aea, 0x1ffd: 0x3af3, 0x1ffe: 0x3b00, 0x1fff: 0x3b0d, - // Block 0x80, offset 0x2000 - 0x2000: 0x3b1a, - // Block 0x81, offset 0x2040 - 0x2040: 0x0906, 0x2041: 0x090b, 0x2042: 0x14ad, 0x2043: 0x090d, 0x2044: 0x090f, 0x2045: 0x14d9, - 0x2046: 0x0914, 0x2047: 0x0916, 0x2048: 0x0918, 0x2049: 0x091a, 0x204a: 0x091c, 0x204b: 0x091e, - 0x204c: 0x0920, 0x204d: 0x0922, 0x204e: 0x0924, 0x204f: 0x0929, 0x2050: 0x14c8, 0x2051: 0x092b, - 0x2052: 0x17f6, 0x2053: 0x092d, 0x2054: 0x092f, 0x2055: 0x155f, 0x2056: 0x0931, 0x2057: 0x1570, - 0x2058: 0x17f8, 0x2059: 0x14d4, 0x205a: 0x0007, 0x205b: 0x093d, 0x205c: 0x0984, 0x205d: 0x093f, - 0x205e: 0x0941, 0x205f: 0x098c, 0x2060: 0x094c, 0x2061: 0x0494, 0x2062: 0x097c, 0x2063: 0x0499, - 0x2064: 0x094e, 0x2065: 0x04c5, 0x2066: 0x0950, 0x2067: 0x14a0, 0x2068: 0x001e, 0x2069: 0x0960, - 0x206a: 0x17fa, 0x206b: 0x049b, 0x206c: 0x02c8, 0x206d: 0x0962, 0x206e: 0x0964, 0x206f: 0x096d, - 0x2070: 0x04a6, 0x2071: 0x04c7, 0x2072: 0x04a8, 0x2073: 0x09df, 0x2074: 0x0906, 0x2075: 0x090b, - 0x2076: 0x14ad, 0x2077: 0x090d, 0x2078: 0x090f, 0x2079: 0x14d9, 0x207a: 0x0914, 0x207b: 0x0916, - 0x207c: 0x0918, 0x207d: 0x091a, 0x207e: 0x091c, 0x207f: 0x091e, - // Block 0x82, offset 0x2080 - 0x2080: 0x0920, 0x2081: 0x0922, 0x2082: 0x0924, 0x2083: 0x0929, 0x2084: 0x14c8, 0x2085: 0x092b, - 0x2086: 0x17f6, 0x2087: 0x092d, 0x2088: 0x092f, 0x2089: 0x155f, 0x208a: 0x0931, 0x208b: 0x1570, - 0x208c: 0x17f8, 0x208d: 0x14d4, 0x208e: 0x0007, 0x208f: 0x093d, 0x2090: 0x0984, 0x2091: 0x093f, - 0x2092: 0x0941, 0x2093: 0x098c, 0x2094: 0x094c, 0x2096: 0x097c, 0x2097: 0x0499, - 0x2098: 0x094e, 0x2099: 0x04c5, 0x209a: 0x0950, 0x209b: 0x14a0, 0x209c: 0x001e, 0x209d: 0x0960, - 0x209e: 0x17fa, 0x209f: 0x049b, 0x20a0: 0x02c8, 0x20a1: 0x0962, 0x20a2: 0x0964, 0x20a3: 0x096d, - 0x20a4: 0x04a6, 0x20a5: 0x04c7, 0x20a6: 0x04a8, 0x20a7: 0x09df, 0x20a8: 0x0906, 0x20a9: 0x090b, - 0x20aa: 0x14ad, 0x20ab: 0x090d, 0x20ac: 0x090f, 0x20ad: 0x14d9, 0x20ae: 0x0914, 0x20af: 0x0916, - 0x20b0: 0x0918, 0x20b1: 0x091a, 0x20b2: 0x091c, 0x20b3: 0x091e, 0x20b4: 0x0920, 0x20b5: 0x0922, - 0x20b6: 0x0924, 0x20b7: 0x0929, 0x20b8: 0x14c8, 0x20b9: 0x092b, 0x20ba: 0x17f6, 0x20bb: 0x092d, - 0x20bc: 0x092f, 0x20bd: 0x155f, 0x20be: 0x0931, 0x20bf: 0x1570, - // Block 0x83, offset 0x20c0 - 0x20c0: 0x17f8, 0x20c1: 0x14d4, 0x20c2: 0x0007, 0x20c3: 0x093d, 0x20c4: 0x0984, 0x20c5: 0x093f, - 0x20c6: 0x0941, 0x20c7: 0x098c, 0x20c8: 0x094c, 0x20c9: 0x0494, 0x20ca: 0x097c, 0x20cb: 0x0499, - 0x20cc: 0x094e, 0x20cd: 0x04c5, 0x20ce: 0x0950, 0x20cf: 0x14a0, 0x20d0: 0x001e, 0x20d1: 0x0960, - 0x20d2: 0x17fa, 0x20d3: 0x049b, 0x20d4: 0x02c8, 0x20d5: 0x0962, 0x20d6: 0x0964, 0x20d7: 0x096d, - 0x20d8: 0x04a6, 0x20d9: 0x04c7, 0x20da: 0x04a8, 0x20db: 0x09df, 0x20dc: 0x0906, - 0x20de: 0x14ad, 0x20df: 0x090d, 0x20e2: 0x0914, - 0x20e5: 0x091a, 0x20e6: 0x091c, 0x20e9: 0x0922, - 0x20ea: 0x0924, 0x20eb: 0x0929, 0x20ec: 0x14c8, 0x20ee: 0x17f6, 0x20ef: 0x092d, - 0x20f0: 0x092f, 0x20f1: 0x155f, 0x20f2: 0x0931, 0x20f3: 0x1570, 0x20f4: 0x17f8, 0x20f5: 0x14d4, - 0x20f6: 0x0007, 0x20f7: 0x093d, 0x20f8: 0x0984, 0x20f9: 0x093f, 0x20fb: 0x098c, - 0x20fd: 0x0494, 0x20fe: 0x097c, 0x20ff: 0x0499, - // Block 0x84, offset 0x2100 - 0x2100: 0x094e, 0x2101: 0x04c5, 0x2102: 0x0950, 0x2103: 0x14a0, 0x2105: 0x0960, - 0x2106: 0x17fa, 0x2107: 0x049b, 0x2108: 0x02c8, 0x2109: 0x0962, 0x210a: 0x0964, 0x210b: 0x096d, - 0x210c: 0x04a6, 0x210d: 0x04c7, 0x210e: 0x04a8, 0x210f: 0x09df, 0x2110: 0x0906, 0x2111: 0x090b, - 0x2112: 0x14ad, 0x2113: 0x090d, 0x2114: 0x090f, 0x2115: 0x14d9, 0x2116: 0x0914, 0x2117: 0x0916, - 0x2118: 0x0918, 0x2119: 0x091a, 0x211a: 0x091c, 0x211b: 0x091e, 0x211c: 0x0920, 0x211d: 0x0922, - 0x211e: 0x0924, 0x211f: 0x0929, 0x2120: 0x14c8, 0x2121: 0x092b, 0x2122: 0x17f6, 0x2123: 0x092d, - 0x2124: 0x092f, 0x2125: 0x155f, 0x2126: 0x0931, 0x2127: 0x1570, 0x2128: 0x17f8, 0x2129: 0x14d4, - 0x212a: 0x0007, 0x212b: 0x093d, 0x212c: 0x0984, 0x212d: 0x093f, 0x212e: 0x0941, 0x212f: 0x098c, - 0x2130: 0x094c, 0x2131: 0x0494, 0x2132: 0x097c, 0x2133: 0x0499, 0x2134: 0x094e, 0x2135: 0x04c5, - 0x2136: 0x0950, 0x2137: 0x14a0, 0x2138: 0x001e, 0x2139: 0x0960, 0x213a: 0x17fa, 0x213b: 0x049b, - 0x213c: 0x02c8, 0x213d: 0x0962, 0x213e: 0x0964, 0x213f: 0x096d, - // Block 0x85, offset 0x2140 - 0x2140: 0x04a6, 0x2141: 0x04c7, 0x2142: 0x04a8, 0x2143: 0x09df, 0x2144: 0x0906, 0x2145: 0x090b, - 0x2147: 0x090d, 0x2148: 0x090f, 0x2149: 0x14d9, 0x214a: 0x0914, - 0x214d: 0x091a, 0x214e: 0x091c, 0x214f: 0x091e, 0x2150: 0x0920, 0x2151: 0x0922, - 0x2152: 0x0924, 0x2153: 0x0929, 0x2154: 0x14c8, 0x2156: 0x17f6, 0x2157: 0x092d, - 0x2158: 0x092f, 0x2159: 0x155f, 0x215a: 0x0931, 0x215b: 0x1570, 0x215c: 0x17f8, - 0x215e: 0x0007, 0x215f: 0x093d, 0x2160: 0x0984, 0x2161: 0x093f, 0x2162: 0x0941, 0x2163: 0x098c, - 0x2164: 0x094c, 0x2165: 0x0494, 0x2166: 0x097c, 0x2167: 0x0499, 0x2168: 0x094e, 0x2169: 0x04c5, - 0x216a: 0x0950, 0x216b: 0x14a0, 0x216c: 0x001e, 0x216d: 0x0960, 0x216e: 0x17fa, 0x216f: 0x049b, - 0x2170: 0x02c8, 0x2171: 0x0962, 0x2172: 0x0964, 0x2173: 0x096d, 0x2174: 0x04a6, 0x2175: 0x04c7, - 0x2176: 0x04a8, 0x2177: 0x09df, 0x2178: 0x0906, 0x2179: 0x090b, 0x217b: 0x090d, - 0x217c: 0x090f, 0x217d: 0x14d9, 0x217e: 0x0914, - // Block 0x86, offset 0x2180 - 0x2180: 0x0918, 0x2181: 0x091a, 0x2182: 0x091c, 0x2183: 0x091e, 0x2184: 0x0920, - 0x2186: 0x0924, 0x218a: 0x17f6, 0x218b: 0x092d, - 0x218c: 0x092f, 0x218d: 0x155f, 0x218e: 0x0931, 0x218f: 0x1570, 0x2190: 0x17f8, - 0x2192: 0x0007, 0x2193: 0x093d, 0x2194: 0x0984, 0x2195: 0x093f, 0x2196: 0x0941, 0x2197: 0x098c, - 0x2198: 0x094c, 0x2199: 0x0494, 0x219a: 0x097c, 0x219b: 0x0499, 0x219c: 0x094e, 0x219d: 0x04c5, - 0x219e: 0x0950, 0x219f: 0x14a0, 0x21a0: 0x001e, 0x21a1: 0x0960, 0x21a2: 0x17fa, 0x21a3: 0x049b, - 0x21a4: 0x02c8, 0x21a5: 0x0962, 0x21a6: 0x0964, 0x21a7: 0x096d, 0x21a8: 0x04a6, 0x21a9: 0x04c7, - 0x21aa: 0x04a8, 0x21ab: 0x09df, 0x21ac: 0x0906, 0x21ad: 0x090b, 0x21ae: 0x14ad, 0x21af: 0x090d, - 0x21b0: 0x090f, 0x21b1: 0x14d9, 0x21b2: 0x0914, 0x21b3: 0x0916, 0x21b4: 0x0918, 0x21b5: 0x091a, - 0x21b6: 0x091c, 0x21b7: 0x091e, 0x21b8: 0x0920, 0x21b9: 0x0922, 0x21ba: 0x0924, 0x21bb: 0x0929, - 0x21bc: 0x14c8, 0x21bd: 0x092b, 0x21be: 0x17f6, 0x21bf: 0x092d, - // Block 0x87, offset 0x21c0 - 0x21c0: 0x092f, 0x21c1: 0x155f, 0x21c2: 0x0931, 0x21c3: 0x1570, 0x21c4: 0x17f8, 0x21c5: 0x14d4, - 0x21c6: 0x0007, 0x21c7: 0x093d, 0x21c8: 0x0984, 0x21c9: 0x093f, 0x21ca: 0x0941, 0x21cb: 0x098c, - 0x21cc: 0x094c, 0x21cd: 0x0494, 0x21ce: 0x097c, 0x21cf: 0x0499, 0x21d0: 0x094e, 0x21d1: 0x04c5, - 0x21d2: 0x0950, 0x21d3: 0x14a0, 0x21d4: 0x001e, 0x21d5: 0x0960, 0x21d6: 0x17fa, 0x21d7: 0x049b, - 0x21d8: 0x02c8, 0x21d9: 0x0962, 0x21da: 0x0964, 0x21db: 0x096d, 0x21dc: 0x04a6, 0x21dd: 0x04c7, - 0x21de: 0x04a8, 0x21df: 0x09df, 0x21e0: 0x0906, 0x21e1: 0x090b, 0x21e2: 0x14ad, 0x21e3: 0x090d, - 0x21e4: 0x090f, 0x21e5: 0x14d9, 0x21e6: 0x0914, 0x21e7: 0x0916, 0x21e8: 0x0918, 0x21e9: 0x091a, - 0x21ea: 0x091c, 0x21eb: 0x091e, 0x21ec: 0x0920, 0x21ed: 0x0922, 0x21ee: 0x0924, 0x21ef: 0x0929, - 0x21f0: 0x14c8, 0x21f1: 0x092b, 0x21f2: 0x17f6, 0x21f3: 0x092d, 0x21f4: 0x092f, 0x21f5: 0x155f, - 0x21f6: 0x0931, 0x21f7: 0x1570, 0x21f8: 0x17f8, 0x21f9: 0x14d4, 0x21fa: 0x0007, 0x21fb: 0x093d, - 0x21fc: 0x0984, 0x21fd: 0x093f, 0x21fe: 0x0941, 0x21ff: 0x098c, - // Block 0x88, offset 0x2200 - 0x2200: 0x094c, 0x2201: 0x0494, 0x2202: 0x097c, 0x2203: 0x0499, 0x2204: 0x094e, 0x2205: 0x04c5, - 0x2206: 0x0950, 0x2207: 0x14a0, 0x2208: 0x001e, 0x2209: 0x0960, 0x220a: 0x17fa, 0x220b: 0x049b, - 0x220c: 0x02c8, 0x220d: 0x0962, 0x220e: 0x0964, 0x220f: 0x096d, 0x2210: 0x04a6, 0x2211: 0x04c7, - 0x2212: 0x04a8, 0x2213: 0x09df, 0x2214: 0x0906, 0x2215: 0x090b, 0x2216: 0x14ad, 0x2217: 0x090d, - 0x2218: 0x090f, 0x2219: 0x14d9, 0x221a: 0x0914, 0x221b: 0x0916, 0x221c: 0x0918, 0x221d: 0x091a, - 0x221e: 0x091c, 0x221f: 0x091e, 0x2220: 0x0920, 0x2221: 0x0922, 0x2222: 0x0924, 0x2223: 0x0929, - 0x2224: 0x14c8, 0x2225: 0x092b, 0x2226: 0x17f6, 0x2227: 0x092d, 0x2228: 0x092f, 0x2229: 0x155f, - 0x222a: 0x0931, 0x222b: 0x1570, 0x222c: 0x17f8, 0x222d: 0x14d4, 0x222e: 0x0007, 0x222f: 0x093d, - 0x2230: 0x0984, 0x2231: 0x093f, 0x2232: 0x0941, 0x2233: 0x098c, 0x2234: 0x094c, 0x2235: 0x0494, - 0x2236: 0x097c, 0x2237: 0x0499, 0x2238: 0x094e, 0x2239: 0x04c5, 0x223a: 0x0950, 0x223b: 0x14a0, - 0x223c: 0x001e, 0x223d: 0x0960, 0x223e: 0x17fa, 0x223f: 0x049b, - // Block 0x89, offset 0x2240 - 0x2240: 0x02c8, 0x2241: 0x0962, 0x2242: 0x0964, 0x2243: 0x096d, 0x2244: 0x04a6, 0x2245: 0x04c7, - 0x2246: 0x04a8, 0x2247: 0x09df, 0x2248: 0x0906, 0x2249: 0x090b, 0x224a: 0x14ad, 0x224b: 0x090d, - 0x224c: 0x090f, 0x224d: 0x14d9, 0x224e: 0x0914, 0x224f: 0x0916, 0x2250: 0x0918, 0x2251: 0x091a, - 0x2252: 0x091c, 0x2253: 0x091e, 0x2254: 0x0920, 0x2255: 0x0922, 0x2256: 0x0924, 0x2257: 0x0929, - 0x2258: 0x14c8, 0x2259: 0x092b, 0x225a: 0x17f6, 0x225b: 0x092d, 0x225c: 0x092f, 0x225d: 0x155f, - 0x225e: 0x0931, 0x225f: 0x1570, 0x2260: 0x17f8, 0x2261: 0x14d4, 0x2262: 0x0007, 0x2263: 0x093d, - 0x2264: 0x0984, 0x2265: 0x093f, 0x2266: 0x0941, 0x2267: 0x098c, 0x2268: 0x094c, 0x2269: 0x0494, - 0x226a: 0x097c, 0x226b: 0x0499, 0x226c: 0x094e, 0x226d: 0x04c5, 0x226e: 0x0950, 0x226f: 0x14a0, - 0x2270: 0x001e, 0x2271: 0x0960, 0x2272: 0x17fa, 0x2273: 0x049b, 0x2274: 0x02c8, 0x2275: 0x0962, - 0x2276: 0x0964, 0x2277: 0x096d, 0x2278: 0x04a6, 0x2279: 0x04c7, 0x227a: 0x04a8, 0x227b: 0x09df, - 0x227c: 0x0906, 0x227d: 0x090b, 0x227e: 0x14ad, 0x227f: 0x090d, - // Block 0x8a, offset 0x2280 - 0x2280: 0x090f, 0x2281: 0x14d9, 0x2282: 0x0914, 0x2283: 0x0916, 0x2284: 0x0918, 0x2285: 0x091a, - 0x2286: 0x091c, 0x2287: 0x091e, 0x2288: 0x0920, 0x2289: 0x0922, 0x228a: 0x0924, 0x228b: 0x0929, - 0x228c: 0x14c8, 0x228d: 0x092b, 0x228e: 0x17f6, 0x228f: 0x092d, 0x2290: 0x092f, 0x2291: 0x155f, - 0x2292: 0x0931, 0x2293: 0x1570, 0x2294: 0x17f8, 0x2295: 0x14d4, 0x2296: 0x0007, 0x2297: 0x093d, - 0x2298: 0x0984, 0x2299: 0x093f, 0x229a: 0x0941, 0x229b: 0x098c, 0x229c: 0x094c, 0x229d: 0x0494, - 0x229e: 0x097c, 0x229f: 0x0499, 0x22a0: 0x094e, 0x22a1: 0x04c5, 0x22a2: 0x0950, 0x22a3: 0x14a0, - 0x22a4: 0x001e, 0x22a5: 0x0960, 0x22a6: 0x17fa, 0x22a7: 0x049b, 0x22a8: 0x02c8, 0x22a9: 0x0962, - 0x22aa: 0x0964, 0x22ab: 0x096d, 0x22ac: 0x04a6, 0x22ad: 0x04c7, 0x22ae: 0x04a8, 0x22af: 0x09df, - 0x22b0: 0x0906, 0x22b1: 0x090b, 0x22b2: 0x14ad, 0x22b3: 0x090d, 0x22b4: 0x090f, 0x22b5: 0x14d9, - 0x22b6: 0x0914, 0x22b7: 0x0916, 0x22b8: 0x0918, 0x22b9: 0x091a, 0x22ba: 0x091c, 0x22bb: 0x091e, - 0x22bc: 0x0920, 0x22bd: 0x0922, 0x22be: 0x0924, 0x22bf: 0x0929, - // Block 0x8b, offset 0x22c0 - 0x22c0: 0x14c8, 0x22c1: 0x092b, 0x22c2: 0x17f6, 0x22c3: 0x092d, 0x22c4: 0x092f, 0x22c5: 0x155f, - 0x22c6: 0x0931, 0x22c7: 0x1570, 0x22c8: 0x17f8, 0x22c9: 0x14d4, 0x22ca: 0x0007, 0x22cb: 0x093d, - 0x22cc: 0x0984, 0x22cd: 0x093f, 0x22ce: 0x0941, 0x22cf: 0x098c, 0x22d0: 0x094c, 0x22d1: 0x0494, - 0x22d2: 0x097c, 0x22d3: 0x0499, 0x22d4: 0x094e, 0x22d5: 0x04c5, 0x22d6: 0x0950, 0x22d7: 0x14a0, - 0x22d8: 0x001e, 0x22d9: 0x0960, 0x22da: 0x17fa, 0x22db: 0x049b, 0x22dc: 0x02c8, 0x22dd: 0x0962, - 0x22de: 0x0964, 0x22df: 0x096d, 0x22e0: 0x04a6, 0x22e1: 0x04c7, 0x22e2: 0x04a8, 0x22e3: 0x09df, - 0x22e4: 0x3b27, 0x22e5: 0x3b2a, 0x22e8: 0x3b2d, 0x22e9: 0x3b30, - 0x22ea: 0x14eb, 0x22eb: 0x3b33, 0x22ec: 0x3b36, 0x22ed: 0x3b39, 0x22ee: 0x3b3c, 0x22ef: 0x057b, - 0x22f0: 0x3b3f, 0x22f1: 0x3b42, 0x22f2: 0x3b45, 0x22f3: 0x3b48, 0x22f4: 0x3b4b, 0x22f5: 0x3b4e, - 0x22f6: 0x3b51, 0x22f7: 0x14ee, 0x22f8: 0x3b54, 0x22f9: 0x057b, 0x22fa: 0x0581, 0x22fb: 0x3b57, - 0x22fc: 0x055f, 0x22fd: 0x3b5a, 0x22fe: 0x3b5d, 0x22ff: 0x3b60, - // Block 0x8c, offset 0x2300 - 0x2300: 0x14d6, 0x2301: 0x3b63, 0x2302: 0x3b67, 0x2303: 0x0559, 0x2304: 0x0973, 0x2305: 0x0976, - 0x2306: 0x057e, 0x2307: 0x3b6a, 0x2308: 0x3b6d, 0x2309: 0x055c, 0x230a: 0x12fd, 0x230b: 0x0572, - 0x230c: 0x3b70, 0x230d: 0x0015, 0x230e: 0x3b73, 0x230f: 0x3b76, 0x2310: 0x3b79, 0x2311: 0x056f, - 0x2312: 0x0575, 0x2313: 0x0578, 0x2314: 0x3b7c, 0x2315: 0x3b7f, 0x2316: 0x3b82, 0x2317: 0x056c, - 0x2318: 0x0979, 0x2319: 0x3b85, 0x231a: 0x3b88, 0x231b: 0x3b8b, 0x231c: 0x057e, 0x231d: 0x055c, - 0x231e: 0x0572, 0x231f: 0x056c, 0x2320: 0x0575, 0x2321: 0x056f, 0x2322: 0x3b2d, 0x2323: 0x3b30, - 0x2324: 0x14eb, 0x2325: 0x3b33, 0x2326: 0x3b36, 0x2327: 0x3b39, 0x2328: 0x3b3c, 0x2329: 0x057b, - 0x232a: 0x3b3f, 0x232b: 0x3b42, 0x232c: 0x3b45, 0x232d: 0x3b48, 0x232e: 0x3b4b, 0x232f: 0x3b4e, - 0x2330: 0x3b51, 0x2331: 0x14ee, 0x2332: 0x3b54, 0x2333: 0x057b, 0x2334: 0x0581, 0x2335: 0x3b57, - 0x2336: 0x055f, 0x2337: 0x3b5a, 0x2338: 0x3b5d, 0x2339: 0x3b60, 0x233a: 0x14d6, 0x233b: 0x3b63, - 0x233c: 0x3b67, 0x233d: 0x0559, 0x233e: 0x0973, 0x233f: 0x0976, - // Block 0x8d, offset 0x2340 - 0x2340: 0x057e, 0x2341: 0x3b6a, 0x2342: 0x3b6d, 0x2343: 0x055c, 0x2344: 0x12fd, 0x2345: 0x0572, - 0x2346: 0x3b70, 0x2347: 0x0015, 0x2348: 0x3b73, 0x2349: 0x3b76, 0x234a: 0x3b79, 0x234b: 0x056f, - 0x234c: 0x0575, 0x234d: 0x0578, 0x234e: 0x3b7c, 0x234f: 0x3b7f, 0x2350: 0x3b82, 0x2351: 0x056c, - 0x2352: 0x0979, 0x2353: 0x3b85, 0x2354: 0x3b88, 0x2355: 0x3b8b, 0x2356: 0x057e, 0x2357: 0x055c, - 0x2358: 0x0572, 0x2359: 0x056c, 0x235a: 0x0575, 0x235b: 0x056f, 0x235c: 0x3b2d, 0x235d: 0x3b30, - 0x235e: 0x14eb, 0x235f: 0x3b33, 0x2360: 0x3b36, 0x2361: 0x3b39, 0x2362: 0x3b3c, 0x2363: 0x057b, - 0x2364: 0x3b3f, 0x2365: 0x3b42, 0x2366: 0x3b45, 0x2367: 0x3b48, 0x2368: 0x3b4b, 0x2369: 0x3b4e, - 0x236a: 0x3b51, 0x236b: 0x14ee, 0x236c: 0x3b54, 0x236d: 0x057b, 0x236e: 0x0581, 0x236f: 0x3b57, - 0x2370: 0x055f, 0x2371: 0x3b5a, 0x2372: 0x3b5d, 0x2373: 0x3b60, 0x2374: 0x14d6, 0x2375: 0x3b63, - 0x2376: 0x3b67, 0x2377: 0x0559, 0x2378: 0x0973, 0x2379: 0x0976, 0x237a: 0x057e, 0x237b: 0x3b6a, - 0x237c: 0x3b6d, 0x237d: 0x055c, 0x237e: 0x12fd, 0x237f: 0x0572, - // Block 0x8e, offset 0x2380 - 0x2380: 0x3b70, 0x2381: 0x0015, 0x2382: 0x3b73, 0x2383: 0x3b76, 0x2384: 0x3b79, 0x2385: 0x056f, - 0x2386: 0x0575, 0x2387: 0x0578, 0x2388: 0x3b7c, 0x2389: 0x3b7f, 0x238a: 0x3b82, 0x238b: 0x056c, - 0x238c: 0x0979, 0x238d: 0x3b85, 0x238e: 0x3b88, 0x238f: 0x3b8b, 0x2390: 0x057e, 0x2391: 0x055c, - 0x2392: 0x0572, 0x2393: 0x056c, 0x2394: 0x0575, 0x2395: 0x056f, 0x2396: 0x3b2d, 0x2397: 0x3b30, - 0x2398: 0x14eb, 0x2399: 0x3b33, 0x239a: 0x3b36, 0x239b: 0x3b39, 0x239c: 0x3b3c, 0x239d: 0x057b, - 0x239e: 0x3b3f, 0x239f: 0x3b42, 0x23a0: 0x3b45, 0x23a1: 0x3b48, 0x23a2: 0x3b4b, 0x23a3: 0x3b4e, - 0x23a4: 0x3b51, 0x23a5: 0x14ee, 0x23a6: 0x3b54, 0x23a7: 0x057b, 0x23a8: 0x0581, 0x23a9: 0x3b57, - 0x23aa: 0x055f, 0x23ab: 0x3b5a, 0x23ac: 0x3b5d, 0x23ad: 0x3b60, 0x23ae: 0x14d6, 0x23af: 0x3b63, - 0x23b0: 0x3b67, 0x23b1: 0x0559, 0x23b2: 0x0973, 0x23b3: 0x0976, 0x23b4: 0x057e, 0x23b5: 0x3b6a, - 0x23b6: 0x3b6d, 0x23b7: 0x055c, 0x23b8: 0x12fd, 0x23b9: 0x0572, 0x23ba: 0x3b70, 0x23bb: 0x0015, - 0x23bc: 0x3b73, 0x23bd: 0x3b76, 0x23be: 0x3b79, 0x23bf: 0x056f, - // Block 0x8f, offset 0x23c0 - 0x23c0: 0x0575, 0x23c1: 0x0578, 0x23c2: 0x3b7c, 0x23c3: 0x3b7f, 0x23c4: 0x3b82, 0x23c5: 0x056c, - 0x23c6: 0x0979, 0x23c7: 0x3b85, 0x23c8: 0x3b88, 0x23c9: 0x3b8b, 0x23ca: 0x057e, 0x23cb: 0x055c, - 0x23cc: 0x0572, 0x23cd: 0x056c, 0x23ce: 0x0575, 0x23cf: 0x056f, 0x23d0: 0x3b2d, 0x23d1: 0x3b30, - 0x23d2: 0x14eb, 0x23d3: 0x3b33, 0x23d4: 0x3b36, 0x23d5: 0x3b39, 0x23d6: 0x3b3c, 0x23d7: 0x057b, - 0x23d8: 0x3b3f, 0x23d9: 0x3b42, 0x23da: 0x3b45, 0x23db: 0x3b48, 0x23dc: 0x3b4b, 0x23dd: 0x3b4e, - 0x23de: 0x3b51, 0x23df: 0x14ee, 0x23e0: 0x3b54, 0x23e1: 0x057b, 0x23e2: 0x0581, 0x23e3: 0x3b57, - 0x23e4: 0x055f, 0x23e5: 0x3b5a, 0x23e6: 0x3b5d, 0x23e7: 0x3b60, 0x23e8: 0x14d6, 0x23e9: 0x3b63, - 0x23ea: 0x3b67, 0x23eb: 0x0559, 0x23ec: 0x0973, 0x23ed: 0x0976, 0x23ee: 0x057e, 0x23ef: 0x3b6a, - 0x23f0: 0x3b6d, 0x23f1: 0x055c, 0x23f2: 0x12fd, 0x23f3: 0x0572, 0x23f4: 0x3b70, 0x23f5: 0x0015, - 0x23f6: 0x3b73, 0x23f7: 0x3b76, 0x23f8: 0x3b79, 0x23f9: 0x056f, 0x23fa: 0x0575, 0x23fb: 0x0578, - 0x23fc: 0x3b7c, 0x23fd: 0x3b7f, 0x23fe: 0x3b82, 0x23ff: 0x056c, - // Block 0x90, offset 0x2400 - 0x2400: 0x0979, 0x2401: 0x3b85, 0x2402: 0x3b88, 0x2403: 0x3b8b, 0x2404: 0x057e, 0x2405: 0x055c, - 0x2406: 0x0572, 0x2407: 0x056c, 0x2408: 0x0575, 0x2409: 0x056f, 0x240a: 0x3b8f, 0x240b: 0x3b92, - 0x240e: 0x1486, 0x240f: 0x001c, 0x2410: 0x000d, 0x2411: 0x000f, - 0x2412: 0x1488, 0x2413: 0x148a, 0x2414: 0x148c, 0x2415: 0x148e, 0x2416: 0x1490, 0x2417: 0x1492, - 0x2418: 0x1486, 0x2419: 0x001c, 0x241a: 0x000d, 0x241b: 0x000f, 0x241c: 0x1488, 0x241d: 0x148a, - 0x241e: 0x148c, 0x241f: 0x148e, 0x2420: 0x1490, 0x2421: 0x1492, 0x2422: 0x1486, 0x2423: 0x001c, - 0x2424: 0x000d, 0x2425: 0x000f, 0x2426: 0x1488, 0x2427: 0x148a, 0x2428: 0x148c, 0x2429: 0x148e, - 0x242a: 0x1490, 0x242b: 0x1492, 0x242c: 0x1486, 0x242d: 0x001c, 0x242e: 0x000d, 0x242f: 0x000f, - 0x2430: 0x1488, 0x2431: 0x148a, 0x2432: 0x148c, 0x2433: 0x148e, 0x2434: 0x1490, 0x2435: 0x1492, - 0x2436: 0x1486, 0x2437: 0x001c, 0x2438: 0x000d, 0x2439: 0x000f, 0x243a: 0x1488, 0x243b: 0x148a, - 0x243c: 0x148c, 0x243d: 0x148e, 0x243e: 0x1490, 0x243f: 0x1492, - // Block 0x91, offset 0x2440 - 0x2440: 0x3b95, 0x2441: 0x3b98, 0x2442: 0x3b9b, 0x2443: 0x3b9e, 0x2444: 0x3ba1, 0x2445: 0x3ba4, - 0x2446: 0x3ba7, 0x2447: 0x3baa, 0x2448: 0x3bad, 0x2449: 0x3bb0, 0x244a: 0x3bb3, - 0x2450: 0x3bb6, 0x2451: 0x3bba, - 0x2452: 0x3bbe, 0x2453: 0x3bc2, 0x2454: 0x3bc6, 0x2455: 0x3bca, 0x2456: 0x3bce, 0x2457: 0x3bd2, - 0x2458: 0x3bd6, 0x2459: 0x3bda, 0x245a: 0x3bde, 0x245b: 0x3be2, 0x245c: 0x3be6, 0x245d: 0x3bea, - 0x245e: 0x3bee, 0x245f: 0x3bf2, 0x2460: 0x3bf6, 0x2461: 0x3bfa, 0x2462: 0x3bfe, 0x2463: 0x3c02, - 0x2464: 0x3c06, 0x2465: 0x3c0a, 0x2466: 0x3c0e, 0x2467: 0x3c12, 0x2468: 0x3c16, 0x2469: 0x3c1a, - 0x246a: 0x3c1e, 0x246b: 0x14ad, 0x246c: 0x092b, 0x246d: 0x3c26, 0x246e: 0x3c29, - 0x2470: 0x0906, 0x2471: 0x090b, 0x2472: 0x14ad, 0x2473: 0x090d, 0x2474: 0x090f, 0x2475: 0x14d9, - 0x2476: 0x0914, 0x2477: 0x0916, 0x2478: 0x0918, 0x2479: 0x091a, 0x247a: 0x091c, 0x247b: 0x091e, - 0x247c: 0x0920, 0x247d: 0x0922, 0x247e: 0x0924, 0x247f: 0x0929, - // Block 0x92, offset 0x2480 - 0x2480: 0x14c8, 0x2481: 0x092b, 0x2482: 0x17f6, 0x2483: 0x092d, 0x2484: 0x092f, 0x2485: 0x155f, - 0x2486: 0x0931, 0x2487: 0x1570, 0x2488: 0x17f8, 0x2489: 0x14d4, 0x248a: 0x3c2c, 0x248b: 0x293d, - 0x248c: 0x3c2f, 0x248d: 0x3c32, 0x248e: 0x3c35, 0x248f: 0x3c39, - // Block 0x93, offset 0x24c0 - 0x24d0: 0x3c3c, - // Block 0x94, offset 0x2500 - 0x2500: 0x3c3f, 0x2501: 0x3c46, 0x2502: 0x2291, - 0x2510: 0x1922, 0x2511: 0x3c4d, - 0x2512: 0x3c51, 0x2513: 0x1cb3, 0x2514: 0x183e, 0x2515: 0x3c55, 0x2516: 0x3c59, 0x2517: 0x1ed0, - 0x2518: 0x3c5d, 0x2519: 0x3c61, 0x251a: 0x3c65, 0x251b: 0x2d49, 0x251c: 0x3c69, 0x251d: 0x3c6d, - 0x251e: 0x3c71, 0x251f: 0x3c75, 0x2520: 0x3c79, 0x2521: 0x3c7d, 0x2522: 0x19b2, 0x2523: 0x3c81, - 0x2524: 0x3c85, 0x2525: 0x3c89, 0x2526: 0x3c8d, 0x2527: 0x3c91, 0x2528: 0x3c95, 0x2529: 0x1826, - 0x252a: 0x1eb0, 0x252b: 0x3c99, 0x252c: 0x21c7, 0x252d: 0x1ebc, 0x252e: 0x21cb, 0x252f: 0x3c9d, - 0x2530: 0x1a92, 0x2531: 0x3ca1, 0x2532: 0x3ca5, 0x2533: 0x3ca9, 0x2534: 0x3cad, 0x2535: 0x3cb1, - 0x2536: 0x2183, 0x2537: 0x194a, 0x2538: 0x3cb5, 0x2539: 0x3cb9, 0x253a: 0x3cbd, - // Block 0x95, offset 0x2540 - 0x2540: 0x3cc1, 0x2541: 0x3ccb, 0x2542: 0x3cd5, 0x2543: 0x3cdf, 0x2544: 0x3ce9, 0x2545: 0x3cf3, - 0x2546: 0x3cfd, 0x2547: 0x3d07, 0x2548: 0x3d11, - 0x2550: 0x3d1b, 0x2551: 0x3d1f, - // Block 0x96, offset 0x2580 - 0x2580: 0x3d23, 0x2581: 0x3d27, 0x2582: 0x3d2b, 0x2583: 0x3d2f, 0x2584: 0x3d34, 0x2585: 0x2eb5, - 0x2586: 0x3d38, 0x2587: 0x3d3c, 0x2588: 0x3d40, 0x2589: 0x3d44, 0x258a: 0x2eb9, 0x258b: 0x3d48, - 0x258c: 0x3d4c, 0x258d: 0x3d50, 0x258e: 0x2ebd, 0x258f: 0x3d55, 0x2590: 0x3d59, 0x2591: 0x3d5d, - 0x2592: 0x3d61, 0x2593: 0x3d66, 0x2594: 0x3d6a, 0x2595: 0x3c71, 0x2596: 0x3d6e, 0x2597: 0x3d73, - 0x2598: 0x3d77, 0x2599: 0x3d7b, 0x259a: 0x3d7f, 0x259b: 0x2f9a, 0x259c: 0x3d83, 0x259d: 0x1866, - 0x259e: 0x3d88, 0x259f: 0x3d8c, 0x25a0: 0x3d90, 0x25a1: 0x3d94, 0x25a2: 0x3cb9, 0x25a3: 0x3d98, - 0x25a4: 0x3d9c, 0x25a5: 0x2fae, 0x25a6: 0x2ec1, 0x25a7: 0x2ec5, 0x25a8: 0x2fb2, 0x25a9: 0x3da0, - 0x25aa: 0x3da4, 0x25ab: 0x2bf1, 0x25ac: 0x3da8, 0x25ad: 0x2ec9, 0x25ae: 0x3dac, 0x25af: 0x3db0, - 0x25b0: 0x3db4, 0x25b1: 0x3db8, 0x25b2: 0x3db8, 0x25b3: 0x3db8, 0x25b4: 0x3dbc, 0x25b5: 0x3dc1, - 0x25b6: 0x3dc5, 0x25b7: 0x3dc9, 0x25b8: 0x3dcd, 0x25b9: 0x3dd2, 0x25ba: 0x3dd6, 0x25bb: 0x3dda, - 0x25bc: 0x3dde, 0x25bd: 0x3de2, 0x25be: 0x3de6, 0x25bf: 0x3dea, - // Block 0x97, offset 0x25c0 - 0x25c0: 0x3dee, 0x25c1: 0x3df2, 0x25c2: 0x3df6, 0x25c3: 0x3dfa, 0x25c4: 0x3dfe, 0x25c5: 0x3e02, - 0x25c6: 0x3e02, 0x25c7: 0x2fba, 0x25c8: 0x3e06, 0x25c9: 0x3e0a, 0x25ca: 0x3e0e, 0x25cb: 0x3e12, - 0x25cc: 0x2ed1, 0x25cd: 0x3e16, 0x25ce: 0x3e1a, 0x25cf: 0x3e1e, 0x25d0: 0x2e39, 0x25d1: 0x3e22, - 0x25d2: 0x3e26, 0x25d3: 0x3e2a, 0x25d4: 0x3e2e, 0x25d5: 0x3e32, 0x25d6: 0x3e36, 0x25d7: 0x3e3a, - 0x25d8: 0x3e3e, 0x25d9: 0x3e42, 0x25da: 0x3e47, 0x25db: 0x3e4b, 0x25dc: 0x3e4f, 0x25dd: 0x3c55, - 0x25de: 0x3e53, 0x25df: 0x3e57, 0x25e0: 0x3e5b, 0x25e1: 0x3e60, 0x25e2: 0x3e65, 0x25e3: 0x3e69, - 0x25e4: 0x3e6d, 0x25e5: 0x3e71, 0x25e6: 0x3e75, 0x25e7: 0x3e79, 0x25e8: 0x3e7d, 0x25e9: 0x3e81, - 0x25ea: 0x3e85, 0x25eb: 0x3e85, 0x25ec: 0x3e89, 0x25ed: 0x3e8e, 0x25ee: 0x3e92, 0x25ef: 0x2be1, - 0x25f0: 0x3e96, 0x25f1: 0x3e9a, 0x25f2: 0x3e9f, 0x25f3: 0x3ea3, 0x25f4: 0x3ea7, 0x25f5: 0x18ce, - 0x25f6: 0x3eab, 0x25f7: 0x3eaf, 0x25f8: 0x18d6, 0x25f9: 0x3eb3, 0x25fa: 0x3eb7, 0x25fb: 0x3ebb, - 0x25fc: 0x3ec0, 0x25fd: 0x3ec4, 0x25fe: 0x3ec9, 0x25ff: 0x3ecd, - // Block 0x98, offset 0x2600 - 0x2600: 0x3ed1, 0x2601: 0x3ed5, 0x2602: 0x3ed9, 0x2603: 0x3edd, 0x2604: 0x3ee1, 0x2605: 0x3ee5, - 0x2606: 0x3ee9, 0x2607: 0x3eed, 0x2608: 0x3ef1, 0x2609: 0x3ef5, 0x260a: 0x3efa, 0x260b: 0x3efe, - 0x260c: 0x3f02, 0x260d: 0x3f06, 0x260e: 0x2b11, 0x260f: 0x3f0a, 0x2610: 0x18fe, 0x2611: 0x3f0f, - 0x2612: 0x3f0f, 0x2613: 0x3f14, 0x2614: 0x3f18, 0x2615: 0x3f18, 0x2616: 0x3f1c, 0x2617: 0x3f20, - 0x2618: 0x3f25, 0x2619: 0x3f2a, 0x261a: 0x3f2e, 0x261b: 0x3f32, 0x261c: 0x3f36, 0x261d: 0x3f3a, - 0x261e: 0x3f3e, 0x261f: 0x3f42, 0x2620: 0x3f46, 0x2621: 0x3f4a, 0x2622: 0x3f4e, 0x2623: 0x2ee5, - 0x2624: 0x3f52, 0x2625: 0x3f57, 0x2626: 0x3f5b, 0x2627: 0x3f5f, 0x2628: 0x2fea, 0x2629: 0x3f5f, - 0x262a: 0x3f63, 0x262b: 0x2eed, 0x262c: 0x3f67, 0x262d: 0x3f6b, 0x262e: 0x3f6f, 0x262f: 0x3f73, - 0x2630: 0x2ef1, 0x2631: 0x2aa5, 0x2632: 0x3f77, 0x2633: 0x3f7b, 0x2634: 0x3f7f, 0x2635: 0x3f83, - 0x2636: 0x3f87, 0x2637: 0x3f8b, 0x2638: 0x3f8f, 0x2639: 0x3f94, 0x263a: 0x3f98, 0x263b: 0x3f9c, - 0x263c: 0x3fa0, 0x263d: 0x3fa4, 0x263e: 0x3fa8, 0x263f: 0x3fad, - // Block 0x99, offset 0x2640 - 0x2640: 0x3fb1, 0x2641: 0x3fb5, 0x2642: 0x3fb9, 0x2643: 0x3fbd, 0x2644: 0x3fc1, 0x2645: 0x3fc5, - 0x2646: 0x3fc9, 0x2647: 0x3fcd, 0x2648: 0x2ef5, 0x2649: 0x3fd1, 0x264a: 0x3fd5, 0x264b: 0x3fda, - 0x264c: 0x3fde, 0x264d: 0x3fe2, 0x264e: 0x3fe6, 0x264f: 0x2efd, 0x2650: 0x3fea, 0x2651: 0x3fee, - 0x2652: 0x3ff2, 0x2653: 0x3ff6, 0x2654: 0x3ffa, 0x2655: 0x3ffe, 0x2656: 0x4002, 0x2657: 0x4006, - 0x2658: 0x2b15, 0x2659: 0x300a, 0x265a: 0x400a, 0x265b: 0x400e, 0x265c: 0x4012, 0x265d: 0x4016, - 0x265e: 0x401b, 0x265f: 0x401f, 0x2660: 0x4023, 0x2661: 0x4027, 0x2662: 0x2f01, 0x2663: 0x402b, - 0x2664: 0x4030, 0x2665: 0x4034, 0x2666: 0x4038, 0x2667: 0x30b5, 0x2668: 0x403c, 0x2669: 0x4040, - 0x266a: 0x4044, 0x266b: 0x4048, 0x266c: 0x404c, 0x266d: 0x4051, 0x266e: 0x4055, 0x266f: 0x4059, - 0x2670: 0x405d, 0x2671: 0x4062, 0x2672: 0x4066, 0x2673: 0x406a, 0x2674: 0x406e, 0x2675: 0x2c25, - 0x2676: 0x4072, 0x2677: 0x4076, 0x2678: 0x407b, 0x2679: 0x4080, 0x267a: 0x4085, 0x267b: 0x4089, - 0x267c: 0x408e, 0x267d: 0x4092, 0x267e: 0x4096, 0x267f: 0x409a, - // Block 0x9a, offset 0x2680 - 0x2680: 0x409e, 0x2681: 0x2f05, 0x2682: 0x2d71, 0x2683: 0x40a2, 0x2684: 0x40a6, 0x2685: 0x40aa, - 0x2686: 0x40ae, 0x2687: 0x40b3, 0x2688: 0x40b7, 0x2689: 0x40bb, 0x268a: 0x40bf, 0x268b: 0x3016, - 0x268c: 0x40c3, 0x268d: 0x40c7, 0x268e: 0x40cc, 0x268f: 0x40d0, 0x2690: 0x40d4, 0x2691: 0x40d9, - 0x2692: 0x40de, 0x2693: 0x40e2, 0x2694: 0x301a, 0x2695: 0x40e6, 0x2696: 0x40ea, 0x2697: 0x40ee, - 0x2698: 0x40f2, 0x2699: 0x40f6, 0x269a: 0x40fa, 0x269b: 0x40fe, 0x269c: 0x4103, 0x269d: 0x4107, - 0x269e: 0x410c, 0x269f: 0x4110, 0x26a0: 0x4115, 0x26a1: 0x3022, 0x26a2: 0x4119, 0x26a3: 0x411d, - 0x26a4: 0x4122, 0x26a5: 0x4126, 0x26a6: 0x412a, 0x26a7: 0x412f, 0x26a8: 0x4134, 0x26a9: 0x4138, - 0x26aa: 0x413c, 0x26ab: 0x4140, 0x26ac: 0x4144, 0x26ad: 0x4144, 0x26ae: 0x4148, 0x26af: 0x414c, - 0x26b0: 0x302a, 0x26b1: 0x4150, 0x26b2: 0x4154, 0x26b3: 0x4158, 0x26b4: 0x415c, 0x26b5: 0x4160, - 0x26b6: 0x4165, 0x26b7: 0x4169, 0x26b8: 0x2bed, 0x26b9: 0x416e, 0x26ba: 0x4173, 0x26bb: 0x4177, - 0x26bc: 0x417c, 0x26bd: 0x4181, 0x26be: 0x4186, 0x26bf: 0x418a, - // Block 0x9b, offset 0x26c0 - 0x26c0: 0x3042, 0x26c1: 0x418e, 0x26c2: 0x4193, 0x26c3: 0x4198, 0x26c4: 0x419d, 0x26c5: 0x41a2, - 0x26c6: 0x41a6, 0x26c7: 0x41a6, 0x26c8: 0x3046, 0x26c9: 0x30bd, 0x26ca: 0x41aa, 0x26cb: 0x41ae, - 0x26cc: 0x41b2, 0x26cd: 0x41b6, 0x26ce: 0x41bb, 0x26cf: 0x2b59, 0x26d0: 0x304e, 0x26d1: 0x41bf, - 0x26d2: 0x41c3, 0x26d3: 0x2f2d, 0x26d4: 0x41c8, 0x26d5: 0x41cd, 0x26d6: 0x2e89, 0x26d7: 0x41d2, - 0x26d8: 0x41d6, 0x26d9: 0x2f39, 0x26da: 0x41da, 0x26db: 0x41de, 0x26dc: 0x41e2, 0x26dd: 0x41e7, - 0x26de: 0x41e7, 0x26df: 0x41ec, 0x26e0: 0x41f0, 0x26e1: 0x41f4, 0x26e2: 0x41f9, 0x26e3: 0x41fd, - 0x26e4: 0x4201, 0x26e5: 0x4205, 0x26e6: 0x420a, 0x26e7: 0x420e, 0x26e8: 0x4212, 0x26e9: 0x4216, - 0x26ea: 0x421a, 0x26eb: 0x421e, 0x26ec: 0x4223, 0x26ed: 0x4227, 0x26ee: 0x422b, 0x26ef: 0x422f, - 0x26f0: 0x4233, 0x26f1: 0x4237, 0x26f2: 0x423b, 0x26f3: 0x4240, 0x26f4: 0x4245, 0x26f5: 0x4249, - 0x26f6: 0x424e, 0x26f7: 0x4252, 0x26f8: 0x4257, 0x26f9: 0x425b, 0x26fa: 0x2f51, 0x26fb: 0x425f, - 0x26fc: 0x4264, 0x26fd: 0x4269, 0x26fe: 0x426d, 0x26ff: 0x4272, - // Block 0x9c, offset 0x2700 - 0x2700: 0x4276, 0x2701: 0x427b, 0x2702: 0x427f, 0x2703: 0x4283, 0x2704: 0x4287, 0x2705: 0x428b, - 0x2706: 0x428f, 0x2707: 0x4293, 0x2708: 0x4298, 0x2709: 0x429d, 0x270a: 0x42a2, 0x270b: 0x3f14, - 0x270c: 0x42a7, 0x270d: 0x42ab, 0x270e: 0x42af, 0x270f: 0x42b3, 0x2710: 0x42b7, 0x2711: 0x42bb, - 0x2712: 0x42bf, 0x2713: 0x42c3, 0x2714: 0x42c7, 0x2715: 0x42cb, 0x2716: 0x42cf, 0x2717: 0x42d3, - 0x2718: 0x2c31, 0x2719: 0x42d8, 0x271a: 0x42dc, 0x271b: 0x42e0, 0x271c: 0x42e4, 0x271d: 0x42e8, - 0x271e: 0x42ec, 0x271f: 0x2f5d, 0x2720: 0x42f0, 0x2721: 0x42f4, 0x2722: 0x42f8, 0x2723: 0x42fc, - 0x2724: 0x4300, 0x2725: 0x4305, 0x2726: 0x430a, 0x2727: 0x430f, 0x2728: 0x4313, 0x2729: 0x4317, - 0x272a: 0x431b, 0x272b: 0x431f, 0x272c: 0x4324, 0x272d: 0x4328, 0x272e: 0x432d, 0x272f: 0x4331, - 0x2730: 0x4335, 0x2731: 0x433a, 0x2732: 0x433f, 0x2733: 0x4343, 0x2734: 0x2b45, 0x2735: 0x4347, - 0x2736: 0x434b, 0x2737: 0x434f, 0x2738: 0x4353, 0x2739: 0x4357, 0x273a: 0x435b, 0x273b: 0x306a, - 0x273c: 0x435f, 0x273d: 0x4363, 0x273e: 0x4367, 0x273f: 0x436b, - // Block 0x9d, offset 0x2740 - 0x2740: 0x436f, 0x2741: 0x4373, 0x2742: 0x4377, 0x2743: 0x437b, 0x2744: 0x1a66, 0x2745: 0x437f, - 0x2746: 0x4384, 0x2747: 0x4388, 0x2748: 0x438c, 0x2749: 0x4390, 0x274a: 0x4394, 0x274b: 0x4398, - 0x274c: 0x439d, 0x274d: 0x43a2, 0x274e: 0x43a6, 0x274f: 0x43aa, 0x2750: 0x307e, 0x2751: 0x3082, - 0x2752: 0x1a82, 0x2753: 0x43ae, 0x2754: 0x43b3, 0x2755: 0x43b7, 0x2756: 0x43bb, 0x2757: 0x43bf, - 0x2758: 0x43c3, 0x2759: 0x43c8, 0x275a: 0x43cd, 0x275b: 0x43d1, 0x275c: 0x43d5, 0x275d: 0x43d9, - 0x275e: 0x43de, 0x275f: 0x3086, 0x2760: 0x43e2, 0x2761: 0x43e7, 0x2762: 0x43ec, 0x2763: 0x43f0, - 0x2764: 0x43f4, 0x2765: 0x43f8, 0x2766: 0x43fd, 0x2767: 0x4401, 0x2768: 0x4405, 0x2769: 0x4409, - 0x276a: 0x440d, 0x276b: 0x4411, 0x276c: 0x4415, 0x276d: 0x4419, 0x276e: 0x441e, 0x276f: 0x4422, - 0x2770: 0x4426, 0x2771: 0x442a, 0x2772: 0x442f, 0x2773: 0x4433, 0x2774: 0x4437, 0x2775: 0x443b, - 0x2776: 0x443f, 0x2777: 0x4444, 0x2778: 0x4449, 0x2779: 0x444d, 0x277a: 0x4451, 0x277b: 0x4455, - 0x277c: 0x445a, 0x277d: 0x445e, 0x277e: 0x309e, 0x277f: 0x309e, - // Block 0x9e, offset 0x2780 - 0x2780: 0x4463, 0x2781: 0x4467, 0x2782: 0x446c, 0x2783: 0x4470, 0x2784: 0x4474, 0x2785: 0x4478, - 0x2786: 0x447c, 0x2787: 0x4480, 0x2788: 0x4484, 0x2789: 0x4488, 0x278a: 0x30a2, 0x278b: 0x448d, - 0x278c: 0x4491, 0x278d: 0x4495, 0x278e: 0x4499, 0x278f: 0x449d, 0x2790: 0x44a1, 0x2791: 0x44a6, - 0x2792: 0x44aa, 0x2793: 0x44af, 0x2794: 0x44b4, 0x2795: 0x1b42, 0x2796: 0x44b9, 0x2797: 0x1b52, - 0x2798: 0x44bd, 0x2799: 0x44c1, 0x279a: 0x44c5, 0x279b: 0x44c9, 0x279c: 0x1b66, 0x279d: 0x44cd, + 0x1040: 0x436f, 0x1041: 0x4373, 0x1042: 0x4377, 0x1043: 0x437b, 0x1044: 0x1a66, 0x1045: 0x437f, + 0x1046: 0x4384, 0x1047: 0x4388, 0x1048: 0x438c, 0x1049: 0x4390, 0x104a: 0x4394, 0x104b: 0x4398, + 0x104c: 0x439d, 0x104d: 0x43a2, 0x104e: 0x43a6, 0x104f: 0x43aa, 0x1050: 0x307e, 0x1051: 0x3082, + 0x1052: 0x1a82, 0x1053: 0x43ae, 0x1054: 0x43b3, 0x1055: 0x43b7, 0x1056: 0x43bb, 0x1057: 0x43bf, + 0x1058: 0x43c3, 0x1059: 0x43c8, 0x105a: 0x43cd, 0x105b: 0x43d1, 0x105c: 0x43d5, 0x105d: 0x43d9, + 0x105e: 0x43de, 0x105f: 0x3086, 0x1060: 0x43e2, 0x1061: 0x43e7, 0x1062: 0x43ec, 0x1063: 0x43f0, + 0x1064: 0x43f4, 0x1065: 0x43f8, 0x1066: 0x43fd, 0x1067: 0x4401, 0x1068: 0x4405, 0x1069: 0x4409, + 0x106a: 0x440d, 0x106b: 0x4411, 0x106c: 0x4415, 0x106d: 0x4419, 0x106e: 0x441e, 0x106f: 0x4422, + 0x1070: 0x4426, 0x1071: 0x442a, 0x1072: 0x442f, 0x1073: 0x4433, 0x1074: 0x4437, 0x1075: 0x443b, + 0x1076: 0x443f, 0x1077: 0x4444, 0x1078: 0x4449, 0x1079: 0x444d, 0x107a: 0x4451, 0x107b: 0x4455, + 0x107c: 0x445a, 0x107d: 0x445e, 0x107e: 0x309e, 0x107f: 0x309e, +} + +// nfkcDecompSparseOffset: 93 entries, 186 bytes +var nfkcDecompSparseOffset = []uint16{0x0, 0xc, 0x16, 0x1e, 0x24, 0x27, 0x31, 0x37, 0x3e, 0x44, 0x4c, 0x59, 0x60, 0x66, 0x6e, 0x70, 0x72, 0x74, 0x78, 0x7c, 0x7e, 0x82, 0x85, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x96, 0x98, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xae, 0xb6, 0xb8, 0xba, 0xc3, 0xc6, 0xcd, 0xd8, 0xe6, 0xf4, 0xfe, 0x102, 0x104, 0x10e, 0x11a, 0x11f, 0x122, 0x124, 0x126, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x133, 0x135, 0x137, 0x139, 0x13b, 0x140, 0x14f, 0x15d, 0x15f, 0x161, 0x169, 0x179, 0x17b, 0x186, 0x18d, 0x198, 0x1a4, 0x1b5, 0x1c6, 0x1cd, 0x1de, 0x1ec, 0x1fa, 0x209, 0x21a, 0x21f, 0x22c, 0x230, 0x234, 0x238, 0x23a, 0x249, 0x24b, 0x24f} + +// nfkcDecompSparseValues: 605 entries, 2420 bytes +var nfkcDecompSparseValues = [605]valueRange{ + // Block 0x0, offset 0x1 + {value: 0x0002, lo: 0x0b}, + {value: 0x0001, lo: 0xa0, hi: 0xa0}, + {value: 0x0003, lo: 0xa8, hi: 0xa8}, + {value: 0x0007, lo: 0xaa, hi: 0xaa}, + {value: 0x0009, lo: 0xaf, hi: 0xaf}, + {value: 0x000d, lo: 0xb2, hi: 0xb4}, + {value: 0x0015, lo: 0xb5, hi: 0xb5}, + {value: 0x0018, lo: 0xb8, hi: 0xb8}, + {value: 0x001c, lo: 0xb9, hi: 0xba}, + {value: 0x0020, lo: 0xbc, hi: 0xbc}, + {value: 0x0026, lo: 0xbd, hi: 0xbd}, + {value: 0x002c, lo: 0xbe, hi: 0xbe}, + // Block 0x1, offset 0x2 + {value: 0x0004, lo: 0x09}, + {value: 0x0032, lo: 0x80, hi: 0x85}, + {value: 0x004a, lo: 0x87, hi: 0x8f}, + {value: 0x006e, lo: 0x91, hi: 0x96}, + {value: 0x0086, lo: 0x99, hi: 0x9d}, + {value: 0x009a, lo: 0xa0, hi: 0xa5}, + {value: 0x00b2, lo: 0xa7, hi: 0xaf}, + {value: 0x00d6, lo: 0xb1, hi: 0xb6}, + {value: 0x00ee, lo: 0xb9, hi: 0xbd}, + {value: 0x0102, lo: 0xbf, hi: 0xbf}, + // Block 0x2, offset 0x3 + {value: 0x0004, lo: 0x07}, + {value: 0x0106, lo: 0x80, hi: 0x8f}, + {value: 0x0146, lo: 0x92, hi: 0xa5}, + {value: 0x0196, lo: 0xa8, hi: 0xb0}, + {value: 0x01ba, lo: 0xb2, hi: 0xb2}, + {value: 0x01bd, lo: 0xb3, hi: 0xb3}, + {value: 0x01c0, lo: 0xb4, hi: 0xb7}, + {value: 0x01d0, lo: 0xb9, hi: 0xbf}, + // Block 0x3, offset 0x4 + {value: 0x0004, lo: 0x05}, + {value: 0x01ec, lo: 0x80, hi: 0x80}, + {value: 0x01f0, lo: 0x83, hi: 0x89}, + {value: 0x020c, lo: 0x8c, hi: 0x91}, + {value: 0x0224, lo: 0x94, hi: 0xa5}, + {value: 0x026c, lo: 0xa8, hi: 0xbf}, + // Block 0x4, offset 0x5 + {value: 0x0004, lo: 0x02}, + {value: 0x02ca, lo: 0xa0, hi: 0xa1}, + {value: 0x02d2, lo: 0xaf, hi: 0xb0}, + // Block 0x5, offset 0x6 + {value: 0x0004, lo: 0x09}, + {value: 0x03d8, lo: 0x80, hi: 0x9b}, + {value: 0x0448, lo: 0x9e, hi: 0x9f}, + {value: 0x0450, lo: 0xa6, hi: 0xaa}, + {value: 0x0466, lo: 0xab, hi: 0xab}, + {value: 0x046c, lo: 0xac, hi: 0xac}, + {value: 0x0472, lo: 0xad, hi: 0xad}, + {value: 0x0478, lo: 0xae, hi: 0xb0}, + {value: 0x0486, lo: 0xb1, hi: 0xb1}, + {value: 0x048c, lo: 0xb2, hi: 0xb3}, + // Block 0x6, offset 0x7 + {value: 0x0002, lo: 0x05}, + {value: 0x0494, lo: 0xb0, hi: 0xb1}, + {value: 0x0499, lo: 0xb2, hi: 0xb4}, + {value: 0x04a0, lo: 0xb5, hi: 0xb5}, + {value: 0x04a3, lo: 0xb6, hi: 0xb6}, + {value: 0x04a6, lo: 0xb7, hi: 0xb8}, + // Block 0x7, offset 0x8 + {value: 0x0004, lo: 0x06}, + {value: 0x04aa, lo: 0x98, hi: 0x9d}, + {value: 0x04c2, lo: 0xa0, hi: 0xa0}, + {value: 0x04c5, lo: 0xa1, hi: 0xa1}, + {value: 0x02c8, lo: 0xa2, hi: 0xa2}, + {value: 0x04c7, lo: 0xa3, hi: 0xa3}, + {value: 0x04c9, lo: 0xa4, hi: 0xa4}, + // Block 0x8, offset 0x9 + {value: 0x0003, lo: 0x05}, + {value: 0x04cc, lo: 0x80, hi: 0x81}, + {value: 0x04d2, lo: 0x83, hi: 0x84}, + {value: 0x04da, lo: 0xb4, hi: 0xb4}, + {value: 0x04dd, lo: 0xba, hi: 0xba}, + {value: 0x04e1, lo: 0xbe, hi: 0xbe}, + // Block 0x9, offset 0xa + {value: 0x0005, lo: 0x07}, + {value: 0x0011, lo: 0x84, hi: 0x84}, + {value: 0x04e8, lo: 0x85, hi: 0x85}, + {value: 0x04ee, lo: 0x86, hi: 0x87}, + {value: 0x04f6, lo: 0x88, hi: 0x8a}, + {value: 0x0505, lo: 0x8c, hi: 0x8c}, + {value: 0x050a, lo: 0x8e, hi: 0x90}, + {value: 0x051b, lo: 0xaa, hi: 0xb0}, + // Block 0xa, offset 0xb + {value: 0x0003, lo: 0x0c}, + {value: 0x0540, lo: 0x8a, hi: 0x8a}, + {value: 0x0545, lo: 0x8b, hi: 0x8b}, + {value: 0x054a, lo: 0x8c, hi: 0x8c}, + {value: 0x054f, lo: 0x8d, hi: 0x8d}, + {value: 0x0554, lo: 0x8e, hi: 0x8e}, + {value: 0x0559, lo: 0x90, hi: 0x92}, + {value: 0x050a, lo: 0x93, hi: 0x93}, + {value: 0x0520, lo: 0x94, hi: 0x94}, + {value: 0x056c, lo: 0x95, hi: 0x96}, + {value: 0x0572, lo: 0xb0, hi: 0xb2}, + {value: 0x057b, lo: 0xb4, hi: 0xb5}, + {value: 0x0581, lo: 0xb9, hi: 0xb9}, + // Block 0xb, offset 0xc + {value: 0x0005, lo: 0x06}, + {value: 0x0584, lo: 0x80, hi: 0x81}, + {value: 0x058e, lo: 0x83, hi: 0x83}, + {value: 0x0593, lo: 0x87, hi: 0x87}, + {value: 0x0598, lo: 0x8c, hi: 0x8e}, + {value: 0x05a7, lo: 0x99, hi: 0x99}, + {value: 0x05ac, lo: 0xb9, hi: 0xb9}, + // Block 0xc, offset 0xd + {value: 0x0005, lo: 0x05}, + {value: 0x05b1, lo: 0x90, hi: 0x91}, + {value: 0x05bb, lo: 0x93, hi: 0x93}, + {value: 0x05c0, lo: 0x97, hi: 0x97}, + {value: 0x05c5, lo: 0x9c, hi: 0x9e}, + {value: 0x05d4, lo: 0xb6, hi: 0xb7}, + // Block 0xd, offset 0xe + {value: 0x0005, lo: 0x07}, + {value: 0x05de, lo: 0x81, hi: 0x82}, + {value: 0x05e8, lo: 0x90, hi: 0x93}, + {value: 0x05fc, lo: 0x96, hi: 0x97}, + {value: 0x0606, lo: 0x9a, hi: 0x9f}, + {value: 0x0624, lo: 0xa2, hi: 0xa7}, + {value: 0x0642, lo: 0xaa, hi: 0xb5}, + {value: 0x067e, lo: 0xb8, hi: 0xb9}, + // Block 0xe, offset 0xf + {value: 0x0000, lo: 0x01}, + {value: 0x0688, lo: 0x87, hi: 0x87}, + // Block 0xf, offset 0x10 + {value: 0x0005, lo: 0x01}, + {value: 0x068d, lo: 0xa2, hi: 0xa6}, + // Block 0x10, offset 0x11 + {value: 0x0005, lo: 0x01}, + {value: 0x06a6, lo: 0xb5, hi: 0xb8}, + // Block 0x11, offset 0x12 + {value: 0x0005, lo: 0x03}, + {value: 0x06ba, lo: 0x80, hi: 0x80}, + {value: 0x06bf, lo: 0x82, hi: 0x82}, + {value: 0x06c4, lo: 0x93, hi: 0x93}, + // Block 0x12, offset 0x13 + {value: 0x0007, lo: 0x03}, + {value: 0x06c9, lo: 0xa9, hi: 0xa9}, + {value: 0x06d0, lo: 0xb1, hi: 0xb1}, + {value: 0x06d7, lo: 0xb4, hi: 0xb4}, + // Block 0x13, offset 0x14 + {value: 0x0007, lo: 0x01}, + {value: 0x06de, lo: 0x98, hi: 0x9f}, + // Block 0x14, offset 0x15 + {value: 0x0007, lo: 0x03}, + {value: 0x0716, lo: 0x8b, hi: 0x8c}, + {value: 0x0724, lo: 0x9c, hi: 0x9d}, + {value: 0x0732, lo: 0x9f, hi: 0x9f}, + // Block 0x15, offset 0x16 + {value: 0x0007, lo: 0x02}, + {value: 0x0739, lo: 0xb3, hi: 0xb3}, + {value: 0x0740, lo: 0xb6, hi: 0xb6}, + // Block 0x16, offset 0x17 + {value: 0x0007, lo: 0x02}, + {value: 0x0747, lo: 0x99, hi: 0x9b}, + {value: 0x075c, lo: 0x9e, hi: 0x9e}, + // Block 0x17, offset 0x18 + {value: 0x0007, lo: 0x03}, + {value: 0x0763, lo: 0x88, hi: 0x88}, + {value: 0x076a, lo: 0x8b, hi: 0x8c}, + {value: 0x0778, lo: 0x9c, hi: 0x9d}, + // Block 0x18, offset 0x19 + {value: 0x0000, lo: 0x01}, + {value: 0x0786, lo: 0x94, hi: 0x94}, + // Block 0x19, offset 0x1a + {value: 0x0007, lo: 0x01}, + {value: 0x078d, lo: 0x8a, hi: 0x8c}, + // Block 0x1a, offset 0x1b + {value: 0x0000, lo: 0x01}, + {value: 0x07a2, lo: 0x88, hi: 0x88}, + // Block 0x1b, offset 0x1c + {value: 0x0007, lo: 0x03}, + {value: 0x07a9, lo: 0x80, hi: 0x80}, + {value: 0x07b0, lo: 0x87, hi: 0x88}, + {value: 0x07be, lo: 0x8a, hi: 0x8b}, + // Block 0x1c, offset 0x1d + {value: 0x0007, lo: 0x01}, + {value: 0x07cf, lo: 0x8a, hi: 0x8c}, + // Block 0x1d, offset 0x1e + {value: 0x0007, lo: 0x03}, + {value: 0x07e4, lo: 0x9a, hi: 0x9a}, + {value: 0x07eb, lo: 0x9c, hi: 0x9d}, + {value: 0x07fc, lo: 0x9e, hi: 0x9e}, + // Block 0x1e, offset 0x1f + {value: 0x0000, lo: 0x01}, + {value: 0x0803, lo: 0xb3, hi: 0xb3}, + // Block 0x1f, offset 0x20 + {value: 0x0000, lo: 0x01}, + {value: 0x080a, lo: 0xb3, hi: 0xb3}, + // Block 0x20, offset 0x21 + {value: 0x0007, lo: 0x01}, + {value: 0x0811, lo: 0x9c, hi: 0x9d}, + // Block 0x21, offset 0x22 + {value: 0x0000, lo: 0x01}, + {value: 0x081f, lo: 0x8c, hi: 0x8c}, + // Block 0x22, offset 0x23 + {value: 0x0007, lo: 0x09}, + {value: 0x0823, lo: 0x83, hi: 0x83}, + {value: 0x082a, lo: 0x8d, hi: 0x8d}, + {value: 0x0831, lo: 0x92, hi: 0x92}, + {value: 0x0838, lo: 0x97, hi: 0x97}, + {value: 0x083f, lo: 0x9c, hi: 0x9c}, + {value: 0x0846, lo: 0xa9, hi: 0xa9}, + {value: 0x084d, lo: 0xb3, hi: 0xb3}, + {value: 0x0854, lo: 0xb5, hi: 0xb7}, + {value: 0x086c, lo: 0xb8, hi: 0xb9}, + // Block 0x23, offset 0x24 + {value: 0x0007, lo: 0x07}, + {value: 0x087d, lo: 0x81, hi: 0x81}, + {value: 0x0884, lo: 0x93, hi: 0x93}, + {value: 0x088b, lo: 0x9d, hi: 0x9d}, + {value: 0x0892, lo: 0xa2, hi: 0xa2}, + {value: 0x0899, lo: 0xa7, hi: 0xa7}, + {value: 0x08a0, lo: 0xac, hi: 0xac}, + {value: 0x08a7, lo: 0xb9, hi: 0xb9}, + // Block 0x24, offset 0x25 + {value: 0x0000, lo: 0x01}, + {value: 0x08ae, lo: 0xa6, hi: 0xa6}, + // Block 0x25, offset 0x26 + {value: 0x0000, lo: 0x01}, + {value: 0x08b5, lo: 0xbc, hi: 0xbc}, + // Block 0x26, offset 0x27 + {value: 0x0007, lo: 0x08}, + {value: 0x08b9, lo: 0x86, hi: 0x86}, + {value: 0x08c0, lo: 0x88, hi: 0x88}, + {value: 0x08c7, lo: 0x8a, hi: 0x8a}, + {value: 0x08ce, lo: 0x8c, hi: 0x8c}, + {value: 0x08d5, lo: 0x8e, hi: 0x8e}, + {value: 0x08dc, lo: 0x92, hi: 0x92}, + {value: 0x08e3, lo: 0xbb, hi: 0xbb}, + {value: 0x08ea, lo: 0xbd, hi: 0xbd}, + // Block 0x27, offset 0x28 + {value: 0x0007, lo: 0x02}, + {value: 0x08f1, lo: 0x80, hi: 0x81}, + {value: 0x08ff, lo: 0x83, hi: 0x83}, + // Block 0x28, offset 0x29 + {value: 0x0002, lo: 0x06}, + {value: 0x0906, lo: 0xac, hi: 0xad}, + {value: 0x090b, lo: 0xae, hi: 0xae}, + {value: 0x090d, lo: 0xb0, hi: 0xb2}, + {value: 0x0914, lo: 0xb3, hi: 0xba}, + {value: 0x0924, lo: 0xbc, hi: 0xbd}, + {value: 0x0929, lo: 0xbe, hi: 0xbf}, + // Block 0x29, offset 0x2a + {value: 0x0003, lo: 0x0a}, + {value: 0x0981, lo: 0x9b, hi: 0x9c}, + {value: 0x0986, lo: 0x9d, hi: 0x9e}, + {value: 0x0949, lo: 0x9f, hi: 0x9f}, + {value: 0x098c, lo: 0xa0, hi: 0xa0}, + {value: 0x098e, lo: 0xa1, hi: 0xa7}, + {value: 0x09a4, lo: 0xa8, hi: 0xaa}, + {value: 0x09ae, lo: 0xab, hi: 0xb8}, + {value: 0x09d9, lo: 0xb9, hi: 0xbb}, + {value: 0x09e1, lo: 0xbc, hi: 0xbe}, + {value: 0x055c, lo: 0xbf, hi: 0xbf}, + // Block 0x2a, offset 0x2b + {value: 0x0004, lo: 0x0d}, + {value: 0x09ea, lo: 0x80, hi: 0x88}, + {value: 0x0a10, lo: 0x89, hi: 0x89}, + {value: 0x0a16, lo: 0x8a, hi: 0x94}, + {value: 0x0a44, lo: 0x95, hi: 0x95}, + {value: 0x0a4a, lo: 0x96, hi: 0x96}, + {value: 0x0a50, lo: 0x97, hi: 0x97}, + {value: 0x0a56, lo: 0x98, hi: 0x9c}, + {value: 0x0a6c, lo: 0x9d, hi: 0x9d}, + {value: 0x0a72, lo: 0x9e, hi: 0xae}, + {value: 0x0ab8, lo: 0xaf, hi: 0xaf}, + {value: 0x0abe, lo: 0xb0, hi: 0xb8}, + {value: 0x0ae4, lo: 0xb9, hi: 0xb9}, + {value: 0x0aea, lo: 0xba, hi: 0xbf}, + // Block 0x2b, offset 0x2c + {value: 0x0000, lo: 0x0d}, + {value: 0x0001, lo: 0x80, hi: 0x8a}, + {value: 0x1436, lo: 0x91, hi: 0x91}, + {value: 0x143a, lo: 0x97, hi: 0x97}, + {value: 0x143e, lo: 0xa4, hi: 0xa4}, + {value: 0x1440, lo: 0xa5, hi: 0xa5}, + {value: 0x1443, lo: 0xa6, hi: 0xa6}, + {value: 0x0001, lo: 0xaf, hi: 0xaf}, + {value: 0x1447, lo: 0xb3, hi: 0xb3}, + {value: 0x144e, lo: 0xb4, hi: 0xb4}, + {value: 0x1458, lo: 0xb6, hi: 0xb6}, + {value: 0x145f, lo: 0xb7, hi: 0xb7}, + {value: 0x1469, lo: 0xbc, hi: 0xbc}, + {value: 0x146c, lo: 0xbe, hi: 0xbe}, + // Block 0x2c, offset 0x2d + {value: 0x0002, lo: 0x09}, + {value: 0x1470, lo: 0x87, hi: 0x87}, + {value: 0x1473, lo: 0x88, hi: 0x88}, + {value: 0x1476, lo: 0x89, hi: 0x89}, + {value: 0x1479, lo: 0x97, hi: 0x97}, + {value: 0x0001, lo: 0x9f, hi: 0x9f}, + {value: 0x1486, lo: 0xb0, hi: 0xb0}, + {value: 0x097c, lo: 0xb1, hi: 0xb1}, + {value: 0x1488, lo: 0xb4, hi: 0xbb}, + {value: 0x149a, lo: 0xbc, hi: 0xbf}, + // Block 0x2d, offset 0x2e + {value: 0x0006, lo: 0x03}, + {value: 0x1599, lo: 0x89, hi: 0x89}, + {value: 0x159f, lo: 0x9a, hi: 0x9b}, + {value: 0x15ab, lo: 0xae, hi: 0xae}, + // Block 0x2e, offset 0x2f + {value: 0x0006, lo: 0x01}, + {value: 0x15b1, lo: 0x8d, hi: 0x8f}, + // Block 0x2f, offset 0x30 + {value: 0x0006, lo: 0x09}, + {value: 0x15c3, lo: 0x84, hi: 0x84}, + {value: 0x15c9, lo: 0x89, hi: 0x89}, + {value: 0x15cf, lo: 0x8c, hi: 0x8c}, + {value: 0x15d5, lo: 0xa4, hi: 0xa4}, + {value: 0x15db, lo: 0xa6, hi: 0xa6}, + {value: 0x15e1, lo: 0xac, hi: 0xac}, + {value: 0x15e8, lo: 0xad, hi: 0xad}, + {value: 0x15f2, lo: 0xaf, hi: 0xaf}, + {value: 0x15f9, lo: 0xb0, hi: 0xb0}, + // Block 0x30, offset 0x31 + {value: 0x0006, lo: 0x0b}, + {value: 0x1603, lo: 0x81, hi: 0x81}, + {value: 0x1609, lo: 0x84, hi: 0x84}, + {value: 0x160f, lo: 0x87, hi: 0x87}, + {value: 0x1615, lo: 0x89, hi: 0x89}, + {value: 0x161b, lo: 0xa0, hi: 0xa0}, + {value: 0x161f, lo: 0xa2, hi: 0xa2}, + {value: 0x1625, lo: 0xad, hi: 0xae}, + {value: 0x162f, lo: 0xaf, hi: 0xaf}, + {value: 0x1633, lo: 0xb0, hi: 0xb1}, + {value: 0x163f, lo: 0xb4, hi: 0xb5}, + {value: 0x164b, lo: 0xb8, hi: 0xb9}, + // Block 0x31, offset 0x32 + {value: 0x0006, lo: 0x04}, + {value: 0x1657, lo: 0x80, hi: 0x81}, + {value: 0x1663, lo: 0x84, hi: 0x85}, + {value: 0x166f, lo: 0x88, hi: 0x89}, + {value: 0x167b, lo: 0xac, hi: 0xaf}, + // Block 0x32, offset 0x33 + {value: 0x0006, lo: 0x02}, + {value: 0x1693, lo: 0xa0, hi: 0xa3}, + {value: 0x16ab, lo: 0xaa, hi: 0xad}, + // Block 0x33, offset 0x34 + {value: 0x0004, lo: 0x01}, + {value: 0x16c3, lo: 0xa9, hi: 0xaa}, + // Block 0x34, offset 0x35 + {value: 0x0000, lo: 0x01}, + {value: 0x17fc, lo: 0x8c, hi: 0x8c}, + // Block 0x35, offset 0x36 + {value: 0x0004, lo: 0x02}, + {value: 0x1809, lo: 0xb4, hi: 0xb5}, + {value: 0x1810, lo: 0xb6, hi: 0xb6}, + // Block 0x36, offset 0x37 + {value: 0x0000, lo: 0x01}, + {value: 0x1814, lo: 0x9c, hi: 0x9c}, + // Block 0x37, offset 0x38 + {value: 0x10c6, lo: 0x01}, + {value: 0x0499, lo: 0xbc, hi: 0xbd}, + // Block 0x38, offset 0x39 + {value: 0x0000, lo: 0x01}, + {value: 0x181a, lo: 0xaf, hi: 0xaf}, + // Block 0x39, offset 0x3a + {value: 0x0000, lo: 0x01}, + {value: 0x181e, lo: 0x9f, hi: 0x9f}, + // Block 0x3a, offset 0x3b + {value: 0x0000, lo: 0x01}, + {value: 0x1822, lo: 0xb3, hi: 0xb3}, + // Block 0x3b, offset 0x3c + {value: 0x0004, lo: 0x01}, + {value: 0x1826, lo: 0x80, hi: 0xbf}, + // Block 0x3c, offset 0x3d + {value: 0x0004, lo: 0x01}, + {value: 0x1926, lo: 0x80, hi: 0xbf}, + // Block 0x3d, offset 0x3e + {value: 0x0004, lo: 0x01}, + {value: 0x1a26, lo: 0x80, hi: 0xbf}, + // Block 0x3e, offset 0x3f + {value: 0x0004, lo: 0x01}, + {value: 0x1b26, lo: 0x80, hi: 0x95}, + // Block 0x3f, offset 0x40 + {value: 0x0300, lo: 0x04}, + {value: 0x0001, lo: 0x80, hi: 0x80}, + {value: 0x1b7e, lo: 0xb6, hi: 0xb6}, + {value: 0x1882, lo: 0xb8, hi: 0xb9}, + {value: 0x1b86, lo: 0xba, hi: 0xba}, + // Block 0x40, offset 0x41 + {value: 0x0007, lo: 0x0e}, + {value: 0x1c39, lo: 0x94, hi: 0x94}, + {value: 0x1c40, lo: 0x9b, hi: 0x9b}, + {value: 0x1c45, lo: 0x9c, hi: 0x9c}, + {value: 0x1c4a, lo: 0x9e, hi: 0x9f}, + {value: 0x1c58, lo: 0xac, hi: 0xac}, + {value: 0x1c5f, lo: 0xae, hi: 0xae}, + {value: 0x1c66, lo: 0xb0, hi: 0xb0}, + {value: 0x1c6d, lo: 0xb2, hi: 0xb2}, + {value: 0x1c74, lo: 0xb4, hi: 0xb4}, + {value: 0x1c7b, lo: 0xb6, hi: 0xb6}, + {value: 0x1c82, lo: 0xb8, hi: 0xb8}, + {value: 0x1c89, lo: 0xba, hi: 0xba}, + {value: 0x1c90, lo: 0xbc, hi: 0xbc}, + {value: 0x1c97, lo: 0xbe, hi: 0xbe}, + // Block 0x41, offset 0x42 + {value: 0x0007, lo: 0x0d}, + {value: 0x1c9e, lo: 0x80, hi: 0x80}, + {value: 0x1ca5, lo: 0x82, hi: 0x82}, + {value: 0x1cac, lo: 0x85, hi: 0x85}, + {value: 0x1cb3, lo: 0x87, hi: 0x87}, + {value: 0x1cba, lo: 0x89, hi: 0x89}, + {value: 0x1cc1, lo: 0x90, hi: 0x91}, + {value: 0x1ccf, lo: 0x93, hi: 0x94}, + {value: 0x1cdd, lo: 0x96, hi: 0x97}, + {value: 0x1ceb, lo: 0x99, hi: 0x9a}, + {value: 0x1cf9, lo: 0x9c, hi: 0x9d}, + {value: 0x1d07, lo: 0xb4, hi: 0xb4}, + {value: 0x1d0e, lo: 0xb7, hi: 0xba}, + {value: 0x1d2a, lo: 0xbe, hi: 0xbf}, + // Block 0x42, offset 0x43 + {value: 0x0004, lo: 0x01}, + {value: 0x1d38, lo: 0xb1, hi: 0xbf}, + // Block 0x43, offset 0x44 + {value: 0x0004, lo: 0x01}, + {value: 0x1d74, lo: 0x80, hi: 0xbf}, + // Block 0x44, offset 0x45 + {value: 0x0004, lo: 0x07}, + {value: 0x1e74, lo: 0x80, hi: 0x8e}, + {value: 0x1826, lo: 0x92, hi: 0x92}, + {value: 0x183e, lo: 0x93, hi: 0x93}, + {value: 0x1eb0, lo: 0x94, hi: 0x99}, + {value: 0x1836, lo: 0x9a, hi: 0x9a}, + {value: 0x1ec8, lo: 0x9b, hi: 0x9e}, + {value: 0x1846, lo: 0x9f, hi: 0x9f}, + // Block 0x45, offset 0x46 + {value: 0x0004, lo: 0x0f}, + {value: 0x221c, lo: 0x80, hi: 0x80}, + {value: 0x2221, lo: 0x81, hi: 0x81}, + {value: 0x2226, lo: 0x82, hi: 0x82}, + {value: 0x222b, lo: 0x83, hi: 0x83}, + {value: 0x2230, lo: 0x84, hi: 0x84}, + {value: 0x2235, lo: 0x85, hi: 0x85}, + {value: 0x223a, lo: 0x86, hi: 0x86}, + {value: 0x223f, lo: 0x87, hi: 0x87}, + {value: 0x2244, lo: 0x88, hi: 0x88}, + {value: 0x2249, lo: 0x89, hi: 0x89}, + {value: 0x224f, lo: 0x8a, hi: 0x8a}, + {value: 0x2255, lo: 0x8b, hi: 0x8b}, + {value: 0x225b, lo: 0x8c, hi: 0x8c}, + {value: 0x225e, lo: 0x8d, hi: 0x8e}, + {value: 0x2265, lo: 0x8f, hi: 0xbe}, + // Block 0x46, offset 0x47 + {value: 0x0000, lo: 0x01}, + {value: 0x2a7d, lo: 0xb0, hi: 0xb0}, + // Block 0x47, offset 0x48 + {value: 0x0004, lo: 0x0a}, + {value: 0x2a81, lo: 0x80, hi: 0x81}, + {value: 0x1a9e, lo: 0x82, hi: 0x82}, + {value: 0x2a89, lo: 0x83, hi: 0x86}, + {value: 0x1b76, lo: 0x87, hi: 0x87}, + {value: 0x1b76, lo: 0x88, hi: 0x88}, + {value: 0x2a99, lo: 0x89, hi: 0x89}, + {value: 0x1abe, lo: 0x8a, hi: 0x8a}, + {value: 0x2a9d, lo: 0x8b, hi: 0xb3}, + {value: 0x1a16, lo: 0xb4, hi: 0xb4}, + {value: 0x2b41, lo: 0xb5, hi: 0xbf}, + // Block 0x48, offset 0x49 + {value: 0x0004, lo: 0x06}, + {value: 0x1b3a, lo: 0x80, hi: 0x80}, + {value: 0x2b6d, lo: 0x81, hi: 0x9b}, + {value: 0x2ac1, lo: 0x9c, hi: 0x9c}, + {value: 0x2bd9, lo: 0x9d, hi: 0xb0}, + {value: 0x1aa6, lo: 0xb1, hi: 0xb1}, + {value: 0x2c29, lo: 0xb2, hi: 0xbf}, + // Block 0x49, offset 0x4a + {value: 0x0004, lo: 0x0a}, + {value: 0x2c61, lo: 0x80, hi: 0x80}, + {value: 0x18ba, lo: 0x81, hi: 0x81}, + {value: 0x2c65, lo: 0x82, hi: 0x89}, + {value: 0x186e, lo: 0x8a, hi: 0x8a}, + {value: 0x2c85, lo: 0x8b, hi: 0xa0}, + {value: 0x2c21, lo: 0xa1, hi: 0xa1}, + {value: 0x2cdd, lo: 0xa2, hi: 0xa9}, + {value: 0x2be1, lo: 0xaa, hi: 0xaa}, + {value: 0x2cfd, lo: 0xab, hi: 0xbe}, + {value: 0x2ac1, lo: 0xbf, hi: 0xbf}, + // Block 0x4a, offset 0x4b + {value: 0x0004, lo: 0x0b}, + {value: 0x2d4d, lo: 0x80, hi: 0x83}, + {value: 0x1b72, lo: 0x84, hi: 0x84}, + {value: 0x2d5d, lo: 0x85, hi: 0x90}, + {value: 0x2173, lo: 0x91, hi: 0x91}, + {value: 0x2d8d, lo: 0x92, hi: 0x9a}, + {value: 0x2be9, lo: 0x9b, hi: 0x9b}, + {value: 0x2db1, lo: 0x9c, hi: 0xa8}, + {value: 0x1aba, lo: 0xa9, hi: 0xa9}, + {value: 0x2de5, lo: 0xaa, hi: 0xb6}, + {value: 0x19f6, lo: 0xb7, hi: 0xb7}, + {value: 0x2e19, lo: 0xb8, hi: 0xbf}, + // Block 0x4b, offset 0x4c + {value: 0x0004, lo: 0x10}, + {value: 0x2e39, lo: 0x80, hi: 0x87}, + {value: 0x1a62, lo: 0x88, hi: 0x88}, + {value: 0x2e59, lo: 0x89, hi: 0x89}, + {value: 0x1a6e, lo: 0x8a, hi: 0x8a}, + {value: 0x2e5d, lo: 0x8b, hi: 0x8d}, + {value: 0x2e69, lo: 0x90, hi: 0x90}, + {value: 0x2e6d, lo: 0x92, hi: 0x92}, + {value: 0x2e71, lo: 0x95, hi: 0x9d}, + {value: 0x1a12, lo: 0x9e, hi: 0x9e}, + {value: 0x2e95, lo: 0xa0, hi: 0xa0}, + {value: 0x2e99, lo: 0xa2, hi: 0xa2}, + {value: 0x2e9d, lo: 0xa5, hi: 0xa6}, + {value: 0x2ea5, lo: 0xaa, hi: 0xad}, + {value: 0x2eb5, lo: 0xb0, hi: 0xbb}, + {value: 0x18d6, lo: 0xbc, hi: 0xbc}, + {value: 0x2ee5, lo: 0xbd, hi: 0xbf}, + // Block 0x4c, offset 0x4d + {value: 0x0004, lo: 0x10}, + {value: 0x2ef1, lo: 0x80, hi: 0x8b}, + {value: 0x2187, lo: 0x8c, hi: 0x8c}, + {value: 0x2f21, lo: 0x8d, hi: 0x90}, + {value: 0x2197, lo: 0x91, hi: 0x91}, + {value: 0x2f31, lo: 0x92, hi: 0x96}, + {value: 0x2cb1, lo: 0x97, hi: 0x97}, + {value: 0x2f45, lo: 0x98, hi: 0x9d}, + {value: 0x2f59, lo: 0x9e, hi: 0xa6}, + {value: 0x2e9d, lo: 0xa7, hi: 0xa7}, + {value: 0x2f7d, lo: 0xa8, hi: 0xac}, + {value: 0x2f92, lo: 0xad, hi: 0xad}, + {value: 0x2f96, lo: 0xb0, hi: 0xb7}, + {value: 0x2ecd, lo: 0xb8, hi: 0xb8}, + {value: 0x2fb6, lo: 0xb9, hi: 0xbb}, + {value: 0x2e69, lo: 0xbc, hi: 0xbc}, + {value: 0x2fc2, lo: 0xbd, hi: 0xbf}, + // Block 0x4d, offset 0x4e + {value: 0x0005, lo: 0x06}, + {value: 0x3277, lo: 0x80, hi: 0x80}, + {value: 0x327e, lo: 0x81, hi: 0x81}, + {value: 0x3285, lo: 0x82, hi: 0x82}, + {value: 0x326d, lo: 0x83, hi: 0x83}, + {value: 0x328c, lo: 0x84, hi: 0x84}, + {value: 0x3293, lo: 0x85, hi: 0xbf}, + // Block 0x4e, offset 0x4f + {value: 0x0005, lo: 0x10}, + {value: 0x356a, lo: 0x80, hi: 0x8b}, + {value: 0x3514, lo: 0x8c, hi: 0x8c}, + {value: 0x35a6, lo: 0x8d, hi: 0x90}, + {value: 0x3533, lo: 0x91, hi: 0xa7}, + {value: 0x3514, lo: 0xa8, hi: 0xa8}, + {value: 0x35a6, lo: 0xa9, hi: 0xac}, + {value: 0x3597, lo: 0xad, hi: 0xaf}, + {value: 0x3514, lo: 0xb0, hi: 0xb0}, + {value: 0x350f, lo: 0xb1, hi: 0xb1}, + {value: 0x3519, lo: 0xb2, hi: 0xb2}, + {value: 0x333d, lo: 0xb3, hi: 0xb3}, + {value: 0x3306, lo: 0xb4, hi: 0xb6}, + {value: 0x3597, lo: 0xb7, hi: 0xb9}, + {value: 0x333d, lo: 0xba, hi: 0xbb}, + {value: 0x35ba, lo: 0xbc, hi: 0xbc}, + {value: 0x35ba, lo: 0xbd, hi: 0xbd}, + // Block 0x4f, offset 0x50 + {value: 0x0007, lo: 0x0d}, + {value: 0x35bf, lo: 0x90, hi: 0x91}, + {value: 0x35c6, lo: 0x92, hi: 0x98}, + {value: 0x35f0, lo: 0x99, hi: 0x9f}, + {value: 0x361a, lo: 0xa0, hi: 0xa2}, + {value: 0x3628, lo: 0xa3, hi: 0xa4}, + {value: 0x362f, lo: 0xa5, hi: 0xa7}, + {value: 0x363d, lo: 0xa8, hi: 0xaa}, + {value: 0x364b, lo: 0xab, hi: 0xac}, + {value: 0x3652, lo: 0xad, hi: 0xaf}, + {value: 0x3660, lo: 0xb0, hi: 0xb1}, + {value: 0x3667, lo: 0xb2, hi: 0xb6}, + {value: 0x3683, lo: 0xb7, hi: 0xbc}, + {value: 0x36a6, lo: 0xbd, hi: 0xbf}, + // Block 0x50, offset 0x51 + {value: 0x0007, lo: 0x0d}, + {value: 0x36bb, lo: 0x80, hi: 0x83}, + {value: 0x36d0, lo: 0x84, hi: 0x85}, + {value: 0x36d7, lo: 0x86, hi: 0x87}, + {value: 0x36de, lo: 0x88, hi: 0x8f}, + {value: 0x3716, lo: 0x92, hi: 0x97}, + {value: 0x3739, lo: 0x98, hi: 0x9c}, + {value: 0x3755, lo: 0x9d, hi: 0xb3}, + {value: 0x36ad, lo: 0xb4, hi: 0xb4}, + {value: 0x36bb, lo: 0xb5, hi: 0xb5}, + {value: 0x37f6, lo: 0xb6, hi: 0xbb}, + {value: 0x3812, lo: 0xbc, hi: 0xbc}, + {value: 0x3804, lo: 0xbd, hi: 0xbd}, + {value: 0x3820, lo: 0xbe, hi: 0xbf}, + // Block 0x51, offset 0x52 + {value: 0x0009, lo: 0x0e}, + {value: 0x382e, lo: 0x80, hi: 0x80}, + {value: 0x3835, lo: 0x81, hi: 0x81}, + {value: 0x383c, lo: 0x82, hi: 0x82}, + {value: 0x3819, lo: 0x83, hi: 0x83}, + {value: 0x367c, lo: 0x84, hi: 0x84}, + {value: 0x3636, lo: 0x85, hi: 0x85}, + {value: 0x3843, lo: 0x86, hi: 0x86}, + {value: 0x384a, lo: 0x87, hi: 0x87}, + {value: 0x3851, lo: 0xb0, hi: 0xb0}, + {value: 0x3858, lo: 0xb1, hi: 0xb1}, + {value: 0x385f, lo: 0xb2, hi: 0xb9}, + {value: 0x38a5, lo: 0xba, hi: 0xba}, + {value: 0x38c7, lo: 0xbb, hi: 0xbb}, + {value: 0x38d7, lo: 0xbc, hi: 0xbc}, + // Block 0x52, offset 0x53 + {value: 0x0004, lo: 0x10}, + {value: 0x38e0, lo: 0x90, hi: 0x90}, + {value: 0x38e2, lo: 0x91, hi: 0x93}, + {value: 0x04e1, lo: 0x94, hi: 0x94}, + {value: 0x38ec, lo: 0x95, hi: 0x95}, + {value: 0x38ee, lo: 0x96, hi: 0x96}, + {value: 0x38f0, lo: 0x97, hi: 0x98}, + {value: 0x1443, lo: 0x99, hi: 0x99}, + {value: 0x1440, lo: 0xb0, hi: 0xb0}, + {value: 0x38f8, lo: 0xb1, hi: 0xb3}, + {value: 0x3900, lo: 0xb4, hi: 0xb4}, + {value: 0x149c, lo: 0xb5, hi: 0xb5}, + {value: 0x149e, lo: 0xb6, hi: 0xb6}, + {value: 0x3902, lo: 0xb7, hi: 0xb7}, + {value: 0x3904, lo: 0xb8, hi: 0xb8}, + {value: 0x3906, lo: 0xb9, hi: 0xbe}, + {value: 0x16c3, lo: 0xbf, hi: 0xbf}, + // Block 0x53, offset 0x54 + {value: 0x0004, lo: 0x04}, + {value: 0x22a5, lo: 0x80, hi: 0x9c}, + {value: 0x3a38, lo: 0x9d, hi: 0x9f}, + {value: 0x1e04, lo: 0xa0, hi: 0xa0}, + {value: 0x1d38, lo: 0xa1, hi: 0xbe}, + // Block 0x54, offset 0x55 + {value: 0x0004, lo: 0x0c}, + {value: 0x1db0, lo: 0x82, hi: 0x87}, + {value: 0x1dc8, lo: 0x8a, hi: 0x8f}, + {value: 0x1de0, lo: 0x92, hi: 0x97}, + {value: 0x1df8, lo: 0x9a, hi: 0x9c}, + {value: 0x3a44, lo: 0xa0, hi: 0xa0}, + {value: 0x3a47, lo: 0xa1, hi: 0xa1}, + {value: 0x3a4a, lo: 0xa2, hi: 0xa2}, + {value: 0x0009, lo: 0xa3, hi: 0xa3}, + {value: 0x3a4d, lo: 0xa4, hi: 0xa4}, + {value: 0x3a50, lo: 0xa5, hi: 0xa5}, + {value: 0x3a53, lo: 0xa6, hi: 0xa6}, + {value: 0x3a57, lo: 0xa8, hi: 0xae}, + // Block 0x55, offset 0x56 + {value: 0x0009, lo: 0x03}, + {value: 0x3a73, lo: 0x9a, hi: 0x9a}, + {value: 0x3a7c, lo: 0x9c, hi: 0x9c}, + {value: 0x3a85, lo: 0xab, hi: 0xab}, + // Block 0x56, offset 0x57 + {value: 0x000d, lo: 0x03}, + {value: 0x3a8e, lo: 0x9e, hi: 0x9e}, + {value: 0x3a97, lo: 0x9f, hi: 0x9f}, + {value: 0x3aa0, lo: 0xa0, hi: 0xa4}, + // Block 0x57, offset 0x58 + {value: 0x0009, lo: 0x03}, + {value: 0x3ae1, lo: 0xbb, hi: 0xbd}, + {value: 0x3b00, lo: 0xbe, hi: 0xbe}, + {value: 0x3b0d, lo: 0xbf, hi: 0xbf}, + // Block 0x58, offset 0x59 + {value: 0x0000, lo: 0x01}, + {value: 0x3b1a, lo: 0x80, hi: 0x80}, + // Block 0x59, offset 0x5a + {value: 0x0003, lo: 0x0e}, + {value: 0x14c8, lo: 0x80, hi: 0x80}, + {value: 0x092b, lo: 0x81, hi: 0x81}, + {value: 0x17f6, lo: 0x82, hi: 0x82}, + {value: 0x092d, lo: 0x83, hi: 0x83}, + {value: 0x092f, lo: 0x84, hi: 0x84}, + {value: 0x155f, lo: 0x85, hi: 0x85}, + {value: 0x0931, lo: 0x86, hi: 0x86}, + {value: 0x1570, lo: 0x87, hi: 0x87}, + {value: 0x17f8, lo: 0x88, hi: 0x88}, + {value: 0x14d4, lo: 0x89, hi: 0x89}, + {value: 0x3c2c, lo: 0x8a, hi: 0x8a}, + {value: 0x293d, lo: 0x8b, hi: 0x8b}, + {value: 0x3c2f, lo: 0x8c, hi: 0x8e}, + {value: 0x3c39, lo: 0x8f, hi: 0x8f}, + // Block 0x5a, offset 0x5b + {value: 0x0000, lo: 0x01}, + {value: 0x3c3c, lo: 0x90, hi: 0x90}, + // Block 0x5b, offset 0x5c + {value: 0x000a, lo: 0x03}, + {value: 0x3cc1, lo: 0x80, hi: 0x88}, + {value: 0x3d1b, lo: 0x90, hi: 0x90}, + {value: 0x3d1f, lo: 0x91, hi: 0x91}, + // Block 0x5c, offset 0x5d + {value: 0x0004, lo: 0x0d}, + {value: 0x4463, lo: 0x80, hi: 0x81}, + {value: 0x446c, lo: 0x82, hi: 0x89}, + {value: 0x30a2, lo: 0x8a, hi: 0x8a}, + {value: 0x448d, lo: 0x8b, hi: 0x90}, + {value: 0x44a6, lo: 0x91, hi: 0x92}, + {value: 0x44af, lo: 0x93, hi: 0x93}, + {value: 0x44b4, lo: 0x94, hi: 0x94}, + {value: 0x1b42, lo: 0x95, hi: 0x95}, + {value: 0x44b9, lo: 0x96, hi: 0x96}, + {value: 0x1b52, lo: 0x97, hi: 0x97}, + {value: 0x44bd, lo: 0x98, hi: 0x9b}, + {value: 0x1b66, lo: 0x9c, hi: 0x9c}, + {value: 0x44cd, lo: 0x9d, hi: 0x9d}, } // nfkcDecompLookup: 960 bytes @@ -4367,51 +4608,51 @@ var nfkcDecompLookup = [960]uint8{ // Block 0x1, offset 0x40 // Block 0x2, offset 0x80 // Block 0x3, offset 0xc0 - 0x0c2: 0x03, 0x0c3: 0x04, 0x0c4: 0x05, 0x0c5: 0x06, 0x0c6: 0x07, 0x0c7: 0x08, - 0x0c8: 0x09, 0x0ca: 0x0a, 0x0cb: 0x0b, 0x0cd: 0x0c, 0x0ce: 0x0d, 0x0cf: 0x0e, - 0x0d0: 0x0f, 0x0d1: 0x10, 0x0d3: 0x11, 0x0d6: 0x12, - 0x0d8: 0x13, 0x0d9: 0x14, 0x0db: 0x15, + 0x0c2: 0x42, 0x0c3: 0x43, 0x0c4: 0x44, 0x0c5: 0x45, 0x0c6: 0x46, 0x0c7: 0x03, + 0x0c8: 0x47, 0x0ca: 0x48, 0x0cb: 0x49, 0x0cd: 0x4a, 0x0ce: 0x4b, 0x0cf: 0x4c, + 0x0d0: 0x4d, 0x0d1: 0x4e, 0x0d3: 0x4f, 0x0d6: 0x50, + 0x0d8: 0x51, 0x0d9: 0x52, 0x0db: 0x53, 0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07, 0x0ea: 0x08, 0x0ef: 0x09, 0x0f0: 0x0e, // Block 0x4, offset 0x100 - 0x124: 0x16, 0x125: 0x17, 0x127: 0x18, - 0x128: 0x19, 0x129: 0x1a, 0x12d: 0x1b, 0x12e: 0x1c, 0x12f: 0x1d, - 0x131: 0x1e, 0x133: 0x1f, 0x135: 0x20, 0x137: 0x21, - 0x138: 0x22, 0x13a: 0x23, 0x13b: 0x24, 0x13c: 0x25, 0x13d: 0x26, 0x13e: 0x27, + 0x124: 0x54, 0x125: 0x55, 0x127: 0x56, + 0x128: 0x57, 0x129: 0x58, 0x12d: 0x59, 0x12e: 0x5a, 0x12f: 0x5b, + 0x131: 0x5c, 0x133: 0x5d, 0x135: 0x5e, 0x137: 0x5f, + 0x138: 0x60, 0x13a: 0x61, 0x13b: 0x62, 0x13c: 0x63, 0x13d: 0x64, 0x13e: 0x65, // Block 0x5, offset 0x140 - 0x140: 0x28, 0x143: 0x29, - 0x16c: 0x2a, 0x16d: 0x2b, - 0x174: 0x2c, 0x175: 0x2d, 0x176: 0x2e, - 0x178: 0x2f, 0x179: 0x30, 0x17a: 0x31, 0x17b: 0x32, 0x17c: 0x33, 0x17d: 0x34, 0x17e: 0x35, 0x17f: 0x36, + 0x140: 0x66, 0x143: 0x67, + 0x16c: 0x68, 0x16d: 0x69, + 0x174: 0x6a, 0x175: 0x04, 0x176: 0x6b, + 0x178: 0x6c, 0x179: 0x05, 0x17a: 0x06, 0x17b: 0x07, 0x17c: 0x08, 0x17d: 0x09, 0x17e: 0x0a, 0x17f: 0x0b, // Block 0x6, offset 0x180 - 0x180: 0x37, 0x181: 0x38, 0x182: 0x39, 0x184: 0x3a, 0x185: 0x3b, 0x186: 0x3c, 0x187: 0x3d, - 0x188: 0x3e, 0x189: 0x3f, 0x18a: 0x40, 0x18b: 0x41, 0x18c: 0x42, - 0x191: 0x43, 0x192: 0x44, 0x193: 0x45, - 0x1a8: 0x46, 0x1a9: 0x47, 0x1ab: 0x48, - 0x1b1: 0x49, 0x1b5: 0x4a, - 0x1ba: 0x4b, 0x1bb: 0x4c, 0x1bc: 0x4d, 0x1bd: 0x4e, 0x1be: 0x4f, 0x1bf: 0x50, + 0x180: 0x6d, 0x181: 0x6e, 0x182: 0x0c, 0x184: 0x0d, 0x185: 0x0e, 0x186: 0x6f, 0x187: 0x70, + 0x188: 0x71, 0x189: 0x72, 0x18a: 0x73, 0x18b: 0x74, 0x18c: 0x75, + 0x191: 0x0f, 0x192: 0x10, 0x193: 0x11, + 0x1a8: 0x76, 0x1a9: 0x77, 0x1ab: 0x78, + 0x1b1: 0x79, 0x1b5: 0x7a, + 0x1ba: 0x7b, 0x1bb: 0x7c, 0x1bc: 0x7d, 0x1bd: 0x7e, 0x1be: 0x7f, 0x1bf: 0x80, // Block 0x7, offset 0x1c0 - 0x1c0: 0x51, 0x1c1: 0x52, 0x1c2: 0x53, 0x1c3: 0x54, 0x1c4: 0x55, 0x1c5: 0x56, 0x1c6: 0x57, - 0x1c8: 0x58, 0x1c9: 0x59, 0x1ca: 0x5a, 0x1cb: 0x5b, 0x1cc: 0x5c, 0x1cd: 0x5d, 0x1ce: 0x5e, 0x1cf: 0x5f, + 0x1c0: 0x81, 0x1c1: 0x12, 0x1c2: 0x82, 0x1c3: 0x83, 0x1c4: 0x84, 0x1c5: 0x85, 0x1c6: 0x86, + 0x1c8: 0x13, 0x1c9: 0x14, 0x1ca: 0x15, 0x1cb: 0x87, 0x1cc: 0x16, 0x1cd: 0x17, 0x1ce: 0x18, 0x1cf: 0x19, // Block 0x8, offset 0x200 - 0x21d: 0x60, + 0x21d: 0x88, // Block 0x9, offset 0x240 - 0x264: 0x61, 0x265: 0x62, 0x266: 0x63, 0x267: 0x64, - 0x268: 0x65, 0x269: 0x66, 0x26a: 0x67, 0x26b: 0x68, 0x26c: 0x69, 0x26d: 0x6a, 0x26e: 0x6b, 0x26f: 0x6c, - 0x270: 0x6d, 0x271: 0x6e, 0x272: 0x6f, 0x273: 0x70, 0x274: 0x71, 0x275: 0x72, 0x276: 0x73, 0x277: 0x74, - 0x278: 0x75, 0x279: 0x76, 0x27a: 0x77, 0x27b: 0x78, 0x27c: 0x79, 0x27d: 0x7a, 0x27e: 0x7b, 0x27f: 0x7c, + 0x264: 0x89, 0x265: 0x8a, 0x266: 0x8b, 0x267: 0x8c, + 0x268: 0x8d, 0x269: 0x8e, 0x26a: 0x1a, 0x26b: 0x1b, 0x26c: 0x1c, 0x26d: 0x1d, 0x26e: 0x1e, 0x26f: 0x1f, + 0x270: 0x8f, 0x271: 0x20, 0x272: 0x21, 0x273: 0x22, 0x274: 0x90, 0x275: 0x91, 0x276: 0x92, 0x277: 0x93, + 0x278: 0x94, 0x279: 0x23, 0x27a: 0x24, 0x27b: 0x25, 0x27c: 0x26, 0x27d: 0x27, 0x27e: 0x95, 0x27f: 0x96, // Block 0xa, offset 0x280 - 0x282: 0x7d, + 0x282: 0x97, // Block 0xb, offset 0x2c0 - 0x2c5: 0x7e, 0x2c6: 0x7f, 0x2c7: 0x80, - 0x2d0: 0x81, 0x2d1: 0x82, 0x2d2: 0x83, 0x2d3: 0x84, 0x2d4: 0x85, 0x2d5: 0x86, 0x2d6: 0x87, 0x2d7: 0x88, - 0x2d8: 0x89, 0x2d9: 0x8a, 0x2da: 0x8b, 0x2db: 0x8c, 0x2dc: 0x8d, 0x2dd: 0x8e, 0x2de: 0x8f, 0x2df: 0x90, + 0x2c5: 0x98, 0x2c6: 0x99, 0x2c7: 0x9a, + 0x2d0: 0x28, 0x2d1: 0x29, 0x2d2: 0x2a, 0x2d3: 0x2b, 0x2d4: 0x2c, 0x2d5: 0x2d, 0x2d6: 0x2e, 0x2d7: 0x2f, + 0x2d8: 0x30, 0x2d9: 0x31, 0x2da: 0x32, 0x2db: 0x33, 0x2dc: 0x34, 0x2dd: 0x35, 0x2de: 0x36, 0x2df: 0x37, // Block 0xc, offset 0x300 - 0x304: 0x91, 0x305: 0x92, 0x306: 0x93, - 0x308: 0x94, 0x309: 0x95, + 0x304: 0x38, 0x305: 0x9b, 0x306: 0x9c, + 0x308: 0x39, 0x309: 0x9d, // Block 0xd, offset 0x340 - 0x360: 0x96, 0x361: 0x97, 0x362: 0x98, 0x363: 0x99, 0x364: 0x9a, 0x365: 0x9b, 0x366: 0x9c, 0x367: 0x9d, + 0x360: 0x3a, 0x361: 0x3b, 0x362: 0x3c, 0x363: 0x3d, 0x364: 0x3e, 0x365: 0x3f, 0x366: 0x40, 0x367: 0x41, 0x368: 0x9e, // Block 0xe, offset 0x380 0x391: 0x0a, @@ -4419,7 +4660,7 @@ var nfkcDecompLookup = [960]uint8{ 0x3af: 0x0d, } -var nfkcDecompTrie = trie{nfkcDecompLookup[:], nfkcDecompValues[:]} +var nfkcDecompTrie = trie{nfkcDecompLookup[:], nfkcDecompValues[:], nfkcDecompSparseValues[:], nfkcDecompSparseOffset[:], 66} // recompMap: 7448 bytes (entries only) var recompMap = map[uint32]uint32{ @@ -5356,9 +5597,9 @@ var recompMap = map[uint32]uint32{ 0x10A510BA: 0x110AB, } -// charInfoValues: 11008 entries, 22016 bytes +// charInfoValues: 1024 entries, 2048 bytes // Block 2 is the null block. -var charInfoValues = [11008]uint16{ +var charInfoValues = [1024]uint16{ // Block 0x0, offset 0x0 0x003c: 0x8800, 0x003d: 0x8800, 0x003e: 0x8800, // Block 0x1, offset 0x40 @@ -5374,1134 +5615,1071 @@ var charInfoValues = [11008]uint16{ 0x0076: 0x8800, 0x0077: 0x8800, 0x0078: 0x8800, 0x0079: 0x8800, 0x007a: 0x8800, // Block 0x2, offset 0x80 // Block 0x3, offset 0xc0 - 0x00e0: 0x3000, - 0x00e8: 0x3800, - 0x00ea: 0x3000, 0x00ef: 0x3000, - 0x00f2: 0x3000, 0x00f3: 0x3000, 0x00f4: 0x3000, 0x00f5: 0x3000, - 0x00f8: 0x3000, 0x00f9: 0x3000, 0x00fa: 0x3000, - 0x00fc: 0x3000, 0x00fd: 0x3000, 0x00fe: 0x3000, + 0x00c0: 0x1100, 0x00c1: 0x1100, 0x00c2: 0x9900, 0x00c3: 0x1100, 0x00c4: 0x9900, 0x00c5: 0x9900, + 0x00c6: 0x8800, 0x00c7: 0x9900, 0x00c8: 0x1100, 0x00c9: 0x1100, 0x00ca: 0x9900, 0x00cb: 0x1100, + 0x00cc: 0x1100, 0x00cd: 0x1100, 0x00ce: 0x1100, 0x00cf: 0x9900, 0x00d1: 0x1100, + 0x00d2: 0x1100, 0x00d3: 0x1100, 0x00d4: 0x9900, 0x00d5: 0x9900, 0x00d6: 0x9900, + 0x00d8: 0x8800, 0x00d9: 0x1100, 0x00da: 0x1100, 0x00db: 0x1100, 0x00dc: 0x9900, 0x00dd: 0x1100, + 0x00e0: 0x1100, 0x00e1: 0x1100, 0x00e2: 0x9900, 0x00e3: 0x1100, + 0x00e4: 0x9900, 0x00e5: 0x9900, 0x00e6: 0x8800, 0x00e7: 0x9900, 0x00e8: 0x1100, 0x00e9: 0x1100, + 0x00ea: 0x9900, 0x00eb: 0x1100, 0x00ec: 0x1100, 0x00ed: 0x1100, 0x00ee: 0x1100, 0x00ef: 0x9900, + 0x00f1: 0x1100, 0x00f2: 0x1100, 0x00f3: 0x1100, 0x00f4: 0x9900, 0x00f5: 0x9900, + 0x00f6: 0x9900, 0x00f8: 0x8800, 0x00f9: 0x1100, 0x00fa: 0x1100, 0x00fb: 0x1100, + 0x00fc: 0x9900, 0x00fd: 0x1100, 0x00ff: 0x1100, // Block 0x4, offset 0x100 - 0x0100: 0x1100, 0x0101: 0x1100, 0x0102: 0x9900, 0x0103: 0x1100, 0x0104: 0x9900, 0x0105: 0x9900, - 0x0106: 0x8800, 0x0107: 0x9900, 0x0108: 0x1100, 0x0109: 0x1100, 0x010a: 0x9900, 0x010b: 0x1100, - 0x010c: 0x1100, 0x010d: 0x1100, 0x010e: 0x1100, 0x010f: 0x9900, 0x0111: 0x1100, - 0x0112: 0x1100, 0x0113: 0x1100, 0x0114: 0x9900, 0x0115: 0x9900, 0x0116: 0x9900, - 0x0118: 0x8800, 0x0119: 0x1100, 0x011a: 0x1100, 0x011b: 0x1100, 0x011c: 0x9900, 0x011d: 0x1100, - 0x0120: 0x1100, 0x0121: 0x1100, 0x0122: 0x9900, 0x0123: 0x1100, - 0x0124: 0x9900, 0x0125: 0x9900, 0x0126: 0x8800, 0x0127: 0x9900, 0x0128: 0x1100, 0x0129: 0x1100, - 0x012a: 0x9900, 0x012b: 0x1100, 0x012c: 0x1100, 0x012d: 0x1100, 0x012e: 0x1100, 0x012f: 0x9900, - 0x0131: 0x1100, 0x0132: 0x1100, 0x0133: 0x1100, 0x0134: 0x9900, 0x0135: 0x9900, - 0x0136: 0x9900, 0x0138: 0x8800, 0x0139: 0x1100, 0x013a: 0x1100, 0x013b: 0x1100, - 0x013c: 0x9900, 0x013d: 0x1100, 0x013f: 0x1100, + 0x0100: 0x66e6, 0x0101: 0x66e6, 0x0102: 0x66e6, 0x0103: 0x66e6, 0x0104: 0x66e6, 0x0105: 0x00e6, + 0x0106: 0x66e6, 0x0107: 0x66e6, 0x0108: 0x66e6, 0x0109: 0x66e6, 0x010a: 0x66e6, 0x010b: 0x66e6, + 0x010c: 0x66e6, 0x010d: 0x00e6, 0x010e: 0x00e6, 0x010f: 0x66e6, 0x0110: 0x00e6, 0x0111: 0x66e6, + 0x0112: 0x00e6, 0x0113: 0x66e6, 0x0114: 0x66e6, 0x0115: 0x00e8, 0x0116: 0x00dc, 0x0117: 0x00dc, + 0x0118: 0x00dc, 0x0119: 0x00dc, 0x011a: 0x00e8, 0x011b: 0x66d8, 0x011c: 0x00dc, 0x011d: 0x00dc, + 0x011e: 0x00dc, 0x011f: 0x00dc, 0x0120: 0x00dc, 0x0121: 0x00ca, 0x0122: 0x00ca, 0x0123: 0x66dc, + 0x0124: 0x66dc, 0x0125: 0x66dc, 0x0126: 0x66dc, 0x0127: 0x66ca, 0x0128: 0x66ca, 0x0129: 0x00dc, + 0x012a: 0x00dc, 0x012b: 0x00dc, 0x012c: 0x00dc, 0x012d: 0x66dc, 0x012e: 0x66dc, 0x012f: 0x00dc, + 0x0130: 0x66dc, 0x0131: 0x66dc, 0x0132: 0x00dc, 0x0133: 0x00dc, 0x0134: 0x0001, 0x0135: 0x0001, + 0x0136: 0x0001, 0x0137: 0x0001, 0x0138: 0x6601, 0x0139: 0x00dc, 0x013a: 0x00dc, 0x013b: 0x00dc, + 0x013c: 0x00dc, 0x013d: 0x00e6, 0x013e: 0x00e6, 0x013f: 0x00e6, // Block 0x5, offset 0x140 - 0x0140: 0x1100, 0x0141: 0x1100, 0x0142: 0x9900, 0x0143: 0x9900, 0x0144: 0x1100, 0x0145: 0x1100, - 0x0146: 0x1100, 0x0147: 0x1100, 0x0148: 0x1100, 0x0149: 0x1100, 0x014a: 0x1100, 0x014b: 0x1100, - 0x014c: 0x1100, 0x014d: 0x1100, 0x014e: 0x1100, 0x014f: 0x1100, - 0x0152: 0x9900, 0x0153: 0x9900, 0x0154: 0x1100, 0x0155: 0x1100, 0x0156: 0x1100, 0x0157: 0x1100, - 0x0158: 0x1100, 0x0159: 0x1100, 0x015a: 0x1100, 0x015b: 0x1100, 0x015c: 0x1100, 0x015d: 0x1100, - 0x015e: 0x1100, 0x015f: 0x1100, 0x0160: 0x1100, 0x0161: 0x1100, 0x0162: 0x1100, 0x0163: 0x1100, - 0x0164: 0x1100, 0x0165: 0x1100, 0x0168: 0x1100, 0x0169: 0x1100, - 0x016a: 0x1100, 0x016b: 0x1100, 0x016c: 0x1100, 0x016d: 0x1100, 0x016e: 0x1100, 0x016f: 0x1100, - 0x0170: 0x1100, 0x0172: 0x3000, 0x0173: 0x3000, 0x0174: 0x1100, 0x0175: 0x1100, - 0x0176: 0x1100, 0x0177: 0x1100, 0x0179: 0x1100, 0x017a: 0x1100, 0x017b: 0x1100, - 0x017c: 0x1100, 0x017d: 0x1100, 0x017e: 0x1100, 0x017f: 0x3000, + 0x0140: 0x33e6, 0x0141: 0x33e6, 0x0142: 0x66e6, 0x0143: 0x33e6, 0x0144: 0x33e6, 0x0145: 0x66f0, + 0x0146: 0x00e6, 0x0147: 0x00dc, 0x0148: 0x00dc, 0x0149: 0x00dc, 0x014a: 0x00e6, 0x014b: 0x00e6, + 0x014c: 0x00e6, 0x014d: 0x00dc, 0x014e: 0x00dc, 0x0150: 0x00e6, 0x0151: 0x00e6, + 0x0152: 0x00e6, 0x0153: 0x00dc, 0x0154: 0x00dc, 0x0155: 0x00dc, 0x0156: 0x00dc, 0x0157: 0x00e6, + 0x0158: 0x00e8, 0x0159: 0x00dc, 0x015a: 0x00dc, 0x015b: 0x00e6, 0x015c: 0x00e9, 0x015d: 0x00ea, + 0x015e: 0x00ea, 0x015f: 0x00e9, 0x0160: 0x00ea, 0x0161: 0x00ea, 0x0162: 0x00e9, 0x0163: 0x00e6, + 0x0164: 0x00e6, 0x0165: 0x00e6, 0x0166: 0x00e6, 0x0167: 0x00e6, 0x0168: 0x00e6, 0x0169: 0x00e6, + 0x016a: 0x00e6, 0x016b: 0x00e6, 0x016c: 0x00e6, 0x016d: 0x00e6, 0x016e: 0x00e6, 0x016f: 0x00e6, + 0x0174: 0x3300, + 0x017a: 0x3000, + 0x017e: 0x3300, // Block 0x6, offset 0x180 - 0x0180: 0x3000, 0x0183: 0x1100, 0x0184: 0x1100, 0x0185: 0x1100, - 0x0186: 0x1100, 0x0187: 0x1100, 0x0188: 0x1100, 0x0189: 0x3000, - 0x018c: 0x9900, 0x018d: 0x9900, 0x018e: 0x1100, 0x018f: 0x1100, 0x0190: 0x1100, 0x0191: 0x1100, - 0x0194: 0x1100, 0x0195: 0x1100, 0x0196: 0x1100, 0x0197: 0x1100, - 0x0198: 0x1100, 0x0199: 0x1100, 0x019a: 0x9900, 0x019b: 0x9900, 0x019c: 0x1100, 0x019d: 0x1100, - 0x019e: 0x1100, 0x019f: 0x1100, 0x01a0: 0x9900, 0x01a1: 0x9900, 0x01a2: 0x1100, 0x01a3: 0x1100, - 0x01a4: 0x1100, 0x01a5: 0x1100, 0x01a8: 0x9900, 0x01a9: 0x9900, - 0x01aa: 0x9900, 0x01ab: 0x9900, 0x01ac: 0x1100, 0x01ad: 0x1100, 0x01ae: 0x1100, 0x01af: 0x1100, - 0x01b0: 0x1100, 0x01b1: 0x1100, 0x01b2: 0x1100, 0x01b3: 0x1100, 0x01b4: 0x1100, 0x01b5: 0x1100, - 0x01b6: 0x1100, 0x01b7: 0x1100, 0x01b8: 0x1100, 0x01b9: 0x1100, 0x01ba: 0x1100, 0x01bb: 0x1100, - 0x01bc: 0x1100, 0x01bd: 0x1100, 0x01be: 0x1100, 0x01bf: 0x3800, + 0x0184: 0x3000, 0x0185: 0x3100, + 0x0186: 0x1100, 0x0187: 0x3300, 0x0188: 0x1100, 0x0189: 0x1100, 0x018a: 0x1100, + 0x018c: 0x1100, 0x018e: 0x1100, 0x018f: 0x1100, 0x0190: 0x1100, 0x0191: 0x8800, + 0x0195: 0x8800, 0x0197: 0x8800, + 0x0199: 0x8800, + 0x019f: 0x8800, 0x01a1: 0x8800, + 0x01a5: 0x8800, 0x01a9: 0x8800, + 0x01aa: 0x1100, 0x01ab: 0x1100, 0x01ac: 0x9900, 0x01ad: 0x1100, 0x01ae: 0x9900, 0x01af: 0x1100, + 0x01b0: 0x1100, 0x01b1: 0x8800, 0x01b5: 0x8800, + 0x01b7: 0x8800, 0x01b9: 0x8800, + 0x01bf: 0x8800, // Block 0x7, offset 0x1c0 - 0x01e0: 0x9900, 0x01e1: 0x9900, - 0x01ef: 0x9900, - 0x01f0: 0x9900, - 0x01f7: 0x8800, + 0x01c0: 0x1100, 0x01c1: 0x1100, 0x01c3: 0x1100, + 0x01c6: 0x8800, 0x01c7: 0x1100, + 0x01cc: 0x1100, 0x01cd: 0x1100, 0x01ce: 0x1100, 0x01d0: 0x8800, + 0x01d3: 0x8800, 0x01d5: 0x8800, 0x01d6: 0x8800, 0x01d7: 0x8800, + 0x01d8: 0x8800, 0x01d9: 0x1100, 0x01da: 0x8800, + 0x01de: 0x8800, 0x01e3: 0x8800, + 0x01e7: 0x8800, + 0x01eb: 0x8800, 0x01ed: 0x8800, + 0x01f0: 0x8800, 0x01f3: 0x8800, 0x01f5: 0x8800, + 0x01f6: 0x8800, 0x01f7: 0x8800, 0x01f8: 0x8800, 0x01f9: 0x1100, 0x01fa: 0x8800, + 0x01fe: 0x8800, // Block 0x8, offset 0x200 - 0x0204: 0x3000, 0x0205: 0x3000, - 0x0206: 0x3000, 0x0207: 0x3000, 0x0208: 0x3000, 0x0209: 0x3000, 0x020a: 0x3000, 0x020b: 0x3000, - 0x020c: 0x3000, 0x020d: 0x1100, 0x020e: 0x1100, 0x020f: 0x1100, 0x0210: 0x1100, 0x0211: 0x1100, - 0x0212: 0x1100, 0x0213: 0x1100, 0x0214: 0x1100, 0x0215: 0x1100, 0x0216: 0x1100, 0x0217: 0x1100, - 0x0218: 0x1100, 0x0219: 0x1100, 0x021a: 0x1100, 0x021b: 0x1100, 0x021c: 0x1100, - 0x021e: 0x1100, 0x021f: 0x1100, 0x0220: 0x1100, 0x0221: 0x1100, 0x0222: 0x1100, 0x0223: 0x1100, - 0x0226: 0x1100, 0x0227: 0x1100, 0x0228: 0x1100, 0x0229: 0x1100, - 0x022a: 0x9900, 0x022b: 0x9900, 0x022c: 0x1100, 0x022d: 0x1100, 0x022e: 0x1100, 0x022f: 0x1100, - 0x0230: 0x1100, 0x0231: 0x3000, 0x0232: 0x3000, 0x0233: 0x3000, 0x0234: 0x1100, 0x0235: 0x1100, - 0x0238: 0x1100, 0x0239: 0x1100, 0x023a: 0x1100, 0x023b: 0x1100, - 0x023c: 0x1100, 0x023d: 0x1100, 0x023e: 0x1100, 0x023f: 0x1100, + 0x0207: 0x3000, + 0x0211: 0x00dc, + 0x0212: 0x00e6, 0x0213: 0x00e6, 0x0214: 0x00e6, 0x0215: 0x00e6, 0x0216: 0x00dc, 0x0217: 0x00e6, + 0x0218: 0x00e6, 0x0219: 0x00e6, 0x021a: 0x00de, 0x021b: 0x00dc, 0x021c: 0x00e6, 0x021d: 0x00e6, + 0x021e: 0x00e6, 0x021f: 0x00e6, 0x0220: 0x00e6, 0x0221: 0x00e6, 0x0222: 0x00dc, 0x0223: 0x00dc, + 0x0224: 0x00dc, 0x0225: 0x00dc, 0x0226: 0x00dc, 0x0227: 0x00dc, 0x0228: 0x00e6, 0x0229: 0x00e6, + 0x022a: 0x00dc, 0x022b: 0x00e6, 0x022c: 0x00e6, 0x022d: 0x00de, 0x022e: 0x00e4, 0x022f: 0x00e6, + 0x0230: 0x000a, 0x0231: 0x000b, 0x0232: 0x000c, 0x0233: 0x000d, 0x0234: 0x000e, 0x0235: 0x000f, + 0x0236: 0x0010, 0x0237: 0x0011, 0x0238: 0x0012, 0x0239: 0x0013, 0x023a: 0x0013, 0x023b: 0x0014, + 0x023c: 0x0015, 0x023d: 0x0016, 0x023f: 0x0017, // Block 0x9, offset 0x240 - 0x0240: 0x1100, 0x0241: 0x1100, 0x0242: 0x1100, 0x0243: 0x1100, 0x0244: 0x1100, 0x0245: 0x1100, - 0x0246: 0x1100, 0x0247: 0x1100, 0x0248: 0x1100, 0x0249: 0x1100, 0x024a: 0x1100, 0x024b: 0x1100, - 0x024c: 0x1100, 0x024d: 0x1100, 0x024e: 0x1100, 0x024f: 0x1100, 0x0250: 0x1100, 0x0251: 0x1100, - 0x0252: 0x1100, 0x0253: 0x1100, 0x0254: 0x1100, 0x0255: 0x1100, 0x0256: 0x1100, 0x0257: 0x1100, - 0x0258: 0x1100, 0x0259: 0x1100, 0x025a: 0x1100, 0x025b: 0x1100, - 0x025e: 0x1100, 0x025f: 0x1100, - 0x0266: 0x9900, 0x0267: 0x9900, 0x0268: 0x9900, 0x0269: 0x9900, - 0x026a: 0x1100, 0x026b: 0x1100, 0x026c: 0x1100, 0x026d: 0x1100, 0x026e: 0x9900, 0x026f: 0x9900, - 0x0270: 0x1100, 0x0271: 0x1100, 0x0272: 0x1100, 0x0273: 0x1100, + 0x0248: 0x8800, 0x024a: 0x8800, 0x024b: 0x001b, + 0x024c: 0x001c, 0x024d: 0x001d, 0x024e: 0x001e, 0x024f: 0x001f, 0x0250: 0x0020, 0x0251: 0x0021, + 0x0252: 0x0022, 0x0253: 0x66e6, 0x0254: 0x66e6, 0x0255: 0x66dc, 0x0256: 0x00dc, 0x0257: 0x00e6, + 0x0258: 0x00e6, 0x0259: 0x00e6, 0x025a: 0x00e6, 0x025b: 0x00e6, 0x025c: 0x00dc, 0x025d: 0x00e6, + 0x025e: 0x00e6, 0x025f: 0x00dc, + 0x0270: 0x0023, 0x0275: 0x3000, + 0x0276: 0x3000, 0x0277: 0x3000, 0x0278: 0x3000, // Block 0xa, offset 0x280 - 0x0292: 0x8800, - 0x02b0: 0x3000, 0x02b1: 0x3000, 0x02b2: 0x3000, 0x02b3: 0x3000, 0x02b4: 0x3000, 0x02b5: 0x3000, - 0x02b6: 0x3000, 0x02b7: 0x3000, 0x02b8: 0x3000, + 0x0280: 0x9900, 0x0281: 0x9900, 0x0282: 0x1100, 0x0283: 0x1100, 0x0284: 0x1100, 0x0285: 0x1100, + 0x0288: 0x9900, 0x0289: 0x9900, 0x028a: 0x1100, 0x028b: 0x1100, + 0x028c: 0x1100, 0x028d: 0x1100, 0x0290: 0x9900, 0x0291: 0x9900, + 0x0292: 0x1100, 0x0293: 0x1100, 0x0294: 0x1100, 0x0295: 0x1100, 0x0296: 0x1100, 0x0297: 0x1100, + 0x0299: 0x9900, 0x029b: 0x1100, 0x029d: 0x1100, + 0x029f: 0x1100, 0x02a0: 0x9900, 0x02a1: 0x9900, 0x02a2: 0x9900, 0x02a3: 0x9900, + 0x02a4: 0x9900, 0x02a5: 0x9900, 0x02a6: 0x9900, 0x02a7: 0x9900, 0x02a8: 0x9900, 0x02a9: 0x9900, + 0x02aa: 0x9900, 0x02ab: 0x9900, 0x02ac: 0x9900, 0x02ad: 0x9900, 0x02ae: 0x9900, 0x02af: 0x9900, + 0x02b0: 0x9900, 0x02b1: 0x3300, 0x02b2: 0x1100, 0x02b3: 0x3300, 0x02b4: 0x9900, 0x02b5: 0x3300, + 0x02b6: 0x1100, 0x02b7: 0x3300, 0x02b8: 0x1100, 0x02b9: 0x3300, 0x02ba: 0x1100, 0x02bb: 0x3300, + 0x02bc: 0x9900, 0x02bd: 0x3300, // Block 0xb, offset 0x2c0 - 0x02d8: 0x3000, 0x02d9: 0x3000, 0x02da: 0x3000, 0x02db: 0x3000, 0x02dc: 0x3000, 0x02dd: 0x3000, - 0x02e0: 0x3000, 0x02e1: 0x3000, 0x02e2: 0x3000, 0x02e3: 0x3000, - 0x02e4: 0x3000, + 0x02c0: 0x3000, 0x02c1: 0x3100, 0x02c2: 0x1100, 0x02c3: 0x1100, 0x02c4: 0x1100, + 0x02c6: 0x9900, 0x02c7: 0x1100, 0x02c8: 0x1100, 0x02c9: 0x3300, 0x02ca: 0x1100, 0x02cb: 0x3300, + 0x02cc: 0x1100, 0x02cd: 0x3100, 0x02ce: 0x3100, 0x02cf: 0x3100, 0x02d0: 0x1100, 0x02d1: 0x1100, + 0x02d2: 0x1100, 0x02d3: 0x3300, 0x02d6: 0x1100, 0x02d7: 0x1100, + 0x02d8: 0x1100, 0x02d9: 0x1100, 0x02da: 0x1100, 0x02db: 0x3300, 0x02dd: 0x3100, + 0x02de: 0x3100, 0x02df: 0x3100, 0x02e0: 0x1100, 0x02e1: 0x1100, 0x02e2: 0x1100, 0x02e3: 0x3300, + 0x02e4: 0x1100, 0x02e5: 0x1100, 0x02e6: 0x1100, 0x02e7: 0x1100, 0x02e8: 0x1100, 0x02e9: 0x1100, + 0x02ea: 0x1100, 0x02eb: 0x3300, 0x02ec: 0x1100, 0x02ed: 0x3100, 0x02ee: 0x3300, 0x02ef: 0x3300, + 0x02f2: 0x1100, 0x02f3: 0x1100, 0x02f4: 0x1100, + 0x02f6: 0x9900, 0x02f7: 0x1100, 0x02f8: 0x1100, 0x02f9: 0x3300, 0x02fa: 0x1100, 0x02fb: 0x3300, + 0x02fc: 0x1100, 0x02fd: 0x3300, 0x02fe: 0x3800, // Block 0xc, offset 0x300 - 0x0300: 0x66e6, 0x0301: 0x66e6, 0x0302: 0x66e6, 0x0303: 0x66e6, 0x0304: 0x66e6, 0x0305: 0x00e6, - 0x0306: 0x66e6, 0x0307: 0x66e6, 0x0308: 0x66e6, 0x0309: 0x66e6, 0x030a: 0x66e6, 0x030b: 0x66e6, - 0x030c: 0x66e6, 0x030d: 0x00e6, 0x030e: 0x00e6, 0x030f: 0x66e6, 0x0310: 0x00e6, 0x0311: 0x66e6, - 0x0312: 0x00e6, 0x0313: 0x66e6, 0x0314: 0x66e6, 0x0315: 0x00e8, 0x0316: 0x00dc, 0x0317: 0x00dc, - 0x0318: 0x00dc, 0x0319: 0x00dc, 0x031a: 0x00e8, 0x031b: 0x66d8, 0x031c: 0x00dc, 0x031d: 0x00dc, - 0x031e: 0x00dc, 0x031f: 0x00dc, 0x0320: 0x00dc, 0x0321: 0x00ca, 0x0322: 0x00ca, 0x0323: 0x66dc, - 0x0324: 0x66dc, 0x0325: 0x66dc, 0x0326: 0x66dc, 0x0327: 0x66ca, 0x0328: 0x66ca, 0x0329: 0x00dc, - 0x032a: 0x00dc, 0x032b: 0x00dc, 0x032c: 0x00dc, 0x032d: 0x66dc, 0x032e: 0x66dc, 0x032f: 0x00dc, - 0x0330: 0x66dc, 0x0331: 0x66dc, 0x0332: 0x00dc, 0x0333: 0x00dc, 0x0334: 0x0001, 0x0335: 0x0001, - 0x0336: 0x0001, 0x0337: 0x0001, 0x0338: 0x6601, 0x0339: 0x00dc, 0x033a: 0x00dc, 0x033b: 0x00dc, - 0x033c: 0x00dc, 0x033d: 0x00e6, 0x033e: 0x00e6, 0x033f: 0x00e6, + 0x0301: 0x1100, 0x0303: 0x8800, 0x0304: 0x1100, 0x0305: 0x8800, + 0x0307: 0x1100, 0x0308: 0x8800, 0x0309: 0x1100, + 0x030d: 0x8800, + 0x0320: 0x1100, 0x0321: 0x8800, 0x0322: 0x1100, + 0x0324: 0x8800, 0x0325: 0x8800, + 0x032d: 0x1100, 0x032e: 0x1100, 0x032f: 0x1100, + 0x0330: 0x1100, 0x0331: 0x1100, 0x0332: 0x8800, 0x0333: 0x8800, 0x0334: 0x1100, 0x0335: 0x1100, + 0x0336: 0x8800, 0x0337: 0x8800, 0x0338: 0x1100, 0x0339: 0x1100, 0x033a: 0x8800, 0x033b: 0x8800, + 0x033c: 0x8800, 0x033d: 0x8800, // Block 0xd, offset 0x340 - 0x0340: 0x33e6, 0x0341: 0x33e6, 0x0342: 0x66e6, 0x0343: 0x33e6, 0x0344: 0x33e6, 0x0345: 0x66f0, - 0x0346: 0x00e6, 0x0347: 0x00dc, 0x0348: 0x00dc, 0x0349: 0x00dc, 0x034a: 0x00e6, 0x034b: 0x00e6, - 0x034c: 0x00e6, 0x034d: 0x00dc, 0x034e: 0x00dc, 0x0350: 0x00e6, 0x0351: 0x00e6, - 0x0352: 0x00e6, 0x0353: 0x00dc, 0x0354: 0x00dc, 0x0355: 0x00dc, 0x0356: 0x00dc, 0x0357: 0x00e6, - 0x0358: 0x00e8, 0x0359: 0x00dc, 0x035a: 0x00dc, 0x035b: 0x00e6, 0x035c: 0x00e9, 0x035d: 0x00ea, - 0x035e: 0x00ea, 0x035f: 0x00e9, 0x0360: 0x00ea, 0x0361: 0x00ea, 0x0362: 0x00e9, 0x0363: 0x00e6, - 0x0364: 0x00e6, 0x0365: 0x00e6, 0x0366: 0x00e6, 0x0367: 0x00e6, 0x0368: 0x00e6, 0x0369: 0x00e6, - 0x036a: 0x00e6, 0x036b: 0x00e6, 0x036c: 0x00e6, 0x036d: 0x00e6, 0x036e: 0x00e6, 0x036f: 0x00e6, - 0x0374: 0x3300, - 0x037a: 0x3000, - 0x037e: 0x3300, + 0x0346: 0x8800, 0x034b: 0x8800, + 0x034c: 0x1100, 0x034d: 0x8800, 0x034e: 0x1100, 0x034f: 0x8800, 0x0350: 0x1100, 0x0351: 0x8800, + 0x0352: 0x1100, 0x0353: 0x8800, 0x0354: 0x1100, 0x0355: 0x8800, 0x0356: 0x1100, 0x0357: 0x8800, + 0x0358: 0x1100, 0x0359: 0x8800, 0x035a: 0x1100, 0x035b: 0x8800, 0x035c: 0x1100, 0x035d: 0x8800, + 0x035e: 0x1100, 0x035f: 0x8800, 0x0360: 0x1100, 0x0361: 0x8800, 0x0362: 0x1100, + 0x0364: 0x8800, 0x0365: 0x1100, 0x0366: 0x8800, 0x0367: 0x1100, 0x0368: 0x8800, 0x0369: 0x1100, + 0x036f: 0x8800, + 0x0370: 0x1100, 0x0371: 0x1100, 0x0372: 0x8800, 0x0373: 0x1100, 0x0374: 0x1100, 0x0375: 0x8800, + 0x0376: 0x1100, 0x0377: 0x1100, 0x0378: 0x8800, 0x0379: 0x1100, 0x037a: 0x1100, 0x037b: 0x8800, + 0x037c: 0x1100, 0x037d: 0x1100, // Block 0xe, offset 0x380 - 0x0384: 0x3000, 0x0385: 0x3100, - 0x0386: 0x1100, 0x0387: 0x3300, 0x0388: 0x1100, 0x0389: 0x1100, 0x038a: 0x1100, - 0x038c: 0x1100, 0x038e: 0x1100, 0x038f: 0x1100, 0x0390: 0x1100, 0x0391: 0x8800, - 0x0395: 0x8800, 0x0397: 0x8800, - 0x0399: 0x8800, - 0x039f: 0x8800, 0x03a1: 0x8800, - 0x03a5: 0x8800, 0x03a9: 0x8800, - 0x03aa: 0x1100, 0x03ab: 0x1100, 0x03ac: 0x9900, 0x03ad: 0x1100, 0x03ae: 0x9900, 0x03af: 0x1100, - 0x03b0: 0x1100, 0x03b1: 0x8800, 0x03b5: 0x8800, - 0x03b7: 0x8800, 0x03b9: 0x8800, - 0x03bf: 0x8800, + 0x0394: 0x1100, + 0x0399: 0x6608, 0x039a: 0x6608, 0x039b: 0x3000, 0x039c: 0x3000, 0x039d: 0x8800, + 0x039e: 0x1100, 0x039f: 0x3000, + 0x03a6: 0x8800, + 0x03ab: 0x8800, 0x03ac: 0x1100, 0x03ad: 0x8800, 0x03ae: 0x1100, 0x03af: 0x8800, + 0x03b0: 0x1100, 0x03b1: 0x8800, 0x03b2: 0x1100, 0x03b3: 0x8800, 0x03b4: 0x1100, 0x03b5: 0x8800, + 0x03b6: 0x1100, 0x03b7: 0x8800, 0x03b8: 0x1100, 0x03b9: 0x8800, 0x03ba: 0x1100, 0x03bb: 0x8800, + 0x03bc: 0x1100, 0x03bd: 0x8800, 0x03be: 0x1100, 0x03bf: 0x8800, // Block 0xf, offset 0x3c0 - 0x03c1: 0x8800, 0x03c5: 0x8800, - 0x03c9: 0x8800, 0x03ca: 0x9900, 0x03cb: 0x9900, - 0x03cc: 0x1100, 0x03cd: 0x1100, 0x03ce: 0x9900, 0x03d0: 0x3000, 0x03d1: 0x3000, - 0x03d2: 0x3800, 0x03d3: 0x3100, 0x03d4: 0x3100, 0x03d5: 0x3000, 0x03d6: 0x3000, - 0x03f0: 0x3000, 0x03f1: 0x3000, 0x03f2: 0x3000, 0x03f4: 0x3000, 0x03f5: 0x3000, - 0x03f9: 0x3000, - // Block 0x10, offset 0x400 - 0x0400: 0x1100, 0x0401: 0x1100, 0x0403: 0x1100, - 0x0406: 0x8800, 0x0407: 0x1100, - 0x040c: 0x1100, 0x040d: 0x1100, 0x040e: 0x1100, 0x0410: 0x8800, - 0x0413: 0x8800, 0x0415: 0x8800, 0x0416: 0x8800, 0x0417: 0x8800, - 0x0418: 0x8800, 0x0419: 0x1100, 0x041a: 0x8800, - 0x041e: 0x8800, 0x0423: 0x8800, - 0x0427: 0x8800, - 0x042b: 0x8800, 0x042d: 0x8800, - 0x0430: 0x8800, 0x0433: 0x8800, 0x0435: 0x8800, - 0x0436: 0x8800, 0x0437: 0x8800, 0x0438: 0x8800, 0x0439: 0x1100, 0x043a: 0x8800, - 0x043e: 0x8800, - // Block 0x11, offset 0x440 - 0x0443: 0x8800, - 0x0447: 0x8800, 0x044b: 0x8800, - 0x044d: 0x8800, 0x0450: 0x1100, 0x0451: 0x1100, - 0x0453: 0x1100, 0x0456: 0x8800, 0x0457: 0x1100, - 0x045c: 0x1100, 0x045d: 0x1100, - 0x045e: 0x1100, - 0x0474: 0x8800, 0x0475: 0x8800, - 0x0476: 0x1100, 0x0477: 0x1100, - // Block 0x12, offset 0x480 - 0x0483: 0x00e6, 0x0484: 0x00e6, 0x0485: 0x00e6, - 0x0486: 0x00e6, 0x0487: 0x00e6, - // Block 0x13, offset 0x4c0 - 0x04c1: 0x1100, 0x04c2: 0x1100, - 0x04d0: 0x1100, 0x04d1: 0x1100, - 0x04d2: 0x1100, 0x04d3: 0x1100, 0x04d6: 0x1100, 0x04d7: 0x1100, - 0x04d8: 0x8800, 0x04d9: 0x8800, 0x04da: 0x1100, 0x04db: 0x1100, 0x04dc: 0x1100, 0x04dd: 0x1100, - 0x04de: 0x1100, 0x04df: 0x1100, 0x04e2: 0x1100, 0x04e3: 0x1100, - 0x04e4: 0x1100, 0x04e5: 0x1100, 0x04e6: 0x1100, 0x04e7: 0x1100, 0x04e8: 0x8800, 0x04e9: 0x8800, - 0x04ea: 0x1100, 0x04eb: 0x1100, 0x04ec: 0x1100, 0x04ed: 0x1100, 0x04ee: 0x1100, 0x04ef: 0x1100, - 0x04f0: 0x1100, 0x04f1: 0x1100, 0x04f2: 0x1100, 0x04f3: 0x1100, 0x04f4: 0x1100, 0x04f5: 0x1100, - 0x04f8: 0x1100, 0x04f9: 0x1100, - // Block 0x14, offset 0x500 - 0x0507: 0x3000, - 0x0511: 0x00dc, - 0x0512: 0x00e6, 0x0513: 0x00e6, 0x0514: 0x00e6, 0x0515: 0x00e6, 0x0516: 0x00dc, 0x0517: 0x00e6, - 0x0518: 0x00e6, 0x0519: 0x00e6, 0x051a: 0x00de, 0x051b: 0x00dc, 0x051c: 0x00e6, 0x051d: 0x00e6, - 0x051e: 0x00e6, 0x051f: 0x00e6, 0x0520: 0x00e6, 0x0521: 0x00e6, 0x0522: 0x00dc, 0x0523: 0x00dc, - 0x0524: 0x00dc, 0x0525: 0x00dc, 0x0526: 0x00dc, 0x0527: 0x00dc, 0x0528: 0x00e6, 0x0529: 0x00e6, - 0x052a: 0x00dc, 0x052b: 0x00e6, 0x052c: 0x00e6, 0x052d: 0x00de, 0x052e: 0x00e4, 0x052f: 0x00e6, - 0x0530: 0x000a, 0x0531: 0x000b, 0x0532: 0x000c, 0x0533: 0x000d, 0x0534: 0x000e, 0x0535: 0x000f, - 0x0536: 0x0010, 0x0537: 0x0011, 0x0538: 0x0012, 0x0539: 0x0013, 0x053a: 0x0013, 0x053b: 0x0014, - 0x053c: 0x0015, 0x053d: 0x0016, 0x053f: 0x0017, - // Block 0x15, offset 0x540 - 0x0541: 0x0018, 0x0542: 0x0019, 0x0544: 0x00e6, 0x0545: 0x00dc, - 0x0547: 0x0012, - // Block 0x16, offset 0x580 - 0x0590: 0x00e6, 0x0591: 0x00e6, - 0x0592: 0x00e6, 0x0593: 0x00e6, 0x0594: 0x00e6, 0x0595: 0x00e6, 0x0596: 0x00e6, 0x0597: 0x00e6, - 0x0598: 0x001e, 0x0599: 0x001f, 0x059a: 0x0020, - 0x05a2: 0x1100, 0x05a3: 0x1100, - 0x05a4: 0x1100, 0x05a5: 0x1100, 0x05a6: 0x1100, 0x05a7: 0x8800, - // Block 0x17, offset 0x5c0 - 0x05c8: 0x8800, 0x05ca: 0x8800, 0x05cb: 0x001b, - 0x05cc: 0x001c, 0x05cd: 0x001d, 0x05ce: 0x001e, 0x05cf: 0x001f, 0x05d0: 0x0020, 0x05d1: 0x0021, - 0x05d2: 0x0022, 0x05d3: 0x66e6, 0x05d4: 0x66e6, 0x05d5: 0x66dc, 0x05d6: 0x00dc, 0x05d7: 0x00e6, - 0x05d8: 0x00e6, 0x05d9: 0x00e6, 0x05da: 0x00e6, 0x05db: 0x00e6, 0x05dc: 0x00dc, 0x05dd: 0x00e6, - 0x05de: 0x00e6, 0x05df: 0x00dc, - 0x05f0: 0x0023, 0x05f5: 0x3000, - 0x05f6: 0x3000, 0x05f7: 0x3000, 0x05f8: 0x3000, - // Block 0x18, offset 0x600 - 0x0600: 0x1100, 0x0601: 0x8800, 0x0602: 0x1100, - 0x0612: 0x8800, 0x0613: 0x1100, 0x0615: 0x8800, 0x0616: 0x00e6, 0x0617: 0x00e6, - 0x0618: 0x00e6, 0x0619: 0x00e6, 0x061a: 0x00e6, 0x061b: 0x00e6, 0x061c: 0x00e6, - 0x061f: 0x00e6, 0x0620: 0x00e6, 0x0621: 0x00e6, 0x0622: 0x00e6, 0x0623: 0x00dc, - 0x0624: 0x00e6, 0x0627: 0x00e6, 0x0628: 0x00e6, - 0x062a: 0x00dc, 0x062b: 0x00e6, 0x062c: 0x00e6, 0x062d: 0x00dc, - // Block 0x19, offset 0x640 - 0x0651: 0x0024, - 0x0670: 0x00e6, 0x0671: 0x00dc, 0x0672: 0x00e6, 0x0673: 0x00e6, 0x0674: 0x00dc, 0x0675: 0x00e6, - 0x0676: 0x00e6, 0x0677: 0x00dc, 0x0678: 0x00dc, 0x0679: 0x00dc, 0x067a: 0x00e6, 0x067b: 0x00dc, - 0x067c: 0x00dc, 0x067d: 0x00e6, 0x067e: 0x00dc, 0x067f: 0x00e6, - // Block 0x1a, offset 0x680 - 0x0680: 0x00e6, 0x0681: 0x00e6, 0x0682: 0x00dc, 0x0683: 0x00e6, 0x0684: 0x00dc, 0x0685: 0x00e6, - 0x0686: 0x00dc, 0x0687: 0x00e6, 0x0688: 0x00dc, 0x0689: 0x00e6, 0x068a: 0x00e6, - // Block 0x1b, offset 0x6c0 - 0x06eb: 0x00e6, 0x06ec: 0x00e6, 0x06ed: 0x00e6, 0x06ee: 0x00e6, 0x06ef: 0x00e6, - 0x06f0: 0x00e6, 0x06f1: 0x00e6, 0x06f2: 0x00dc, 0x06f3: 0x00e6, - // Block 0x1c, offset 0x700 - 0x0716: 0x00e6, 0x0717: 0x00e6, - 0x0718: 0x00e6, 0x0719: 0x00e6, 0x071b: 0x00e6, 0x071c: 0x00e6, 0x071d: 0x00e6, - 0x071e: 0x00e6, 0x071f: 0x00e6, 0x0720: 0x00e6, 0x0721: 0x00e6, 0x0722: 0x00e6, 0x0723: 0x00e6, - 0x0725: 0x00e6, 0x0726: 0x00e6, 0x0727: 0x00e6, 0x0729: 0x00e6, - 0x072a: 0x00e6, 0x072b: 0x00e6, 0x072c: 0x00e6, 0x072d: 0x00e6, - // Block 0x1d, offset 0x740 - 0x0759: 0x00dc, 0x075a: 0x00dc, 0x075b: 0x00dc, - // Block 0x1e, offset 0x780 - 0x07a8: 0x8800, 0x07a9: 0x1100, - 0x07b0: 0x8800, 0x07b1: 0x1100, 0x07b3: 0x8800, 0x07b4: 0x1100, - 0x07bc: 0x6607, - // Block 0x1f, offset 0x7c0 - 0x07cd: 0x0009, 0x07d1: 0x00e6, - 0x07d2: 0x00dc, 0x07d3: 0x00e6, 0x07d4: 0x00e6, - 0x07d8: 0x3300, 0x07d9: 0x3300, 0x07da: 0x3300, 0x07db: 0x3300, 0x07dc: 0x3300, 0x07dd: 0x3300, - 0x07de: 0x3300, 0x07df: 0x3300, - // Block 0x20, offset 0x800 - 0x083c: 0x0007, 0x083e: 0x6600, - // Block 0x21, offset 0x840 - 0x0847: 0x8800, 0x084b: 0x1100, - 0x084c: 0x1100, 0x084d: 0x0009, - 0x0857: 0x6600, - 0x085c: 0x3300, 0x085d: 0x3300, - 0x085f: 0x3300, - // Block 0x22, offset 0x880 - 0x08b3: 0x3300, - 0x08b6: 0x3300, - 0x08bc: 0x0007, - // Block 0x23, offset 0x8c0 - 0x08cd: 0x0009, - 0x08d9: 0x3300, 0x08da: 0x3300, 0x08db: 0x3300, - 0x08de: 0x3300, - // Block 0x24, offset 0x900 - 0x093c: 0x0007, - // Block 0x25, offset 0x940 - 0x094d: 0x0009, - // Block 0x26, offset 0x980 - 0x0987: 0x8800, 0x0988: 0x1100, 0x098b: 0x1100, - 0x098c: 0x1100, 0x098d: 0x0009, - 0x0996: 0x6600, 0x0997: 0x6600, - 0x099c: 0x3300, 0x099d: 0x3300, - // Block 0x27, offset 0x9c0 - 0x09d2: 0x8800, 0x09d4: 0x1100, - 0x09fe: 0x6600, - // Block 0x28, offset 0xa00 - 0x0a06: 0x8800, 0x0a07: 0x8800, 0x0a0a: 0x1100, 0x0a0b: 0x1100, - 0x0a0c: 0x1100, 0x0a0d: 0x0009, - 0x0a17: 0x6600, - // Block 0x29, offset 0xa40 - 0x0a46: 0x8800, 0x0a48: 0x1100, - 0x0a4d: 0x0009, - 0x0a55: 0x0054, 0x0a56: 0x665b, - // Block 0x2a, offset 0xa80 - 0x0abc: 0x0007, 0x0abf: 0x8800, - // Block 0x2b, offset 0xac0 - 0x0ac0: 0x1100, 0x0ac2: 0x6600, - 0x0ac6: 0x8800, 0x0ac7: 0x1100, 0x0ac8: 0x1100, 0x0aca: 0x9900, 0x0acb: 0x1100, - 0x0acd: 0x0009, - 0x0ad5: 0x6600, 0x0ad6: 0x6600, - // Block 0x2c, offset 0xb00 - 0x0b3e: 0x6600, - // Block 0x2d, offset 0xb40 - 0x0b4a: 0x6609, - 0x0b4f: 0x6600, - 0x0b59: 0x8800, 0x0b5a: 0x1100, 0x0b5c: 0x9900, 0x0b5d: 0x1100, - 0x0b5e: 0x1100, 0x0b5f: 0x6600, - // Block 0x2e, offset 0xb80 - 0x0bb3: 0x3000, - 0x0bb8: 0x0067, 0x0bb9: 0x0067, 0x0bba: 0x0009, - // Block 0x2f, offset 0xbc0 - 0x0bc8: 0x006b, 0x0bc9: 0x006b, 0x0bca: 0x006b, 0x0bcb: 0x006b, - // Block 0x30, offset 0xc00 - 0x0c33: 0x3000, - 0x0c38: 0x0076, 0x0c39: 0x0076, - // Block 0x31, offset 0xc40 - 0x0c48: 0x007a, 0x0c49: 0x007a, 0x0c4a: 0x007a, 0x0c4b: 0x007a, - 0x0c5c: 0x3000, 0x0c5d: 0x3000, - // Block 0x32, offset 0xc80 - 0x0c8c: 0x3000, - 0x0c98: 0x00dc, 0x0c99: 0x00dc, - 0x0cb5: 0x00dc, - 0x0cb7: 0x00dc, 0x0cb9: 0x00d8, - // Block 0x33, offset 0xcc0 - 0x0cc3: 0x3300, - 0x0ccd: 0x3300, - 0x0cd2: 0x3300, 0x0cd7: 0x3300, - 0x0cdc: 0x3300, - 0x0ce9: 0x3300, - 0x0cf1: 0x0081, 0x0cf2: 0x0082, 0x0cf3: 0x3300, 0x0cf4: 0x0084, 0x0cf5: 0x3300, - 0x0cf6: 0x3300, 0x0cf7: 0x3000, 0x0cf8: 0x3300, 0x0cf9: 0x3000, 0x0cfa: 0x0082, 0x0cfb: 0x0082, - 0x0cfc: 0x0082, 0x0cfd: 0x0082, - // Block 0x34, offset 0xd00 - 0x0d00: 0x0082, 0x0d01: 0x3300, 0x0d02: 0x00e6, 0x0d03: 0x00e6, 0x0d04: 0x0009, - 0x0d06: 0x00e6, 0x0d07: 0x00e6, - 0x0d13: 0x3300, - 0x0d1d: 0x3300, - 0x0d22: 0x3300, - 0x0d27: 0x3300, - 0x0d2c: 0x3300, - 0x0d39: 0x3300, - // Block 0x35, offset 0xd40 - 0x0d46: 0x00dc, - // Block 0x36, offset 0xd80 - 0x0da5: 0x8800, 0x0da6: 0x1100, - 0x0dae: 0x6600, - 0x0db7: 0x0007, 0x0db9: 0x0009, 0x0dba: 0x0009, - // Block 0x37, offset 0xdc0 - 0x0dcd: 0x00dc, - // Block 0x38, offset 0xe00 - 0x0e3c: 0x3000, - // Block 0x39, offset 0xe40 - 0x0e40: 0x8800, 0x0e41: 0x8800, 0x0e42: 0x8800, 0x0e43: 0x8800, 0x0e44: 0x8800, 0x0e45: 0x8800, - 0x0e46: 0x8800, 0x0e47: 0x8800, 0x0e48: 0x8800, 0x0e49: 0x8800, 0x0e4a: 0x8800, 0x0e4b: 0x8800, - 0x0e4c: 0x8800, 0x0e4d: 0x8800, 0x0e4e: 0x8800, 0x0e4f: 0x8800, 0x0e50: 0x8800, 0x0e51: 0x8800, - 0x0e52: 0x8800, - // Block 0x3a, offset 0xe80 - 0x0ea1: 0xee00, 0x0ea2: 0xee00, 0x0ea3: 0xee00, - 0x0ea4: 0xee00, 0x0ea5: 0xee00, 0x0ea6: 0xee00, 0x0ea7: 0xee00, 0x0ea8: 0xee00, 0x0ea9: 0xee00, - 0x0eaa: 0xee00, 0x0eab: 0xee00, 0x0eac: 0xee00, 0x0ead: 0xee00, 0x0eae: 0xee00, 0x0eaf: 0xee00, - 0x0eb0: 0xee00, 0x0eb1: 0xee00, 0x0eb2: 0xee00, 0x0eb3: 0xee00, 0x0eb4: 0xee00, 0x0eb5: 0xee00, - 0x0eb6: 0xee00, 0x0eb7: 0xee00, 0x0eb8: 0xee00, 0x0eb9: 0xee00, 0x0eba: 0xee00, 0x0ebb: 0xee00, - 0x0ebc: 0xee00, 0x0ebd: 0xee00, 0x0ebe: 0xee00, 0x0ebf: 0xee00, - // Block 0x3b, offset 0xec0 - 0x0ec0: 0xee00, 0x0ec1: 0xee00, 0x0ec2: 0xee00, 0x0ec3: 0xee00, 0x0ec4: 0xee00, 0x0ec5: 0xee00, - 0x0ec6: 0xee00, 0x0ec7: 0xee00, 0x0ec8: 0xee00, 0x0ec9: 0xee00, 0x0eca: 0xee00, 0x0ecb: 0xee00, - 0x0ecc: 0xee00, 0x0ecd: 0xee00, 0x0ece: 0xee00, 0x0ecf: 0xee00, 0x0ed0: 0xee00, 0x0ed1: 0xee00, - 0x0ed2: 0xee00, 0x0ed3: 0xee00, 0x0ed4: 0xee00, 0x0ed5: 0xee00, 0x0ed6: 0xee00, 0x0ed7: 0xee00, - 0x0ed8: 0xee00, 0x0ed9: 0xee00, 0x0eda: 0xee00, 0x0edb: 0xee00, 0x0edc: 0xee00, 0x0edd: 0xee00, - 0x0ede: 0xee00, 0x0edf: 0xee00, 0x0ee0: 0xee00, 0x0ee1: 0xee00, 0x0ee2: 0xee00, 0x0ee3: 0xee00, - 0x0ee4: 0xee00, 0x0ee5: 0xee00, 0x0ee6: 0xee00, 0x0ee7: 0xee00, 0x0ee8: 0xee00, 0x0ee9: 0xee00, - 0x0eea: 0xee00, 0x0eeb: 0xee00, 0x0eec: 0xee00, 0x0eed: 0xee00, 0x0eee: 0xee00, 0x0eef: 0xee00, - 0x0ef0: 0xee00, 0x0ef1: 0xee00, 0x0ef2: 0xee00, 0x0ef3: 0xee00, 0x0ef4: 0xee00, 0x0ef5: 0xee00, - 0x0ef6: 0xee00, 0x0ef7: 0xee00, 0x0ef8: 0xee00, 0x0ef9: 0xee00, 0x0efa: 0xee00, 0x0efb: 0xee00, - 0x0efc: 0xee00, 0x0efd: 0xee00, 0x0efe: 0xee00, 0x0eff: 0xee00, - // Block 0x3c, offset 0xf00 - 0x0f00: 0xee00, 0x0f01: 0xee00, 0x0f02: 0xee00, - // Block 0x3d, offset 0xf40 - 0x0f5d: 0x00e6, - 0x0f5e: 0x00e6, 0x0f5f: 0x00e6, - // Block 0x3e, offset 0xf80 - 0x0f94: 0x0009, - 0x0fb4: 0x0009, - // Block 0x3f, offset 0xfc0 - 0x0fd2: 0x0009, - 0x0fdd: 0x00e6, - // Block 0x40, offset 0x1000 - 0x1029: 0x00e4, - // Block 0x41, offset 0x1040 - 0x1079: 0x00de, 0x107a: 0x00e6, 0x107b: 0x00dc, - // Block 0x42, offset 0x1080 - 0x1097: 0x00e6, - 0x1098: 0x00dc, - // Block 0x43, offset 0x10c0 - 0x10e0: 0x0009, - 0x10f5: 0x00e6, - 0x10f6: 0x00e6, 0x10f7: 0x00e6, 0x10f8: 0x00e6, 0x10f9: 0x00e6, 0x10fa: 0x00e6, 0x10fb: 0x00e6, - 0x10fc: 0x00e6, 0x10ff: 0x00dc, - // Block 0x44, offset 0x1100 - 0x1105: 0x8800, - 0x1106: 0x1100, 0x1107: 0x8800, 0x1108: 0x1100, 0x1109: 0x8800, 0x110a: 0x1100, 0x110b: 0x8800, - 0x110c: 0x1100, 0x110d: 0x8800, 0x110e: 0x1100, 0x1111: 0x8800, - 0x1112: 0x1100, - 0x1134: 0x0007, 0x1135: 0x6600, - 0x113a: 0x8800, 0x113b: 0x1100, - 0x113c: 0x8800, 0x113d: 0x1100, 0x113e: 0x8800, 0x113f: 0x8800, - // Block 0x45, offset 0x1140 - 0x1140: 0x1100, 0x1141: 0x1100, 0x1142: 0x8800, 0x1143: 0x1100, 0x1144: 0x0009, - 0x116b: 0x00e6, 0x116c: 0x00dc, 0x116d: 0x00e6, 0x116e: 0x00e6, 0x116f: 0x00e6, - 0x1170: 0x00e6, 0x1171: 0x00e6, 0x1172: 0x00e6, 0x1173: 0x00e6, - // Block 0x46, offset 0x1180 - 0x11aa: 0x0009, - // Block 0x47, offset 0x11c0 - 0x11e6: 0x0007, - 0x11f2: 0x0009, 0x11f3: 0x0009, - // Block 0x48, offset 0x1200 - 0x1237: 0x0007, - // Block 0x49, offset 0x1240 - 0x1250: 0x00e6, 0x1251: 0x00e6, - 0x1252: 0x00e6, 0x1254: 0x0001, 0x1255: 0x00dc, 0x1256: 0x00dc, 0x1257: 0x00dc, - 0x1258: 0x00dc, 0x1259: 0x00dc, 0x125a: 0x00e6, 0x125b: 0x00e6, 0x125c: 0x00dc, 0x125d: 0x00dc, - 0x125e: 0x00dc, 0x125f: 0x00dc, 0x1260: 0x00e6, 0x1262: 0x0001, 0x1263: 0x0001, - 0x1264: 0x0001, 0x1265: 0x0001, 0x1266: 0x0001, 0x1267: 0x0001, 0x1268: 0x0001, - 0x126d: 0x00dc, - // Block 0x4a, offset 0x1280 - 0x12ac: 0x3000, 0x12ad: 0x3000, 0x12ae: 0x3000, - 0x12b0: 0x3000, 0x12b1: 0x3000, 0x12b2: 0x3000, 0x12b3: 0x3000, 0x12b4: 0x3000, 0x12b5: 0x3000, - 0x12b6: 0x3000, 0x12b7: 0x3000, 0x12b8: 0x3000, 0x12b9: 0x3000, 0x12ba: 0x3000, - 0x12bc: 0x3000, 0x12bd: 0x3000, 0x12be: 0x3000, 0x12bf: 0x3000, - // Block 0x4b, offset 0x12c0 - 0x12c0: 0x3000, 0x12c1: 0x3000, 0x12c2: 0x3000, 0x12c3: 0x3000, 0x12c4: 0x3000, 0x12c5: 0x3000, - 0x12c6: 0x3000, 0x12c7: 0x3000, 0x12c8: 0x3000, 0x12c9: 0x3000, 0x12ca: 0x3000, 0x12cb: 0x3000, - 0x12cc: 0x3000, 0x12cd: 0x3000, 0x12cf: 0x3000, 0x12d0: 0x3000, 0x12d1: 0x3000, - 0x12d2: 0x3000, 0x12d3: 0x3000, 0x12d4: 0x3000, 0x12d5: 0x3000, 0x12d6: 0x3000, 0x12d7: 0x3000, - 0x12d8: 0x3000, 0x12d9: 0x3000, 0x12da: 0x3000, 0x12db: 0x3000, 0x12dc: 0x3000, 0x12dd: 0x3000, - 0x12de: 0x3000, 0x12df: 0x3000, 0x12e0: 0x3000, 0x12e1: 0x3000, 0x12e2: 0x3000, 0x12e3: 0x3000, - 0x12e4: 0x3000, 0x12e5: 0x3000, 0x12e6: 0x3000, 0x12e7: 0x3000, 0x12e8: 0x3000, 0x12e9: 0x3000, - 0x12ea: 0x3000, - 0x12f8: 0x3000, - // Block 0x4c, offset 0x1300 - 0x131b: 0x3000, 0x131c: 0x3000, 0x131d: 0x3000, - 0x131e: 0x3000, 0x131f: 0x3000, 0x1320: 0x3000, 0x1321: 0x3000, 0x1322: 0x3000, 0x1323: 0x3000, - 0x1324: 0x3000, 0x1325: 0x3000, 0x1326: 0x3000, 0x1327: 0x3000, 0x1328: 0x3000, 0x1329: 0x3000, - 0x132a: 0x3000, 0x132b: 0x3000, 0x132c: 0x3000, 0x132d: 0x3000, 0x132e: 0x3000, 0x132f: 0x3000, - 0x1330: 0x3000, 0x1331: 0x3000, 0x1332: 0x3000, 0x1333: 0x3000, 0x1334: 0x3000, 0x1335: 0x3000, - 0x1336: 0x3000, 0x1337: 0x3000, 0x1338: 0x3000, 0x1339: 0x3000, 0x133a: 0x3000, 0x133b: 0x3000, - 0x133c: 0x3000, 0x133d: 0x3000, 0x133e: 0x3000, 0x133f: 0x3000, - // Block 0x4d, offset 0x1340 - 0x1340: 0x00e6, 0x1341: 0x00e6, 0x1342: 0x00dc, 0x1343: 0x00e6, 0x1344: 0x00e6, 0x1345: 0x00e6, - 0x1346: 0x00e6, 0x1347: 0x00e6, 0x1348: 0x00e6, 0x1349: 0x00e6, 0x134a: 0x00dc, 0x134b: 0x00e6, - 0x134c: 0x00e6, 0x134d: 0x00ea, 0x134e: 0x00d6, 0x134f: 0x00dc, 0x1350: 0x00ca, 0x1351: 0x00e6, - 0x1352: 0x00e6, 0x1353: 0x00e6, 0x1354: 0x00e6, 0x1355: 0x00e6, 0x1356: 0x00e6, 0x1357: 0x00e6, - 0x1358: 0x00e6, 0x1359: 0x00e6, 0x135a: 0x00e6, 0x135b: 0x00e6, 0x135c: 0x00e6, 0x135d: 0x00e6, - 0x135e: 0x00e6, 0x135f: 0x00e6, 0x1360: 0x00e6, 0x1361: 0x00e6, 0x1362: 0x00e6, 0x1363: 0x00e6, - 0x1364: 0x00e6, 0x1365: 0x00e6, 0x1366: 0x00e6, - 0x137c: 0x00e9, 0x137d: 0x00dc, 0x137e: 0x00e6, 0x137f: 0x00dc, - // Block 0x4e, offset 0x1380 - 0x1380: 0x1100, 0x1381: 0x1100, 0x1382: 0x1100, 0x1383: 0x1100, 0x1384: 0x1100, 0x1385: 0x1100, - 0x1386: 0x1100, 0x1387: 0x1100, 0x1388: 0x1100, 0x1389: 0x1100, 0x138a: 0x1100, 0x138b: 0x1100, - 0x138c: 0x1100, 0x138d: 0x1100, 0x138e: 0x1100, 0x138f: 0x1100, 0x1390: 0x1100, 0x1391: 0x1100, - 0x1392: 0x1100, 0x1393: 0x1100, 0x1394: 0x1100, 0x1395: 0x1100, 0x1396: 0x1100, 0x1397: 0x1100, - 0x1398: 0x1100, 0x1399: 0x1100, 0x139a: 0x1100, 0x139b: 0x1100, 0x139c: 0x1100, 0x139d: 0x1100, - 0x139e: 0x1100, 0x139f: 0x1100, 0x13a0: 0x1100, 0x13a1: 0x1100, 0x13a2: 0x1100, 0x13a3: 0x1100, - 0x13a4: 0x1100, 0x13a5: 0x1100, 0x13a6: 0x1100, 0x13a7: 0x1100, 0x13a8: 0x1100, 0x13a9: 0x1100, - 0x13aa: 0x1100, 0x13ab: 0x1100, 0x13ac: 0x1100, 0x13ad: 0x1100, 0x13ae: 0x1100, 0x13af: 0x1100, - 0x13b0: 0x1100, 0x13b1: 0x1100, 0x13b2: 0x1100, 0x13b3: 0x1100, 0x13b4: 0x1100, 0x13b5: 0x1100, - 0x13b6: 0x9900, 0x13b7: 0x9900, 0x13b8: 0x1100, 0x13b9: 0x1100, 0x13ba: 0x1100, 0x13bb: 0x1100, - 0x13bc: 0x1100, 0x13bd: 0x1100, 0x13be: 0x1100, 0x13bf: 0x1100, - // Block 0x4f, offset 0x13c0 - 0x13c0: 0x1100, 0x13c1: 0x1100, 0x13c2: 0x1100, 0x13c3: 0x1100, 0x13c4: 0x1100, 0x13c5: 0x1100, - 0x13c6: 0x1100, 0x13c7: 0x1100, 0x13c8: 0x1100, 0x13c9: 0x1100, 0x13ca: 0x1100, 0x13cb: 0x1100, - 0x13cc: 0x1100, 0x13cd: 0x1100, 0x13ce: 0x1100, 0x13cf: 0x1100, 0x13d0: 0x1100, 0x13d1: 0x1100, - 0x13d2: 0x1100, 0x13d3: 0x1100, 0x13d4: 0x1100, 0x13d5: 0x1100, 0x13d6: 0x1100, 0x13d7: 0x1100, - 0x13d8: 0x1100, 0x13d9: 0x1100, 0x13da: 0x9900, 0x13db: 0x9900, 0x13dc: 0x1100, 0x13dd: 0x1100, - 0x13de: 0x1100, 0x13df: 0x1100, 0x13e0: 0x1100, 0x13e1: 0x1100, 0x13e2: 0x9900, 0x13e3: 0x9900, - 0x13e4: 0x1100, 0x13e5: 0x1100, 0x13e6: 0x1100, 0x13e7: 0x1100, 0x13e8: 0x1100, 0x13e9: 0x1100, - 0x13ea: 0x1100, 0x13eb: 0x1100, 0x13ec: 0x1100, 0x13ed: 0x1100, 0x13ee: 0x1100, 0x13ef: 0x1100, - 0x13f0: 0x1100, 0x13f1: 0x1100, 0x13f2: 0x1100, 0x13f3: 0x1100, 0x13f4: 0x1100, 0x13f5: 0x1100, - 0x13f6: 0x1100, 0x13f7: 0x1100, 0x13f8: 0x1100, 0x13f9: 0x1100, 0x13fa: 0x1100, 0x13fb: 0x1100, - 0x13fc: 0x1100, 0x13fd: 0x1100, 0x13fe: 0x1100, 0x13ff: 0x1100, - // Block 0x50, offset 0x1400 - 0x1400: 0x1100, 0x1401: 0x1100, 0x1402: 0x1100, 0x1403: 0x1100, 0x1404: 0x1100, 0x1405: 0x1100, - 0x1406: 0x1100, 0x1407: 0x1100, 0x1408: 0x1100, 0x1409: 0x1100, 0x140a: 0x1100, 0x140b: 0x1100, - 0x140c: 0x1100, 0x140d: 0x1100, 0x140e: 0x1100, 0x140f: 0x1100, 0x1410: 0x1100, 0x1411: 0x1100, - 0x1412: 0x1100, 0x1413: 0x1100, 0x1414: 0x1100, 0x1415: 0x1100, 0x1416: 0x1100, 0x1417: 0x1100, - 0x1418: 0x1100, 0x1419: 0x1100, 0x141a: 0x3000, 0x141b: 0x3100, - 0x1420: 0x9900, 0x1421: 0x9900, 0x1422: 0x1100, 0x1423: 0x1100, - 0x1424: 0x1100, 0x1425: 0x1100, 0x1426: 0x1100, 0x1427: 0x1100, 0x1428: 0x1100, 0x1429: 0x1100, - 0x142a: 0x1100, 0x142b: 0x1100, 0x142c: 0x1100, 0x142d: 0x1100, 0x142e: 0x1100, 0x142f: 0x1100, - 0x1430: 0x1100, 0x1431: 0x1100, 0x1432: 0x1100, 0x1433: 0x1100, 0x1434: 0x1100, 0x1435: 0x1100, - 0x1436: 0x1100, 0x1437: 0x1100, 0x1438: 0x9900, 0x1439: 0x9900, 0x143a: 0x1100, 0x143b: 0x1100, - 0x143c: 0x1100, 0x143d: 0x1100, 0x143e: 0x1100, 0x143f: 0x1100, - // Block 0x51, offset 0x1440 - 0x1440: 0x1100, 0x1441: 0x1100, 0x1442: 0x1100, 0x1443: 0x1100, 0x1444: 0x1100, 0x1445: 0x1100, - 0x1446: 0x1100, 0x1447: 0x1100, 0x1448: 0x1100, 0x1449: 0x1100, 0x144a: 0x1100, 0x144b: 0x1100, - 0x144c: 0x9900, 0x144d: 0x9900, 0x144e: 0x1100, 0x144f: 0x1100, 0x1450: 0x1100, 0x1451: 0x1100, - 0x1452: 0x1100, 0x1453: 0x1100, 0x1454: 0x1100, 0x1455: 0x1100, 0x1456: 0x1100, 0x1457: 0x1100, - 0x1458: 0x1100, 0x1459: 0x1100, 0x145a: 0x1100, 0x145b: 0x1100, 0x145c: 0x1100, 0x145d: 0x1100, - 0x145e: 0x1100, 0x145f: 0x1100, 0x1460: 0x1100, 0x1461: 0x1100, 0x1462: 0x1100, 0x1463: 0x1100, - 0x1464: 0x1100, 0x1465: 0x1100, 0x1466: 0x1100, 0x1467: 0x1100, 0x1468: 0x1100, 0x1469: 0x1100, - 0x146a: 0x1100, 0x146b: 0x1100, 0x146c: 0x1100, 0x146d: 0x1100, 0x146e: 0x1100, 0x146f: 0x1100, - 0x1470: 0x1100, 0x1471: 0x1100, 0x1472: 0x1100, 0x1473: 0x1100, 0x1474: 0x1100, 0x1475: 0x1100, - 0x1476: 0x1100, 0x1477: 0x1100, 0x1478: 0x1100, 0x1479: 0x1100, - // Block 0x52, offset 0x1480 - 0x1480: 0x9900, 0x1481: 0x9900, 0x1482: 0x9900, 0x1483: 0x9900, 0x1484: 0x9900, 0x1485: 0x9900, - 0x1486: 0x9900, 0x1487: 0x9900, 0x1488: 0x9900, 0x1489: 0x9900, 0x148a: 0x9900, 0x148b: 0x9900, - 0x148c: 0x9900, 0x148d: 0x9900, 0x148e: 0x9900, 0x148f: 0x9900, 0x1490: 0x9900, 0x1491: 0x9900, - 0x1492: 0x1100, 0x1493: 0x1100, 0x1494: 0x1100, 0x1495: 0x1100, - 0x1498: 0x9900, 0x1499: 0x9900, 0x149a: 0x1100, 0x149b: 0x1100, 0x149c: 0x1100, 0x149d: 0x1100, - 0x14a0: 0x9900, 0x14a1: 0x9900, 0x14a2: 0x9900, 0x14a3: 0x9900, - 0x14a4: 0x9900, 0x14a5: 0x9900, 0x14a6: 0x9900, 0x14a7: 0x9900, 0x14a8: 0x9900, 0x14a9: 0x9900, - 0x14aa: 0x9900, 0x14ab: 0x9900, 0x14ac: 0x9900, 0x14ad: 0x9900, 0x14ae: 0x9900, 0x14af: 0x9900, - 0x14b0: 0x9900, 0x14b1: 0x9900, 0x14b2: 0x1100, 0x14b3: 0x1100, 0x14b4: 0x1100, 0x14b5: 0x1100, - 0x14b6: 0x1100, 0x14b7: 0x1100, 0x14b8: 0x9900, 0x14b9: 0x9900, 0x14ba: 0x1100, 0x14bb: 0x1100, - 0x14bc: 0x1100, 0x14bd: 0x1100, 0x14be: 0x1100, 0x14bf: 0x1100, - // Block 0x53, offset 0x14c0 - 0x14c0: 0x9900, 0x14c1: 0x9900, 0x14c2: 0x1100, 0x14c3: 0x1100, 0x14c4: 0x1100, 0x14c5: 0x1100, - 0x14c8: 0x9900, 0x14c9: 0x9900, 0x14ca: 0x1100, 0x14cb: 0x1100, - 0x14cc: 0x1100, 0x14cd: 0x1100, 0x14d0: 0x9900, 0x14d1: 0x9900, - 0x14d2: 0x1100, 0x14d3: 0x1100, 0x14d4: 0x1100, 0x14d5: 0x1100, 0x14d6: 0x1100, 0x14d7: 0x1100, - 0x14d9: 0x9900, 0x14db: 0x1100, 0x14dd: 0x1100, - 0x14df: 0x1100, 0x14e0: 0x9900, 0x14e1: 0x9900, 0x14e2: 0x9900, 0x14e3: 0x9900, - 0x14e4: 0x9900, 0x14e5: 0x9900, 0x14e6: 0x9900, 0x14e7: 0x9900, 0x14e8: 0x9900, 0x14e9: 0x9900, - 0x14ea: 0x9900, 0x14eb: 0x9900, 0x14ec: 0x9900, 0x14ed: 0x9900, 0x14ee: 0x9900, 0x14ef: 0x9900, - 0x14f0: 0x9900, 0x14f1: 0x3300, 0x14f2: 0x1100, 0x14f3: 0x3300, 0x14f4: 0x9900, 0x14f5: 0x3300, - 0x14f6: 0x1100, 0x14f7: 0x3300, 0x14f8: 0x1100, 0x14f9: 0x3300, 0x14fa: 0x1100, 0x14fb: 0x3300, - 0x14fc: 0x9900, 0x14fd: 0x3300, - // Block 0x54, offset 0x1500 - 0x1500: 0x1100, 0x1501: 0x1100, 0x1502: 0x1100, 0x1503: 0x1100, 0x1504: 0x1100, 0x1505: 0x1100, - 0x1506: 0x1100, 0x1507: 0x1100, 0x1508: 0x1100, 0x1509: 0x1100, 0x150a: 0x1100, 0x150b: 0x1100, - 0x150c: 0x1100, 0x150d: 0x1100, 0x150e: 0x1100, 0x150f: 0x1100, 0x1510: 0x1100, 0x1511: 0x1100, - 0x1512: 0x1100, 0x1513: 0x1100, 0x1514: 0x1100, 0x1515: 0x1100, 0x1516: 0x1100, 0x1517: 0x1100, - 0x1518: 0x1100, 0x1519: 0x1100, 0x151a: 0x1100, 0x151b: 0x1100, 0x151c: 0x1100, 0x151d: 0x1100, - 0x151e: 0x1100, 0x151f: 0x1100, 0x1520: 0x1100, 0x1521: 0x1100, 0x1522: 0x1100, 0x1523: 0x1100, - 0x1524: 0x1100, 0x1525: 0x1100, 0x1526: 0x1100, 0x1527: 0x1100, 0x1528: 0x1100, 0x1529: 0x1100, - 0x152a: 0x1100, 0x152b: 0x1100, 0x152c: 0x1100, 0x152d: 0x1100, 0x152e: 0x1100, 0x152f: 0x1100, - 0x1530: 0x1100, 0x1531: 0x1100, 0x1532: 0x1100, 0x1533: 0x1100, 0x1534: 0x1100, - 0x1536: 0x9900, 0x1537: 0x1100, 0x1538: 0x1100, 0x1539: 0x1100, 0x153a: 0x1100, 0x153b: 0x3300, - 0x153c: 0x1100, 0x153d: 0x3000, 0x153e: 0x3300, 0x153f: 0x3800, - // Block 0x55, offset 0x1540 - 0x1540: 0x3000, 0x1541: 0x3100, 0x1542: 0x1100, 0x1543: 0x1100, 0x1544: 0x1100, - 0x1546: 0x9900, 0x1547: 0x1100, 0x1548: 0x1100, 0x1549: 0x3300, 0x154a: 0x1100, 0x154b: 0x3300, - 0x154c: 0x1100, 0x154d: 0x3100, 0x154e: 0x3100, 0x154f: 0x3100, 0x1550: 0x1100, 0x1551: 0x1100, - 0x1552: 0x1100, 0x1553: 0x3300, 0x1556: 0x1100, 0x1557: 0x1100, - 0x1558: 0x1100, 0x1559: 0x1100, 0x155a: 0x1100, 0x155b: 0x3300, 0x155d: 0x3100, - 0x155e: 0x3100, 0x155f: 0x3100, 0x1560: 0x1100, 0x1561: 0x1100, 0x1562: 0x1100, 0x1563: 0x3300, - 0x1564: 0x1100, 0x1565: 0x1100, 0x1566: 0x1100, 0x1567: 0x1100, 0x1568: 0x1100, 0x1569: 0x1100, - 0x156a: 0x1100, 0x156b: 0x3300, 0x156c: 0x1100, 0x156d: 0x3100, 0x156e: 0x3300, 0x156f: 0x3300, - 0x1572: 0x1100, 0x1573: 0x1100, 0x1574: 0x1100, - 0x1576: 0x9900, 0x1577: 0x1100, 0x1578: 0x1100, 0x1579: 0x3300, 0x157a: 0x1100, 0x157b: 0x3300, - 0x157c: 0x1100, 0x157d: 0x3300, 0x157e: 0x3800, - // Block 0x56, offset 0x1580 - 0x1580: 0x3300, 0x1581: 0x3300, 0x1582: 0x3000, 0x1583: 0x3000, 0x1584: 0x3000, 0x1585: 0x3000, - 0x1586: 0x3000, 0x1587: 0x3000, 0x1588: 0x3000, 0x1589: 0x3000, 0x158a: 0x3000, - 0x1591: 0x3000, - 0x1597: 0x3000, - 0x15a4: 0x3000, 0x15a5: 0x3000, 0x15a6: 0x3000, - 0x15af: 0x3000, - 0x15b3: 0x3000, 0x15b4: 0x3000, - 0x15b6: 0x3000, 0x15b7: 0x3000, - 0x15bc: 0x3000, 0x15be: 0x3000, - // Block 0x57, offset 0x15c0 - 0x15c7: 0x3000, 0x15c8: 0x3000, 0x15c9: 0x3000, - 0x15d7: 0x3000, - 0x15df: 0x3000, - 0x15f0: 0x3000, 0x15f1: 0x3000, 0x15f4: 0x3000, 0x15f5: 0x3000, - 0x15f6: 0x3000, 0x15f7: 0x3000, 0x15f8: 0x3000, 0x15f9: 0x3000, 0x15fa: 0x3000, 0x15fb: 0x3000, - 0x15fc: 0x3000, 0x15fd: 0x3000, 0x15fe: 0x3000, 0x15ff: 0x3000, - // Block 0x58, offset 0x1600 - 0x1600: 0x3000, 0x1601: 0x3000, 0x1602: 0x3000, 0x1603: 0x3000, 0x1604: 0x3000, 0x1605: 0x3000, - 0x1606: 0x3000, 0x1607: 0x3000, 0x1608: 0x3000, 0x1609: 0x3000, 0x160a: 0x3000, 0x160b: 0x3000, - 0x160c: 0x3000, 0x160d: 0x3000, 0x160e: 0x3000, 0x1610: 0x3000, 0x1611: 0x3000, - 0x1612: 0x3000, 0x1613: 0x3000, 0x1614: 0x3000, 0x1615: 0x3000, 0x1616: 0x3000, 0x1617: 0x3000, - 0x1618: 0x3000, 0x1619: 0x3000, 0x161a: 0x3000, 0x161b: 0x3000, 0x161c: 0x3000, - 0x1628: 0x3000, - // Block 0x59, offset 0x1640 - 0x1650: 0x00e6, 0x1651: 0x00e6, - 0x1652: 0x0001, 0x1653: 0x0001, 0x1654: 0x00e6, 0x1655: 0x00e6, 0x1656: 0x00e6, 0x1657: 0x00e6, - 0x1658: 0x0001, 0x1659: 0x0001, 0x165a: 0x0001, 0x165b: 0x00e6, 0x165c: 0x00e6, - 0x1661: 0x00e6, - 0x1665: 0x0001, 0x1666: 0x0001, 0x1667: 0x00e6, 0x1668: 0x00dc, 0x1669: 0x00e6, - 0x166a: 0x0001, 0x166b: 0x0001, 0x166c: 0x00dc, 0x166d: 0x00dc, 0x166e: 0x00dc, 0x166f: 0x00dc, - 0x1670: 0x00e6, - // Block 0x5a, offset 0x1680 - 0x1680: 0x3000, 0x1681: 0x3000, 0x1682: 0x3000, 0x1683: 0x3000, 0x1685: 0x3000, - 0x1686: 0x3000, 0x1687: 0x3000, 0x1689: 0x3000, 0x168a: 0x3000, 0x168b: 0x3000, - 0x168c: 0x3000, 0x168d: 0x3000, 0x168e: 0x3000, 0x168f: 0x3000, 0x1690: 0x3000, 0x1691: 0x3000, - 0x1692: 0x3000, 0x1693: 0x3000, 0x1695: 0x3000, 0x1696: 0x3000, - 0x1699: 0x3000, 0x169a: 0x3000, 0x169b: 0x3000, 0x169c: 0x3000, 0x169d: 0x3000, - 0x16a0: 0x3000, 0x16a1: 0x3000, 0x16a2: 0x3000, - 0x16a4: 0x3000, 0x16a6: 0x3300, 0x16a8: 0x3000, - 0x16aa: 0x3300, 0x16ab: 0x3300, 0x16ac: 0x3000, 0x16ad: 0x3000, 0x16af: 0x3000, - 0x16b0: 0x3000, 0x16b1: 0x3000, 0x16b3: 0x3000, 0x16b4: 0x3000, 0x16b5: 0x3000, - 0x16b6: 0x3000, 0x16b7: 0x3000, 0x16b8: 0x3000, 0x16b9: 0x3000, 0x16bb: 0x3000, - 0x16bc: 0x3000, 0x16bd: 0x3000, 0x16be: 0x3000, 0x16bf: 0x3000, - // Block 0x5b, offset 0x16c0 - 0x16c0: 0x3000, 0x16c5: 0x3000, - 0x16c6: 0x3000, 0x16c7: 0x3000, 0x16c8: 0x3000, 0x16c9: 0x3000, - 0x16d0: 0x3000, 0x16d1: 0x3000, - 0x16d2: 0x3000, 0x16d3: 0x3000, 0x16d4: 0x3000, 0x16d5: 0x3000, 0x16d6: 0x3000, 0x16d7: 0x3000, - 0x16d8: 0x3000, 0x16d9: 0x3000, 0x16da: 0x3000, 0x16db: 0x3000, 0x16dc: 0x3000, 0x16dd: 0x3000, - 0x16de: 0x3000, 0x16df: 0x3000, 0x16e0: 0x3000, 0x16e1: 0x3000, 0x16e2: 0x3000, 0x16e3: 0x3000, - 0x16e4: 0x3000, 0x16e5: 0x3000, 0x16e6: 0x3000, 0x16e7: 0x3000, 0x16e8: 0x3000, 0x16e9: 0x3000, - 0x16ea: 0x3000, 0x16eb: 0x3000, 0x16ec: 0x3000, 0x16ed: 0x3000, 0x16ee: 0x3000, 0x16ef: 0x3000, - 0x16f0: 0x3000, 0x16f1: 0x3000, 0x16f2: 0x3000, 0x16f3: 0x3000, 0x16f4: 0x3000, 0x16f5: 0x3000, - 0x16f6: 0x3000, 0x16f7: 0x3000, 0x16f8: 0x3000, 0x16f9: 0x3000, 0x16fa: 0x3000, 0x16fb: 0x3000, - 0x16fc: 0x3000, 0x16fd: 0x3000, 0x16fe: 0x3000, 0x16ff: 0x3000, - // Block 0x5c, offset 0x1700 - 0x1709: 0x3000, - 0x1710: 0x8800, - 0x1712: 0x8800, 0x1714: 0x8800, - 0x171a: 0x1100, 0x171b: 0x1100, - 0x172e: 0x1100, - // Block 0x5d, offset 0x1740 - 0x174d: 0x1100, 0x174e: 0x1100, 0x174f: 0x1100, 0x1750: 0x8800, - 0x1752: 0x8800, 0x1754: 0x8800, - // Block 0x5e, offset 0x1780 - 0x1783: 0x8800, 0x1784: 0x1100, - 0x1788: 0x8800, 0x1789: 0x1100, 0x178b: 0x8800, - 0x178c: 0x1100, - 0x17a3: 0x8800, - 0x17a4: 0x1100, 0x17a5: 0x8800, 0x17a6: 0x1100, - 0x17ac: 0x3000, 0x17ad: 0x3000, 0x17af: 0x3000, - 0x17b0: 0x3000, - 0x17bc: 0x8800, - // Block 0x5f, offset 0x17c0 - 0x17c1: 0x1100, 0x17c3: 0x8800, 0x17c4: 0x1100, 0x17c5: 0x8800, - 0x17c7: 0x1100, 0x17c8: 0x8800, 0x17c9: 0x1100, - 0x17cd: 0x8800, - 0x17e0: 0x1100, 0x17e1: 0x8800, 0x17e2: 0x1100, - 0x17e4: 0x8800, 0x17e5: 0x8800, - 0x17ed: 0x1100, 0x17ee: 0x1100, 0x17ef: 0x1100, - 0x17f0: 0x1100, 0x17f1: 0x1100, 0x17f2: 0x8800, 0x17f3: 0x8800, 0x17f4: 0x1100, 0x17f5: 0x1100, - 0x17f6: 0x8800, 0x17f7: 0x8800, 0x17f8: 0x1100, 0x17f9: 0x1100, 0x17fa: 0x8800, 0x17fb: 0x8800, - 0x17fc: 0x8800, 0x17fd: 0x8800, - // Block 0x60, offset 0x1800 - 0x1800: 0x1100, 0x1801: 0x1100, 0x1802: 0x8800, 0x1803: 0x8800, 0x1804: 0x1100, 0x1805: 0x1100, - 0x1806: 0x8800, 0x1807: 0x8800, 0x1808: 0x1100, 0x1809: 0x1100, - 0x1811: 0x8800, - 0x1812: 0x8800, - 0x1822: 0x8800, - 0x1828: 0x8800, 0x1829: 0x8800, - 0x182b: 0x8800, 0x182c: 0x1100, 0x182d: 0x1100, 0x182e: 0x1100, 0x182f: 0x1100, - 0x1832: 0x8800, 0x1833: 0x8800, 0x1834: 0x8800, 0x1835: 0x8800, - // Block 0x61, offset 0x1840 - 0x1860: 0x1100, 0x1861: 0x1100, 0x1862: 0x1100, 0x1863: 0x1100, - 0x186a: 0x1100, 0x186b: 0x1100, 0x186c: 0x1100, 0x186d: 0x1100, - // Block 0x62, offset 0x1880 - 0x18a9: 0x3300, - 0x18aa: 0x3300, - // Block 0x63, offset 0x18c0 - 0x18e0: 0x3000, 0x18e1: 0x3000, 0x18e2: 0x3000, 0x18e3: 0x3000, - 0x18e4: 0x3000, 0x18e5: 0x3000, 0x18e6: 0x3000, 0x18e7: 0x3000, 0x18e8: 0x3000, 0x18e9: 0x3000, - 0x18ea: 0x3000, 0x18eb: 0x3000, 0x18ec: 0x3000, 0x18ed: 0x3000, 0x18ee: 0x3000, 0x18ef: 0x3000, - 0x18f0: 0x3000, 0x18f1: 0x3000, 0x18f2: 0x3000, 0x18f3: 0x3000, 0x18f4: 0x3000, 0x18f5: 0x3000, - 0x18f6: 0x3000, 0x18f7: 0x3000, 0x18f8: 0x3000, 0x18f9: 0x3000, 0x18fa: 0x3000, 0x18fb: 0x3000, - 0x18fc: 0x3000, 0x18fd: 0x3000, 0x18fe: 0x3000, 0x18ff: 0x3000, - // Block 0x64, offset 0x1900 - 0x1900: 0x3000, 0x1901: 0x3000, 0x1902: 0x3000, 0x1903: 0x3000, 0x1904: 0x3000, 0x1905: 0x3000, - 0x1906: 0x3000, 0x1907: 0x3000, 0x1908: 0x3000, 0x1909: 0x3000, 0x190a: 0x3000, 0x190b: 0x3000, - 0x190c: 0x3000, 0x190d: 0x3000, 0x190e: 0x3000, 0x190f: 0x3000, 0x1910: 0x3000, 0x1911: 0x3000, - 0x1912: 0x3000, 0x1913: 0x3000, 0x1914: 0x3000, 0x1915: 0x3000, 0x1916: 0x3000, 0x1917: 0x3000, - 0x1918: 0x3000, 0x1919: 0x3000, 0x191a: 0x3000, 0x191b: 0x3000, 0x191c: 0x3000, 0x191d: 0x3000, - 0x191e: 0x3000, 0x191f: 0x3000, 0x1920: 0x3000, 0x1921: 0x3000, 0x1922: 0x3000, 0x1923: 0x3000, - 0x1924: 0x3000, 0x1925: 0x3000, 0x1926: 0x3000, 0x1927: 0x3000, 0x1928: 0x3000, 0x1929: 0x3000, - 0x192a: 0x3000, 0x192b: 0x3000, 0x192c: 0x3000, 0x192d: 0x3000, 0x192e: 0x3000, 0x192f: 0x3000, - 0x1930: 0x3000, 0x1931: 0x3000, 0x1932: 0x3000, 0x1933: 0x3000, 0x1934: 0x3000, 0x1935: 0x3000, - 0x1936: 0x3000, 0x1937: 0x3000, 0x1938: 0x3000, 0x1939: 0x3000, 0x193a: 0x3000, 0x193b: 0x3000, - 0x193c: 0x3000, 0x193d: 0x3000, 0x193e: 0x3000, 0x193f: 0x3000, - // Block 0x65, offset 0x1940 - 0x1940: 0x3000, 0x1941: 0x3000, 0x1942: 0x3000, 0x1943: 0x3000, 0x1944: 0x3000, 0x1945: 0x3000, - 0x1946: 0x3000, 0x1947: 0x3000, 0x1948: 0x3000, 0x1949: 0x3000, 0x194a: 0x3000, 0x194b: 0x3000, - 0x194c: 0x3000, 0x194d: 0x3000, 0x194e: 0x3000, 0x194f: 0x3000, 0x1950: 0x3000, 0x1951: 0x3000, - 0x1952: 0x3000, 0x1953: 0x3000, 0x1954: 0x3000, 0x1955: 0x3000, 0x1956: 0x3000, 0x1957: 0x3000, - 0x1958: 0x3000, 0x1959: 0x3000, 0x195a: 0x3000, 0x195b: 0x3000, 0x195c: 0x3000, 0x195d: 0x3000, - 0x195e: 0x3000, 0x195f: 0x3000, 0x1960: 0x3000, 0x1961: 0x3000, 0x1962: 0x3000, 0x1963: 0x3000, - 0x1964: 0x3000, 0x1965: 0x3000, 0x1966: 0x3000, 0x1967: 0x3000, 0x1968: 0x3000, 0x1969: 0x3000, - 0x196a: 0x3000, - // Block 0x66, offset 0x1980 - 0x198c: 0x3000, - // Block 0x67, offset 0x19c0 - 0x19f4: 0x3000, 0x19f5: 0x3000, - 0x19f6: 0x3000, - // Block 0x68, offset 0x1a00 - 0x1a1c: 0x3300, - // Block 0x69, offset 0x1a40 - 0x1a7c: 0x3000, 0x1a7d: 0x3000, - // Block 0x6a, offset 0x1a80 - 0x1aaf: 0x00e6, - 0x1ab0: 0x00e6, 0x1ab1: 0x00e6, - // Block 0x6b, offset 0x1ac0 - 0x1aef: 0x3000, - 0x1aff: 0x0009, - // Block 0x6c, offset 0x1b00 - 0x1b20: 0x00e6, 0x1b21: 0x00e6, 0x1b22: 0x00e6, 0x1b23: 0x00e6, - 0x1b24: 0x00e6, 0x1b25: 0x00e6, 0x1b26: 0x00e6, 0x1b27: 0x00e6, 0x1b28: 0x00e6, 0x1b29: 0x00e6, - 0x1b2a: 0x00e6, 0x1b2b: 0x00e6, 0x1b2c: 0x00e6, 0x1b2d: 0x00e6, 0x1b2e: 0x00e6, 0x1b2f: 0x00e6, - 0x1b30: 0x00e6, 0x1b31: 0x00e6, 0x1b32: 0x00e6, 0x1b33: 0x00e6, 0x1b34: 0x00e6, 0x1b35: 0x00e6, - 0x1b36: 0x00e6, 0x1b37: 0x00e6, 0x1b38: 0x00e6, 0x1b39: 0x00e6, 0x1b3a: 0x00e6, 0x1b3b: 0x00e6, - 0x1b3c: 0x00e6, 0x1b3d: 0x00e6, 0x1b3e: 0x00e6, 0x1b3f: 0x00e6, - // Block 0x6d, offset 0x1b40 - 0x1b5f: 0x3000, - // Block 0x6e, offset 0x1b80 - 0x1bb3: 0x3000, - // Block 0x6f, offset 0x1bc0 - 0x1bc0: 0x3000, 0x1bc1: 0x3000, 0x1bc2: 0x3000, 0x1bc3: 0x3000, 0x1bc4: 0x3000, 0x1bc5: 0x3000, - 0x1bc6: 0x3000, 0x1bc7: 0x3000, 0x1bc8: 0x3000, 0x1bc9: 0x3000, 0x1bca: 0x3000, 0x1bcb: 0x3000, - 0x1bcc: 0x3000, 0x1bcd: 0x3000, 0x1bce: 0x3000, 0x1bcf: 0x3000, 0x1bd0: 0x3000, 0x1bd1: 0x3000, - 0x1bd2: 0x3000, 0x1bd3: 0x3000, 0x1bd4: 0x3000, 0x1bd5: 0x3000, - // Block 0x70, offset 0x1c00 - 0x1c00: 0x3000, - 0x1c2a: 0x00da, 0x1c2b: 0x00e4, 0x1c2c: 0x00e8, 0x1c2d: 0x00de, 0x1c2e: 0x00e0, 0x1c2f: 0x00e0, - 0x1c36: 0x3000, 0x1c38: 0x3000, 0x1c39: 0x3000, 0x1c3a: 0x3000, - // Block 0x71, offset 0x1c40 - 0x1c46: 0x8800, 0x1c4b: 0x8800, - 0x1c4c: 0x1100, 0x1c4d: 0x8800, 0x1c4e: 0x1100, 0x1c4f: 0x8800, 0x1c50: 0x1100, 0x1c51: 0x8800, - 0x1c52: 0x1100, 0x1c53: 0x8800, 0x1c54: 0x1100, 0x1c55: 0x8800, 0x1c56: 0x1100, 0x1c57: 0x8800, - 0x1c58: 0x1100, 0x1c59: 0x8800, 0x1c5a: 0x1100, 0x1c5b: 0x8800, 0x1c5c: 0x1100, 0x1c5d: 0x8800, - 0x1c5e: 0x1100, 0x1c5f: 0x8800, 0x1c60: 0x1100, 0x1c61: 0x8800, 0x1c62: 0x1100, - 0x1c64: 0x8800, 0x1c65: 0x1100, 0x1c66: 0x8800, 0x1c67: 0x1100, 0x1c68: 0x8800, 0x1c69: 0x1100, - 0x1c6f: 0x8800, - 0x1c70: 0x1100, 0x1c71: 0x1100, 0x1c72: 0x8800, 0x1c73: 0x1100, 0x1c74: 0x1100, 0x1c75: 0x8800, - 0x1c76: 0x1100, 0x1c77: 0x1100, 0x1c78: 0x8800, 0x1c79: 0x1100, 0x1c7a: 0x1100, 0x1c7b: 0x8800, - 0x1c7c: 0x1100, 0x1c7d: 0x1100, - // Block 0x72, offset 0x1c80 - 0x1c94: 0x1100, - 0x1c99: 0x6608, 0x1c9a: 0x6608, 0x1c9b: 0x3000, 0x1c9c: 0x3000, 0x1c9d: 0x8800, - 0x1c9e: 0x1100, 0x1c9f: 0x3000, - 0x1ca6: 0x8800, - 0x1cab: 0x8800, 0x1cac: 0x1100, 0x1cad: 0x8800, 0x1cae: 0x1100, 0x1caf: 0x8800, - 0x1cb0: 0x1100, 0x1cb1: 0x8800, 0x1cb2: 0x1100, 0x1cb3: 0x8800, 0x1cb4: 0x1100, 0x1cb5: 0x8800, - 0x1cb6: 0x1100, 0x1cb7: 0x8800, 0x1cb8: 0x1100, 0x1cb9: 0x8800, 0x1cba: 0x1100, 0x1cbb: 0x8800, - 0x1cbc: 0x1100, 0x1cbd: 0x8800, 0x1cbe: 0x1100, 0x1cbf: 0x8800, - // Block 0x73, offset 0x1cc0 - 0x1cc0: 0x1100, 0x1cc1: 0x8800, 0x1cc2: 0x1100, 0x1cc4: 0x8800, 0x1cc5: 0x1100, - 0x1cc6: 0x8800, 0x1cc7: 0x1100, 0x1cc8: 0x8800, 0x1cc9: 0x1100, - 0x1ccf: 0x8800, 0x1cd0: 0x1100, 0x1cd1: 0x1100, - 0x1cd2: 0x8800, 0x1cd3: 0x1100, 0x1cd4: 0x1100, 0x1cd5: 0x8800, 0x1cd6: 0x1100, 0x1cd7: 0x1100, - 0x1cd8: 0x8800, 0x1cd9: 0x1100, 0x1cda: 0x1100, 0x1cdb: 0x8800, 0x1cdc: 0x1100, 0x1cdd: 0x1100, - 0x1cef: 0x8800, - 0x1cf0: 0x8800, 0x1cf1: 0x8800, 0x1cf2: 0x8800, 0x1cf4: 0x1100, - 0x1cf7: 0x1100, 0x1cf8: 0x1100, 0x1cf9: 0x1100, 0x1cfa: 0x1100, - 0x1cfd: 0x8800, 0x1cfe: 0x1100, 0x1cff: 0x3000, - // Block 0x74, offset 0x1d00 - 0x1d31: 0x3000, 0x1d32: 0x3000, 0x1d33: 0x3000, 0x1d34: 0x3000, 0x1d35: 0x3000, - 0x1d36: 0x3000, 0x1d37: 0x3000, 0x1d38: 0x3000, 0x1d39: 0x3000, 0x1d3a: 0x3000, 0x1d3b: 0x3000, - 0x1d3c: 0x3000, 0x1d3d: 0x3000, 0x1d3e: 0x3000, 0x1d3f: 0x3000, - // Block 0x75, offset 0x1d40 - 0x1d40: 0x3000, 0x1d41: 0x3000, 0x1d42: 0x3000, 0x1d43: 0x3000, 0x1d44: 0x3000, 0x1d45: 0x3000, - 0x1d46: 0x3000, 0x1d47: 0x3000, 0x1d48: 0x3000, 0x1d49: 0x3000, 0x1d4a: 0x3000, 0x1d4b: 0x3000, - 0x1d4c: 0x3000, 0x1d4d: 0x3000, 0x1d4e: 0x3000, - 0x1d52: 0x3000, 0x1d53: 0x3000, 0x1d54: 0x3000, 0x1d55: 0x3000, 0x1d56: 0x3000, 0x1d57: 0x3000, - 0x1d58: 0x3000, 0x1d59: 0x3000, 0x1d5a: 0x3000, 0x1d5b: 0x3000, 0x1d5c: 0x3000, 0x1d5d: 0x3000, - 0x1d5e: 0x3000, 0x1d5f: 0x3000, - // Block 0x76, offset 0x1d80 - 0x1d80: 0x3000, 0x1d81: 0x3000, 0x1d82: 0x3000, 0x1d83: 0x3000, 0x1d84: 0x3000, 0x1d85: 0x3000, - 0x1d86: 0x3000, 0x1d87: 0x3000, 0x1d88: 0x3000, 0x1d89: 0x3000, 0x1d8a: 0x3000, 0x1d8b: 0x3000, - 0x1d8c: 0x3000, 0x1d8d: 0x3000, 0x1d8e: 0x3000, 0x1d8f: 0x3000, 0x1d90: 0x3000, 0x1d91: 0x3000, - 0x1d92: 0x3000, 0x1d93: 0x3000, 0x1d94: 0x3000, 0x1d95: 0x3000, 0x1d96: 0x3000, 0x1d97: 0x3000, - 0x1d98: 0x3000, 0x1d99: 0x3000, 0x1d9a: 0x3000, 0x1d9b: 0x3000, 0x1d9c: 0x3000, 0x1d9d: 0x3000, - 0x1d9e: 0x3000, 0x1da0: 0x3000, 0x1da1: 0x3000, 0x1da2: 0x3000, 0x1da3: 0x3000, - 0x1da4: 0x3000, 0x1da5: 0x3000, 0x1da6: 0x3000, 0x1da7: 0x3000, 0x1da8: 0x3000, 0x1da9: 0x3000, - 0x1daa: 0x3000, 0x1dab: 0x3000, 0x1dac: 0x3000, 0x1dad: 0x3000, 0x1dae: 0x3000, 0x1daf: 0x3000, - 0x1db0: 0x3000, 0x1db1: 0x3000, 0x1db2: 0x3000, 0x1db3: 0x3000, 0x1db4: 0x3000, 0x1db5: 0x3000, - 0x1db6: 0x3000, 0x1db7: 0x3000, 0x1db8: 0x3000, 0x1db9: 0x3000, 0x1dba: 0x3000, 0x1dbb: 0x3000, - 0x1dbc: 0x3000, 0x1dbd: 0x3000, 0x1dbe: 0x3000, 0x1dbf: 0x3000, - // Block 0x77, offset 0x1dc0 - 0x1dc0: 0x3000, 0x1dc1: 0x3000, 0x1dc2: 0x3000, 0x1dc3: 0x3000, 0x1dc4: 0x3000, 0x1dc5: 0x3000, - 0x1dc6: 0x3000, 0x1dc7: 0x3000, - 0x1dd0: 0x3000, 0x1dd1: 0x3000, - 0x1dd2: 0x3000, 0x1dd3: 0x3000, 0x1dd4: 0x3000, 0x1dd5: 0x3000, 0x1dd6: 0x3000, 0x1dd7: 0x3000, - 0x1dd8: 0x3000, 0x1dd9: 0x3000, 0x1dda: 0x3000, 0x1ddb: 0x3000, 0x1ddc: 0x3000, 0x1ddd: 0x3000, - 0x1dde: 0x3000, 0x1ddf: 0x3000, 0x1de0: 0x3000, 0x1de1: 0x3000, 0x1de2: 0x3000, 0x1de3: 0x3000, - 0x1de4: 0x3000, 0x1de5: 0x3000, 0x1de6: 0x3000, 0x1de7: 0x3000, 0x1de8: 0x3000, 0x1de9: 0x3000, - 0x1dea: 0x3000, 0x1deb: 0x3000, 0x1dec: 0x3000, 0x1ded: 0x3000, 0x1dee: 0x3000, 0x1def: 0x3000, - 0x1df0: 0x3000, 0x1df1: 0x3000, 0x1df2: 0x3000, 0x1df3: 0x3000, 0x1df4: 0x3000, 0x1df5: 0x3000, - 0x1df6: 0x3000, 0x1df7: 0x3000, 0x1df8: 0x3000, 0x1df9: 0x3000, 0x1dfa: 0x3000, 0x1dfb: 0x3000, - 0x1dfc: 0x3000, 0x1dfd: 0x3000, 0x1dfe: 0x3000, - // Block 0x78, offset 0x1e00 - 0x1e00: 0x3000, 0x1e01: 0x3000, 0x1e02: 0x3000, 0x1e03: 0x3000, 0x1e04: 0x3000, 0x1e05: 0x3000, - 0x1e06: 0x3000, 0x1e07: 0x3000, 0x1e08: 0x3000, 0x1e09: 0x3000, 0x1e0a: 0x3000, 0x1e0b: 0x3000, - 0x1e0c: 0x3000, 0x1e0d: 0x3000, 0x1e0e: 0x3000, 0x1e0f: 0x3000, 0x1e10: 0x3000, 0x1e11: 0x3000, - 0x1e12: 0x3000, 0x1e13: 0x3000, 0x1e14: 0x3000, 0x1e15: 0x3000, 0x1e16: 0x3000, 0x1e17: 0x3000, - 0x1e18: 0x3000, 0x1e19: 0x3000, 0x1e1a: 0x3000, 0x1e1b: 0x3000, 0x1e1c: 0x3000, 0x1e1d: 0x3000, - 0x1e1e: 0x3000, 0x1e1f: 0x3000, 0x1e20: 0x3000, 0x1e21: 0x3000, 0x1e22: 0x3000, 0x1e23: 0x3000, - 0x1e24: 0x3000, 0x1e25: 0x3000, 0x1e26: 0x3000, 0x1e27: 0x3000, 0x1e28: 0x3000, 0x1e29: 0x3000, - 0x1e2a: 0x3000, 0x1e2b: 0x3000, 0x1e2c: 0x3000, 0x1e2d: 0x3000, 0x1e2e: 0x3000, 0x1e2f: 0x3000, - 0x1e30: 0x3000, 0x1e31: 0x3000, 0x1e32: 0x3000, 0x1e33: 0x3000, 0x1e34: 0x3000, 0x1e35: 0x3000, - 0x1e36: 0x3000, 0x1e37: 0x3000, 0x1e38: 0x3000, 0x1e39: 0x3000, 0x1e3a: 0x3000, 0x1e3b: 0x3000, - 0x1e3c: 0x3000, 0x1e3d: 0x3000, 0x1e3e: 0x3000, - // Block 0x79, offset 0x1e40 - 0x1e6f: 0x00e6, - 0x1e7c: 0x00e6, 0x1e7d: 0x00e6, - // Block 0x7a, offset 0x1e80 - 0x1eb0: 0x00e6, 0x1eb1: 0x00e6, - // Block 0x7b, offset 0x1ec0 - 0x1ef0: 0x3000, - // Block 0x7c, offset 0x1f00 - 0x1f06: 0x0009, - // Block 0x7d, offset 0x1f40 - 0x1f44: 0x0009, - 0x1f60: 0x00e6, 0x1f61: 0x00e6, 0x1f62: 0x00e6, 0x1f63: 0x00e6, - 0x1f64: 0x00e6, 0x1f65: 0x00e6, 0x1f66: 0x00e6, 0x1f67: 0x00e6, 0x1f68: 0x00e6, 0x1f69: 0x00e6, - 0x1f6a: 0x00e6, 0x1f6b: 0x00e6, 0x1f6c: 0x00e6, 0x1f6d: 0x00e6, 0x1f6e: 0x00e6, 0x1f6f: 0x00e6, - 0x1f70: 0x00e6, 0x1f71: 0x00e6, - // Block 0x7e, offset 0x1f80 - 0x1fab: 0x00dc, 0x1fac: 0x00dc, 0x1fad: 0x00dc, - // Block 0x7f, offset 0x1fc0 - 0x1fd3: 0x0009, - // Block 0x80, offset 0x2000 - 0x2033: 0x0007, - // Block 0x81, offset 0x2040 - 0x2040: 0x0009, - // Block 0x82, offset 0x2080 - 0x20b0: 0x00e6, 0x20b2: 0x00e6, 0x20b3: 0x00e6, 0x20b4: 0x00dc, - 0x20b7: 0x00e6, 0x20b8: 0x00e6, - 0x20be: 0x00e6, 0x20bf: 0x00e6, - // Block 0x83, offset 0x20c0 - 0x20c1: 0x00e6, - // Block 0x84, offset 0x2100 - 0x212d: 0x0009, - // Block 0x85, offset 0x2140 - 0x2140: 0x1100, 0x2141: 0x1100, 0x2142: 0x1100, 0x2143: 0x1100, 0x2144: 0x1100, 0x2145: 0x1100, - 0x2146: 0x1100, 0x2147: 0x1100, 0x2148: 0x1100, 0x2149: 0x1100, 0x214a: 0x1100, 0x214b: 0x1100, - 0x214c: 0x1100, 0x214d: 0x1100, 0x214e: 0x1100, 0x214f: 0x1100, 0x2150: 0x1100, 0x2151: 0x1100, - 0x2152: 0x1100, 0x2153: 0x1100, 0x2154: 0x1100, 0x2155: 0x1100, 0x2156: 0x1100, 0x2157: 0x1100, - 0x2158: 0x1100, 0x2159: 0x1100, 0x215a: 0x1100, 0x215b: 0x1100, 0x215c: 0x1100, 0x215d: 0x1100, - 0x215e: 0x1100, 0x215f: 0x1100, 0x2160: 0x1100, 0x2161: 0x1100, 0x2162: 0x1100, 0x2163: 0x1100, - 0x2164: 0x1100, 0x2165: 0x1100, 0x2166: 0x1100, 0x2167: 0x1100, 0x2168: 0x1100, 0x2169: 0x1100, - 0x216a: 0x1100, 0x216b: 0x1100, 0x216c: 0x1100, 0x216d: 0x1100, 0x216e: 0x1100, 0x216f: 0x1100, - 0x2170: 0x1100, 0x2171: 0x1100, 0x2172: 0x1100, 0x2173: 0x1100, 0x2174: 0x1100, 0x2175: 0x1100, - 0x2176: 0x1100, 0x2177: 0x1100, 0x2178: 0x1100, 0x2179: 0x1100, 0x217a: 0x1100, 0x217b: 0x1100, - 0x217c: 0x1100, 0x217d: 0x1100, 0x217e: 0x1100, 0x217f: 0x1100, - // Block 0x86, offset 0x2180 - 0x2180: 0x1100, 0x2181: 0x1100, 0x2182: 0x1100, 0x2183: 0x1100, 0x2184: 0x1100, 0x2185: 0x1100, - 0x2186: 0x1100, 0x2187: 0x1100, 0x2188: 0x1100, 0x2189: 0x1100, 0x218a: 0x1100, 0x218b: 0x1100, - 0x218c: 0x1100, 0x218d: 0x1100, 0x218e: 0x1100, 0x218f: 0x1100, 0x2190: 0x1100, 0x2191: 0x1100, - 0x2192: 0x1100, 0x2193: 0x1100, 0x2194: 0x1100, 0x2195: 0x1100, 0x2196: 0x1100, 0x2197: 0x1100, - 0x2198: 0x1100, 0x2199: 0x1100, 0x219a: 0x1100, 0x219b: 0x1100, 0x219c: 0x1100, 0x219d: 0x1100, - 0x219e: 0x1100, 0x219f: 0x1100, 0x21a0: 0x1100, 0x21a1: 0x1100, 0x21a2: 0x1100, 0x21a3: 0x1100, - // Block 0x87, offset 0x21c0 - 0x21c0: 0x3300, 0x21c1: 0x3300, 0x21c2: 0x3300, 0x21c3: 0x3300, 0x21c4: 0x3300, 0x21c5: 0x3300, - 0x21c6: 0x3300, 0x21c7: 0x3300, 0x21c8: 0x3300, 0x21c9: 0x3300, 0x21ca: 0x3300, 0x21cb: 0x3300, - 0x21cc: 0x3300, 0x21cd: 0x3300, 0x21ce: 0x3300, 0x21cf: 0x3300, 0x21d0: 0x3300, 0x21d1: 0x3300, - 0x21d2: 0x3300, 0x21d3: 0x3300, 0x21d4: 0x3300, 0x21d5: 0x3300, 0x21d6: 0x3300, 0x21d7: 0x3300, - 0x21d8: 0x3300, 0x21d9: 0x3300, 0x21da: 0x3300, 0x21db: 0x3300, 0x21dc: 0x3300, 0x21dd: 0x3300, - 0x21de: 0x3300, 0x21df: 0x3300, 0x21e0: 0x3300, 0x21e1: 0x3300, 0x21e2: 0x3300, 0x21e3: 0x3300, - 0x21e4: 0x3300, 0x21e5: 0x3300, 0x21e6: 0x3300, 0x21e7: 0x3300, 0x21e8: 0x3300, 0x21e9: 0x3300, - 0x21ea: 0x3300, 0x21eb: 0x3300, 0x21ec: 0x3300, 0x21ed: 0x3300, 0x21ee: 0x3300, 0x21ef: 0x3300, - 0x21f0: 0x3300, 0x21f1: 0x3300, 0x21f2: 0x3300, 0x21f3: 0x3300, 0x21f4: 0x3300, 0x21f5: 0x3300, - 0x21f6: 0x3300, 0x21f7: 0x3300, 0x21f8: 0x3300, 0x21f9: 0x3300, 0x21fa: 0x3300, 0x21fb: 0x3300, - 0x21fc: 0x3300, 0x21fd: 0x3300, 0x21fe: 0x3300, 0x21ff: 0x3300, - // Block 0x88, offset 0x2200 - 0x2200: 0x3300, 0x2201: 0x3300, 0x2202: 0x3300, 0x2203: 0x3300, 0x2204: 0x3300, 0x2205: 0x3300, - 0x2206: 0x3300, 0x2207: 0x3300, 0x2208: 0x3300, 0x2209: 0x3300, 0x220a: 0x3300, 0x220b: 0x3300, - 0x220c: 0x3300, 0x220d: 0x3300, 0x2210: 0x3300, - 0x2212: 0x3300, 0x2215: 0x3300, 0x2216: 0x3300, 0x2217: 0x3300, - 0x2218: 0x3300, 0x2219: 0x3300, 0x221a: 0x3300, 0x221b: 0x3300, 0x221c: 0x3300, 0x221d: 0x3300, - 0x221e: 0x3300, 0x2220: 0x3300, 0x2222: 0x3300, - 0x2225: 0x3300, 0x2226: 0x3300, - 0x222a: 0x3300, 0x222b: 0x3300, 0x222c: 0x3300, 0x222d: 0x3300, - 0x2230: 0x3300, 0x2231: 0x3300, 0x2232: 0x3300, 0x2233: 0x3300, 0x2234: 0x3300, 0x2235: 0x3300, - 0x2236: 0x3300, 0x2237: 0x3300, 0x2238: 0x3300, 0x2239: 0x3300, 0x223a: 0x3300, 0x223b: 0x3300, - 0x223c: 0x3300, 0x223d: 0x3300, 0x223e: 0x3300, 0x223f: 0x3300, - // Block 0x89, offset 0x2240 - 0x2240: 0x3300, 0x2241: 0x3300, 0x2242: 0x3300, 0x2243: 0x3300, 0x2244: 0x3300, 0x2245: 0x3300, - 0x2246: 0x3300, 0x2247: 0x3300, 0x2248: 0x3300, 0x2249: 0x3300, 0x224a: 0x3300, 0x224b: 0x3300, - 0x224c: 0x3300, 0x224d: 0x3300, 0x224e: 0x3300, 0x224f: 0x3300, 0x2250: 0x3300, 0x2251: 0x3300, - 0x2252: 0x3300, 0x2253: 0x3300, 0x2254: 0x3300, 0x2255: 0x3300, 0x2256: 0x3300, 0x2257: 0x3300, - 0x2258: 0x3300, 0x2259: 0x3300, 0x225a: 0x3300, 0x225b: 0x3300, 0x225c: 0x3300, 0x225d: 0x3300, - 0x225e: 0x3300, 0x225f: 0x3300, 0x2260: 0x3300, 0x2261: 0x3300, 0x2262: 0x3300, 0x2263: 0x3300, - 0x2264: 0x3300, 0x2265: 0x3300, 0x2266: 0x3300, 0x2267: 0x3300, 0x2268: 0x3300, 0x2269: 0x3300, - 0x226a: 0x3300, 0x226b: 0x3300, 0x226c: 0x3300, 0x226d: 0x3300, - 0x2270: 0x3300, 0x2271: 0x3300, 0x2272: 0x3300, 0x2273: 0x3300, 0x2274: 0x3300, 0x2275: 0x3300, - 0x2276: 0x3300, 0x2277: 0x3300, 0x2278: 0x3300, 0x2279: 0x3300, 0x227a: 0x3300, 0x227b: 0x3300, - 0x227c: 0x3300, 0x227d: 0x3300, 0x227e: 0x3300, 0x227f: 0x3300, - // Block 0x8a, offset 0x2280 - 0x2280: 0x3300, 0x2281: 0x3300, 0x2282: 0x3300, 0x2283: 0x3300, 0x2284: 0x3300, 0x2285: 0x3300, - 0x2286: 0x3300, 0x2287: 0x3300, 0x2288: 0x3300, 0x2289: 0x3300, 0x228a: 0x3300, 0x228b: 0x3300, - 0x228c: 0x3300, 0x228d: 0x3300, 0x228e: 0x3300, 0x228f: 0x3300, 0x2290: 0x3300, 0x2291: 0x3300, - 0x2292: 0x3300, 0x2293: 0x3300, 0x2294: 0x3300, 0x2295: 0x3300, 0x2296: 0x3300, 0x2297: 0x3300, - 0x2298: 0x3300, 0x2299: 0x3300, - // Block 0x8b, offset 0x22c0 - 0x22c0: 0x3000, 0x22c1: 0x3000, 0x22c2: 0x3000, 0x22c3: 0x3000, 0x22c4: 0x3000, 0x22c5: 0x3000, - 0x22c6: 0x3000, - 0x22d3: 0x3000, 0x22d4: 0x3000, 0x22d5: 0x3000, 0x22d6: 0x3000, 0x22d7: 0x3000, - 0x22dd: 0x3300, - 0x22de: 0x001a, 0x22df: 0x3300, 0x22e0: 0x3000, 0x22e1: 0x3000, 0x22e2: 0x3000, 0x22e3: 0x3000, - 0x22e4: 0x3000, 0x22e5: 0x3000, 0x22e6: 0x3000, 0x22e7: 0x3000, 0x22e8: 0x3000, 0x22e9: 0x3000, - 0x22ea: 0x3300, 0x22eb: 0x3300, 0x22ec: 0x3300, 0x22ed: 0x3300, 0x22ee: 0x3300, 0x22ef: 0x3300, - 0x22f0: 0x3300, 0x22f1: 0x3300, 0x22f2: 0x3300, 0x22f3: 0x3300, 0x22f4: 0x3300, 0x22f5: 0x3300, - 0x22f6: 0x3300, 0x22f8: 0x3300, 0x22f9: 0x3300, 0x22fa: 0x3300, 0x22fb: 0x3300, - 0x22fc: 0x3300, 0x22fe: 0x3300, - // Block 0x8c, offset 0x2300 - 0x2300: 0x3300, 0x2301: 0x3300, 0x2303: 0x3300, 0x2304: 0x3300, - 0x2306: 0x3300, 0x2307: 0x3300, 0x2308: 0x3300, 0x2309: 0x3300, 0x230a: 0x3300, 0x230b: 0x3300, - 0x230c: 0x3300, 0x230d: 0x3300, 0x230e: 0x3300, 0x230f: 0x3000, 0x2310: 0x3000, 0x2311: 0x3000, - 0x2312: 0x3000, 0x2313: 0x3000, 0x2314: 0x3000, 0x2315: 0x3000, 0x2316: 0x3000, 0x2317: 0x3000, - 0x2318: 0x3000, 0x2319: 0x3000, 0x231a: 0x3000, 0x231b: 0x3000, 0x231c: 0x3000, 0x231d: 0x3000, - 0x231e: 0x3000, 0x231f: 0x3000, 0x2320: 0x3000, 0x2321: 0x3000, 0x2322: 0x3000, 0x2323: 0x3000, - 0x2324: 0x3000, 0x2325: 0x3000, 0x2326: 0x3000, 0x2327: 0x3000, 0x2328: 0x3000, 0x2329: 0x3000, - 0x232a: 0x3000, 0x232b: 0x3000, 0x232c: 0x3000, 0x232d: 0x3000, 0x232e: 0x3000, 0x232f: 0x3000, - 0x2330: 0x3000, 0x2331: 0x3000, 0x2332: 0x3000, 0x2333: 0x3000, 0x2334: 0x3000, 0x2335: 0x3000, - 0x2336: 0x3000, 0x2337: 0x3000, 0x2338: 0x3000, 0x2339: 0x3000, 0x233a: 0x3000, 0x233b: 0x3000, - 0x233c: 0x3000, 0x233d: 0x3000, 0x233e: 0x3000, 0x233f: 0x3000, - // Block 0x8d, offset 0x2340 - 0x2340: 0x3000, 0x2341: 0x3000, 0x2342: 0x3000, 0x2343: 0x3000, 0x2344: 0x3000, 0x2345: 0x3000, - 0x2346: 0x3000, 0x2347: 0x3000, 0x2348: 0x3000, 0x2349: 0x3000, 0x234a: 0x3000, 0x234b: 0x3000, - 0x234c: 0x3000, 0x234d: 0x3000, 0x234e: 0x3000, 0x234f: 0x3000, 0x2350: 0x3000, 0x2351: 0x3000, - 0x2352: 0x3000, 0x2353: 0x3000, 0x2354: 0x3000, 0x2355: 0x3000, 0x2356: 0x3000, 0x2357: 0x3000, - 0x2358: 0x3000, 0x2359: 0x3000, 0x235a: 0x3000, 0x235b: 0x3000, 0x235c: 0x3000, 0x235d: 0x3000, - 0x235e: 0x3000, 0x235f: 0x3000, 0x2360: 0x3000, 0x2361: 0x3000, 0x2362: 0x3000, 0x2363: 0x3000, - 0x2364: 0x3000, 0x2365: 0x3000, 0x2366: 0x3000, 0x2367: 0x3000, 0x2368: 0x3000, 0x2369: 0x3000, - 0x236a: 0x3000, 0x236b: 0x3000, 0x236c: 0x3000, 0x236d: 0x3000, 0x236e: 0x3000, 0x236f: 0x3000, - 0x2370: 0x3000, 0x2371: 0x3000, - // Block 0x8e, offset 0x2380 - 0x2393: 0x3000, 0x2394: 0x3000, 0x2395: 0x3000, 0x2396: 0x3000, 0x2397: 0x3000, - 0x2398: 0x3000, 0x2399: 0x3000, 0x239a: 0x3000, 0x239b: 0x3000, 0x239c: 0x3000, 0x239d: 0x3000, - 0x239e: 0x3000, 0x239f: 0x3000, 0x23a0: 0x3000, 0x23a1: 0x3000, 0x23a2: 0x3000, 0x23a3: 0x3000, - 0x23a4: 0x3000, 0x23a5: 0x3000, 0x23a6: 0x3000, 0x23a7: 0x3000, 0x23a8: 0x3000, 0x23a9: 0x3000, - 0x23aa: 0x3000, 0x23ab: 0x3000, 0x23ac: 0x3000, 0x23ad: 0x3000, 0x23ae: 0x3000, 0x23af: 0x3000, - 0x23b0: 0x3000, 0x23b1: 0x3000, 0x23b2: 0x3000, 0x23b3: 0x3000, 0x23b4: 0x3000, 0x23b5: 0x3000, - 0x23b6: 0x3000, 0x23b7: 0x3000, 0x23b8: 0x3000, 0x23b9: 0x3000, 0x23ba: 0x3000, 0x23bb: 0x3000, - 0x23bc: 0x3000, 0x23bd: 0x3000, 0x23be: 0x3000, 0x23bf: 0x3000, - // Block 0x8f, offset 0x23c0 - 0x23c0: 0x3000, 0x23c1: 0x3000, 0x23c2: 0x3000, 0x23c3: 0x3000, 0x23c4: 0x3000, 0x23c5: 0x3000, - 0x23c6: 0x3000, 0x23c7: 0x3000, 0x23c8: 0x3000, 0x23c9: 0x3000, 0x23ca: 0x3000, 0x23cb: 0x3000, - 0x23cc: 0x3000, 0x23cd: 0x3000, 0x23ce: 0x3000, 0x23cf: 0x3000, 0x23d0: 0x3000, 0x23d1: 0x3000, - 0x23d2: 0x3000, 0x23d3: 0x3000, 0x23d4: 0x3000, 0x23d5: 0x3000, 0x23d6: 0x3000, 0x23d7: 0x3000, - 0x23d8: 0x3000, 0x23d9: 0x3000, 0x23da: 0x3000, 0x23db: 0x3000, 0x23dc: 0x3000, 0x23dd: 0x3000, - 0x23de: 0x3000, 0x23df: 0x3000, 0x23e0: 0x3000, 0x23e1: 0x3000, 0x23e2: 0x3000, 0x23e3: 0x3000, - 0x23e4: 0x3000, 0x23e5: 0x3000, 0x23e6: 0x3000, 0x23e7: 0x3000, 0x23e8: 0x3000, 0x23e9: 0x3000, - 0x23ea: 0x3000, 0x23eb: 0x3000, 0x23ec: 0x3000, 0x23ed: 0x3000, 0x23ee: 0x3000, 0x23ef: 0x3000, - 0x23f0: 0x3000, 0x23f1: 0x3000, 0x23f2: 0x3000, 0x23f3: 0x3000, 0x23f4: 0x3000, 0x23f5: 0x3000, - 0x23f6: 0x3000, 0x23f7: 0x3000, 0x23f8: 0x3000, 0x23f9: 0x3000, 0x23fa: 0x3000, 0x23fb: 0x3000, - 0x23fc: 0x3000, 0x23fd: 0x3000, - // Block 0x90, offset 0x2400 - 0x2410: 0x3000, 0x2411: 0x3000, - 0x2412: 0x3000, 0x2413: 0x3000, 0x2414: 0x3000, 0x2415: 0x3000, 0x2416: 0x3000, 0x2417: 0x3000, - 0x2418: 0x3000, 0x2419: 0x3000, 0x241a: 0x3000, 0x241b: 0x3000, 0x241c: 0x3000, 0x241d: 0x3000, - 0x241e: 0x3000, 0x241f: 0x3000, 0x2420: 0x3000, 0x2421: 0x3000, 0x2422: 0x3000, 0x2423: 0x3000, - 0x2424: 0x3000, 0x2425: 0x3000, 0x2426: 0x3000, 0x2427: 0x3000, 0x2428: 0x3000, 0x2429: 0x3000, - 0x242a: 0x3000, 0x242b: 0x3000, 0x242c: 0x3000, 0x242d: 0x3000, 0x242e: 0x3000, 0x242f: 0x3000, - 0x2430: 0x3000, 0x2431: 0x3000, 0x2432: 0x3000, 0x2433: 0x3000, 0x2434: 0x3000, 0x2435: 0x3000, - 0x2436: 0x3000, 0x2437: 0x3000, 0x2438: 0x3000, 0x2439: 0x3000, 0x243a: 0x3000, 0x243b: 0x3000, - 0x243c: 0x3000, 0x243d: 0x3000, 0x243e: 0x3000, 0x243f: 0x3000, - // Block 0x91, offset 0x2440 - 0x2440: 0x3000, 0x2441: 0x3000, 0x2442: 0x3000, 0x2443: 0x3000, 0x2444: 0x3000, 0x2445: 0x3000, - 0x2446: 0x3000, 0x2447: 0x3000, 0x2448: 0x3000, 0x2449: 0x3000, 0x244a: 0x3000, 0x244b: 0x3000, - 0x244c: 0x3000, 0x244d: 0x3000, 0x244e: 0x3000, 0x244f: 0x3000, - 0x2452: 0x3000, 0x2453: 0x3000, 0x2454: 0x3000, 0x2455: 0x3000, 0x2456: 0x3000, 0x2457: 0x3000, - 0x2458: 0x3000, 0x2459: 0x3000, 0x245a: 0x3000, 0x245b: 0x3000, 0x245c: 0x3000, 0x245d: 0x3000, - 0x245e: 0x3000, 0x245f: 0x3000, 0x2460: 0x3000, 0x2461: 0x3000, 0x2462: 0x3000, 0x2463: 0x3000, - 0x2464: 0x3000, 0x2465: 0x3000, 0x2466: 0x3000, 0x2467: 0x3000, 0x2468: 0x3000, 0x2469: 0x3000, - 0x246a: 0x3000, 0x246b: 0x3000, 0x246c: 0x3000, 0x246d: 0x3000, 0x246e: 0x3000, 0x246f: 0x3000, - 0x2470: 0x3000, 0x2471: 0x3000, 0x2472: 0x3000, 0x2473: 0x3000, 0x2474: 0x3000, 0x2475: 0x3000, - 0x2476: 0x3000, 0x2477: 0x3000, 0x2478: 0x3000, 0x2479: 0x3000, 0x247a: 0x3000, 0x247b: 0x3000, - 0x247c: 0x3000, 0x247d: 0x3000, 0x247e: 0x3000, 0x247f: 0x3000, - // Block 0x92, offset 0x2480 - 0x2480: 0x3000, 0x2481: 0x3000, 0x2482: 0x3000, 0x2483: 0x3000, 0x2484: 0x3000, 0x2485: 0x3000, - 0x2486: 0x3000, 0x2487: 0x3000, - 0x24b0: 0x3000, 0x24b1: 0x3000, 0x24b2: 0x3000, 0x24b3: 0x3000, 0x24b4: 0x3000, 0x24b5: 0x3000, - 0x24b6: 0x3000, 0x24b7: 0x3000, 0x24b8: 0x3000, 0x24b9: 0x3000, 0x24ba: 0x3000, 0x24bb: 0x3000, - 0x24bc: 0x3000, - // Block 0x93, offset 0x24c0 - 0x24d0: 0x3000, 0x24d1: 0x3000, - 0x24d2: 0x3000, 0x24d3: 0x3000, 0x24d4: 0x3000, 0x24d5: 0x3000, 0x24d6: 0x3000, 0x24d7: 0x3000, - 0x24d8: 0x3000, 0x24d9: 0x3000, - 0x24e0: 0x00e6, 0x24e1: 0x00e6, 0x24e2: 0x00e6, 0x24e3: 0x00e6, - 0x24e4: 0x00e6, 0x24e5: 0x00e6, 0x24e6: 0x00e6, - 0x24f0: 0x3000, 0x24f1: 0x3000, 0x24f2: 0x3000, 0x24f3: 0x3000, 0x24f4: 0x3000, 0x24f5: 0x3000, - 0x24f6: 0x3000, 0x24f7: 0x3000, 0x24f8: 0x3000, 0x24f9: 0x3000, 0x24fa: 0x3000, 0x24fb: 0x3000, - 0x24fc: 0x3000, 0x24fd: 0x3000, 0x24fe: 0x3000, 0x24ff: 0x3000, - // Block 0x94, offset 0x2500 - 0x2500: 0x3000, 0x2501: 0x3000, 0x2502: 0x3000, 0x2503: 0x3000, 0x2504: 0x3000, - 0x2507: 0x3000, 0x2508: 0x3000, 0x2509: 0x3000, 0x250a: 0x3000, 0x250b: 0x3000, - 0x250c: 0x3000, 0x250d: 0x3000, 0x250e: 0x3000, 0x250f: 0x3000, 0x2510: 0x3000, 0x2511: 0x3000, - 0x2512: 0x3000, 0x2514: 0x3000, 0x2515: 0x3000, 0x2516: 0x3000, 0x2517: 0x3000, - 0x2518: 0x3000, 0x2519: 0x3000, 0x251a: 0x3000, 0x251b: 0x3000, 0x251c: 0x3000, 0x251d: 0x3000, - 0x251e: 0x3000, 0x251f: 0x3000, 0x2520: 0x3000, 0x2521: 0x3000, 0x2522: 0x3000, 0x2523: 0x3000, - 0x2524: 0x3000, 0x2525: 0x3000, 0x2526: 0x3000, 0x2528: 0x3000, 0x2529: 0x3000, - 0x252a: 0x3000, 0x252b: 0x3000, - 0x2530: 0x3000, 0x2531: 0x3000, 0x2532: 0x3000, 0x2534: 0x3000, - 0x2536: 0x3000, 0x2537: 0x3000, 0x2538: 0x3000, 0x2539: 0x3000, 0x253a: 0x3000, 0x253b: 0x3000, - 0x253c: 0x3000, 0x253d: 0x3000, 0x253e: 0x3000, 0x253f: 0x3000, - // Block 0x95, offset 0x2540 - 0x2540: 0x3000, 0x2541: 0x3000, 0x2542: 0x3000, 0x2543: 0x3000, 0x2544: 0x3000, 0x2545: 0x3000, - 0x2546: 0x3000, 0x2547: 0x3000, 0x2548: 0x3000, 0x2549: 0x3000, 0x254a: 0x3000, 0x254b: 0x3000, - 0x254c: 0x3000, 0x254d: 0x3000, 0x254e: 0x3000, 0x254f: 0x3000, 0x2550: 0x3000, 0x2551: 0x3000, - 0x2552: 0x3000, 0x2553: 0x3000, 0x2554: 0x3000, 0x2555: 0x3000, 0x2556: 0x3000, 0x2557: 0x3000, - 0x2558: 0x3000, 0x2559: 0x3000, 0x255a: 0x3000, 0x255b: 0x3000, 0x255c: 0x3000, 0x255d: 0x3000, - 0x255e: 0x3000, 0x255f: 0x3000, 0x2560: 0x3000, 0x2561: 0x3000, 0x2562: 0x3000, 0x2563: 0x3000, - 0x2564: 0x3000, 0x2565: 0x3000, 0x2566: 0x3000, 0x2567: 0x3000, 0x2568: 0x3000, 0x2569: 0x3000, - 0x256a: 0x3000, 0x256b: 0x3000, 0x256c: 0x3000, 0x256d: 0x3000, 0x256e: 0x3000, 0x256f: 0x3000, - 0x2570: 0x3000, 0x2571: 0x3000, 0x2572: 0x3000, 0x2573: 0x3000, 0x2574: 0x3000, 0x2575: 0x3000, - 0x2576: 0x3000, 0x2577: 0x3000, 0x2578: 0x3000, 0x2579: 0x3000, 0x257a: 0x3000, 0x257b: 0x3000, - 0x257c: 0x3000, - // Block 0x96, offset 0x2580 - 0x2581: 0x3000, 0x2582: 0x3000, 0x2583: 0x3000, 0x2584: 0x3000, 0x2585: 0x3000, - 0x2586: 0x3000, 0x2587: 0x3000, 0x2588: 0x3000, 0x2589: 0x3000, 0x258a: 0x3000, 0x258b: 0x3000, - 0x258c: 0x3000, 0x258d: 0x3000, 0x258e: 0x3000, 0x258f: 0x3000, 0x2590: 0x3000, 0x2591: 0x3000, - 0x2592: 0x3000, 0x2593: 0x3000, 0x2594: 0x3000, 0x2595: 0x3000, 0x2596: 0x3000, 0x2597: 0x3000, - 0x2598: 0x3000, 0x2599: 0x3000, 0x259a: 0x3000, 0x259b: 0x3000, 0x259c: 0x3000, 0x259d: 0x3000, - 0x259e: 0x3000, 0x259f: 0x3000, 0x25a0: 0x3000, 0x25a1: 0x3000, 0x25a2: 0x3000, 0x25a3: 0x3000, - 0x25a4: 0x3000, 0x25a5: 0x3000, 0x25a6: 0x3000, 0x25a7: 0x3000, 0x25a8: 0x3000, 0x25a9: 0x3000, - 0x25aa: 0x3000, 0x25ab: 0x3000, 0x25ac: 0x3000, 0x25ad: 0x3000, 0x25ae: 0x3000, 0x25af: 0x3000, - 0x25b0: 0x3000, 0x25b1: 0x3000, 0x25b2: 0x3000, 0x25b3: 0x3000, 0x25b4: 0x3000, 0x25b5: 0x3000, - 0x25b6: 0x3000, 0x25b7: 0x3000, 0x25b8: 0x3000, 0x25b9: 0x3000, 0x25ba: 0x3000, 0x25bb: 0x3000, - 0x25bc: 0x3000, 0x25bd: 0x3000, 0x25be: 0x3000, 0x25bf: 0x3000, - // Block 0x97, offset 0x25c0 - 0x25c2: 0x3000, 0x25c3: 0x3000, 0x25c4: 0x3000, 0x25c5: 0x3000, - 0x25c6: 0x3000, 0x25c7: 0x3000, 0x25ca: 0x3000, 0x25cb: 0x3000, - 0x25cc: 0x3000, 0x25cd: 0x3000, 0x25ce: 0x3000, 0x25cf: 0x3000, - 0x25d2: 0x3000, 0x25d3: 0x3000, 0x25d4: 0x3000, 0x25d5: 0x3000, 0x25d6: 0x3000, 0x25d7: 0x3000, - 0x25da: 0x3000, 0x25db: 0x3000, 0x25dc: 0x3000, - 0x25e0: 0x3000, 0x25e1: 0x3000, 0x25e2: 0x3000, 0x25e3: 0x3000, - 0x25e4: 0x3000, 0x25e5: 0x3000, 0x25e6: 0x3000, 0x25e8: 0x3000, 0x25e9: 0x3000, - 0x25ea: 0x3000, 0x25eb: 0x3000, 0x25ec: 0x3000, 0x25ed: 0x3000, 0x25ee: 0x3000, - // Block 0x98, offset 0x2600 - 0x263d: 0x00dc, - // Block 0x99, offset 0x2640 - 0x264d: 0x00dc, 0x264f: 0x00e6, - 0x2678: 0x00e6, 0x2679: 0x0001, 0x267a: 0x00dc, - 0x267f: 0x0009, - // Block 0x9a, offset 0x2680 - 0x2699: 0x8800, 0x269a: 0x1100, 0x269b: 0x8800, 0x269c: 0x1100, - 0x26a5: 0x8800, - 0x26ab: 0x1100, - 0x26b9: 0x0009, 0x26ba: 0x6607, - // Block 0x9b, offset 0x26c0 - 0x26de: 0x3300, 0x26df: 0x3300, 0x26e0: 0x3300, 0x26e1: 0x3300, 0x26e2: 0x3300, 0x26e3: 0x3300, - 0x26e4: 0x3300, 0x26e5: 0x00d8, 0x26e6: 0x00d8, 0x26e7: 0x0001, 0x26e8: 0x0001, 0x26e9: 0x0001, - 0x26ed: 0x00e2, 0x26ee: 0x00d8, 0x26ef: 0x00d8, - 0x26f0: 0x00d8, 0x26f1: 0x00d8, 0x26f2: 0x00d8, - 0x26fb: 0x00dc, - 0x26fc: 0x00dc, 0x26fd: 0x00dc, 0x26fe: 0x00dc, 0x26ff: 0x00dc, - // Block 0x9c, offset 0x2700 - 0x2700: 0x00dc, 0x2701: 0x00dc, 0x2702: 0x00dc, 0x2705: 0x00e6, - 0x2706: 0x00e6, 0x2707: 0x00e6, 0x2708: 0x00e6, 0x2709: 0x00e6, 0x270a: 0x00dc, 0x270b: 0x00dc, - 0x272a: 0x00e6, 0x272b: 0x00e6, 0x272c: 0x00e6, 0x272d: 0x00e6, - 0x273b: 0x3300, - 0x273c: 0x3300, 0x273d: 0x3300, 0x273e: 0x3300, 0x273f: 0x3300, - // Block 0x9d, offset 0x2740 - 0x2740: 0x3300, - // Block 0x9e, offset 0x2780 - 0x2782: 0x00e6, 0x2783: 0x00e6, 0x2784: 0x00e6, - // Block 0x9f, offset 0x27c0 - 0x27c0: 0x3000, 0x27c1: 0x3000, 0x27c2: 0x3000, 0x27c3: 0x3000, 0x27c4: 0x3000, 0x27c5: 0x3000, - 0x27c6: 0x3000, 0x27c7: 0x3000, 0x27c8: 0x3000, 0x27c9: 0x3000, 0x27ca: 0x3000, 0x27cb: 0x3000, - 0x27cc: 0x3000, 0x27cd: 0x3000, 0x27ce: 0x3000, 0x27cf: 0x3000, 0x27d0: 0x3000, 0x27d1: 0x3000, - 0x27d2: 0x3000, 0x27d3: 0x3000, 0x27d4: 0x3000, 0x27d6: 0x3000, 0x27d7: 0x3000, - 0x27d8: 0x3000, 0x27d9: 0x3000, 0x27da: 0x3000, 0x27db: 0x3000, 0x27dc: 0x3000, 0x27dd: 0x3000, - 0x27de: 0x3000, 0x27df: 0x3000, 0x27e0: 0x3000, 0x27e1: 0x3000, 0x27e2: 0x3000, 0x27e3: 0x3000, - 0x27e4: 0x3000, 0x27e5: 0x3000, 0x27e6: 0x3000, 0x27e7: 0x3000, 0x27e8: 0x3000, 0x27e9: 0x3000, - 0x27ea: 0x3000, 0x27eb: 0x3000, 0x27ec: 0x3000, 0x27ed: 0x3000, 0x27ee: 0x3000, 0x27ef: 0x3000, - 0x27f0: 0x3000, 0x27f1: 0x3000, 0x27f2: 0x3000, 0x27f3: 0x3000, 0x27f4: 0x3000, 0x27f5: 0x3000, - 0x27f6: 0x3000, 0x27f7: 0x3000, 0x27f8: 0x3000, 0x27f9: 0x3000, 0x27fa: 0x3000, 0x27fb: 0x3000, - 0x27fc: 0x3000, 0x27fd: 0x3000, 0x27fe: 0x3000, 0x27ff: 0x3000, - // Block 0xa0, offset 0x2800 - 0x2800: 0x3000, 0x2801: 0x3000, 0x2802: 0x3000, 0x2803: 0x3000, 0x2804: 0x3000, 0x2805: 0x3000, - 0x2806: 0x3000, 0x2807: 0x3000, 0x2808: 0x3000, 0x2809: 0x3000, 0x280a: 0x3000, 0x280b: 0x3000, - 0x280c: 0x3000, 0x280d: 0x3000, 0x280e: 0x3000, 0x280f: 0x3000, 0x2810: 0x3000, 0x2811: 0x3000, - 0x2812: 0x3000, 0x2813: 0x3000, 0x2814: 0x3000, 0x2815: 0x3000, 0x2816: 0x3000, 0x2817: 0x3000, - 0x2818: 0x3000, 0x2819: 0x3000, 0x281a: 0x3000, 0x281b: 0x3000, 0x281c: 0x3000, - 0x281e: 0x3000, 0x281f: 0x3000, 0x2822: 0x3000, - 0x2825: 0x3000, 0x2826: 0x3000, 0x2829: 0x3000, - 0x282a: 0x3000, 0x282b: 0x3000, 0x282c: 0x3000, 0x282e: 0x3000, 0x282f: 0x3000, - 0x2830: 0x3000, 0x2831: 0x3000, 0x2832: 0x3000, 0x2833: 0x3000, 0x2834: 0x3000, 0x2835: 0x3000, - 0x2836: 0x3000, 0x2837: 0x3000, 0x2838: 0x3000, 0x2839: 0x3000, 0x283b: 0x3000, - 0x283d: 0x3000, 0x283e: 0x3000, 0x283f: 0x3000, - // Block 0xa1, offset 0x2840 - 0x2840: 0x3000, 0x2841: 0x3000, 0x2842: 0x3000, 0x2843: 0x3000, 0x2845: 0x3000, - 0x2846: 0x3000, 0x2847: 0x3000, 0x2848: 0x3000, 0x2849: 0x3000, 0x284a: 0x3000, 0x284b: 0x3000, - 0x284c: 0x3000, 0x284d: 0x3000, 0x284e: 0x3000, 0x284f: 0x3000, 0x2850: 0x3000, 0x2851: 0x3000, - 0x2852: 0x3000, 0x2853: 0x3000, 0x2854: 0x3000, 0x2855: 0x3000, 0x2856: 0x3000, 0x2857: 0x3000, - 0x2858: 0x3000, 0x2859: 0x3000, 0x285a: 0x3000, 0x285b: 0x3000, 0x285c: 0x3000, 0x285d: 0x3000, - 0x285e: 0x3000, 0x285f: 0x3000, 0x2860: 0x3000, 0x2861: 0x3000, 0x2862: 0x3000, 0x2863: 0x3000, - 0x2864: 0x3000, 0x2865: 0x3000, 0x2866: 0x3000, 0x2867: 0x3000, 0x2868: 0x3000, 0x2869: 0x3000, - 0x286a: 0x3000, 0x286b: 0x3000, 0x286c: 0x3000, 0x286d: 0x3000, 0x286e: 0x3000, 0x286f: 0x3000, - 0x2870: 0x3000, 0x2871: 0x3000, 0x2872: 0x3000, 0x2873: 0x3000, 0x2874: 0x3000, 0x2875: 0x3000, - 0x2876: 0x3000, 0x2877: 0x3000, 0x2878: 0x3000, 0x2879: 0x3000, 0x287a: 0x3000, 0x287b: 0x3000, - 0x287c: 0x3000, 0x287d: 0x3000, 0x287e: 0x3000, 0x287f: 0x3000, - // Block 0xa2, offset 0x2880 - 0x2880: 0x3000, 0x2881: 0x3000, 0x2882: 0x3000, 0x2883: 0x3000, 0x2884: 0x3000, 0x2885: 0x3000, - 0x2887: 0x3000, 0x2888: 0x3000, 0x2889: 0x3000, 0x288a: 0x3000, - 0x288d: 0x3000, 0x288e: 0x3000, 0x288f: 0x3000, 0x2890: 0x3000, 0x2891: 0x3000, - 0x2892: 0x3000, 0x2893: 0x3000, 0x2894: 0x3000, 0x2896: 0x3000, 0x2897: 0x3000, - 0x2898: 0x3000, 0x2899: 0x3000, 0x289a: 0x3000, 0x289b: 0x3000, 0x289c: 0x3000, - 0x289e: 0x3000, 0x289f: 0x3000, 0x28a0: 0x3000, 0x28a1: 0x3000, 0x28a2: 0x3000, 0x28a3: 0x3000, - 0x28a4: 0x3000, 0x28a5: 0x3000, 0x28a6: 0x3000, 0x28a7: 0x3000, 0x28a8: 0x3000, 0x28a9: 0x3000, - 0x28aa: 0x3000, 0x28ab: 0x3000, 0x28ac: 0x3000, 0x28ad: 0x3000, 0x28ae: 0x3000, 0x28af: 0x3000, - 0x28b0: 0x3000, 0x28b1: 0x3000, 0x28b2: 0x3000, 0x28b3: 0x3000, 0x28b4: 0x3000, 0x28b5: 0x3000, - 0x28b6: 0x3000, 0x28b7: 0x3000, 0x28b8: 0x3000, 0x28b9: 0x3000, 0x28bb: 0x3000, - 0x28bc: 0x3000, 0x28bd: 0x3000, 0x28be: 0x3000, - // Block 0xa3, offset 0x28c0 - 0x28c0: 0x3000, 0x28c1: 0x3000, 0x28c2: 0x3000, 0x28c3: 0x3000, 0x28c4: 0x3000, - 0x28c6: 0x3000, 0x28ca: 0x3000, 0x28cb: 0x3000, - 0x28cc: 0x3000, 0x28cd: 0x3000, 0x28ce: 0x3000, 0x28cf: 0x3000, 0x28d0: 0x3000, - 0x28d2: 0x3000, 0x28d3: 0x3000, 0x28d4: 0x3000, 0x28d5: 0x3000, 0x28d6: 0x3000, 0x28d7: 0x3000, - 0x28d8: 0x3000, 0x28d9: 0x3000, 0x28da: 0x3000, 0x28db: 0x3000, 0x28dc: 0x3000, 0x28dd: 0x3000, - 0x28de: 0x3000, 0x28df: 0x3000, 0x28e0: 0x3000, 0x28e1: 0x3000, 0x28e2: 0x3000, 0x28e3: 0x3000, - 0x28e4: 0x3000, 0x28e5: 0x3000, 0x28e6: 0x3000, 0x28e7: 0x3000, 0x28e8: 0x3000, 0x28e9: 0x3000, - 0x28ea: 0x3000, 0x28eb: 0x3000, 0x28ec: 0x3000, 0x28ed: 0x3000, 0x28ee: 0x3000, 0x28ef: 0x3000, - 0x28f0: 0x3000, 0x28f1: 0x3000, 0x28f2: 0x3000, 0x28f3: 0x3000, 0x28f4: 0x3000, 0x28f5: 0x3000, - 0x28f6: 0x3000, 0x28f7: 0x3000, 0x28f8: 0x3000, 0x28f9: 0x3000, 0x28fa: 0x3000, 0x28fb: 0x3000, - 0x28fc: 0x3000, 0x28fd: 0x3000, 0x28fe: 0x3000, 0x28ff: 0x3000, - // Block 0xa4, offset 0x2900 - 0x2900: 0x3000, 0x2901: 0x3000, 0x2902: 0x3000, 0x2903: 0x3000, 0x2904: 0x3000, 0x2905: 0x3000, - 0x2906: 0x3000, 0x2907: 0x3000, 0x2908: 0x3000, 0x2909: 0x3000, 0x290a: 0x3000, 0x290b: 0x3000, - 0x290c: 0x3000, 0x290d: 0x3000, 0x290e: 0x3000, 0x290f: 0x3000, 0x2910: 0x3000, 0x2911: 0x3000, - 0x2912: 0x3000, 0x2913: 0x3000, 0x2914: 0x3000, 0x2915: 0x3000, 0x2916: 0x3000, 0x2917: 0x3000, - 0x2918: 0x3000, 0x2919: 0x3000, 0x291a: 0x3000, 0x291b: 0x3000, 0x291c: 0x3000, 0x291d: 0x3000, - 0x291e: 0x3000, 0x291f: 0x3000, 0x2920: 0x3000, 0x2921: 0x3000, 0x2922: 0x3000, 0x2923: 0x3000, - 0x2924: 0x3000, 0x2925: 0x3000, 0x2928: 0x3000, 0x2929: 0x3000, - 0x292a: 0x3000, 0x292b: 0x3000, 0x292c: 0x3000, 0x292d: 0x3000, 0x292e: 0x3000, 0x292f: 0x3000, - 0x2930: 0x3000, 0x2931: 0x3000, 0x2932: 0x3000, 0x2933: 0x3000, 0x2934: 0x3000, 0x2935: 0x3000, - 0x2936: 0x3000, 0x2937: 0x3000, 0x2938: 0x3000, 0x2939: 0x3000, 0x293a: 0x3000, 0x293b: 0x3000, - 0x293c: 0x3000, 0x293d: 0x3000, 0x293e: 0x3000, 0x293f: 0x3000, - // Block 0xa5, offset 0x2940 - 0x2940: 0x3000, 0x2941: 0x3000, 0x2942: 0x3000, 0x2943: 0x3000, 0x2944: 0x3000, 0x2945: 0x3000, - 0x2946: 0x3000, 0x2947: 0x3000, 0x2948: 0x3000, 0x2949: 0x3000, 0x294a: 0x3000, 0x294b: 0x3000, - 0x294e: 0x3000, 0x294f: 0x3000, 0x2950: 0x3000, 0x2951: 0x3000, - 0x2952: 0x3000, 0x2953: 0x3000, 0x2954: 0x3000, 0x2955: 0x3000, 0x2956: 0x3000, 0x2957: 0x3000, - 0x2958: 0x3000, 0x2959: 0x3000, 0x295a: 0x3000, 0x295b: 0x3000, 0x295c: 0x3000, 0x295d: 0x3000, - 0x295e: 0x3000, 0x295f: 0x3000, 0x2960: 0x3000, 0x2961: 0x3000, 0x2962: 0x3000, 0x2963: 0x3000, - 0x2964: 0x3000, 0x2965: 0x3000, 0x2966: 0x3000, 0x2967: 0x3000, 0x2968: 0x3000, 0x2969: 0x3000, - 0x296a: 0x3000, 0x296b: 0x3000, 0x296c: 0x3000, 0x296d: 0x3000, 0x296e: 0x3000, 0x296f: 0x3000, - 0x2970: 0x3000, 0x2971: 0x3000, 0x2972: 0x3000, 0x2973: 0x3000, 0x2974: 0x3000, 0x2975: 0x3000, - 0x2976: 0x3000, 0x2977: 0x3000, 0x2978: 0x3000, 0x2979: 0x3000, 0x297a: 0x3000, 0x297b: 0x3000, - 0x297c: 0x3000, 0x297d: 0x3000, 0x297e: 0x3000, 0x297f: 0x3000, - // Block 0xa6, offset 0x2980 - 0x2980: 0x3000, 0x2981: 0x3000, 0x2982: 0x3000, 0x2983: 0x3000, 0x2984: 0x3000, 0x2985: 0x3000, - 0x2986: 0x3000, 0x2987: 0x3000, 0x2988: 0x3000, 0x2989: 0x3000, 0x298a: 0x3000, - 0x2990: 0x3000, 0x2991: 0x3000, - 0x2992: 0x3000, 0x2993: 0x3000, 0x2994: 0x3000, 0x2995: 0x3000, 0x2996: 0x3000, 0x2997: 0x3000, - 0x2998: 0x3000, 0x2999: 0x3000, 0x299a: 0x3000, 0x299b: 0x3000, 0x299c: 0x3000, 0x299d: 0x3000, - 0x299e: 0x3000, 0x299f: 0x3000, 0x29a0: 0x3000, 0x29a1: 0x3000, 0x29a2: 0x3000, 0x29a3: 0x3000, - 0x29a4: 0x3000, 0x29a5: 0x3000, 0x29a6: 0x3000, 0x29a7: 0x3000, 0x29a8: 0x3000, 0x29a9: 0x3000, - 0x29aa: 0x3000, 0x29ab: 0x3000, 0x29ac: 0x3000, 0x29ad: 0x3000, 0x29ae: 0x3000, - 0x29b0: 0x3000, 0x29b1: 0x3000, 0x29b2: 0x3000, 0x29b3: 0x3000, 0x29b4: 0x3000, 0x29b5: 0x3000, - 0x29b6: 0x3000, 0x29b7: 0x3000, 0x29b8: 0x3000, 0x29b9: 0x3000, 0x29ba: 0x3000, 0x29bb: 0x3000, - 0x29bc: 0x3000, 0x29bd: 0x3000, 0x29be: 0x3000, 0x29bf: 0x3000, - // Block 0xa7, offset 0x29c0 - 0x29c0: 0x3000, 0x29c1: 0x3000, 0x29c2: 0x3000, 0x29c3: 0x3000, 0x29c4: 0x3000, 0x29c5: 0x3000, - 0x29c6: 0x3000, 0x29c7: 0x3000, 0x29c8: 0x3000, 0x29c9: 0x3000, 0x29ca: 0x3000, 0x29cb: 0x3000, - 0x29cc: 0x3000, 0x29cd: 0x3000, 0x29ce: 0x3000, 0x29cf: 0x3000, - // Block 0xa8, offset 0x2a00 - 0x2a10: 0x3000, - // Block 0xa9, offset 0x2a40 - 0x2a40: 0x3000, 0x2a41: 0x3000, 0x2a42: 0x3000, - 0x2a50: 0x3000, 0x2a51: 0x3000, - 0x2a52: 0x3000, 0x2a53: 0x3000, 0x2a54: 0x3000, 0x2a55: 0x3000, 0x2a56: 0x3000, 0x2a57: 0x3000, - 0x2a58: 0x3000, 0x2a59: 0x3000, 0x2a5a: 0x3000, 0x2a5b: 0x3000, 0x2a5c: 0x3000, 0x2a5d: 0x3000, - 0x2a5e: 0x3000, 0x2a5f: 0x3000, 0x2a60: 0x3000, 0x2a61: 0x3000, 0x2a62: 0x3000, 0x2a63: 0x3000, - 0x2a64: 0x3000, 0x2a65: 0x3000, 0x2a66: 0x3000, 0x2a67: 0x3000, 0x2a68: 0x3000, 0x2a69: 0x3000, - 0x2a6a: 0x3000, 0x2a6b: 0x3000, 0x2a6c: 0x3000, 0x2a6d: 0x3000, 0x2a6e: 0x3000, 0x2a6f: 0x3000, - 0x2a70: 0x3000, 0x2a71: 0x3000, 0x2a72: 0x3000, 0x2a73: 0x3000, 0x2a74: 0x3000, 0x2a75: 0x3000, - 0x2a76: 0x3000, 0x2a77: 0x3000, 0x2a78: 0x3000, 0x2a79: 0x3000, 0x2a7a: 0x3000, - // Block 0xaa, offset 0x2a80 - 0x2a80: 0x3000, 0x2a81: 0x3000, 0x2a82: 0x3000, 0x2a83: 0x3000, 0x2a84: 0x3000, 0x2a85: 0x3000, - 0x2a86: 0x3000, 0x2a87: 0x3000, 0x2a88: 0x3000, - 0x2a90: 0x3000, 0x2a91: 0x3000, - // Block 0xab, offset 0x2ac0 - 0x2ac0: 0x3300, 0x2ac1: 0x3300, 0x2ac2: 0x3300, 0x2ac3: 0x3300, 0x2ac4: 0x3300, 0x2ac5: 0x3300, - 0x2ac6: 0x3300, 0x2ac7: 0x3300, 0x2ac8: 0x3300, 0x2ac9: 0x3300, 0x2aca: 0x3300, 0x2acb: 0x3300, - 0x2acc: 0x3300, 0x2acd: 0x3300, 0x2ace: 0x3300, 0x2acf: 0x3300, 0x2ad0: 0x3300, 0x2ad1: 0x3300, - 0x2ad2: 0x3300, 0x2ad3: 0x3300, 0x2ad4: 0x3300, 0x2ad5: 0x3300, 0x2ad6: 0x3300, 0x2ad7: 0x3300, - 0x2ad8: 0x3300, 0x2ad9: 0x3300, 0x2ada: 0x3300, 0x2adb: 0x3300, 0x2adc: 0x3300, 0x2add: 0x3300, + 0x03c0: 0x1100, 0x03c1: 0x8800, 0x03c2: 0x1100, 0x03c4: 0x8800, 0x03c5: 0x1100, + 0x03c6: 0x8800, 0x03c7: 0x1100, 0x03c8: 0x8800, 0x03c9: 0x1100, + 0x03cf: 0x8800, 0x03d0: 0x1100, 0x03d1: 0x1100, + 0x03d2: 0x8800, 0x03d3: 0x1100, 0x03d4: 0x1100, 0x03d5: 0x8800, 0x03d6: 0x1100, 0x03d7: 0x1100, + 0x03d8: 0x8800, 0x03d9: 0x1100, 0x03da: 0x1100, 0x03db: 0x8800, 0x03dc: 0x1100, 0x03dd: 0x1100, + 0x03ef: 0x8800, + 0x03f0: 0x8800, 0x03f1: 0x8800, 0x03f2: 0x8800, 0x03f4: 0x1100, + 0x03f7: 0x1100, 0x03f8: 0x1100, 0x03f9: 0x1100, 0x03fa: 0x1100, + 0x03fd: 0x8800, 0x03fe: 0x1100, 0x03ff: 0x3000, +} + +// charInfoSparseOffset: 156 entries, 312 bytes +var charInfoSparseOffset = []uint16{0x0, 0x8, 0x13, 0x21, 0x25, 0x2f, 0x36, 0x39, 0x3c, 0x4a, 0x56, 0x58, 0x62, 0x67, 0x6e, 0x7d, 0x8a, 0x92, 0x96, 0x9b, 0x9d, 0xa5, 0xab, 0xae, 0xb5, 0xb9, 0xbd, 0xbf, 0xc1, 0xc8, 0xcc, 0xd1, 0xd7, 0xda, 0xe3, 0xe5, 0xed, 0xf1, 0xf3, 0xf6, 0xf9, 0xff, 0x10f, 0x11b, 0x11d, 0x123, 0x125, 0x127, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x134, 0x137, 0x139, 0x13c, 0x13f, 0x143, 0x152, 0x15a, 0x15c, 0x15f, 0x161, 0x16a, 0x16e, 0x172, 0x174, 0x183, 0x187, 0x18d, 0x195, 0x199, 0x1a2, 0x1ab, 0x1b6, 0x1bc, 0x1c0, 0x1ce, 0x1dd, 0x1e1, 0x1e8, 0x1ed, 0x1fc, 0x208, 0x20b, 0x20d, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21b, 0x21d, 0x220, 0x222, 0x224, 0x226, 0x228, 0x231, 0x233, 0x236, 0x239, 0x23c, 0x23e, 0x241, 0x243, 0x245, 0x247, 0x24a, 0x24c, 0x24e, 0x250, 0x252, 0x258, 0x25a, 0x25c, 0x25e, 0x260, 0x262, 0x26c, 0x26f, 0x271, 0x27b, 0x280, 0x282, 0x284, 0x286, 0x288, 0x28b, 0x28e, 0x292, 0x29a, 0x29c, 0x29e, 0x2a5, 0x2a7, 0x2ae, 0x2b6, 0x2bd, 0x2c3, 0x2c5, 0x2c7, 0x2ca, 0x2d3, 0x2d6, 0x2dd, 0x2e2, 0x2e5, 0x2e8, 0x2ec, 0x2ee, 0x2f0, 0x2f3, 0x2f6} + +// charInfoSparseValues: 760 entries, 3040 bytes +var charInfoSparseValues = [760]valueRange{ + // Block 0x0, offset 0x1 + {value: 0x0000, lo: 0x07}, + {value: 0x3000, lo: 0xa0, hi: 0xa0}, + {value: 0x3800, lo: 0xa8, hi: 0xa8}, + {value: 0x3000, lo: 0xaa, hi: 0xaa}, + {value: 0x3000, lo: 0xaf, hi: 0xaf}, + {value: 0x3000, lo: 0xb2, hi: 0xb5}, + {value: 0x3000, lo: 0xb8, hi: 0xba}, + {value: 0x3000, lo: 0xbc, hi: 0xbe}, + // Block 0x1, offset 0x2 + {value: 0x0000, lo: 0x0a}, + {value: 0x1100, lo: 0x80, hi: 0x81}, + {value: 0x9900, lo: 0x82, hi: 0x83}, + {value: 0x1100, lo: 0x84, hi: 0x8f}, + {value: 0x9900, lo: 0x92, hi: 0x93}, + {value: 0x1100, lo: 0x94, hi: 0xa5}, + {value: 0x1100, lo: 0xa8, hi: 0xb0}, + {value: 0x3000, lo: 0xb2, hi: 0xb3}, + {value: 0x1100, lo: 0xb4, hi: 0xb7}, + {value: 0x1100, lo: 0xb9, hi: 0xbe}, + {value: 0x3000, lo: 0xbf, hi: 0xbf}, + // Block 0x2, offset 0x3 + {value: 0x0000, lo: 0x0d}, + {value: 0x3000, lo: 0x80, hi: 0x80}, + {value: 0x1100, lo: 0x83, hi: 0x88}, + {value: 0x3000, lo: 0x89, hi: 0x89}, + {value: 0x9900, lo: 0x8c, hi: 0x8d}, + {value: 0x1100, lo: 0x8e, hi: 0x91}, + {value: 0x1100, lo: 0x94, hi: 0x99}, + {value: 0x9900, lo: 0x9a, hi: 0x9b}, + {value: 0x1100, lo: 0x9c, hi: 0x9f}, + {value: 0x9900, lo: 0xa0, hi: 0xa1}, + {value: 0x1100, lo: 0xa2, hi: 0xa5}, + {value: 0x9900, lo: 0xa8, hi: 0xab}, + {value: 0x1100, lo: 0xac, hi: 0xbe}, + {value: 0x3800, lo: 0xbf, hi: 0xbf}, + // Block 0x3, offset 0x4 + {value: 0x0000, lo: 0x03}, + {value: 0x9900, lo: 0xa0, hi: 0xa1}, + {value: 0x9900, lo: 0xaf, hi: 0xb0}, + {value: 0x8800, lo: 0xb7, hi: 0xb7}, + // Block 0x4, offset 0x5 + {value: 0x0000, lo: 0x09}, + {value: 0x3000, lo: 0x84, hi: 0x8c}, + {value: 0x1100, lo: 0x8d, hi: 0x9c}, + {value: 0x1100, lo: 0x9e, hi: 0xa3}, + {value: 0x1100, lo: 0xa6, hi: 0xa9}, + {value: 0x9900, lo: 0xaa, hi: 0xab}, + {value: 0x1100, lo: 0xac, hi: 0xb0}, + {value: 0x3000, lo: 0xb1, hi: 0xb3}, + {value: 0x1100, lo: 0xb4, hi: 0xb5}, + {value: 0x1100, lo: 0xb8, hi: 0xbf}, + // Block 0x5, offset 0x6 + {value: 0x0000, lo: 0x06}, + {value: 0x1100, lo: 0x80, hi: 0x9b}, + {value: 0x1100, lo: 0x9e, hi: 0x9f}, + {value: 0x9900, lo: 0xa6, hi: 0xa9}, + {value: 0x1100, lo: 0xaa, hi: 0xad}, + {value: 0x9900, lo: 0xae, hi: 0xaf}, + {value: 0x1100, lo: 0xb0, hi: 0xb3}, + // Block 0x6, offset 0x7 + {value: 0x0000, lo: 0x02}, + {value: 0x8800, lo: 0x92, hi: 0x92}, + {value: 0x3000, lo: 0xb0, hi: 0xb8}, + // Block 0x7, offset 0x8 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x98, hi: 0x9d}, + {value: 0x3000, lo: 0xa0, hi: 0xa4}, + // Block 0x8, offset 0x9 + {value: 0x0000, lo: 0x0d}, + {value: 0x8800, lo: 0x81, hi: 0x81}, + {value: 0x8800, lo: 0x85, hi: 0x85}, + {value: 0x8800, lo: 0x89, hi: 0x89}, + {value: 0x9900, lo: 0x8a, hi: 0x8b}, + {value: 0x1100, lo: 0x8c, hi: 0x8d}, + {value: 0x9900, lo: 0x8e, hi: 0x8e}, + {value: 0x3000, lo: 0x90, hi: 0x91}, + {value: 0x3800, lo: 0x92, hi: 0x92}, + {value: 0x3100, lo: 0x93, hi: 0x94}, + {value: 0x3000, lo: 0x95, hi: 0x96}, + {value: 0x3000, lo: 0xb0, hi: 0xb2}, + {value: 0x3000, lo: 0xb4, hi: 0xb5}, + {value: 0x3000, lo: 0xb9, hi: 0xb9}, + // Block 0x9, offset 0xa + {value: 0x0000, lo: 0x0b}, + {value: 0x8800, lo: 0x83, hi: 0x83}, + {value: 0x8800, lo: 0x87, hi: 0x87}, + {value: 0x8800, lo: 0x8b, hi: 0x8b}, + {value: 0x8800, lo: 0x8d, hi: 0x8d}, + {value: 0x1100, lo: 0x90, hi: 0x91}, + {value: 0x1100, lo: 0x93, hi: 0x93}, + {value: 0x8800, lo: 0x96, hi: 0x96}, + {value: 0x1100, lo: 0x97, hi: 0x97}, + {value: 0x1100, lo: 0x9c, hi: 0x9e}, + {value: 0x8800, lo: 0xb4, hi: 0xb5}, + {value: 0x1100, lo: 0xb6, hi: 0xb7}, + // Block 0xa, offset 0xb + {value: 0x0000, lo: 0x01}, + {value: 0x00e6, lo: 0x83, hi: 0x87}, + // Block 0xb, offset 0xc + {value: 0x0000, lo: 0x09}, + {value: 0x1100, lo: 0x81, hi: 0x82}, + {value: 0x1100, lo: 0x90, hi: 0x93}, + {value: 0x1100, lo: 0x96, hi: 0x97}, + {value: 0x8800, lo: 0x98, hi: 0x99}, + {value: 0x1100, lo: 0x9a, hi: 0x9f}, + {value: 0x1100, lo: 0xa2, hi: 0xa7}, + {value: 0x8800, lo: 0xa8, hi: 0xa9}, + {value: 0x1100, lo: 0xaa, hi: 0xb5}, + {value: 0x1100, lo: 0xb8, hi: 0xb9}, + // Block 0xc, offset 0xd + {value: 0x0001, lo: 0x04}, + {value: 0x0018, lo: 0x81, hi: 0x82}, + {value: 0x00e6, lo: 0x84, hi: 0x84}, + {value: 0x00dc, lo: 0x85, hi: 0x85}, + {value: 0x0012, lo: 0x87, hi: 0x87}, + // Block 0xd, offset 0xe + {value: 0x0000, lo: 0x06}, + {value: 0x00e6, lo: 0x90, hi: 0x97}, + {value: 0x001e, lo: 0x98, hi: 0x98}, + {value: 0x001f, lo: 0x99, hi: 0x99}, + {value: 0x0020, lo: 0x9a, hi: 0x9a}, + {value: 0x1100, lo: 0xa2, hi: 0xa6}, + {value: 0x8800, lo: 0xa7, hi: 0xa7}, + // Block 0xe, offset 0xf + {value: 0x0000, lo: 0x0e}, + {value: 0x1100, lo: 0x80, hi: 0x80}, + {value: 0x8800, lo: 0x81, hi: 0x81}, + {value: 0x1100, lo: 0x82, hi: 0x82}, + {value: 0x8800, lo: 0x92, hi: 0x92}, + {value: 0x1100, lo: 0x93, hi: 0x93}, + {value: 0x8800, lo: 0x95, hi: 0x95}, + {value: 0x00e6, lo: 0x96, hi: 0x9c}, + {value: 0x00e6, lo: 0x9f, hi: 0xa2}, + {value: 0x00dc, lo: 0xa3, hi: 0xa3}, + {value: 0x00e6, lo: 0xa4, hi: 0xa4}, + {value: 0x00e6, lo: 0xa7, hi: 0xa8}, + {value: 0x00dc, lo: 0xaa, hi: 0xaa}, + {value: 0x00e6, lo: 0xab, hi: 0xac}, + {value: 0x00dc, lo: 0xad, hi: 0xad}, + // Block 0xf, offset 0x10 + {value: 0x0000, lo: 0x0c}, + {value: 0x0024, lo: 0x91, hi: 0x91}, + {value: 0x00e6, lo: 0xb0, hi: 0xb0}, + {value: 0x00dc, lo: 0xb1, hi: 0xb1}, + {value: 0x00e6, lo: 0xb2, hi: 0xb3}, + {value: 0x00dc, lo: 0xb4, hi: 0xb4}, + {value: 0x00e6, lo: 0xb5, hi: 0xb6}, + {value: 0x00dc, lo: 0xb7, hi: 0xb9}, + {value: 0x00e6, lo: 0xba, hi: 0xba}, + {value: 0x00dc, lo: 0xbb, hi: 0xbc}, + {value: 0x00e6, lo: 0xbd, hi: 0xbd}, + {value: 0x00dc, lo: 0xbe, hi: 0xbe}, + {value: 0x00e6, lo: 0xbf, hi: 0xbf}, + // Block 0x10, offset 0x11 + {value: 0x000a, lo: 0x07}, + {value: 0x00e6, lo: 0x80, hi: 0x80}, + {value: 0x00e6, lo: 0x81, hi: 0x81}, + {value: 0x00dc, lo: 0x82, hi: 0x83}, + {value: 0x00dc, lo: 0x84, hi: 0x85}, + {value: 0x00dc, lo: 0x86, hi: 0x87}, + {value: 0x00dc, lo: 0x88, hi: 0x89}, + {value: 0x00e6, lo: 0x8a, hi: 0x8a}, + // Block 0x11, offset 0x12 + {value: 0x0000, lo: 0x03}, + {value: 0x00e6, lo: 0xab, hi: 0xb1}, + {value: 0x00dc, lo: 0xb2, hi: 0xb2}, + {value: 0x00e6, lo: 0xb3, hi: 0xb3}, + // Block 0x12, offset 0x13 + {value: 0x0000, lo: 0x04}, + {value: 0x00e6, lo: 0x96, hi: 0x99}, + {value: 0x00e6, lo: 0x9b, hi: 0xa3}, + {value: 0x00e6, lo: 0xa5, hi: 0xa7}, + {value: 0x00e6, lo: 0xa9, hi: 0xad}, + // Block 0x13, offset 0x14 + {value: 0x0000, lo: 0x01}, + {value: 0x00dc, lo: 0x99, hi: 0x9b}, + // Block 0x14, offset 0x15 + {value: 0x7700, lo: 0x07}, + {value: 0x8800, lo: 0xa8, hi: 0xa8}, + {value: 0x1100, lo: 0xa9, hi: 0xa9}, + {value: 0x8800, lo: 0xb0, hi: 0xb0}, + {value: 0x1100, lo: 0xb1, hi: 0xb1}, + {value: 0x8800, lo: 0xb3, hi: 0xb3}, + {value: 0x1100, lo: 0xb4, hi: 0xb4}, + {value: 0x6607, lo: 0xbc, hi: 0xbc}, + // Block 0x15, offset 0x16 + {value: 0x0000, lo: 0x05}, + {value: 0x0009, lo: 0x8d, hi: 0x8d}, + {value: 0x00e6, lo: 0x91, hi: 0x91}, + {value: 0x00dc, lo: 0x92, hi: 0x92}, + {value: 0x00e6, lo: 0x93, hi: 0x94}, + {value: 0x3300, lo: 0x98, hi: 0x9f}, + // Block 0x16, offset 0x17 + {value: 0x65f9, lo: 0x02}, + {value: 0x0007, lo: 0xbc, hi: 0xbc}, + {value: 0x6600, lo: 0xbe, hi: 0xbe}, + // Block 0x17, offset 0x18 + {value: 0x0000, lo: 0x06}, + {value: 0x8800, lo: 0x87, hi: 0x87}, + {value: 0x1100, lo: 0x8b, hi: 0x8c}, + {value: 0x0009, lo: 0x8d, hi: 0x8d}, + {value: 0x6600, lo: 0x97, hi: 0x97}, + {value: 0x3300, lo: 0x9c, hi: 0x9d}, + {value: 0x3300, lo: 0x9f, hi: 0x9f}, + // Block 0x18, offset 0x19 + {value: 0x0000, lo: 0x03}, + {value: 0x3300, lo: 0xb3, hi: 0xb3}, + {value: 0x3300, lo: 0xb6, hi: 0xb6}, + {value: 0x0007, lo: 0xbc, hi: 0xbc}, + // Block 0x19, offset 0x1a + {value: 0x0000, lo: 0x03}, + {value: 0x0009, lo: 0x8d, hi: 0x8d}, + {value: 0x3300, lo: 0x99, hi: 0x9b}, + {value: 0x3300, lo: 0x9e, hi: 0x9e}, + // Block 0x1a, offset 0x1b + {value: 0x0000, lo: 0x01}, + {value: 0x0007, lo: 0xbc, hi: 0xbc}, + // Block 0x1b, offset 0x1c + {value: 0x0000, lo: 0x01}, + {value: 0x0009, lo: 0x8d, hi: 0x8d}, + // Block 0x1c, offset 0x1d + {value: 0x0000, lo: 0x06}, + {value: 0x8800, lo: 0x87, hi: 0x87}, + {value: 0x1100, lo: 0x88, hi: 0x88}, + {value: 0x1100, lo: 0x8b, hi: 0x8c}, + {value: 0x0009, lo: 0x8d, hi: 0x8d}, + {value: 0x6600, lo: 0x96, hi: 0x97}, + {value: 0x3300, lo: 0x9c, hi: 0x9d}, + // Block 0x1d, offset 0x1e + {value: 0x5500, lo: 0x03}, + {value: 0x8800, lo: 0x92, hi: 0x92}, + {value: 0x1100, lo: 0x94, hi: 0x94}, + {value: 0x6600, lo: 0xbe, hi: 0xbe}, + // Block 0x1e, offset 0x1f + {value: 0x0000, lo: 0x04}, + {value: 0x8800, lo: 0x86, hi: 0x87}, + {value: 0x1100, lo: 0x8a, hi: 0x8c}, + {value: 0x0009, lo: 0x8d, hi: 0x8d}, + {value: 0x6600, lo: 0x97, hi: 0x97}, + // Block 0x1f, offset 0x20 + {value: 0x004b, lo: 0x05}, + {value: 0x8800, lo: 0x86, hi: 0x86}, + {value: 0x1100, lo: 0x88, hi: 0x88}, + {value: 0x0009, lo: 0x8d, hi: 0x8d}, + {value: 0x0054, lo: 0x95, hi: 0x95}, + {value: 0x665b, lo: 0x96, hi: 0x96}, + // Block 0x20, offset 0x21 + {value: 0x87f9, lo: 0x02}, + {value: 0x0007, lo: 0xbc, hi: 0xbc}, + {value: 0x8800, lo: 0xbf, hi: 0xbf}, + // Block 0x21, offset 0x22 + {value: 0x0000, lo: 0x08}, + {value: 0x1100, lo: 0x80, hi: 0x80}, + {value: 0x6600, lo: 0x82, hi: 0x82}, + {value: 0x8800, lo: 0x86, hi: 0x86}, + {value: 0x1100, lo: 0x87, hi: 0x88}, + {value: 0x9900, lo: 0x8a, hi: 0x8a}, + {value: 0x1100, lo: 0x8b, hi: 0x8b}, + {value: 0x0009, lo: 0x8d, hi: 0x8d}, + {value: 0x6600, lo: 0x95, hi: 0x96}, + // Block 0x22, offset 0x23 + {value: 0x0000, lo: 0x01}, + {value: 0x6600, lo: 0xbe, hi: 0xbe}, + // Block 0x23, offset 0x24 + {value: 0x0000, lo: 0x07}, + {value: 0x6609, lo: 0x8a, hi: 0x8a}, + {value: 0x6600, lo: 0x8f, hi: 0x8f}, + {value: 0x8800, lo: 0x99, hi: 0x99}, + {value: 0x1100, lo: 0x9a, hi: 0x9a}, + {value: 0x9900, lo: 0x9c, hi: 0x9c}, + {value: 0x1100, lo: 0x9d, hi: 0x9e}, + {value: 0x6600, lo: 0x9f, hi: 0x9f}, + // Block 0x24, offset 0x25 + {value: 0x0000, lo: 0x03}, + {value: 0x3000, lo: 0xb3, hi: 0xb3}, + {value: 0x0067, lo: 0xb8, hi: 0xb9}, + {value: 0x0009, lo: 0xba, hi: 0xba}, + // Block 0x25, offset 0x26 + {value: 0x0000, lo: 0x01}, + {value: 0x006b, lo: 0x88, hi: 0x8b}, + // Block 0x26, offset 0x27 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0xb3, hi: 0xb3}, + {value: 0x0076, lo: 0xb8, hi: 0xb9}, + // Block 0x27, offset 0x28 + {value: 0x0000, lo: 0x02}, + {value: 0x007a, lo: 0x88, hi: 0x8b}, + {value: 0x3000, lo: 0x9c, hi: 0x9d}, + // Block 0x28, offset 0x29 + {value: 0x0000, lo: 0x05}, + {value: 0x3000, lo: 0x8c, hi: 0x8c}, + {value: 0x00dc, lo: 0x98, hi: 0x99}, + {value: 0x00dc, lo: 0xb5, hi: 0xb5}, + {value: 0x00dc, lo: 0xb7, hi: 0xb7}, + {value: 0x00d8, lo: 0xb9, hi: 0xb9}, + // Block 0x29, offset 0x2a + {value: 0x0000, lo: 0x0f}, + {value: 0x3300, lo: 0x83, hi: 0x83}, + {value: 0x3300, lo: 0x8d, hi: 0x8d}, + {value: 0x3300, lo: 0x92, hi: 0x92}, + {value: 0x3300, lo: 0x97, hi: 0x97}, + {value: 0x3300, lo: 0x9c, hi: 0x9c}, + {value: 0x3300, lo: 0xa9, hi: 0xa9}, + {value: 0x0081, lo: 0xb1, hi: 0xb1}, + {value: 0x0082, lo: 0xb2, hi: 0xb2}, + {value: 0x3300, lo: 0xb3, hi: 0xb3}, + {value: 0x0084, lo: 0xb4, hi: 0xb4}, + {value: 0x3300, lo: 0xb5, hi: 0xb6}, + {value: 0x3000, lo: 0xb7, hi: 0xb7}, + {value: 0x3300, lo: 0xb8, hi: 0xb8}, + {value: 0x3000, lo: 0xb9, hi: 0xb9}, + {value: 0x0082, lo: 0xba, hi: 0xbd}, + // Block 0x2a, offset 0x2b + {value: 0x0000, lo: 0x0b}, + {value: 0x0082, lo: 0x80, hi: 0x80}, + {value: 0x3300, lo: 0x81, hi: 0x81}, + {value: 0x00e6, lo: 0x82, hi: 0x83}, + {value: 0x0009, lo: 0x84, hi: 0x84}, + {value: 0x00e6, lo: 0x86, hi: 0x87}, + {value: 0x3300, lo: 0x93, hi: 0x93}, + {value: 0x3300, lo: 0x9d, hi: 0x9d}, + {value: 0x3300, lo: 0xa2, hi: 0xa2}, + {value: 0x3300, lo: 0xa7, hi: 0xa7}, + {value: 0x3300, lo: 0xac, hi: 0xac}, + {value: 0x3300, lo: 0xb9, hi: 0xb9}, + // Block 0x2b, offset 0x2c + {value: 0x0000, lo: 0x01}, + {value: 0x00dc, lo: 0x86, hi: 0x86}, + // Block 0x2c, offset 0x2d + {value: 0x0000, lo: 0x05}, + {value: 0x8800, lo: 0xa5, hi: 0xa5}, + {value: 0x1100, lo: 0xa6, hi: 0xa6}, + {value: 0x6600, lo: 0xae, hi: 0xae}, + {value: 0x0007, lo: 0xb7, hi: 0xb7}, + {value: 0x0009, lo: 0xb9, hi: 0xba}, + // Block 0x2d, offset 0x2e + {value: 0x0000, lo: 0x01}, + {value: 0x00dc, lo: 0x8d, hi: 0x8d}, + // Block 0x2e, offset 0x2f + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0xbc, hi: 0xbc}, + // Block 0x2f, offset 0x30 + {value: 0x0000, lo: 0x01}, + {value: 0x8800, lo: 0x80, hi: 0x92}, + // Block 0x30, offset 0x31 + {value: 0x0000, lo: 0x01}, + {value: 0xee00, lo: 0xa1, hi: 0xb5}, + // Block 0x31, offset 0x32 + {value: 0x0000, lo: 0x01}, + {value: 0x6600, lo: 0xa8, hi: 0xbf}, + // Block 0x32, offset 0x33 + {value: 0x0000, lo: 0x01}, + {value: 0x6600, lo: 0x80, hi: 0x82}, + // Block 0x33, offset 0x34 + {value: 0x0000, lo: 0x01}, + {value: 0x00e6, lo: 0x9d, hi: 0x9f}, + // Block 0x34, offset 0x35 + {value: 0x0000, lo: 0x02}, + {value: 0x0009, lo: 0x94, hi: 0x94}, + {value: 0x0009, lo: 0xb4, hi: 0xb4}, + // Block 0x35, offset 0x36 + {value: 0x00dd, lo: 0x02}, + {value: 0x0009, lo: 0x92, hi: 0x92}, + {value: 0x00e6, lo: 0x9d, hi: 0x9d}, + // Block 0x36, offset 0x37 + {value: 0x0000, lo: 0x01}, + {value: 0x00e4, lo: 0xa9, hi: 0xa9}, + // Block 0x37, offset 0x38 + {value: 0x0008, lo: 0x02}, + {value: 0x00de, lo: 0xb9, hi: 0xba}, + {value: 0x00dc, lo: 0xbb, hi: 0xbb}, + // Block 0x38, offset 0x39 + {value: 0x0000, lo: 0x02}, + {value: 0x00e6, lo: 0x97, hi: 0x97}, + {value: 0x00dc, lo: 0x98, hi: 0x98}, + // Block 0x39, offset 0x3a + {value: 0x0000, lo: 0x03}, + {value: 0x0009, lo: 0xa0, hi: 0xa0}, + {value: 0x00e6, lo: 0xb5, hi: 0xbc}, + {value: 0x00dc, lo: 0xbf, hi: 0xbf}, + // Block 0x3a, offset 0x3b + {value: 0x7700, lo: 0x0e}, + {value: 0x8800, lo: 0x85, hi: 0x85}, + {value: 0x1100, lo: 0x86, hi: 0x87}, + {value: 0x1100, lo: 0x88, hi: 0x89}, + {value: 0x1100, lo: 0x8a, hi: 0x8b}, + {value: 0x1100, lo: 0x8c, hi: 0x8d}, + {value: 0x1100, lo: 0x8e, hi: 0x8e}, + {value: 0x8800, lo: 0x91, hi: 0x91}, + {value: 0x1100, lo: 0x92, hi: 0x92}, + {value: 0x0007, lo: 0xb4, hi: 0xb4}, + {value: 0x6600, lo: 0xb5, hi: 0xb5}, + {value: 0x8800, lo: 0xba, hi: 0xba}, + {value: 0x1100, lo: 0xbb, hi: 0xbc}, + {value: 0x1100, lo: 0xbd, hi: 0xbe}, + {value: 0x8800, lo: 0xbf, hi: 0xbf}, + // Block 0x3b, offset 0x3c + {value: 0x0000, lo: 0x07}, + {value: 0x1100, lo: 0x80, hi: 0x81}, + {value: 0x8800, lo: 0x82, hi: 0x82}, + {value: 0x1100, lo: 0x83, hi: 0x83}, + {value: 0x0009, lo: 0x84, hi: 0x84}, + {value: 0x00e6, lo: 0xab, hi: 0xab}, + {value: 0x00dc, lo: 0xac, hi: 0xac}, + {value: 0x00e6, lo: 0xad, hi: 0xb3}, + // Block 0x3c, offset 0x3d + {value: 0x0000, lo: 0x01}, + {value: 0x0009, lo: 0xaa, hi: 0xaa}, + // Block 0x3d, offset 0x3e + {value: 0x0000, lo: 0x02}, + {value: 0x0007, lo: 0xa6, hi: 0xa6}, + {value: 0x0009, lo: 0xb2, hi: 0xb3}, + // Block 0x3e, offset 0x3f + {value: 0x0000, lo: 0x01}, + {value: 0x0007, lo: 0xb7, hi: 0xb7}, + // Block 0x3f, offset 0x40 + {value: 0x0000, lo: 0x08}, + {value: 0x00e6, lo: 0x90, hi: 0x92}, + {value: 0x0001, lo: 0x94, hi: 0x94}, + {value: 0x00dc, lo: 0x95, hi: 0x99}, + {value: 0x00e6, lo: 0x9a, hi: 0x9b}, + {value: 0x00dc, lo: 0x9c, hi: 0x9f}, + {value: 0x00e6, lo: 0xa0, hi: 0xa0}, + {value: 0x0001, lo: 0xa2, hi: 0xa8}, + {value: 0x00dc, lo: 0xad, hi: 0xad}, + // Block 0x40, offset 0x41 + {value: 0x0000, lo: 0x03}, + {value: 0x3000, lo: 0xac, hi: 0xae}, + {value: 0x3000, lo: 0xb0, hi: 0xba}, + {value: 0x3000, lo: 0xbc, hi: 0xbf}, + // Block 0x41, offset 0x42 + {value: 0x0000, lo: 0x03}, + {value: 0x3000, lo: 0x80, hi: 0x8d}, + {value: 0x3000, lo: 0x8f, hi: 0xaa}, + {value: 0x3000, lo: 0xb8, hi: 0xb8}, + // Block 0x42, offset 0x43 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x9b, hi: 0xbf}, + // Block 0x43, offset 0x44 + {value: 0x0000, lo: 0x0e}, + {value: 0x00e6, lo: 0x80, hi: 0x81}, + {value: 0x00dc, lo: 0x82, hi: 0x82}, + {value: 0x00e6, lo: 0x83, hi: 0x89}, + {value: 0x00dc, lo: 0x8a, hi: 0x8a}, + {value: 0x00e6, lo: 0x8b, hi: 0x8c}, + {value: 0x00ea, lo: 0x8d, hi: 0x8d}, + {value: 0x00d6, lo: 0x8e, hi: 0x8e}, + {value: 0x00dc, lo: 0x8f, hi: 0x8f}, + {value: 0x00ca, lo: 0x90, hi: 0x90}, + {value: 0x00e6, lo: 0x91, hi: 0xa6}, + {value: 0x00e9, lo: 0xbc, hi: 0xbc}, + {value: 0x00dc, lo: 0xbd, hi: 0xbd}, + {value: 0x00e6, lo: 0xbe, hi: 0xbe}, + {value: 0x00dc, lo: 0xbf, hi: 0xbf}, + // Block 0x44, offset 0x45 + {value: 0x0000, lo: 0x03}, + {value: 0x1100, lo: 0x80, hi: 0xb5}, + {value: 0x9900, lo: 0xb6, hi: 0xb7}, + {value: 0x1100, lo: 0xb8, hi: 0xbf}, + // Block 0x45, offset 0x46 + {value: 0x0000, lo: 0x05}, + {value: 0x1100, lo: 0x80, hi: 0x99}, + {value: 0x9900, lo: 0x9a, hi: 0x9b}, + {value: 0x1100, lo: 0x9c, hi: 0xa1}, + {value: 0x9900, lo: 0xa2, hi: 0xa3}, + {value: 0x1100, lo: 0xa4, hi: 0xbf}, + // Block 0x46, offset 0x47 + {value: 0x0000, lo: 0x07}, + {value: 0x1100, lo: 0x80, hi: 0x99}, + {value: 0x3000, lo: 0x9a, hi: 0x9a}, + {value: 0x3100, lo: 0x9b, hi: 0x9b}, + {value: 0x9900, lo: 0xa0, hi: 0xa1}, + {value: 0x1100, lo: 0xa2, hi: 0xb7}, + {value: 0x9900, lo: 0xb8, hi: 0xb9}, + {value: 0x1100, lo: 0xba, hi: 0xbf}, + // Block 0x47, offset 0x48 + {value: 0x0000, lo: 0x03}, + {value: 0x1100, lo: 0x80, hi: 0x8b}, + {value: 0x9900, lo: 0x8c, hi: 0x8d}, + {value: 0x1100, lo: 0x8e, hi: 0xb9}, + // Block 0x48, offset 0x49 + {value: 0x0000, lo: 0x08}, + {value: 0x9900, lo: 0x80, hi: 0x91}, + {value: 0x1100, lo: 0x92, hi: 0x95}, + {value: 0x9900, lo: 0x98, hi: 0x99}, + {value: 0x1100, lo: 0x9a, hi: 0x9d}, + {value: 0x9900, lo: 0xa0, hi: 0xb1}, + {value: 0x1100, lo: 0xb2, hi: 0xb7}, + {value: 0x9900, lo: 0xb8, hi: 0xb9}, + {value: 0x1100, lo: 0xba, hi: 0xbf}, + // Block 0x49, offset 0x4a + {value: 0x0000, lo: 0x08}, + {value: 0x1100, lo: 0x80, hi: 0xb4}, + {value: 0x9900, lo: 0xb6, hi: 0xb6}, + {value: 0x1100, lo: 0xb7, hi: 0xba}, + {value: 0x3300, lo: 0xbb, hi: 0xbb}, + {value: 0x1100, lo: 0xbc, hi: 0xbc}, + {value: 0x3000, lo: 0xbd, hi: 0xbd}, + {value: 0x3300, lo: 0xbe, hi: 0xbe}, + {value: 0x3800, lo: 0xbf, hi: 0xbf}, + // Block 0x4a, offset 0x4b + {value: 0x0000, lo: 0x0a}, + {value: 0x3300, lo: 0x80, hi: 0x81}, + {value: 0x3000, lo: 0x82, hi: 0x8a}, + {value: 0x3000, lo: 0x91, hi: 0x91}, + {value: 0x3000, lo: 0x97, hi: 0x97}, + {value: 0x3000, lo: 0xa4, hi: 0xa6}, + {value: 0x3000, lo: 0xaf, hi: 0xaf}, + {value: 0x3000, lo: 0xb3, hi: 0xb4}, + {value: 0x3000, lo: 0xb6, hi: 0xb7}, + {value: 0x3000, lo: 0xbc, hi: 0xbc}, + {value: 0x3000, lo: 0xbe, hi: 0xbe}, + // Block 0x4b, offset 0x4c + {value: 0x0000, lo: 0x05}, + {value: 0x3000, lo: 0x87, hi: 0x89}, + {value: 0x3000, lo: 0x97, hi: 0x97}, + {value: 0x3000, lo: 0x9f, hi: 0x9f}, + {value: 0x3000, lo: 0xb0, hi: 0xb1}, + {value: 0x3000, lo: 0xb4, hi: 0xbf}, + // Block 0x4c, offset 0x4d + {value: 0x0000, lo: 0x03}, + {value: 0x3000, lo: 0x80, hi: 0x8e}, + {value: 0x3000, lo: 0x90, hi: 0x9c}, + {value: 0x3000, lo: 0xa8, hi: 0xa8}, + // Block 0x4d, offset 0x4e + {value: 0x0000, lo: 0x0d}, + {value: 0x00e6, lo: 0x90, hi: 0x91}, + {value: 0x0001, lo: 0x92, hi: 0x93}, + {value: 0x00e6, lo: 0x94, hi: 0x97}, + {value: 0x0001, lo: 0x98, hi: 0x9a}, + {value: 0x00e6, lo: 0x9b, hi: 0x9c}, + {value: 0x00e6, lo: 0xa1, hi: 0xa1}, + {value: 0x0001, lo: 0xa5, hi: 0xa6}, + {value: 0x00e6, lo: 0xa7, hi: 0xa7}, + {value: 0x00dc, lo: 0xa8, hi: 0xa8}, + {value: 0x00e6, lo: 0xa9, hi: 0xa9}, + {value: 0x0001, lo: 0xaa, hi: 0xab}, + {value: 0x00dc, lo: 0xac, hi: 0xaf}, + {value: 0x00e6, lo: 0xb0, hi: 0xb0}, + // Block 0x4e, offset 0x4f + {value: 0x0000, lo: 0x0e}, + {value: 0x3000, lo: 0x80, hi: 0x83}, + {value: 0x3000, lo: 0x85, hi: 0x87}, + {value: 0x3000, lo: 0x89, hi: 0x93}, + {value: 0x3000, lo: 0x95, hi: 0x96}, + {value: 0x3000, lo: 0x99, hi: 0x9d}, + {value: 0x3000, lo: 0xa0, hi: 0xa2}, + {value: 0x3000, lo: 0xa4, hi: 0xa4}, + {value: 0x3300, lo: 0xa6, hi: 0xa6}, + {value: 0x3000, lo: 0xa8, hi: 0xa8}, + {value: 0x3300, lo: 0xaa, hi: 0xab}, + {value: 0x3000, lo: 0xac, hi: 0xad}, + {value: 0x3000, lo: 0xaf, hi: 0xb1}, + {value: 0x3000, lo: 0xb3, hi: 0xb9}, + {value: 0x3000, lo: 0xbb, hi: 0xbf}, + // Block 0x4f, offset 0x50 + {value: 0x0000, lo: 0x03}, + {value: 0x3000, lo: 0x80, hi: 0x80}, + {value: 0x3000, lo: 0x85, hi: 0x89}, + {value: 0x3000, lo: 0x90, hi: 0xbf}, + // Block 0x50, offset 0x51 + {value: 0x0000, lo: 0x06}, + {value: 0x3000, lo: 0x89, hi: 0x89}, + {value: 0x8800, lo: 0x90, hi: 0x90}, + {value: 0x8800, lo: 0x92, hi: 0x92}, + {value: 0x8800, lo: 0x94, hi: 0x94}, + {value: 0x1100, lo: 0x9a, hi: 0x9b}, + {value: 0x1100, lo: 0xae, hi: 0xae}, + // Block 0x51, offset 0x52 + {value: 0x0000, lo: 0x04}, + {value: 0x1100, lo: 0x8d, hi: 0x8f}, + {value: 0x8800, lo: 0x90, hi: 0x90}, + {value: 0x8800, lo: 0x92, hi: 0x92}, + {value: 0x8800, lo: 0x94, hi: 0x94}, + // Block 0x52, offset 0x53 + {value: 0x7700, lo: 0x0e}, + {value: 0x8800, lo: 0x83, hi: 0x83}, + {value: 0x1100, lo: 0x84, hi: 0x84}, + {value: 0x8800, lo: 0x88, hi: 0x88}, + {value: 0x1100, lo: 0x89, hi: 0x89}, + {value: 0x8800, lo: 0x8b, hi: 0x8b}, + {value: 0x1100, lo: 0x8c, hi: 0x8c}, + {value: 0x8800, lo: 0xa3, hi: 0xa3}, + {value: 0x1100, lo: 0xa4, hi: 0xa5}, + {value: 0x1100, lo: 0xa6, hi: 0xa6}, + {value: 0x3000, lo: 0xac, hi: 0xac}, + {value: 0x3000, lo: 0xad, hi: 0xad}, + {value: 0x3000, lo: 0xaf, hi: 0xaf}, + {value: 0x3000, lo: 0xb0, hi: 0xb0}, + {value: 0x8800, lo: 0xbc, hi: 0xbc}, + // Block 0x53, offset 0x54 + {value: 0x0000, lo: 0x0b}, + {value: 0x1100, lo: 0x80, hi: 0x81}, + {value: 0x8800, lo: 0x82, hi: 0x83}, + {value: 0x1100, lo: 0x84, hi: 0x85}, + {value: 0x8800, lo: 0x86, hi: 0x87}, + {value: 0x1100, lo: 0x88, hi: 0x89}, + {value: 0x8800, lo: 0x91, hi: 0x92}, + {value: 0x8800, lo: 0xa2, hi: 0xa2}, + {value: 0x8800, lo: 0xa8, hi: 0xa9}, + {value: 0x8800, lo: 0xab, hi: 0xab}, + {value: 0x1100, lo: 0xac, hi: 0xaf}, + {value: 0x8800, lo: 0xb2, hi: 0xb5}, + // Block 0x54, offset 0x55 + {value: 0x0000, lo: 0x02}, + {value: 0x1100, lo: 0xa0, hi: 0xa3}, + {value: 0x1100, lo: 0xaa, hi: 0xad}, + // Block 0x55, offset 0x56 + {value: 0x0000, lo: 0x01}, + {value: 0x3300, lo: 0xa9, hi: 0xaa}, + // Block 0x56, offset 0x57 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0xa0, hi: 0xbf}, + // Block 0x57, offset 0x58 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x80, hi: 0xbf}, + // Block 0x58, offset 0x59 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x80, hi: 0xaa}, + // Block 0x59, offset 0x5a + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x8c, hi: 0x8c}, + // Block 0x5a, offset 0x5b + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0xb4, hi: 0xb6}, + // Block 0x5b, offset 0x5c + {value: 0x0000, lo: 0x01}, + {value: 0x3300, lo: 0x9c, hi: 0x9c}, + // Block 0x5c, offset 0x5d + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0xbc, hi: 0xbd}, + // Block 0x5d, offset 0x5e + {value: 0x0000, lo: 0x01}, + {value: 0x00e6, lo: 0xaf, hi: 0xb1}, + // Block 0x5e, offset 0x5f + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0xaf, hi: 0xaf}, + {value: 0x0009, lo: 0xbf, hi: 0xbf}, + // Block 0x5f, offset 0x60 + {value: 0x0000, lo: 0x01}, + {value: 0x00e6, lo: 0xa0, hi: 0xbf}, + // Block 0x60, offset 0x61 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x9f, hi: 0x9f}, + // Block 0x61, offset 0x62 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0xb3, hi: 0xb3}, + // Block 0x62, offset 0x63 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x80, hi: 0x95}, + // Block 0x63, offset 0x64 + {value: 0x0000, lo: 0x08}, + {value: 0x3000, lo: 0x80, hi: 0x80}, + {value: 0x00da, lo: 0xaa, hi: 0xaa}, + {value: 0x00e4, lo: 0xab, hi: 0xab}, + {value: 0x00e8, lo: 0xac, hi: 0xac}, + {value: 0x00de, lo: 0xad, hi: 0xad}, + {value: 0x00e0, lo: 0xae, hi: 0xaf}, + {value: 0x3000, lo: 0xb6, hi: 0xb6}, + {value: 0x3000, lo: 0xb8, hi: 0xba}, + // Block 0x64, offset 0x65 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0xb1, hi: 0xbf}, + // Block 0x65, offset 0x66 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0x8e}, + {value: 0x3000, lo: 0x92, hi: 0x9f}, + // Block 0x66, offset 0x67 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0x9e}, + {value: 0x3000, lo: 0xa0, hi: 0xbf}, + // Block 0x67, offset 0x68 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0x87}, + {value: 0x3000, lo: 0x90, hi: 0xbe}, + // Block 0x68, offset 0x69 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x80, hi: 0xbe}, + // Block 0x69, offset 0x6a + {value: 0x0000, lo: 0x02}, + {value: 0x00e6, lo: 0xaf, hi: 0xaf}, + {value: 0x00e6, lo: 0xbc, hi: 0xbd}, + // Block 0x6a, offset 0x6b + {value: 0x0000, lo: 0x01}, + {value: 0x00e6, lo: 0xb0, hi: 0xb1}, + // Block 0x6b, offset 0x6c + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0xb0, hi: 0xb0}, + // Block 0x6c, offset 0x6d + {value: 0x0000, lo: 0x01}, + {value: 0x0009, lo: 0x86, hi: 0x86}, + // Block 0x6d, offset 0x6e + {value: 0x0000, lo: 0x02}, + {value: 0x0009, lo: 0x84, hi: 0x84}, + {value: 0x00e6, lo: 0xa0, hi: 0xb1}, + // Block 0x6e, offset 0x6f + {value: 0x0000, lo: 0x01}, + {value: 0x00dc, lo: 0xab, hi: 0xad}, + // Block 0x6f, offset 0x70 + {value: 0x0000, lo: 0x01}, + {value: 0x0009, lo: 0x93, hi: 0x93}, + // Block 0x70, offset 0x71 + {value: 0x0000, lo: 0x01}, + {value: 0x0007, lo: 0xb3, hi: 0xb3}, + // Block 0x71, offset 0x72 + {value: 0x0000, lo: 0x01}, + {value: 0x0009, lo: 0x80, hi: 0x80}, + // Block 0x72, offset 0x73 + {value: 0x0000, lo: 0x05}, + {value: 0x00e6, lo: 0xb0, hi: 0xb0}, + {value: 0x00e6, lo: 0xb2, hi: 0xb3}, + {value: 0x00dc, lo: 0xb4, hi: 0xb4}, + {value: 0x00e6, lo: 0xb7, hi: 0xb8}, + {value: 0x00e6, lo: 0xbe, hi: 0xbf}, + // Block 0x73, offset 0x74 + {value: 0x0000, lo: 0x01}, + {value: 0x00e6, lo: 0x81, hi: 0x81}, + // Block 0x74, offset 0x75 + {value: 0x0000, lo: 0x01}, + {value: 0x0009, lo: 0xad, hi: 0xad}, + // Block 0x75, offset 0x76 + {value: 0x0000, lo: 0x01}, + {value: 0x1100, lo: 0x80, hi: 0xbf}, + // Block 0x76, offset 0x77 + {value: 0x0000, lo: 0x01}, + {value: 0x1100, lo: 0x80, hi: 0xa3}, + // Block 0x77, offset 0x78 + {value: 0x0000, lo: 0x01}, + {value: 0x3300, lo: 0x80, hi: 0xbf}, + // Block 0x78, offset 0x79 + {value: 0x0000, lo: 0x09}, + {value: 0x3300, lo: 0x80, hi: 0x8d}, + {value: 0x3300, lo: 0x90, hi: 0x90}, + {value: 0x3300, lo: 0x92, hi: 0x92}, + {value: 0x3300, lo: 0x95, hi: 0x9e}, + {value: 0x3300, lo: 0xa0, hi: 0xa0}, + {value: 0x3300, lo: 0xa2, hi: 0xa2}, + {value: 0x3300, lo: 0xa5, hi: 0xa6}, + {value: 0x3300, lo: 0xaa, hi: 0xad}, + {value: 0x3300, lo: 0xb0, hi: 0xbf}, + // Block 0x79, offset 0x7a + {value: 0x0000, lo: 0x02}, + {value: 0x3300, lo: 0x80, hi: 0xad}, + {value: 0x3300, lo: 0xb0, hi: 0xbf}, + // Block 0x7a, offset 0x7b + {value: 0x0000, lo: 0x01}, + {value: 0x3300, lo: 0x80, hi: 0x99}, + // Block 0x7b, offset 0x7c + {value: 0x0000, lo: 0x09}, + {value: 0x3000, lo: 0x80, hi: 0x86}, + {value: 0x3000, lo: 0x93, hi: 0x97}, + {value: 0x3300, lo: 0x9d, hi: 0x9d}, + {value: 0x001a, lo: 0x9e, hi: 0x9e}, + {value: 0x3300, lo: 0x9f, hi: 0x9f}, + {value: 0x3000, lo: 0xa0, hi: 0xa9}, + {value: 0x3300, lo: 0xaa, hi: 0xb6}, + {value: 0x3300, lo: 0xb8, hi: 0xbc}, + {value: 0x3300, lo: 0xbe, hi: 0xbe}, + // Block 0x7c, offset 0x7d + {value: 0x0000, lo: 0x04}, + {value: 0x3300, lo: 0x80, hi: 0x81}, + {value: 0x3300, lo: 0x83, hi: 0x84}, + {value: 0x3300, lo: 0x86, hi: 0x8e}, + {value: 0x3000, lo: 0x8f, hi: 0xbf}, + // Block 0x7d, offset 0x7e + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x80, hi: 0xb1}, + // Block 0x7e, offset 0x7f + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x93, hi: 0xbf}, + // Block 0x7f, offset 0x80 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x80, hi: 0xbd}, + // Block 0x80, offset 0x81 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x90, hi: 0xbf}, + // Block 0x81, offset 0x82 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0x8f}, + {value: 0x3000, lo: 0x92, hi: 0xbf}, + // Block 0x82, offset 0x83 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0x87}, + {value: 0x3000, lo: 0xb0, hi: 0xbc}, + // Block 0x83, offset 0x84 + {value: 0x0000, lo: 0x03}, + {value: 0x3000, lo: 0x90, hi: 0x99}, + {value: 0x00e6, lo: 0xa0, hi: 0xa6}, + {value: 0x3000, lo: 0xb0, hi: 0xbf}, + // Block 0x84, offset 0x85 + {value: 0x0000, lo: 0x07}, + {value: 0x3000, lo: 0x80, hi: 0x84}, + {value: 0x3000, lo: 0x87, hi: 0x92}, + {value: 0x3000, lo: 0x94, hi: 0xa6}, + {value: 0x3000, lo: 0xa8, hi: 0xab}, + {value: 0x3000, lo: 0xb0, hi: 0xb2}, + {value: 0x3000, lo: 0xb4, hi: 0xb4}, + {value: 0x3000, lo: 0xb6, hi: 0xbf}, + // Block 0x85, offset 0x86 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x80, hi: 0xbc}, + // Block 0x86, offset 0x87 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x81, hi: 0xbf}, + // Block 0x87, offset 0x88 + {value: 0x0000, lo: 0x06}, + {value: 0x3000, lo: 0x82, hi: 0x87}, + {value: 0x3000, lo: 0x8a, hi: 0x8f}, + {value: 0x3000, lo: 0x92, hi: 0x97}, + {value: 0x3000, lo: 0x9a, hi: 0x9c}, + {value: 0x3000, lo: 0xa0, hi: 0xa6}, + {value: 0x3000, lo: 0xa8, hi: 0xae}, + // Block 0x88, offset 0x89 + {value: 0x0000, lo: 0x01}, + {value: 0x00dc, lo: 0xbd, hi: 0xbd}, + // Block 0x89, offset 0x8a + {value: 0x0000, lo: 0x06}, + {value: 0x00dc, lo: 0x8d, hi: 0x8d}, + {value: 0x00e6, lo: 0x8f, hi: 0x8f}, + {value: 0x00e6, lo: 0xb8, hi: 0xb8}, + {value: 0x0001, lo: 0xb9, hi: 0xb9}, + {value: 0x00dc, lo: 0xba, hi: 0xba}, + {value: 0x0009, lo: 0xbf, hi: 0xbf}, + // Block 0x8a, offset 0x8b + {value: 0x7700, lo: 0x07}, + {value: 0x8800, lo: 0x99, hi: 0x99}, + {value: 0x1100, lo: 0x9a, hi: 0x9b}, + {value: 0x1100, lo: 0x9c, hi: 0x9c}, + {value: 0x8800, lo: 0xa5, hi: 0xa5}, + {value: 0x1100, lo: 0xab, hi: 0xab}, + {value: 0x0009, lo: 0xb9, hi: 0xb9}, + {value: 0x6607, lo: 0xba, hi: 0xba}, + // Block 0x8b, offset 0x8c + {value: 0x0000, lo: 0x06}, + {value: 0x3300, lo: 0x9e, hi: 0xa4}, + {value: 0x00d8, lo: 0xa5, hi: 0xa6}, + {value: 0x0001, lo: 0xa7, hi: 0xa9}, + {value: 0x00e2, lo: 0xad, hi: 0xad}, + {value: 0x00d8, lo: 0xae, hi: 0xb2}, + {value: 0x00dc, lo: 0xbb, hi: 0xbf}, + // Block 0x8c, offset 0x8d + {value: 0x0000, lo: 0x05}, + {value: 0x00dc, lo: 0x80, hi: 0x82}, + {value: 0x00e6, lo: 0x85, hi: 0x89}, + {value: 0x00dc, lo: 0x8a, hi: 0x8b}, + {value: 0x00e6, lo: 0xaa, hi: 0xad}, + {value: 0x3300, lo: 0xbb, hi: 0xbf}, + // Block 0x8d, offset 0x8e + {value: 0x0000, lo: 0x01}, + {value: 0x3300, lo: 0x80, hi: 0x80}, + // Block 0x8e, offset 0x8f + {value: 0x0000, lo: 0x01}, + {value: 0x00e6, lo: 0x82, hi: 0x84}, + // Block 0x8f, offset 0x90 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0x94}, + {value: 0x3000, lo: 0x96, hi: 0xbf}, + // Block 0x90, offset 0x91 + {value: 0x0000, lo: 0x08}, + {value: 0x3000, lo: 0x80, hi: 0x9c}, + {value: 0x3000, lo: 0x9e, hi: 0x9f}, + {value: 0x3000, lo: 0xa2, hi: 0xa2}, + {value: 0x3000, lo: 0xa5, hi: 0xa6}, + {value: 0x3000, lo: 0xa9, hi: 0xac}, + {value: 0x3000, lo: 0xae, hi: 0xb9}, + {value: 0x3000, lo: 0xbb, hi: 0xbb}, + {value: 0x3000, lo: 0xbd, hi: 0xbf}, + // Block 0x91, offset 0x92 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0x83}, + {value: 0x3000, lo: 0x85, hi: 0xbf}, + // Block 0x92, offset 0x93 + {value: 0x0000, lo: 0x06}, + {value: 0x3000, lo: 0x80, hi: 0x85}, + {value: 0x3000, lo: 0x87, hi: 0x8a}, + {value: 0x3000, lo: 0x8d, hi: 0x94}, + {value: 0x3000, lo: 0x96, hi: 0x9c}, + {value: 0x3000, lo: 0x9e, hi: 0xb9}, + {value: 0x3000, lo: 0xbb, hi: 0xbe}, + // Block 0x93, offset 0x94 + {value: 0x0000, lo: 0x04}, + {value: 0x3000, lo: 0x80, hi: 0x84}, + {value: 0x3000, lo: 0x86, hi: 0x86}, + {value: 0x3000, lo: 0x8a, hi: 0x90}, + {value: 0x3000, lo: 0x92, hi: 0xbf}, + // Block 0x94, offset 0x95 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0xa5}, + {value: 0x3000, lo: 0xa8, hi: 0xbf}, + // Block 0x95, offset 0x96 + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0x8b}, + {value: 0x3000, lo: 0x8e, hi: 0xbf}, + // Block 0x96, offset 0x97 + {value: 0x0000, lo: 0x03}, + {value: 0x3000, lo: 0x80, hi: 0x8a}, + {value: 0x3000, lo: 0x90, hi: 0xae}, + {value: 0x3000, lo: 0xb0, hi: 0xbf}, + // Block 0x97, offset 0x98 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x80, hi: 0x8f}, + // Block 0x98, offset 0x99 + {value: 0x0000, lo: 0x01}, + {value: 0x3000, lo: 0x90, hi: 0x90}, + // Block 0x99, offset 0x9a + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0x82}, + {value: 0x3000, lo: 0x90, hi: 0xba}, + // Block 0x9a, offset 0x9b + {value: 0x0000, lo: 0x02}, + {value: 0x3000, lo: 0x80, hi: 0x88}, + {value: 0x3000, lo: 0x90, hi: 0x91}, + // Block 0x9b, offset 0x9c + {value: 0x0000, lo: 0x01}, + {value: 0x3300, lo: 0x80, hi: 0x9d}, } // charInfoLookup: 1152 bytes @@ -6511,36 +6689,36 @@ var charInfoLookup = [1152]uint8{ // Block 0x1, offset 0x40 // Block 0x2, offset 0x80 // Block 0x3, offset 0xc0 - 0x0c2: 0x03, 0x0c3: 0x04, 0x0c4: 0x05, 0x0c5: 0x06, 0x0c6: 0x07, 0x0c7: 0x08, - 0x0c8: 0x09, 0x0ca: 0x0a, 0x0cb: 0x0b, 0x0cc: 0x0c, 0x0cd: 0x0d, 0x0ce: 0x0e, 0x0cf: 0x0f, - 0x0d0: 0x10, 0x0d1: 0x11, 0x0d2: 0x12, 0x0d3: 0x13, 0x0d6: 0x14, 0x0d7: 0x15, - 0x0d8: 0x16, 0x0d9: 0x17, 0x0db: 0x18, 0x0dc: 0x19, 0x0dd: 0x1a, 0x0df: 0x1b, + 0x0c2: 0x10, 0x0c3: 0x03, 0x0c4: 0x11, 0x0c5: 0x12, 0x0c6: 0x13, 0x0c7: 0x14, + 0x0c8: 0x15, 0x0ca: 0x16, 0x0cb: 0x17, 0x0cc: 0x04, 0x0cd: 0x05, 0x0ce: 0x06, 0x0cf: 0x18, + 0x0d0: 0x07, 0x0d1: 0x19, 0x0d2: 0x1a, 0x0d3: 0x1b, 0x0d6: 0x08, 0x0d7: 0x1c, + 0x0d8: 0x1d, 0x0d9: 0x09, 0x0db: 0x1e, 0x0dc: 0x1f, 0x0dd: 0x20, 0x0df: 0x21, 0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07, 0x0ea: 0x08, 0x0eb: 0x09, 0x0ec: 0x09, 0x0ed: 0x0a, 0x0ef: 0x0b, 0x0f0: 0x11, // Block 0x4, offset 0x100 - 0x120: 0x1c, 0x121: 0x1d, 0x124: 0x1e, 0x125: 0x1f, 0x126: 0x20, 0x127: 0x21, - 0x128: 0x22, 0x129: 0x23, 0x12a: 0x24, 0x12b: 0x25, 0x12c: 0x20, 0x12d: 0x26, 0x12e: 0x27, 0x12f: 0x28, - 0x131: 0x29, 0x132: 0x2a, 0x133: 0x2b, 0x134: 0x2c, 0x135: 0x28, 0x137: 0x2d, - 0x138: 0x2e, 0x139: 0x2f, 0x13a: 0x30, 0x13b: 0x31, 0x13c: 0x32, 0x13d: 0x33, 0x13e: 0x34, 0x13f: 0x35, + 0x120: 0x22, 0x121: 0x23, 0x124: 0x24, 0x125: 0x25, 0x126: 0x26, 0x127: 0x27, + 0x128: 0x28, 0x129: 0x29, 0x12a: 0x2a, 0x12b: 0x2b, 0x12c: 0x26, 0x12d: 0x2c, 0x12e: 0x2d, 0x12f: 0x2e, + 0x131: 0x2f, 0x132: 0x30, 0x133: 0x31, 0x134: 0x32, 0x135: 0x2e, 0x137: 0x33, + 0x138: 0x34, 0x139: 0x35, 0x13a: 0x36, 0x13b: 0x37, 0x13c: 0x38, 0x13d: 0x39, 0x13e: 0x3a, 0x13f: 0x3b, // Block 0x5, offset 0x140 - 0x140: 0x36, 0x142: 0x37, 0x143: 0x38, 0x144: 0x39, 0x145: 0x3a, 0x146: 0x3b, 0x147: 0x3c, - 0x14d: 0x3d, - 0x15c: 0x3e, 0x15f: 0x3f, - 0x162: 0x40, 0x164: 0x41, - 0x168: 0x42, 0x169: 0x43, 0x16c: 0x44, 0x16d: 0x45, 0x16e: 0x46, 0x16f: 0x47, - 0x170: 0x48, 0x173: 0x49, 0x174: 0x4a, 0x175: 0x4b, 0x176: 0x4c, 0x177: 0x4d, - 0x178: 0x4e, 0x179: 0x4f, 0x17a: 0x50, 0x17b: 0x51, 0x17c: 0x52, 0x17d: 0x53, 0x17e: 0x54, 0x17f: 0x55, + 0x140: 0x3c, 0x142: 0x3d, 0x143: 0x3e, 0x144: 0x3f, 0x145: 0x40, 0x146: 0x41, 0x147: 0x42, + 0x14d: 0x43, + 0x15c: 0x44, 0x15f: 0x45, + 0x162: 0x46, 0x164: 0x47, + 0x168: 0x48, 0x169: 0x49, 0x16c: 0x4a, 0x16d: 0x4b, 0x16e: 0x4c, 0x16f: 0x4d, + 0x170: 0x4e, 0x173: 0x4f, 0x174: 0x50, 0x175: 0x51, 0x176: 0x52, 0x177: 0x53, + 0x178: 0x54, 0x179: 0x55, 0x17a: 0x56, 0x17b: 0x57, 0x17c: 0x58, 0x17d: 0x0a, 0x17e: 0x59, 0x17f: 0x0b, // Block 0x6, offset 0x180 - 0x180: 0x56, 0x181: 0x57, 0x182: 0x58, 0x183: 0x59, 0x184: 0x5a, 0x185: 0x5b, 0x186: 0x5c, 0x187: 0x5d, - 0x188: 0x5e, 0x189: 0x5f, 0x18a: 0x60, 0x18b: 0x61, 0x18c: 0x62, - 0x191: 0x63, 0x192: 0x64, 0x193: 0x65, - 0x1a8: 0x66, 0x1a9: 0x67, 0x1ab: 0x68, - 0x1b1: 0x69, 0x1b3: 0x6a, 0x1b5: 0x6b, 0x1b7: 0x6c, - 0x1ba: 0x6d, 0x1bb: 0x6e, 0x1bc: 0x64, 0x1bd: 0x64, 0x1be: 0x64, 0x1bf: 0x6f, + 0x180: 0x5a, 0x181: 0x5b, 0x182: 0x5c, 0x183: 0x5d, 0x184: 0x5e, 0x185: 0x5f, 0x186: 0x60, 0x187: 0x61, + 0x188: 0x62, 0x189: 0x0c, 0x18a: 0x63, 0x18b: 0x64, 0x18c: 0x65, + 0x191: 0x66, 0x192: 0x67, 0x193: 0x68, + 0x1a8: 0x69, 0x1a9: 0x6a, 0x1ab: 0x6b, + 0x1b1: 0x6c, 0x1b3: 0x6d, 0x1b5: 0x6e, 0x1b7: 0x6f, + 0x1ba: 0x70, 0x1bb: 0x71, 0x1bc: 0x67, 0x1bd: 0x67, 0x1be: 0x67, 0x1bf: 0x72, // Block 0x7, offset 0x1c0 - 0x1c0: 0x70, 0x1c1: 0x71, 0x1c2: 0x72, 0x1c3: 0x73, 0x1c4: 0x74, 0x1c5: 0x64, 0x1c6: 0x75, - 0x1c8: 0x76, 0x1c9: 0x77, 0x1ca: 0x64, 0x1cb: 0x78, 0x1cc: 0x64, 0x1cd: 0x64, 0x1ce: 0x64, 0x1cf: 0x64, + 0x1c0: 0x73, 0x1c1: 0x0d, 0x1c2: 0x0e, 0x1c3: 0x0f, 0x1c4: 0x74, 0x1c5: 0x67, 0x1c6: 0x75, + 0x1c8: 0x76, 0x1c9: 0x77, 0x1ca: 0x67, 0x1cb: 0x78, 0x1cc: 0x67, 0x1cd: 0x67, 0x1ce: 0x67, 0x1cf: 0x67, // Block 0x8, offset 0x200 0x219: 0x79, 0x21b: 0x7a, 0x21d: 0x7b, 0x220: 0x7c, 0x223: 0x7d, 0x224: 0x7e, 0x225: 0x7f, 0x226: 0x80, 0x227: 0x81, @@ -6564,8 +6742,8 @@ var charInfoLookup = [1152]uint8{ // Block 0xb, offset 0x2c0 0x2e4: 0x87, 0x2e5: 0x87, 0x2e6: 0x87, 0x2e7: 0x87, 0x2e8: 0x88, 0x2e9: 0x89, 0x2ea: 0x87, 0x2eb: 0x8a, 0x2ec: 0x8b, 0x2ed: 0x8c, 0x2ee: 0x8d, 0x2ef: 0x8e, - 0x2f0: 0x64, 0x2f1: 0x64, 0x2f2: 0x64, 0x2f3: 0x64, 0x2f4: 0x8f, 0x2f5: 0x90, 0x2f6: 0x91, 0x2f7: 0x92, - 0x2f8: 0x93, 0x2f9: 0x94, 0x2fa: 0x64, 0x2fb: 0x95, 0x2fc: 0x96, 0x2fd: 0x64, 0x2fe: 0x78, 0x2ff: 0x97, + 0x2f0: 0x67, 0x2f1: 0x67, 0x2f2: 0x67, 0x2f3: 0x67, 0x2f4: 0x8f, 0x2f5: 0x90, 0x2f6: 0x91, 0x2f7: 0x92, + 0x2f8: 0x93, 0x2f9: 0x94, 0x2fa: 0x67, 0x2fb: 0x95, 0x2fc: 0x96, 0x2fd: 0x67, 0x2fe: 0x78, 0x2ff: 0x97, // Block 0xc, offset 0x300 0x307: 0x98, 0x328: 0x99, @@ -6574,8 +6752,8 @@ var charInfoLookup = [1152]uint8{ // Block 0xe, offset 0x380 0x385: 0x9b, 0x386: 0x9c, 0x387: 0x9d, 0x389: 0x9e, - 0x390: 0x64, 0x391: 0x9f, 0x392: 0xa0, 0x393: 0xa1, 0x394: 0xa2, 0x395: 0xa3, 0x396: 0x64, 0x397: 0x64, - 0x398: 0x64, 0x399: 0x64, 0x39a: 0xa4, 0x39b: 0x64, 0x39c: 0x64, 0x39d: 0x64, 0x39e: 0x64, 0x39f: 0xa5, + 0x390: 0x67, 0x391: 0x9f, 0x392: 0xa0, 0x393: 0xa1, 0x394: 0xa2, 0x395: 0xa3, 0x396: 0x67, 0x397: 0x67, + 0x398: 0x67, 0x399: 0x67, 0x39a: 0xa4, 0x39b: 0x67, 0x39c: 0x67, 0x39d: 0x67, 0x39e: 0x67, 0x39f: 0xa5, // Block 0xf, offset 0x3c0 0x3c4: 0xa6, 0x3c5: 0xa7, 0x3c6: 0xa8, 0x3c8: 0xa9, 0x3c9: 0xaa, @@ -6588,6 +6766,6 @@ var charInfoLookup = [1152]uint8{ 0x46f: 0x10, } -var charInfoTrie = trie{charInfoLookup[:], charInfoValues[:]} +var charInfoTrie = trie{charInfoLookup[:], charInfoValues[:], charInfoSparseValues[:], charInfoSparseOffset[:], 16} -// Total size of tables: 78KB (80362 bytes) +// Total size of tables: 48KB (48756 bytes) diff --git a/src/pkg/exp/norm/trie.go b/src/pkg/exp/norm/trie.go index edae2c212..93cb9c339 100644 --- a/src/pkg/exp/norm/trie.go +++ b/src/pkg/exp/norm/trie.go @@ -4,9 +4,44 @@ package norm +type valueRange struct { + value uint16 // header: value:stride + lo, hi byte // header: lo:n +} + type trie struct { - index []uint8 - values []uint16 + index []uint8 + values []uint16 + sparse []valueRange + sparseOffset []uint16 + cutoff uint8 // indices >= cutoff are sparse +} + +// lookupValue determines the type of block n and looks up the value for b. +// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block +// is a list of ranges with an accompanying value. Given a matching range r, +// the value for b is by r.value + (b - r.lo) * stride. +func (t *trie) lookupValue(n uint8, b byte) uint16 { + if n < t.cutoff { + return t.values[uint16(n)<<6+uint16(b&maskx)] + } + offset := t.sparseOffset[n-t.cutoff] + header := t.sparse[offset] + lo := offset + 1 + hi := lo + uint16(header.lo) + for lo < hi { + m := lo + (hi-lo)/2 + r := t.sparse[m] + if r.lo <= b && b <= r.hi { + return r.value + uint16(b-r.lo)*header.value + } + if b < r.lo { + hi = m + } else { + lo = m + 1 + } + } + return 0 } const ( @@ -44,8 +79,7 @@ func (t *trie) lookup(s []byte) (v uint16, sz int) { if c1 < tx || t2 <= c1 { return 0, 1 } - o := uint16(i)<<6 + uint16(c1)&maskx - return t.values[o], 2 + return t.lookupValue(i, c1), 2 case c0 < t4: if len(s) < 3 { return 0, 0 @@ -61,8 +95,7 @@ func (t *trie) lookup(s []byte) (v uint16, sz int) { if c2 < tx || t2 <= c2 { return 0, 2 } - o = uint16(i)<<6 + uint16(c2)&maskx - return t.values[o], 3 + return t.lookupValue(i, c2), 3 case c0 < t5: if len(s) < 4 { return 0, 0 @@ -84,8 +117,7 @@ func (t *trie) lookup(s []byte) (v uint16, sz int) { if c3 < tx || t2 <= c3 { return 0, 3 } - o = uint16(i)<<6 + uint16(c3)&maskx - return t.values[o], 4 + return t.lookupValue(i, c3), 4 } // Illegal rune return 0, 1 @@ -110,8 +142,7 @@ func (t *trie) lookupString(s string) (v uint16, sz int) { if c1 < tx || t2 <= c1 { return 0, 1 } - o := uint16(i)<<6 + uint16(c1)&maskx - return t.values[o], 2 + return t.lookupValue(i, c1), 2 case c0 < t4: if len(s) < 3 { return 0, 0 @@ -127,8 +158,7 @@ func (t *trie) lookupString(s string) (v uint16, sz int) { if c2 < tx || t2 <= c2 { return 0, 2 } - o = uint16(i)<<6 + uint16(c2)&maskx - return t.values[o], 3 + return t.lookupValue(i, c2), 3 case c0 < t5: if len(s) < 4 { return 0, 0 @@ -150,8 +180,7 @@ func (t *trie) lookupString(s string) (v uint16, sz int) { if c3 < tx || t2 <= c3 { return 0, 3 } - o = uint16(i)<<6 + uint16(c3)&maskx - return t.values[o], 4 + return t.lookupValue(i, c3), 4 } // Illegal rune return 0, 1 @@ -168,19 +197,16 @@ func (t *trie) lookupUnsafe(s []byte) uint16 { return 0 } i := t.index[c0] - o := uint16(i)<<6 + uint16(s[1])&maskx if c0 < t3 { - return t.values[o] + return t.lookupValue(i, s[1]) } - i = t.index[o] - o = uint16(i)<<6 + uint16(s[2])&maskx + i = t.index[uint16(i)<<6+uint16(s[1])&maskx] if c0 < t4 { - return t.values[o] + return t.lookupValue(i, s[2]) } - i = t.index[o] - o = uint16(i)<<6 + uint16(s[3])&maskx + i = t.index[uint16(i)<<6+uint16(s[2])&maskx] if c0 < t5 { - return t.values[o] + return t.lookupValue(i, s[3]) } return 0 } @@ -196,19 +222,16 @@ func (t *trie) lookupStringUnsafe(s string) uint16 { return 0 } i := t.index[c0] - o := uint16(i)<<6 + uint16(s[1])&maskx if c0 < t3 { - return t.values[o] + return t.lookupValue(i, s[1]) } - i = t.index[o] - o = uint16(i)<<6 + uint16(s[2])&maskx + i = t.index[uint16(i)<<6+uint16(s[1])&maskx] if c0 < t4 { - return t.values[o] + return t.lookupValue(i, s[2]) } - i = t.index[o] - o = uint16(i)<<6 + uint16(s[3])&maskx + i = t.index[uint16(i)<<6+uint16(s[2])&maskx] if c0 < t5 { - return t.values[o] + return t.lookupValue(i, s[3]) } return 0 } diff --git a/src/pkg/exp/norm/trie_test.go b/src/pkg/exp/norm/trie_test.go index 6a309426e..5649fb7ee 100644 --- a/src/pkg/exp/norm/trie_test.go +++ b/src/pkg/exp/norm/trie_test.go @@ -8,6 +8,41 @@ import ( // Test data is located in triedata_test.go; generated by maketesttables. var testdata = testdataTrie +type rangeTest struct { + block uint8 + lookup byte + result uint16 + table []valueRange + offsets []uint16 +} + +var range1Off = []uint16{0, 2} +var range1 = []valueRange{ + {0, 1, 0}, + {1, 0x80, 0x80}, + {0, 2, 0}, + {1, 0x80, 0x80}, + {9, 0xff, 0xff}, +} + +var rangeTests = []rangeTest{ + {10, 0x80, 1, range1, range1Off}, + {10, 0x00, 0, range1, range1Off}, + {11, 0x80, 1, range1, range1Off}, + {11, 0xff, 9, range1, range1Off}, + {11, 0x00, 0, range1, range1Off}, +} + +func TestLookupSparse(t *testing.T) { + for i, test := range rangeTests { + n := trie{sparse: test.table, sparseOffset: test.offsets, cutoff: 10} + v := n.lookupValue(test.block, test.lookup) + if v != test.result { + t.Errorf("LookupSparse:%d: found %X; want %X", i, v, test.result) + } + } +} + // Test cases for illegal runes. type trietest struct { size int @@ -49,10 +84,10 @@ func TestLookup(t *testing.T) { b, szg := mkUtf8(tt) v, szt := testdata.lookup(b) if int(v) != i { - t.Errorf("lookup(%U): found value %#x, expected %#x", i, v, i) + t.Errorf("lookup(%U): found value %#x, expected %#x", tt, v, i) } if szt != szg { - t.Errorf("lookup(%U): found size %d, expected %d", i, szt, szg) + t.Errorf("lookup(%U): found size %d, expected %d", tt, szt, szg) } } for i, tt := range tests { diff --git a/src/pkg/exp/norm/triedata_test.go b/src/pkg/exp/norm/triedata_test.go index f886e6004..e8898e5d4 100644 --- a/src/pkg/exp/norm/triedata_test.go +++ b/src/pkg/exp/norm/triedata_test.go @@ -4,34 +4,55 @@ package norm -var testRunes = []int{1, 12, 127, 128, 256, 2047, 2048, 2457, 65535, 65536, 65793, 1114111} +var testRunes = []int{1, 12, 127, 128, 256, 2047, 2048, 2457, 65535, 65536, 65793, 1114111, 512, 513, 514, 528, 533} -// testdataValues: 768 entries, 1536 bytes +// testdataValues: 192 entries, 384 bytes // Block 2 is the null block. -var testdataValues = [768]uint16{ +var testdataValues = [192]uint16{ // Block 0x0, offset 0x0 0x000c: 0x0001, // Block 0x1, offset 0x40 0x007f: 0x0002, // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0x00c0: 0x0003, - // Block 0x4, offset 0x100 - 0x0100: 0x0004, - // Block 0x5, offset 0x140 - 0x017f: 0x0005, - // Block 0x6, offset 0x180 - 0x0180: 0x0006, - // Block 0x7, offset 0x1c0 - 0x01d9: 0x0007, - // Block 0x8, offset 0x200 - 0x023f: 0x0008, - // Block 0x9, offset 0x240 - 0x0240: 0x0009, - // Block 0xa, offset 0x280 - 0x0281: 0x000a, - // Block 0xb, offset 0x2c0 - 0x02ff: 0x000b, +} + +// testdataSparseOffset: 10 entries, 20 bytes +var testdataSparseOffset = []uint16{0x0, 0x2, 0x4, 0x8, 0xa, 0xc, 0xe, 0x10, 0x12, 0x14} + +// testdataSparseValues: 22 entries, 88 bytes +var testdataSparseValues = [22]valueRange{ + // Block 0x0, offset 0x1 + {value: 0x0000, lo: 0x01}, + {value: 0x0003, lo: 0x80, hi: 0x80}, + // Block 0x1, offset 0x2 + {value: 0x0000, lo: 0x01}, + {value: 0x0004, lo: 0x80, hi: 0x80}, + // Block 0x2, offset 0x3 + {value: 0x0001, lo: 0x03}, + {value: 0x000c, lo: 0x80, hi: 0x82}, + {value: 0x000f, lo: 0x90, hi: 0x90}, + {value: 0x0010, lo: 0x95, hi: 0x95}, + // Block 0x3, offset 0x4 + {value: 0x0000, lo: 0x01}, + {value: 0x0005, lo: 0xbf, hi: 0xbf}, + // Block 0x4, offset 0x5 + {value: 0x0000, lo: 0x01}, + {value: 0x0006, lo: 0x80, hi: 0x80}, + // Block 0x5, offset 0x6 + {value: 0x0000, lo: 0x01}, + {value: 0x0007, lo: 0x99, hi: 0x99}, + // Block 0x6, offset 0x7 + {value: 0x0000, lo: 0x01}, + {value: 0x0008, lo: 0xbf, hi: 0xbf}, + // Block 0x7, offset 0x8 + {value: 0x0000, lo: 0x01}, + {value: 0x0009, lo: 0x80, hi: 0x80}, + // Block 0x8, offset 0x9 + {value: 0x0000, lo: 0x01}, + {value: 0x000a, lo: 0x81, hi: 0x81}, + // Block 0x9, offset 0xa + {value: 0x0000, lo: 0x01}, + {value: 0x000b, lo: 0xbf, hi: 0xbf}, } // testdataLookup: 640 bytes @@ -42,22 +63,23 @@ var testdataLookup = [640]uint8{ // Block 0x2, offset 0x80 // Block 0x3, offset 0xc0 0x0c2: 0x03, 0x0c4: 0x04, - 0x0df: 0x05, + 0x0c8: 0x05, + 0x0df: 0x06, 0x0e0: 0x04, 0x0ef: 0x05, 0x0f0: 0x07, 0x0f4: 0x09, // Block 0x4, offset 0x100 - 0x120: 0x06, 0x126: 0x07, + 0x120: 0x07, 0x126: 0x08, // Block 0x5, offset 0x140 - 0x17f: 0x08, + 0x17f: 0x09, // Block 0x6, offset 0x180 - 0x180: 0x09, 0x184: 0x0a, + 0x180: 0x0a, 0x184: 0x0b, // Block 0x7, offset 0x1c0 0x1d0: 0x06, // Block 0x8, offset 0x200 - 0x23f: 0x0b, + 0x23f: 0x0c, // Block 0x9, offset 0x240 0x24f: 0x08, } -var testdataTrie = trie{testdataLookup[:], testdataValues[:]} +var testdataTrie = trie{testdataLookup[:], testdataValues[:], testdataSparseValues[:], testdataSparseOffset[:], 3} diff --git a/src/pkg/exp/norm/triegen.go b/src/pkg/exp/norm/triegen.go index 2b7eeee17..515e1c786 100644 --- a/src/pkg/exp/norm/triegen.go +++ b/src/pkg/exp/norm/triegen.go @@ -17,10 +17,13 @@ import ( "utf8" ) +const blockSize = 64 +const maxSparseEntries = 16 + // Intermediate trie structure type trieNode struct { table [256]*trieNode - value uint16 + value int b byte leaf bool } @@ -53,6 +56,44 @@ func (n trieNode) isInternal() bool { return internal } +func (n trieNode) mostFrequentStride() int { + counts := make(map[int]int) + v := 0 + for _, t := range n.table[0x80 : 0x80+blockSize] { + if t != nil { + if stride := t.value - v; v != 0 && stride >= 0 { + counts[stride]++ + } + v = t.value + } + } + var maxs, maxc int + for stride, cnt := range counts { + if cnt > maxc { + maxs, maxc = stride, cnt + } + } + return maxs +} + +func (n trieNode) countSparseEntries() int { + stride := n.mostFrequentStride() + var count, v int + for _, t := range n.table[0x80 : 0x80+blockSize] { + tv := 0 + if t != nil { + tv = t.value + } + if tv-v != stride { + if tv != 0 { + count++ + } + } + v = tv + } + return count +} + func (n *trieNode) insert(rune int, value uint16) { var p [utf8.UTFMax]byte sz := utf8.EncodeRune(p[:], rune) @@ -69,35 +110,40 @@ func (n *trieNode) insert(rune int, value uint16) { } n = nn } - n.value = value + n.value = int(value) n.leaf = true } type nodeIndex struct { lookupBlocks []*trieNode valueBlocks []*trieNode + sparseBlocks []*trieNode + sparseOffset []uint16 + sparseCount int - lookupBlockIdx map[uint32]uint16 - valueBlockIdx map[uint32]uint16 + lookupBlockIdx map[uint32]int + valueBlockIdx map[uint32]int } func newIndex() *nodeIndex { index := &nodeIndex{} index.lookupBlocks = make([]*trieNode, 0) index.valueBlocks = make([]*trieNode, 0) - index.lookupBlockIdx = make(map[uint32]uint16) - index.valueBlockIdx = make(map[uint32]uint16) + index.sparseBlocks = make([]*trieNode, 0) + index.sparseOffset = make([]uint16, 1) + index.lookupBlockIdx = make(map[uint32]int) + index.valueBlockIdx = make(map[uint32]int) return index } -func computeOffsets(index *nodeIndex, n *trieNode) uint16 { +func computeOffsets(index *nodeIndex, n *trieNode) int { if n.leaf { return n.value } hasher := crc32.New(crc32.MakeTable(crc32.IEEE)) // We only index continuation bytes. - for i := 0; i < 64; i++ { - var v uint16 = 0 + for i := 0; i < blockSize; i++ { + v := 0 if nn := n.table[0x80+i]; nn != nil { v = computeOffsets(index, nn) } @@ -107,7 +153,7 @@ func computeOffsets(index *nodeIndex, n *trieNode) uint16 { if n.isInternal() { v, ok := index.lookupBlockIdx[h] if !ok { - v = uint16(len(index.lookupBlocks)) + v = len(index.lookupBlocks) index.lookupBlocks = append(index.lookupBlocks, n) index.lookupBlockIdx[h] = v } @@ -115,9 +161,17 @@ func computeOffsets(index *nodeIndex, n *trieNode) uint16 { } else { v, ok := index.valueBlockIdx[h] if !ok { - v = uint16(len(index.valueBlocks)) - index.valueBlocks = append(index.valueBlocks, n) - index.valueBlockIdx[h] = v + if c := n.countSparseEntries(); c > maxSparseEntries { + v = len(index.valueBlocks) + index.valueBlocks = append(index.valueBlocks, n) + index.valueBlockIdx[h] = v + } else { + v = -len(index.sparseOffset) + index.sparseBlocks = append(index.sparseBlocks, n) + index.sparseOffset = append(index.sparseOffset, uint16(index.sparseCount)) + index.sparseCount += c + 1 + index.valueBlockIdx[h] = v + } } n.value = v } @@ -125,14 +179,14 @@ func computeOffsets(index *nodeIndex, n *trieNode) uint16 { } func printValueBlock(nr int, n *trieNode, offset int) { - boff := nr * 64 + boff := nr * blockSize fmt.Printf("\n// Block %#x, offset %#x", nr, boff) var printnewline bool - for i := 0; i < 64; i++ { + for i := 0; i < blockSize; i++ { if i%6 == 0 { printnewline = true } - v := uint16(0) + v := 0 if nn := n.table[i+offset]; nn != nil { v = nn.value } @@ -141,24 +195,55 @@ func printValueBlock(nr int, n *trieNode, offset int) { fmt.Printf("\n") printnewline = false } - fmt.Printf("%#04x:%#04x, ", nr*64+i, v) + fmt.Printf("%#04x:%#04x, ", boff+i, v) } } } -func printLookupBlock(nr int, n *trieNode, offset int) { - boff := nr * 64 +func printSparseBlock(nr int, n *trieNode) { + boff := -n.value + fmt.Printf("\n// Block %#x, offset %#x", nr, boff) + v := 0 + //stride := f(n) + stride := n.mostFrequentStride() + c := n.countSparseEntries() + fmt.Printf("\n{value:%#04x,lo:%#02x},", stride, uint8(c)) + for i, nn := range n.table[0x80 : 0x80+blockSize] { + nv := 0 + if nn != nil { + nv = nn.value + } + if nv-v != stride { + if v != 0 { + fmt.Printf(",hi:%#02x},", 0x80+i-1) + } + if nv != 0 { + fmt.Printf("\n{value:%#04x,lo:%#02x", nv, nn.b) + } + } + v = nv + } + if v != 0 { + fmt.Printf(",hi:%#02x},", 0x80+blockSize-1) + } +} + +func printLookupBlock(nr int, n *trieNode, offset, cutoff int) { + boff := nr * blockSize fmt.Printf("\n// Block %#x, offset %#x", nr, boff) var printnewline bool - for i := 0; i < 64; i++ { + for i := 0; i < blockSize; i++ { if i%8 == 0 { printnewline = true } - v := uint16(0) + v := 0 if nn := n.table[i+offset]; nn != nil { v = nn.value } if v != 0 { + if v < 0 { + v = -v - 1 + cutoff + } if printnewline { fmt.Printf("\n") printnewline = false @@ -182,7 +267,7 @@ func (t *trieNode) printTables(name string) int { } } - nv := len(index.valueBlocks) * 64 + nv := len(index.valueBlocks) * blockSize fmt.Printf("// %sValues: %d entries, %d bytes\n", name, nv, nv*2) fmt.Printf("// Block 2 is the null block.\n") fmt.Printf("var %sValues = [%d]uint16 {", name, nv) @@ -194,18 +279,32 @@ func (t *trieNode) printTables(name string) int { } fmt.Print("\n}\n\n") - ni := len(index.lookupBlocks) * 64 + ls := len(index.sparseBlocks) + fmt.Printf("// %sSparseOffset: %d entries, %d bytes\n", name, ls, ls*2) + fmt.Printf("var %sSparseOffset = %#v\n\n", name, index.sparseOffset[1:]) + + ns := index.sparseCount + fmt.Printf("// %sSparseValues: %d entries, %d bytes\n", name, ns, ns*4) + fmt.Printf("var %sSparseValues = [%d]valueRange {", name, ns) + for i, n := range index.sparseBlocks { + printSparseBlock(i, n) + } + fmt.Print("\n}\n\n") + + cutoff := len(index.valueBlocks) + ni := len(index.lookupBlocks) * blockSize fmt.Printf("// %sLookup: %d bytes\n", name, ni) fmt.Printf("// Block 0 is the null block.\n") fmt.Printf("var %sLookup = [%d]uint8 {", name, ni) - printLookupBlock(0, newNode(), 0) - printLookupBlock(1, newNode(), 0) - printLookupBlock(2, newNode(), 0) - printLookupBlock(3, t, 0xC0) + printLookupBlock(0, newNode(), 0, cutoff) + printLookupBlock(1, newNode(), 0, cutoff) + printLookupBlock(2, newNode(), 0, cutoff) + printLookupBlock(3, t, 0xC0, cutoff) for i := 4; i < len(index.lookupBlocks); i++ { - printLookupBlock(i, index.lookupBlocks[i], 0x80) + printLookupBlock(i, index.lookupBlocks[i], 0x80, cutoff) } fmt.Print("\n}\n\n") - fmt.Printf("var %sTrie = trie{ %sLookup[:], %sValues[:] }\n\n", name, name, name) - return nv*2 + ni + fmt.Printf("var %sTrie = trie{ %sLookup[:], %sValues[:], %sSparseValues[:], %sSparseOffset[:], %d}\n\n", + name, name, name, name, name, cutoff) + return nv*2 + ns*4 + ni + ls*2 } diff --git a/src/pkg/exp/regexp/exec.go b/src/pkg/exp/regexp/exec.go index 88b16032e..43499a92f 100644 --- a/src/pkg/exp/regexp/exec.go +++ b/src/pkg/exp/regexp/exec.go @@ -128,6 +128,11 @@ func (m *machine) match(i input, pos int) bool { 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 rune, width = rune1, width1 if rune != endOfText { @@ -155,37 +160,37 @@ func (m *machine) clear(q *queue) { // 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, c int, nextCond syntax.EmptyOp) { + longest := m.re.longest for j := 0; j < len(runq.dense); j++ { d := &runq.dense[j] t := d.t if t == nil { continue } - /* - * If we support leftmost-longest matching: - if longest && matched && match[0] < t.cap[0] { - m.free(t) - continue - } - */ - + if longest && m.matched && len(t.cap) > 0 && m.matchcap[0] < t.cap[0] { + m.free(t) + continue + } i := t.inst switch i.Op { default: panic("bad inst") case syntax.InstMatch: - if len(t.cap) > 0 { + if len(t.cap) > 0 && (!longest || !m.matched || m.matchcap[1] < pos) { t.cap[1] = pos copy(m.matchcap, t.cap) } - m.matched = true - for _, d := range runq.dense[j+1:] { - if d.t != nil { - m.free(d.t) + if !longest { + // First-match mode: cut off all lower-priority threads. + for _, d := range runq.dense[j+1:] { + if d.t != nil { + m.free(d.t) + } } + runq.dense = runq.dense[:0] } - runq.dense = runq.dense[:0] + m.matched = true case syntax.InstRune: if i.MatchRune(c) { diff --git a/src/pkg/exp/regexp/exec_test.go b/src/pkg/exp/regexp/exec_test.go index 15c4c532a..3adf8484c 100644 --- a/src/pkg/exp/regexp/exec_test.go +++ b/src/pkg/exp/regexp/exec_test.go @@ -6,9 +6,12 @@ package regexp import ( "bufio" - "compress/gzip" + "compress/bzip2" + "exp/regexp/syntax" "fmt" + "io" "os" + "path/filepath" "strconv" "strings" "testing" @@ -59,24 +62,34 @@ import ( // At time of writing, re2.txt is 32 MB but compresses to 760 kB, // so we store re2.txt.gz in the repository and decompress it on the fly. // -func TestRE2(t *testing.T) { +func TestRE2Search(t *testing.T) { + testRE2(t, "testdata/re2-search.txt") +} + +func TestRE2Exhaustive(t *testing.T) { if testing.Short() { - t.Log("skipping TestRE2 during short test") + t.Log("skipping TestRE2Exhaustive during short test") return } + testRE2(t, "testdata/re2-exhaustive.txt.bz2") +} - f, err := os.Open("re2.txt.gz") +func testRE2(t *testing.T, file string) { + f, err := os.Open(file) if err != nil { t.Fatal(err) } defer f.Close() - gz, err := gzip.NewReader(f) - if err != nil { - t.Fatalf("decompress re2.txt.gz: %v", err) + var txt io.Reader + if strings.HasSuffix(file, ".bz2") { + z := bzip2.NewReader(f) + txt = z + file = file[:len(file)-len(".bz2")] // for error messages + } else { + txt = f } - defer gz.Close() lineno := 0 - r := bufio.NewReader(gz) + r := bufio.NewReader(txt) var ( str []string input []string @@ -92,13 +105,13 @@ func TestRE2(t *testing.T) { if err == os.EOF { break } - t.Fatalf("re2.txt:%d: %v", lineno, err) + t.Fatalf("%s:%d: %v", file, lineno, err) } line = line[:len(line)-1] // chop \n lineno++ switch { case line == "": - t.Fatalf("re2.txt:%d: unexpected blank line", lineno) + t.Fatalf("%s:%d: unexpected blank line", file, lineno) case line[0] == '#': continue case 'A' <= line[0] && line[0] <= 'Z': @@ -114,7 +127,7 @@ func TestRE2(t *testing.T) { q, err := strconv.Unquote(line) if err != nil { // Fatal because we'll get out of sync. - t.Fatalf("re2.txt:%d: unquote %s: %v", lineno, line, err) + t.Fatalf("%s:%d: unquote %s: %v", file, lineno, line, err) } if inStrings { str = append(str, q) @@ -122,7 +135,7 @@ func TestRE2(t *testing.T) { } // Is a regexp. if len(input) != 0 { - t.Fatalf("re2.txt:%d: out of sync: have %d strings left before %#q", lineno, len(input), q) + t.Fatalf("%s:%d: out of sync: have %d strings left before %#q", file, lineno, len(input), q) } re, err = tryCompile(q) if err != nil { @@ -130,7 +143,7 @@ func TestRE2(t *testing.T) { // We don't and likely never will support \C; keep going. continue } - t.Errorf("re2.txt:%d: compile %#q: %v", lineno, q, err) + t.Errorf("%s:%d: compile %#q: %v", file, lineno, q, err) if nfail++; nfail >= 100 { t.Fatalf("stopping after %d errors", nfail) } @@ -140,7 +153,7 @@ func TestRE2(t *testing.T) { refull, err = tryCompile(full) if err != nil { // Fatal because q worked, so this should always work. - t.Fatalf("re2.txt:%d: compile full %#q: %v", lineno, full, err) + t.Fatalf("%s:%d: compile full %#q: %v", file, lineno, full, err) } input = str case line[0] == '-' || '0' <= line[0] && line[0] <= '9': @@ -151,7 +164,7 @@ func TestRE2(t *testing.T) { continue } if len(input) == 0 { - t.Fatalf("re2.txt:%d: out of sync: no input remaining", lineno) + t.Fatalf("%s:%d: out of sync: no input remaining", file, lineno) } var text string text, input = input[0], input[1:] @@ -164,39 +177,93 @@ func TestRE2(t *testing.T) { continue } res := strings.Split(line, ";") - if len(res) != 2 { - t.Fatalf("re2.txt:%d: have %d test results, want 2", lineno, len(res)) + if len(res) != len(run) { + t.Fatalf("%s:%d: have %d test results, want %d", file, lineno, len(res), len(run)) } - // res[0] is full match - // res[1] is partial match - // Run partial match first; don't bother with full if partial fails. - have := re.FindStringSubmatchIndex(text) - want := parseResult(t, lineno, res[1]) - if !same(have, want) { - t.Errorf("re2.txt:%d: %#q.FindSubmatchIndex(%#q) = %v, want %v", lineno, re, text, have, want) - if nfail++; nfail >= 100 { - t.Fatalf("stopping after %d errors", nfail) + 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 } - continue - } - have = refull.FindStringSubmatchIndex(text) - want = parseResult(t, lineno, res[0]) - if !same(have, want) { - t.Errorf("re2.txt:%d: %#q.FindSubmatchIndex(%#q) = %v, want %v", lineno, refull, text, have, want) - if nfail++; nfail >= 100 { - t.Fatalf("stopping after %d errors", nfail) + 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("re2.txt:%d: out of sync: %s\n", lineno, line) + t.Fatalf("%s:%d: out of sync: %s\n", file, lineno, line) } } if len(input) != 0 { - t.Fatalf("re2.txt:%d: out of sync: have %d strings left at EOF", lineno, len(input)) + t.Fatalf("%s:%d: out of sync: have %d strings left at EOF", file, lineno, len(input)) } t.Logf("%d cases tested", ncase) } +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 { @@ -216,7 +283,7 @@ func tryCompile(s string) (re *Regexp, err os.Error) { return Compile(s) } -func parseResult(t *testing.T, lineno int, res string) []int { +func parseResult(t *testing.T, file string, lineno int, res string) []int { // A single - indicates no match. if res == "-" { return nil @@ -241,12 +308,12 @@ func parseResult(t *testing.T, lineno int, res string) []int { } else { k := strings.Index(pair, "-") if k < 0 { - t.Fatalf("re2.txt:%d: invalid pair %s", lineno, pair) + t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair) } lo, err1 := strconv.Atoi(pair[:k]) hi, err2 := strconv.Atoi(pair[k+1:]) if err1 != nil || err2 != nil || lo > hi { - t.Fatalf("re2.txt:%d: invalid pair %s", lineno, pair) + t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair) } out[n] = lo out[n+1] = hi @@ -269,3 +336,314 @@ func same(x, y []int) bool { } return true } + +// TestFowler runs this package's regexp API against the +// POSIX regular expression tests collected by Glenn Fowler +// at http://www2.research.att.com/~gsf/testregex/. +func TestFowler(t *testing.T) { + files, err := filepath.Glob("testdata/*.dat") + if err != nil { + t.Fatal(err) + } + for _, file := range files { + t.Log(file) + testFowler(t, file) + } +} + +var notab = 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 != os.EOF { + t.Errorf("%s:%d: %v", file, lineno, err) + } + break Reading + } + + // http://www2.research.att.com/~gsf/man/man1/testregex.html + // + // INPUT FORMAT + // Input lines may be blank, a comment beginning with #, or a test + // specification. A specification is five fields separated by one + // or more tabs. NULL denotes the empty string and NIL denotes the + // 0 pointer. + if line[0] == '#' || line[0] == '\n' { + continue Reading + } + line = line[:len(line)-1] + field := notab.FindAllString(line, -1) + for i, f := range field { + if f == "NULL" { + field[i] = "" + } + if f == "NIL" { + t.Logf("%s:%d: skip: %s", file, lineno, line) + continue Reading + } + } + if len(field) == 0 { + continue Reading + } + + // Field 1: the regex(3) flags to apply, one character per REG_feature + // flag. The test is skipped if REG_feature is not supported by the + // implementation. If the first character is not [BEASKLP] then the + // specification is a global control line. One or more of [BEASKLP] may be + // specified; the test will be repeated for each mode. + // + // B basic BRE (grep, ed, sed) + // E REG_EXTENDED ERE (egrep) + // A REG_AUGMENTED ARE (egrep with negation) + // S REG_SHELL SRE (sh glob) + // K REG_SHELL|REG_AUGMENTED KRE (ksh glob) + // L REG_LITERAL LRE (fgrep) + // + // a REG_LEFT|REG_RIGHT implicit ^...$ + // b REG_NOTBOL lhs does not match ^ + // c REG_COMMENT ignore space and #...\n + // d REG_SHELL_DOT explicit leading . match + // e REG_NOTEOL rhs does not match $ + // f REG_MULTIPLE multiple \n separated patterns + // g FNM_LEADING_DIR testfnmatch only -- match until / + // h REG_MULTIREF multiple digit backref + // i REG_ICASE ignore case + // j REG_SPAN . matches \n + // k REG_ESCAPE \ to ecape [...] delimiter + // l REG_LEFT implicit ^... + // m REG_MINIMAL minimal match + // n REG_NEWLINE explicit \n match + // o REG_ENCLOSED (|&) magic inside [@|&](...) + // p REG_SHELL_PATH explicit / match + // q REG_DELIMITED delimited pattern + // r REG_RIGHT implicit ...$ + // s REG_SHELL_ESCAPED \ not special + // t REG_MUSTDELIM all delimiters must be specified + // u standard unspecified behavior -- errors not counted + // v REG_CLASS_ESCAPE \ special inside [...] + // w REG_NOSUB no subexpression match array + // x REG_LENIENT let some errors slide + // y REG_LEFT regexec() implicit ^... + // z REG_NULL NULL subexpressions ok + // $ expand C \c escapes in fields 2 and 3 + // / field 2 is a regsubcomp() expression + // = field 3 is a regdecomp() expression + // + // Field 1 control lines: + // + // C set LC_COLLATE and LC_CTYPE to locale in field 2 + // + // ?test ... output field 5 if passed and != EXPECTED, silent otherwise + // &test ... output field 5 if current and previous passed + // |test ... output field 5 if current passed and previous failed + // ; ... output field 2 if previous failed + // {test ... skip if failed until } + // } end of skip + // + // : comment comment copied as output NOTE + // :comment:test :comment: ignored + // N[OTE] comment comment copied as output NOTE + // T[EST] comment comment + // + // number use number for nmatch (20 by default) + flag := field[0] + switch flag[0] { + case '?', '&', '|', ';', '{', '}': + // Ignore all the control operators. + // Just run everything. + flag = flag[1:] + if flag == "" { + continue Reading + } + case ':': + i := strings.Index(flag[1:], ":") + if i < 0 { + t.Logf("skip: %s", line) + continue Reading + } + flag = flag[1+i+1:] + case 'C', 'N', 'T', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + t.Logf("skip: %s", line) + continue Reading + } + + // Can check field count now that we've handled the myriad comment formats. + if len(field) < 4 { + t.Errorf("%s:%d: too few fields: %s", file, lineno, line) + continue Reading + } + + // Expand C escapes (a.k.a. Go escapes). + if strings.Contains(flag, "$") { + f := `"` + field[1] + `"` + if field[1], err = strconv.Unquote(f); err != nil { + t.Errorf("%s:%d: cannot unquote %s", file, lineno, f) + } + f = `"` + field[2] + `"` + if field[2], err = strconv.Unquote(f); err != nil { + t.Errorf("%s:%d: cannot unquote %s", file, lineno, f) + } + } + + // Field 2: the regular expression pattern; SAME uses the pattern from + // the previous specification. + // + if field[1] == "SAME" { + field[1] = lastRegexp + } + lastRegexp = field[1] + + // Field 3: the string to match. + text := field[2] + + // Field 4: the test outcome... + ok, shouldCompile, shouldMatch, pos := parseFowlerResult(field[3]) + if !ok { + t.Errorf("%s:%d: cannot parse result %#q", file, lineno, field[3]) + continue Reading + } + + // Field 5: optional comment appended to the report. + + Testing: + // Run test once for each specified capital letter mode that we support. + for _, c := range flag { + pattern := field[1] + syn := syntax.POSIX | syntax.ClassNL + switch c { + default: + continue Testing + case 'E': + // extended regexp (what we support) + case 'L': + // literal + pattern = QuoteMeta(pattern) + } + + for _, c := range flag { + switch c { + case 'i': + syn |= syntax.FoldCase + } + } + + re, err := compile(pattern, syn, true) + if err != nil { + if shouldCompile { + t.Errorf("%s:%d: %#q did not compile", file, lineno, pattern) + } + continue Testing + } + if !shouldCompile { + t.Errorf("%s:%d: %#q should not compile", file, lineno, pattern) + continue Testing + } + match := re.MatchString(text) + if match != shouldMatch { + t.Errorf("%s:%d: %#q.Match(%#q) = %v, want %v", file, lineno, pattern, text, match, shouldMatch) + continue Testing + } + have := re.FindStringSubmatchIndex(text) + if (len(have) > 0) != match { + t.Errorf("%s:%d: %#q.Match(%#q) = %v, but %#q.FindSubmatchIndex(%#q) = %v", file, lineno, pattern, text, match, 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 os.Error + if s[:i] != "?" { + v, err = strconv.Atoi(s[:i]) + if err != nil { + ok = false + return + } + } + x = append(x, v) + s = s[i+1:] + } + if len(x)%2 != 0 { + ok = false + return + } + ok = true + matched = true + pos = x + return +} diff --git a/src/pkg/exp/regexp/find_test.go b/src/pkg/exp/regexp/find_test.go index 6406bb6e6..e07eb7d5c 100644 --- a/src/pkg/exp/regexp/find_test.go +++ b/src/pkg/exp/regexp/find_test.go @@ -98,6 +98,15 @@ var findTests = []FindTest{ {`\B`, "x y", nil}, {`\B`, "xx yy", build(2, 1, 1, 4, 4)}, + // RE2 tests + {`[^\S\s]`, "abcd", nil}, + {`[^\S[:space:]]`, "abcd", nil}, + {`[^\D\d]`, "abcd", nil}, + {`[^\D[:digit:]]`, "abcd", nil}, + {`(?i)\W`, "x", nil}, + {`(?i)\W`, "k", nil}, + {`(?i)\W`, "s", nil}, + // can backslash-escape any punctuation {`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`, `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)}, diff --git a/src/pkg/exp/regexp/re2.txt.gz b/src/pkg/exp/regexp/re2.txt.gz deleted file mode 100644 index 2b8c832e5..000000000 Binary files a/src/pkg/exp/regexp/re2.txt.gz and /dev/null differ diff --git a/src/pkg/exp/regexp/regexp.go b/src/pkg/exp/regexp/regexp.go index 11feecd55..7480b098c 100644 --- a/src/pkg/exp/regexp/regexp.go +++ b/src/pkg/exp/regexp/regexp.go @@ -58,6 +58,7 @@ import ( "exp/regexp/syntax" "io" "os" + "strconv" "strings" "sync" "utf8" @@ -85,6 +86,7 @@ type Regexp struct { prefixRune int // first rune in prefix cond syntax.EmptyOp // empty-width conditions required at start of match numSubexp int + longest bool // cache of machines for running regexp mu sync.Mutex @@ -96,10 +98,45 @@ func (re *Regexp) String() string { return re.expr } -// Compile parses a regular expression and returns, if successful, a Regexp -// object that can be used to match against text. +// Compile parses a regular expression and returns, if successful, +// a Regexp object that can be used to match against text. +// +// When matching against text, the regexp returns a match that +// begins as early as possible in the input (leftmost), and among those +// it chooses the one that a backtracking search would have found first. +// This so-called leftmost-first matching is the same semantics +// that Perl, Python, and other implementations use, although this +// package implements it without the expense of backtracking. +// For POSIX leftmost-longest matching, see CompilePOSIX. func Compile(expr string) (*Regexp, os.Error) { - re, err := syntax.Parse(expr, syntax.Perl) + return compile(expr, syntax.Perl, false) +} + +// CompilePOSIX is like Compile but restricts the regular expression +// to POSIX ERE (egrep) syntax and changes the match semantics to +// leftmost-longest. +// +// That is, when matching against text, the regexp returns a match that +// begins as early as possible in the input (leftmost), and among those +// it chooses a match that is as long as possible. +// This so-called leftmost-longest matching is the same semantics +// that early regular expression implementations used and that POSIX +// specifies. +// +// However, there can be multiple leftmost-longest matches, with different +// submatch choices, and here this package diverges from POSIX. +// Among the possible leftmost-longest matches, this package chooses +// the one that a backtracking search would have found first, while POSIX +// specifies that the match be chosen to maximize the length of the first +// subexpression, then the second, and so on from left to right. +// The POSIX rule is computationally prohibitive and not even well-defined. +// See http://swtch.com/~rsc/regexp/regexp2.html#posix for details. +func CompilePOSIX(expr string) (*Regexp, os.Error) { + return compile(expr, syntax.POSIX, true) +} + +func compile(expr string, mode syntax.Flags, longest bool) (*Regexp, os.Error) { + re, err := syntax.Parse(expr, mode) if err != nil { return nil, err } @@ -113,6 +150,8 @@ func Compile(expr string) (*Regexp, os.Error) { expr: expr, prog: prog, numSubexp: maxCap, + cond: prog.StartCond(), + longest: longest, } regexp.prefix, regexp.prefixComplete = prog.Prefix() if regexp.prefix != "" { @@ -121,7 +160,6 @@ func Compile(expr string) (*Regexp, os.Error) { regexp.prefixBytes = []byte(regexp.prefix) regexp.prefixRune, _ = utf8.DecodeRuneInString(regexp.prefix) } - regexp.cond = prog.StartCond() return regexp, nil } @@ -158,11 +196,29 @@ func (re *Regexp) put(z *machine) { func MustCompile(str string) *Regexp { regexp, error := Compile(str) if error != nil { - panic(`regexp: compiling "` + str + `": ` + error.String()) + panic(`regexp: Compile(` + quote(str) + `): ` + error.String()) } 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, error := CompilePOSIX(str) + if error != nil { + panic(`regexp: CompilePOSIX(` + quote(str) + `): ` + error.String()) + } + 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 diff --git a/src/pkg/exp/regexp/syntax/parse.go b/src/pkg/exp/regexp/syntax/parse.go index 954a0ad8a..1165db3e2 100644 --- a/src/pkg/exp/regexp/syntax/parse.go +++ b/src/pkg/exp/regexp/syntax/parse.go @@ -181,11 +181,29 @@ func (p *parser) maybeConcat(r int, flags Flags) bool { func (p *parser) newLiteral(r int, flags Flags) *Regexp { re := p.newRegexp(OpLiteral) re.Flags = flags + if flags&FoldCase != 0 { + r = minFoldRune(r) + } re.Rune0[0] = r re.Rune = re.Rune0[:1] return re } +// minFoldRune returns the minimum rune fold-equivalent to r. +func minFoldRune(r int) int { + if r < minFold || r > maxFold { + return r + } + min := r + r0 := r + for r = unicode.SimpleFold(r); r != r0; r = unicode.SimpleFold(r) { + if min > r { + min = r + } + } + return min +} + // literal pushes a literal regexp for the rune r on the stack // and returns that regexp. func (p *parser) literal(r int) { @@ -200,27 +218,32 @@ func (p *parser) op(op Op) *Regexp { return p.push(re) } -// repeat replaces the top stack element with itself repeated -// according to op. -func (p *parser) repeat(op Op, min, max int, opstr, t, lastRepeat string) (string, os.Error) { +// 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, os.Error) { flags := p.flags if p.flags&PerlX != 0 { - if len(t) > 0 && t[0] == '?' { - t = t[1:] + 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(t)]} + return "", &Error{ErrInvalidRepeatOp, lastRepeat[:len(lastRepeat)-len(after)]} } } n := len(p.stack) if n == 0 { - return "", &Error{ErrMissingRepeatArgument, opstr} + 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 @@ -228,7 +251,7 @@ func (p *parser) repeat(op Op, min, max int, opstr, t, lastRepeat string) (strin re.Sub = re.Sub0[:1] re.Sub[0] = sub p.stack[n-1] = re - return t, nil + return after, nil } // concat replaces the top of the stack (above the topmost '|' or '(') with its concatenation. @@ -704,6 +727,7 @@ func Parse(s string, flags Flags) (*Regexp, os.Error) { return nil, err } case '*', '+', '?': + before := t switch t[0] { case '*': op = OpStar @@ -712,21 +736,31 @@ func Parse(s string, flags Flags) (*Regexp, os.Error) { case '?': op = OpQuest } - if t, err = p.repeat(op, min, max, t[:1], t[1:], lastRepeat); err != nil { + after := t[1:] + if after, err = p.repeat(op, min, max, before, after, lastRepeat); err != nil { return nil, err } + repeat = before + t = after case '{': op = OpRepeat - min, max, tt, ok := p.parseRepeat(t) + 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 t, err = p.repeat(op, min, max, t[:len(t)-len(tt)], tt, lastRepeat); err != nil { + 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] { @@ -815,12 +849,14 @@ func Parse(s string, flags Flags) (*Regexp, os.Error) { // 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:] - if min, s, ok = p.parseInt(s); !ok { + var ok1 bool + if min, s, ok1 = p.parseInt(s); !ok1 { return } if s == "" { @@ -835,8 +871,11 @@ func (p *parser) parseRepeat(s string) (min, max int, rest string, ok bool) { } if s[0] == '}' { max = -1 - } else if max, s, ok = p.parseInt(s); !ok { + } 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] != '}' { @@ -981,16 +1020,22 @@ func (p *parser) parseInt(s string) (n int, rest string, ok bool) { if len(s) >= 2 && s[0] == '0' && '0' <= s[1] && s[1] <= '9' { return } + t := s for s != "" && '0' <= s[0] && s[0] <= '9' { - // Avoid overflow. - if n >= 1e8 { - return - } - n = n*10 + int(s[0]) - '0' 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 } @@ -1125,6 +1170,8 @@ func (p *parser) parseRightParen() os.Error { if re2.Op != opLeftParen { return &Error{ErrMissingParen, p.wholeRegexp} } + // Restore flags at time of paren. + p.flags = re2.Flags if re2.Cap == 0 { // Just for grouping. p.push(re1) @@ -1330,9 +1377,18 @@ func (p *parser) appendGroup(r []int, g charGroup) []int { return r } +var anyTable = &unicode.RangeTable{ + []unicode.Range16{{0, 1<<16 - 1, 1}}, + []unicode.Range32{{1 << 16, unicode.MaxRune, 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] } diff --git a/src/pkg/exp/regexp/syntax/parse_test.go b/src/pkg/exp/regexp/syntax/parse_test.go index a146c89c3..f20276c59 100644 --- a/src/pkg/exp/regexp/syntax/parse_test.go +++ b/src/pkg/exp/regexp/syntax/parse_test.go @@ -11,10 +11,12 @@ import ( "unicode" ) -var parseTests = []struct { +type parseTest struct { Regexp string Dump string -}{ +} + +var parseTests = []parseTest{ // Base cases {`a`, `lit{a}`}, {`a.`, `cat{lit{a}dot{}}`}, @@ -38,6 +40,12 @@ var parseTests = []struct { {`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{}}`}, @@ -101,6 +109,8 @@ var parseTests = []struct { {`\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}}`}, @@ -174,14 +184,80 @@ var parseTests = []struct { {`(?-s).`, `dnl{}`}, {`(?:(?:^).)`, `cat{bol{}dot{}}`}, {`(?-s)(?:(?:^).)`, `cat{bol{}dnl{}}`}, + + // RE2 prefix_tests + {`abc|abd`, `cat{str{ab}cc{0x63-0x64}}`}, + {`a(?:b)c|abd`, `cat{str{ab}cc{0x63-0x64}}`}, + {`abc|abd|aef|bcx|bcy`, + `alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}` + + `cat{str{bc}cc{0x78-0x79}}}`}, + {`abc|x|abd`, `alt{str{abc}lit{x}str{abd}}`}, + {`(?i)abc|ABD`, `cat{strfold{AB}cc{0x43-0x44 0x63-0x64}}`}, + {`[ab]c|[ab]d`, `cat{cc{0x61-0x62}cc{0x63-0x64}}`}, + {`(?:xx|yy)c|(?:xx|yy)d`, + `cat{alt{str{xx}str{yy}}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}}}}`}, } 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) { - for _, tt := range parseTests { - re, err := Parse(tt.Regexp, testFlags) +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 @@ -360,3 +436,116 @@ func TestAppendRangeCollapse(t *testing.T) { t.Errorf("appendRange interlaced A-Z a-z = %s, want AZaz", string(r)) } } + +var invalidRegexps = []string{ + `(`, + `)`, + `(a`, + `(a|b|`, + `(a|b`, + `[a-z`, + `([a-z)`, + `x{1001}`, + `x{9876543210}`, + `x{2,1}`, + `x{1,9876543210}`, + "\xff", // Invalid UTF-8 + "[\xff]", + "[\\\xff]", + "\\\xff", + `(?Pa`, + `(?P`, + `(?Pa)`, + `(?P<>a)`, + `[a-Z]`, + `(?i)[a-Z]`, + `a{100000}`, + `a{100000,}`, +} + +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 + } + 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, t, 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) + } + } + } +} diff --git a/src/pkg/exp/regexp/syntax/prog.go b/src/pkg/exp/regexp/syntax/prog.go index d214d70b5..e92baaca0 100644 --- a/src/pkg/exp/regexp/syntax/prog.go +++ b/src/pkg/exp/regexp/syntax/prog.go @@ -57,7 +57,7 @@ func EmptyOpContext(r1, r2 int) EmptyOp { op |= EmptyBeginLine } if r2 < 0 { - op |= EmptyEndText + op |= EmptyEndText | EmptyEndLine } if r2 == '\n' { op |= EmptyEndLine diff --git a/src/pkg/exp/regexp/syntax/regexp.go b/src/pkg/exp/regexp/syntax/regexp.go index d8f51b903..033848df2 100644 --- a/src/pkg/exp/regexp/syntax/regexp.go +++ b/src/pkg/exp/regexp/syntax/regexp.go @@ -164,9 +164,9 @@ func writeRegexp(b *bytes.Buffer, re *Regexp) { } b.WriteRune(']') case OpAnyCharNotNL: - b.WriteString(`[^\n]`) + b.WriteString(`(?-s:.)`) case OpAnyChar: - b.WriteRune('.') + b.WriteString(`(?s:.)`) case OpBeginLine: b.WriteRune('^') case OpEndLine: @@ -174,7 +174,11 @@ func writeRegexp(b *bytes.Buffer, re *Regexp) { case OpBeginText: b.WriteString(`\A`) case OpEndText: - b.WriteString(`\z`) + if re.Flags&WasDollar != 0 { + b.WriteString(`(?-m:$)`) + } else { + b.WriteString(`\z`) + } case OpWordBoundary: b.WriteString(`\b`) case OpNoWordBoundary: @@ -192,7 +196,7 @@ func writeRegexp(b *bytes.Buffer, re *Regexp) { } b.WriteRune(')') case OpStar, OpPlus, OpQuest, OpRepeat: - if sub := re.Sub[0]; sub.Op > OpCapture { + if sub := re.Sub[0]; sub.Op > OpCapture || sub.Op == OpLiteral && len(sub.Rune) > 1 { b.WriteString(`(?:`) writeRegexp(b, sub) b.WriteString(`)`) @@ -217,6 +221,9 @@ func writeRegexp(b *bytes.Buffer, re *Regexp) { } b.WriteRune('}') } + if re.Flags&NonGreedy != 0 { + b.WriteRune('?') + } case OpConcat: for _, sub := range re.Sub { if sub.Op == OpAlternate { diff --git a/src/pkg/exp/regexp/syntax/simplify_test.go b/src/pkg/exp/regexp/syntax/simplify_test.go index c8cec2183..879eff5be 100644 --- a/src/pkg/exp/regexp/syntax/simplify_test.go +++ b/src/pkg/exp/regexp/syntax/simplify_test.go @@ -18,7 +18,7 @@ var simplifyTests = []struct { {`(ab)*`, `(ab)*`}, {`(ab)+`, `(ab)+`}, {`(ab)?`, `(ab)?`}, - {`.`, `.`}, + {`.`, `(?s:.)`}, {`^`, `^`}, {`$`, `$`}, {`[ac]`, `[ac]`}, @@ -97,22 +97,22 @@ var simplifyTests = []struct { {`[^[:cntrl:][:^cntrl:]]`, `[^\x00-\x{10FFFF}]`}, // Full character classes - {`[[:cntrl:][:^cntrl:]]`, `.`}, + {`[[:cntrl:][:^cntrl:]]`, `(?s:.)`}, // Unicode case folding. {`(?i)A`, `(?i:A)`}, - {`(?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:\u212A)"}, + {`(?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}]`, `.`}, + {`(?i)[\x00-\x{10FFFF}]`, `(?s:.)`}, // Empty string as a regular expression. // The empty string must be preserved inside parens in order diff --git a/src/pkg/exp/regexp/testdata/README b/src/pkg/exp/regexp/testdata/README new file mode 100644 index 000000000..b1b301be8 --- /dev/null +++ b/src/pkg/exp/regexp/testdata/README @@ -0,0 +1,23 @@ +AT&T POSIX Test Files +See textregex.c for copyright + license. + +testregex.c http://www2.research.att.com/~gsf/testregex/testregex.c +basic.dat http://www2.research.att.com/~gsf/testregex/basic.dat +nullsubexpr.dat http://www2.research.att.com/~gsf/testregex/nullsubexpr.dat +repetition.dat http://www2.research.att.com/~gsf/testregex/repetition.dat + +The test data has been edited to reflect RE2/Go differences: + * In a star of a possibly empty match like (a*)* matching x, + the no match case runs the starred subexpression zero times, + not once. This is consistent with (a*)* matching a, which + runs the starred subexpression one time, not twice. + * The submatch choice is first match, not the POSIX rule. + +Such changes are marked with 'RE2/Go'. + + +RE2 Test Files + +re2-exhaustive.txt.bz2 and re2-search.txt are built by running +'make log' in the RE2 distribution. http://code.google.com/p/re2/. +The exhaustive file is compressed because it is huge. diff --git a/src/pkg/exp/regexp/testdata/basic.dat b/src/pkg/exp/regexp/testdata/basic.dat new file mode 100644 index 000000000..7859290ba --- /dev/null +++ b/src/pkg/exp/regexp/testdata/basic.dat @@ -0,0 +1,221 @@ +NOTE all standard compliant implementations should pass these : 2002-05-31 + +BE abracadabra$ abracadabracadabra (7,18) +BE a...b abababbb (2,7) +BE XXXXXX ..XXXXXX (2,8) +E \) () (1,2) +BE a] a]a (0,2) +B } } (0,1) +E \} } (0,1) +BE \] ] (0,1) +B ] ] (0,1) +E ] ] (0,1) +B { { (0,1) +B } } (0,1) +BE ^a ax (0,1) +BE \^a a^a (1,3) +BE a\^ a^ (0,2) +BE a$ aa (1,2) +BE a\$ a$ (0,2) +BE ^$ NULL (0,0) +E $^ NULL (0,0) +E a($) aa (1,2)(2,2) +E a*(^a) aa (0,1)(0,1) +E (..)*(...)* a (0,0) +E (..)*(...)* abcd (0,4)(2,4) +E (ab|a)(bc|c) abc (0,3)(0,2)(2,3) +E (ab)c|abc abc (0,3)(0,2) +E a{0}b ab (1,2) +E (a*)(b?)(b+)b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7) +E (a*)(b{0,1})(b{1,})b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7) +E a{9876543210} NULL BADBR +E ((a|a)|a) a (0,1)(0,1)(0,1) +E (a*)(a|aa) aaaa (0,4)(0,3)(3,4) +E a*(a.|aa) aaaa (0,4)(2,4) +E a(b)|c(d)|a(e)f aef (0,3)(?,?)(?,?)(1,2) +E (a|b)?.* b (0,1)(0,1) +E (a|b)c|a(b|c) ac (0,2)(0,1) +E (a|b)c|a(b|c) ab (0,2)(?,?)(1,2) +E (a|b)*c|(a|ab)*c abc (0,3)(1,2) +E (a|b)*c|(a|ab)*c xc (1,2) +E (.a|.b).*|.*(.a|.b) xa (0,2)(0,2) +E a?(ab|ba)ab abab (0,4)(0,2) +E a?(ac{0}b|ba)ab abab (0,4)(0,2) +E ab|abab abbabab (0,2) +E aba|bab|bba baaabbbaba (5,8) +E aba|bab baaabbbaba (6,9) +E (aa|aaa)*|(a|aaaaa) aa (0,2)(0,2) +E (a.|.a.)*|(a|.a...) aa (0,2)(0,2) +E ab|a xabc (1,3) +E ab|a xxabc (2,4) +Ei (Ab|cD)* aBcD (0,4)(2,4) +BE [^-] --a (2,3) +BE [a-]* --a (0,3) +BE [a-m-]* --amoma-- (0,4) +E :::1:::0:|:::1:1:0: :::0:::1:::1:::0: (8,17) +E :::1:::0:|:::1:1:1: :::0:::1:::1:::0: (8,17) +{E [[:upper:]] A (0,1) [[]] not supported +E [[:lower:]]+ `az{ (1,3) +E [[:upper:]]+ @AZ[ (1,3) +# No collation in Go +#BE [[-]] [[-]] (2,4) +#BE [[.NIL.]] NULL ECOLLATE +#BE [[=aleph=]] NULL ECOLLATE +} +BE$ \n \n (0,1) +BEn$ \n \n (0,1) +BE$ [^a] \n (0,1) +BE$ \na \na (0,2) +E (a)(b)(c) abc (0,3)(0,1)(1,2)(2,3) +BE xxx xxx (0,3) +E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 6, (0,6) +E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) 2/7 (0,3) +E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 1,Feb 6 (5,11) +E3 ((((((((((((((((((((((((((((((x)))))))))))))))))))))))))))))) x (0,1)(0,1)(0,1) +E3 ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))* xx (0,2)(1,2)(1,2) +E a?(ab|ba)* ababababababababababababababababababababababababababababababababababababababababa (0,81)(79,81) +E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabbbbaa (18,25) +E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabaa (18,22) +E aaac|aabc|abac|abbc|baac|babc|bbac|bbbc baaabbbabac (7,11) +BE$ .* \x01\xff (0,2) +E aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa (53,57) +L aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa NOMATCH +E a*a*a*a*a*b aaaaaaaaab (0,10) +BE ^ NULL (0,0) +BE $ NULL (0,0) +BE ^$ NULL (0,0) +BE ^a$ a (0,1) +BE abc abc (0,3) +BE abc xabcy (1,4) +BE abc ababc (2,5) +BE ab*c abc (0,3) +BE ab*bc abc (0,3) +BE ab*bc abbc (0,4) +BE ab*bc abbbbc (0,6) +E ab+bc abbc (0,4) +E ab+bc abbbbc (0,6) +E ab?bc abbc (0,4) +E ab?bc abc (0,3) +E ab?c abc (0,3) +BE ^abc$ abc (0,3) +BE ^abc abcc (0,3) +BE abc$ aabc (1,4) +BE ^ abc (0,0) +BE $ abc (3,3) +BE a.c abc (0,3) +BE a.c axc (0,3) +BE a.*c axyzc (0,5) +BE a[bc]d abd (0,3) +BE a[b-d]e ace (0,3) +BE a[b-d] aac (1,3) +BE a[-b] a- (0,2) +BE a[b-] a- (0,2) +BE a] a] (0,2) +BE a[]]b a]b (0,3) +BE a[^bc]d aed (0,3) +BE a[^-b]c adc (0,3) +BE a[^]b]c adc (0,3) +E ab|cd abc (0,2) +E ab|cd abcd (0,2) +E a\(b a(b (0,3) +E a\(*b ab (0,2) +E a\(*b a((b (0,4) +E ((a)) abc (0,1)(0,1)(0,1) +E (a)b(c) abc (0,3)(0,1)(2,3) +E a+b+c aabbabc (4,7) +E a* aaa (0,3) +#E (a*)* - (0,0)(0,0) +E (a*)* - (0,0)(?,?) RE2/Go +E (a*)+ - (0,0)(0,0) +#E (a*|b)* - (0,0)(0,0) +E (a*|b)* - (0,0)(?,?) RE2/Go +E (a+|b)* ab (0,2)(1,2) +E (a+|b)+ ab (0,2)(1,2) +E (a+|b)? ab (0,1)(0,1) +BE [^ab]* cde (0,3) +#E (^)* - (0,0)(0,0) +E (^)* - (0,0)(?,?) RE2/Go +BE a* NULL (0,0) +E ([abc])*d abbbcd (0,6)(4,5) +E ([abc])*bcd abcd (0,4)(0,1) +E a|b|c|d|e e (0,1) +E (a|b|c|d|e)f ef (0,2)(0,1) +#E ((a*|b))* - (0,0)(0,0)(0,0) +E ((a*|b))* - (0,0)(?,?)(?,?) RE2/Go +BE abcd*efg abcdefg (0,7) +BE ab* xabyabbbz (1,3) +BE ab* xayabbbz (1,2) +E (ab|cd)e abcde (2,5)(2,4) +BE [abhgefdc]ij hij (0,3) +E (a|b)c*d abcd (1,4)(1,2) +E (ab|ab*)bc abc (0,3)(0,1) +E a([bc]*)c* abc (0,3)(1,3) +E a([bc]*)(c*d) abcd (0,4)(1,3)(3,4) +E a([bc]+)(c*d) abcd (0,4)(1,3)(3,4) +E a([bc]*)(c+d) abcd (0,4)(1,2)(2,4) +E a[bcd]*dcdcde adcdcde (0,7) +E (ab|a)b*c abc (0,3)(0,2) +E ((a)(b)c)(d) abcd (0,4)(0,3)(0,1)(1,2)(3,4) +BE [A-Za-z_][A-Za-z0-9_]* alpha (0,5) +E ^a(bc+|b[eh])g|.h$ abh (1,3) +E (bc+d$|ef*g.|h?i(j|k)) effgz (0,5)(0,5) +E (bc+d$|ef*g.|h?i(j|k)) ij (0,2)(0,2)(1,2) +E (bc+d$|ef*g.|h?i(j|k)) reffgz (1,6)(1,6) +E (((((((((a))))))))) a (0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1) +BE multiple words multiple words yeah (0,14) +E (.*)c(.*) abcde (0,5)(0,2)(3,5) +BE abcd abcd (0,4) +E a(bc)d abcd (0,4)(1,3) +E a[-]?c ac (0,3) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qaddafi (0,15)(?,?)(10,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mo'ammar Gadhafi (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Kaddafi (0,15)(?,?)(10,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qadhafi (0,15)(?,?)(10,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gadafi (0,14)(?,?)(10,11) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadafi (0,15)(?,?)(11,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moamar Gaddafi (0,14)(?,?)(9,11) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadhdhafi (0,18)(?,?)(13,15) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Khaddafi (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafy (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghadafi (0,15)(?,?)(11,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafi (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muamar Kaddafi (0,14)(?,?)(9,11) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Quathafi (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gheddafi (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Khadafy (0,15)(?,?)(11,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Qudhafi (0,15)(?,?)(10,12) +E a+(b|c)*d+ aabcdd (0,6)(3,4) +E ^.+$ vivi (0,4) +E ^(.+)$ vivi (0,4)(0,4) +E ^([^!.]+).att.com!(.+)$ gryphon.att.com!eby (0,19)(0,7)(16,19) +E ^([^!]+!)?([^!]+)$ bas (0,3)(?,?)(0,3) +E ^([^!]+!)?([^!]+)$ bar!bas (0,7)(0,4)(4,7) +E ^([^!]+!)?([^!]+)$ foo!bas (0,7)(0,4)(4,7) +E ^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(4,8)(8,11) +E ((foo)|(bar))!bas bar!bas (0,7)(0,3)(?,?)(0,3) +E ((foo)|(bar))!bas foo!bar!bas (4,11)(4,7)(?,?)(4,7) +E ((foo)|(bar))!bas foo!bas (0,7)(0,3)(0,3) +E ((foo)|bar)!bas bar!bas (0,7)(0,3) +E ((foo)|bar)!bas foo!bar!bas (4,11)(4,7) +E ((foo)|bar)!bas foo!bas (0,7)(0,3)(0,3) +E (foo|(bar))!bas bar!bas (0,7)(0,3)(0,3) +E (foo|(bar))!bas foo!bar!bas (4,11)(4,7)(4,7) +E (foo|(bar))!bas foo!bas (0,7)(0,3) +E (foo|bar)!bas bar!bas (0,7)(0,3) +E (foo|bar)!bas foo!bar!bas (4,11)(4,7) +E (foo|bar)!bas foo!bas (0,7)(0,3) +E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11) +E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bas (0,3)(?,?)(0,3) +E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bar!bas (0,7)(0,4)(4,7) +E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(?,?)(?,?)(4,8)(8,11) +E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bas (0,7)(0,4)(4,7) +E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bas (0,3)(0,3)(?,?)(0,3) +E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bar!bas (0,7)(0,7)(0,4)(4,7) +E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11) +E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bas (0,7)(0,7)(0,4)(4,7) +E .*(/XXX).* /XXX (0,4)(0,4) +E .*(\\XXX).* \XXX (0,4)(0,4) +E \\XXX \XXX (0,4) +E .*(/000).* /000 (0,4)(0,4) +E .*(\\000).* \000 (0,4)(0,4) +E \\000 \000 (0,4) diff --git a/src/pkg/exp/regexp/testdata/nullsubexpr.dat b/src/pkg/exp/regexp/testdata/nullsubexpr.dat new file mode 100644 index 000000000..2e18fbb91 --- /dev/null +++ b/src/pkg/exp/regexp/testdata/nullsubexpr.dat @@ -0,0 +1,79 @@ +NOTE null subexpression matches : 2002-06-06 + +E (a*)* a (0,1)(0,1) +#E SAME x (0,0)(0,0) +E SAME x (0,0)(?,?) RE2/Go +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) +E (a*)+ a (0,1)(0,1) +E SAME x (0,0)(0,0) +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) +E (a+)* a (0,1)(0,1) +E SAME x (0,0) +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) +E (a+)+ a (0,1)(0,1) +E SAME x NOMATCH +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) + +E ([a]*)* a (0,1)(0,1) +#E SAME x (0,0)(0,0) +E SAME x (0,0)(?,?) RE2/Go +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) +E ([a]*)+ a (0,1)(0,1) +E SAME x (0,0)(0,0) +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) +E ([^b]*)* a (0,1)(0,1) +#E SAME b (0,0)(0,0) +E SAME b (0,0)(?,?) RE2/Go +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaab (0,6)(0,6) +E ([ab]*)* a (0,1)(0,1) +E SAME aaaaaa (0,6)(0,6) +E SAME ababab (0,6)(0,6) +E SAME bababa (0,6)(0,6) +E SAME b (0,1)(0,1) +E SAME bbbbbb (0,6)(0,6) +E SAME aaaabcde (0,5)(0,5) +E ([^a]*)* b (0,1)(0,1) +E SAME bbbbbb (0,6)(0,6) +#E SAME aaaaaa (0,0)(0,0) +E SAME aaaaaa (0,0)(?,?) RE2/Go +E ([^ab]*)* ccccxx (0,6)(0,6) +#E SAME ababab (0,0)(0,0) +E SAME ababab (0,0)(?,?) RE2/Go + +E ((z)+|a)* zabcde (0,2)(1,2) + +#{E a+? aaaaaa (0,1) no *? +? mimimal match ops +#E (a) aaa (0,1)(0,1) +#E (a*?) aaa (0,0)(0,0) +#E (a)*? aaa (0,0) +#E (a*?)*? aaa (0,0) +#} + +B \(a*\)*\(x\) x (0,1)(0,0)(0,1) +B \(a*\)*\(x\) ax (0,2)(0,1)(1,2) +B \(a*\)*\(x\) axa (0,2)(0,1)(1,2) +B \(a*\)*\(x\)\(\1\) x (0,1)(0,0)(0,1)(1,1) +B \(a*\)*\(x\)\(\1\) ax (0,2)(1,1)(1,2)(2,2) +B \(a*\)*\(x\)\(\1\) axa (0,3)(0,1)(1,2)(2,3) +B \(a*\)*\(x\)\(\1\)\(x\) axax (0,4)(0,1)(1,2)(2,3)(3,4) +B \(a*\)*\(x\)\(\1\)\(x\) axxa (0,3)(1,1)(1,2)(2,2)(2,3) + +#E (a*)*(x) x (0,1)(0,0)(0,1) +E (a*)*(x) x (0,1)(?,?)(0,1) RE2/Go +E (a*)*(x) ax (0,2)(0,1)(1,2) +E (a*)*(x) axa (0,2)(0,1)(1,2) + +E (a*)+(x) x (0,1)(0,0)(0,1) +E (a*)+(x) ax (0,2)(0,1)(1,2) +E (a*)+(x) axa (0,2)(0,1)(1,2) + +E (a*){2}(x) x (0,1)(0,0)(0,1) +E (a*){2}(x) ax (0,2)(1,1)(1,2) +E (a*){2}(x) axa (0,2)(1,1)(1,2) diff --git a/src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2 b/src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2 new file mode 100644 index 000000000..a357f2801 Binary files /dev/null and b/src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2 differ diff --git a/src/pkg/exp/regexp/testdata/re2-search.txt b/src/pkg/exp/regexp/testdata/re2-search.txt new file mode 100644 index 000000000..f648e5527 --- /dev/null +++ b/src/pkg/exp/regexp/testdata/re2-search.txt @@ -0,0 +1,3667 @@ +# RE2 basic search tests built by make log +# Thu Sep 8 13:43:43 EDT 2011 +Regexp.SearchTests +strings +"" +"a" +regexps +"a" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:a)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"zyzzyva" +regexps +"a" +-;-;-;- +-;6-7;-;6-7 +"^(?:a)$" +-;-;-;- +-;-;-;- +"^(?:a)" +-;-;-;- +-;-;-;- +"(?:a)$" +-;-;-;- +-;6-7;-;6-7 +strings +"" +"aa" +regexps +"a+" +-;-;-;- +0-2;0-2;0-2;0-2 +"^(?:a+)$" +-;-;-;- +0-2;0-2;0-2;0-2 +"^(?:a+)" +-;-;-;- +0-2;0-2;0-2;0-2 +"(?:a+)$" +-;-;-;- +0-2;0-2;0-2;0-2 +strings +"" +"ab" +regexps +"(a+|b)+" +-;-;-;- +0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2 +"^(?:(a+|b)+)$" +-;-;-;- +0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2 +"^(?:(a+|b)+)" +-;-;-;- +0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2 +"(?:(a+|b)+)$" +-;-;-;- +0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2 +strings +"" +"xabcdx" +regexps +"ab|cd" +-;-;-;- +-;1-3;-;1-3 +"^(?:ab|cd)$" +-;-;-;- +-;-;-;- +"^(?:ab|cd)" +-;-;-;- +-;-;-;- +"(?:ab|cd)$" +-;-;-;- +-;-;-;- +strings +"" +"hello\ngoodbye\n" +regexps +"h.*od?" +-;-;-;- +-;0-5;-;0-5 +"^(?:h.*od?)$" +-;-;-;- +-;-;-;- +"^(?:h.*od?)" +-;-;-;- +-;0-5;-;0-5 +"(?:h.*od?)$" +-;-;-;- +-;-;-;- +strings +"" +"hello\ngoodbye\n" +regexps +"h.*o" +-;-;-;- +-;0-5;-;0-5 +"^(?:h.*o)$" +-;-;-;- +-;-;-;- +"^(?:h.*o)" +-;-;-;- +-;0-5;-;0-5 +"(?:h.*o)$" +-;-;-;- +-;-;-;- +strings +"" +"goodbye\nhello\n" +regexps +"h.*o" +-;-;-;- +-;8-13;-;8-13 +"^(?:h.*o)$" +-;-;-;- +-;-;-;- +"^(?:h.*o)" +-;-;-;- +-;-;-;- +"(?:h.*o)$" +-;-;-;- +-;-;-;- +strings +"" +"hello world" +regexps +"h.*o" +-;-;-;- +-;0-8;-;0-8 +"^(?:h.*o)$" +-;-;-;- +-;-;-;- +"^(?:h.*o)" +-;-;-;- +-;0-8;-;0-8 +"(?:h.*o)$" +-;-;-;- +-;-;-;- +strings +"" +"othello, world" +regexps +"h.*o" +-;-;-;- +-;2-11;-;2-11 +"^(?:h.*o)$" +-;-;-;- +-;-;-;- +"^(?:h.*o)" +-;-;-;- +-;-;-;- +"(?:h.*o)$" +-;-;-;- +-;-;-;- +strings +"" +"aaaaaaa" +regexps +"[^\\s\\S]" +-;-;-;- +-;-;-;- +"^(?:[^\\s\\S])$" +-;-;-;- +-;-;-;- +"^(?:[^\\s\\S])" +-;-;-;- +-;-;-;- +"(?:[^\\s\\S])$" +-;-;-;- +-;-;-;- +strings +"" +"aaaaaaa" +regexps +"a" +-;-;-;- +-;0-1;-;0-1 +"^(?:a)$" +-;-;-;- +-;-;-;- +"^(?:a)" +-;-;-;- +-;0-1;-;0-1 +"(?:a)$" +-;-;-;- +-;6-7;-;6-7 +strings +"" +"aaaaaaa" +regexps +"a*" +0-0;0-0;0-0;0-0 +0-7;0-7;0-7;0-7 +"^(?:a*)$" +0-0;0-0;0-0;0-0 +0-7;0-7;0-7;0-7 +"^(?:a*)" +0-0;0-0;0-0;0-0 +0-7;0-7;0-7;0-7 +"(?:a*)$" +0-0;0-0;0-0;0-0 +0-7;0-7;0-7;0-7 +strings +"" +"" +regexps +"a*" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:a*)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:a*)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:a*)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"" +regexps +"a*" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:a*)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:a*)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:a*)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"xabcdx" +regexps +"ab|cd" +-;-;-;- +-;1-3;-;1-3 +"^(?:ab|cd)$" +-;-;-;- +-;-;-;- +"^(?:ab|cd)" +-;-;-;- +-;-;-;- +"(?:ab|cd)$" +-;-;-;- +-;-;-;- +strings +"" +"cab" +regexps +"a" +-;-;-;- +-;1-2;-;1-2 +"^(?:a)$" +-;-;-;- +-;-;-;- +"^(?:a)" +-;-;-;- +-;-;-;- +"(?:a)$" +-;-;-;- +-;-;-;- +strings +"" +"cab" +regexps +"a*b" +-;-;-;- +-;1-3;-;1-3 +"^(?:a*b)$" +-;-;-;- +-;-;-;- +"^(?:a*b)" +-;-;-;- +-;-;-;- +"(?:a*b)$" +-;-;-;- +-;1-3;-;1-3 +strings +"" +"x" +regexps +"((((((((((((((((((((x))))))))))))))))))))" +-;-;-;- +0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 +"^(?:((((((((((((((((((((x)))))))))))))))))))))$" +-;-;-;- +0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 +"^(?:((((((((((((((((((((x)))))))))))))))))))))" +-;-;-;- +0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 +"(?:((((((((((((((((((((x)))))))))))))))))))))$" +-;-;-;- +0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 +strings +"" +"xxxabcdxxx" +regexps +"[abcd]" +-;-;-;- +-;3-4;-;3-4 +"^(?:[abcd])$" +-;-;-;- +-;-;-;- +"^(?:[abcd])" +-;-;-;- +-;-;-;- +"(?:[abcd])$" +-;-;-;- +-;-;-;- +strings +"" +"xxxabcdxxx" +regexps +"[^x]" +-;-;-;- +-;3-4;-;3-4 +"^(?:[^x])$" +-;-;-;- +-;-;-;- +"^(?:[^x])" +-;-;-;- +-;-;-;- +"(?:[^x])$" +-;-;-;- +-;-;-;- +strings +"" +"xxxabcdxxx" +regexps +"[abcd]+" +-;-;-;- +-;3-7;-;3-7 +"^(?:[abcd]+)$" +-;-;-;- +-;-;-;- +"^(?:[abcd]+)" +-;-;-;- +-;-;-;- +"(?:[abcd]+)$" +-;-;-;- +-;-;-;- +strings +"" +"xxxabcdxxx" +regexps +"[^x]+" +-;-;-;- +-;3-7;-;3-7 +"^(?:[^x]+)$" +-;-;-;- +-;-;-;- +"^(?:[^x]+)" +-;-;-;- +-;-;-;- +"(?:[^x]+)$" +-;-;-;- +-;-;-;- +strings +"" +"fo" +regexps +"(fo|foo)" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"^(?:(fo|foo))$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"^(?:(fo|foo))" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"(?:(fo|foo))$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +strings +"" +"foo" +regexps +"(foo|fo)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:(foo|fo))$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:(foo|fo))" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:(foo|fo))$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"aA" +regexps +"aa" +-;-;-;- +-;-;-;- +"^(?:aa)$" +-;-;-;- +-;-;-;- +"^(?:aa)" +-;-;-;- +-;-;-;- +"(?:aa)$" +-;-;-;- +-;-;-;- +strings +"" +"Aa" +regexps +"a" +-;-;-;- +-;1-2;-;1-2 +"^(?:a)$" +-;-;-;- +-;-;-;- +"^(?:a)" +-;-;-;- +-;-;-;- +"(?:a)$" +-;-;-;- +-;1-2;-;1-2 +strings +"" +"A" +regexps +"a" +-;-;-;- +-;-;-;- +"^(?:a)$" +-;-;-;- +-;-;-;- +"^(?:a)" +-;-;-;- +-;-;-;- +"(?:a)$" +-;-;-;- +-;-;-;- +strings +"" +"abc" +regexps +"ABC" +-;-;-;- +-;-;-;- +"^(?:ABC)$" +-;-;-;- +-;-;-;- +"^(?:ABC)" +-;-;-;- +-;-;-;- +"(?:ABC)$" +-;-;-;- +-;-;-;- +strings +"" +"XABCY" +regexps +"abc" +-;-;-;- +-;-;-;- +"^(?:abc)$" +-;-;-;- +-;-;-;- +"^(?:abc)" +-;-;-;- +-;-;-;- +"(?:abc)$" +-;-;-;- +-;-;-;- +strings +"" +"xabcy" +regexps +"ABC" +-;-;-;- +-;-;-;- +"^(?:ABC)$" +-;-;-;- +-;-;-;- +"^(?:ABC)" +-;-;-;- +-;-;-;- +"(?:ABC)$" +-;-;-;- +-;-;-;- +strings +"" +"foo" +regexps +"foo|bar|[A-Z]" +-;-;-;- +0-3;0-3;0-3;0-3 +"^(?:foo|bar|[A-Z])$" +-;-;-;- +0-3;0-3;0-3;0-3 +"^(?:foo|bar|[A-Z])" +-;-;-;- +0-3;0-3;0-3;0-3 +"(?:foo|bar|[A-Z])$" +-;-;-;- +0-3;0-3;0-3;0-3 +strings +"" +"foo" +regexps +"^(foo|bar|[A-Z])" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^(foo|bar|[A-Z]))$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^(foo|bar|[A-Z]))" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:^(foo|bar|[A-Z]))$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"foo\n" +regexps +"(foo|bar|[A-Z])$" +-;-;-;- +-;-;-;- +"^(?:(foo|bar|[A-Z])$)$" +-;-;-;- +-;-;-;- +"^(?:(foo|bar|[A-Z])$)" +-;-;-;- +-;-;-;- +"(?:(foo|bar|[A-Z])$)$" +-;-;-;- +-;-;-;- +strings +"" +"foo" +regexps +"(foo|bar|[A-Z])$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:(foo|bar|[A-Z])$)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:(foo|bar|[A-Z])$)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:(foo|bar|[A-Z])$)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"foo\n" +regexps +"^(foo|bar|[A-Z])$" +-;-;-;- +-;-;-;- +"^(?:^(foo|bar|[A-Z])$)$" +-;-;-;- +-;-;-;- +"^(?:^(foo|bar|[A-Z])$)" +-;-;-;- +-;-;-;- +"(?:^(foo|bar|[A-Z])$)$" +-;-;-;- +-;-;-;- +strings +"" +"foo" +regexps +"^(foo|bar|[A-Z])$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^(foo|bar|[A-Z])$)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^(foo|bar|[A-Z])$)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:^(foo|bar|[A-Z])$)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"bar" +regexps +"^(foo|bar|[A-Z])$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^(foo|bar|[A-Z])$)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^(foo|bar|[A-Z])$)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:^(foo|bar|[A-Z])$)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"X" +regexps +"^(foo|bar|[A-Z])$" +-;-;-;- +0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 +"^(?:^(foo|bar|[A-Z])$)$" +-;-;-;- +0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 +"^(?:^(foo|bar|[A-Z])$)" +-;-;-;- +0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 +"(?:^(foo|bar|[A-Z])$)$" +-;-;-;- +0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 +strings +"" +"XY" +regexps +"^(foo|bar|[A-Z])$" +-;-;-;- +-;-;-;- +"^(?:^(foo|bar|[A-Z])$)$" +-;-;-;- +-;-;-;- +"^(?:^(foo|bar|[A-Z])$)" +-;-;-;- +-;-;-;- +"(?:^(foo|bar|[A-Z])$)$" +-;-;-;- +-;-;-;- +strings +"" +"fo" +regexps +"^(fo|foo)$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"^(?:^(fo|foo)$)$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"^(?:^(fo|foo)$)" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"(?:^(fo|foo)$)$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +strings +"" +"foo" +regexps +"^(fo|foo)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^(fo|foo)$)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^(fo|foo)$)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:^(fo|foo)$)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"fo" +regexps +"^^(fo|foo)$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"^(?:^^(fo|foo)$)$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"^(?:^^(fo|foo)$)" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"(?:^^(fo|foo)$)$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +strings +"" +"foo" +regexps +"^^(fo|foo)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^^(fo|foo)$)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^^(fo|foo)$)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:^^(fo|foo)$)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"" +regexps +"^$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^$)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"^$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"" +regexps +"^^$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^^$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^^$)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^^$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"" +regexps +"^$$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^$$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^$$)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^$$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"^^$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^^$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x" +regexps +"^$$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^$$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"" +regexps +"^^$$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^^$$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^^$$)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^^$$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"^^$$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^^$$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^^$$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^^$$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"" +regexps +"^^^^^^^^$$$$$$$$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^^^^^^^^$$$$$$$$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^^^^^^^^$$$$$$$$)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^^^^^^^^$$$$$$$$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"^" +0-0;0-0;0-0;0-0 +-;0-0;-;0-0 +"^(?:^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^)" +0-0;0-0;0-0;0-0 +-;0-0;-;0-0 +"(?:^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x" +regexps +"$" +0-0;0-0;0-0;0-0 +-;1-1;-;1-1 +"^(?:$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:$)$" +0-0;0-0;0-0;0-0 +-;1-1;-;1-1 +strings +"" +"nofoo foo that" +regexps +"\\bfoo\\b" +-;-;-;- +-;6-9;-;6-9 +"^(?:\\bfoo\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bfoo\\b)" +-;-;-;- +-;-;-;- +"(?:\\bfoo\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"faoa x" +regexps +"a\\b" +-;-;-;- +-;3-4;-;3-4 +"^(?:a\\b)$" +-;-;-;- +-;-;-;- +"^(?:a\\b)" +-;-;-;- +-;-;-;- +"(?:a\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"bar x" +regexps +"\\bbar" +-;-;-;- +-;0-3;-;0-3 +"^(?:\\bbar)$" +-;-;-;- +-;-;-;- +"^(?:\\bbar)" +-;-;-;- +-;0-3;-;0-3 +"(?:\\bbar)$" +-;-;-;- +-;-;-;- +strings +"" +"foo\nbar x" +regexps +"\\bbar" +-;-;-;- +-;4-7;-;4-7 +"^(?:\\bbar)$" +-;-;-;- +-;-;-;- +"^(?:\\bbar)" +-;-;-;- +-;-;-;- +"(?:\\bbar)$" +-;-;-;- +-;-;-;- +strings +"" +"foobar" +regexps +"bar\\b" +-;-;-;- +-;3-6;-;3-6 +"^(?:bar\\b)$" +-;-;-;- +-;-;-;- +"^(?:bar\\b)" +-;-;-;- +-;-;-;- +"(?:bar\\b)$" +-;-;-;- +-;3-6;-;3-6 +strings +"" +"foobar\nxxx" +regexps +"bar\\b" +-;-;-;- +-;3-6;-;3-6 +"^(?:bar\\b)$" +-;-;-;- +-;-;-;- +"^(?:bar\\b)" +-;-;-;- +-;-;-;- +"(?:bar\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"foo" +regexps +"(foo|bar|[A-Z])\\b" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:(foo|bar|[A-Z])\\b)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:(foo|bar|[A-Z])\\b)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:(foo|bar|[A-Z])\\b)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"foo\n" +regexps +"(foo|bar|[A-Z])\\b" +-;-;-;- +-;0-3 0-3;-;0-3 0-3 +"^(?:(foo|bar|[A-Z])\\b)$" +-;-;-;- +-;-;-;- +"^(?:(foo|bar|[A-Z])\\b)" +-;-;-;- +-;0-3 0-3;-;0-3 0-3 +"(?:(foo|bar|[A-Z])\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"" +regexps +"\\b" +-;-;-;- +-;-;-;- +"^(?:\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\b)" +-;-;-;- +-;-;-;- +"(?:\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"x" +regexps +"\\b" +-;-;-;- +-;0-0;-;0-0 +"^(?:\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\b)" +-;-;-;- +-;0-0;-;0-0 +"(?:\\b)$" +-;-;-;- +-;1-1;-;1-1 +strings +"" +"foo" +regexps +"\\b(foo|bar|[A-Z])" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:\\b(foo|bar|[A-Z]))$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:\\b(foo|bar|[A-Z]))" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:\\b(foo|bar|[A-Z]))$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"X" +regexps +"\\b(foo|bar|[A-Z])\\b" +-;-;-;- +0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 +"^(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 +"^(?:\\b(foo|bar|[A-Z])\\b)" +-;-;-;- +0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 +"(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1 +strings +"" +"XY" +regexps +"\\b(foo|bar|[A-Z])\\b" +-;-;-;- +-;-;-;- +"^(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\b(foo|bar|[A-Z])\\b)" +-;-;-;- +-;-;-;- +"(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"bar" +regexps +"\\b(foo|bar|[A-Z])\\b" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:\\b(foo|bar|[A-Z])\\b)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"foo" +regexps +"\\b(foo|bar|[A-Z])\\b" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:\\b(foo|bar|[A-Z])\\b)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"foo\n" +regexps +"\\b(foo|bar|[A-Z])\\b" +-;-;-;- +-;0-3 0-3;-;0-3 0-3 +"^(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\b(foo|bar|[A-Z])\\b)" +-;-;-;- +-;0-3 0-3;-;0-3 0-3 +"(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"ffoo bbar N x" +regexps +"\\b(foo|bar|[A-Z])\\b" +-;-;-;- +-;10-11 10-11;-;10-11 10-11 +"^(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\b(foo|bar|[A-Z])\\b)" +-;-;-;- +-;-;-;- +"(?:\\b(foo|bar|[A-Z])\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"fo" +regexps +"\\b(fo|foo)\\b" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"^(?:\\b(fo|foo)\\b)$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"^(?:\\b(fo|foo)\\b)" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"(?:\\b(fo|foo)\\b)$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +strings +"" +"foo" +regexps +"\\b(fo|foo)\\b" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:\\b(fo|foo)\\b)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:\\b(fo|foo)\\b)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:\\b(fo|foo)\\b)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"" +regexps +"\\b\\b" +-;-;-;- +-;-;-;- +"^(?:\\b\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\b\\b)" +-;-;-;- +-;-;-;- +"(?:\\b\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"x" +regexps +"\\b\\b" +-;-;-;- +-;0-0;-;0-0 +"^(?:\\b\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\b\\b)" +-;-;-;- +-;0-0;-;0-0 +"(?:\\b\\b)$" +-;-;-;- +-;1-1;-;1-1 +strings +"" +"" +regexps +"\\b$" +-;-;-;- +-;-;-;- +"^(?:\\b$)$" +-;-;-;- +-;-;-;- +"^(?:\\b$)" +-;-;-;- +-;-;-;- +"(?:\\b$)$" +-;-;-;- +-;-;-;- +strings +"" +"x" +regexps +"\\b$" +-;-;-;- +-;1-1;-;1-1 +"^(?:\\b$)$" +-;-;-;- +-;-;-;- +"^(?:\\b$)" +-;-;-;- +-;-;-;- +"(?:\\b$)$" +-;-;-;- +-;1-1;-;1-1 +strings +"" +"y x" +regexps +"\\b$" +-;-;-;- +-;3-3;-;3-3 +"^(?:\\b$)$" +-;-;-;- +-;-;-;- +"^(?:\\b$)" +-;-;-;- +-;-;-;- +"(?:\\b$)$" +-;-;-;- +-;3-3;-;3-3 +strings +"" +"x" +regexps +"\\b.$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\b.$)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\b.$)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:\\b.$)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"fo" +regexps +"^\\b(fo|foo)\\b" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"^(?:^\\b(fo|foo)\\b)$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"^(?:^\\b(fo|foo)\\b)" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +"(?:^\\b(fo|foo)\\b)$" +-;-;-;- +0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2 +strings +"" +"foo" +regexps +"^\\b(fo|foo)\\b" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^\\b(fo|foo)\\b)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:^\\b(fo|foo)\\b)" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"(?:^\\b(fo|foo)\\b)$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"" +regexps +"^\\b" +-;-;-;- +-;-;-;- +"^(?:^\\b)$" +-;-;-;- +-;-;-;- +"^(?:^\\b)" +-;-;-;- +-;-;-;- +"(?:^\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"x" +regexps +"^\\b" +-;-;-;- +-;0-0;-;0-0 +"^(?:^\\b)$" +-;-;-;- +-;-;-;- +"^(?:^\\b)" +-;-;-;- +-;0-0;-;0-0 +"(?:^\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"" +regexps +"^\\b\\b" +-;-;-;- +-;-;-;- +"^(?:^\\b\\b)$" +-;-;-;- +-;-;-;- +"^(?:^\\b\\b)" +-;-;-;- +-;-;-;- +"(?:^\\b\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"x" +regexps +"^\\b\\b" +-;-;-;- +-;0-0;-;0-0 +"^(?:^\\b\\b)$" +-;-;-;- +-;-;-;- +"^(?:^\\b\\b)" +-;-;-;- +-;0-0;-;0-0 +"(?:^\\b\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"" +regexps +"^\\b$" +-;-;-;- +-;-;-;- +"^(?:^\\b$)$" +-;-;-;- +-;-;-;- +"^(?:^\\b$)" +-;-;-;- +-;-;-;- +"(?:^\\b$)$" +-;-;-;- +-;-;-;- +strings +"" +"x" +regexps +"^\\b$" +-;-;-;- +-;-;-;- +"^(?:^\\b$)$" +-;-;-;- +-;-;-;- +"^(?:^\\b$)" +-;-;-;- +-;-;-;- +"(?:^\\b$)$" +-;-;-;- +-;-;-;- +strings +"" +"x" +regexps +"^\\b.$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:^\\b.$)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:^\\b.$)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:^\\b.$)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"x" +regexps +"^\\b.\\b$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:^\\b.\\b$)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:^\\b.\\b$)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:^\\b.\\b$)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"" +regexps +"^^^^^^^^\\b$$$$$$$" +-;-;-;- +-;-;-;- +"^(?:^^^^^^^^\\b$$$$$$$)$" +-;-;-;- +-;-;-;- +"^(?:^^^^^^^^\\b$$$$$$$)" +-;-;-;- +-;-;-;- +"(?:^^^^^^^^\\b$$$$$$$)$" +-;-;-;- +-;-;-;- +strings +"" +"x" +regexps +"^^^^^^^^\\b.$$$$$$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:^^^^^^^^\\b.$$$$$$)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:^^^^^^^^\\b.$$$$$$)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:^^^^^^^^\\b.$$$$$$)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"x" +regexps +"^^^^^^^^\\b$$$$$$$" +-;-;-;- +-;-;-;- +"^(?:^^^^^^^^\\b$$$$$$$)$" +-;-;-;- +-;-;-;- +"^(?:^^^^^^^^\\b$$$$$$$)" +-;-;-;- +-;-;-;- +"(?:^^^^^^^^\\b$$$$$$$)$" +-;-;-;- +-;-;-;- +strings +"" +"n foo xfoox that" +regexps +"\\Bfoo\\B" +-;-;-;- +-;7-10;-;7-10 +"^(?:\\Bfoo\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\Bfoo\\B)" +-;-;-;- +-;-;-;- +"(?:\\Bfoo\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"faoa x" +regexps +"a\\B" +-;-;-;- +-;1-2;-;1-2 +"^(?:a\\B)$" +-;-;-;- +-;-;-;- +"^(?:a\\B)" +-;-;-;- +-;-;-;- +"(?:a\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"bar x" +regexps +"\\Bbar" +-;-;-;- +-;-;-;- +"^(?:\\Bbar)$" +-;-;-;- +-;-;-;- +"^(?:\\Bbar)" +-;-;-;- +-;-;-;- +"(?:\\Bbar)$" +-;-;-;- +-;-;-;- +strings +"" +"foo\nbar x" +regexps +"\\Bbar" +-;-;-;- +-;-;-;- +"^(?:\\Bbar)$" +-;-;-;- +-;-;-;- +"^(?:\\Bbar)" +-;-;-;- +-;-;-;- +"(?:\\Bbar)$" +-;-;-;- +-;-;-;- +strings +"" +"foobar" +regexps +"bar\\B" +-;-;-;- +-;-;-;- +"^(?:bar\\B)$" +-;-;-;- +-;-;-;- +"^(?:bar\\B)" +-;-;-;- +-;-;-;- +"(?:bar\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"foobar\nxxx" +regexps +"bar\\B" +-;-;-;- +-;-;-;- +"^(?:bar\\B)$" +-;-;-;- +-;-;-;- +"^(?:bar\\B)" +-;-;-;- +-;-;-;- +"(?:bar\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"foox" +regexps +"(foo|bar|[A-Z])\\B" +-;-;-;- +-;0-3 0-3;-;0-3 0-3 +"^(?:(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +"^(?:(foo|bar|[A-Z])\\B)" +-;-;-;- +-;0-3 0-3;-;0-3 0-3 +"(?:(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"foo\n" +regexps +"(foo|bar|[A-Z])\\B" +-;-;-;- +-;-;-;- +"^(?:(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +"^(?:(foo|bar|[A-Z])\\B)" +-;-;-;- +-;-;-;- +"(?:(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"" +regexps +"\\B" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:\\B)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:\\B)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:\\B)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"\\B" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:\\B)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:\\B)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:\\B)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"foo" +regexps +"\\B(foo|bar|[A-Z])" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z]))$" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z]))" +-;-;-;- +-;-;-;- +"(?:\\B(foo|bar|[A-Z]))$" +-;-;-;- +-;-;-;- +strings +"" +"xXy" +regexps +"\\B(foo|bar|[A-Z])\\B" +-;-;-;- +-;1-2 1-2;-;1-2 1-2 +"^(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z])\\B)" +-;-;-;- +-;-;-;- +"(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"XY" +regexps +"\\B(foo|bar|[A-Z])\\B" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z])\\B)" +-;-;-;- +-;-;-;- +"(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"XYZ" +regexps +"\\B(foo|bar|[A-Z])\\B" +-;-;-;- +-;1-2 1-2;-;1-2 1-2 +"^(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z])\\B)" +-;-;-;- +-;-;-;- +"(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"abara" +regexps +"\\B(foo|bar|[A-Z])\\B" +-;-;-;- +-;1-4 1-4;-;1-4 1-4 +"^(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z])\\B)" +-;-;-;- +-;-;-;- +"(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"xfoo_" +regexps +"\\B(foo|bar|[A-Z])\\B" +-;-;-;- +-;1-4 1-4;-;1-4 1-4 +"^(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z])\\B)" +-;-;-;- +-;-;-;- +"(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"xfoo\n" +regexps +"\\B(foo|bar|[A-Z])\\B" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z])\\B)" +-;-;-;- +-;-;-;- +"(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"foo bar vNx" +regexps +"\\B(foo|bar|[A-Z])\\B" +-;-;-;- +-;9-10 9-10;-;9-10 9-10 +"^(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|bar|[A-Z])\\B)" +-;-;-;- +-;-;-;- +"(?:\\B(foo|bar|[A-Z])\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"xfoo" +regexps +"\\B(fo|foo)\\B" +-;-;-;- +-;1-3 1-3;-;1-3 1-3 +"^(?:\\B(fo|foo)\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\B(fo|foo)\\B)" +-;-;-;- +-;-;-;- +"(?:\\B(fo|foo)\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"xfooo" +regexps +"\\B(foo|fo)\\B" +-;-;-;- +-;1-4 1-4;-;1-4 1-4 +"^(?:\\B(foo|fo)\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\B(foo|fo)\\B)" +-;-;-;- +-;-;-;- +"(?:\\B(foo|fo)\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"" +regexps +"\\B\\B" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:\\B\\B)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:\\B\\B)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:\\B\\B)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"\\B\\B" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:\\B\\B)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:\\B\\B)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:\\B\\B)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"" +regexps +"\\B$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:\\B$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:\\B$)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:\\B$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"\\B$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:\\B$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:\\B$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:\\B$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"y x" +regexps +"\\B$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:\\B$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:\\B$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:\\B$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x" +regexps +"\\B.$" +-;-;-;- +-;-;-;- +"^(?:\\B.$)$" +-;-;-;- +-;-;-;- +"^(?:\\B.$)" +-;-;-;- +-;-;-;- +"(?:\\B.$)$" +-;-;-;- +-;-;-;- +strings +"" +"fo" +regexps +"^\\B(fo|foo)\\B" +-;-;-;- +-;-;-;- +"^(?:^\\B(fo|foo)\\B)$" +-;-;-;- +-;-;-;- +"^(?:^\\B(fo|foo)\\B)" +-;-;-;- +-;-;-;- +"(?:^\\B(fo|foo)\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"foo" +regexps +"^\\B(fo|foo)\\B" +-;-;-;- +-;-;-;- +"^(?:^\\B(fo|foo)\\B)$" +-;-;-;- +-;-;-;- +"^(?:^\\B(fo|foo)\\B)" +-;-;-;- +-;-;-;- +"(?:^\\B(fo|foo)\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"" +regexps +"^\\B" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^\\B)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^\\B)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^\\B)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"^\\B" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^\\B)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^\\B)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^\\B)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"" +regexps +"^\\B\\B" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^\\B\\B)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^\\B\\B)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^\\B\\B)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"^\\B\\B" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^\\B\\B)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^\\B\\B)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^\\B\\B)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"" +regexps +"^\\B$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^\\B$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^\\B$)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^\\B$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"^\\B$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^\\B$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^\\B$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^\\B$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x" +regexps +"^\\B.$" +-;-;-;- +-;-;-;- +"^(?:^\\B.$)$" +-;-;-;- +-;-;-;- +"^(?:^\\B.$)" +-;-;-;- +-;-;-;- +"(?:^\\B.$)$" +-;-;-;- +-;-;-;- +strings +"" +"x" +regexps +"^\\B.\\B$" +-;-;-;- +-;-;-;- +"^(?:^\\B.\\B$)$" +-;-;-;- +-;-;-;- +"^(?:^\\B.\\B$)" +-;-;-;- +-;-;-;- +"(?:^\\B.\\B$)$" +-;-;-;- +-;-;-;- +strings +"" +"" +regexps +"^^^^^^^^\\B$$$$$$$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^^^^^^^^\\B$$$$$$$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^^^^^^^^\\B$$$$$$$)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^^^^^^^^\\B$$$$$$$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"^^^^^^^^\\B.$$$$$$" +-;-;-;- +-;-;-;- +"^(?:^^^^^^^^\\B.$$$$$$)$" +-;-;-;- +-;-;-;- +"^(?:^^^^^^^^\\B.$$$$$$)" +-;-;-;- +-;-;-;- +"(?:^^^^^^^^\\B.$$$$$$)$" +-;-;-;- +-;-;-;- +strings +"" +"x" +regexps +"^^^^^^^^\\B$$$$$$$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^^^^^^^^\\B$$$$$$$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^^^^^^^^\\B$$$$$$$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^^^^^^^^\\B$$$$$$$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x" +regexps +"\\bx\\b" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\bx\\b)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\bx\\b)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:\\bx\\b)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"x>" +regexps +"\\bx\\b" +-;-;-;- +-;0-1;-;0-1 +"^(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)" +-;-;-;- +-;0-1;-;0-1 +"(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"" +regexps +"\\bx\\b" +-;-;-;- +-;1-2;-;1-2 +"^(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)" +-;-;-;- +-;-;-;- +"(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"ax" +regexps +"\\bx\\b" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)" +-;-;-;- +-;-;-;- +"(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"xb" +regexps +"\\bx\\b" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)" +-;-;-;- +-;-;-;- +"(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"axb" +regexps +"\\bx\\b" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)" +-;-;-;- +-;-;-;- +"(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"«x" +regexps +"\\bx\\b" +-;-;-;- +-;2-3;-;2-3 +"^(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)" +-;-;-;- +-;-;-;- +"(?:\\bx\\b)$" +-;-;-;- +-;2-3;-;2-3 +strings +"" +"x»" +regexps +"\\bx\\b" +-;-;-;- +-;0-1;-;0-1 +"^(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)" +-;-;-;- +-;0-1;-;0-1 +"(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"«x»" +regexps +"\\bx\\b" +-;-;-;- +-;2-3;-;2-3 +"^(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)" +-;-;-;- +-;-;-;- +"(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"axb" +regexps +"\\bx\\b" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)" +-;-;-;- +-;-;-;- +"(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"áxβ" +regexps +"\\bx\\b" +-;-;-;- +-;2-3;-;2-3 +"^(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +"^(?:\\bx\\b)" +-;-;-;- +-;-;-;- +"(?:\\bx\\b)$" +-;-;-;- +-;-;-;- +strings +"" +"axb" +regexps +"\\Bx\\B" +-;-;-;- +-;1-2;-;1-2 +"^(?:\\Bx\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\Bx\\B)" +-;-;-;- +-;-;-;- +"(?:\\Bx\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"áxβ" +regexps +"\\Bx\\B" +-;-;-;- +-;-;-;- +"^(?:\\Bx\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\Bx\\B)" +-;-;-;- +-;-;-;- +"(?:\\Bx\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"" +regexps +"^$^$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^$^$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^$^$)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^$^$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"" +regexps +"^$^" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^$^)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:^$^)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:^$^)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"" +regexps +"$^$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:$^$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"^(?:$^$)" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +"(?:$^$)$" +0-0;0-0;0-0;0-0 +0-0;0-0;0-0;0-0 +strings +"" +"x" +regexps +"^$^$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x" +regexps +"^$^" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^$^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x" +regexps +"$^$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:$^$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x\ny" +regexps +"^$^$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x\ny" +regexps +"^$^" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^$^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x\ny" +regexps +"$^$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:$^$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x\n\ny" +regexps +"^$^$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x\n\ny" +regexps +"^$^" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^$^)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:^$^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"x\n\ny" +regexps +"$^$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:$^$)" +0-0;0-0;0-0;0-0 +-;-;-;- +"(?:$^$)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"foo$bar" +regexps +"^(foo\\$)$" +-;-;-;- +-;-;-;- +"^(?:^(foo\\$)$)$" +-;-;-;- +-;-;-;- +"^(?:^(foo\\$)$)" +-;-;-;- +-;-;-;- +"(?:^(foo\\$)$)$" +-;-;-;- +-;-;-;- +strings +"" +"foo$bar" +regexps +"(foo\\$)" +-;-;-;- +-;0-4 0-4;-;0-4 0-4 +"^(?:(foo\\$))$" +-;-;-;- +-;-;-;- +"^(?:(foo\\$))" +-;-;-;- +-;0-4 0-4;-;0-4 0-4 +"(?:(foo\\$))$" +-;-;-;- +-;-;-;- +strings +"" +"abc" +regexps +"^...$" +-;-;-;- +0-3;0-3;0-3;0-3 +"^(?:^...$)$" +-;-;-;- +0-3;0-3;0-3;0-3 +"^(?:^...$)" +-;-;-;- +0-3;0-3;0-3;0-3 +"(?:^...$)$" +-;-;-;- +0-3;0-3;0-3;0-3 +strings +"" +"本" +regexps +"^本$" +-;-;-;- +0-3;0-3;0-3;0-3 +"^(?:^本$)$" +-;-;-;- +0-3;0-3;0-3;0-3 +"^(?:^本$)" +-;-;-;- +0-3;0-3;0-3;0-3 +"(?:^本$)$" +-;-;-;- +0-3;0-3;0-3;0-3 +strings +"" +"日本語" +regexps +"^...$" +-;-;-;- +0-9;0-9;0-9;0-9 +"^(?:^...$)$" +-;-;-;- +0-9;0-9;0-9;0-9 +"^(?:^...$)" +-;-;-;- +0-9;0-9;0-9;0-9 +"(?:^...$)$" +-;-;-;- +0-9;0-9;0-9;0-9 +strings +"" +".本." +regexps +"^...$" +-;-;-;- +0-5;0-5;0-5;0-5 +"^(?:^...$)$" +-;-;-;- +0-5;0-5;0-5;0-5 +"^(?:^...$)" +-;-;-;- +0-5;0-5;0-5;0-5 +"(?:^...$)$" +-;-;-;- +0-5;0-5;0-5;0-5 +strings +"" +"本" +regexps +"^\\C\\C\\C$" +-;-;-;- +0-3;0-3;0-3;0-3 +"^(?:^\\C\\C\\C$)$" +-;-;-;- +0-3;0-3;0-3;0-3 +"^(?:^\\C\\C\\C$)" +-;-;-;- +0-3;0-3;0-3;0-3 +"(?:^\\C\\C\\C$)$" +-;-;-;- +0-3;0-3;0-3;0-3 +strings +"" +"本" +regexps +"^\\C$" +-;-;-;- +-;-;-;- +"^(?:^\\C$)$" +-;-;-;- +-;-;-;- +"^(?:^\\C$)" +-;-;-;- +-;-;-;- +"(?:^\\C$)$" +-;-;-;- +-;-;-;- +strings +"" +"日本語" +regexps +"^\\C\\C\\C$" +-;-;-;- +-;-;-;- +"^(?:^\\C\\C\\C$)$" +-;-;-;- +-;-;-;- +"^(?:^\\C\\C\\C$)" +-;-;-;- +-;-;-;- +"(?:^\\C\\C\\C$)$" +-;-;-;- +-;-;-;- +strings +"" +"日本語" +regexps +"^...$" +-;-;-;- +0-9;0-9;0-9;0-9 +"^(?:^...$)$" +-;-;-;- +0-9;0-9;0-9;0-9 +"^(?:^...$)" +-;-;-;- +0-9;0-9;0-9;0-9 +"(?:^...$)$" +-;-;-;- +0-9;0-9;0-9;0-9 +strings +"" +"日本語" +regexps +"^.........$" +-;-;-;- +-;-;-;- +"^(?:^.........$)$" +-;-;-;- +-;-;-;- +"^(?:^.........$)" +-;-;-;- +-;-;-;- +"(?:^.........$)$" +-;-;-;- +-;-;-;- +strings +"" +".本." +regexps +"^...$" +-;-;-;- +0-5;0-5;0-5;0-5 +"^(?:^...$)$" +-;-;-;- +0-5;0-5;0-5;0-5 +"^(?:^...$)" +-;-;-;- +0-5;0-5;0-5;0-5 +"(?:^...$)$" +-;-;-;- +0-5;0-5;0-5;0-5 +strings +"" +".本." +regexps +"^.....$" +-;-;-;- +-;-;-;- +"^(?:^.....$)$" +-;-;-;- +-;-;-;- +"^(?:^.....$)" +-;-;-;- +-;-;-;- +"(?:^.....$)$" +-;-;-;- +-;-;-;- +strings +"" +"xfooo" +regexps +"\\B(fo|foo)\\B" +-;-;-;- +-;1-3 1-3;-;1-4 1-4 +"^(?:\\B(fo|foo)\\B)$" +-;-;-;- +-;-;-;- +"^(?:\\B(fo|foo)\\B)" +-;-;-;- +-;-;-;- +"(?:\\B(fo|foo)\\B)$" +-;-;-;- +-;-;-;- +strings +"" +"foo" +regexps +"(fo|foo)" +-;-;-;- +0-3 0-3;0-2 0-2;0-3 0-3;0-3 0-3 +"^(?:(fo|foo))$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +"^(?:(fo|foo))" +-;-;-;- +0-3 0-3;0-2 0-2;0-3 0-3;0-3 0-3 +"(?:(fo|foo))$" +-;-;-;- +0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3 +strings +"" +"a" +regexps +"\\141" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\141)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\141)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:\\141)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"0" +regexps +"\\060" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\060)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\060)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:\\060)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"00" +regexps +"\\0600" +-;-;-;- +0-2;0-2;0-2;0-2 +"^(?:\\0600)$" +-;-;-;- +0-2;0-2;0-2;0-2 +"^(?:\\0600)" +-;-;-;- +0-2;0-2;0-2;0-2 +"(?:\\0600)$" +-;-;-;- +0-2;0-2;0-2;0-2 +strings +"" +"08" +regexps +"\\608" +-;-;-;- +0-2;0-2;0-2;0-2 +"^(?:\\608)$" +-;-;-;- +0-2;0-2;0-2;0-2 +"^(?:\\608)" +-;-;-;- +0-2;0-2;0-2;0-2 +"(?:\\608)$" +-;-;-;- +0-2;0-2;0-2;0-2 +strings +"" +"" +regexps +"\\01" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\01)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\01)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:\\01)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"8" +regexps +"\\018" +-;-;-;- +0-2;0-2;0-2;0-2 +"^(?:\\018)$" +-;-;-;- +0-2;0-2;0-2;0-2 +"^(?:\\018)" +-;-;-;- +0-2;0-2;0-2;0-2 +"(?:\\018)$" +-;-;-;- +0-2;0-2;0-2;0-2 +strings +"" +"a" +regexps +"\\x{61}" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\x{61})$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\x{61})" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:\\x{61})$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"a" +regexps +"\\x61" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\x61)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\x61)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:\\x61)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"a" +regexps +"\\x{00000061}" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\x{00000061})$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:\\x{00000061})" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:\\x{00000061})$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"aαβb" +regexps +"\\p{Greek}+" +-;-;-;- +-;1-5;-;1-5 +"^(?:\\p{Greek}+)$" +-;-;-;- +-;-;-;- +"^(?:\\p{Greek}+)" +-;-;-;- +-;-;-;- +"(?:\\p{Greek}+)$" +-;-;-;- +-;-;-;- +strings +"" +"aαβb" +regexps +"\\P{Greek}+" +-;-;-;- +-;0-1;-;0-1 +"^(?:\\P{Greek}+)$" +-;-;-;- +-;-;-;- +"^(?:\\P{Greek}+)" +-;-;-;- +-;0-1;-;0-1 +"(?:\\P{Greek}+)$" +-;-;-;- +-;5-6;-;5-6 +strings +"" +"aαβb" +regexps +"\\p{^Greek}+" +-;-;-;- +-;0-1;-;0-1 +"^(?:\\p{^Greek}+)$" +-;-;-;- +-;-;-;- +"^(?:\\p{^Greek}+)" +-;-;-;- +-;0-1;-;0-1 +"(?:\\p{^Greek}+)$" +-;-;-;- +-;5-6;-;5-6 +strings +"" +"aαβb" +regexps +"\\P{^Greek}+" +-;-;-;- +-;1-5;-;1-5 +"^(?:\\P{^Greek}+)$" +-;-;-;- +-;-;-;- +"^(?:\\P{^Greek}+)" +-;-;-;- +-;-;-;- +"(?:\\P{^Greek}+)$" +-;-;-;- +-;-;-;- +strings +"" +"abc123" +regexps +"[^0-9]+" +-;-;-;- +-;0-3;-;0-3 +"^(?:[^0-9]+)$" +-;-;-;- +-;-;-;- +"^(?:[^0-9]+)" +-;-;-;- +-;0-3;-;0-3 +"(?:[^0-9]+)$" +-;-;-;- +-;-;-;- +strings +"" +"abc123²³¼½¾₀₉" +regexps +"\\p{Nd}+" +-;-;-;- +-;3-6;-;3-6 +"^(?:\\p{Nd}+)$" +-;-;-;- +-;-;-;- +"^(?:\\p{Nd}+)" +-;-;-;- +-;-;-;- +"(?:\\p{Nd}+)$" +-;-;-;- +-;-;-;- +strings +"" +"abc123²³¼½¾₀₉" +regexps +"\\p{^Nd}+" +-;-;-;- +-;0-3;-;0-3 +"^(?:\\p{^Nd}+)$" +-;-;-;- +-;-;-;- +"^(?:\\p{^Nd}+)" +-;-;-;- +-;0-3;-;0-3 +"(?:\\p{^Nd}+)$" +-;-;-;- +-;6-22;-;6-22 +strings +"" +"abc123²³¼½¾₀₉" +regexps +"\\P{Nd}+" +-;-;-;- +-;0-3;-;0-3 +"^(?:\\P{Nd}+)$" +-;-;-;- +-;-;-;- +"^(?:\\P{Nd}+)" +-;-;-;- +-;0-3;-;0-3 +"(?:\\P{Nd}+)$" +-;-;-;- +-;6-22;-;6-22 +strings +"" +"abc123²³¼½¾₀₉" +regexps +"\\P{^Nd}+" +-;-;-;- +-;3-6;-;3-6 +"^(?:\\P{^Nd}+)$" +-;-;-;- +-;-;-;- +"^(?:\\P{^Nd}+)" +-;-;-;- +-;-;-;- +"(?:\\P{^Nd}+)$" +-;-;-;- +-;-;-;- +strings +"" +"abc123²³¼½¾₀₉" +regexps +"\\pN+" +-;-;-;- +-;3-22;-;3-22 +"^(?:\\pN+)$" +-;-;-;- +-;-;-;- +"^(?:\\pN+)" +-;-;-;- +-;-;-;- +"(?:\\pN+)$" +-;-;-;- +-;3-22;-;3-22 +strings +"" +"abc123²³¼½¾₀₉" +regexps +"\\p{N}+" +-;-;-;- +-;3-22;-;3-22 +"^(?:\\p{N}+)$" +-;-;-;- +-;-;-;- +"^(?:\\p{N}+)" +-;-;-;- +-;-;-;- +"(?:\\p{N}+)$" +-;-;-;- +-;3-22;-;3-22 +strings +"" +"abc123²³¼½¾₀₉" +regexps +"\\p{^N}+" +-;-;-;- +-;0-3;-;0-3 +"^(?:\\p{^N}+)$" +-;-;-;- +-;-;-;- +"^(?:\\p{^N}+)" +-;-;-;- +-;0-3;-;0-3 +"(?:\\p{^N}+)$" +-;-;-;- +-;-;-;- +strings +"" +"abc123" +regexps +"\\p{Any}+" +-;-;-;- +0-6;0-6;0-6;0-6 +"^(?:\\p{Any}+)$" +-;-;-;- +0-6;0-6;0-6;0-6 +"^(?:\\p{Any}+)" +-;-;-;- +0-6;0-6;0-6;0-6 +"(?:\\p{Any}+)$" +-;-;-;- +0-6;0-6;0-6;0-6 +strings +"" +"@AaB" +regexps +"(?i)[@-A]+" +-;-;-;- +-;0-3;-;0-3 +"^(?:(?i)[@-A]+)$" +-;-;-;- +-;-;-;- +"^(?:(?i)[@-A]+)" +-;-;-;- +-;0-3;-;0-3 +"(?:(?i)[@-A]+)$" +-;-;-;- +-;-;-;- +strings +"" +"aAzZ" +regexps +"(?i)[A-Z]+" +-;-;-;- +0-4;0-4;0-4;0-4 +"^(?:(?i)[A-Z]+)$" +-;-;-;- +0-4;0-4;0-4;0-4 +"^(?:(?i)[A-Z]+)" +-;-;-;- +0-4;0-4;0-4;0-4 +"(?:(?i)[A-Z]+)$" +-;-;-;- +0-4;0-4;0-4;0-4 +strings +"" +"Aa\\" +regexps +"(?i)[^\\\\]+" +-;-;-;- +-;0-2;-;0-2 +"^(?:(?i)[^\\\\]+)$" +-;-;-;- +-;-;-;- +"^(?:(?i)[^\\\\]+)" +-;-;-;- +-;0-2;-;0-2 +"(?:(?i)[^\\\\]+)$" +-;-;-;- +-;-;-;- +strings +"" +"acegikmoqsuwyACEGIKMOQSUWY" +regexps +"(?i)[acegikmoqsuwy]+" +-;-;-;- +0-26;0-26;0-26;0-26 +"^(?:(?i)[acegikmoqsuwy]+)$" +-;-;-;- +0-26;0-26;0-26;0-26 +"^(?:(?i)[acegikmoqsuwy]+)" +-;-;-;- +0-26;0-26;0-26;0-26 +"(?:(?i)[acegikmoqsuwy]+)$" +-;-;-;- +0-26;0-26;0-26;0-26 +strings +"" +"@AaB" +regexps +"[@-A]+" +-;-;-;- +-;0-2;-;0-2 +"^(?:[@-A]+)$" +-;-;-;- +-;-;-;- +"^(?:[@-A]+)" +-;-;-;- +-;0-2;-;0-2 +"(?:[@-A]+)$" +-;-;-;- +-;-;-;- +strings +"" +"aAzZ" +regexps +"[A-Z]+" +-;-;-;- +-;1-2;-;1-2 +"^(?:[A-Z]+)$" +-;-;-;- +-;-;-;- +"^(?:[A-Z]+)" +-;-;-;- +-;-;-;- +"(?:[A-Z]+)$" +-;-;-;- +-;3-4;-;3-4 +strings +"" +"Aa\\" +regexps +"[^\\\\]+" +-;-;-;- +-;0-2;-;0-2 +"^(?:[^\\\\]+)$" +-;-;-;- +-;-;-;- +"^(?:[^\\\\]+)" +-;-;-;- +-;0-2;-;0-2 +"(?:[^\\\\]+)$" +-;-;-;- +-;-;-;- +strings +"" +"acegikmoqsuwyACEGIKMOQSUWY" +regexps +"[acegikmoqsuwy]+" +-;-;-;- +-;0-13;-;0-13 +"^(?:[acegikmoqsuwy]+)$" +-;-;-;- +-;-;-;- +"^(?:[acegikmoqsuwy]+)" +-;-;-;- +-;0-13;-;0-13 +"(?:[acegikmoqsuwy]+)$" +-;-;-;- +-;-;-;- +strings +"" +"abcdef" +regexps +"^abc" +-;-;-;- +-;0-3;-;0-3 +"^(?:^abc)$" +-;-;-;- +-;-;-;- +"^(?:^abc)" +-;-;-;- +-;0-3;-;0-3 +"(?:^abc)$" +-;-;-;- +-;-;-;- +strings +"" +"aabcdef" +regexps +"^abc" +-;-;-;- +-;-;-;- +"^(?:^abc)$" +-;-;-;- +-;-;-;- +"^(?:^abc)" +-;-;-;- +-;-;-;- +"(?:^abc)$" +-;-;-;- +-;-;-;- +strings +"" +"abcdef" +regexps +"^[ay]*[bx]+c" +-;-;-;- +-;0-3;-;0-3 +"^(?:^[ay]*[bx]+c)$" +-;-;-;- +-;-;-;- +"^(?:^[ay]*[bx]+c)" +-;-;-;- +-;0-3;-;0-3 +"(?:^[ay]*[bx]+c)$" +-;-;-;- +-;-;-;- +strings +"" +"aabcdef" +regexps +"^[ay]*[bx]+c" +-;-;-;- +-;0-4;-;0-4 +"^(?:^[ay]*[bx]+c)$" +-;-;-;- +-;-;-;- +"^(?:^[ay]*[bx]+c)" +-;-;-;- +-;0-4;-;0-4 +"(?:^[ay]*[bx]+c)$" +-;-;-;- +-;-;-;- +strings +"" +"abcdef" +regexps +"def$" +-;-;-;- +-;3-6;-;3-6 +"^(?:def$)$" +-;-;-;- +-;-;-;- +"^(?:def$)" +-;-;-;- +-;-;-;- +"(?:def$)$" +-;-;-;- +-;3-6;-;3-6 +strings +"" +"abcdeff" +regexps +"def$" +-;-;-;- +-;-;-;- +"^(?:def$)$" +-;-;-;- +-;-;-;- +"^(?:def$)" +-;-;-;- +-;-;-;- +"(?:def$)$" +-;-;-;- +-;-;-;- +strings +"" +"abcdef" +regexps +"d[ex][fy]$" +-;-;-;- +-;3-6;-;3-6 +"^(?:d[ex][fy]$)$" +-;-;-;- +-;-;-;- +"^(?:d[ex][fy]$)" +-;-;-;- +-;-;-;- +"(?:d[ex][fy]$)$" +-;-;-;- +-;3-6;-;3-6 +strings +"" +"abcdeff" +regexps +"d[ex][fy]$" +-;-;-;- +-;-;-;- +"^(?:d[ex][fy]$)$" +-;-;-;- +-;-;-;- +"^(?:d[ex][fy]$)" +-;-;-;- +-;-;-;- +"(?:d[ex][fy]$)$" +-;-;-;- +-;-;-;- +strings +"" +"abcdef" +regexps +"[dz][ex][fy]$" +-;-;-;- +-;3-6;-;3-6 +"^(?:[dz][ex][fy]$)$" +-;-;-;- +-;-;-;- +"^(?:[dz][ex][fy]$)" +-;-;-;- +-;-;-;- +"(?:[dz][ex][fy]$)$" +-;-;-;- +-;3-6;-;3-6 +strings +"" +"abcdeff" +regexps +"[dz][ex][fy]$" +-;-;-;- +-;-;-;- +"^(?:[dz][ex][fy]$)$" +-;-;-;- +-;-;-;- +"^(?:[dz][ex][fy]$)" +-;-;-;- +-;-;-;- +"(?:[dz][ex][fy]$)$" +-;-;-;- +-;-;-;- +strings +"" +"abcdef" +regexps +"(?m)^abc" +-;-;-;- +-;0-3;-;0-3 +"^(?:(?m)^abc)$" +-;-;-;- +-;-;-;- +"^(?:(?m)^abc)" +-;-;-;- +-;0-3;-;0-3 +"(?:(?m)^abc)$" +-;-;-;- +-;-;-;- +strings +"" +"aabcdef" +regexps +"(?m)^abc" +-;-;-;- +-;-;-;- +"^(?:(?m)^abc)$" +-;-;-;- +-;-;-;- +"^(?:(?m)^abc)" +-;-;-;- +-;-;-;- +"(?:(?m)^abc)$" +-;-;-;- +-;-;-;- +strings +"" +"abcdef" +regexps +"(?m)^[ay]*[bx]+c" +-;-;-;- +-;0-3;-;0-3 +"^(?:(?m)^[ay]*[bx]+c)$" +-;-;-;- +-;-;-;- +"^(?:(?m)^[ay]*[bx]+c)" +-;-;-;- +-;0-3;-;0-3 +"(?:(?m)^[ay]*[bx]+c)$" +-;-;-;- +-;-;-;- +strings +"" +"aabcdef" +regexps +"(?m)^[ay]*[bx]+c" +-;-;-;- +-;0-4;-;0-4 +"^(?:(?m)^[ay]*[bx]+c)$" +-;-;-;- +-;-;-;- +"^(?:(?m)^[ay]*[bx]+c)" +-;-;-;- +-;0-4;-;0-4 +"(?:(?m)^[ay]*[bx]+c)$" +-;-;-;- +-;-;-;- +strings +"" +"abcdef" +regexps +"(?m)def$" +-;-;-;- +-;3-6;-;3-6 +"^(?:(?m)def$)$" +-;-;-;- +-;-;-;- +"^(?:(?m)def$)" +-;-;-;- +-;-;-;- +"(?:(?m)def$)$" +-;-;-;- +-;3-6;-;3-6 +strings +"" +"abcdeff" +regexps +"(?m)def$" +-;-;-;- +-;-;-;- +"^(?:(?m)def$)$" +-;-;-;- +-;-;-;- +"^(?:(?m)def$)" +-;-;-;- +-;-;-;- +"(?:(?m)def$)$" +-;-;-;- +-;-;-;- +strings +"" +"abcdef" +regexps +"(?m)d[ex][fy]$" +-;-;-;- +-;3-6;-;3-6 +"^(?:(?m)d[ex][fy]$)$" +-;-;-;- +-;-;-;- +"^(?:(?m)d[ex][fy]$)" +-;-;-;- +-;-;-;- +"(?:(?m)d[ex][fy]$)$" +-;-;-;- +-;3-6;-;3-6 +strings +"" +"abcdeff" +regexps +"(?m)d[ex][fy]$" +-;-;-;- +-;-;-;- +"^(?:(?m)d[ex][fy]$)$" +-;-;-;- +-;-;-;- +"^(?:(?m)d[ex][fy]$)" +-;-;-;- +-;-;-;- +"(?:(?m)d[ex][fy]$)$" +-;-;-;- +-;-;-;- +strings +"" +"abcdef" +regexps +"(?m)[dz][ex][fy]$" +-;-;-;- +-;3-6;-;3-6 +"^(?:(?m)[dz][ex][fy]$)$" +-;-;-;- +-;-;-;- +"^(?:(?m)[dz][ex][fy]$)" +-;-;-;- +-;-;-;- +"(?:(?m)[dz][ex][fy]$)$" +-;-;-;- +-;3-6;-;3-6 +strings +"" +"abcdeff" +regexps +"(?m)[dz][ex][fy]$" +-;-;-;- +-;-;-;- +"^(?:(?m)[dz][ex][fy]$)$" +-;-;-;- +-;-;-;- +"^(?:(?m)[dz][ex][fy]$)" +-;-;-;- +-;-;-;- +"(?:(?m)[dz][ex][fy]$)$" +-;-;-;- +-;-;-;- +strings +"" +"a" +regexps +"^" +0-0;0-0;0-0;0-0 +-;0-0;-;0-0 +"^(?:^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^)" +0-0;0-0;0-0;0-0 +-;0-0;-;0-0 +"(?:^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"a" +regexps +"^^" +0-0;0-0;0-0;0-0 +-;0-0;-;0-0 +"^(?:^^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +"^(?:^^)" +0-0;0-0;0-0;0-0 +-;0-0;-;0-0 +"(?:^^)$" +0-0;0-0;0-0;0-0 +-;-;-;- +strings +"" +"a" +regexps +"a" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:a)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"a" +regexps +"ab*" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:ab*)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:ab*)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:ab*)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"a" +regexps +"a\\C*" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a\\C*)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a\\C*)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:a\\C*)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"baba" +regexps +"a\\C*|ba\\C" +-;-;-;- +-;0-3;-;0-3 +"^(?:a\\C*|ba\\C)$" +-;-;-;- +-;-;-;- +"^(?:a\\C*|ba\\C)" +-;-;-;- +-;0-3;-;0-3 +"(?:a\\C*|ba\\C)$" +-;-;-;- +-;1-4;-;1-4 diff --git a/src/pkg/exp/regexp/testdata/repetition.dat b/src/pkg/exp/regexp/testdata/repetition.dat new file mode 100644 index 000000000..e6361f51a --- /dev/null +++ b/src/pkg/exp/regexp/testdata/repetition.dat @@ -0,0 +1,163 @@ +NOTE 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 diff --git a/src/pkg/exp/regexp/testdata/testregex.c b/src/pkg/exp/regexp/testdata/testregex.c new file mode 100644 index 000000000..37545d057 --- /dev/null +++ b/src/pkg/exp/regexp/testdata/testregex.c @@ -0,0 +1,2286 @@ +#pragma prototyped noticed + +/* + * regex(3) test harness + * + * build: cc -o testregex testregex.c + * help: testregex --man + * note: REG_* features are detected by #ifdef; if REG_* are enums + * then supply #define REG_foo REG_foo for each enum REG_foo + * + * Glenn Fowler + * 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; +} diff --git a/src/pkg/exp/ssh/Makefile b/src/pkg/exp/ssh/Makefile new file mode 100644 index 000000000..e8f33b708 --- /dev/null +++ b/src/pkg/exp/ssh/Makefile @@ -0,0 +1,16 @@ +# 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. + +include ../../../Make.inc + +TARG=exp/ssh +GOFILES=\ + common.go\ + messages.go\ + server.go\ + transport.go\ + channel.go\ + server_shell.go\ + +include ../../../Make.pkg diff --git a/src/pkg/exp/ssh/channel.go b/src/pkg/exp/ssh/channel.go new file mode 100644 index 000000000..922584f63 --- /dev/null +++ b/src/pkg/exp/ssh/channel.go @@ -0,0 +1,317 @@ +// 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 ssh + +import ( + "os" + "sync" +) + +// A Channel is an ordered, reliable, duplex stream that is multiplexed over an +// SSH connection. +type Channel interface { + // Accept accepts the channel creation request. + Accept() os.Error + // Reject rejects the channel creation request. After calling this, no + // other methods on the Channel may be called. If they are then the + // peer is likely to signal a protocol error and drop the connection. + Reject(reason RejectionReason, message string) os.Error + + // Read may return a ChannelRequest as an os.Error. + Read(data []byte) (int, os.Error) + Write(data []byte) (int, os.Error) + Close() os.Error + + // AckRequest either sends an ack or nack to the channel request. + AckRequest(ok bool) os.Error + + // ChannelType returns the type of the channel, as supplied by the + // client. + ChannelType() string + // ExtraData returns the arbitary payload for this channel, as supplied + // by the client. This data is specific to the channel type. + ExtraData() []byte +} + +// ChannelRequest represents a request sent on a channel, outside of the normal +// stream of bytes. It may result from calling Read on a Channel. +type ChannelRequest struct { + Request string + WantReply bool + Payload []byte +} + +func (c ChannelRequest) String() string { + return "channel request received" +} + +// RejectionReason is an enumeration used when rejecting channel creation +// requests. See RFC 4254, section 5.1. +type RejectionReason int + +const ( + Prohibited RejectionReason = iota + 1 + ConnectionFailed + UnknownChannelType + ResourceShortage +) + +type channel struct { + // immutable once created + chanType string + extraData []byte + + theyClosed bool + theySentEOF bool + weClosed bool + dead bool + + serverConn *ServerConnection + myId, theirId uint32 + myWindow, theirWindow uint32 + maxPacketSize uint32 + err os.Error + + pendingRequests []ChannelRequest + pendingData []byte + head, length int + + // This lock is inferior to serverConn.lock + lock sync.Mutex + cond *sync.Cond +} + +func (c *channel) Accept() os.Error { + c.serverConn.lock.Lock() + defer c.serverConn.lock.Unlock() + + if c.serverConn.err != nil { + return c.serverConn.err + } + + confirm := channelOpenConfirmMsg{ + PeersId: c.theirId, + MyId: c.myId, + MyWindow: c.myWindow, + MaxPacketSize: c.maxPacketSize, + } + return c.serverConn.writePacket(marshal(msgChannelOpenConfirm, confirm)) +} + +func (c *channel) Reject(reason RejectionReason, message string) os.Error { + c.serverConn.lock.Lock() + defer c.serverConn.lock.Unlock() + + if c.serverConn.err != nil { + return c.serverConn.err + } + + reject := channelOpenFailureMsg{ + PeersId: c.theirId, + Reason: uint32(reason), + Message: message, + Language: "en", + } + return c.serverConn.writePacket(marshal(msgChannelOpenFailure, reject)) +} + +func (c *channel) handlePacket(packet interface{}) { + c.lock.Lock() + defer c.lock.Unlock() + + switch packet := packet.(type) { + case *channelRequestMsg: + req := ChannelRequest{ + Request: packet.Request, + WantReply: packet.WantReply, + Payload: packet.RequestSpecificData, + } + + c.pendingRequests = append(c.pendingRequests, req) + c.cond.Signal() + case *channelCloseMsg: + c.theyClosed = true + c.cond.Signal() + case *channelEOFMsg: + c.theySentEOF = true + c.cond.Signal() + default: + panic("unknown packet type") + } +} + +func (c *channel) handleData(data []byte) { + c.lock.Lock() + defer c.lock.Unlock() + + // The other side should never send us more than our window. + if len(data)+c.length > len(c.pendingData) { + // TODO(agl): we should tear down the channel with a protocol + // error. + return + } + + c.myWindow -= uint32(len(data)) + for i := 0; i < 2; i++ { + tail := c.head + c.length + if tail > len(c.pendingData) { + tail -= len(c.pendingData) + } + n := copy(c.pendingData[tail:], data) + data = data[n:] + c.length += n + } + + c.cond.Signal() +} + +func (c *channel) Read(data []byte) (n int, err os.Error) { + c.lock.Lock() + defer c.lock.Unlock() + + if c.err != nil { + return 0, c.err + } + + if c.myWindow <= uint32(len(c.pendingData))/2 { + packet := marshal(msgChannelWindowAdjust, windowAdjustMsg{ + PeersId: c.theirId, + AdditionalBytes: uint32(len(c.pendingData)) - c.myWindow, + }) + if err := c.serverConn.writePacket(packet); err != nil { + return 0, err + } + } + + for { + if c.theySentEOF || c.theyClosed || c.dead { + return 0, os.EOF + } + + if len(c.pendingRequests) > 0 { + req := c.pendingRequests[0] + if len(c.pendingRequests) == 1 { + c.pendingRequests = nil + } else { + oldPendingRequests := c.pendingRequests + c.pendingRequests = make([]ChannelRequest, len(oldPendingRequests)-1) + copy(c.pendingRequests, oldPendingRequests[1:]) + } + + return 0, req + } + + if c.length > 0 { + tail := c.head + c.length + if tail > len(c.pendingData) { + tail -= len(c.pendingData) + } + n = copy(data, c.pendingData[c.head:tail]) + c.head += n + c.length -= n + if c.head == len(c.pendingData) { + c.head = 0 + } + return + } + + c.cond.Wait() + } + + panic("unreachable") +} + +func (c *channel) Write(data []byte) (n int, err os.Error) { + for len(data) > 0 { + c.lock.Lock() + if c.dead || c.weClosed { + return 0, os.EOF + } + + if c.theirWindow == 0 { + c.cond.Wait() + continue + } + c.lock.Unlock() + + todo := data + if uint32(len(todo)) > c.theirWindow { + todo = todo[:c.theirWindow] + } + + packet := make([]byte, 1+4+4+len(todo)) + packet[0] = msgChannelData + packet[1] = byte(c.theirId) >> 24 + packet[2] = byte(c.theirId) >> 16 + packet[3] = byte(c.theirId) >> 8 + packet[4] = byte(c.theirId) + packet[5] = byte(len(todo)) >> 24 + packet[6] = byte(len(todo)) >> 16 + packet[7] = byte(len(todo)) >> 8 + packet[8] = byte(len(todo)) + copy(packet[9:], todo) + + c.serverConn.lock.Lock() + if err = c.serverConn.writePacket(packet); err != nil { + c.serverConn.lock.Unlock() + return + } + c.serverConn.lock.Unlock() + + n += len(todo) + data = data[len(todo):] + } + + return +} + +func (c *channel) Close() os.Error { + c.serverConn.lock.Lock() + defer c.serverConn.lock.Unlock() + + if c.serverConn.err != nil { + return c.serverConn.err + } + + if c.weClosed { + return os.NewError("ssh: channel already closed") + } + c.weClosed = true + + closeMsg := channelCloseMsg{ + PeersId: c.theirId, + } + return c.serverConn.writePacket(marshal(msgChannelClose, closeMsg)) +} + +func (c *channel) AckRequest(ok bool) os.Error { + c.serverConn.lock.Lock() + defer c.serverConn.lock.Unlock() + + if c.serverConn.err != nil { + return c.serverConn.err + } + + if ok { + ack := channelRequestSuccessMsg{ + PeersId: c.theirId, + } + return c.serverConn.writePacket(marshal(msgChannelSuccess, ack)) + } else { + ack := channelRequestFailureMsg{ + PeersId: c.theirId, + } + return c.serverConn.writePacket(marshal(msgChannelFailure, ack)) + } + panic("unreachable") +} + +func (c *channel) ChannelType() string { + return c.chanType +} + +func (c *channel) ExtraData() []byte { + return c.extraData +} diff --git a/src/pkg/exp/ssh/common.go b/src/pkg/exp/ssh/common.go new file mode 100644 index 000000000..698db60b8 --- /dev/null +++ b/src/pkg/exp/ssh/common.go @@ -0,0 +1,96 @@ +// 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 ssh + +import ( + "strconv" +) + +// These are string constants in the SSH protocol. +const ( + kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" + hostAlgoRSA = "ssh-rsa" + cipherAES128CTR = "aes128-ctr" + macSHA196 = "hmac-sha1-96" + compressionNone = "none" + serviceUserAuth = "ssh-userauth" + serviceSSH = "ssh-connection" +) + +// UnexpectedMessageError results when the SSH message that we received didn't +// match what we wanted. +type UnexpectedMessageError struct { + expected, got uint8 +} + +func (u UnexpectedMessageError) String() string { + return "ssh: unexpected message type " + strconv.Itoa(int(u.got)) + " (expected " + strconv.Itoa(int(u.expected)) + ")" +} + +// ParseError results from a malformed SSH message. +type ParseError struct { + msgType uint8 +} + +func (p ParseError) String() string { + return "ssh: parse error in message type " + strconv.Itoa(int(p.msgType)) +} + +func findCommonAlgorithm(clientAlgos []string, serverAlgos []string) (commonAlgo string, ok bool) { + for _, clientAlgo := range clientAlgos { + for _, serverAlgo := range serverAlgos { + if clientAlgo == serverAlgo { + return clientAlgo, true + } + } + } + + return +} + +func findAgreedAlgorithms(clientToServer, serverToClient *transport, clientKexInit, serverKexInit *kexInitMsg) (kexAlgo, hostKeyAlgo string, ok bool) { + kexAlgo, ok = findCommonAlgorithm(clientKexInit.KexAlgos, serverKexInit.KexAlgos) + if !ok { + return + } + + hostKeyAlgo, ok = findCommonAlgorithm(clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) + if !ok { + return + } + + clientToServer.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) + if !ok { + return + } + + serverToClient.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) + if !ok { + return + } + + clientToServer.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) + if !ok { + return + } + + serverToClient.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) + if !ok { + return + } + + clientToServer.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) + if !ok { + return + } + + serverToClient.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) + if !ok { + return + } + + ok = true + return +} diff --git a/src/pkg/exp/ssh/doc.go b/src/pkg/exp/ssh/doc.go new file mode 100644 index 000000000..54a7ba9fd --- /dev/null +++ b/src/pkg/exp/ssh/doc.go @@ -0,0 +1,79 @@ +// 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 ssh implements an SSH server. + +SSH is a transport security protocol, an authentication protocol and a +family of application protocols. The most typical application level +protocol is a remote shell and this is specifically implemented. However, +the multiplexed nature of SSH is exposed to users that wish to support +others. + +An SSH server is represented by a Server, which manages a number of +ServerConnections and handles authentication. + + var s Server + s.PubKeyCallback = pubKeyAuth + s.PasswordCallback = passwordAuth + + pemBytes, err := ioutil.ReadFile("id_rsa") + if err != nil { + panic("Failed to load private key") + } + err = s.SetRSAPrivateKey(pemBytes) + if err != nil { + panic("Failed to parse private key") + } + +Once a Server has been set up, connections can be attached. + + var sConn ServerConnection + sConn.Server = &s + err = sConn.Handshake(conn) + if err != nil { + panic("failed to handshake") + } + +An SSH connection multiplexes several channels, which must be accepted themselves: + + + for { + channel, err := sConn.Accept() + if err != nil { + panic("error from Accept") + } + + ... + } + +Accept reads from the connection, demultiplexes packets to their corresponding +channels and returns when a new channel request is seen. Some goroutine must +always be calling Accept; otherwise no messages will be forwarded to the +channels. + +Channels have a type, depending on the application level protocol intended. In +the case of a shell, the type is "session" and ServerShell may be used to +present a simple terminal interface. + + if channel.ChannelType() != "session" { + c.Reject(UnknownChannelType, "unknown channel type") + return + } + channel.Accept() + + shell := NewServerShell(channel, "> ") + go func() { + defer channel.Close() + for { + line, err := shell.ReadLine() + if err != nil { + break + } + println(line) + } + return + }() +*/ +package ssh diff --git a/src/pkg/exp/ssh/messages.go b/src/pkg/exp/ssh/messages.go new file mode 100644 index 000000000..d375eafae --- /dev/null +++ b/src/pkg/exp/ssh/messages.go @@ -0,0 +1,557 @@ +// 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 ssh + +import ( + "big" + "bytes" + "io" + "os" + "reflect" +) + +// These are SSH message type numbers. They are scattered around several +// documents but many were taken from +// http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 +const ( + msgDisconnect = 1 + msgIgnore = 2 + msgUnimplemented = 3 + msgDebug = 4 + msgServiceRequest = 5 + msgServiceAccept = 6 + + msgKexInit = 20 + msgNewKeys = 21 + + msgKexDHInit = 30 + msgKexDHReply = 31 + + msgUserAuthRequest = 50 + msgUserAuthFailure = 51 + msgUserAuthSuccess = 52 + msgUserAuthBanner = 53 + msgUserAuthPubKeyOk = 60 + + msgGlobalRequest = 80 + msgRequestSuccess = 81 + msgRequestFailure = 82 + + msgChannelOpen = 90 + msgChannelOpenConfirm = 91 + msgChannelOpenFailure = 92 + msgChannelWindowAdjust = 93 + msgChannelData = 94 + msgChannelExtendedData = 95 + msgChannelEOF = 96 + msgChannelClose = 97 + msgChannelRequest = 98 + msgChannelSuccess = 99 + msgChannelFailure = 100 +) + +// SSH messages: +// +// These structures mirror the wire format of the corresponding SSH messages. +// They are marshaled using reflection with the marshal and unmarshal functions +// in this file. The only wrinkle is that a final member of type []byte with a +// tag of "rest" receives the remainder of a packet when unmarshaling. + +// See RFC 4253, section 7.1. +type kexInitMsg struct { + Cookie [16]byte + KexAlgos []string + ServerHostKeyAlgos []string + CiphersClientServer []string + CiphersServerClient []string + MACsClientServer []string + MACsServerClient []string + CompressionClientServer []string + CompressionServerClient []string + LanguagesClientServer []string + LanguagesServerClient []string + FirstKexFollows bool + Reserved uint32 +} + +// See RFC 4253, section 8. +type kexDHInitMsg struct { + X *big.Int +} + +type kexDHReplyMsg struct { + HostKey []byte + Y *big.Int + Signature []byte +} + +// See RFC 4253, section 10. +type serviceRequestMsg struct { + Service string +} + +// See RFC 4253, section 10. +type serviceAcceptMsg struct { + Service string +} + +// See RFC 4252, section 5. +type userAuthRequestMsg struct { + User string + Service string + Method string + Payload []byte "rest" +} + +// See RFC 4252, section 5.1 +type userAuthFailureMsg struct { + Methods []string + PartialSuccess bool +} + +// See RFC 4254, section 5.1. +type channelOpenMsg struct { + ChanType string + PeersId uint32 + PeersWindow uint32 + MaxPacketSize uint32 + TypeSpecificData []byte "rest" +} + +// See RFC 4254, section 5.1. +type channelOpenConfirmMsg struct { + PeersId uint32 + MyId uint32 + MyWindow uint32 + MaxPacketSize uint32 + TypeSpecificData []byte "rest" +} + +// See RFC 4254, section 5.1. +type channelOpenFailureMsg struct { + PeersId uint32 + Reason uint32 + Message string + Language string +} + +type channelRequestMsg struct { + PeersId uint32 + Request string + WantReply bool + RequestSpecificData []byte "rest" +} + +// See RFC 4254, section 5.4. +type channelRequestSuccessMsg struct { + PeersId uint32 +} + +// See RFC 4254, section 5.4. +type channelRequestFailureMsg struct { + PeersId uint32 +} + +// See RFC 4254, section 5.3 +type channelCloseMsg struct { + PeersId uint32 +} + +// See RFC 4254, section 5.3 +type channelEOFMsg struct { + PeersId uint32 +} + +// See RFC 4254, section 4 +type globalRequestMsg struct { + Type string + WantReply bool +} + +// See RFC 4254, section 5.2 +type windowAdjustMsg struct { + PeersId uint32 + AdditionalBytes uint32 +} + +// See RFC 4252, section 7 +type userAuthPubKeyOkMsg struct { + Algo string + PubKey string +} + +// unmarshal parses the SSH wire data in packet into out using reflection. +// expectedType is the expected SSH message type. It either returns nil on +// success, or a ParseError or UnexpectedMessageError on error. +func unmarshal(out interface{}, packet []byte, expectedType uint8) os.Error { + if len(packet) == 0 { + return ParseError{expectedType} + } + if packet[0] != expectedType { + return UnexpectedMessageError{expectedType, packet[0]} + } + packet = packet[1:] + + v := reflect.ValueOf(out).Elem() + structType := v.Type() + var ok bool + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + t := field.Type() + switch t.Kind() { + case reflect.Bool: + if len(packet) < 1 { + return ParseError{expectedType} + } + field.SetBool(packet[0] != 0) + packet = packet[1:] + case reflect.Array: + if t.Elem().Kind() != reflect.Uint8 { + panic("array of non-uint8") + } + if len(packet) < t.Len() { + return ParseError{expectedType} + } + for j := 0; j < t.Len(); j++ { + field.Index(j).Set(reflect.ValueOf(packet[j])) + } + packet = packet[t.Len():] + case reflect.Uint32: + var u32 uint32 + if u32, packet, ok = parseUint32(packet); !ok { + return ParseError{expectedType} + } + field.SetUint(uint64(u32)) + case reflect.String: + var s []byte + if s, packet, ok = parseString(packet); !ok { + return ParseError{expectedType} + } + field.SetString(string(s)) + case reflect.Slice: + switch t.Elem().Kind() { + case reflect.Uint8: + if structType.Field(i).Tag == "rest" { + field.Set(reflect.ValueOf(packet)) + packet = nil + } else { + var s []byte + if s, packet, ok = parseString(packet); !ok { + return ParseError{expectedType} + } + field.Set(reflect.ValueOf(s)) + } + case reflect.String: + var nl []string + if nl, packet, ok = parseNameList(packet); !ok { + return ParseError{expectedType} + } + field.Set(reflect.ValueOf(nl)) + default: + panic("slice of unknown type") + } + case reflect.Ptr: + if t == bigIntType { + var n *big.Int + if n, packet, ok = parseInt(packet); !ok { + return ParseError{expectedType} + } + field.Set(reflect.ValueOf(n)) + } else { + panic("pointer to unknown type") + } + default: + panic("unknown type") + } + } + + if len(packet) != 0 { + return ParseError{expectedType} + } + + return nil +} + +// marshal serializes the message in msg, using the given message type. +func marshal(msgType uint8, msg interface{}) []byte { + var out []byte + out = append(out, msgType) + + v := reflect.ValueOf(msg) + structType := v.Type() + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + t := field.Type() + switch t.Kind() { + case reflect.Bool: + var v uint8 + if field.Bool() { + v = 1 + } + out = append(out, v) + case reflect.Array: + if t.Elem().Kind() != reflect.Uint8 { + panic("array of non-uint8") + } + for j := 0; j < t.Len(); j++ { + out = append(out, byte(field.Index(j).Uint())) + } + case reflect.Uint32: + u32 := uint32(field.Uint()) + out = append(out, byte(u32>>24)) + out = append(out, byte(u32>>16)) + out = append(out, byte(u32>>8)) + out = append(out, byte(u32)) + case reflect.String: + s := field.String() + out = append(out, byte(len(s)>>24)) + out = append(out, byte(len(s)>>16)) + out = append(out, byte(len(s)>>8)) + out = append(out, byte(len(s))) + out = append(out, []byte(s)...) + case reflect.Slice: + switch t.Elem().Kind() { + case reflect.Uint8: + length := field.Len() + if structType.Field(i).Tag != "rest" { + out = append(out, byte(length>>24)) + out = append(out, byte(length>>16)) + out = append(out, byte(length>>8)) + out = append(out, byte(length)) + } + for j := 0; j < length; j++ { + out = append(out, byte(field.Index(j).Uint())) + } + case reflect.String: + var length int + for j := 0; j < field.Len(); j++ { + if j != 0 { + length++ /* comma */ + } + length += len(field.Index(j).String()) + } + + out = append(out, byte(length>>24)) + out = append(out, byte(length>>16)) + out = append(out, byte(length>>8)) + out = append(out, byte(length)) + for j := 0; j < field.Len(); j++ { + if j != 0 { + out = append(out, ',') + } + out = append(out, []byte(field.Index(j).String())...) + } + default: + panic("slice of unknown type") + } + case reflect.Ptr: + if t == bigIntType { + var n *big.Int + nValue := reflect.ValueOf(&n) + nValue.Elem().Set(field) + needed := intLength(n) + oldLength := len(out) + + if cap(out)-len(out) < needed { + newOut := make([]byte, len(out), 2*(len(out)+needed)) + copy(newOut, out) + out = newOut + } + out = out[:oldLength+needed] + marshalInt(out[oldLength:], n) + } else { + panic("pointer to unknown type") + } + } + } + + return out +} + +var bigOne = big.NewInt(1) + +func parseString(in []byte) (out, rest []byte, ok bool) { + if len(in) < 4 { + return + } + length := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3]) + if uint32(len(in)) < 4+length { + return + } + out = in[4 : 4+length] + rest = in[4+length:] + ok = true + return +} + +var comma = []byte{','} + +func parseNameList(in []byte) (out []string, rest []byte, ok bool) { + contents, rest, ok := parseString(in) + if !ok { + return + } + if len(contents) == 0 { + return + } + parts := bytes.Split(contents, comma) + out = make([]string, len(parts)) + for i, part := range parts { + out[i] = string(part) + } + return +} + +func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) { + contents, rest, ok := parseString(in) + if !ok { + return + } + out = new(big.Int) + + if len(contents) > 0 && contents[0]&0x80 == 0x80 { + // This is a negative number + notBytes := make([]byte, len(contents)) + for i := range notBytes { + notBytes[i] = ^contents[i] + } + out.SetBytes(notBytes) + out.Add(out, bigOne) + out.Neg(out) + } else { + // Positive number + out.SetBytes(contents) + } + ok = true + return +} + +func parseUint32(in []byte) (out uint32, rest []byte, ok bool) { + if len(in) < 4 { + return + } + out = uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3]) + rest = in[4:] + ok = true + return +} + +const maxPacketSize = 36000 + +func nameListLength(namelist []string) int { + length := 4 /* uint32 length prefix */ + for i, name := range namelist { + if i != 0 { + length++ /* comma */ + } + length += len(name) + } + return length +} + +func intLength(n *big.Int) int { + length := 4 /* length bytes */ + if n.Sign() < 0 { + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bitLen := nMinus1.BitLen() + if bitLen%8 == 0 { + // The number will need 0xff padding + length++ + } + length += (bitLen + 7) / 8 + } else if n.Sign() == 0 { + // A zero is the zero length string + } else { + bitLen := n.BitLen() + if bitLen%8 == 0 { + // The number will need 0x00 padding + length++ + } + length += (bitLen + 7) / 8 + } + + return length +} + +func marshalInt(to []byte, n *big.Int) []byte { + lengthBytes := to + to = to[4:] + length := 0 + + if n.Sign() < 0 { + // A negative number has to be converted to two's-complement + // form. So we'll subtract 1 and invert. If the + // most-significant-bit isn't set then we'll need to pad the + // beginning with 0xff in order to keep the number negative. + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bytes := nMinus1.Bytes() + for i := range bytes { + bytes[i] ^= 0xff + } + if len(bytes) == 0 || bytes[0]&0x80 == 0 { + to[0] = 0xff + to = to[1:] + length++ + } + nBytes := copy(to, bytes) + to = to[nBytes:] + length += nBytes + } else if n.Sign() == 0 { + // A zero is the zero length string + } else { + bytes := n.Bytes() + if len(bytes) > 0 && bytes[0]&0x80 != 0 { + // We'll have to pad this with a 0x00 in order to + // stop it looking like a negative number. + to[0] = 0 + to = to[1:] + length++ + } + nBytes := copy(to, bytes) + to = to[nBytes:] + length += nBytes + } + + lengthBytes[0] = byte(length >> 24) + lengthBytes[1] = byte(length >> 16) + lengthBytes[2] = byte(length >> 8) + lengthBytes[3] = byte(length) + return to +} + +func writeInt(w io.Writer, n *big.Int) { + length := intLength(n) + buf := make([]byte, length) + marshalInt(buf, n) + w.Write(buf) +} + +func writeString(w io.Writer, s []byte) { + var lengthBytes [4]byte + lengthBytes[0] = byte(len(s) >> 24) + lengthBytes[1] = byte(len(s) >> 16) + lengthBytes[2] = byte(len(s) >> 8) + lengthBytes[3] = byte(len(s)) + w.Write(lengthBytes[:]) + w.Write(s) +} + +func stringLength(s []byte) int { + return 4 + len(s) +} + +func marshalString(to []byte, s []byte) []byte { + to[0] = byte(len(s) >> 24) + to[1] = byte(len(s) >> 16) + to[2] = byte(len(s) >> 8) + to[3] = byte(len(s)) + to = to[4:] + copy(to, s) + return to[len(s):] +} + +var bigIntType = reflect.TypeOf((*big.Int)(nil)) diff --git a/src/pkg/exp/ssh/messages_test.go b/src/pkg/exp/ssh/messages_test.go new file mode 100644 index 000000000..629f3d3b1 --- /dev/null +++ b/src/pkg/exp/ssh/messages_test.go @@ -0,0 +1,125 @@ +// 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 ssh + +import ( + "big" + "rand" + "reflect" + "testing" + "testing/quick" +) + +var intLengthTests = []struct { + val, length int +}{ + {0, 4 + 0}, + {1, 4 + 1}, + {127, 4 + 1}, + {128, 4 + 2}, + {-1, 4 + 1}, +} + +func TestIntLength(t *testing.T) { + for _, test := range intLengthTests { + v := new(big.Int).SetInt64(int64(test.val)) + length := intLength(v) + if length != test.length { + t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length) + } + } +} + +var messageTypes = []interface{}{ + &kexInitMsg{}, + &kexDHInitMsg{}, + &serviceRequestMsg{}, + &serviceAcceptMsg{}, + &userAuthRequestMsg{}, + &channelOpenMsg{}, + &channelOpenConfirmMsg{}, + &channelRequestMsg{}, + &channelRequestSuccessMsg{}, +} + +func TestMarshalUnmarshal(t *testing.T) { + rand := rand.New(rand.NewSource(0)) + for i, iface := range messageTypes { + ty := reflect.ValueOf(iface).Type() + + n := 100 + if testing.Short() { + n = 5 + } + for j := 0; j < n; j++ { + v, ok := quick.Value(ty, rand) + if !ok { + t.Errorf("#%d: failed to create value", i) + break + } + + m1 := v.Elem().Interface() + m2 := iface + + marshaled := marshal(msgIgnore, m1) + if err := unmarshal(m2, marshaled, msgIgnore); err != nil { + t.Errorf("#%d failed to unmarshal %#v: %s", i, m1, err) + break + } + + if !reflect.DeepEqual(v.Interface(), m2) { + t.Errorf("#%d\ngot: %#v\nwant:%#v\n%x", i, m2, m1, marshaled) + break + } + } + } +} + +func randomBytes(out []byte, rand *rand.Rand) { + for i := 0; i < len(out); i++ { + out[i] = byte(rand.Int31()) + } +} + +func randomNameList(rand *rand.Rand) []string { + ret := make([]string, rand.Int31()&15) + for i := range ret { + s := make([]byte, 1+(rand.Int31()&15)) + for j := range s { + s[j] = 'a' + uint8(rand.Int31()&15) + } + ret[i] = string(s) + } + return ret +} + +func randomInt(rand *rand.Rand) *big.Int { + return new(big.Int).SetInt64(int64(int32(rand.Uint32()))) +} + +func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { + ki := &kexInitMsg{} + randomBytes(ki.Cookie[:], rand) + ki.KexAlgos = randomNameList(rand) + ki.ServerHostKeyAlgos = randomNameList(rand) + ki.CiphersClientServer = randomNameList(rand) + ki.CiphersServerClient = randomNameList(rand) + ki.MACsClientServer = randomNameList(rand) + ki.MACsServerClient = randomNameList(rand) + ki.CompressionClientServer = randomNameList(rand) + ki.CompressionServerClient = randomNameList(rand) + ki.LanguagesClientServer = randomNameList(rand) + ki.LanguagesServerClient = randomNameList(rand) + if rand.Int31()&1 == 1 { + ki.FirstKexFollows = true + } + return reflect.ValueOf(ki) +} + +func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { + dhi := &kexDHInitMsg{} + dhi.X = randomInt(rand) + return reflect.ValueOf(dhi) +} diff --git a/src/pkg/exp/ssh/server.go b/src/pkg/exp/ssh/server.go new file mode 100644 index 000000000..bc0af13e8 --- /dev/null +++ b/src/pkg/exp/ssh/server.go @@ -0,0 +1,714 @@ +// 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 ssh + +import ( + "big" + "bufio" + "bytes" + "crypto" + "crypto/rand" + "crypto/rsa" + _ "crypto/sha1" + "crypto/x509" + "encoding/pem" + "net" + "os" + "sync" +) + +var supportedKexAlgos = []string{kexAlgoDH14SHA1} +var supportedHostKeyAlgos = []string{hostAlgoRSA} +var supportedCiphers = []string{cipherAES128CTR} +var supportedMACs = []string{macSHA196} +var supportedCompressions = []string{compressionNone} + +// Server represents an SSH server. A Server may have several ServerConnections. +type Server struct { + rsa *rsa.PrivateKey + rsaSerialized []byte + + // NoClientAuth is true if clients are allowed to connect without + // authenticating. + NoClientAuth bool + + // PasswordCallback, if non-nil, is called when a user attempts to + // authenticate using a password. It may be called concurrently from + // several goroutines. + PasswordCallback func(user, password string) bool + + // PubKeyCallback, if non-nil, is called when a client attempts public + // key authentication. It must return true iff the given public key is + // valid for the given user. + PubKeyCallback func(user, algo string, pubkey []byte) bool +} + +// SetRSAPrivateKey sets the private key for a Server. A Server must have a +// private key configured in order to accept connections. The private key must +// be in the form of a PEM encoded, PKCS#1, RSA private key. The file "id_rsa" +// typically contains such a key. +func (s *Server) SetRSAPrivateKey(pemBytes []byte) os.Error { + block, _ := pem.Decode(pemBytes) + if block == nil { + return os.NewError("ssh: no key found") + } + var err os.Error + s.rsa, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + return err + } + + s.rsaSerialized = marshalRSA(s.rsa) + return nil +} + +// marshalRSA serializes an RSA private key according to RFC 4256, section 6.6. +func marshalRSA(priv *rsa.PrivateKey) []byte { + e := new(big.Int).SetInt64(int64(priv.E)) + length := stringLength([]byte(hostAlgoRSA)) + length += intLength(e) + length += intLength(priv.N) + + ret := make([]byte, length) + r := marshalString(ret, []byte(hostAlgoRSA)) + r = marshalInt(r, e) + r = marshalInt(r, priv.N) + + return ret +} + +// parseRSA parses an RSA key according to RFC 4256, section 6.6. +func parseRSA(in []byte) (pubKey *rsa.PublicKey, ok bool) { + algo, in, ok := parseString(in) + if !ok || string(algo) != hostAlgoRSA { + return nil, false + } + bigE, in, ok := parseInt(in) + if !ok || bigE.BitLen() > 24 { + return nil, false + } + e := bigE.Int64() + if e < 3 || e&1 == 0 { + return nil, false + } + N, in, ok := parseInt(in) + if !ok || len(in) > 0 { + return nil, false + } + return &rsa.PublicKey{ + N: N, + E: int(e), + }, true +} + +func parseRSASig(in []byte) (sig []byte, ok bool) { + algo, in, ok := parseString(in) + if !ok || string(algo) != hostAlgoRSA { + return nil, false + } + sig, in, ok = parseString(in) + if len(in) > 0 { + ok = false + } + return +} + +// cachedPubKey contains the results of querying whether a public key is +// acceptable for a user. The cache only applies to a single ServerConnection. +type cachedPubKey struct { + user, algo string + pubKey []byte + result bool +} + +const maxCachedPubKeys = 16 + +// ServerConnection represents an incomming connection to a Server. +type ServerConnection struct { + Server *Server + + *transport + + channels map[uint32]*channel + nextChanId uint32 + + // lock protects err and also allows Channels to serialise their writes + // to out. + lock sync.RWMutex + err os.Error + + // cachedPubKeys contains the cache results of tests for public keys. + // Since SSH clients will query whether a public key is acceptable + // before attempting to authenticate with it, we end up with duplicate + // queries for public key validity. + cachedPubKeys []cachedPubKey +} + +// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. +type dhGroup struct { + g, p *big.Int +} + +// dhGroup14 is the group called diffie-hellman-group14-sha1 in RFC 4253 and +// Oakley Group 14 in RFC 3526. +var dhGroup14 *dhGroup + +var dhGroup14Once sync.Once + +func initDHGroup14() { + p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) + + dhGroup14 = &dhGroup{ + g: new(big.Int).SetInt64(2), + p: p, + } +} + +type handshakeMagics struct { + clientVersion, serverVersion []byte + clientKexInit, serverKexInit []byte +} + +// kexDH performs Diffie-Hellman key agreement on a ServerConnection. The +// returned values are given the same names as in RFC 4253, section 8. +func (s *ServerConnection) kexDH(group *dhGroup, hashFunc crypto.Hash, magics *handshakeMagics, hostKeyAlgo string) (H, K []byte, err os.Error) { + packet, err := s.readPacket() + if err != nil { + return + } + var kexDHInit kexDHInitMsg + if err = unmarshal(&kexDHInit, packet, msgKexDHInit); err != nil { + return + } + + if kexDHInit.X.Sign() == 0 || kexDHInit.X.Cmp(group.p) >= 0 { + return nil, nil, os.NewError("client DH parameter out of bounds") + } + + y, err := rand.Int(rand.Reader, group.p) + if err != nil { + return + } + + Y := new(big.Int).Exp(group.g, y, group.p) + kInt := new(big.Int).Exp(kexDHInit.X, y, group.p) + + var serializedHostKey []byte + switch hostKeyAlgo { + case hostAlgoRSA: + serializedHostKey = s.Server.rsaSerialized + default: + return nil, nil, os.NewError("internal error") + } + + h := hashFunc.New() + writeString(h, magics.clientVersion) + writeString(h, magics.serverVersion) + writeString(h, magics.clientKexInit) + writeString(h, magics.serverKexInit) + writeString(h, serializedHostKey) + writeInt(h, kexDHInit.X) + writeInt(h, Y) + K = make([]byte, intLength(kInt)) + marshalInt(K, kInt) + h.Write(K) + + H = h.Sum() + + h.Reset() + h.Write(H) + hh := h.Sum() + + var sig []byte + switch hostKeyAlgo { + case hostAlgoRSA: + sig, err = rsa.SignPKCS1v15(rand.Reader, s.Server.rsa, hashFunc, hh) + if err != nil { + return + } + default: + return nil, nil, os.NewError("internal error") + } + + serializedSig := serializeRSASignature(sig) + + kexDHReply := kexDHReplyMsg{ + HostKey: serializedHostKey, + Y: Y, + Signature: serializedSig, + } + packet = marshal(msgKexDHReply, kexDHReply) + + err = s.writePacket(packet) + return +} + +func serializeRSASignature(sig []byte) []byte { + length := stringLength([]byte(hostAlgoRSA)) + length += stringLength(sig) + + ret := make([]byte, length) + r := marshalString(ret, []byte(hostAlgoRSA)) + r = marshalString(r, sig) + + return ret +} + +// serverVersion is the fixed identification string that Server will use. +var serverVersion = []byte("SSH-2.0-Go\r\n") + +// buildDataSignedForAuth returns the data that is signed in order to prove +// posession of a private key. See RFC 4252, section 7. +func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte { + user := []byte(req.User) + service := []byte(req.Service) + method := []byte(req.Method) + + length := stringLength(sessionId) + length += 1 + length += stringLength(user) + length += stringLength(service) + length += stringLength(method) + length += 1 + length += stringLength(algo) + length += stringLength(pubKey) + + ret := make([]byte, length) + r := marshalString(ret, sessionId) + r[0] = msgUserAuthRequest + r = r[1:] + r = marshalString(r, user) + r = marshalString(r, service) + r = marshalString(r, method) + r[0] = 1 + r = r[1:] + r = marshalString(r, algo) + r = marshalString(r, pubKey) + return ret +} + +// Handshake performs an SSH transport and client authentication on the given ServerConnection. +func (s *ServerConnection) Handshake(conn net.Conn) os.Error { + var magics handshakeMagics + s.transport = &transport{ + reader: reader{ + Reader: bufio.NewReader(conn), + }, + writer: writer{ + Writer: bufio.NewWriter(conn), + rand: rand.Reader, + }, + Close: func() os.Error { + return conn.Close() + }, + } + + if _, err := conn.Write(serverVersion); err != nil { + return err + } + magics.serverVersion = serverVersion[:len(serverVersion)-2] + + version, ok := readVersion(s.transport) + if !ok { + return os.NewError("failed to read version string from client") + } + magics.clientVersion = version + + serverKexInit := kexInitMsg{ + KexAlgos: supportedKexAlgos, + ServerHostKeyAlgos: supportedHostKeyAlgos, + CiphersClientServer: supportedCiphers, + CiphersServerClient: supportedCiphers, + MACsClientServer: supportedMACs, + MACsServerClient: supportedMACs, + CompressionClientServer: supportedCompressions, + CompressionServerClient: supportedCompressions, + } + kexInitPacket := marshal(msgKexInit, serverKexInit) + magics.serverKexInit = kexInitPacket + + if err := s.writePacket(kexInitPacket); err != nil { + return err + } + + packet, err := s.readPacket() + if err != nil { + return err + } + + magics.clientKexInit = packet + + var clientKexInit kexInitMsg + if err = unmarshal(&clientKexInit, packet, msgKexInit); err != nil { + return err + } + + kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(s.transport, s.transport, &clientKexInit, &serverKexInit) + if !ok { + return os.NewError("ssh: no common algorithms") + } + + if clientKexInit.FirstKexFollows && kexAlgo != clientKexInit.KexAlgos[0] { + // The client sent a Kex message for the wrong algorithm, + // which we have to ignore. + _, err := s.readPacket() + if err != nil { + return err + } + } + + var H, K []byte + var hashFunc crypto.Hash + switch kexAlgo { + case kexAlgoDH14SHA1: + hashFunc = crypto.SHA1 + dhGroup14Once.Do(initDHGroup14) + H, K, err = s.kexDH(dhGroup14, hashFunc, &magics, hostKeyAlgo) + default: + err = os.NewError("ssh: internal error") + } + + if err != nil { + return err + } + + packet = []byte{msgNewKeys} + if err = s.writePacket(packet); err != nil { + return err + } + if err = s.transport.writer.setupKeys(serverKeys, K, H, H, hashFunc); err != nil { + return err + } + + if packet, err = s.readPacket(); err != nil { + return err + } + if packet[0] != msgNewKeys { + return UnexpectedMessageError{msgNewKeys, packet[0]} + } + + s.transport.reader.setupKeys(clientKeys, K, H, H, hashFunc) + + packet, err = s.readPacket() + if err != nil { + return err + } + + var serviceRequest serviceRequestMsg + if err = unmarshal(&serviceRequest, packet, msgServiceRequest); err != nil { + return err + } + if serviceRequest.Service != serviceUserAuth { + return os.NewError("ssh: requested service '" + serviceRequest.Service + "' before authenticating") + } + + serviceAccept := serviceAcceptMsg{ + Service: serviceUserAuth, + } + packet = marshal(msgServiceAccept, serviceAccept) + if err = s.writePacket(packet); err != nil { + return err + } + + if err = s.authenticate(H); err != nil { + return err + } + + s.channels = make(map[uint32]*channel) + return nil +} + +func isAcceptableAlgo(algo string) bool { + return algo == hostAlgoRSA +} + +// testPubKey returns true if the given public key is acceptable for the user. +func (s *ServerConnection) testPubKey(user, algo string, pubKey []byte) bool { + if s.Server.PubKeyCallback == nil || !isAcceptableAlgo(algo) { + return false + } + + for _, c := range s.cachedPubKeys { + if c.user == user && c.algo == algo && bytes.Equal(c.pubKey, pubKey) { + return c.result + } + } + + result := s.Server.PubKeyCallback(user, algo, pubKey) + if len(s.cachedPubKeys) < maxCachedPubKeys { + c := cachedPubKey{ + user: user, + algo: algo, + pubKey: make([]byte, len(pubKey)), + result: result, + } + copy(c.pubKey, pubKey) + s.cachedPubKeys = append(s.cachedPubKeys, c) + } + + return result +} + +func (s *ServerConnection) authenticate(H []byte) os.Error { + var userAuthReq userAuthRequestMsg + var err os.Error + var packet []byte + +userAuthLoop: + for { + if packet, err = s.readPacket(); err != nil { + return err + } + if err = unmarshal(&userAuthReq, packet, msgUserAuthRequest); err != nil { + return err + } + + if userAuthReq.Service != serviceSSH { + return os.NewError("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service) + } + + switch userAuthReq.Method { + case "none": + if s.Server.NoClientAuth { + break userAuthLoop + } + case "password": + if s.Server.PasswordCallback == nil { + break + } + payload := userAuthReq.Payload + if len(payload) < 1 || payload[0] != 0 { + return ParseError{msgUserAuthRequest} + } + payload = payload[1:] + password, payload, ok := parseString(payload) + if !ok || len(payload) > 0 { + return ParseError{msgUserAuthRequest} + } + + if s.Server.PasswordCallback(userAuthReq.User, string(password)) { + break userAuthLoop + } + case "publickey": + if s.Server.PubKeyCallback == nil { + break + } + payload := userAuthReq.Payload + if len(payload) < 1 { + return ParseError{msgUserAuthRequest} + } + isQuery := payload[0] == 0 + payload = payload[1:] + algoBytes, payload, ok := parseString(payload) + if !ok { + return ParseError{msgUserAuthRequest} + } + algo := string(algoBytes) + + pubKey, payload, ok := parseString(payload) + if !ok { + return ParseError{msgUserAuthRequest} + } + if isQuery { + // The client can query if the given public key + // would be ok. + if len(payload) > 0 { + return ParseError{msgUserAuthRequest} + } + if s.testPubKey(userAuthReq.User, algo, pubKey) { + okMsg := userAuthPubKeyOkMsg{ + Algo: algo, + PubKey: string(pubKey), + } + if err = s.writePacket(marshal(msgUserAuthPubKeyOk, okMsg)); err != nil { + return err + } + continue userAuthLoop + } + } else { + sig, payload, ok := parseString(payload) + if !ok || len(payload) > 0 { + return ParseError{msgUserAuthRequest} + } + if !isAcceptableAlgo(algo) { + break + } + rsaSig, ok := parseRSASig(sig) + if !ok { + return ParseError{msgUserAuthRequest} + } + signedData := buildDataSignedForAuth(H, userAuthReq, algoBytes, pubKey) + switch algo { + case hostAlgoRSA: + hashFunc := crypto.SHA1 + h := hashFunc.New() + h.Write(signedData) + digest := h.Sum() + rsaKey, ok := parseRSA(pubKey) + if !ok { + return ParseError{msgUserAuthRequest} + } + if rsa.VerifyPKCS1v15(rsaKey, hashFunc, digest, rsaSig) != nil { + return ParseError{msgUserAuthRequest} + } + default: + return os.NewError("ssh: isAcceptableAlgo incorrect") + } + if s.testPubKey(userAuthReq.User, algo, pubKey) { + break userAuthLoop + } + } + } + + var failureMsg userAuthFailureMsg + if s.Server.PasswordCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "password") + } + if s.Server.PubKeyCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "publickey") + } + + if len(failureMsg.Methods) == 0 { + return os.NewError("ssh: no authentication methods configured but NoClientAuth is also false") + } + + if err = s.writePacket(marshal(msgUserAuthFailure, failureMsg)); err != nil { + return err + } + } + + packet = []byte{msgUserAuthSuccess} + if err = s.writePacket(packet); err != nil { + return err + } + + return nil +} + +const defaultWindowSize = 32768 + +// Accept reads and processes messages on a ServerConnection. It must be called +// in order to demultiplex messages to any resulting Channels. +func (s *ServerConnection) Accept() (Channel, os.Error) { + if s.err != nil { + return nil, s.err + } + + for { + packet, err := s.readPacket() + if err != nil { + + s.lock.Lock() + s.err = err + s.lock.Unlock() + + for _, c := range s.channels { + c.dead = true + c.handleData(nil) + } + + return nil, err + } + + switch packet[0] { + case msgChannelOpen: + var chanOpen channelOpenMsg + if err := unmarshal(&chanOpen, packet, msgChannelOpen); err != nil { + return nil, err + } + + c := new(channel) + c.chanType = chanOpen.ChanType + c.theirId = chanOpen.PeersId + c.theirWindow = chanOpen.PeersWindow + c.maxPacketSize = chanOpen.MaxPacketSize + c.extraData = chanOpen.TypeSpecificData + c.myWindow = defaultWindowSize + c.serverConn = s + c.cond = sync.NewCond(&c.lock) + c.pendingData = make([]byte, c.myWindow) + + s.lock.Lock() + c.myId = s.nextChanId + s.nextChanId++ + s.channels[c.myId] = c + s.lock.Unlock() + return c, nil + + case msgChannelRequest: + var chanRequest channelRequestMsg + if err := unmarshal(&chanRequest, packet, msgChannelRequest); err != nil { + return nil, err + } + + s.lock.Lock() + c, ok := s.channels[chanRequest.PeersId] + if !ok { + continue + } + c.handlePacket(&chanRequest) + s.lock.Unlock() + + case msgChannelData: + if len(packet) < 5 { + return nil, ParseError{msgChannelData} + } + chanId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4]) + + s.lock.Lock() + c, ok := s.channels[chanId] + if !ok { + continue + } + c.handleData(packet[9:]) + s.lock.Unlock() + + case msgChannelEOF: + var eofMsg channelEOFMsg + if err := unmarshal(&eofMsg, packet, msgChannelEOF); err != nil { + return nil, err + } + + s.lock.Lock() + c, ok := s.channels[eofMsg.PeersId] + if !ok { + continue + } + c.handlePacket(&eofMsg) + s.lock.Unlock() + + case msgChannelClose: + var closeMsg channelCloseMsg + if err := unmarshal(&closeMsg, packet, msgChannelClose); err != nil { + return nil, err + } + + s.lock.Lock() + c, ok := s.channels[closeMsg.PeersId] + if !ok { + continue + } + c.handlePacket(&closeMsg) + s.lock.Unlock() + + case msgGlobalRequest: + var request globalRequestMsg + if err := unmarshal(&request, packet, msgGlobalRequest); err != nil { + return nil, err + } + + if request.WantReply { + if err := s.writePacket([]byte{msgRequestFailure}); err != nil { + return nil, err + } + } + + default: + // Unknown message. Ignore. + } + } + + panic("unreachable") +} diff --git a/src/pkg/exp/ssh/server_shell.go b/src/pkg/exp/ssh/server_shell.go new file mode 100644 index 000000000..53a3241f5 --- /dev/null +++ b/src/pkg/exp/ssh/server_shell.go @@ -0,0 +1,399 @@ +// 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 ssh + +import ( + "os" +) + +// ServerShell contains the state for running a VT100 terminal that is capable +// of reading lines of input. +type ServerShell struct { + c Channel + prompt string + + // line is the current line being entered. + line []byte + // pos is the logical position of the cursor in line + pos int + + // cursorX contains the current X value of the cursor where the left + // edge is 0. cursorY contains the row number where the first row of + // the current line is 0. + cursorX, cursorY int + // maxLine is the greatest value of cursorY so far. + maxLine int + + termWidth, termHeight int + + // outBuf contains the terminal data to be sent. + outBuf []byte + // remainder contains the remainder of any partial key sequences after + // a read. It aliases into inBuf. + remainder []byte + inBuf [256]byte +} + +// NewServerShell runs a VT100 terminal on the given channel. prompt is a +// string that is written at the start of each input line. For example: "> ". +func NewServerShell(c Channel, prompt string) *ServerShell { + return &ServerShell{ + c: c, + prompt: prompt, + termWidth: 80, + termHeight: 24, + } +} + +const ( + keyCtrlD = 4 + keyEnter = '\r' + keyEscape = 27 + keyBackspace = 127 + keyUnknown = 256 + iota + keyUp + keyDown + keyLeft + keyRight + keyAltLeft + keyAltRight +) + +// bytesToKey tries to parse a key sequence from b. If successful, it returns +// the key and the remainder of the input. Otherwise it returns -1. +func bytesToKey(b []byte) (int, []byte) { + if len(b) == 0 { + return -1, nil + } + + if b[0] != keyEscape { + return int(b[0]), b[1:] + } + + if len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { + switch b[2] { + case 'A': + return keyUp, b[3:] + case 'B': + return keyDown, b[3:] + case 'C': + return keyRight, b[3:] + case 'D': + return keyLeft, b[3:] + } + } + + if len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { + switch b[5] { + case 'C': + return keyAltRight, b[6:] + case 'D': + return keyAltLeft, b[6:] + } + } + + // If we get here then we have a key that we don't recognise, or a + // partial sequence. It's not clear how one should find the end of a + // sequence without knowing them all, but it seems that [a-zA-Z] only + // appears at the end of a sequence. + for i, c := range b[0:] { + if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' { + return keyUnknown, b[i+1:] + } + } + + return -1, b +} + +// queue appends data to the end of ss.outBuf +func (ss *ServerShell) queue(data []byte) { + if len(ss.outBuf)+len(data) > cap(ss.outBuf) { + newOutBuf := make([]byte, len(ss.outBuf), 2*(len(ss.outBuf)+len(data))) + copy(newOutBuf, ss.outBuf) + ss.outBuf = newOutBuf + } + + oldLen := len(ss.outBuf) + ss.outBuf = ss.outBuf[:len(ss.outBuf)+len(data)] + copy(ss.outBuf[oldLen:], data) +} + +var eraseUnderCursor = []byte{' ', keyEscape, '[', 'D'} + +func isPrintable(key int) bool { + return key >= 32 && key < 127 +} + +// moveCursorToPos appends data to ss.outBuf which will move the cursor to the +// given, logical position in the text. +func (ss *ServerShell) moveCursorToPos(pos int) { + x := len(ss.prompt) + pos + y := x / ss.termWidth + x = x % ss.termWidth + + up := 0 + if y < ss.cursorY { + up = ss.cursorY - y + } + + down := 0 + if y > ss.cursorY { + down = y - ss.cursorY + } + + left := 0 + if x < ss.cursorX { + left = ss.cursorX - x + } + + right := 0 + if x > ss.cursorX { + right = x - ss.cursorX + } + + movement := make([]byte, 3*(up+down+left+right)) + m := movement + for i := 0; i < up; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'A' + m = m[3:] + } + for i := 0; i < down; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'B' + m = m[3:] + } + for i := 0; i < left; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'D' + m = m[3:] + } + for i := 0; i < right; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'C' + m = m[3:] + } + + ss.cursorX = x + ss.cursorY = y + ss.queue(movement) +} + +const maxLineLength = 4096 + +// handleKey processes the given key and, optionally, returns a line of text +// that the user has entered. +func (ss *ServerShell) handleKey(key int) (line string, ok bool) { + switch key { + case keyBackspace: + if ss.pos == 0 { + return + } + ss.pos-- + + copy(ss.line[ss.pos:], ss.line[1+ss.pos:]) + ss.line = ss.line[:len(ss.line)-1] + ss.writeLine(ss.line[ss.pos:]) + ss.moveCursorToPos(ss.pos) + ss.queue(eraseUnderCursor) + case keyAltLeft: + // move left by a word. + if ss.pos == 0 { + return + } + ss.pos-- + for ss.pos > 0 { + if ss.line[ss.pos] != ' ' { + break + } + ss.pos-- + } + for ss.pos > 0 { + if ss.line[ss.pos] == ' ' { + ss.pos++ + break + } + ss.pos-- + } + ss.moveCursorToPos(ss.pos) + case keyAltRight: + // move right by a word. + for ss.pos < len(ss.line) { + if ss.line[ss.pos] == ' ' { + break + } + ss.pos++ + } + for ss.pos < len(ss.line) { + if ss.line[ss.pos] != ' ' { + break + } + ss.pos++ + } + ss.moveCursorToPos(ss.pos) + case keyLeft: + if ss.pos == 0 { + return + } + ss.pos-- + ss.moveCursorToPos(ss.pos) + case keyRight: + if ss.pos == len(ss.line) { + return + } + ss.pos++ + ss.moveCursorToPos(ss.pos) + case keyEnter: + ss.moveCursorToPos(len(ss.line)) + ss.queue([]byte("\r\n")) + line = string(ss.line) + ok = true + ss.line = ss.line[:0] + ss.pos = 0 + ss.cursorX = 0 + ss.cursorY = 0 + ss.maxLine = 0 + default: + if !isPrintable(key) { + return + } + if len(ss.line) == maxLineLength { + return + } + if len(ss.line) == cap(ss.line) { + newLine := make([]byte, len(ss.line), 2*(1+len(ss.line))) + copy(newLine, ss.line) + ss.line = newLine + } + ss.line = ss.line[:len(ss.line)+1] + copy(ss.line[ss.pos+1:], ss.line[ss.pos:]) + ss.line[ss.pos] = byte(key) + ss.writeLine(ss.line[ss.pos:]) + ss.pos++ + ss.moveCursorToPos(ss.pos) + } + return +} + +func (ss *ServerShell) writeLine(line []byte) { + for len(line) != 0 { + if ss.cursorX == ss.termWidth { + ss.queue([]byte("\r\n")) + ss.cursorX = 0 + ss.cursorY++ + if ss.cursorY > ss.maxLine { + ss.maxLine = ss.cursorY + } + } + + remainingOnLine := ss.termWidth - ss.cursorX + todo := len(line) + if todo > remainingOnLine { + todo = remainingOnLine + } + ss.queue(line[:todo]) + ss.cursorX += todo + line = line[todo:] + } +} + +// parsePtyRequest parses the payload of the pty-req message and extracts the +// dimensions of the terminal. See RFC 4254, section 6.2. +func parsePtyRequest(s []byte) (width, height int, ok bool) { + _, s, ok = parseString(s) + if !ok { + return + } + width32, s, ok := parseUint32(s) + if !ok { + return + } + height32, _, ok := parseUint32(s) + width = int(width32) + height = int(height32) + if width < 1 { + ok = false + } + if height < 1 { + ok = false + } + return +} + +func (ss *ServerShell) Write(buf []byte) (n int, err os.Error) { + return ss.c.Write(buf) +} + +// ReadLine returns a line of input from the terminal. +func (ss *ServerShell) ReadLine() (line string, err os.Error) { + ss.writeLine([]byte(ss.prompt)) + ss.c.Write(ss.outBuf) + ss.outBuf = ss.outBuf[:0] + + for { + // ss.remainder is a slice at the beginning of ss.inBuf + // containing a partial key sequence + readBuf := ss.inBuf[len(ss.remainder):] + n, err := ss.c.Read(readBuf) + if err == nil { + ss.remainder = ss.inBuf[:n+len(ss.remainder)] + rest := ss.remainder + lineOk := false + for !lineOk { + var key int + key, rest = bytesToKey(rest) + if key < 0 { + break + } + if key == keyCtrlD { + return "", os.EOF + } + line, lineOk = ss.handleKey(key) + } + if len(rest) > 0 { + n := copy(ss.inBuf[:], rest) + ss.remainder = ss.inBuf[:n] + } else { + ss.remainder = nil + } + ss.c.Write(ss.outBuf) + ss.outBuf = ss.outBuf[:0] + if lineOk { + return + } + continue + } + + if req, ok := err.(ChannelRequest); ok { + ok := false + switch req.Request { + case "pty-req": + ss.termWidth, ss.termHeight, ok = parsePtyRequest(req.Payload) + if !ok { + ss.termWidth = 80 + ss.termHeight = 24 + } + case "shell": + ok = true + if len(req.Payload) > 0 { + // We don't accept any commands, only the default shell. + ok = false + } + case "env": + ok = true + } + if req.WantReply { + ss.c.AckRequest(ok) + } + } else { + return "", err + } + } + panic("unreachable") +} diff --git a/src/pkg/exp/ssh/server_shell_test.go b/src/pkg/exp/ssh/server_shell_test.go new file mode 100644 index 000000000..622cf7cfa --- /dev/null +++ b/src/pkg/exp/ssh/server_shell_test.go @@ -0,0 +1,134 @@ +// 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 ssh + +import ( + "testing" + "os" +) + +type MockChannel struct { + toSend []byte + bytesPerRead int + received []byte +} + +func (c *MockChannel) Accept() os.Error { + return nil +} + +func (c *MockChannel) Reject(RejectionReason, string) os.Error { + return nil +} + +func (c *MockChannel) Read(data []byte) (n int, err os.Error) { + n = len(data) + if n == 0 { + return + } + if n > len(c.toSend) { + n = len(c.toSend) + } + if n == 0 { + return 0, os.EOF + } + if c.bytesPerRead > 0 && n > c.bytesPerRead { + n = c.bytesPerRead + } + copy(data, c.toSend[:n]) + c.toSend = c.toSend[n:] + return +} + +func (c *MockChannel) Write(data []byte) (n int, err os.Error) { + c.received = append(c.received, data...) + return len(data), nil +} + +func (c *MockChannel) Close() os.Error { + return nil +} + +func (c *MockChannel) AckRequest(ok bool) os.Error { + return nil +} + +func (c *MockChannel) ChannelType() string { + return "" +} + +func (c *MockChannel) ExtraData() []byte { + return nil +} + +func TestClose(t *testing.T) { + c := &MockChannel{} + ss := NewServerShell(c, "> ") + line, err := ss.ReadLine() + if line != "" { + t.Errorf("Expected empty line but got: %s", line) + } + if err != os.EOF { + t.Errorf("Error should have been EOF but got: %s", err) + } +} + +var keyPressTests = []struct { + in string + line string + err os.Error +}{ + { + "", + "", + os.EOF, + }, + { + "\r", + "", + nil, + }, + { + "foo\r", + "foo", + nil, + }, + { + "a\x1b[Cb\r", // right + "ab", + nil, + }, + { + "a\x1b[Db\r", // left + "ba", + nil, + }, + { + "a\177b\r", // backspace + "b", + nil, + }, +} + +func TestKeyPresses(t *testing.T) { + for i, test := range keyPressTests { + for j := 0; j < len(test.in); j++ { + c := &MockChannel{ + toSend: []byte(test.in), + bytesPerRead: j, + } + ss := NewServerShell(c, "> ") + line, err := ss.ReadLine() + if line != test.line { + t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line) + break + } + if err != test.err { + t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err) + break + } + } + } +} diff --git a/src/pkg/exp/ssh/transport.go b/src/pkg/exp/ssh/transport.go new file mode 100644 index 000000000..5a474a9f2 --- /dev/null +++ b/src/pkg/exp/ssh/transport.go @@ -0,0 +1,322 @@ +// 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 ssh + +import ( + "bufio" + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/hmac" + "crypto/subtle" + "hash" + "io" + "os" +) + +const ( + paddingMultiple = 16 // TODO(dfc) does this need to be configurable? +) + +// transport represents the SSH connection to the remote peer. +type transport struct { + reader + writer + + cipherAlgo string + macAlgo string + compressionAlgo string + + Close func() os.Error +} + +// reader represents the incoming connection state. +type reader struct { + io.Reader + common +} + +// writer represnts the outgoing connection state. +type writer struct { + *bufio.Writer + paddingMultiple int + rand io.Reader + common +} + +// common represents the cipher state needed to process messages in a single +// direction. +type common struct { + seqNum uint32 + mac hash.Hash + cipher cipher.Stream +} + +// Read and decrypt a single packet from the remote peer. +func (r *reader) readOnePacket() ([]byte, os.Error) { + var lengthBytes = make([]byte, 5) + var macSize uint32 + + if _, err := io.ReadFull(r, lengthBytes); err != nil { + return nil, err + } + + if r.cipher != nil { + r.cipher.XORKeyStream(lengthBytes, lengthBytes) + } + + if r.mac != nil { + r.mac.Reset() + seqNumBytes := []byte{ + byte(r.seqNum >> 24), + byte(r.seqNum >> 16), + byte(r.seqNum >> 8), + byte(r.seqNum), + } + r.mac.Write(seqNumBytes) + r.mac.Write(lengthBytes) + macSize = uint32(r.mac.Size()) + } + + length := uint32(lengthBytes[0])<<24 | uint32(lengthBytes[1])<<16 | uint32(lengthBytes[2])<<8 | uint32(lengthBytes[3]) + paddingLength := uint32(lengthBytes[4]) + + if length <= paddingLength+1 { + return nil, os.NewError("invalid packet length") + } + if length > maxPacketSize { + return nil, os.NewError("packet too large") + } + + packet := make([]byte, length-1+macSize) + if _, err := io.ReadFull(r, packet); err != nil { + return nil, err + } + mac := packet[length-1:] + if r.cipher != nil { + r.cipher.XORKeyStream(packet, packet[:length-1]) + } + + if r.mac != nil { + r.mac.Write(packet[:length-1]) + if subtle.ConstantTimeCompare(r.mac.Sum(), mac) != 1 { + return nil, os.NewError("ssh: MAC failure") + } + } + + r.seqNum++ + return packet[:length-paddingLength-1], nil +} + +// Read and decrypt next packet discarding debug and noop messages. +func (t *transport) readPacket() ([]byte, os.Error) { + for { + packet, err := t.readOnePacket() + if err != nil { + return nil, err + } + if packet[0] != msgIgnore && packet[0] != msgDebug { + return packet, nil + } + } + panic("unreachable") +} + +// Encrypt and send a packet of data to the remote peer. +func (w *writer) writePacket(packet []byte) os.Error { + paddingLength := paddingMultiple - (5+len(packet))%paddingMultiple + if paddingLength < 4 { + paddingLength += paddingMultiple + } + + length := len(packet) + 1 + paddingLength + lengthBytes := []byte{ + byte(length >> 24), + byte(length >> 16), + byte(length >> 8), + byte(length), + byte(paddingLength), + } + padding := make([]byte, paddingLength) + _, err := io.ReadFull(w.rand, padding) + if err != nil { + return err + } + + if w.mac != nil { + w.mac.Reset() + seqNumBytes := []byte{ + byte(w.seqNum >> 24), + byte(w.seqNum >> 16), + byte(w.seqNum >> 8), + byte(w.seqNum), + } + w.mac.Write(seqNumBytes) + w.mac.Write(lengthBytes) + w.mac.Write(packet) + w.mac.Write(padding) + } + + // TODO(dfc) lengthBytes, packet and padding should be + // subslices of a single buffer + if w.cipher != nil { + w.cipher.XORKeyStream(lengthBytes, lengthBytes) + w.cipher.XORKeyStream(packet, packet) + w.cipher.XORKeyStream(padding, padding) + } + + if _, err := w.Write(lengthBytes); err != nil { + return err + } + if _, err := w.Write(packet); err != nil { + return err + } + if _, err := w.Write(padding); err != nil { + return err + } + + if w.mac != nil { + if _, err := w.Write(w.mac.Sum()); err != nil { + return err + } + } + + if err := w.Flush(); err != nil { + return err + } + w.seqNum++ + return err +} + +type direction struct { + ivTag []byte + keyTag []byte + macKeyTag []byte +} + +// TODO(dfc) can this be made a constant ? +var ( + serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}} + clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} +) + +// setupKeys sets the cipher and MAC keys from K, H and sessionId, as +// described in RFC 4253, section 6.4. direction should either be serverKeys +// (to setup server->client keys) or clientKeys (for client->server keys). +func (c *common) setupKeys(d direction, K, H, sessionId []byte, hashFunc crypto.Hash) os.Error { + h := hashFunc.New() + + blockSize := 16 + keySize := 16 + macKeySize := 20 + + iv := make([]byte, blockSize) + key := make([]byte, keySize) + macKey := make([]byte, macKeySize) + generateKeyMaterial(iv, d.ivTag, K, H, sessionId, h) + generateKeyMaterial(key, d.keyTag, K, H, sessionId, h) + generateKeyMaterial(macKey, d.macKeyTag, K, H, sessionId, h) + + c.mac = truncatingMAC{12, hmac.NewSHA1(macKey)} + aes, err := aes.NewCipher(key) + if err != nil { + return err + } + c.cipher = cipher.NewCTR(aes, iv) + return nil +} + +// generateKeyMaterial fills out with key material generated from tag, K, H +// and sessionId, as specified in RFC 4253, section 7.2. +func generateKeyMaterial(out, tag []byte, K, H, sessionId []byte, h hash.Hash) { + var digestsSoFar []byte + + for len(out) > 0 { + h.Reset() + h.Write(K) + h.Write(H) + + if len(digestsSoFar) == 0 { + h.Write(tag) + h.Write(sessionId) + } else { + h.Write(digestsSoFar) + } + + digest := h.Sum() + n := copy(out, digest) + out = out[n:] + if len(out) > 0 { + digestsSoFar = append(digestsSoFar, digest...) + } + } +} + +// truncatingMAC wraps around a hash.Hash and truncates the output digest to +// a given size. +type truncatingMAC struct { + length int + hmac hash.Hash +} + +func (t truncatingMAC) Write(data []byte) (int, os.Error) { + return t.hmac.Write(data) +} + +func (t truncatingMAC) Sum() []byte { + digest := t.hmac.Sum() + return digest[:t.length] +} + +func (t truncatingMAC) Reset() { + t.hmac.Reset() +} + +func (t truncatingMAC) Size() int { + return t.length +} + +// maxVersionStringBytes is the maximum number of bytes that we'll accept as a +// version string. In the event that the client is talking a different protocol +// we need to set a limit otherwise we will keep using more and more memory +// while searching for the end of the version handshake. +const maxVersionStringBytes = 1024 + +// Read version string as specified by RFC 4253, section 4.2. +func readVersion(r io.Reader) (versionString []byte, ok bool) { + versionString = make([]byte, 0, 64) + seenCR := false + + var buf [1]byte +forEachByte: + for len(versionString) < maxVersionStringBytes { + _, err := io.ReadFull(r, buf[:]) + if err != nil { + return + } + b := buf[0] + + if !seenCR { + if b == '\r' { + seenCR = true + } + } else { + if b == '\n' { + ok = true + break forEachByte + } else { + seenCR = false + } + } + versionString = append(versionString, b) + } + + if ok { + // We need to remove the CR from versionString + versionString = versionString[:len(versionString)-1] + } + + return +} diff --git a/src/pkg/exp/ssh/transport_test.go b/src/pkg/exp/ssh/transport_test.go new file mode 100644 index 000000000..9a610a780 --- /dev/null +++ b/src/pkg/exp/ssh/transport_test.go @@ -0,0 +1,37 @@ +// 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 ssh + +import ( + "bufio" + "bytes" + "testing" +) + +func TestReadVersion(t *testing.T) { + buf := []byte(serverVersion) + result, ok := readVersion(bufio.NewReader(bytes.NewBuffer(buf))) + if !ok { + t.Error("readVersion didn't read version correctly") + } + if !bytes.Equal(buf[:len(buf)-2], result) { + t.Error("version read did not match expected") + } +} + +func TestReadVersionTooLong(t *testing.T) { + buf := make([]byte, maxVersionStringBytes+1) + if _, ok := readVersion(bufio.NewReader(bytes.NewBuffer(buf))); ok { + t.Errorf("readVersion consumed %d bytes without error", len(buf)) + } +} + +func TestReadVersionWithoutCRLF(t *testing.T) { + buf := []byte(serverVersion) + buf = buf[:len(buf)-1] + if _, ok := readVersion(bufio.NewReader(bytes.NewBuffer(buf))); ok { + t.Error("readVersion did not notice \\n was missing") + } +} diff --git a/src/pkg/exp/template/html/Makefile b/src/pkg/exp/template/html/Makefile index 3a93bebc0..9032aead8 100644 --- a/src/pkg/exp/template/html/Makefile +++ b/src/pkg/exp/template/html/Makefile @@ -6,8 +6,16 @@ include ../../../../Make.inc TARG=exp/template/html GOFILES=\ + clone.go\ + content.go\ context.go\ + css.go\ + doc.go\ + error.go\ escape.go\ + html.go\ js.go\ + transition.go\ + url.go\ include ../../../../Make.pkg diff --git a/src/pkg/exp/template/html/clone.go b/src/pkg/exp/template/html/clone.go new file mode 100644 index 000000000..803a64de1 --- /dev/null +++ b/src/pkg/exp/template/html/clone.go @@ -0,0 +1,90 @@ +// 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 html + +import ( + "template/parse" +) + +// clone clones a template Node. +func clone(n parse.Node) parse.Node { + switch t := n.(type) { + case *parse.ActionNode: + return cloneAction(t) + case *parse.IfNode: + b := new(parse.IfNode) + copyBranch(&b.BranchNode, &t.BranchNode) + return b + case *parse.ListNode: + return cloneList(t) + case *parse.RangeNode: + b := new(parse.RangeNode) + copyBranch(&b.BranchNode, &t.BranchNode) + return b + case *parse.TemplateNode: + return cloneTemplate(t) + case *parse.TextNode: + return cloneText(t) + case *parse.WithNode: + b := new(parse.WithNode) + copyBranch(&b.BranchNode, &t.BranchNode) + return b + } + panic("cloning " + n.String() + " is unimplemented") +} + +// cloneAction returns a deep clone of n. +func cloneAction(n *parse.ActionNode) *parse.ActionNode { + // We use keyless fields because they won't compile if a field is added. + return &parse.ActionNode{n.NodeType, n.Line, clonePipe(n.Pipe)} +} + +// cloneList returns a deep clone of n. +func cloneList(n *parse.ListNode) *parse.ListNode { + if n == nil { + return nil + } + // We use keyless fields because they won't compile if a field is added. + c := parse.ListNode{n.NodeType, make([]parse.Node, len(n.Nodes))} + for i, child := range n.Nodes { + c.Nodes[i] = clone(child) + } + return &c +} + +// clonePipe returns a shallow clone of n. +// The escaper does not modify pipe descendants in place so there's no need to +// clone deeply. +func clonePipe(n *parse.PipeNode) *parse.PipeNode { + if n == nil { + return nil + } + // We use keyless fields because they won't compile if a field is added. + return &parse.PipeNode{n.NodeType, n.Line, n.Decl, n.Cmds} +} + +// cloneTemplate returns a deep clone of n. +func cloneTemplate(n *parse.TemplateNode) *parse.TemplateNode { + // We use keyless fields because they won't compile if a field is added. + return &parse.TemplateNode{n.NodeType, n.Line, n.Name, clonePipe(n.Pipe)} +} + +// cloneText clones the given node sharing its []byte. +func cloneText(n *parse.TextNode) *parse.TextNode { + // We use keyless fields because they won't compile if a field is added. + return &parse.TextNode{n.NodeType, n.Text} +} + +// copyBranch clones src into dst. +func copyBranch(dst, src *parse.BranchNode) { + // We use keyless fields because they won't compile if a field is added. + *dst = parse.BranchNode{ + src.NodeType, + src.Line, + clonePipe(src.Pipe), + cloneList(src.List), + cloneList(src.ElseList), + } +} diff --git a/src/pkg/exp/template/html/clone_test.go b/src/pkg/exp/template/html/clone_test.go new file mode 100644 index 000000000..d91542529 --- /dev/null +++ b/src/pkg/exp/template/html/clone_test.go @@ -0,0 +1,90 @@ +// 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 html + +import ( + "bytes" + "template" + "template/parse" + "testing" +) + +func TestClone(t *testing.T) { + tests := []struct { + input, want, wantClone string + }{ + { + `Hello, {{if true}}{{""}}{{end}}!`, + "Hello, !", + "Hello, <World>!", + }, + { + `Hello, {{if false}}{{.X}}{{else}}{{""}}{{end}}!`, + "Hello, !", + "Hello, <World>!", + }, + { + `Hello, {{with ""}}{{.}}{{end}}!`, + "Hello, !", + "Hello, <World>!", + }, + { + `{{range .}}

{{.}}

{{end}}`, + "

foo

baz

", + "

foo

<bar>

baz

", + }, + { + `Hello, {{"" | html}}!`, + "Hello, <World>!", + "Hello, <World>!", + }, + { + `Hello{{if 1}}, World{{else}}{{template "d"}}{{end}}!`, + "Hello, World!", + "Hello, World!", + }, + } + + for _, test := range tests { + s := template.Must(template.New("s").Parse(test.input)) + d := template.New("d") + d.Tree = &parse.Tree{Name: d.Name(), Root: cloneList(s.Root)} + + if want, got := s.Root.String(), d.Root.String(); want != got { + t.Errorf("want %q, got %q", want, got) + } + + d, err := Escape(d) + if err != nil { + t.Errorf("%q: failed to escape: %s", test.input, err) + continue + } + + if want, got := "s", s.Name(); want != got { + t.Errorf("want %q, got %q", want, got) + continue + } + if want, got := "d", d.Name(); want != got { + t.Errorf("want %q, got %q", want, got) + continue + } + + data := []string{"foo", "", "baz"} + + // Make sure escaping d did not affect s. + var b bytes.Buffer + s.Execute(&b, data) + if got := b.String(); got != test.want { + t.Errorf("%q: want %q, got %q", test.input, test.want, got) + continue + } + + b.Reset() + d.Execute(&b, data) + if got := b.String(); got != test.wantClone { + t.Errorf("%q: want %q, got %q", test.input, test.wantClone, got) + } + } +} diff --git a/src/pkg/exp/template/html/content.go b/src/pkg/exp/template/html/content.go new file mode 100644 index 000000000..8b9809b98 --- /dev/null +++ b/src/pkg/exp/template/html/content.go @@ -0,0 +1,90 @@ +// 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 html + +import ( + "fmt" +) + +// Strings of content from a trusted source. +type ( + // CSS encapsulates known safe content that matches any of: + // (1) The CSS3 stylesheet production, such as `p { color: purple }`. + // (2) The CSS3 rule production, such as `a[href=~"https:"].foo#bar`. + // (3) CSS3 declaration productions, such as `color: red; margin: 2px`. + // (4) The CSS3 value production, such as `rgba(0, 0, 255, 127)`. + // See http://www.w3.org/TR/css3-syntax/#style + CSS string + + // HTML encapsulates a known safe HTML document fragment. + // It should not be used for HTML from a third-party, or HTML with + // unclosed tags or comments. The outputs of a sound HTML sanitizer + // and a template escaped by this package are fine for use with HTML. + HTML string + + // HTMLAttr encapsulates an HTML attribute from a trusted source, + // for example: ` dir="ltr"`. + HTMLAttr string + + // JS encapsulates a known safe EcmaScript5 Expression, or example, + // `(x + y * z())`. + // Template authors are responsible for ensuring that typed expressions + // do not break the intended precedence and that there is no + // statement/expression ambiguity as when passing an expression like + // "{ foo: bar() }\n['foo']()", which is both a valid Expression and a + // valid Program with a very different meaning. + JS string + + // JSStr encapsulates a sequence of characters meant to be embedded + // between quotes in a JavaScript expression. + // The string must match a series of StringCharacters: + // StringCharacter :: SourceCharacter but not `\` or LineTerminator + // | EscapeSequence + // Note that LineContinuations are not allowed. + // JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not. + JSStr string + + // URL encapsulates a known safe URL as defined in RFC 3896. + // A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()` + // from a trusted source should go in the page, but by default dynamic + // `javascript:` URLs are filtered out since they are a frequently + // exploited injection vector. + URL string +) + +type contentType uint8 + +const ( + contentTypePlain contentType = iota + contentTypeCSS + contentTypeHTML + contentTypeHTMLAttr + contentTypeJS + contentTypeJSStr + contentTypeURL +) + +// stringify converts its arguments to a string and the type of the content. +func stringify(args ...interface{}) (string, contentType) { + if len(args) == 1 { + switch s := args[0].(type) { + case string: + return s, contentTypePlain + case CSS: + return string(s), contentTypeCSS + case HTML: + return string(s), contentTypeHTML + case HTMLAttr: + return string(s), contentTypeHTMLAttr + case JS: + return string(s), contentTypeJS + case JSStr: + return string(s), contentTypeJSStr + case URL: + return string(s), contentTypeURL + } + } + return fmt.Sprint(args...), contentTypePlain +} diff --git a/src/pkg/exp/template/html/content_test.go b/src/pkg/exp/template/html/content_test.go new file mode 100644 index 000000000..033dee174 --- /dev/null +++ b/src/pkg/exp/template/html/content_test.go @@ -0,0 +1,222 @@ +// 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 html + +import ( + "bytes" + "strings" + "template" + "testing" +) + +func TestTypedContent(t *testing.T) { + data := []interface{}{ + ` "foo%" O'Reilly &bar;`, + CSS(`a[href =~ "//example.com"]#foo`), + HTML(`Hello, World &tc!`), + HTMLAttr(` dir="ltr"`), + JS(`c && alert("Hello, World!");`), + JSStr(`Hello, World & O'Reilly\x21`), + URL(`greeting=H%69&addressee=(World)`), + } + + // For each content sensitive escaper, see how it does on + // each of the typed strings above. + tests := []struct { + // A template containing a single {{.}}. + input string + want []string + }{ + { + ``, + []string{ + `ZgotmplZ`, + // Allowed but not escaped. + `a[href =~ "//example.com"]#foo`, + `ZgotmplZ`, + `ZgotmplZ`, + `ZgotmplZ`, + `ZgotmplZ`, + `ZgotmplZ`, + }, + }, + { + `
`, + []string{ + `ZgotmplZ`, + // Allowed and HTML escaped. + `a[href =~ "//example.com"]#foo`, + `ZgotmplZ`, + `ZgotmplZ`, + `ZgotmplZ`, + `ZgotmplZ`, + `ZgotmplZ`, + }, + }, + { + `{{.}}`, + []string{ + `<b> "foo%" O'Reilly &bar;`, + `a[href =~ "//example.com"]#foo`, + // Not escaped. + `Hello, World &tc!`, + ` dir="ltr"`, + `c && alert("Hello, World!");`, + `Hello, World & O'Reilly\x21`, + `greeting=H%69&addressee=(World)`, + }, + }, + { + ``, + []string{ + `ZgotmplZ`, + `ZgotmplZ`, + `ZgotmplZ`, + // Allowed and HTML escaped. + ` dir="ltr"`, + `ZgotmplZ`, + `ZgotmplZ`, + `ZgotmplZ`, + }, + }, + { + ``, + []string{ + `<b> "foo%" O'Reilly &bar;`, + `a[href =~ "//example.com"]#foo`, + // Tags stripped, spaces escaped, entity not re-escaped. + `Hello, World &tc!`, + ` dir="ltr"`, + `c && alert("Hello, World!");`, + `Hello, World & O'Reilly\x21`, + `greeting=H%69&addressee=(World)`, + }, + }, + { + ``, + []string{ + `<b> "foo%" O'Reilly &bar;`, + `a[href =~ "//example.com"]#foo`, + // Tags stripped, entity not re-escaped. + `Hello, World &tc!`, + ` dir="ltr"`, + `c && alert("Hello, World!");`, + `Hello, World & O'Reilly\x21`, + `greeting=H%69&addressee=(World)`, + }, + }, + { + ``, + []string{ + `<b> "foo%" O'Reilly &bar;`, + `a[href =~ "//example.com"]#foo`, + // Angle brackets escaped to prevent injection of close tags, entity not re-escaped. + `Hello, <b>World</b> &tc!`, + ` dir="ltr"`, + `c && alert("Hello, World!");`, + `Hello, World & O'Reilly\x21`, + `greeting=H%69&addressee=(World)`, + }, + }, + { + ``, + []string{ + `"\u003cb\u003e \"foo%\" O'Reilly &bar;"`, + `"a[href =~ \"//example.com\"]#foo"`, + `"Hello, \u003cb\u003eWorld\u003c/b\u003e &tc!"`, + `" dir=\"ltr\""`, + // Not escaped. + `c && alert("Hello, World!");`, + // Escape sequence not over-escaped. + `"Hello, World & O'Reilly\x21"`, + `"greeting=H%69&addressee=(World)"`, + }, + }, + { + `