summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/go/gofrontend/gogo.cc3
-rw-r--r--gcc/go/gofrontend/runtime.cc7
-rw-r--r--gcc/go/gofrontend/runtime.def13
-rw-r--r--gcc/go/gofrontend/statements.cc5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug358.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug369.go4
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/Makefile.am151
-rw-r--r--libgo/Makefile.in305
-rwxr-xr-xlibgo/configure20
-rw-r--r--libgo/configure.ac3
-rw-r--r--libgo/go/archive/tar/common.go63
-rw-r--r--libgo/go/archive/tar/stat_atim.go20
-rw-r--r--libgo/go/archive/tar/stat_atimespec.go20
-rw-r--r--libgo/go/archive/tar/stat_unix.go32
-rw-r--r--libgo/go/archive/tar/tar_test.go56
-rw-r--r--libgo/go/archive/tar/writer.go2
-rw-r--r--libgo/go/archive/zip/reader.go114
-rw-r--r--libgo/go/archive/zip/reader_test.go11
-rw-r--r--libgo/go/archive/zip/struct.go93
-rw-r--r--libgo/go/archive/zip/testdata/zip64.zipbin0 -> 242 bytes
-rw-r--r--libgo/go/archive/zip/writer.go134
-rw-r--r--libgo/go/archive/zip/zip_test.go114
-rw-r--r--libgo/go/bufio/bufio.go35
-rw-r--r--libgo/go/bufio/bufio_test.go104
-rw-r--r--libgo/go/bytes/buffer.go13
-rw-r--r--libgo/go/bytes/buffer_test.go56
-rw-r--r--libgo/go/bytes/bytes.go11
-rw-r--r--libgo/go/bytes/bytes_test.go51
-rw-r--r--libgo/go/bytes/example_test.go9
-rw-r--r--libgo/go/compress/flate/copy.go17
-rw-r--r--libgo/go/compress/flate/copy_test.go52
-rw-r--r--libgo/go/compress/flate/deflate_test.go2
-rw-r--r--libgo/go/compress/flate/inflate.go66
-rw-r--r--libgo/go/compress/flate/writer_test.go60
-rw-r--r--libgo/go/compress/lzw/reader_test.go12
-rw-r--r--libgo/go/compress/lzw/writer.go11
-rw-r--r--libgo/go/compress/lzw/writer_test.go20
-rw-r--r--libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt2
-rw-r--r--libgo/go/compress/testdata/e.txt2
-rw-r--r--libgo/go/compress/testdata/pi.txt2
-rw-r--r--libgo/go/compress/zlib/reader.go2
-rw-r--r--libgo/go/container/heap/heap.go4
-rw-r--r--libgo/go/container/heap/heap_test.go13
-rwxr-xr-xlibgo/go/container/list/list.go236
-rwxr-xr-xlibgo/go/container/list/list_test.go102
-rw-r--r--libgo/go/crypto/aes/aes_test.go33
-rw-r--r--libgo/go/crypto/aes/block.go6
-rw-r--r--libgo/go/crypto/aes/cipher.go8
-rw-r--r--libgo/go/crypto/aes/cipher_asm.go46
-rw-r--r--libgo/go/crypto/aes/cipher_generic.go19
-rw-r--r--libgo/go/crypto/ecdsa/ecdsa.go6
-rw-r--r--libgo/go/crypto/ecdsa/ecdsa_test.go256
-rw-r--r--libgo/go/crypto/elliptic/elliptic.go90
-rw-r--r--libgo/go/crypto/elliptic/elliptic_test.go38
-rw-r--r--libgo/go/crypto/elliptic/p224.go91
-rw-r--r--libgo/go/crypto/md5/gen.go298
-rw-r--r--libgo/go/crypto/md5/md5.go35
-rw-r--r--libgo/go/crypto/md5/md5_test.go25
-rw-r--r--libgo/go/crypto/md5/md5block.go356
-rw-r--r--libgo/go/crypto/rand/rand_unix.go20
-rw-r--r--libgo/go/crypto/rsa/pkcs1v15.go13
-rw-r--r--libgo/go/crypto/rsa/rsa.go70
-rw-r--r--libgo/go/crypto/rsa/rsa_test.go18
-rw-r--r--libgo/go/crypto/sha1/sha1.go39
-rw-r--r--libgo/go/crypto/sha1/sha1_test.go25
-rw-r--r--libgo/go/crypto/sha1/sha1block.go9
-rw-r--r--libgo/go/crypto/sha256/sha256.go83
-rw-r--r--libgo/go/crypto/sha256/sha256_test.go25
-rw-r--r--libgo/go/crypto/sha256/sha256block.go17
-rw-r--r--libgo/go/crypto/sha512/sha512.go83
-rw-r--r--libgo/go/crypto/sha512/sha512_test.go25
-rw-r--r--libgo/go/crypto/sha512/sha512block.go16
-rw-r--r--libgo/go/crypto/tls/cipher_suites.go4
-rw-r--r--libgo/go/crypto/tls/common.go19
-rw-r--r--libgo/go/crypto/tls/conn.go61
-rw-r--r--libgo/go/crypto/tls/handshake_client.go9
-rw-r--r--libgo/go/crypto/tls/handshake_client_test.go218
-rw-r--r--libgo/go/crypto/tls/handshake_messages.go108
-rw-r--r--libgo/go/crypto/tls/handshake_messages_test.go34
-rw-r--r--libgo/go/crypto/tls/handshake_server.go525
-rw-r--r--libgo/go/crypto/tls/handshake_server_test.go539
-rw-r--r--libgo/go/crypto/tls/prf.go21
-rw-r--r--libgo/go/crypto/tls/prf_test.go15
-rw-r--r--libgo/go/crypto/tls/root_test.go61
-rw-r--r--libgo/go/crypto/tls/ticket.go182
-rw-r--r--libgo/go/crypto/tls/tls.go14
-rw-r--r--libgo/go/crypto/tls/tls_test.go47
-rw-r--r--libgo/go/crypto/x509/pem_decrypt.go133
-rw-r--r--libgo/go/crypto/x509/pem_decrypt_test.go119
-rw-r--r--libgo/go/crypto/x509/pkcs8.go2
-rw-r--r--libgo/go/crypto/x509/root_plan9.go31
-rw-r--r--libgo/go/crypto/x509/root_stub.go2
-rw-r--r--libgo/go/crypto/x509/root_windows.go8
-rw-r--r--libgo/go/crypto/x509/verify.go93
-rw-r--r--libgo/go/crypto/x509/verify_test.go97
-rw-r--r--libgo/go/crypto/x509/x509.go348
-rw-r--r--libgo/go/crypto/x509/x509_test.go235
-rw-r--r--libgo/go/database/sql/convert.go58
-rw-r--r--libgo/go/database/sql/fakedb_test.go29
-rw-r--r--libgo/go/database/sql/sql.go93
-rw-r--r--libgo/go/database/sql/sql_test.go4
-rw-r--r--libgo/go/debug/elf/file.go34
-rw-r--r--libgo/go/debug/elf/file_test.go15
-rw-r--r--libgo/go/debug/pe/file.go68
-rw-r--r--libgo/go/debug/pe/file_test.go30
-rw-r--r--libgo/go/debug/pe/pe.go11
-rw-r--r--libgo/go/encoding/asn1/asn1.go33
-rw-r--r--libgo/go/encoding/asn1/asn1_test.go2
-rw-r--r--libgo/go/encoding/asn1/common.go2
-rw-r--r--libgo/go/encoding/asn1/marshal.go38
-rw-r--r--libgo/go/encoding/asn1/marshal_test.go8
-rw-r--r--libgo/go/encoding/base32/base32.go3
-rw-r--r--libgo/go/encoding/base64/base64.go3
-rw-r--r--libgo/go/encoding/csv/writer.go5
-rw-r--r--libgo/go/encoding/gob/codec_test.go15
-rw-r--r--libgo/go/encoding/gob/decode.go2
-rw-r--r--libgo/go/encoding/gob/decoder.go37
-rw-r--r--libgo/go/encoding/gob/encode.go23
-rw-r--r--libgo/go/encoding/gob/encoder.go6
-rw-r--r--libgo/go/encoding/gob/encoder_test.go77
-rw-r--r--libgo/go/encoding/gob/type.go3
-rw-r--r--libgo/go/encoding/gob/type_test.go61
-rw-r--r--libgo/go/encoding/json/decode.go161
-rw-r--r--libgo/go/encoding/json/decode_test.go378
-rw-r--r--libgo/go/encoding/json/encode.go255
-rw-r--r--libgo/go/encoding/json/stream.go6
-rw-r--r--libgo/go/encoding/json/stream_test.go22
-rw-r--r--libgo/go/encoding/xml/marshal.go36
-rw-r--r--libgo/go/encoding/xml/marshal_test.go56
-rw-r--r--libgo/go/encoding/xml/read.go18
-rw-r--r--libgo/go/encoding/xml/typeinfo.go27
-rw-r--r--libgo/go/encoding/xml/xml.go51
-rw-r--r--libgo/go/encoding/xml/xml_test.go84
-rw-r--r--libgo/go/exp/html/atom/atom.go81
-rw-r--r--libgo/go/exp/html/atom/atom_test.go109
-rw-r--r--libgo/go/exp/html/atom/gen.go636
-rw-r--r--libgo/go/exp/html/atom/table.go694
-rw-r--r--libgo/go/exp/html/atom/table_test.go341
-rw-r--r--libgo/go/exp/html/doc.go2
-rw-r--r--libgo/go/exp/html/entity.go4154
-rw-r--r--libgo/go/exp/html/escape.go21
-rw-r--r--libgo/go/exp/html/foreign.go102
-rw-r--r--libgo/go/exp/html/node.go137
-rw-r--r--libgo/go/exp/html/node_test.go146
-rw-r--r--libgo/go/exp/html/parse.go1516
-rw-r--r--libgo/go/exp/html/parse_test.go282
-rw-r--r--libgo/go/exp/html/render.go32
-rw-r--r--libgo/go/exp/html/render_test.go215
-rw-r--r--libgo/go/exp/html/testdata/go1.html2237
-rw-r--r--libgo/go/exp/html/testdata/webkit/pending-spec-changes.dat24
-rw-r--r--libgo/go/exp/html/testdata/webkit/tables01.dat15
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests16.dat22
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests19.dat25
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests26.dat118
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests_innerHTML_1.dat8
-rw-r--r--libgo/go/exp/html/testdata/webkit/webkit01.dat11
-rw-r--r--libgo/go/exp/html/testdata/webkit/webkit02.dat55
-rw-r--r--libgo/go/exp/html/token.go534
-rw-r--r--libgo/go/exp/html/token_test.go133
-rw-r--r--libgo/go/exp/locale/collate/build/builder.go476
-rw-r--r--libgo/go/exp/locale/collate/build/builder_test.go269
-rw-r--r--libgo/go/exp/locale/collate/build/colelem.go329
-rw-r--r--libgo/go/exp/locale/collate/build/colelem_test.go197
-rw-r--r--libgo/go/exp/locale/collate/build/contract.go307
-rw-r--r--libgo/go/exp/locale/collate/build/contract_test.go264
-rw-r--r--libgo/go/exp/locale/collate/build/order.go309
-rw-r--r--libgo/go/exp/locale/collate/build/order_test.go197
-rw-r--r--libgo/go/exp/locale/collate/build/table.go136
-rw-r--r--libgo/go/exp/locale/collate/build/trie.go281
-rw-r--r--libgo/go/exp/locale/collate/build/trie_test.go107
-rw-r--r--libgo/go/exp/locale/collate/colelem.go183
-rw-r--r--libgo/go/exp/locale/collate/colelem_test.go169
-rw-r--r--libgo/go/exp/locale/collate/collate.go363
-rw-r--r--libgo/go/exp/locale/collate/contract.go86
-rw-r--r--libgo/go/exp/locale/collate/contract_test.go132
-rw-r--r--libgo/go/exp/locale/collate/export.go43
-rw-r--r--libgo/go/exp/locale/collate/export_test.go87
-rw-r--r--libgo/go/exp/locale/collate/maketables.go722
-rw-r--r--libgo/go/exp/locale/collate/regtest.go268
-rw-r--r--libgo/go/exp/locale/collate/table.go150
-rw-r--r--libgo/go/exp/locale/collate/tables.go7578
-rw-r--r--libgo/go/exp/locale/collate/tools/colcmp/chars.go937
-rw-r--r--libgo/go/exp/locale/collate/tools/colcmp/col.go95
-rw-r--r--libgo/go/exp/locale/collate/tools/colcmp/colcmp.go528
-rw-r--r--libgo/go/exp/locale/collate/tools/colcmp/darwin.go111
-rw-r--r--libgo/go/exp/locale/collate/tools/colcmp/gen.go179
-rw-r--r--libgo/go/exp/locale/collate/tools/colcmp/icu.go209
-rw-r--r--libgo/go/exp/locale/collate/trie.go99
-rw-r--r--libgo/go/exp/locale/collate/trie_test.go106
-rw-r--r--libgo/go/exp/norm/composition.go20
-rw-r--r--libgo/go/exp/norm/forminfo.go104
-rw-r--r--libgo/go/exp/norm/iter.go10
-rw-r--r--libgo/go/exp/norm/maketables.go17
-rw-r--r--libgo/go/exp/norm/normalize.go28
-rw-r--r--libgo/go/exp/norm/normregtest.go5
-rw-r--r--libgo/go/exp/norm/tables.go253
-rw-r--r--libgo/go/exp/norm/trie.go27
-rw-r--r--libgo/go/exp/norm/trie_test.go6
-rw-r--r--libgo/go/exp/norm/triedata_test.go28
-rw-r--r--libgo/go/exp/norm/triegen.go13
-rw-r--r--libgo/go/exp/types/check.go46
-rw-r--r--libgo/go/exp/types/check_test.go12
-rw-r--r--libgo/go/exp/types/exportdata.go7
-rw-r--r--libgo/go/exp/types/gcimporter.go65
-rw-r--r--libgo/go/exp/types/gcimporter_test.go59
-rw-r--r--libgo/go/exp/types/resolver_test.go136
-rw-r--r--libgo/go/exp/types/staging/builtins.go349
-rw-r--r--libgo/go/exp/types/staging/check.go352
-rw-r--r--libgo/go/exp/types/staging/check_test.go257
-rw-r--r--libgo/go/exp/types/staging/const.go662
-rw-r--r--libgo/go/exp/types/staging/conversions.go39
-rw-r--r--libgo/go/exp/types/staging/errors.go301
-rw-r--r--libgo/go/exp/types/staging/exportdata.go110
-rw-r--r--libgo/go/exp/types/staging/expr.go867
-rw-r--r--libgo/go/exp/types/staging/gcimporter.go889
-rw-r--r--libgo/go/exp/types/staging/gcimporter_test.go153
-rw-r--r--libgo/go/exp/types/staging/operand.go201
-rw-r--r--libgo/go/exp/types/staging/predicates.go236
-rw-r--r--libgo/go/exp/types/staging/resolver_test.go130
-rw-r--r--libgo/go/exp/types/staging/stmt.go473
-rw-r--r--libgo/go/exp/types/staging/testdata/builtins.src258
-rw-r--r--libgo/go/exp/types/staging/testdata/const0.src209
-rw-r--r--libgo/go/exp/types/staging/testdata/conversions.src18
-rw-r--r--libgo/go/exp/types/staging/testdata/decls0.src168
-rw-r--r--libgo/go/exp/types/staging/testdata/decls1.src123
-rw-r--r--libgo/go/exp/types/staging/testdata/decls2a.src66
-rw-r--r--libgo/go/exp/types/staging/testdata/decls2b.src15
-rw-r--r--libgo/go/exp/types/staging/testdata/exports.go89
-rw-r--r--libgo/go/exp/types/staging/testdata/expr0.src135
-rw-r--r--libgo/go/exp/types/staging/testdata/expr1.src7
-rw-r--r--libgo/go/exp/types/staging/testdata/expr2.src7
-rw-r--r--libgo/go/exp/types/staging/testdata/expr3.src115
-rw-r--r--libgo/go/exp/types/staging/testdata/stmt0.src42
-rw-r--r--libgo/go/exp/types/staging/types.go235
-rw-r--r--libgo/go/exp/types/staging/types_test.go181
-rw-r--r--libgo/go/exp/types/staging/universe.go159
-rw-r--r--libgo/go/exp/types/testdata/exports.go5
-rw-r--r--libgo/go/exp/types/testdata/test0.src33
-rw-r--r--libgo/go/exp/types/types.go150
-rw-r--r--libgo/go/exp/types/types_test.go128
-rw-r--r--libgo/go/fmt/fmt_test.go38
-rw-r--r--libgo/go/fmt/format.go55
-rw-r--r--libgo/go/fmt/print.go41
-rw-r--r--libgo/go/fmt/scan.go3
-rw-r--r--libgo/go/fmt/scan_test.go27
-rw-r--r--libgo/go/go/ast/ast.go1
-rw-r--r--libgo/go/go/ast/commentmap.go332
-rw-r--r--libgo/go/go/ast/commentmap_test.go143
-rw-r--r--libgo/go/go/ast/print.go6
-rw-r--r--libgo/go/go/build/build.go47
-rw-r--r--libgo/go/go/build/build_test.go13
-rw-r--r--libgo/go/go/build/deps_test.go9
-rw-r--r--libgo/go/go/build/doc.go2
-rw-r--r--libgo/go/go/build/read.go238
-rw-r--r--libgo/go/go/build/read_test.go226
-rw-r--r--libgo/go/go/doc/example.go191
-rw-r--r--libgo/go/go/doc/reader.go74
-rw-r--r--libgo/go/go/doc/synopsis.go41
-rw-r--r--libgo/go/go/doc/synopsis_test.go5
-rw-r--r--libgo/go/go/doc/testdata/benchmark.go4
-rw-r--r--libgo/go/go/doc/testdata/testing.1.golden2
-rw-r--r--libgo/go/go/parser/interface.go9
-rw-r--r--libgo/go/go/parser/parser.go166
-rw-r--r--libgo/go/go/parser/parser_test.go47
-rw-r--r--libgo/go/go/parser/performance_test.go30
-rw-r--r--libgo/go/go/parser/short_test.go12
-rw-r--r--libgo/go/go/printer/nodes.go45
-rw-r--r--libgo/go/go/printer/printer.go33
-rw-r--r--libgo/go/go/printer/printer_test.go150
-rw-r--r--libgo/go/go/printer/testdata/comments2.golden79
-rw-r--r--libgo/go/go/printer/testdata/comments2.input79
-rw-r--r--libgo/go/go/printer/testdata/declarations.golden29
-rw-r--r--libgo/go/go/printer/testdata/declarations.input29
-rw-r--r--libgo/go/go/printer/testdata/expressions.golden15
-rw-r--r--libgo/go/go/printer/testdata/expressions.input15
-rw-r--r--libgo/go/go/printer/testdata/expressions.raw15
-rw-r--r--libgo/go/go/printer/testdata/statements.golden26
-rw-r--r--libgo/go/go/printer/testdata/statements.input24
-rw-r--r--libgo/go/go/scanner/scanner.go37
-rw-r--r--libgo/go/go/scanner/scanner_test.go116
-rw-r--r--libgo/go/hash/adler32/adler32.go68
-rw-r--r--libgo/go/hash/adler32/adler32_test.go90
-rw-r--r--libgo/go/hash/crc32/crc32.go6
-rw-r--r--libgo/go/hash/crc32/crc32_amd64.go2
-rw-r--r--libgo/go/hash/crc32/crc32_test.go18
-rw-r--r--libgo/go/hash/crc64/crc64.go10
-rw-r--r--libgo/go/hash/crc64/crc64_test.go17
-rw-r--r--libgo/go/hash/fnv/fnv.go32
-rw-r--r--libgo/go/hash/fnv/fnv_test.go34
-rw-r--r--libgo/go/html/entity.go4154
-rw-r--r--libgo/go/html/template/escape.go9
-rw-r--r--libgo/go/html/template/escape_test.go5
-rw-r--r--libgo/go/image/jpeg/dct_test.go291
-rw-r--r--libgo/go/image/jpeg/idct.go80
-rw-r--r--libgo/go/image/jpeg/reader.go59
-rw-r--r--libgo/go/image/jpeg/writer_test.go28
-rw-r--r--libgo/go/image/png/paeth.go70
-rw-r--r--libgo/go/image/png/paeth_test.go91
-rw-r--r--libgo/go/image/png/reader.go65
-rw-r--r--libgo/go/image/png/reader_test.go54
-rw-r--r--libgo/go/image/png/writer.go105
-rw-r--r--libgo/go/image/png/writer_test.go45
-rw-r--r--libgo/go/image/ycbcr.go9
-rw-r--r--libgo/go/image/ycbcr_test.go1
-rw-r--r--libgo/go/io/ioutil/blackhole.go13
-rw-r--r--libgo/go/io/ioutil/blackhole_race.go13
-rw-r--r--libgo/go/io/ioutil/ioutil.go5
-rw-r--r--libgo/go/io/ioutil/tempfile.go4
-rw-r--r--libgo/go/math/acosh.go2
-rw-r--r--libgo/go/math/all_test.go4
-rw-r--r--libgo/go/math/asinh.go2
-rw-r--r--libgo/go/math/atan.go99
-rw-r--r--libgo/go/math/atanh.go2
-rw-r--r--libgo/go/math/big/arith_test.go86
-rw-r--r--libgo/go/math/big/calibrate_test.go42
-rw-r--r--libgo/go/math/big/gcd_test.go47
-rw-r--r--libgo/go/math/big/int.go91
-rw-r--r--libgo/go/math/big/int_test.go148
-rw-r--r--libgo/go/math/big/nat.go167
-rw-r--r--libgo/go/math/big/nat_test.go92
-rw-r--r--libgo/go/math/big/rat.go118
-rw-r--r--libgo/go/math/big/rat_test.go90
-rw-r--r--libgo/go/math/cbrt.go2
-rw-r--r--libgo/go/math/copysign.go2
-rw-r--r--libgo/go/math/erf.go4
-rw-r--r--libgo/go/math/gamma.go27
-rw-r--r--libgo/go/math/hypot.go2
-rw-r--r--libgo/go/math/logb.go4
-rw-r--r--libgo/go/math/rand/rand_test.go13
-rw-r--r--libgo/go/math/sincos.go2
-rw-r--r--libgo/go/math/tanh.go89
-rw-r--r--libgo/go/mime/type_windows.go9
-rw-r--r--libgo/go/net/cgo_bsd.go4
-rw-r--r--libgo/go/net/cgo_linux.go8
-rw-r--r--libgo/go/net/cgo_netbsd.go14
-rw-r--r--libgo/go/net/cgo_unix.go10
-rw-r--r--libgo/go/net/dial.go2
-rw-r--r--libgo/go/net/dial_test.go2
-rw-r--r--libgo/go/net/dialgoogle_test.go11
-rw-r--r--libgo/go/net/dnsclient_unix.go28
-rw-r--r--libgo/go/net/dnsconfig_unix.go (renamed from libgo/go/net/dnsconfig.go)0
-rw-r--r--libgo/go/net/fd_unix.go (renamed from libgo/go/net/fd.go)97
-rw-r--r--libgo/go/net/fd_windows.go2
-rw-r--r--libgo/go/net/file_unix.go (renamed from libgo/go/net/file.go)14
-rw-r--r--libgo/go/net/http/client.go31
-rw-r--r--libgo/go/net/http/client_test.go6
-rw-r--r--libgo/go/net/http/cookie.go7
-rw-r--r--libgo/go/net/http/fs.go64
-rw-r--r--libgo/go/net/http/fs_test.go192
-rw-r--r--libgo/go/net/http/header.go85
-rw-r--r--libgo/go/net/http/header_test.go130
-rw-r--r--libgo/go/net/http/httptest/recorder.go24
-rw-r--r--libgo/go/net/http/httptest/recorder_test.go90
-rw-r--r--libgo/go/net/http/httputil/dump.go2
-rw-r--r--libgo/go/net/http/httputil/reverseproxy.go58
-rw-r--r--libgo/go/net/http/httputil/reverseproxy_test.go84
-rw-r--r--libgo/go/net/http/lex.go206
-rw-r--r--libgo/go/net/http/lex_test.go65
-rw-r--r--libgo/go/net/http/pprof/pprof.go4
-rw-r--r--libgo/go/net/http/request.go191
-rw-r--r--libgo/go/net/http/request_test.go40
-rw-r--r--libgo/go/net/http/response.go6
-rw-r--r--libgo/go/net/http/serve_test.go241
-rw-r--r--libgo/go/net/http/server.go133
-rw-r--r--libgo/go/net/http/server_test.go95
-rw-r--r--libgo/go/net/http/transfer.go10
-rw-r--r--libgo/go/net/http/transport.go134
-rw-r--r--libgo/go/net/http/transport_test.go68
-rw-r--r--libgo/go/net/interface_test.go10
-rw-r--r--libgo/go/net/ipraw_test.go4
-rw-r--r--libgo/go/net/iprawsock_plan9.go97
-rw-r--r--libgo/go/net/iprawsock_posix.go128
-rw-r--r--libgo/go/net/ipsock.go13
-rw-r--r--libgo/go/net/ipsock_plan9.go51
-rw-r--r--libgo/go/net/ipsock_posix.go5
-rw-r--r--libgo/go/net/lookup.go (renamed from libgo/go/net/doc.go)0
-rw-r--r--libgo/go/net/lookup_test.go12
-rw-r--r--libgo/go/net/mail/message.go12
-rw-r--r--libgo/go/net/mail/message_test.go17
-rw-r--r--libgo/go/net/multicast_posix_test.go (renamed from libgo/go/net/multicast_test.go)71
-rw-r--r--libgo/go/net/net_test.go82
-rw-r--r--libgo/go/net/newpollserver_unix.go (renamed from libgo/go/net/newpollserver.go)2
-rw-r--r--libgo/go/net/port.go73
-rw-r--r--libgo/go/net/port_unix.go69
-rw-r--r--libgo/go/net/rpc/client.go29
-rw-r--r--libgo/go/net/rpc/jsonrpc/all_test.go53
-rw-r--r--libgo/go/net/rpc/jsonrpc/server.go13
-rw-r--r--libgo/go/net/sendfile_freebsd.go105
-rw-r--r--libgo/go/net/sendfile_linux.go2
-rw-r--r--libgo/go/net/sendfile_stub.go2
-rw-r--r--libgo/go/net/sock_posix.go (renamed from libgo/go/net/sock.go)34
-rw-r--r--libgo/go/net/sockopt_posix.go (renamed from libgo/go/net/sockopt.go)0
-rw-r--r--libgo/go/net/sockoptip.go219
-rw-r--r--libgo/go/net/sockoptip_bsd.go36
-rw-r--r--libgo/go/net/sockoptip_darwin.go90
-rw-r--r--libgo/go/net/sockoptip_freebsd.go92
-rw-r--r--libgo/go/net/sockoptip_linux.go101
-rw-r--r--libgo/go/net/sockoptip_netbsd.go39
-rw-r--r--libgo/go/net/sockoptip_openbsd.go90
-rw-r--r--libgo/go/net/sockoptip_posix.go73
-rw-r--r--libgo/go/net/sockoptip_windows.go61
-rw-r--r--libgo/go/net/tcp_test.go118
-rw-r--r--libgo/go/net/tcpsock_plan9.go54
-rw-r--r--libgo/go/net/tcpsock_posix.go120
-rw-r--r--libgo/go/net/textproto/reader.go31
-rw-r--r--libgo/go/net/textproto/reader_test.go17
-rw-r--r--libgo/go/net/textproto/textproto.go26
-rw-r--r--libgo/go/net/udpsock.go4
-rw-r--r--libgo/go/net/udpsock_plan9.go68
-rw-r--r--libgo/go/net/udpsock_posix.go155
-rw-r--r--libgo/go/net/unicast_posix_test.go (renamed from libgo/go/net/unicast_test.go)89
-rw-r--r--libgo/go/net/unixsock_plan9.go158
-rw-r--r--libgo/go/net/unixsock_posix.go114
-rw-r--r--libgo/go/net/url/url.go28
-rw-r--r--libgo/go/net/url/url_test.go29
-rw-r--r--libgo/go/os/dir.go2
-rw-r--r--libgo/go/os/dir_plan9.go34
-rw-r--r--libgo/go/os/error_test.go24
-rw-r--r--libgo/go/os/exec.go8
-rw-r--r--libgo/go/os/exec/exec_test.go5
-rw-r--r--libgo/go/os/exec_plan9.go40
-rw-r--r--libgo/go/os/exec_posix.go8
-rw-r--r--libgo/go/os/file_plan9.go54
-rw-r--r--libgo/go/os/os_test.go29
-rw-r--r--libgo/go/os/path_plan9.go4
-rw-r--r--libgo/go/os/path_test.go12
-rw-r--r--libgo/go/os/stat_plan9.go24
-rw-r--r--libgo/go/os/user/lookup_unix.go2
-rw-r--r--libgo/go/os/user/lookup_windows.go16
-rw-r--r--libgo/go/os/user/user_test.go8
-rw-r--r--libgo/go/path/filepath/path.go102
-rw-r--r--libgo/go/path/filepath/path_plan9.go8
-rw-r--r--libgo/go/path/filepath/path_test.go30
-rw-r--r--libgo/go/path/filepath/path_unix.go8
-rw-r--r--libgo/go/path/filepath/path_windows.go22
-rw-r--r--libgo/go/path/filepath/symlink_windows.go10
-rw-r--r--libgo/go/path/path.go80
-rw-r--r--libgo/go/path/path_test.go21
-rw-r--r--libgo/go/reflect/all_test.go1082
-rw-r--r--libgo/go/reflect/deepequal.go1
-rw-r--r--libgo/go/reflect/example_test.go52
-rw-r--r--libgo/go/reflect/export_test.go16
-rw-r--r--libgo/go/reflect/makefunc.go81
-rw-r--r--libgo/go/reflect/type.go241
-rw-r--r--libgo/go/reflect/value.go544
-rw-r--r--libgo/go/regexp/syntax/doc.go127
-rw-r--r--libgo/go/regexp/syntax/parse.go4
-rw-r--r--libgo/go/runtime/complex_test.go67
-rw-r--r--libgo/go/runtime/crash_cgo_test.go15
-rw-r--r--libgo/go/runtime/crash_test.go109
-rw-r--r--libgo/go/runtime/debug.go25
-rw-r--r--libgo/go/runtime/debug/stack_test.go2
-rw-r--r--libgo/go/runtime/error.go32
-rw-r--r--libgo/go/runtime/export_test.go36
-rw-r--r--libgo/go/runtime/gc_test.go19
-rw-r--r--libgo/go/runtime/iface_test.go138
-rw-r--r--libgo/go/runtime/lfstack_test.go130
-rw-r--r--libgo/go/runtime/parfor_test.go125
-rw-r--r--libgo/go/runtime/pprof/pprof.go76
-rw-r--r--libgo/go/runtime/proc_test.go26
-rw-r--r--libgo/go/runtime/string_test.go45
-rw-r--r--libgo/go/runtime/vlop_arm_test.go70
-rw-r--r--libgo/go/strconv/atof.go303
-rw-r--r--libgo/go/strconv/atof_test.go128
-rw-r--r--libgo/go/strconv/decimal.go2
-rw-r--r--libgo/go/strconv/extfloat.go336
-rw-r--r--libgo/go/strconv/ftoa.go157
-rw-r--r--libgo/go/strconv/ftoa_test.go74
-rw-r--r--libgo/go/strconv/itoa_test.go34
-rw-r--r--libgo/go/strconv/strconv_test.go67
-rw-r--r--libgo/go/strings/export_test.go36
-rw-r--r--libgo/go/strings/replace.go416
-rw-r--r--libgo/go/strings/replace_test.go437
-rw-r--r--libgo/go/strings/search.go124
-rw-r--r--libgo/go/strings/search_test.go90
-rw-r--r--libgo/go/strings/strings_test.go44
-rw-r--r--libgo/go/sync/atomic/64bit_linux_arm.go36
-rw-r--r--libgo/go/sync/atomic/atomic_test.go140
-rw-r--r--libgo/go/sync/atomic/doc.go48
-rw-r--r--libgo/go/sync/atomic/race.go191
-rw-r--r--libgo/go/sync/cond.go18
-rw-r--r--libgo/go/sync/mutex.go16
-rw-r--r--libgo/go/sync/once.go2
-rw-r--r--libgo/go/sync/once_test.go29
-rw-r--r--libgo/go/sync/race.go34
-rw-r--r--libgo/go/sync/race0.go28
-rw-r--r--libgo/go/sync/rwmutex.go36
-rw-r--r--libgo/go/sync/waitgroup.go29
-rw-r--r--libgo/go/syscall/creds_test.go109
-rw-r--r--libgo/go/syscall/env_windows.go6
-rw-r--r--libgo/go/syscall/exec_unix.go30
-rw-r--r--libgo/go/syscall/exec_windows.go16
-rw-r--r--libgo/go/syscall/libcall_posix.go10
-rw-r--r--libgo/go/syscall/mksyscall.awk22
-rw-r--r--libgo/go/syscall/passfd_test.go151
-rw-r--r--libgo/go/syscall/race0.go19
-rw-r--r--libgo/go/syscall/security_windows.go10
-rw-r--r--libgo/go/syscall/syscall.go16
-rw-r--r--libgo/go/syscall/syscall_unix.go17
-rw-r--r--libgo/go/testing/benchmark.go66
-rw-r--r--libgo/go/testing/testing.go58
-rw-r--r--libgo/go/text/scanner/scanner.go23
-rw-r--r--libgo/go/text/scanner/scanner_test.go10
-rw-r--r--libgo/go/text/template/doc.go7
-rw-r--r--libgo/go/text/template/exec.go192
-rw-r--r--libgo/go/text/template/exec_test.go86
-rw-r--r--libgo/go/text/template/funcs.go14
-rw-r--r--libgo/go/text/template/parse/lex.go240
-rw-r--r--libgo/go/text/template/parse/lex_test.go384
-rw-r--r--libgo/go/text/template/parse/node.go242
-rw-r--r--libgo/go/text/template/parse/parse.go285
-rw-r--r--libgo/go/text/template/parse/parse_test.go87
-rw-r--r--libgo/go/text/template/template.go3
-rw-r--r--libgo/go/time/format.go405
-rw-r--r--libgo/go/time/time.go54
-rw-r--r--libgo/go/time/time_test.go122
-rw-r--r--libgo/go/time/zoneinfo.go14
-rw-r--r--libgo/go/time/zoneinfo_read.go2
-rw-r--r--libgo/go/unicode/digit.go2
-rw-r--r--libgo/go/unicode/graphic.go10
-rw-r--r--libgo/go/unicode/letter.go74
-rw-r--r--libgo/go/unicode/letter_test.go118
-rw-r--r--libgo/go/unicode/tables.go38
-rw-r--r--libgo/go/unicode/utf8/example_test.go192
-rw-r--r--libgo/go/unicode/utf8/utf8.go54
-rw-r--r--libgo/go/unicode/utf8/utf8_test.go101
-rwxr-xr-xlibgo/merge.sh2
-rw-r--r--libgo/runtime/chan.c295
-rw-r--r--libgo/runtime/cpuprof.c2
-rw-r--r--libgo/runtime/go-rune.c35
-rw-r--r--libgo/runtime/go-signal.c19
-rw-r--r--libgo/runtime/go-trampoline.c4
-rw-r--r--libgo/runtime/lfstack.c66
-rw-r--r--libgo/runtime/malloc.goc293
-rw-r--r--libgo/runtime/malloc.h97
-rw-r--r--libgo/runtime/mcache.c5
-rw-r--r--libgo/runtime/mcentral.c41
-rw-r--r--libgo/runtime/mfinal.c6
-rw-r--r--libgo/runtime/mgc0.c641
-rw-r--r--libgo/runtime/mheap.c36
-rw-r--r--libgo/runtime/mprof.goc179
-rw-r--r--libgo/runtime/panic.c115
-rw-r--r--libgo/runtime/parfor.c232
-rw-r--r--libgo/runtime/print.c11
-rw-r--r--libgo/runtime/proc.c306
-rw-r--r--libgo/runtime/race.h30
-rw-r--r--libgo/runtime/runtime.c127
-rw-r--r--libgo/runtime/runtime.h116
-rw-r--r--libgo/runtime/runtime1.goc4
-rw-r--r--libgo/runtime/sema.goc62
-rw-r--r--libgo/runtime/string.goc14
-rw-r--r--libgo/runtime/time.goc38
-rwxr-xr-xlibgo/testsuite/gotest16
554 files changed, 56868 insertions, 12562 deletions
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index fa61808ec3c..defa208a582 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -1251,6 +1251,7 @@ Gogo::clear_file_scope()
this->package_->bindings()->clear_file_scope();
// Warn about packages which were imported but not used.
+ bool quiet = saw_errors();
for (Packages::iterator p = this->packages_.begin();
p != this->packages_.end();
++p)
@@ -1260,7 +1261,7 @@ Gogo::clear_file_scope()
&& package->is_imported()
&& !package->used()
&& !package->uses_sink_alias()
- && !saw_errors())
+ && !quiet)
error_at(package->location(), "imported and not used: %s",
Gogo::message_name(package->package_name()).c_str());
package->clear_is_imported();
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index 9d190302057..3da2f3dae26 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -32,6 +32,8 @@ enum Runtime_function_type
RFT_BOOLPTR,
// Go type int, C type int.
RFT_INT,
+ // Go type int32, C type int32_t.
+ RFT_INT32,
// Go type int64, C type int64_t.
RFT_INT64,
// Go type uint64, C type uint64_t.
@@ -102,6 +104,10 @@ runtime_function_type(Runtime_function_type bft)
t = Type::lookup_integer_type("int");
break;
+ case RFT_INT32:
+ t = Type::lookup_integer_type("int32");
+ break;
+
case RFT_INT64:
t = Type::lookup_integer_type("int64");
break;
@@ -206,6 +212,7 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
case RFT_BOOL:
case RFT_BOOLPTR:
case RFT_INT:
+ case RFT_INT32:
case RFT_INT64:
case RFT_UINT64:
case RFT_UINTPTR:
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 7dda5398cfb..b9492dc8af2 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -148,27 +148,28 @@ DEF_GO_RUNTIME(CHANRECV2, "runtime.chanrecv2", P3(TYPE, CHAN, POINTER),
// Start building a select statement.
-DEF_GO_RUNTIME(NEWSELECT, "runtime.newselect", P1(INT), R1(POINTER))
+DEF_GO_RUNTIME(NEWSELECT, "runtime.newselect", P1(INT32), R1(POINTER))
// Add a default clause to a select statement.
-DEF_GO_RUNTIME(SELECTDEFAULT, "runtime.selectdefault", P2(POINTER, INT), R0())
+DEF_GO_RUNTIME(SELECTDEFAULT, "runtime.selectdefault",
+ P2(POINTER, INT32), R0())
// Add a send clause to a select statement.
DEF_GO_RUNTIME(SELECTSEND, "runtime.selectsend",
- P4(POINTER, CHAN, POINTER, INT), R0())
+ P4(POINTER, CHAN, POINTER, INT32), R0())
// Add a receive clause to a select statement, for a clause which does
// not check whether the channel is closed.
DEF_GO_RUNTIME(SELECTRECV, "runtime.selectrecv",
- P4(POINTER, CHAN, POINTER, INT), R0())
+ P4(POINTER, CHAN, POINTER, INT32), R0())
// Add a receive clause to a select statement, for a clause which does
// check whether the channel is closed.
DEF_GO_RUNTIME(SELECTRECV2, "runtime.selectrecv2",
- P5(POINTER, CHAN, POINTER, BOOLPTR, INT), R0())
+ P5(POINTER, CHAN, POINTER, BOOLPTR, INT32), R0())
// Run a select, returning the index of the selected clause.
-DEF_GO_RUNTIME(SELECTGO, "runtime.selectgo", P1(POINTER), R1(INT))
+DEF_GO_RUNTIME(SELECTGO, "runtime.selectgo", P1(POINTER), R1(INT32))
// Panic.
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index af34670aee0..ad249f6ac57 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -4841,6 +4841,8 @@ Select_clauses::get_backend(Translate_context* context,
std::vector<std::vector<Bexpression*> > cases(count);
std::vector<Bstatement*> clauses(count);
+ Type* int32_type = Type::lookup_integer_type("int32");
+
int i = 0;
for (Clauses::iterator p = this->clauses_.begin();
p != this->clauses_.end();
@@ -4849,7 +4851,8 @@ Select_clauses::get_backend(Translate_context* context,
int index = p->index();
mpz_t ival;
mpz_init_set_ui(ival, index);
- Expression* index_expr = Expression::make_integer(&ival, NULL, location);
+ Expression* index_expr = Expression::make_integer(&ival, int32_type,
+ location);
mpz_clear(ival);
cases[i].push_back(tree_to_expr(index_expr->get_tree(context)));
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug358.go b/gcc/testsuite/go.test/test/fixedbugs/bug358.go
index 6a008484f4f..063c2e0bf8d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug358.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug358.go
@@ -12,7 +12,7 @@ package main
import (
"io/ioutil" // GCCGO_ERROR "imported and not used"
"net/http"
- "os"
+ "os" // GCCGO_ERROR "imported and not used"
)
func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug369.go b/gcc/testsuite/go.test/test/fixedbugs/bug369.go
index 2ee8568e044..6d526228b8a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug369.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug369.go
@@ -38,9 +38,9 @@ func BenchmarkSlowNonASCII(b *testing.B) {
}
func main() {
- os.Args = []string{os.Args[0], "-test.benchtime=0.1"}
+ os.Args = []string{os.Args[0], "-test.benchtime=100ms"}
flag.Parse()
-
+
rslow := testing.Benchmark(BenchmarkSlowNonASCII)
rfast := testing.Benchmark(BenchmarkFastNonASCII)
tslow := rslow.NsPerOp()
diff --git a/libgo/MERGE b/libgo/MERGE
index 89116d1feef..640cfb866f3 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-2d8bc3c94ecb
+291d9f1baf75
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index b2eb39e5972..a0565b80b3a 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -230,6 +230,21 @@ toolexeclibgoexp_DATA = \
exp/types.gox \
exp/utf8string.gox
+toolexeclibgoexphtmldir = $(toolexeclibgoexpdir)/html
+
+toolexeclibgoexphtml_DATA = \
+ exp/html/atom.gox
+
+toolexeclibgoexplocaledir = $(toolexeclibgoexpdir)/locale
+
+toolexeclibgoexplocale_DATA = \
+ exp/locale/collate.gox
+
+toolexeclibgoexplocalecollatedir = $(toolexeclibgoexplocaledir)/collate
+
+toolexeclibgoexplocalecollate_DATA = \
+ exp/locale/collate/build.gox
+
toolexeclibgogodir = $(toolexeclibgodir)/go
toolexeclibgogo_DATA = \
@@ -483,6 +498,7 @@ runtime_files = \
runtime/go-unwind.c \
runtime/chan.c \
runtime/cpuprof.c \
+ runtime/lfstack.c \
$(runtime_lock_files) \
runtime/mcache.c \
runtime/mcentral.c \
@@ -492,6 +508,8 @@ runtime_files = \
runtime/mgc0.c \
runtime/mheap.c \
runtime/msize.c \
+ runtime/panic.c \
+ runtime/parfor.c \
runtime/print.c \
runtime/proc.c \
runtime/runtime.c \
@@ -656,16 +674,16 @@ go_net_newpollserver_file = go/net/newpollserver_rtems.go
else # !LIBGO_IS_RTEMS
if LIBGO_IS_LINUX
go_net_fd_os_file = go/net/fd_linux.go
-go_net_newpollserver_file = go/net/newpollserver.go
+go_net_newpollserver_file = go/net/newpollserver_unix.go
else # !LIBGO_IS_LINUX && !LIBGO_IS_RTEMS
if LIBGO_IS_NETBSD
go_net_fd_os_file = go/net/fd_netbsd.go
-go_net_newpollserver_file = go/net/newpollserver.go
+go_net_newpollserver_file = go/net/newpollserver_unix.go
else # !LIBGO_IS_NETBSD && !LIBGO_IS_LINUX && !LIBGO_IS_RTEMS
# By default use select with pipes. Most systems should have
# something better.
go_net_fd_os_file = go/net/fd_select.go
-go_net_newpollserver_file = go/net/newpollserver.go
+go_net_newpollserver_file = go/net/newpollserver_unix.go
endif # !LIBGO_IS_NETBSD
endif # !LIBGO_IS_LINUX
endif # !LIBGO_IS_RTEMS
@@ -674,13 +692,13 @@ if LIBGO_IS_LINUX
go_net_cgo_file = go/net/cgo_linux.go
go_net_sock_file = go/net/sock_linux.go
go_net_sockopt_file = go/net/sockopt_linux.go
-go_net_sockoptip_file = go/net/sockoptip_linux.go
+go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
else
if LIBGO_IS_IRIX
go_net_cgo_file = go/net/cgo_linux.go
go_net_sock_file = go/net/sock_linux.go
go_net_sockopt_file = go/net/sockopt_linux.go
-go_net_sockoptip_file = go/net/sockoptip_linux.go
+go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
else
if LIBGO_IS_SOLARIS
go_net_cgo_file = go/net/cgo_linux.go
@@ -692,12 +710,19 @@ if LIBGO_IS_FREEBSD
go_net_cgo_file = go/net/cgo_bsd.go
go_net_sock_file = go/net/sock_bsd.go
go_net_sockopt_file = go/net/sockopt_bsd.go
-go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_freebsd.go
+go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
+else
+if LIBGO_IS_NETBSD
+go_net_cgo_file = go/net/cgo_netbsd.go
+go_net_sock_file = go/net/sock_bsd.go
+go_net_sockopt_file = go/net/sockopt_bsd.go
+go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
else
go_net_cgo_file = go/net/cgo_bsd.go
go_net_sock_file = go/net/sock_bsd.go
go_net_sockopt_file = go/net/sockopt_bsd.go
-go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_netbsd.go
+go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
+endif
endif
endif
endif
@@ -706,8 +731,12 @@ endif
if LIBGO_IS_LINUX
go_net_sendfile_file = go/net/sendfile_linux.go
else
+if LIBGO_IS_FREEBSD
+go_net_sendfile_file = go/net/sendfile_freebsd.go
+else
go_net_sendfile_file = go/net/sendfile_stub.go
endif
+endif
if LIBGO_IS_LINUX
go_net_interface_file = go/net/interface_linux.go
@@ -725,13 +754,12 @@ go_net_files = \
go/net/dial.go \
go/net/dnsclient.go \
go/net/dnsclient_unix.go \
- go/net/dnsconfig.go \
+ go/net/dnsconfig_unix.go \
go/net/dnsmsg.go \
- go/net/doc.go \
$(go_net_newpollserver_file) \
- go/net/fd.go \
+ go/net/fd_unix.go \
$(go_net_fd_os_file) \
- go/net/file.go \
+ go/net/file_unix.go \
go/net/hosts.go \
go/net/interface.go \
$(go_net_interface_file) \
@@ -740,6 +768,7 @@ go_net_files = \
go/net/iprawsock_posix.go \
go/net/ipsock.go \
go/net/ipsock_posix.go \
+ go/net/lookup.go \
go/net/lookup_unix.go \
go/net/mac.go \
go/net/net.go \
@@ -747,12 +776,12 @@ go_net_files = \
go/net/parse.go \
go/net/pipe.go \
go/net/port.go \
+ go/net/port_unix.go \
$(go_net_sendfile_file) \
- go/net/sock.go \
+ go/net/sock_posix.go \
$(go_net_sock_file) \
- go/net/sockopt.go \
+ go/net/sockopt_posix.go \
$(go_net_sockopt_file) \
- go/net/sockoptip.go \
$(go_net_sockoptip_file) \
go/net/tcpsock.go \
go/net/tcpsock_posix.go \
@@ -831,6 +860,7 @@ go_path_files = \
go_reflect_files = \
go/reflect/deepequal.go \
+ go/reflect/makefunc.go \
go/reflect/type.go \
go/reflect/value.go
@@ -882,12 +912,14 @@ go_strconv_files = \
go_strings_files = \
go/strings/reader.go \
go/strings/replace.go \
+ go/strings/search.go \
go/strings/strings.go
go_sync_files = \
go/sync/cond.go \
go/sync/mutex.go \
go/sync/once.go \
+ go/sync/race0.go \
go/sync/runtime.go \
go/sync/rwmutex.go \
go/sync/waitgroup.go
@@ -930,11 +962,28 @@ go_unicode_files = \
go/unicode/letter.go \
go/unicode/tables.go
+if LIBGO_IS_LINUX
+archive_tar_atim_file = go/archive/tar/stat_atim.go
+endif
+if LIBGO_IS_OPENBSD
+archive_tar_atim_file = go/archive/tar/stat_atim.go
+endif
+if LIBGO_IS_DARWIN
+archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+endif
+if LIBGO_IS_FREEBSD
+archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+endif
+if LIBGO_IS_NETBSD
+archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+endif
go_archive_tar_files = \
go/archive/tar/common.go \
go/archive/tar/reader.go \
- go/archive/tar/writer.go
+ go/archive/tar/stat_unix.go \
+ go/archive/tar/writer.go \
+ $(archive_tar_atim_file)
go_archive_zip_files = \
go/archive/zip/reader.go \
@@ -948,6 +997,7 @@ go_compress_bzip2_files = \
go/compress/bzip2/move_to_front.go
go_compress_flate_files = \
+ go/compress/flate/copy.go \
go/compress/flate/deflate.go \
go/compress/flate/huffman_bit_writer.go \
go/compress/flate/huffman_code.go \
@@ -979,6 +1029,7 @@ go_container_ring_files = \
go_crypto_aes_files = \
go/crypto/aes/block.go \
go/crypto/aes/cipher.go \
+ go/crypto/aes/cipher_generic.go \
go/crypto/aes/const.go
go_crypto_cipher_files = \
go/crypto/cipher/cbc.go \
@@ -1033,9 +1084,11 @@ go_crypto_tls_files = \
go/crypto/tls/handshake_server.go \
go/crypto/tls/key_agreement.go \
go/crypto/tls/prf.go \
+ go/crypto/tls/ticket.go \
go/crypto/tls/tls.go
go_crypto_x509_files = \
go/crypto/x509/cert_pool.go \
+ go/crypto/x509/pem_decrypt.go \
go/crypto/x509/pkcs1.go \
go/crypto/x509/pkcs8.go \
go/crypto/x509/root.go \
@@ -1130,8 +1183,26 @@ go_exp_html_files = \
go/exp/html/parse.go \
go/exp/html/render.go \
go/exp/html/token.go
+go_exp_html_atom_files = \
+ go/exp/html/atom/atom.go \
+ go/exp/html/atom/table.go
go_exp_inotify_files = \
go/exp/inotify/inotify_linux.go
+go_exp_locale_collate_files = \
+ go/exp/locale/collate/colelem.go \
+ go/exp/locale/collate/collate.go \
+ go/exp/locale/collate/contract.go \
+ go/exp/locale/collate/export.go \
+ go/exp/locale/collate/table.go \
+ go/exp/locale/collate/tables.go \
+ go/exp/locale/collate/trie.go
+go_exp_locale_collate_build_files = \
+ go/exp/locale/collate/build/builder.go \
+ go/exp/locale/collate/build/colelem.go \
+ go/exp/locale/collate/build/contract.go \
+ go/exp/locale/collate/build/order.go \
+ go/exp/locale/collate/build/table.go \
+ go/exp/locale/collate/build/trie.go
go_exp_norm_files = \
go/exp/norm/composition.go \
go/exp/norm/forminfo.go \
@@ -1161,6 +1232,7 @@ go_exp_utf8string_files = \
go_go_ast_files = \
go/go/ast/ast.go \
+ go/go/ast/commentmap.go \
go/go/ast/filter.go \
go/go/ast/import.go \
go/go/ast/print.go \
@@ -1170,6 +1242,7 @@ go_go_ast_files = \
go_go_build_files = \
go/go/build/build.go \
go/go/build/doc.go \
+ go/go/build/read.go \
syslist.go
go_go_doc_files = \
go/go/doc/comment.go \
@@ -1235,6 +1308,7 @@ go_image_jpeg_files = \
go/image/jpeg/writer.go
go_image_png_files = \
+ go/image/png/paeth.go \
go/image/png/reader.go \
go/image/png/writer.go
@@ -1243,6 +1317,7 @@ go_index_suffixarray_files = \
go/index/suffixarray/suffixarray.go
go_io_ioutil_files = \
+ go/io/ioutil/blackhole.go \
go/io/ioutil/ioutil.go \
go/io/ioutil/tempfile.go
@@ -1358,6 +1433,7 @@ go_path_filepath_files = \
go_regexp_syntax_files = \
go/regexp/syntax/compile.go \
+ go/regexp/syntax/doc.go \
go/regexp/syntax/parse.go \
go/regexp/syntax/perl_groups.go \
go/regexp/syntax/prog.go \
@@ -1544,6 +1620,7 @@ go_base_syscall_files = \
go/syscall/syscall_errno.go \
go/syscall/libcall_support.go \
go/syscall/libcall_posix.go \
+ go/syscall/race0.go \
go/syscall/socket.go \
go/syscall/sockcmsg_unix.go \
go/syscall/str.go \
@@ -1714,6 +1791,9 @@ libgo_go_objs = \
encoding/xml.lo \
exp/ebnf.lo \
exp/html.lo \
+ exp/html/atom.lo \
+ exp/locale/collate.lo \
+ exp/locale/collate/build.lo \
exp/norm.lo \
exp/proxy.lo \
exp/terminal.lo \
@@ -2562,6 +2642,33 @@ exp/html/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: exp/html/check
+@go_include@ exp/html/atom.lo.dep
+exp/html/atom.lo.dep: $(go_exp_html_atom_files)
+ $(BUILDDEPS)
+exp/html/atom.lo: $(go_exp_html_atom_files)
+ $(BUILDPACKAGE)
+exp/html/atom/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: exp/html/atom/check
+
+@go_include@ exp/locale/collate.lo.dep
+exp/locale/collate.lo.dep: $(go_exp_locale_collate_files)
+ $(BUILDDEPS)
+exp/locale/collate.lo: $(go_exp_locale_collate_files)
+ $(BUILDPACKAGE)
+exp/locale/collate/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: exp/locale/collate/check
+
+@go_include@ exp/locale/collate/build.lo.dep
+exp/locale/collate/build.lo.dep: $(go_exp_locale_collate_build_files)
+ $(BUILDDEPS)
+exp/locale/collate/build.lo: $(go_exp_locale_collate_build_files)
+ $(BUILDPACKAGE)
+exp/locale/collate/build/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: exp/locale/collate/build/check
+
@go_include@ exp/norm.lo.dep
exp/norm.lo.dep: $(go_exp_norm_files)
$(BUILDDEPS)
@@ -3142,6 +3249,9 @@ syscall/signame.lo: go/syscall/signame.c
syscall/wait.lo: go/syscall/wait.c
@$(MKDIR_P) syscall
$(LTCOMPILE) -c -o $@ $<
+syscall/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: syscall/check
# How to build a .gox file from a .lo file.
BUILDGOX = \
@@ -3310,8 +3420,14 @@ exp/ebnf.gox: exp/ebnf.lo
$(BUILDGOX)
exp/html.gox: exp/html.lo
$(BUILDGOX)
+exp/html/atom.gox: exp/html/atom.lo
+ $(BUILDGOX)
exp/inotify.gox: exp/inotify.lo
$(BUILDGOX)
+exp/locale/collate.gox: exp/locale/collate.lo
+ $(BUILDGOX)
+exp/locale/collate/build.gox: exp/locale/collate/build.lo
+ $(BUILDGOX)
exp/norm.gox: exp/norm.lo
$(BUILDGOX)
exp/proxy.gox: exp/proxy.lo
@@ -3484,6 +3600,7 @@ TEST_PACKAGES = \
strconv/check \
strings/check \
sync/check \
+ syscall/check \
time/check \
unicode/check \
archive/tar/check \
@@ -3532,10 +3649,14 @@ TEST_PACKAGES = \
encoding/xml/check \
exp/ebnf/check \
exp/html/check \
+ exp/html/atom/check \
$(exp_inotify_check) \
+ exp/locale/collate/check \
+ exp/locale/collate/build/check \
exp/norm/check \
exp/proxy/check \
exp/terminal/check \
+ exp/types/check \
exp/utf8string/check \
html/template/check \
go/ast/check \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 59705642926..48228231972 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -101,6 +101,9 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibgodebugdir)" \
"$(DESTDIR)$(toolexeclibgoencodingdir)" \
"$(DESTDIR)$(toolexeclibgoexpdir)" \
+ "$(DESTDIR)$(toolexeclibgoexphtmldir)" \
+ "$(DESTDIR)$(toolexeclibgoexplocaledir)" \
+ "$(DESTDIR)$(toolexeclibgoexplocalecollatedir)" \
"$(DESTDIR)$(toolexeclibgogodir)" \
"$(DESTDIR)$(toolexeclibgohashdir)" \
"$(DESTDIR)$(toolexeclibgohtmldir)" \
@@ -151,24 +154,25 @@ am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
encoding/base32.lo encoding/base64.lo encoding/binary.lo \
encoding/csv.lo encoding/gob.lo encoding/hex.lo \
encoding/json.lo encoding/pem.lo encoding/xml.lo exp/ebnf.lo \
- exp/html.lo exp/norm.lo exp/proxy.lo exp/terminal.lo \
- exp/types.lo exp/utf8string.lo html/template.lo go/ast.lo \
- go/build.lo go/doc.lo go/parser.lo go/printer.lo go/scanner.lo \
- go/token.lo hash/adler32.lo hash/crc32.lo hash/crc64.lo \
- hash/fnv.lo net/http/cgi.lo net/http/fcgi.lo \
- net/http/httptest.lo net/http/httputil.lo net/http/pprof.lo \
- image/color.lo image/draw.lo image/gif.lo image/jpeg.lo \
- image/png.lo index/suffixarray.lo io/ioutil.lo log/syslog.lo \
- log/syslog/syslog_c.lo math/big.lo math/cmplx.lo math/rand.lo \
- mime/multipart.lo net/http.lo net/mail.lo net/rpc.lo \
- net/smtp.lo net/textproto.lo net/url.lo old/netchan.lo \
- old/regexp.lo old/template.lo os/exec.lo $(am__DEPENDENCIES_1) \
- os/signal.lo os/user.lo path/filepath.lo regexp/syntax.lo \
- net/rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
- sync/atomic.lo sync/atomic_c.lo text/scanner.lo \
- text/tabwriter.lo text/template.lo text/template/parse.lo \
- testing/iotest.lo testing/quick.lo unicode/utf16.lo \
- unicode/utf8.lo
+ exp/html.lo exp/html/atom.lo exp/locale/collate.lo \
+ exp/locale/collate/build.lo exp/norm.lo exp/proxy.lo \
+ exp/terminal.lo exp/types.lo exp/utf8string.lo \
+ html/template.lo go/ast.lo go/build.lo go/doc.lo go/parser.lo \
+ go/printer.lo go/scanner.lo go/token.lo hash/adler32.lo \
+ hash/crc32.lo hash/crc64.lo hash/fnv.lo net/http/cgi.lo \
+ net/http/fcgi.lo net/http/httptest.lo net/http/httputil.lo \
+ net/http/pprof.lo image/color.lo image/draw.lo image/gif.lo \
+ image/jpeg.lo image/png.lo index/suffixarray.lo io/ioutil.lo \
+ log/syslog.lo log/syslog/syslog_c.lo math/big.lo math/cmplx.lo \
+ math/rand.lo mime/multipart.lo net/http.lo net/mail.lo \
+ net/rpc.lo net/smtp.lo net/textproto.lo net/url.lo \
+ old/netchan.lo old/regexp.lo old/template.lo os/exec.lo \
+ $(am__DEPENDENCIES_1) os/signal.lo os/user.lo path/filepath.lo \
+ regexp/syntax.lo net/rpc/jsonrpc.lo runtime/debug.lo \
+ runtime/pprof.lo sync/atomic.lo sync/atomic_c.lo \
+ text/scanner.lo text/tabwriter.lo text/template.lo \
+ text/template/parse.lo testing/iotest.lo testing/quick.lo \
+ unicode/utf16.lo unicode/utf8.lo
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \
../libbacktrace/libbacktrace.la $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
@@ -207,12 +211,12 @@ am__objects_5 = go-append.lo go-assert.lo go-assert-interface.lo \
go-type-identity.lo go-type-interface.lo go-type-string.lo \
go-typedesc-equal.lo go-typestring.lo go-unsafe-new.lo \
go-unsafe-newarray.lo go-unsafe-pointer.lo go-unwind.lo \
- chan.lo cpuprof.lo $(am__objects_1) mcache.lo mcentral.lo \
- $(am__objects_2) mfinal.lo mfixalloc.lo mgc0.lo mheap.lo \
- msize.lo print.lo proc.lo runtime.lo signal_unix.lo thread.lo \
- yield.lo $(am__objects_3) iface.lo malloc.lo map.lo mprof.lo \
- reflect.lo runtime1.lo sema.lo sigqueue.lo string.lo time.lo \
- $(am__objects_4)
+ chan.lo cpuprof.lo lfstack.lo $(am__objects_1) mcache.lo \
+ mcentral.lo $(am__objects_2) mfinal.lo mfixalloc.lo mgc0.lo \
+ mheap.lo msize.lo panic.lo parfor.lo print.lo proc.lo \
+ runtime.lo signal_unix.lo thread.lo yield.lo $(am__objects_3) \
+ iface.lo malloc.lo map.lo mprof.lo reflect.lo runtime1.lo \
+ sema.lo sigqueue.lo string.lo time.lo $(am__objects_4)
am_libgo_la_OBJECTS = $(am__objects_5)
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -250,7 +254,9 @@ DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
$(toolexeclibgocrypto_DATA) $(toolexeclibgocryptox509_DATA) \
$(toolexeclibgodatabase_DATA) $(toolexeclibgodatabasesql_DATA) \
$(toolexeclibgodebug_DATA) $(toolexeclibgoencoding_DATA) \
- $(toolexeclibgoexp_DATA) $(toolexeclibgogo_DATA) \
+ $(toolexeclibgoexp_DATA) $(toolexeclibgoexphtml_DATA) \
+ $(toolexeclibgoexplocale_DATA) \
+ $(toolexeclibgoexplocalecollate_DATA) $(toolexeclibgogo_DATA) \
$(toolexeclibgohash_DATA) $(toolexeclibgohtml_DATA) \
$(toolexeclibgoimage_DATA) $(toolexeclibgoindex_DATA) \
$(toolexeclibgoio_DATA) $(toolexeclibgolog_DATA) \
@@ -611,6 +617,18 @@ toolexeclibgoexp_DATA = \
exp/types.gox \
exp/utf8string.gox
+toolexeclibgoexphtmldir = $(toolexeclibgoexpdir)/html
+toolexeclibgoexphtml_DATA = \
+ exp/html/atom.gox
+
+toolexeclibgoexplocaledir = $(toolexeclibgoexpdir)/locale
+toolexeclibgoexplocale_DATA = \
+ exp/locale/collate.gox
+
+toolexeclibgoexplocalecollatedir = $(toolexeclibgoexplocaledir)/collate
+toolexeclibgoexplocalecollate_DATA = \
+ exp/locale/collate/build.gox
+
toolexeclibgogodir = $(toolexeclibgodir)/go
toolexeclibgogo_DATA = \
go/ast.gox \
@@ -811,6 +829,7 @@ runtime_files = \
runtime/go-unwind.c \
runtime/chan.c \
runtime/cpuprof.c \
+ runtime/lfstack.c \
$(runtime_lock_files) \
runtime/mcache.c \
runtime/mcentral.c \
@@ -820,6 +839,8 @@ runtime_files = \
runtime/mgc0.c \
runtime/mheap.c \
runtime/msize.c \
+ runtime/panic.c \
+ runtime/parfor.c \
runtime/print.c \
runtime/proc.c \
runtime/runtime.c \
@@ -947,31 +968,36 @@ go_mime_files = \
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = go/net/fd_netbsd.go
@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = go/net/fd_linux.go
@LIBGO_IS_RTEMS_TRUE@go_net_fd_os_file = go/net/fd_select.go
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver.go
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver.go
-@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver_unix.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver_unix.go
+@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver_unix.go
@LIBGO_IS_RTEMS_TRUE@go_net_newpollserver_file = go/net/newpollserver_rtems.go
-@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_netbsd.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_cgo_file = go/net/cgo_linux.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cgo_file = go/net/cgo_linux.go
@LIBGO_IS_LINUX_TRUE@go_net_cgo_file = go/net/cgo_linux.go
-@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sock_file = go/net/sock_solaris.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sock_file = go/net/sock_linux.go
@LIBGO_IS_LINUX_TRUE@go_net_sock_file = go/net/sock_linux.go
-@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockopt_file = go/net/sockopt_bsd.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockopt_file = go/net/sockopt_linux.go
@LIBGO_IS_LINUX_TRUE@go_net_sockopt_file = go/net/sockopt_linux.go
-@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_netbsd.go
-@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_freebsd.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
+@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_solaris.go
-@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockoptip_file = go/net/sockoptip_linux.go
-@LIBGO_IS_LINUX_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go
-@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
+@LIBGO_IS_LINUX_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go
+@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_freebsd.go
@LIBGO_IS_LINUX_TRUE@go_net_sendfile_file = go/net/sendfile_linux.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_stub.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@go_net_interface_file = go/net/interface_netbsd.go
@@ -982,13 +1008,12 @@ go_net_files = \
go/net/dial.go \
go/net/dnsclient.go \
go/net/dnsclient_unix.go \
- go/net/dnsconfig.go \
+ go/net/dnsconfig_unix.go \
go/net/dnsmsg.go \
- go/net/doc.go \
$(go_net_newpollserver_file) \
- go/net/fd.go \
+ go/net/fd_unix.go \
$(go_net_fd_os_file) \
- go/net/file.go \
+ go/net/file_unix.go \
go/net/hosts.go \
go/net/interface.go \
$(go_net_interface_file) \
@@ -997,6 +1022,7 @@ go_net_files = \
go/net/iprawsock_posix.go \
go/net/ipsock.go \
go/net/ipsock_posix.go \
+ go/net/lookup.go \
go/net/lookup_unix.go \
go/net/mac.go \
go/net/net.go \
@@ -1004,12 +1030,12 @@ go_net_files = \
go/net/parse.go \
go/net/pipe.go \
go/net/port.go \
+ go/net/port_unix.go \
$(go_net_sendfile_file) \
- go/net/sock.go \
+ go/net/sock_posix.go \
$(go_net_sock_file) \
- go/net/sockopt.go \
+ go/net/sockopt_posix.go \
$(go_net_sockopt_file) \
- go/net/sockoptip.go \
$(go_net_sockoptip_file) \
go/net/tcpsock.go \
go/net/tcpsock_posix.go \
@@ -1058,6 +1084,7 @@ go_path_files = \
go_reflect_files = \
go/reflect/deepequal.go \
+ go/reflect/makefunc.go \
go/reflect/type.go \
go/reflect/value.go
@@ -1098,12 +1125,14 @@ go_strconv_files = \
go_strings_files = \
go/strings/reader.go \
go/strings/replace.go \
+ go/strings/search.go \
go/strings/strings.go
go_sync_files = \
go/sync/cond.go \
go/sync/mutex.go \
go/sync/once.go \
+ go/sync/race0.go \
go/sync/runtime.go \
go/sync/rwmutex.go \
go/sync/waitgroup.go
@@ -1140,10 +1169,17 @@ go_unicode_files = \
go/unicode/letter.go \
go/unicode/tables.go
+@LIBGO_IS_DARWIN_TRUE@archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+@LIBGO_IS_FREEBSD_TRUE@archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+@LIBGO_IS_LINUX_TRUE@archive_tar_atim_file = go/archive/tar/stat_atim.go
+@LIBGO_IS_NETBSD_TRUE@archive_tar_atim_file = go/archive/tar/stat_atimespec.go
+@LIBGO_IS_OPENBSD_TRUE@archive_tar_atim_file = go/archive/tar/stat_atim.go
go_archive_tar_files = \
go/archive/tar/common.go \
go/archive/tar/reader.go \
- go/archive/tar/writer.go
+ go/archive/tar/stat_unix.go \
+ go/archive/tar/writer.go \
+ $(archive_tar_atim_file)
go_archive_zip_files = \
go/archive/zip/reader.go \
@@ -1157,6 +1193,7 @@ go_compress_bzip2_files = \
go/compress/bzip2/move_to_front.go
go_compress_flate_files = \
+ go/compress/flate/copy.go \
go/compress/flate/deflate.go \
go/compress/flate/huffman_bit_writer.go \
go/compress/flate/huffman_code.go \
@@ -1188,6 +1225,7 @@ go_container_ring_files = \
go_crypto_aes_files = \
go/crypto/aes/block.go \
go/crypto/aes/cipher.go \
+ go/crypto/aes/cipher_generic.go \
go/crypto/aes/const.go
go_crypto_cipher_files = \
@@ -1257,10 +1295,12 @@ go_crypto_tls_files = \
go/crypto/tls/handshake_server.go \
go/crypto/tls/key_agreement.go \
go/crypto/tls/prf.go \
+ go/crypto/tls/ticket.go \
go/crypto/tls/tls.go
go_crypto_x509_files = \
go/crypto/x509/cert_pool.go \
+ go/crypto/x509/pem_decrypt.go \
go/crypto/x509/pkcs1.go \
go/crypto/x509/pkcs8.go \
go/crypto/x509/root.go \
@@ -1371,9 +1411,30 @@ go_exp_html_files = \
go/exp/html/render.go \
go/exp/html/token.go
+go_exp_html_atom_files = \
+ go/exp/html/atom/atom.go \
+ go/exp/html/atom/table.go
+
go_exp_inotify_files = \
go/exp/inotify/inotify_linux.go
+go_exp_locale_collate_files = \
+ go/exp/locale/collate/colelem.go \
+ go/exp/locale/collate/collate.go \
+ go/exp/locale/collate/contract.go \
+ go/exp/locale/collate/export.go \
+ go/exp/locale/collate/table.go \
+ go/exp/locale/collate/tables.go \
+ go/exp/locale/collate/trie.go
+
+go_exp_locale_collate_build_files = \
+ go/exp/locale/collate/build/builder.go \
+ go/exp/locale/collate/build/colelem.go \
+ go/exp/locale/collate/build/contract.go \
+ go/exp/locale/collate/build/order.go \
+ go/exp/locale/collate/build/table.go \
+ go/exp/locale/collate/build/trie.go
+
go_exp_norm_files = \
go/exp/norm/composition.go \
go/exp/norm/forminfo.go \
@@ -1407,6 +1468,7 @@ go_exp_utf8string_files = \
go_go_ast_files = \
go/go/ast/ast.go \
+ go/go/ast/commentmap.go \
go/go/ast/filter.go \
go/go/ast/import.go \
go/go/ast/print.go \
@@ -1417,6 +1479,7 @@ go_go_ast_files = \
go_go_build_files = \
go/go/build/build.go \
go/go/build/doc.go \
+ go/go/build/read.go \
syslist.go
go_go_doc_files = \
@@ -1490,6 +1553,7 @@ go_image_jpeg_files = \
go/image/jpeg/writer.go
go_image_png_files = \
+ go/image/png/paeth.go \
go/image/png/reader.go \
go/image/png/writer.go
@@ -1498,6 +1562,7 @@ go_index_suffixarray_files = \
go/index/suffixarray/suffixarray.go
go_io_ioutil_files = \
+ go/io/ioutil/blackhole.go \
go/io/ioutil/ioutil.go \
go/io/ioutil/tempfile.go
@@ -1624,6 +1689,7 @@ go_path_filepath_files = \
go_regexp_syntax_files = \
go/regexp/syntax/compile.go \
+ go/regexp/syntax/doc.go \
go/regexp/syntax/parse.go \
go/regexp/syntax/perl_groups.go \
go/regexp/syntax/prog.go \
@@ -1750,6 +1816,7 @@ go_base_syscall_files = \
go/syscall/syscall_errno.go \
go/syscall/libcall_support.go \
go/syscall/libcall_posix.go \
+ go/syscall/race0.go \
go/syscall/socket.go \
go/syscall/sockcmsg_unix.go \
go/syscall/str.go \
@@ -1867,6 +1934,9 @@ libgo_go_objs = \
encoding/xml.lo \
exp/ebnf.lo \
exp/html.lo \
+ exp/html/atom.lo \
+ exp/locale/collate.lo \
+ exp/locale/collate/build.lo \
exp/norm.lo \
exp/proxy.lo \
exp/terminal.lo \
@@ -2065,6 +2135,7 @@ TEST_PACKAGES = \
strconv/check \
strings/check \
sync/check \
+ syscall/check \
time/check \
unicode/check \
archive/tar/check \
@@ -2113,10 +2184,14 @@ TEST_PACKAGES = \
encoding/xml/check \
exp/ebnf/check \
exp/html/check \
+ exp/html/atom/check \
$(exp_inotify_check) \
+ exp/locale/collate/check \
+ exp/locale/collate/build/check \
exp/norm/check \
exp/proxy/check \
exp/terminal/check \
+ exp/types/check \
exp/utf8string/check \
html/template/check \
go/ast/check \
@@ -2377,6 +2452,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-pointer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unwind.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lfstack.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_futex.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_sema.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Plo@am__quote@
@@ -2391,6 +2467,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mheap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mprof.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msize.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parfor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reflect.Plo@am__quote@
@@ -2897,6 +2975,13 @@ cpuprof.lo: runtime/cpuprof.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpuprof.lo `test -f 'runtime/cpuprof.c' || echo '$(srcdir)/'`runtime/cpuprof.c
+lfstack.lo: runtime/lfstack.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lfstack.lo -MD -MP -MF $(DEPDIR)/lfstack.Tpo -c -o lfstack.lo `test -f 'runtime/lfstack.c' || echo '$(srcdir)/'`runtime/lfstack.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lfstack.Tpo $(DEPDIR)/lfstack.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/lfstack.c' object='lfstack.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lfstack.lo `test -f 'runtime/lfstack.c' || echo '$(srcdir)/'`runtime/lfstack.c
+
lock_sema.lo: runtime/lock_sema.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lock_sema.lo -MD -MP -MF $(DEPDIR)/lock_sema.Tpo -c -o lock_sema.lo `test -f 'runtime/lock_sema.c' || echo '$(srcdir)/'`runtime/lock_sema.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lock_sema.Tpo $(DEPDIR)/lock_sema.Plo
@@ -2988,6 +3073,20 @@ msize.lo: runtime/msize.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msize.lo `test -f 'runtime/msize.c' || echo '$(srcdir)/'`runtime/msize.c
+panic.lo: runtime/panic.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT panic.lo -MD -MP -MF $(DEPDIR)/panic.Tpo -c -o panic.lo `test -f 'runtime/panic.c' || echo '$(srcdir)/'`runtime/panic.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/panic.Tpo $(DEPDIR)/panic.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/panic.c' object='panic.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o panic.lo `test -f 'runtime/panic.c' || echo '$(srcdir)/'`runtime/panic.c
+
+parfor.lo: runtime/parfor.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT parfor.lo -MD -MP -MF $(DEPDIR)/parfor.Tpo -c -o parfor.lo `test -f 'runtime/parfor.c' || echo '$(srcdir)/'`runtime/parfor.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/parfor.Tpo $(DEPDIR)/parfor.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/parfor.c' object='parfor.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o parfor.lo `test -f 'runtime/parfor.c' || echo '$(srcdir)/'`runtime/parfor.c
+
print.lo: runtime/print.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT print.lo -MD -MP -MF $(DEPDIR)/print.Tpo -c -o print.lo `test -f 'runtime/print.c' || echo '$(srcdir)/'`runtime/print.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/print.Tpo $(DEPDIR)/print.Plo
@@ -3317,6 +3416,66 @@ uninstall-toolexeclibgoexpDATA:
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(toolexeclibgoexpdir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(toolexeclibgoexpdir)" && rm -f $$files
+install-toolexeclibgoexphtmlDATA: $(toolexeclibgoexphtml_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(toolexeclibgoexphtmldir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoexphtmldir)"
+ @list='$(toolexeclibgoexphtml_DATA)'; test -n "$(toolexeclibgoexphtmldir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoexphtmldir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoexphtmldir)" || exit $$?; \
+ done
+
+uninstall-toolexeclibgoexphtmlDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(toolexeclibgoexphtml_DATA)'; test -n "$(toolexeclibgoexphtmldir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(toolexeclibgoexphtmldir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(toolexeclibgoexphtmldir)" && rm -f $$files
+install-toolexeclibgoexplocaleDATA: $(toolexeclibgoexplocale_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(toolexeclibgoexplocaledir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoexplocaledir)"
+ @list='$(toolexeclibgoexplocale_DATA)'; test -n "$(toolexeclibgoexplocaledir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoexplocaledir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoexplocaledir)" || exit $$?; \
+ done
+
+uninstall-toolexeclibgoexplocaleDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(toolexeclibgoexplocale_DATA)'; test -n "$(toolexeclibgoexplocaledir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(toolexeclibgoexplocaledir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(toolexeclibgoexplocaledir)" && rm -f $$files
+install-toolexeclibgoexplocalecollateDATA: $(toolexeclibgoexplocalecollate_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(toolexeclibgoexplocalecollatedir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoexplocalecollatedir)"
+ @list='$(toolexeclibgoexplocalecollate_DATA)'; test -n "$(toolexeclibgoexplocalecollatedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoexplocalecollatedir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoexplocalecollatedir)" || exit $$?; \
+ done
+
+uninstall-toolexeclibgoexplocalecollateDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(toolexeclibgoexplocalecollate_DATA)'; test -n "$(toolexeclibgoexplocalecollatedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(toolexeclibgoexplocalecollatedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(toolexeclibgoexplocalecollatedir)" && rm -f $$files
install-toolexeclibgogoDATA: $(toolexeclibgogo_DATA)
@$(NORMAL_INSTALL)
test -z "$(toolexeclibgogodir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgogodir)"
@@ -3898,7 +4057,7 @@ all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) all-multi $(DATA) \
config.h
installdirs: installdirs-recursive
installdirs-am:
- for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohtmldir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgologdir)" "$(DESTDIR)$(toolexeclibgomathdir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgonethttpdir)" "$(DESTDIR)$(toolexeclibgonetrpcdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotextdir)" "$(DESTDIR)$(toolexeclibgotexttemplatedir)" "$(DESTDIR)$(toolexeclibgounicodedir)"; do \
+ for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgoexphtmldir)" "$(DESTDIR)$(toolexeclibgoexplocaledir)" "$(DESTDIR)$(toolexeclibgoexplocalecollatedir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohtmldir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgologdir)" "$(DESTDIR)$(toolexeclibgomathdir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgonethttpdir)" "$(DESTDIR)$(toolexeclibgonetrpcdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotextdir)" "$(DESTDIR)$(toolexeclibgotexttemplatedir)" "$(DESTDIR)$(toolexeclibgounicodedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
@@ -3969,6 +4128,9 @@ install-exec-am: install-multi install-toolexeclibLIBRARIES \
install-toolexeclibgodatabasesqlDATA \
install-toolexeclibgodebugDATA \
install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \
+ install-toolexeclibgoexphtmlDATA \
+ install-toolexeclibgoexplocaleDATA \
+ install-toolexeclibgoexplocalecollateDATA \
install-toolexeclibgogoDATA install-toolexeclibgohashDATA \
install-toolexeclibgohtmlDATA install-toolexeclibgoimageDATA \
install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
@@ -4034,8 +4196,11 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgodatabasesqlDATA \
uninstall-toolexeclibgodebugDATA \
uninstall-toolexeclibgoencodingDATA \
- uninstall-toolexeclibgoexpDATA uninstall-toolexeclibgogoDATA \
- uninstall-toolexeclibgohashDATA \
+ uninstall-toolexeclibgoexpDATA \
+ uninstall-toolexeclibgoexphtmlDATA \
+ uninstall-toolexeclibgoexplocaleDATA \
+ uninstall-toolexeclibgoexplocalecollateDATA \
+ uninstall-toolexeclibgogoDATA uninstall-toolexeclibgohashDATA \
uninstall-toolexeclibgohtmlDATA \
uninstall-toolexeclibgoimageDATA \
uninstall-toolexeclibgoindexDATA uninstall-toolexeclibgoioDATA \
@@ -4080,6 +4245,9 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
install-toolexeclibgodatabasesqlDATA \
install-toolexeclibgodebugDATA \
install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \
+ install-toolexeclibgoexphtmlDATA \
+ install-toolexeclibgoexplocaleDATA \
+ install-toolexeclibgoexplocalecollateDATA \
install-toolexeclibgogoDATA install-toolexeclibgohashDATA \
install-toolexeclibgohtmlDATA install-toolexeclibgoimageDATA \
install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
@@ -4109,8 +4277,11 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgodatabasesqlDATA \
uninstall-toolexeclibgodebugDATA \
uninstall-toolexeclibgoencodingDATA \
- uninstall-toolexeclibgoexpDATA uninstall-toolexeclibgogoDATA \
- uninstall-toolexeclibgohashDATA \
+ uninstall-toolexeclibgoexpDATA \
+ uninstall-toolexeclibgoexphtmlDATA \
+ uninstall-toolexeclibgoexplocaleDATA \
+ uninstall-toolexeclibgoexplocalecollateDATA \
+ uninstall-toolexeclibgogoDATA uninstall-toolexeclibgohashDATA \
uninstall-toolexeclibgohtmlDATA \
uninstall-toolexeclibgoimageDATA \
uninstall-toolexeclibgoindexDATA uninstall-toolexeclibgoioDATA \
@@ -4909,6 +5080,33 @@ exp/html/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: exp/html/check
+@go_include@ exp/html/atom.lo.dep
+exp/html/atom.lo.dep: $(go_exp_html_atom_files)
+ $(BUILDDEPS)
+exp/html/atom.lo: $(go_exp_html_atom_files)
+ $(BUILDPACKAGE)
+exp/html/atom/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: exp/html/atom/check
+
+@go_include@ exp/locale/collate.lo.dep
+exp/locale/collate.lo.dep: $(go_exp_locale_collate_files)
+ $(BUILDDEPS)
+exp/locale/collate.lo: $(go_exp_locale_collate_files)
+ $(BUILDPACKAGE)
+exp/locale/collate/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: exp/locale/collate/check
+
+@go_include@ exp/locale/collate/build.lo.dep
+exp/locale/collate/build.lo.dep: $(go_exp_locale_collate_build_files)
+ $(BUILDDEPS)
+exp/locale/collate/build.lo: $(go_exp_locale_collate_build_files)
+ $(BUILDPACKAGE)
+exp/locale/collate/build/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: exp/locale/collate/build/check
+
@go_include@ exp/norm.lo.dep
exp/norm.lo.dep: $(go_exp_norm_files)
$(BUILDDEPS)
@@ -5486,6 +5684,9 @@ syscall/signame.lo: go/syscall/signame.c
syscall/wait.lo: go/syscall/wait.c
@$(MKDIR_P) syscall
$(LTCOMPILE) -c -o $@ $<
+syscall/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: syscall/check
bufio.gox: bufio.lo
$(BUILDGOX)
@@ -5649,8 +5850,14 @@ exp/ebnf.gox: exp/ebnf.lo
$(BUILDGOX)
exp/html.gox: exp/html.lo
$(BUILDGOX)
+exp/html/atom.gox: exp/html/atom.lo
+ $(BUILDGOX)
exp/inotify.gox: exp/inotify.lo
$(BUILDGOX)
+exp/locale/collate.gox: exp/locale/collate.lo
+ $(BUILDGOX)
+exp/locale/collate/build.gox: exp/locale/collate/build.lo
+ $(BUILDGOX)
exp/norm.gox: exp/norm.lo
$(BUILDGOX)
exp/proxy.gox: exp/proxy.lo
diff --git a/libgo/configure b/libgo/configure
index dc85ccfa9db..e20fa71f6a0 100755
--- a/libgo/configure
+++ b/libgo/configure
@@ -658,6 +658,8 @@ LIBGO_IS_SOLARIS_FALSE
LIBGO_IS_SOLARIS_TRUE
LIBGO_IS_RTEMS_FALSE
LIBGO_IS_RTEMS_TRUE
+LIBGO_IS_OPENBSD_FALSE
+LIBGO_IS_OPENBSD_TRUE
LIBGO_IS_NETBSD_FALSE
LIBGO_IS_NETBSD_TRUE
LIBGO_IS_LINUX_FALSE
@@ -11100,7 +11102,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11103 "configure"
+#line 11105 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11206,7 +11208,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11209 "configure"
+#line 11211 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -13471,6 +13473,7 @@ is_freebsd=no
is_irix=no
is_linux=no
is_netbsd=no
+is_openbsd=no
is_rtems=no
is_solaris=no
GOOS=unknown
@@ -13480,6 +13483,7 @@ case ${host} in
*-*-irix6*) is_irix=yes; GOOS=irix ;;
*-*-linux*) is_linux=yes; GOOS=linux ;;
*-*-netbsd*) is_netbsd=yes; GOOS=netbsd ;;
+ *-*-openbsd*) is_openbsd=yes; GOOS=openbsd ;;
*-*-rtems*) is_rtems=yes; GOOS=rtems ;;
*-*-solaris2*) is_solaris=yes; GOOS=solaris ;;
esac
@@ -13523,6 +13527,14 @@ else
LIBGO_IS_NETBSD_FALSE=
fi
+ if test $is_openbsd = yes; then
+ LIBGO_IS_OPENBSD_TRUE=
+ LIBGO_IS_OPENBSD_FALSE='#'
+else
+ LIBGO_IS_OPENBSD_TRUE='#'
+ LIBGO_IS_OPENBSD_FALSE=
+fi
+
if test $is_rtems = yes; then
LIBGO_IS_RTEMS_TRUE=
LIBGO_IS_RTEMS_FALSE='#'
@@ -15311,6 +15323,10 @@ if test -z "${LIBGO_IS_NETBSD_TRUE}" && test -z "${LIBGO_IS_NETBSD_FALSE}"; then
as_fn_error "conditional \"LIBGO_IS_NETBSD\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${LIBGO_IS_OPENBSD_TRUE}" && test -z "${LIBGO_IS_OPENBSD_FALSE}"; then
+ as_fn_error "conditional \"LIBGO_IS_OPENBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${LIBGO_IS_RTEMS_TRUE}" && test -z "${LIBGO_IS_RTEMS_FALSE}"; then
as_fn_error "conditional \"LIBGO_IS_RTEMS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/libgo/configure.ac b/libgo/configure.ac
index a31acabb3bb..217763d19b2 100644
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -129,6 +129,7 @@ is_freebsd=no
is_irix=no
is_linux=no
is_netbsd=no
+is_openbsd=no
is_rtems=no
is_solaris=no
GOOS=unknown
@@ -138,6 +139,7 @@ case ${host} in
*-*-irix6*) is_irix=yes; GOOS=irix ;;
*-*-linux*) is_linux=yes; GOOS=linux ;;
*-*-netbsd*) is_netbsd=yes; GOOS=netbsd ;;
+ *-*-openbsd*) is_openbsd=yes; GOOS=openbsd ;;
*-*-rtems*) is_rtems=yes; GOOS=rtems ;;
*-*-solaris2*) is_solaris=yes; GOOS=solaris ;;
esac
@@ -146,6 +148,7 @@ AM_CONDITIONAL(LIBGO_IS_FREEBSD, test $is_freebsd = yes)
AM_CONDITIONAL(LIBGO_IS_IRIX, test $is_irix = yes)
AM_CONDITIONAL(LIBGO_IS_LINUX, test $is_linux = yes)
AM_CONDITIONAL(LIBGO_IS_NETBSD, test $is_netbsd = yes)
+AM_CONDITIONAL(LIBGO_IS_OPENBSD, test $is_openbsd = yes)
AM_CONDITIONAL(LIBGO_IS_RTEMS, test $is_rtems = yes)
AM_CONDITIONAL(LIBGO_IS_SOLARIS, test $is_solaris = yes)
AC_SUBST(GOOS)
diff --git a/libgo/go/archive/tar/common.go b/libgo/go/archive/tar/common.go
index fc7a40923cd..921b9fe9bdd 100644
--- a/libgo/go/archive/tar/common.go
+++ b/libgo/go/archive/tar/common.go
@@ -11,7 +11,12 @@
// http://www.gnu.org/software/tar/manual/html_node/Standard.html
package tar
-import "time"
+import (
+ "errors"
+ "fmt"
+ "os"
+ "time"
+)
const (
blockSize = 512
@@ -49,6 +54,62 @@ type Header struct {
ChangeTime time.Time // status change time
}
+// sysStat, if non-nil, populates h from system-dependent fields of fi.
+var sysStat func(fi os.FileInfo, h *Header) error
+
+// Mode constants from the tar spec.
+const (
+ c_ISDIR = 040000
+ c_ISFIFO = 010000
+ c_ISREG = 0100000
+ c_ISLNK = 0120000
+ c_ISBLK = 060000
+ c_ISCHR = 020000
+ c_ISSOCK = 0140000
+)
+
+// FileInfoHeader creates a partially-populated Header from fi.
+// If fi describes a symlink, FileInfoHeader records link as the link target.
+func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
+ if fi == nil {
+ return nil, errors.New("tar: FileInfo is nil")
+ }
+ h := &Header{
+ Name: fi.Name(),
+ ModTime: fi.ModTime(),
+ Mode: int64(fi.Mode().Perm()), // or'd with c_IS* constants later
+ }
+ switch {
+ case fi.Mode()&os.ModeType == 0:
+ h.Mode |= c_ISREG
+ h.Typeflag = TypeReg
+ h.Size = fi.Size()
+ case fi.IsDir():
+ h.Typeflag = TypeDir
+ h.Mode |= c_ISDIR
+ case fi.Mode()&os.ModeSymlink != 0:
+ h.Typeflag = TypeSymlink
+ h.Mode |= c_ISLNK
+ h.Linkname = link
+ case fi.Mode()&os.ModeDevice != 0:
+ if fi.Mode()&os.ModeCharDevice != 0 {
+ h.Mode |= c_ISCHR
+ h.Typeflag = TypeChar
+ } else {
+ h.Mode |= c_ISBLK
+ h.Typeflag = TypeBlock
+ }
+ case fi.Mode()&os.ModeSocket != 0:
+ h.Mode |= c_ISSOCK
+ default:
+ return nil, fmt.Errorf("archive/tar: unknown file mode %v", fi.Mode())
+ }
+ if sysStat != nil {
+ return h, sysStat(fi, h)
+ }
+ return h, nil
+}
+
var zeroBlock = make([]byte, blockSize)
// POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signed byte values.
diff --git a/libgo/go/archive/tar/stat_atim.go b/libgo/go/archive/tar/stat_atim.go
new file mode 100644
index 00000000000..6029b087123
--- /dev/null
+++ b/libgo/go/archive/tar/stat_atim.go
@@ -0,0 +1,20 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux openbsd
+
+package tar
+
+import (
+ "syscall"
+ "time"
+)
+
+func statAtime(st *syscall.Stat_t) time.Time {
+ return time.Unix(st.Atim.Unix())
+}
+
+func statCtime(st *syscall.Stat_t) time.Time {
+ return time.Unix(st.Ctim.Unix())
+}
diff --git a/libgo/go/archive/tar/stat_atimespec.go b/libgo/go/archive/tar/stat_atimespec.go
new file mode 100644
index 00000000000..6f17dbe3072
--- /dev/null
+++ b/libgo/go/archive/tar/stat_atimespec.go
@@ -0,0 +1,20 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd netbsd
+
+package tar
+
+import (
+ "syscall"
+ "time"
+)
+
+func statAtime(st *syscall.Stat_t) time.Time {
+ return time.Unix(st.Atimespec.Unix())
+}
+
+func statCtime(st *syscall.Stat_t) time.Time {
+ return time.Unix(st.Ctimespec.Unix())
+}
diff --git a/libgo/go/archive/tar/stat_unix.go b/libgo/go/archive/tar/stat_unix.go
new file mode 100644
index 00000000000..92bc9242429
--- /dev/null
+++ b/libgo/go/archive/tar/stat_unix.go
@@ -0,0 +1,32 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux darwin freebsd openbsd netbsd
+
+package tar
+
+import (
+ "os"
+ "syscall"
+)
+
+func init() {
+ sysStat = statUnix
+}
+
+func statUnix(fi os.FileInfo, h *Header) error {
+ sys, ok := fi.Sys().(*syscall.Stat_t)
+ if !ok {
+ return nil
+ }
+ h.Uid = int(sys.Uid)
+ h.Gid = int(sys.Gid)
+ // TODO(bradfitz): populate username & group. os/user
+ // doesn't cache LookupId lookups, and lacks group
+ // lookup functions.
+ h.AccessTime = statAtime(sys)
+ h.ChangeTime = statCtime(sys)
+ // TODO(bradfitz): major/minor device numbers?
+ return nil
+}
diff --git a/libgo/go/archive/tar/tar_test.go b/libgo/go/archive/tar/tar_test.go
new file mode 100644
index 00000000000..0adc1790033
--- /dev/null
+++ b/libgo/go/archive/tar/tar_test.go
@@ -0,0 +1,56 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tar
+
+import (
+ "os"
+ "testing"
+ "time"
+)
+
+func TestFileInfoHeader(t *testing.T) {
+ fi, err := os.Lstat("testdata/small.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ h, err := FileInfoHeader(fi, "")
+ if err != nil {
+ t.Fatalf("on small.txt: %v", err)
+ }
+ if g, e := h.Name, "small.txt"; g != e {
+ t.Errorf("Name = %q; want %q", g, e)
+ }
+ if g, e := h.Mode, int64(fi.Mode().Perm())|c_ISREG; g != e {
+ t.Errorf("Mode = %#o; want %#o", g, e)
+ }
+ if g, e := h.Size, int64(5); g != e {
+ t.Errorf("Size = %v; want %v", g, e)
+ }
+ if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) {
+ t.Errorf("ModTime = %v; want %v", g, e)
+ }
+}
+
+func TestFileInfoHeaderSymlink(t *testing.T) {
+ h, err := FileInfoHeader(symlink{}, "some-target")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if g, e := h.Name, "some-symlink"; g != e {
+ t.Errorf("Name = %q; want %q", g, e)
+ }
+ if g, e := h.Linkname, "some-target"; g != e {
+ t.Errorf("Linkname = %q; want %q", g, e)
+ }
+}
+
+type symlink struct{}
+
+func (symlink) Name() string { return "some-symlink" }
+func (symlink) Size() int64 { return 0 }
+func (symlink) Mode() os.FileMode { return os.ModeSymlink }
+func (symlink) ModTime() time.Time { return time.Time{} }
+func (symlink) IsDir() bool { return false }
+func (symlink) Sys() interface{} { return nil }
diff --git a/libgo/go/archive/tar/writer.go b/libgo/go/archive/tar/writer.go
index b2b7a58a10a..a9c8fdbbc9a 100644
--- a/libgo/go/archive/tar/writer.go
+++ b/libgo/go/archive/tar/writer.go
@@ -27,7 +27,7 @@ var (
//
// Example:
// tw := tar.NewWriter(w)
-// hdr := new(Header)
+// hdr := new(tar.Header)
// hdr.Size = length of data in bytes
// // populate other hdr fields as desired
// if err := tw.WriteHeader(hdr); err != nil {
diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go
index ddd507538b3..a6b049ec32b 100644
--- a/libgo/go/archive/zip/reader.go
+++ b/libgo/go/archive/zip/reader.go
@@ -103,7 +103,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
}
z.File = append(z.File, f)
}
- if uint16(len(z.File)) != end.directoryRecords {
+ if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here
// Return the readDirectoryHeader error if we read
// the wrong number of directory entries.
return err
@@ -123,7 +123,7 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
if err != nil {
return
}
- size := int64(f.CompressedSize)
+ size := int64(f.CompressedSize64)
r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size)
switch f.Method {
case Store: // (no compression)
@@ -220,6 +220,8 @@ func readDirectoryHeader(f *File, r io.Reader) error {
f.CRC32 = b.uint32()
f.CompressedSize = b.uint32()
f.UncompressedSize = b.uint32()
+ f.CompressedSize64 = uint64(f.CompressedSize)
+ f.UncompressedSize64 = uint64(f.UncompressedSize)
filenameLen := int(b.uint16())
extraLen := int(b.uint16())
commentLen := int(b.uint16())
@@ -233,6 +235,28 @@ func readDirectoryHeader(f *File, r io.Reader) error {
f.Name = string(d[:filenameLen])
f.Extra = d[filenameLen : filenameLen+extraLen]
f.Comment = string(d[filenameLen+extraLen:])
+
+ if len(f.Extra) > 0 {
+ b := readBuf(f.Extra)
+ for len(b) > 0 {
+ tag := b.uint16()
+ size := b.uint16()
+ if tag == zip64ExtraId {
+ // update directory values from the zip64 extra block
+ eb := readBuf(b)
+ if len(eb) >= 8 {
+ f.UncompressedSize64 = eb.uint64()
+ }
+ if len(eb) >= 8 {
+ f.CompressedSize64 = eb.uint64()
+ }
+ if len(eb) >= 8 {
+ f.headerOffset = int64(eb.uint64())
+ }
+ }
+ b = b[size:]
+ }
+ }
return nil
}
@@ -263,15 +287,23 @@ func readDataDescriptor(r io.Reader, f *File) error {
return err
}
b := readBuf(buf[:12])
- f.CRC32 = b.uint32()
- f.CompressedSize = b.uint32()
- f.UncompressedSize = b.uint32()
+ if b.uint32() != f.CRC32 {
+ return ErrChecksum
+ }
+
+ // The two sizes that follow here can be either 32 bits or 64 bits
+ // but the spec is not very clear on this and different
+ // interpretations has been made causing incompatibilities. We
+ // already have the sizes from the central directory so we can
+ // just ignore these.
+
return nil
}
func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) {
// look for directoryEndSignature in the last 1k, then in the last 65k
var buf []byte
+ var directoryEndOffset int64
for i, bLen := range []int64{1024, 65 * 1024} {
if bLen > size {
bLen = size
@@ -282,6 +314,7 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error)
}
if p := findSignatureInBlock(buf); p >= 0 {
buf = buf[p:]
+ directoryEndOffset = size - bLen + int64(p)
break
}
if i == 1 || bLen == size {
@@ -292,12 +325,12 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error)
// read header into struct
b := readBuf(buf[4:]) // skip signature
d := &directoryEnd{
- diskNbr: b.uint16(),
- dirDiskNbr: b.uint16(),
- dirRecordsThisDisk: b.uint16(),
- directoryRecords: b.uint16(),
- directorySize: b.uint32(),
- directoryOffset: b.uint32(),
+ diskNbr: uint32(b.uint16()),
+ dirDiskNbr: uint32(b.uint16()),
+ dirRecordsThisDisk: uint64(b.uint16()),
+ directoryRecords: uint64(b.uint16()),
+ directorySize: uint64(b.uint32()),
+ directoryOffset: uint64(b.uint32()),
commentLen: b.uint16(),
}
l := int(d.commentLen)
@@ -305,9 +338,62 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error)
return nil, errors.New("zip: invalid comment length")
}
d.comment = string(b[:l])
+
+ p, err := findDirectory64End(r, directoryEndOffset)
+ if err == nil && p >= 0 {
+ err = readDirectory64End(r, p, d)
+ }
+ if err != nil {
+ return nil, err
+ }
return d, nil
}
+// findDirectory64End tries to read the zip64 locator just before the
+// directory end and returns the offset of the zip64 directory end if
+// found.
+func findDirectory64End(r io.ReaderAt, directoryEndOffset int64) (int64, error) {
+ locOffset := directoryEndOffset - directory64LocLen
+ if locOffset < 0 {
+ return -1, nil // no need to look for a header outside the file
+ }
+ buf := make([]byte, directory64LocLen)
+ if _, err := r.ReadAt(buf, locOffset); err != nil {
+ return -1, err
+ }
+ b := readBuf(buf)
+ if sig := b.uint32(); sig != directory64LocSignature {
+ return -1, nil
+ }
+ b = b[4:] // skip number of the disk with the start of the zip64 end of central directory
+ p := b.uint64() // relative offset of the zip64 end of central directory record
+ return int64(p), nil
+}
+
+// readDirectory64End reads the zip64 directory end and updates the
+// directory end with the zip64 directory end values.
+func readDirectory64End(r io.ReaderAt, offset int64, d *directoryEnd) (err error) {
+ buf := make([]byte, directory64EndLen)
+ if _, err := r.ReadAt(buf, offset); err != nil {
+ return err
+ }
+
+ b := readBuf(buf)
+ if sig := b.uint32(); sig != directory64EndSignature {
+ return ErrFormat
+ }
+
+ b = b[12:] // skip dir size, version and version needed (uint64 + 2x uint16)
+ d.diskNbr = b.uint32() // number of this disk
+ d.dirDiskNbr = b.uint32() // number of the disk with the start of the central directory
+ d.dirRecordsThisDisk = b.uint64() // total number of entries in the central directory on this disk
+ d.directoryRecords = b.uint64() // total number of entries in the central directory
+ d.directorySize = b.uint64() // size of the central directory
+ d.directoryOffset = b.uint64() // offset of start of central directory with respect to the starting disk number
+
+ return nil
+}
+
func findSignatureInBlock(b []byte) int {
for i := len(b) - directoryEndLen; i >= 0; i-- {
// defined from directoryEndSignature in struct.go
@@ -335,3 +421,9 @@ func (b *readBuf) uint32() uint32 {
*b = (*b)[4:]
return v
}
+
+func (b *readBuf) uint64() uint64 {
+ v := binary.LittleEndian.Uint64(*b)
+ *b = (*b)[8:]
+ return v
+}
diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go
index 5f1d1b28a98..cf9c59c4b92 100644
--- a/libgo/go/archive/zip/reader_test.go
+++ b/libgo/go/archive/zip/reader_test.go
@@ -206,6 +206,17 @@ var tests = []ZipTest{
},
},
},
+ {
+ Name: "zip64.zip",
+ File: []ZipTestFile{
+ {
+ Name: "README",
+ Content: []byte("This small file is in ZIP64 format.\n"),
+ Mtime: "08-10-12 14:33:32",
+ Mode: 0644,
+ },
+ },
+ },
}
var crossPlatform = []ZipTestFile{
diff --git a/libgo/go/archive/zip/struct.go b/libgo/go/archive/zip/struct.go
index 55f3dcfb82e..ea067f3554f 100644
--- a/libgo/go/archive/zip/struct.go
+++ b/libgo/go/archive/zip/struct.go
@@ -7,12 +7,19 @@ Package zip provides support for reading and writing ZIP archives.
See: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
-This package does not support ZIP64 or disk spanning.
+This package does not support disk spanning.
+
+A note about ZIP64:
+
+To be backwards compatible the FileHeader has both 32 and 64 bit Size
+fields. The 64 bit fields will always contain the correct value and
+for normal archives both fields will be the same. For files requiring
+the ZIP64 format the 32 bit fields will be 0xffffffff and the 64 bit
+fields must be used instead.
*/
package zip
import (
- "errors"
"os"
"time"
)
@@ -27,11 +34,16 @@ const (
fileHeaderSignature = 0x04034b50
directoryHeaderSignature = 0x02014b50
directoryEndSignature = 0x06054b50
+ directory64LocSignature = 0x07064b50
+ directory64EndSignature = 0x06064b50
dataDescriptorSignature = 0x08074b50 // de-facto standard; required by OS X Finder
fileHeaderLen = 30 // + filename + extra
directoryHeaderLen = 46 // + filename + extra + comment
directoryEndLen = 22 // + comment
dataDescriptorLen = 16 // four uint32: descriptor signature, crc32, compressed size, size
+ dataDescriptor64Len = 24 // descriptor with 8 byte sizes
+ directory64LocLen = 20 //
+ directory64EndLen = 56 // + extra
// Constants for the first byte in CreatorVersion
creatorFAT = 0
@@ -39,22 +51,35 @@ const (
creatorNTFS = 11
creatorVFAT = 14
creatorMacOSX = 19
+
+ // version numbers
+ zipVersion20 = 20 // 2.0
+ zipVersion45 = 45 // 4.5 (reads and writes zip64 archives)
+
+ // limits for non zip64 files
+ uint16max = (1 << 16) - 1
+ uint32max = (1 << 32) - 1
+
+ // extra header id's
+ zip64ExtraId = 0x0001 // zip64 Extended Information Extra Field
)
type FileHeader struct {
- Name string
- CreatorVersion uint16
- ReaderVersion uint16
- Flags uint16
- Method uint16
- ModifiedTime uint16 // MS-DOS time
- ModifiedDate uint16 // MS-DOS date
- CRC32 uint32
- CompressedSize uint32
- UncompressedSize uint32
- Extra []byte
- ExternalAttrs uint32 // Meaning depends on CreatorVersion
- Comment string
+ Name string
+ CreatorVersion uint16
+ ReaderVersion uint16
+ Flags uint16
+ Method uint16
+ ModifiedTime uint16 // MS-DOS time
+ ModifiedDate uint16 // MS-DOS date
+ CRC32 uint32
+ CompressedSize uint32 // deprecated; use CompressedSize64
+ UncompressedSize uint32 // deprecated; use UncompressedSize64
+ CompressedSize64 uint64
+ UncompressedSize64 uint64
+ Extra []byte
+ ExternalAttrs uint32 // Meaning depends on CreatorVersion
+ Comment string
}
// FileInfo returns an os.FileInfo for the FileHeader.
@@ -67,8 +92,13 @@ type headerFileInfo struct {
fh *FileHeader
}
-func (fi headerFileInfo) Name() string { return fi.fh.Name }
-func (fi headerFileInfo) Size() int64 { return int64(fi.fh.UncompressedSize) }
+func (fi headerFileInfo) Name() string { return fi.fh.Name }
+func (fi headerFileInfo) Size() int64 {
+ if fi.fh.UncompressedSize64 > 0 {
+ return int64(fi.fh.UncompressedSize64)
+ }
+ return int64(fi.fh.UncompressedSize)
+}
func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() }
func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() }
func (fi headerFileInfo) Mode() os.FileMode { return fi.fh.Mode() }
@@ -78,25 +108,27 @@ func (fi headerFileInfo) Sys() interface{} { return fi.fh }
// os.FileInfo.
func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
size := fi.Size()
- if size > (1<<32 - 1) {
- return nil, errors.New("zip: file over 4GB")
- }
fh := &FileHeader{
- Name: fi.Name(),
- UncompressedSize: uint32(size),
+ Name: fi.Name(),
+ UncompressedSize64: uint64(size),
}
fh.SetModTime(fi.ModTime())
fh.SetMode(fi.Mode())
+ if fh.UncompressedSize64 > uint32max {
+ fh.UncompressedSize = uint32max
+ } else {
+ fh.UncompressedSize = uint32(fh.UncompressedSize64)
+ }
return fh, nil
}
type directoryEnd struct {
- diskNbr uint16 // unused
- dirDiskNbr uint16 // unused
- dirRecordsThisDisk uint16 // unused
- directoryRecords uint16
- directorySize uint32
- directoryOffset uint32 // relative to file
+ diskNbr uint32 // unused
+ dirDiskNbr uint32 // unused
+ dirRecordsThisDisk uint64 // unused
+ directoryRecords uint64
+ directorySize uint64
+ directoryOffset uint64 // relative to file
commentLen uint16
comment string
}
@@ -190,6 +222,11 @@ func (h *FileHeader) SetMode(mode os.FileMode) {
}
}
+// isZip64 returns true if the file size exceeds the 32 bit limit
+func (fh *FileHeader) isZip64() bool {
+ return fh.CompressedSize64 > uint32max || fh.UncompressedSize64 > uint32max
+}
+
func msdosModeToFileMode(m uint32) (mode os.FileMode) {
if m&msdosDir != 0 {
mode = os.ModeDir | 0777
diff --git a/libgo/go/archive/zip/testdata/zip64.zip b/libgo/go/archive/zip/testdata/zip64.zip
new file mode 100644
index 00000000000..a2ee1fa33dc
--- /dev/null
+++ b/libgo/go/archive/zip/testdata/zip64.zip
Binary files differ
diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go
index 45eb6bd730d..50d83946d2c 100644
--- a/libgo/go/archive/zip/writer.go
+++ b/libgo/go/archive/zip/writer.go
@@ -27,7 +27,7 @@ type Writer struct {
type header struct {
*FileHeader
- offset uint32
+ offset uint64
}
// NewWriter returns a new Writer writing a zip file to w.
@@ -62,14 +62,36 @@ func (w *Writer) Close() error {
b.uint16(h.ModifiedTime)
b.uint16(h.ModifiedDate)
b.uint32(h.CRC32)
- b.uint32(h.CompressedSize)
- b.uint32(h.UncompressedSize)
+ if h.isZip64() || h.offset > uint32max {
+ // the file needs a zip64 header. store maxint in both
+ // 32 bit size fields (and offset later) to signal that the
+ // zip64 extra header should be used.
+ b.uint32(uint32max) // compressed size
+ b.uint32(uint32max) // uncompressed size
+
+ // append a zip64 extra block to Extra
+ var buf [28]byte // 2x uint16 + 3x uint64
+ eb := writeBuf(buf[:])
+ eb.uint16(zip64ExtraId)
+ eb.uint16(24) // size = 3x uint64
+ eb.uint64(h.UncompressedSize64)
+ eb.uint64(h.CompressedSize64)
+ eb.uint64(h.offset)
+ h.Extra = append(h.Extra, buf[:]...)
+ } else {
+ b.uint32(h.CompressedSize)
+ b.uint32(h.UncompressedSize)
+ }
b.uint16(uint16(len(h.Name)))
b.uint16(uint16(len(h.Extra)))
b.uint16(uint16(len(h.Comment)))
b = b[4:] // skip disk number start and internal file attr (2x uint16)
b.uint32(h.ExternalAttrs)
- b.uint32(h.offset)
+ if h.offset > uint32max {
+ b.uint32(uint32max)
+ } else {
+ b.uint32(uint32(h.offset))
+ }
if _, err := w.cw.Write(buf[:]); err != nil {
return err
}
@@ -85,15 +107,52 @@ func (w *Writer) Close() error {
}
end := w.cw.count
+ records := uint64(len(w.dir))
+ size := uint64(end - start)
+ offset := uint64(start)
+
+ if records > uint16max || size > uint32max || offset > uint32max {
+ var buf [directory64EndLen + directory64LocLen]byte
+ b := writeBuf(buf[:])
+
+ // zip64 end of central directory record
+ b.uint32(directory64EndSignature)
+ b.uint64(directory64EndLen)
+ b.uint16(zipVersion45) // version made by
+ b.uint16(zipVersion45) // version needed to extract
+ b.uint32(0) // number of this disk
+ b.uint32(0) // number of the disk with the start of the central directory
+ b.uint64(records) // total number of entries in the central directory on this disk
+ b.uint64(records) // total number of entries in the central directory
+ b.uint64(size) // size of the central directory
+ b.uint64(offset) // offset of start of central directory with respect to the starting disk number
+
+ // zip64 end of central directory locator
+ b.uint32(directory64LocSignature)
+ b.uint32(0) // number of the disk with the start of the zip64 end of central directory
+ b.uint64(uint64(end)) // relative offset of the zip64 end of central directory record
+ b.uint32(1) // total number of disks
+
+ if _, err := w.cw.Write(buf[:]); err != nil {
+ return err
+ }
+
+ // store max values in the regular end record to signal that
+ // that the zip64 values should be used instead
+ records = uint16max
+ size = uint32max
+ offset = uint32max
+ }
+
// write end record
var buf [directoryEndLen]byte
b := writeBuf(buf[:])
b.uint32(uint32(directoryEndSignature))
- b = b[4:] // skip over disk number and first disk number (2x uint16)
- b.uint16(uint16(len(w.dir))) // number of entries this disk
- b.uint16(uint16(len(w.dir))) // number of entries total
- b.uint32(uint32(end - start)) // size of directory
- b.uint32(uint32(start)) // start of directory
+ b = b[4:] // skip over disk number and first disk number (2x uint16)
+ b.uint16(uint16(records)) // number of entries this disk
+ b.uint16(uint16(records)) // number of entries total
+ b.uint32(uint32(size)) // size of directory
+ b.uint32(uint32(offset)) // start of directory
// skipped size of comment (always zero)
if _, err := w.cw.Write(buf[:]); err != nil {
return err
@@ -127,8 +186,9 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
}
fh.Flags |= 0x8 // we will write a data descriptor
- fh.CreatorVersion = fh.CreatorVersion&0xff00 | 0x14
- fh.ReaderVersion = 0x14
+
+ fh.CreatorVersion = fh.CreatorVersion&0xff00 | zipVersion20 // preserve compatibility byte
+ fh.ReaderVersion = zipVersion20
fw := &fileWriter{
zipw: w.cw,
@@ -151,7 +211,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
h := &header{
FileHeader: fh,
- offset: uint32(w.cw.count),
+ offset: uint64(w.cw.count),
}
w.dir = append(w.dir, h)
fw.header = h
@@ -173,9 +233,9 @@ func writeHeader(w io.Writer, h *FileHeader) error {
b.uint16(h.Method)
b.uint16(h.ModifiedTime)
b.uint16(h.ModifiedDate)
- b.uint32(h.CRC32)
- b.uint32(h.CompressedSize)
- b.uint32(h.UncompressedSize)
+ b.uint32(0) // since we are writing a data descriptor crc32,
+ b.uint32(0) // compressed size,
+ b.uint32(0) // and uncompressed size should be zero
b.uint16(uint16(len(h.Name)))
b.uint16(uint16(len(h.Extra)))
if _, err := w.Write(buf[:]); err != nil {
@@ -218,17 +278,40 @@ func (w *fileWriter) close() error {
// update FileHeader
fh := w.header.FileHeader
fh.CRC32 = w.crc32.Sum32()
- fh.CompressedSize = uint32(w.compCount.count)
- fh.UncompressedSize = uint32(w.rawCount.count)
+ fh.CompressedSize64 = uint64(w.compCount.count)
+ fh.UncompressedSize64 = uint64(w.rawCount.count)
- // write data descriptor
- var buf [dataDescriptorLen]byte
- b := writeBuf(buf[:])
+ if fh.isZip64() {
+ fh.CompressedSize = uint32max
+ fh.UncompressedSize = uint32max
+ fh.ReaderVersion = zipVersion45 // requires 4.5 - File uses ZIP64 format extensions
+ } else {
+ fh.CompressedSize = uint32(fh.CompressedSize64)
+ fh.UncompressedSize = uint32(fh.UncompressedSize64)
+ }
+
+ // Write data descriptor. This is more complicated than one would
+ // think, see e.g. comments in zipfile.c:putextended() and
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588.
+ // The approach here is to write 8 byte sizes if needed without
+ // adding a zip64 extra in the local header (too late anyway).
+ var buf []byte
+ if fh.isZip64() {
+ buf = make([]byte, dataDescriptor64Len)
+ } else {
+ buf = make([]byte, dataDescriptorLen)
+ }
+ b := writeBuf(buf)
b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X
b.uint32(fh.CRC32)
- b.uint32(fh.CompressedSize)
- b.uint32(fh.UncompressedSize)
- _, err := w.zipw.Write(buf[:])
+ if fh.isZip64() {
+ b.uint64(fh.CompressedSize64)
+ b.uint64(fh.UncompressedSize64)
+ } else {
+ b.uint32(fh.CompressedSize)
+ b.uint32(fh.UncompressedSize)
+ }
+ _, err := w.zipw.Write(buf)
return err
}
@@ -262,3 +345,8 @@ func (b *writeBuf) uint32(v uint32) {
binary.LittleEndian.PutUint32(*b, v)
*b = (*b)[4:]
}
+
+func (b *writeBuf) uint64(v uint64) {
+ binary.LittleEndian.PutUint64(*b, v)
+ *b = (*b)[8:]
+}
diff --git a/libgo/go/archive/zip/zip_test.go b/libgo/go/archive/zip/zip_test.go
index d6490c4cbbe..1d229d080ac 100644
--- a/libgo/go/archive/zip/zip_test.go
+++ b/libgo/go/archive/zip/zip_test.go
@@ -9,7 +9,8 @@ package zip
import (
"bytes"
"fmt"
- "reflect"
+ "io"
+ "io/ioutil"
"strings"
"testing"
"time"
@@ -58,6 +59,33 @@ func TestModTime(t *testing.T) {
}
}
+func testHeaderRoundTrip(fh *FileHeader, wantUncompressedSize uint32, wantUncompressedSize64 uint64, t *testing.T) {
+ fi := fh.FileInfo()
+ fh2, err := FileInfoHeader(fi)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got, want := fh2.Name, fh.Name; got != want {
+ t.Errorf("Name: got %s, want %s\n", got, want)
+ }
+ if got, want := fh2.UncompressedSize, wantUncompressedSize; got != want {
+ t.Errorf("UncompressedSize: got %d, want %d\n", got, want)
+ }
+ if got, want := fh2.UncompressedSize64, wantUncompressedSize64; got != want {
+ t.Errorf("UncompressedSize64: got %d, want %d\n", got, want)
+ }
+ if got, want := fh2.ModifiedTime, fh.ModifiedTime; got != want {
+ t.Errorf("ModifiedTime: got %d, want %d\n", got, want)
+ }
+ if got, want := fh2.ModifiedDate, fh.ModifiedDate; got != want {
+ t.Errorf("ModifiedDate: got %d, want %d\n", got, want)
+ }
+
+ if sysfh, ok := fi.Sys().(*FileHeader); !ok && sysfh != fh {
+ t.Errorf("Sys didn't return original *FileHeader")
+ }
+}
+
func TestFileHeaderRoundTrip(t *testing.T) {
fh := &FileHeader{
Name: "foo.txt",
@@ -65,17 +93,83 @@ func TestFileHeaderRoundTrip(t *testing.T) {
ModifiedTime: 1234,
ModifiedDate: 5678,
}
- fi := fh.FileInfo()
- fh2, err := FileInfoHeader(fi)
+ testHeaderRoundTrip(fh, fh.UncompressedSize, uint64(fh.UncompressedSize), t)
+}
- // Ignore these fields:
- fh2.CreatorVersion = 0
- fh2.ExternalAttrs = 0
+func TestFileHeaderRoundTrip64(t *testing.T) {
+ fh := &FileHeader{
+ Name: "foo.txt",
+ UncompressedSize64: 9876543210,
+ ModifiedTime: 1234,
+ ModifiedDate: 5678,
+ }
+ testHeaderRoundTrip(fh, uint32max, fh.UncompressedSize64, t)
+}
- if !reflect.DeepEqual(fh, fh2) {
- t.Errorf("mismatch\n input=%#v\noutput=%#v\nerr=%v", fh, fh2, err)
+func TestZip64(t *testing.T) {
+ if testing.Short() {
+ t.Logf("slow test; skipping")
+ return
}
- if sysfh, ok := fi.Sys().(*FileHeader); !ok && sysfh != fh {
- t.Errorf("Sys didn't return original *FileHeader")
+ // write 2^32 bytes plus "END\n" to a zip file
+ buf := new(bytes.Buffer)
+ w := NewWriter(buf)
+ f, err := w.Create("huge.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ chunk := make([]byte, 1024)
+ for i := range chunk {
+ chunk[i] = '.'
+ }
+ chunk[len(chunk)-1] = '\n'
+ end := []byte("END\n")
+ for i := 0; i < (1<<32)/1024; i++ {
+ _, err := f.Write(chunk)
+ if err != nil {
+ t.Fatal("write chunk:", err)
+ }
+ }
+ _, err = f.Write(end)
+ if err != nil {
+ t.Fatal("write end:", err)
+ }
+ if err := w.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ // read back zip file and check that we get to the end of it
+ r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
+ if err != nil {
+ t.Fatal("reader:", err)
+ }
+ f0 := r.File[0]
+ rc, err := f0.Open()
+ if err != nil {
+ t.Fatal("opening:", err)
+ }
+ for i := 0; i < (1<<32)/1024; i++ {
+ _, err := io.ReadFull(rc, chunk)
+ if err != nil {
+ t.Fatal("read:", err)
+ }
+ }
+ gotEnd, err := ioutil.ReadAll(rc)
+ if err != nil {
+ t.Fatal("read end:", err)
+ }
+ if !bytes.Equal(gotEnd, end) {
+ t.Errorf("End of zip64 archive %q, want %q", gotEnd, end)
+ }
+ err = rc.Close()
+ if err != nil {
+ t.Fatal("closing:", err)
+ }
+ if got, want := f0.UncompressedSize, uint32(uint32max); got != want {
+ t.Errorf("UncompressedSize %d, want %d", got, want)
+ }
+
+ if got, want := f0.UncompressedSize64, (1<<32)+uint64(len(end)); got != want {
+ t.Errorf("UncompressedSize64 %d, want %d", got, want)
}
}
diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go
index 0e284825bd0..d6ba485fa3e 100644
--- a/libgo/go/bufio/bufio.go
+++ b/libgo/go/bufio/bufio.go
@@ -375,6 +375,41 @@ func (b *Reader) ReadString(delim byte) (line string, err error) {
return string(bytes), e
}
+// WriteTo implements io.WriterTo.
+func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
+ n, err = b.writeBuf(w)
+ if err != nil {
+ return
+ }
+
+ if r, ok := b.rd.(io.WriterTo); ok {
+ m, err := r.WriteTo(w)
+ n += m
+ return n, err
+ }
+
+ for b.fill(); b.r < b.w; b.fill() {
+ m, err := b.writeBuf(w)
+ n += m
+ if err != nil {
+ return n, err
+ }
+ }
+
+ if b.err == io.EOF {
+ b.err = nil
+ }
+
+ return n, b.readErr()
+}
+
+// writeBuf writes the Reader's buffer to the writer.
+func (b *Reader) writeBuf(w io.Writer) (int64, error) {
+ n, err := w.Write(b.buf[b.r:b.w])
+ b.r += n
+ return int64(n), err
+}
+
// buffered output
// Writer implements buffering for an io.Writer object.
diff --git a/libgo/go/bufio/bufio_test.go b/libgo/go/bufio/bufio_test.go
index a43cbd23a64..4e10207efbd 100644
--- a/libgo/go/bufio/bufio_test.go
+++ b/libgo/go/bufio/bufio_test.go
@@ -762,3 +762,107 @@ func testReadLineNewlines(t *testing.T, input string, expect []readLineResult) {
}
}
}
+
+func TestReaderWriteTo(t *testing.T) {
+ input := make([]byte, 8192)
+ for i := range input {
+ // 101 and 251 are arbitrary prime numbers.
+ // The idea is to create an input sequence
+ // which doesn't repeat too frequently.
+ input[i] = byte(i % 251)
+ if i%101 == 0 {
+ input[i] ^= byte(i / 101)
+ }
+ }
+ r := NewReader(bytes.NewBuffer(input))
+ w := new(bytes.Buffer)
+ if n, err := r.WriteTo(w); err != nil || n != int64(len(input)) {
+ t.Fatalf("r.WriteTo(w) = %d, %v, want %d, nil", n, err, len(input))
+ }
+
+ for i, val := range w.Bytes() {
+ if val != input[i] {
+ t.Errorf("after write: out[%d] = %#x, want %#x", i, val, input[i])
+ }
+ }
+}
+
+type errorWriterToTest struct {
+ rn, wn int
+ rerr, werr error
+ expected error
+}
+
+func (r errorWriterToTest) Read(p []byte) (int, error) {
+ return len(p) * r.rn, r.rerr
+}
+
+func (w errorWriterToTest) Write(p []byte) (int, error) {
+ return len(p) * w.wn, w.werr
+}
+
+var errorWriterToTests = []errorWriterToTest{
+ {1, 0, nil, io.ErrClosedPipe, io.ErrClosedPipe},
+ {0, 1, io.ErrClosedPipe, nil, io.ErrClosedPipe},
+ {0, 0, io.ErrUnexpectedEOF, io.ErrClosedPipe, io.ErrClosedPipe},
+ {0, 1, io.EOF, nil, nil},
+}
+
+func TestReaderWriteToErrors(t *testing.T) {
+ for i, rw := range errorWriterToTests {
+ r := NewReader(rw)
+ if _, err := r.WriteTo(rw); err != rw.expected {
+ t.Errorf("r.WriteTo(errorWriterToTests[%d]) = _, %v, want _,%v", i, err, rw.expected)
+ }
+ }
+}
+
+// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have.
+type onlyReader struct {
+ r io.Reader
+}
+
+func (r *onlyReader) Read(b []byte) (int, error) {
+ return r.r.Read(b)
+}
+
+// An onlyWriter only implements io.Writer, no matter what other methods the underlying implementation may have.
+type onlyWriter struct {
+ w io.Writer
+}
+
+func (w *onlyWriter) Write(b []byte) (int, error) {
+ return w.w.Write(b)
+}
+
+func BenchmarkReaderCopyOptimal(b *testing.B) {
+ // Optimal case is where the underlying reader implements io.WriterTo
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+ src := NewReader(bytes.NewBuffer(make([]byte, 8192)))
+ dst := &onlyWriter{new(bytes.Buffer)}
+ b.StartTimer()
+ io.Copy(dst, src)
+ }
+}
+
+func BenchmarkReaderCopyUnoptimal(b *testing.B) {
+ // Unoptimal case is where the underlying reader doesn't implement io.WriterTo
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+ src := NewReader(&onlyReader{bytes.NewBuffer(make([]byte, 8192))})
+ dst := &onlyWriter{new(bytes.Buffer)}
+ b.StartTimer()
+ io.Copy(dst, src)
+ }
+}
+
+func BenchmarkReaderCopyNoWriteTo(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+ src := &onlyReader{NewReader(bytes.NewBuffer(make([]byte, 8192)))}
+ dst := &onlyWriter{new(bytes.Buffer)}
+ b.StartTimer()
+ io.Copy(dst, src)
+ }
+}
diff --git a/libgo/go/bytes/buffer.go b/libgo/go/bytes/buffer.go
index afdf2205598..efb9798ee01 100644
--- a/libgo/go/bytes/buffer.go
+++ b/libgo/go/bytes/buffer.go
@@ -99,6 +99,19 @@ func (b *Buffer) grow(n int) int {
return b.off + m
}
+// Grow grows the buffer's capacity, if necessary, to guarantee space for
+// another n bytes. After Grow(n), at least n bytes can be written to the
+// buffer without another allocation.
+// If n is negative, Grow will panic.
+// If the buffer can't grow it will panic with ErrTooLarge.
+func (b *Buffer) Grow(n int) {
+ if n < 0 {
+ panic("bytes.Buffer.Grow: negative count")
+ }
+ m := b.grow(n)
+ b.buf = b.buf[0:m]
+}
+
// Write appends the contents of p to the buffer. The return
// value n is the length of p; err is always nil.
// If the buffer becomes too large, Write will panic with
diff --git a/libgo/go/bytes/buffer_test.go b/libgo/go/bytes/buffer_test.go
index d0af11f104b..dfecea19ae3 100644
--- a/libgo/go/bytes/buffer_test.go
+++ b/libgo/go/bytes/buffer_test.go
@@ -8,20 +8,21 @@ import (
. "bytes"
"io"
"math/rand"
+ "runtime"
"testing"
"unicode/utf8"
)
-const N = 10000 // make this bigger for a larger (and slower) test
-var data string // test data for write tests
-var bytes []byte // test data; same as data but as a slice.
+const N = 10000 // make this bigger for a larger (and slower) test
+var data string // test data for write tests
+var testBytes []byte // test data; same as data but as a slice.
func init() {
- bytes = make([]byte, N)
+ testBytes = make([]byte, N)
for i := 0; i < N; i++ {
- bytes[i] = 'a' + byte(i%26)
+ testBytes[i] = 'a' + byte(i%26)
}
- data = string(bytes)
+ data = string(testBytes)
}
// Verify that contents of buf match the string s.
@@ -84,7 +85,7 @@ func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub
}
func TestNewBuffer(t *testing.T) {
- buf := NewBuffer(bytes)
+ buf := NewBuffer(testBytes)
check(t, "NewBuffer", buf, data)
}
@@ -187,7 +188,7 @@ func TestLargeByteWrites(t *testing.T) {
limit = 9
}
for i := 3; i < limit; i += 3 {
- s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, bytes)
+ s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, testBytes)
empty(t, "TestLargeByteWrites (2)", &buf, s, make([]byte, len(data)/i))
}
check(t, "TestLargeByteWrites (3)", &buf, "")
@@ -205,7 +206,7 @@ func TestLargeStringReads(t *testing.T) {
func TestLargeByteReads(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
- s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, bytes[0:len(bytes)/i])
+ s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data)))
}
check(t, "TestLargeByteReads (3)", &buf, "")
@@ -219,7 +220,7 @@ func TestMixedReadsAndWrites(t *testing.T) {
if i%2 == 0 {
s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0:wlen])
} else {
- s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, bytes[0:wlen])
+ s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testBytes[0:wlen])
}
rlen := rand.Intn(len(data))
@@ -240,7 +241,7 @@ func TestNil(t *testing.T) {
func TestReadFrom(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
- s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, bytes[0:len(bytes)/i])
+ s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
var b Buffer
b.ReadFrom(&buf)
empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(data)))
@@ -250,7 +251,7 @@ func TestReadFrom(t *testing.T) {
func TestWriteTo(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
- s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, bytes[0:len(bytes)/i])
+ s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
var b Buffer
buf.WriteTo(&b)
empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(data)))
@@ -374,6 +375,37 @@ func TestReadBytes(t *testing.T) {
}
}
+func TestGrow(t *testing.T) {
+ x := []byte{'x'}
+ y := []byte{'y'}
+ tmp := make([]byte, 72)
+ for _, startLen := range []int{0, 100, 1000, 10000, 100000} {
+ xBytes := Repeat(x, startLen)
+ for _, growLen := range []int{0, 100, 1000, 10000, 100000} {
+ buf := NewBuffer(xBytes)
+ // If we read, this affects buf.off, which is good to test.
+ readBytes, _ := buf.Read(tmp)
+ buf.Grow(growLen)
+ yBytes := Repeat(y, growLen)
+ // Check no allocation occurs in write, as long as we're single-threaded.
+ var m1, m2 runtime.MemStats
+ runtime.ReadMemStats(&m1)
+ buf.Write(yBytes)
+ runtime.ReadMemStats(&m2)
+ if runtime.GOMAXPROCS(-1) == 1 && m1.Mallocs != m2.Mallocs {
+ t.Errorf("allocation occurred during write")
+ }
+ // Check that buffer has correct data.
+ if !Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) {
+ t.Errorf("bad initial data at %d %d", startLen, growLen)
+ }
+ if !Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) {
+ t.Errorf("bad written data at %d %d", startLen, growLen)
+ }
+ }
+ }
+}
+
// Was a bug: used to give EOF reading empty slice at EOF.
func TestReadEmptyAtEOF(t *testing.T) {
b := new(Buffer)
diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go
index 09b3c1a2705..c3980bb2ab5 100644
--- a/libgo/go/bytes/bytes.go
+++ b/libgo/go/bytes/bytes.go
@@ -333,14 +333,15 @@ func FieldsFunc(s []byte, f func(rune) bool) [][]byte {
return a[0:na]
}
-// Join concatenates the elements of a to create a single byte array. The separator
+// Join concatenates the elements of a to create a new byte array. The separator
// sep is placed between elements in the resulting array.
func Join(a [][]byte, sep []byte) []byte {
if len(a) == 0 {
return []byte{}
}
if len(a) == 1 {
- return a[0]
+ // Just return a copy.
+ return append([]byte(nil), a[0]...)
}
n := len(sep) * (len(a) - 1)
for i := 0; i < len(a); i++ {
@@ -619,10 +620,8 @@ func Replace(s, old, new []byte, n int) []byte {
m = Count(s, old)
}
if m == 0 {
- // Nothing to do. Just copy.
- t := make([]byte, len(s))
- copy(t, s)
- return t
+ // Just return a copy.
+ return append([]byte(nil), s...)
}
if n < 0 || m < n {
n = m
diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go
index 000f235176d..124760ac741 100644
--- a/libgo/go/bytes/bytes_test.go
+++ b/libgo/go/bytes/bytes_test.go
@@ -6,6 +6,7 @@ package bytes_test
import (
. "bytes"
+ "math/rand"
"reflect"
"testing"
"unicode"
@@ -490,6 +491,12 @@ func TestSplit(t *testing.T) {
t.Errorf("Split disagrees withSplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
}
}
+ if len(a) > 0 {
+ in, out := a[0], s
+ if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] {
+ t.Errorf("Join(%#v, %q) didn't copy", a, tt.sep)
+ }
+ }
}
}
@@ -561,6 +568,14 @@ func TestFields(t *testing.T) {
}
func TestFieldsFunc(t *testing.T) {
+ for _, tt := range fieldstests {
+ a := FieldsFunc([]byte(tt.s), unicode.IsSpace)
+ result := arrayOfString(a)
+ if !eq(result, tt.a) {
+ t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a)
+ continue
+ }
+ }
pred := func(c rune) bool { return c == 'X' }
var fieldsFuncTests = []FieldsTest{
{"", []string{}},
@@ -1008,3 +1023,39 @@ func TestEqualFold(t *testing.T) {
}
}
}
+
+var makeFieldsInput = func() []byte {
+ x := make([]byte, 1<<20)
+ // Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
+ for i := range x {
+ switch rand.Intn(10) {
+ case 0:
+ x[i] = ' '
+ case 1:
+ if i > 0 && x[i-1] == 'x' {
+ copy(x[i-1:], "χ")
+ break
+ }
+ fallthrough
+ default:
+ x[i] = 'x'
+ }
+ }
+ return x
+}
+
+var fieldsInput = makeFieldsInput()
+
+func BenchmarkFields(b *testing.B) {
+ b.SetBytes(int64(len(fieldsInput)))
+ for i := 0; i < b.N; i++ {
+ Fields(fieldsInput)
+ }
+}
+
+func BenchmarkFieldsFunc(b *testing.B) {
+ b.SetBytes(int64(len(fieldsInput)))
+ for i := 0; i < b.N; i++ {
+ FieldsFunc(fieldsInput, unicode.IsSpace)
+ }
+}
diff --git a/libgo/go/bytes/example_test.go b/libgo/go/bytes/example_test.go
index 6fe8cd5a90c..1774a5ab426 100644
--- a/libgo/go/bytes/example_test.go
+++ b/libgo/go/bytes/example_test.go
@@ -5,23 +5,24 @@
package bytes_test
import (
- . "bytes"
+ "bytes"
"encoding/base64"
+ "fmt"
"io"
"os"
)
func ExampleBuffer() {
- var b Buffer // A Buffer needs no initialization.
+ var b bytes.Buffer // A Buffer needs no initialization.
b.Write([]byte("Hello "))
- b.Write([]byte("world!"))
+ fmt.Fprintf(&b, "world!")
b.WriteTo(os.Stdout)
// Output: Hello world!
}
func ExampleBuffer_reader() {
// A Buffer can turn a string or a []byte into an io.Reader.
- buf := NewBufferString("R29waGVycyBydWxlIQ==")
+ buf := bytes.NewBufferString("R29waGVycyBydWxlIQ==")
dec := base64.NewDecoder(base64.StdEncoding, buf)
io.Copy(os.Stdout, dec)
// Output: Gophers rule!
diff --git a/libgo/go/compress/flate/copy.go b/libgo/go/compress/flate/copy.go
new file mode 100644
index 00000000000..06e5d2e66d9
--- /dev/null
+++ b/libgo/go/compress/flate/copy.go
@@ -0,0 +1,17 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package flate
+
+// forwardCopy is like the built-in copy function except that it always goes
+// forward from the start, even if the dst and src overlap.
+func forwardCopy(dst, src []byte) int {
+ if len(src) > len(dst) {
+ src = src[:len(dst)]
+ }
+ for i, x := range src {
+ dst[i] = x
+ }
+ return len(src)
+}
diff --git a/libgo/go/compress/flate/copy_test.go b/libgo/go/compress/flate/copy_test.go
new file mode 100644
index 00000000000..a9281d446e9
--- /dev/null
+++ b/libgo/go/compress/flate/copy_test.go
@@ -0,0 +1,52 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package flate
+
+import (
+ "testing"
+)
+
+func TestForwardCopy(t *testing.T) {
+ testCases := []struct {
+ dst0, dst1 int
+ src0, src1 int
+ want string
+ }{
+ {0, 9, 0, 9, "012345678"},
+ {0, 5, 4, 9, "45678"},
+ {4, 9, 0, 5, "01230"},
+ {1, 6, 3, 8, "34567"},
+ {3, 8, 1, 6, "12121"},
+ {0, 9, 3, 6, "345"},
+ {3, 6, 0, 9, "012"},
+ {1, 6, 0, 9, "00000"},
+ {0, 4, 7, 8, "7"},
+ {0, 1, 6, 8, "6"},
+ {4, 4, 6, 9, ""},
+ {2, 8, 6, 6, ""},
+ {0, 0, 0, 0, ""},
+ }
+ for _, tc := range testCases {
+ b := []byte("0123456789")
+ dst := b[tc.dst0:tc.dst1]
+ src := b[tc.src0:tc.src1]
+ n := forwardCopy(dst, src)
+ got := string(dst[:n])
+ if got != tc.want {
+ t.Errorf("dst=b[%d:%d], src=b[%d:%d]: got %q, want %q",
+ tc.dst0, tc.dst1, tc.src0, tc.src1, got, tc.want)
+ }
+ // Check that the bytes outside of dst[:n] were not modified.
+ for i, x := range b {
+ if i >= tc.dst0 && i < tc.dst0+n {
+ continue
+ }
+ if int(x) != '0'+i {
+ t.Errorf("dst=b[%d:%d], src=b[%d:%d]: copy overrun at b[%d]: got '%c', want '%c'",
+ tc.dst0, tc.dst1, tc.src0, tc.src1, i, x, '0'+i)
+ }
+ }
+ }
+}
diff --git a/libgo/go/compress/flate/deflate_test.go b/libgo/go/compress/flate/deflate_test.go
index f1e6db2ace4..e0b225e2988 100644
--- a/libgo/go/compress/flate/deflate_test.go
+++ b/libgo/go/compress/flate/deflate_test.go
@@ -334,7 +334,7 @@ var deflateInflateStringTests = []deflateInflateStringTest{
{
"../testdata/e.txt",
"2.718281828...",
- [...]int{10013, 5065, 5096, 5115, 5093, 5079, 5079, 5079, 5079, 5079},
+ [...]int{100018, 50650, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790},
},
{
"../testdata/Mark.Twain-Tom.Sawyer.txt",
diff --git a/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go
index 394c32fa3a6..c7ef5ff7e60 100644
--- a/libgo/go/compress/flate/inflate.go
+++ b/libgo/go/compress/flate/inflate.go
@@ -212,7 +212,7 @@ type decompressor struct {
codebits [numCodes]int
// Output history, buffer.
- hist [maxHist]byte
+ hist *[maxHist]byte
hp int // current output position in buffer
hw int // have written hist[0:hw] already
hfull bool // buffer has filled at least once
@@ -511,51 +511,49 @@ func (f *decompressor) huffmanBlock() {
return
}
- p := f.hp - dist
- if p < 0 {
- p += len(f.hist)
- }
- for i := 0; i < length; i++ {
- f.hist[f.hp] = f.hist[p]
- f.hp++
- p++
- if f.hp == len(f.hist) {
- // After flush continue copying out of history.
- f.copyLen = length - (i + 1)
- f.copyDist = dist
- f.flush((*decompressor).copyHuff)
- return
- }
- if p == len(f.hist) {
- p = 0
- }
+ f.copyLen, f.copyDist = length, dist
+ if f.copyHist() {
+ return
}
}
panic("unreached")
}
-func (f *decompressor) copyHuff() {
- length := f.copyLen
- dist := f.copyDist
- p := f.hp - dist
+// copyHist copies f.copyLen bytes from f.hist (f.copyDist bytes ago) to itself.
+// It reports whether the f.hist buffer is full.
+func (f *decompressor) copyHist() bool {
+ p := f.hp - f.copyDist
if p < 0 {
p += len(f.hist)
}
- for i := 0; i < length; i++ {
- f.hist[f.hp] = f.hist[p]
- f.hp++
- p++
+ for f.copyLen > 0 {
+ n := f.copyLen
+ if x := len(f.hist) - f.hp; n > x {
+ n = x
+ }
+ if x := len(f.hist) - p; n > x {
+ n = x
+ }
+ forwardCopy(f.hist[f.hp:f.hp+n], f.hist[p:p+n])
+ p += n
+ f.hp += n
+ f.copyLen -= n
if f.hp == len(f.hist) {
- f.copyLen = length - (i + 1)
+ // After flush continue copying out of history.
f.flush((*decompressor).copyHuff)
- return
+ return true
}
if p == len(f.hist) {
p = 0
}
}
+ return false
+}
- // Continue processing Huffman block.
+func (f *decompressor) copyHuff() {
+ if f.copyHist() {
+ return
+ }
f.huffmanBlock()
}
@@ -590,9 +588,9 @@ func (f *decompressor) dataBlock() {
f.copyData()
}
+// copyData copies f.copyLen bytes from the underlying reader into f.hist.
+// It pauses for reads when f.hist is full.
func (f *decompressor) copyData() {
- // Read f.dataLen bytes into history,
- // pausing for reads as history fills.
n := f.copyLen
for n > 0 {
m := len(f.hist) - f.hp
@@ -695,6 +693,7 @@ func makeReader(r io.Reader) Reader {
func NewReader(r io.Reader) io.ReadCloser {
var f decompressor
f.r = makeReader(r)
+ f.hist = new([maxHist]byte)
f.step = (*decompressor).nextBlock
return &f
}
@@ -706,8 +705,9 @@ func NewReader(r io.Reader) io.ReadCloser {
// to read data compressed by NewWriterDict.
func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser {
var f decompressor
- f.setDict(dict)
f.r = makeReader(r)
+ f.hist = new([maxHist]byte)
f.step = (*decompressor).nextBlock
+ f.setDict(dict)
return &f
}
diff --git a/libgo/go/compress/flate/writer_test.go b/libgo/go/compress/flate/writer_test.go
new file mode 100644
index 00000000000..58431774e0e
--- /dev/null
+++ b/libgo/go/compress/flate/writer_test.go
@@ -0,0 +1,60 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package flate
+
+import (
+ "io/ioutil"
+ "runtime"
+ "testing"
+)
+
+func benchmarkEncoder(b *testing.B, testfile, level, n int) {
+ b.StopTimer()
+ b.SetBytes(int64(n))
+ buf0, err := ioutil.ReadFile(testfiles[testfile])
+ if err != nil {
+ b.Fatal(err)
+ }
+ if len(buf0) == 0 {
+ b.Fatalf("test file %q has no data", testfiles[testfile])
+ }
+ buf1 := make([]byte, n)
+ for i := 0; i < n; i += len(buf0) {
+ if len(buf0) > n-i {
+ buf0 = buf0[:n-i]
+ }
+ copy(buf1[i:], buf0)
+ }
+ buf0 = nil
+ runtime.GC()
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ w, err := NewWriter(ioutil.Discard, level)
+ if err != nil {
+ b.Fatal(err)
+ }
+ w.Write(buf1)
+ w.Close()
+ }
+}
+
+func BenchmarkEncodeDigitsSpeed1e4(b *testing.B) { benchmarkEncoder(b, digits, speed, 1e4) }
+func BenchmarkEncodeDigitsSpeed1e5(b *testing.B) { benchmarkEncoder(b, digits, speed, 1e5) }
+func BenchmarkEncodeDigitsSpeed1e6(b *testing.B) { benchmarkEncoder(b, digits, speed, 1e6) }
+func BenchmarkEncodeDigitsDefault1e4(b *testing.B) { benchmarkEncoder(b, digits, default_, 1e4) }
+func BenchmarkEncodeDigitsDefault1e5(b *testing.B) { benchmarkEncoder(b, digits, default_, 1e5) }
+func BenchmarkEncodeDigitsDefault1e6(b *testing.B) { benchmarkEncoder(b, digits, default_, 1e6) }
+func BenchmarkEncodeDigitsCompress1e4(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e4) }
+func BenchmarkEncodeDigitsCompress1e5(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e5) }
+func BenchmarkEncodeDigitsCompress1e6(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e6) }
+func BenchmarkEncodeTwainSpeed1e4(b *testing.B) { benchmarkEncoder(b, twain, speed, 1e4) }
+func BenchmarkEncodeTwainSpeed1e5(b *testing.B) { benchmarkEncoder(b, twain, speed, 1e5) }
+func BenchmarkEncodeTwainSpeed1e6(b *testing.B) { benchmarkEncoder(b, twain, speed, 1e6) }
+func BenchmarkEncodeTwainDefault1e4(b *testing.B) { benchmarkEncoder(b, twain, default_, 1e4) }
+func BenchmarkEncodeTwainDefault1e5(b *testing.B) { benchmarkEncoder(b, twain, default_, 1e5) }
+func BenchmarkEncodeTwainDefault1e6(b *testing.B) { benchmarkEncoder(b, twain, default_, 1e6) }
+func BenchmarkEncodeTwainCompress1e4(b *testing.B) { benchmarkEncoder(b, twain, compress, 1e4) }
+func BenchmarkEncodeTwainCompress1e5(b *testing.B) { benchmarkEncoder(b, twain, compress, 1e5) }
+func BenchmarkEncodeTwainCompress1e6(b *testing.B) { benchmarkEncoder(b, twain, compress, 1e6) }
diff --git a/libgo/go/compress/lzw/reader_test.go b/libgo/go/compress/lzw/reader_test.go
index e5be12f54e8..6f155b1bdee 100644
--- a/libgo/go/compress/lzw/reader_test.go
+++ b/libgo/go/compress/lzw/reader_test.go
@@ -114,11 +114,19 @@ func TestReader(t *testing.T) {
func benchmarkDecoder(b *testing.B, n int) {
b.StopTimer()
b.SetBytes(int64(n))
- buf0, _ := ioutil.ReadFile("../testdata/e.txt")
- buf0 = buf0[:10000]
+ buf0, err := ioutil.ReadFile("../testdata/e.txt")
+ if err != nil {
+ b.Fatal(err)
+ }
+ if len(buf0) == 0 {
+ b.Fatalf("test file has no data")
+ }
compressed := new(bytes.Buffer)
w := NewWriter(compressed, LSB, 8)
for i := 0; i < n; i += len(buf0) {
+ if len(buf0) > n-i {
+ buf0 = buf0[:n-i]
+ }
io.Copy(w, bytes.NewBuffer(buf0))
}
w.Close()
diff --git a/libgo/go/compress/lzw/writer.go b/libgo/go/compress/lzw/writer.go
index 488ba6428db..c6f891b4bc0 100644
--- a/libgo/go/compress/lzw/writer.go
+++ b/libgo/go/compress/lzw/writer.go
@@ -131,13 +131,14 @@ func (e *encoder) incHi() error {
}
// Write writes a compressed representation of p to e's underlying writer.
-func (e *encoder) Write(p []byte) (int, error) {
+func (e *encoder) Write(p []byte) (n int, err error) {
if e.err != nil {
return 0, e.err
}
if len(p) == 0 {
return 0, nil
}
+ n = len(p)
litMask := uint32(1<<e.litWidth - 1)
code := e.savedCode
if code == invalidCode {
@@ -167,11 +168,11 @@ loop:
code = literal
// Increment e.hi, the next implied code. If we run out of codes, reset
// the encoder state (including clearing the hash table) and continue.
- if err := e.incHi(); err != nil {
- if err == errOutOfCodes {
+ if err1 := e.incHi(); err1 != nil {
+ if err1 == errOutOfCodes {
continue
}
- e.err = err
+ e.err = err1
return 0, e.err
}
// Otherwise, insert key -> e.hi into the map that e.table represents.
@@ -184,7 +185,7 @@ loop:
}
}
e.savedCode = code
- return len(p), nil
+ return n, nil
}
// Close closes the encoder, flushing any pending output. It does not close or
diff --git a/libgo/go/compress/lzw/writer_test.go b/libgo/go/compress/lzw/writer_test.go
index d249a09b295..3e4e6de2114 100644
--- a/libgo/go/compress/lzw/writer_test.go
+++ b/libgo/go/compress/lzw/writer_test.go
@@ -96,13 +96,29 @@ func TestWriter(t *testing.T) {
}
}
+func TestWriterReturnValues(t *testing.T) {
+ w := NewWriter(ioutil.Discard, LSB, 8)
+ n, err := w.Write([]byte("asdf"))
+ if n != 4 || err != nil {
+ t.Errorf("got %d, %v, want 4, nil", n, err)
+ }
+}
+
func benchmarkEncoder(b *testing.B, n int) {
b.StopTimer()
b.SetBytes(int64(n))
- buf0, _ := ioutil.ReadFile("../testdata/e.txt")
- buf0 = buf0[:10000]
+ buf0, err := ioutil.ReadFile("../testdata/e.txt")
+ if err != nil {
+ b.Fatal(err)
+ }
+ if len(buf0) == 0 {
+ b.Fatalf("test file has no data")
+ }
buf1 := make([]byte, n)
for i := 0; i < n; i += len(buf0) {
+ if len(buf0) > n-i {
+ buf0 = buf0[:n-i]
+ }
copy(buf1[i:], buf0)
}
buf0 = nil
diff --git a/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt b/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt
index 8d0ff4e65ce..c97da7eccf3 100644
--- a/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt
+++ b/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt
@@ -1,4 +1,4 @@
-The Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
+The Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
by Mark Twain (Samuel Clemens)
This eBook is for the use of anyone anywhere at no cost and with
diff --git a/libgo/go/compress/testdata/e.txt b/libgo/go/compress/testdata/e.txt
index 76cf2a7b691..5ca186f14c1 100644
--- a/libgo/go/compress/testdata/e.txt
+++ b/libgo/go/compress/testdata/e.txt
@@ -1 +1 @@
-2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190115738341879307021540891499348841675092447614606680822648001684774118537423454424371075390777449920695517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416928368190255151086574637721112523897844250569536967707854499699679468644549059879316368892300987931277361782154249992295763514822082698951936680331825288693984964651058209392398294887933203625094431173012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509961818815930416903515988885193458072738667385894228792284998920868058257492796104841984443634632449684875602336248270419786232090021609902353043699418491463140934317381436405462531520961836908887070167683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354021234078498193343210681701210056278802351930332247450158539047304199577770935036604169973297250886876966403555707162268447162560798826517871341951246652010305921236677194325278675398558944896970964097545918569563802363701621120477427228364896134225164450781824423529486363721417402388934412479635743702637552944483379980161254922785092577825620926226483262779333865664816277251640191059004916449982893150566047258027786318641551956532442586982946959308019152987211725563475463964479101459040905862984967912874068705048958586717479854667757573205681288459205413340539220001137863009455606881667400169842055804033637953764520304024322566135278369511778838638744396625322498506549958862342818997077332761717839280349465014345588970719425863987727547109629537415211151368350627526023264847287039207643100595841166120545297030236472549296669381151373227536450988890313602057248176585118063036442812314965507047510254465011727211555194866850800368532281831521960037356252794495158284188294787610852639813955990067376482922443752871846245780361929819713991475644882626039033814418232625150974827987779964373089970388867782271383605772978824125611907176639465070633045279546618550966661856647097113444740160704626215680717481877844371436988218559670959102596862002353718588748569652200050311734392073211390803293634479727355955277349071783793421637012050054513263835440001863239914907054797780566978533580489669062951194324730995876552368128590413832411607226029983305353708761389396391779574540161372236187893652605381558415871869255386061647798340254351284396129460352913325942794904337299085731580290958631382683291477116396337092400316894586360606458459251269946557248391865642097526850823075442545993769170419777800853627309417101634349076964237222943523661255725088147792231519747780605696725380171807763603462459278778465850656050780844211529697521890874019660906651803516501792504619501366585436632712549639908549144200014574760819302212066024330096412704894390397177195180699086998606636583232278709376502260149291011517177635944602023249300280401867723910288097866605651183260043688508817157238669842242201024950551881694803221002515426494639812873677658927688163598312477886520141174110913601164995076629077943646005851941998560162647907615321038727557126992518275687989302761761146162549356495903798045838182323368612016243736569846703785853305275833337939907521660692380533698879565137285593883499894707416181550125397064648171946708348197214488898790676503795903669672494992545279033729636162658976039498576741397359441023744329709355477982629614591442936451428617158587339746791897571211956187385783644758448423555581050025611492391518893099463428413936080383091662818811503715284967059741625628236092168075150177725387402564253470879089137291722828611515915683725241630772254406337875931059826760944203261924285317018781772960235413060672136046000389661093647095141417185777014180606443636815464440053316087783143174440811949422975599314011888683314832802706553833004693290115744147563139997221703804617092894579096271662260740718749975359212756084414737823303270330168237193648002173285734935947564334129943024850235732214597843282641421684878721673367010615094243456984401873312810107945127223737886126058165668053714396127888732527373890392890506865324138062796025930387727697783792868409325365880733988457218746021005311483351323850047827169376218004904795597959290591655470505777514308175112698985188408718564026035305583737832422924185625644255022672155980274012617971928047139600689163828665277009752767069777036439260224372841840883251848770472638440379530166905465937461619323840363893131364327137688841026811219891275223056256756254701725086349765367288605966752740868627407912856576996313789753034660616669804218267724560530660773899624218340859882071864682623215080288286359746839654358856685503773131296587975810501214916207656769950659715344763470320853215603674828608378656803073062657633469774295634643716709397193060876963495328846833613038829431040800296873869117066666146800015121143442256023874474325250769387077775193299942137277211258843608715834835626961661980572526612206797540621062080649882918454395301529982092503005498257043390553570168653120526495614857249257386206917403695213533732531666345466588597286659451136441370331393672118569553952108458407244323835586063106806964924851232632699514603596037297253198368423363904632136710116192821711150282801604488058802382031981493096369596735832742024988245684941273860566491352526706046234450549227581151709314921879592718001940968866986837037302200475314338181092708030017205935530520700706072233999463990571311587099635777359027196285061146514837526209565346713290025994397663114545902685898979115837093419370441155121920117164880566945938131183843765620627846310490346293950029458341164824114969758326011800731699437393506966295712410273239138741754923071862454543222039552735295240245903805744502892246886285336542213815722131163288112052146489805180092024719391710555390113943316681515828843687606961102505171007392762385553386272553538830960671644662370922646809671254061869502143176211668140097595281493907222601112681153108387317617323235263605838173151034595736538223534992935822836851007810884634349983518404451704270189381994243410090575376257767571118090088164183319201962623416288166521374717325477727783488774366518828752156685719506371936565390389449366421764003121527870222366463635755503565576948886549500270853923617105502131147413744106134445544192101336172996285694899193369184729478580729156088510396781959429833186480756083679551496636448965592948187851784038773326247051945050419847742014183947731202815886845707290544057510601285258056594703046836344592652552137008068752009593453607316226118728173928074623094685367823106097921599360019946237993434210687813497346959246469752506246958616909178573976595199392993995567542714654910456860702099012606818704984178079173924071945996323060254707901774527513186809982284730860766536866855516467702911336827563107223346726113705490795365834538637196235856312618387156774118738527722922594743373785695538456246801013905727871016512966636764451872465653730402443684140814488732957847348490003019477888020460324660842875351848364959195082888323206522128104190448047247949291342284951970022601310430062410717971502793433263407995960531446053230488528972917659876016667811937932372453857209607582277178483361613582612896226118129455927462767137794487586753657544861407611931125958512655759734573015333642630767985443385761715333462325270572005303988289499034259566232975782488735029259166825894456894655992658454762694528780516501720674785417887982276806536650641910973434528878338621726156269582654478205672987756426325321594294418039943217000090542650763095588465895171709147607437136893319469090981904501290307099566226620303182649365733698419555776963787624918852865686607600566025605445711337286840205574416030837052312242587223438854123179481388550075689381124935386318635287083799845692619981794523364087429591180747453419551420351726184200845509170845682368200897739455842679214273477560879644279202708312150156406341341617166448069815483764491573900121217041547872591998943825364950514771379399147205219529079396137621107238494290616357604596231253506068537651423115349665683715116604220796394466621163255157729070978473156278277598788136491951257483328793771571459091064841642678309949723674420175862269402159407924480541255360431317992696739157542419296607312393763542139230617876753958711436104089409966089471418340698362993675362621545247298464213752891079884381306095552622720837518629837066787224430195793793786072107254277289071732854874374355781966511716618330881129120245204048682200072344035025448202834254187884653602591506445271657700044521097735585897622655484941621714989532383421600114062950718490427789258552743035221396835679018076406042138307308774460170842688272261177180842664333651780002171903449234264266292261456004337383868335555343453004264818473989215627086095650629340405264943244261445665921291225648893569655009154306426134252668472594914314239398845432486327461842846655985332312210466259890141712103446084271616619001257195870793217569698544013397622096749454185407118446433946990162698351607848924514058940946395267807354579700307051163682519487701189764002827648414160587206184185297189154019688253289309149665345753571427318482016384644832499037886069008072709327673127581966563941148961716832980455139729506687604740915420428429993541025829113502241690769431668574242522509026939034814856451303069925199590436384028429267412573422447765584177886171737265462085498294498946787350929581652632072258992368768457017823038096567883112289305809140572610865884845873101658151167533327674887014829167419701512559782572707406431808601428149024146780472327597684269633935773542930186739439716388611764209004068663398856841681003872389214483176070116684503887212364367043314091155733280182977988736590916659612402021778558854876176161989370794380056663364884365089144805571039765214696027662583599051987042300179465536788
+2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190115738341879307021540891499348841675092447614606680822648001684774118537423454424371075390777449920695517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416928368190255151086574637721112523897844250569536967707854499699679468644549059879316368892300987931277361782154249992295763514822082698951936680331825288693984964651058209392398294887933203625094431173012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509961818815930416903515988885193458072738667385894228792284998920868058257492796104841984443634632449684875602336248270419786232090021609902353043699418491463140934317381436405462531520961836908887070167683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354021234078498193343210681701210056278802351930332247450158539047304199577770935036604169973297250886876966403555707162268447162560798826517871341951246652010305921236677194325278675398558944896970964097545918569563802363701621120477427228364896134225164450781824423529486363721417402388934412479635743702637552944483379980161254922785092577825620926226483262779333865664816277251640191059004916449982893150566047258027786318641551956532442586982946959308019152987211725563475463964479101459040905862984967912874068705048958586717479854667757573205681288459205413340539220001137863009455606881667400169842055804033637953764520304024322566135278369511778838638744396625322498506549958862342818997077332761717839280349465014345588970719425863987727547109629537415211151368350627526023264847287039207643100595841166120545297030236472549296669381151373227536450988890313602057248176585118063036442812314965507047510254465011727211555194866850800368532281831521960037356252794495158284188294787610852639813955990067376482922443752871846245780361929819713991475644882626039033814418232625150974827987779964373089970388867782271383605772978824125611907176639465070633045279546618550966661856647097113444740160704626215680717481877844371436988218559670959102596862002353718588748569652200050311734392073211390803293634479727355955277349071783793421637012050054513263835440001863239914907054797780566978533580489669062951194324730995876552368128590413832411607226029983305353708761389396391779574540161372236187893652605381558415871869255386061647798340254351284396129460352913325942794904337299085731580290958631382683291477116396337092400316894586360606458459251269946557248391865642097526850823075442545993769170419777800853627309417101634349076964237222943523661255725088147792231519747780605696725380171807763603462459278778465850656050780844211529697521890874019660906651803516501792504619501366585436632712549639908549144200014574760819302212066024330096412704894390397177195180699086998606636583232278709376502260149291011517177635944602023249300280401867723910288097866605651183260043688508817157238669842242201024950551881694803221002515426494639812873677658927688163598312477886520141174110913601164995076629077943646005851941998560162647907615321038727557126992518275687989302761761146162549356495903798045838182323368612016243736569846703785853305275833337939907521660692380533698879565137285593883499894707416181550125397064648171946708348197214488898790676503795903669672494992545279033729636162658976039498576741397359441023744329709355477982629614591442936451428617158587339746791897571211956187385783644758448423555581050025611492391518893099463428413936080383091662818811503715284967059741625628236092168075150177725387402564253470879089137291722828611515915683725241630772254406337875931059826760944203261924285317018781772960235413060672136046000389661093647095141417185777014180606443636815464440053316087783143174440811949422975599314011888683314832802706553833004693290115744147563139997221703804617092894579096271662260740718749975359212756084414737823303270330168237193648002173285734935947564334129943024850235732214597843282641421684878721673367010615094243456984401873312810107945127223737886126058165668053714396127888732527373890392890506865324138062796025930387727697783792868409325365880733988457218746021005311483351323850047827169376218004904795597959290591655470505777514308175112698985188408718564026035305583737832422924185625644255022672155980274012617971928047139600689163828665277009752767069777036439260224372841840883251848770472638440379530166905465937461619323840363893131364327137688841026811219891275223056256756254701725086349765367288605966752740868627407912856576996313789753034660616669804218267724560530660773899624218340859882071864682623215080288286359746839654358856685503773131296587975810501214916207656769950659715344763470320853215603674828608378656803073062657633469774295634643716709397193060876963495328846833613038829431040800296873869117066666146800015121143442256023874474325250769387077775193299942137277211258843608715834835626961661980572526612206797540621062080649882918454395301529982092503005498257043390553570168653120526495614857249257386206917403695213533732531666345466588597286659451136441370331393672118569553952108458407244323835586063106806964924851232632699514603596037297253198368423363904632136710116192821711150282801604488058802382031981493096369596735832742024988245684941273860566491352526706046234450549227581151709314921879592718001940968866986837037302200475314338181092708030017205935530520700706072233999463990571311587099635777359027196285061146514837526209565346713290025994397663114545902685898979115837093419370441155121920117164880566945938131183843765620627846310490346293950029458341164824114969758326011800731699437393506966295712410273239138741754923071862454543222039552735295240245903805744502892246886285336542213815722131163288112052146489805180092024719391710555390113943316681515828843687606961102505171007392762385553386272553538830960671644662370922646809671254061869502143176211668140097595281493907222601112681153108387317617323235263605838173151034595736538223534992935822836851007810884634349983518404451704270189381994243410090575376257767571118090088164183319201962623416288166521374717325477727783488774366518828752156685719506371936565390389449366421764003121527870222366463635755503565576948886549500270853923617105502131147413744106134445544192101336172996285694899193369184729478580729156088510396781959429833186480756083679551496636448965592948187851784038773326247051945050419847742014183947731202815886845707290544057510601285258056594703046836344592652552137008068752009593453607316226118728173928074623094685367823106097921599360019946237993434210687813497346959246469752506246958616909178573976595199392993995567542714654910456860702099012606818704984178079173924071945996323060254707901774527513186809982284730860766536866855516467702911336827563107223346726113705490795365834538637196235856312618387156774118738527722922594743373785695538456246801013905727871016512966636764451872465653730402443684140814488732957847348490003019477888020460324660842875351848364959195082888323206522128104190448047247949291342284951970022601310430062410717971502793433263407995960531446053230488528972917659876016667811937932372453857209607582277178483361613582612896226118129455927462767137794487586753657544861407611931125958512655759734573015333642630767985443385761715333462325270572005303988289499034259566232975782488735029259166825894456894655992658454762694528780516501720674785417887982276806536650641910973434528878338621726156269582654478205672987756426325321594294418039943217000090542650763095588465895171709147607437136893319469090981904501290307099566226620303182649365733698419555776963787624918852865686607600566025605445711337286840205574416030837052312242587223438854123179481388550075689381124935386318635287083799845692619981794523364087429591180747453419551420351726184200845509170845682368200897739455842679214273477560879644279202708312150156406341341617166448069815483764491573900121217041547872591998943825364950514771379399147205219529079396137621107238494290616357604596231253506068537651423115349665683715116604220796394466621163255157729070978473156278277598788136491951257483328793771571459091064841642678309949723674420175862269402159407924480541255360431317992696739157542419296607312393763542139230617876753958711436104089409966089471418340698362993675362621545247298464213752891079884381306095552622720837518629837066787224430195793793786072107254277289071732854874374355781966511716618330881129120245204048682200072344035025448202834254187884653602591506445271657700044521097735585897622655484941621714989532383421600114062950718490427789258552743035221396835679018076406042138307308774460170842688272261177180842664333651780002171903449234264266292261456004337383868335555343453004264818473989215627086095650629340405264943244261445665921291225648893569655009154306426134252668472594914314239398845432486327461842846655985332312210466259890141712103446084271616619001257195870793217569698544013397622096749454185407118446433946990162698351607848924514058940946395267807354579700307051163682519487701189764002827648414160587206184185297189154019688253289309149665345753571427318482016384644832499037886069008072709327673127581966563941148961716832980455139729506687604740915420428429993541025829113502241690769431668574242522509026939034814856451303069925199590436384028429267412573422447765584177886171737265462085498294498946787350929581652632072258992368768457017823038096567883112289305809140572610865884845873101658151167533327674887014829167419701512559782572707406431808601428149024146780472327597684269633935773542930186739439716388611764209004068663398856841681003872389214483176070116684503887212364367043314091155733280182977988736590916659612402021778558854876176161989370794380056663364884365089144805571039765214696027662583599051987042300179465536788567430285974600143785483237068701190078499404930918919181649327259774030074879681484882342932023012128032327460392219687528340516906974194257614673978110715464186273369091584973185011183960482533518748438923177292613543024932562896371361977285456622924461644497284597867711574125670307871885109336344480149675240618536569532074170533486782754827815415561966911055101472799040386897220465550833170782394808785990501947563108984124144672821865459971596639015641941751820935932616316888380132758752601460507676098392625726411120135288591317848299475682472564885533357279772205543568126302535748216585414000805314820697137262149755576051890481622376790414926742600071045922695314835188137463887104273544767623577933993970632396604969145303273887874557905934937772320142954803345000695256980935282887783710670585567749481373858630385762823040694005665340584887527005308832459182183494318049834199639981458773435863115940570443683515285383609442955964360676090221741896883548131643997437764158365242234642619597390455450680695232850751868719449064767791886720306418630751053512149851051207313846648717547518382979990189317751550639981016466414592102406838294603208535554058147159273220677567669213664081505900806952540610628536408293276621931939933861623836069111767785448236129326858199965239275488427435414402884536455595124735546139403154952097397051896240157976832639450633230452192645049651735466775699295718989690470902730288544945416699791992948038254980285946029052763145580316514066229171223429375806143993484914362107993576737317948964252488813720435579287511385856973381976083524423240466778020948399639946684833774706725483618848273000648319163826022110555221246733323184463005504481849916996622087746140216157021029603318588727333298779352570182393861244026868339555870607758169954398469568540671174444932479519572159419645863736126915526457574786985964242176592896862383506370433939811671397544736228625506803682664135541448048997721373174119199970017293907303350869020922519124447393278376156321810842898207706974138707053266117683698647741787180202729412982310888796831880854367327806879771659111654224453806625861711729498038248879986504061563975629936962809358189761491017145343556659542757064194408833816841111166200759787244137082333917886114708228657531078536674695018462140736493917366254937783014074302668422150335117736471853872324040421037907750266020114814935482228916663640782450166815341213505278578539332606110249802273093636740213515386431693015267460536064351732154701091440650878823636764236831187390937464232609021646365627553976834019482932795750624399645272578624400375983422050808935129023122475970644105678361870877172333555465482598906861201410107222465904008553798235253885171623518256518482203125214950700378300411216212126052726059944320443056274522916128891766814160639131235975350390320077529587392412476451850809163911459296071156344204347133544720981178461451077872399140606290228276664309264900592249810291068759434533858330391178747575977065953570979640012224092199031158229259667913153991561438070129260780197022589662923368154312499412259460023399472228171056603931877226800493833148980338548909468685130789292064242819174795866199944411196208730498064385006852620258432842085582338566936649849720817046135376163584015342840674118587581546514598270228676671855309311923340191286170613364873183197560812569460089402953094429119590295968563923037689976327462283900735457144596414108229285922239332836210192822937243590283003884445701383771632056518351970100115722010956997890484964453434612129224964732356126321951155701565824427661599326463155806672053127596948538057364208384918887095176052287817339462747644656858900936266123311152910816041524100214195937349786431661556732702792109593543055579732660554677963552005378304619540636971842916168582734122217145885870814274090248185446421774876925093328785670674677381226752831653559245204578070541352576903253522738963847495646255940378924925007624386893776475310102323746733771474581625530698032499033676455430305274561512961214585944432150749051491453950981001388737926379964873728396416897555132275962011838248650746985492038097691932606437608743209385602815642849756549307909733854185583515789409814007691892389063090542534883896831762904120212949167195811935791203162514344096503132835216728021372415947344095498316138322505486708172221475138425166790445416617303200820330902895488808516797258495813407132180533988828139346049850532340472595097214331492586604248511405819579711564191458842833000525684776874305916390494306871343118796189637475503362820939949343690321031976898112055595369465424704173323895394046035325396758354395350516720261647961347790912327995264929045151148307923369382166010702872651938143844844532639517394110131152502750465749343063766541866128915264446926222884366299462732467958736383501937142786471398054038215513463223702071533134887083174146591492406359493020921122052610312390682941345696785958518393491382340884274312419099152870804332809132993078936867127413922890033069995875921815297612482409116951587789964090352577345938248232053055567238095022266790439614231852991989181065554412477204508510210071522352342792531266930108270633942321762570076323139159349709946933241013908779161651226804414809765618979735043151396066913258379033748620836695475083280318786707751177525663963479259219733577949555498655214193398170268639987388347010255262052312317215254062571636771270010760912281528326508984359568975961038372157726831170734552250194121701541318793651818502020877326906133592182000762327269503283827391243828198170871168108951187896746707073377869592565542713340052326706040004348843432902760360498027862160749469654989210474443927871934536701798673920803845633723311983855862638008516345597194441994344624761123844617615736242015935078520825600604101556889899501732554337298073561699861101908472096600708320280569917042590103876928658336557728758684250492690370934262028022399861803400211320742198642917383679176232826444645756330336556777374808644109969141827774253417010988435853189339175934511574023847292909015468559163792696196841000676598399744972047287881831200233383298030567865480871476464512824264478216644266616732096012564794514827125671326697067367144617795643752391742928503987022583734069852309190464967260243411270345611114149835783901793499713790913696706497637127248466613279908254305449295528594932793818341607827091326680865655921102733746700132583428715240835661522165574998431236278287106649401564670141943713823863454729606978693335973109537126499416282656463708490580151538205338326511289504938566468752921135932220265681856418260827538790002407915892646028490894922299966167437731347776134150965262448332709343898412056926145108857812249139616912534202918139898683901335795857624435194008943955180554746554000051766240202825944828833811886381749594284892013520090951007864941868256009273977667585642598378587497776669563350170748579027248701370264203283965756348010818356182372177082236423186591595883669487322411726504487268392328453010991677518376831599821263237123854357312681202445175401852132663740538802901249728180895021553100673598184430429105288459323064725590442355960551978839325930339572934663055160430923785677229293537208416693134575284011873746854691620648991164726909428982971065606801805807843600461866223562874591385185904416250663222249561448724413813849763797102676020845531824111963927941069619465426480006761727618115630063644321116224837379105623611358836334550102286170517890440570419577859833348463317921904494652923021469259756566389965893747728751393377105569802455757436190501772466214587592374418657530064998056688376964229825501195065837843125232135309371235243969149662310110328243570065781487677299160941153954063362752423712935549926713485031578238899567545287915578420483105749330060197958207739558522807307048950936235550769837881926357141779338750216344391014187576711938914416277109602859415809719913429313295145924373636456473035037374538503489286113141638094752301745088784885645741275003353303416138096560043105860548355773946625033230034341587814634602169235079216111013148948281895391028916816328709309713184139815427678818067628650978085718262117003140003377301581536334149093237034703637513354537634521050370995452942055232078817449370937677056009306353645510913481627378204985657055608784211964039972344556458607689515569686899384896439195225232309703301037277227710870564912966121061494072782442033414057441446459968236966118878411656290355117839944070961772567164919790168195234523807446299877664824873753313018142763910519234685081979001796519907050490865237442841652776611425351538665162781316090964802801234493372427866930894827913465443931965254154829494577875758599482099181824522449312077768250830768282335001597040419199560509705364696473142448453825888112602753909548852639708652339052941829691802357120545328231809270356491743371932080628731303589640570873779967845174740515317401384878082881006046388936711640477755985481263907504747295012609419990373721246201677030517790352952793168766305099837441859803498821239340919805055103821539827677291373138006715339240126954586376422065097810852907639079727841301764553247527073788764069366420012194745702358295481365781809867944020220280822637957006755393575808086318932075864444206644691649334467698180811716568665213389686173592450920801465312529777966137198695916451869432324246404401672381978020728394418264502183131483366019384891972317817154372192103946638473715630226701801343515930442853848941825678870721238520597263859224934763623122188113706307506918260109689069251417142514218153491532129077723748506635489170892850760234351768218355008829647410655814882049239533702270536705630750317499788187009989251020178015601042277836283644323729779929935160925884515772055232896978333126427671291093993103773425910592303277652667641874842441076564447767097790392324958416348527735171981064673837142742974468992320406932506062834468937543016787815320616009057693404906146176607094380110915443261929000745209895959201159412324102274845482605404361871836330268992858623582145643879695210235266673372434423091577183277565800211928270391042391966426911155333594569685782817020325495552528875464466074620294766116004435551604735044292127916358748473501590215522120388281168021413865865168464569964810015633741255098479730138656275460161279246359783661480163871602794405482710196290774543628092612567507181773641749763254436773503632580004042919906963117397787875081560227368824967077635559869284901628768699628053790181848148810833946900016380791075960745504688912686792812391148880036720729730801354431325347713094186717178607522981373539126772812593958220524289991371690685650421575056729991274177149279608831502358697816190894908487717722503860872618384947939757440664912760518878124233683125467278331513186758915668300679210215947336858591201395360301678110413444411030903388761520488296909104689167671555373346622545575975202624771242796225983278405833585897671474205724047439720232895903726148688388003174146490203843590358527993123871042845981608996101945691646983837718267264685264869172948414153004604004299585035164101899027529366867431834955447458124140190754681607770977920579383895378192128847409929537040546962226547278807248685508046571043123854873351653070570784584243335550958221912862797205455466267099131902370311779690892786623112661337671178512943059323281605826535623848164192144732543731002062738466812351691016359252588256806438946389880872735284406462208149513862275239938938734905082625472417781702582044129853760499827899020083498387362992498125742354568439023012261733665820546785671147973065077035475620567428300187473019197310881157516777005071432012726354601912460800451608108641835539669946936947322271670748972850464195392966434725254724357659192969949061670189061433616907056148280980363243454128229968275980226694045642181328624517549652147221620839824594576613342710564957193564431561774500828376935700995419541839029151033187933907614207467028867968594985439789457300768939890070073924697461812855764662265412913204052279071212820653775058280040897163467163709024906774736309136904002615646432159560910851092445162454420141442641660181385990017417408244245378610158433361777292580611159192008414091888191208858207627011483671760749046980914443057262211104583300789331698191603917150622792986282709446275915009683226345073725451366858172483498470080840163868209726371345205439802277866337293290829914010645589761697455978409211409167684020269370229231743334499986901841510888993165125090001163719114994852024821586396216294981753094623047604832399379391002142532996476235163569009445086058091202459904612118623318278614464727795523218635916551883057930657703331498510068357135624341881884405780028844018129031378653794869614630467726914552953690154167025838032477842272417994513653582260971652588356712133519546838335349801503269359798167463231847628306340588324731228951257944267639877946713121042763380872695738609314631539148548792514028885025189788076023838995615684850391995855029256054176767663145354058496296796781349420116003325874431438746248313850214980401681940795687219268462617287403480967931949965604299190281810597603263251746405016454606266765529010639868703668263299050577706266397868453584384057673298268163448646707439990917504018892319267557518354054956017732907127219134577524905771512773358423314008356080926962298894163047287780054743798498545562870729968407382937218623831766524716090967192007237658894226186550487552614557855898773008703234726418384831040394818743616224455286163287628541175946460497027724490799275146445792982549802258601001772437840167723166802004162547244179415547810554178036773553354467030326469619447560812831933095679685582771932031205941616693902049665352189672822671972640029493307384717544753761937017882976382487233361813499414541694736549254840633793674361541081593464960431603544354737728802361047743115330785159902977771499610274627769759612488879448609863349422852847651310277926279743981957617505591300993377368240510902583759345170015340522266144077237050890044496613295859536020556034009492820943862994618834790932894161098856594954213114335608810239423706087108026465913203560121875933791639666437282836752328391688865373751335794859860107569374889645657187292540448508624449947816273842517229343960137212406286783636675845331904743954740664015260871940915743955282773904303868772728262065663129387459875317749973799293043294371763801856280061141619563942414312254397099163565102848315765427037906837175764870230052388197498746636856292655058222887713221781440489538099681072143012394693530931524054081215705402274414521876541901428386744260011889041724570537470755550581632831687247110220353727166112304857340460879272501694701067831178927095527253222125224361673343366384756590949728221809418684074238351567868893421148203905824224324264643630201441787982022116248471657468291146315407563770222740135841109076078464780070182766336227978104546331131294044833570134869585165267459515187680033395522410548181767867772152798270250117195816577603549732923724732067853690257536233971216884390878879262188202305529937132397194333083536231248870386416194361506529551267334207198502259771408638122015980894363561808597010080081622557455039101321981979045520049618583777721048046635533806616517023595097133203631578945644487800945620369784973459902004606886572701865867757842758530645706617127194967371083950603267501532435909029491516973738110897934782297684100117657987098185725131372267749706609250481876835516003714638685918913011736805218743265426063700710595364425062760458252336880552521181566417553430681181548267844169315284408461087588214317641649835663127518728182948655658524206852221830755306118393326934164459415342651778653397980580828158806300749952897558204686612590853678738603318442905510689778698417735603118111677563872589911516803236547002987989628986181014596471307916144369564690909518788574398821730583884980809523077569358851616027719521488998358632323127308909861560777386006984035267826785387215920936255817889813416247486456433211043194821421299793188104636399541496539441501383868748384870224681829391860319598667962363489309283087840712400431022706137591368056518861313458307990705003607588327248867879324093380071864152853317943535073401891193638546730000660453783784472469288830546979000131248952100446949032058838294923613919284305249167833012980192255157050378521810552961623637523647962685751660066539364142273063001648652613891842243501797455993616794063303522111829071597538821839777552812981538570168702202620274678647916644030729018445497956399844836807851997088201407769199261674991148329821854382718946282165387064858588646221611410343570342878862979083418871606214430014533275029715104673156021000043869510583773779766003460887624861640938645252177935289947578496255243925598620521409052346250847830487046492688313289470553891357290706967599556298586669559721686506052072801342104355762779184021797626656484580261591407173477009039475168017709900129391137881248534255949312866653465033728846390649968460644741907524313323903404908195233044389559060547854954620263256676813262435925020249516275607080900436460421497025691488555265022810327762115842282433269528629137662675481993546118143913367579700141255870143319434764035725376914388899683088262844616425575034001428982557620386364384137906519612917777354183694676232982904981261717676191554292570438432239918482261744350470199171258214687683172646078959690569981353264435973965173473319484798758064137926885413552523275720457329477215706850016950046959758389373527538622664943456437071610511521617176237598050900553232154896062817794302268640579555845730600598376482703339859420098582351400179507104569019191359062304102336798080907240196312675268916362136351032648077232914950859151265812143823371072949148088472355286394195993455684156344577951727033374238129903260198160571971183950662758220321837136059718025940870615534713104482272716848395524105913605919812444978458110854511231668173534838253724825347636777581712867205865148285317273569069839935110763432091319780314031658897379628301178409806410175016511072932907832177487566289310650383806093372841399226733384778203302020700517188941706465146238366720632742644336612174011766914919235570905644803016342294301837655263108450172510307540942604409687066288066265900569082451407632599158164499361455172452057020443093722305550217222299706209749268609762787409626448772056043078634808885709143464793241536214303199965695610753570417207285334250171325558818113295504095217830139465216436594262960768570585698507157151317262928960072587601564840556088613165411835958628710665496282599535127193244635791046554389165150954187306071015034430609582302257455974944275067630926322529966338219395202927917973247094559691016402983683080426309910481567503623509654924302589575273521412445149542462972258510120707802110188106722347972579330653187713438466713807546383471635428854957610942841898601794658721444495198801550804042506452191484989920400007310672369944655246020908767882300064337725657385010969899058191290957079866699453765080407917852438222041070599278889267745752084287526377986730360561230710723922581504781379172731261234878334034473833573601973235946604273704635201327182592410906040097638585857716958419563109577748529579836844756803121874818202833941887076311731615289811756429711334181497218078040465077657204457082859417475114926179367379999220181789399433337731146911970737861041963986422166045588965683206701337505745038872111332436739840284188639147633491695114032583475841514170325690161784931455706904169858050217798497637014758914810543205854914100662201721719726878930012101267481270235940855162601689425111458499658315589660460091525797881670384625905383256920520425791378948827579603278877535466861441826827797651258953563761485994485049706638406266121957141911063246061774180577212381659872472432252969098533628440799030007594546281549235506086481557928961969617060715201589825299772803520002610888814176506636216905928021516429198484077446143617891415191517976537848282687018750030264867608433204658525470555882410254654806040437372771834769014720664234434374255514129178503032471263418076525187802925534774001104853996960549926508093910691337614841834884596365621526610332239417467064368340504749943339802285610313083038484571294767389856293937641914407036507544622061186499127249643799875806537850203753189972618014404667793050140301580709266213229273649718653952866567538572115133606114457222800851183757899219543063413692302293139751143702404830227357629039911794499248480915071002444078482866598579406525539141041497342780203520135419925977628178182825372022920108186449448349255421793982723279357095828748597126780783134286180750497175747373730296280477376908932558914598141724852658299510882230055223242218586191394795184220131553319634363922684259164168669438122537135960710031743651959027712571604588486044820674410935215327906816032054215967959066411120187618531256710150212239401285668608469435937408158536481912528004920724042172170913983123118054043277015835629513656274610248827706488865037765175678806872498861657094846665770674577000207144332525555736557083150320019082992096545498737419756608619533492312940263904930982014700371161829485939931199955070455381196711289367735249958182011774799788636393286405807810818657337668157893827656450642917396685579555053188715314552353070355994740186225988149854660737787698781542360397080977412361518245964026869979609564523828584235953564615185448165799966460648261396618720304839119560250381111550938420209894591555760083897989949964566262540514195610780090298667014635238532066032574466820259430618801773091109212741138269148784355679352572808875543164693077235363768226036080174040660997151176880434927489197133087822951123746632635635328517394189466510943745768270782209928468034684157443127739811044186762032954475468077511126663685479944460934809992951875666499902261686019672053749149951226823637895865245462813439289338365156536992413109638102559114643923805213907862893561660998836479175633176725856523591069520326895990054884753424160586689820067483163174286329119633399132709086065074595260357157323069712106423424081597068328707624437165532750228797802598690981111226558888151520837482450034463046505984569690276166958278982913613535306291331427881888249342136442417833519319786543940201465328083410341785272489879050919932369270996567133507711905899945951923990615156165480300145359212550696405345263823452155999210578191371030188979206408883974767667144727314254467923500524618849237455307575734902707342496298879996942094595961008702501329453325358045689285707241207965919809225550560061971283541270202072583994171175520920820151096509526685113897577150810849443508285458749912943857563115668324566827992991861539009255871716840495663991959154034218364537212023678608655364745175654879318925644085274489190918193411667583563439758886046349413111875241038425467937999203546910411935443113219136068129657568583611774564654674861061988591414805799318725367531243470335482637527081353105570818049642498584646147973467599315946514787025065271083508782350656532331797738656666181652390017664988485456054961300215776115255813396184027067814900350252876823607822107397102339146870159735868589015297010347780503292154014359595298683404657471756232196640515401477953167461726208727304820634652469109953327375561090578378455945469160223687689641425960164689647106348074109928546482353083540132332924864037318003195202317476206537726163717445360549726690601711176761047774971666890152163838974311714180622222345718567941507299526201086205084783127474791909996889937275229053674785020500038630036526218800670926674104806027341997756660029427941090400064654281074454007616429525362460261476180471744322889953285828397762184600967669267581270302806519535452053173536808954589902180783145775891280203970053633193821100095443241244197949192916205234421346395653840781209416214835001155883618421164283992454027590719621537570187067083731012246141362048926555668109467076386536083015847614512581588569610030337081197058344452874666198891534664244887911940711423940115986970795745946337170243268484864632018986352827092313047089215684758207753034387689978702323438584381125011714013265769320554911860153519551654627941175593967947958810333935413289702528893533748106257875620364294270257512121137330213811951395756419122685155962476203282038726342066227347868223036522019655729325905068134849292299647248229359787842720945578267329975853818536442370617353517653060396801087899490506654491544577952166038552398013798104340564182403396162494910454712104839439200945914647542424785991096900046541371091630096785951563947332190934511838669964622788855817353221326876634958059123761251203010983867841195725887799206041260049865895027247133146763722204388398558347770112599424691208308595666787531942465131444389971195968105937957532155524204659410081418351120174196853432672343271868099625045432475688702055341969199545300952644398446384346598830418262932239295612610045884644244285011551557765935780379565026806130721758672048541797157896401554276881090475899564605488362989140226580026134158039480357971019004151547655018391755772677897148793477372747525743898158705040701968215101218826088040084551332795162841280679678965570163917067779841529149397403158167896865448841319046368332179115059107813898261026271979696826411179918656038993895418928488851750122504754778999508544083983800725431468842988412616042682248823097788556495765424017114510393927980290997604904428832198976751320535115230545666467143795931915272680278210241540629795828828466355623580986725638200565215519951793551069127710538552661926903526081367717666435071213453983711357500975854405939558661737828297120544693182260401670308530911657973113259516101749193468250063285777004686987177255226525708428745733039859744230639751837209975339055095883623642814493247460522424051972825153787541962759327436278819283740253185668545040893929401040561666867664402868211607294830305236465560955351079987185041352121321534713770667681396211443891632403235741573773787908838267618458756361026435182951815392455211729022985278518025598478407179607904114472041476091765804302984501746867981277584971731733287305281134969591668387877072315968334322509070204019030503595891994666652037530271923764252552910347950343816357721698115464329245608951158732012675424975710520894362639501382962152214033621065422821876739580121286442788547491928976959315766891987305176388698461503354594898541849550251690616888419122873385522699976822609645007504500096116866129171093180282355042553653997166054753907348915189650027442328981181709248273610863801576007240601649547082331349361582435128299050405405333992577071321011503713898695076713447940748097845416328110406350804863393555238405735580863718763530261867971725608155328716436111474875107033512913923595452951407437943144900950809932872153235195999616750297532475931909938012968640379783553559071355708369947311923538531051736669154087312467233440702525006918026747725078958903448856673081487299464807786497709361969389290891718228134002845552513917355978456150353144603409441211512001738697261466786933733154341007587514908295822756919350542184106448264951943804240543255345965248373785310657979037977505031436474651422484768831323479762673689855474944277949916560108528257618964374464656819789319422077536824661110427671936481836360534108748971066866318805026555929568123959680449295166615409802610781691689418764353363449482900125929366840591370059526914934421861891742142561071896846626335874414976973921566392767687720145153302241853125308442727245771161505550519076276250016522166274796257424425420546785767478190959486500575711016264847833741198041625940813327229905891486422127968042984725356237202887830051788539737909455265135144073130049869453403245984236934627060242579432563660640597549471239092372458126154582526667304702319359866523378856244229188278436440434628094888288712101968642736370461639297485616780079779959696843367730352483047478240669928277140069031660709951473154191919911453182543906294573298686613524886500574780251977607442660798300291573030523199052185718628543687577860915726925232573171665625274275808460620177046433101212443409281314659760221360416223031167750085960128475289259463348312408766740128170543067985261868949895004918275008304998926472034986965363326210919830621495095877228260815566702155693484634079776879525038204442326697479264829899016938511552124688935873289878336267819361764023681714606495185508780596635354698788205094762016350757090024201498400967867845405354130050482404996646978558002628931826518708714613909521454987992300431779500489569529280112698632533646737179519363094399609176354568799002814515169743717518330632232942199132137614506411391269837128970829395360832883050256072727563548374205497856659895469089938558918441085605111510354367477810778500572718180809661542709143010161515013086522842238721618109043183163796046431523184434669799904865336375319295967726080853457652274714047941973192220960296582500937408249714373040087376988068797038047223488825819819025644086847749767508999164153502160223967816357097637814023962825054332801828798160046910336602415904504637333597488119998663995617171089911809851197616486499233594328274275983382931099806461605360243604040848379619072542165869409486682092396143083817303621520642297839982533698027039931804024928814430649614747600087654305571672697259114631990688823893005380061568007730984416061355843701277573463708822073792921409548717956947854414951731561828176343929570234710460088230637509877521391223419548471196982303169544468045517922669260631327498272520906329003279972932906827204647650366969765227673645419031639887433042226322021325368176044169612053532174352764937901877252263626883107879345194133825996368795020985033021472307603375442346871647223795507794130304865403488955400210765171630884759704098331306109510294140865574071074640401937347718815339902047036749084359309086354777210564861918603858715882024476138160390378532660185842568914109194464566162667753712365992832481865739251429498555141512136758288423285957759412684479036912662015308418041737698963759002546999454131659341985624780714434977201991702665380714107259910648709897259362243300706760476097690456341576573395549588448948093604077155688747288451838106069038026528318275560395905381507241627615047252487759578650784894547389096573312763852962664517004459626327934637721151028545472312880039058405918498833810711366073657536918428084655898982349219315205257478363855266205400703561310260405145079325925798227406012199249391735122145336707913500607486561657301854049217477162051678486507913573336334257685988361252720250944019430674728667983441293018131344299088234006652915385763779110955708000600143579956351811596764725075668367726052352939773016348235753572874236648294604770429166438403558846422370760111774821079625901180265548868995181239470625954254584491340203400196442965370643088660925268811549596291166168612036195319253262662271108142149856132646467211954801142455133946382385908540917878668826947602781853283155445565265933912487885639504644196022475186011405239187543742526581685003052301877096152411653980646785444273124462179491306502631062903402737260479940181929954454297256377507172705659271779285537195547433852182309492703218343678206382655341157162788603990157495208065443409462446634653253581574814022471260618973060860559065082163068709634119751925774318683671722139063093061019303182326666420628155129647685313861018672921889347039342072245556791239578260248978371473556820782675452142687314252252601795889759116238720807580527221031327444754083319215135934526961397220564699247718289310588394769170851420631557192703636345039529604362885088555160008371973526383838996789184600327073682083234847108471706160879195227388252347506380811606090840124222431476103563328940609282430125462013806032608121942876847907192546246309055749298781661271916548229644317263587524548607563020667656942355342774617635549231817456159185668061686428714964129290560130053913469569829490891003991259088290348791943368696942620662946948514931472688923571615032405542263391673583102728579723061998175868700492227418629077079508809336215346303842967525604369606110193842723883107587771653594778681499030978765900869583480043137176832954871752604714113064847270887246697164585218774442100900090916189819413456305028950484575822161887397443918833085509908566008543102796375247476265353031558684515120283396640547496946343986288291957510384781539068343717740714095628337554413567955424664601335663617305811711646062717854078898495334329100315985673932305693426085376230981047171826940937686754301837015557540822371538037838383342702379535934403549452173960327095407712107332936507766465603712364707109272580867897181182493799540477008369348889220963814281561595610931815183701135104790176383595168144627670903450457460997444500166918675661035889313483800512736411157304599205955471122443903196476642761038164285918037488354360663299436899730090925177601162043761411616688128178292382311221745850238080733727204908880095181889576314103157447684338100457385008523652069340710078955916549813037292944462306371284357984809871964143085146878525033128989319500645722582281175483887671061073178169281242483613796475692482076321356427357261609825142445262515952514875273805633150964052552659776922077806644338105562443538136258941809788015677378951310313157361136026047890761945591820289365770116416881703644242694283057457471567494391573593353763114830246668754727566653059819746822346578699972291792416156043557665183382167059157867799311835820189855730344883681934418305987021880502259192818047775223884407167894780414701414651073580452021499197980812095692195622632313741870979731320870864552236740416185590793816745658234353037283309503729022429802768451559528656923189798000383061378732434546500582722712325031420712488100290697226311129067629080951145758060270806092801504406139446350643069742785469477459876821004441453438033759717384777232052065301037861326418823586036569054773343070911759152582503029410738914441818378779490613137536794654893375260322906277631983337976816641721083140551864133302224787118511817036598365960493964571491686005656771360533192423185262166760222073368844844409234470948568027905894191829969467724456269443308241243846160408284006424867072583661011433404214473683453638496544701067827313169538435919120440283949541956874453676459875488726170687163109591315801609722382049772577307454562979127906177531663252857205858766376754282917933549923678212008601904369428956102301731743150352204665675088491593025926618816581008701658499456495586855628208747248318351516339189292646558880593601275151838235485893426165223086697314511412035659916934103076974774451947043836739600076578628245472064617380804602903639144493859012422380173377038154675297645596518492676039300171943042511794045679862114630138402371099347243455794730048929825402680821621522346560274258486595687074510352794291633405915025075992398611224340312056999780516223878772230396359709132856830486160362127579561601328561866388146004722200580017580282279272167842720649966956840905752590774886105493806116954293569077377792821084159737469613143291808510446953973485067590503662391722108732333169909603363771705474725026941732982890400239372879549386540463828596742216318201530139629734398479588628632934746650690284066719018081265539973675916799759010867483920062877888531102781695087545740384607594616919584610655963327283485609570305572502494416337066573150237126843581984154103154401008430380631442183776750349813408169325201240813452285974626715177152223063741359255747513535160669108359443999692315898156732033027129284241219651936303734407981204656795322986357374589031654007016472204989445629050395873788912680565516464274460174738175296313458739390484560414203426465560422112239134631023161290836446988901247285192778589195228773637440432659264672239982186452797664826673070168802722052338600372842903155828454593854349099449420750911108532138744823216151007808922516285123275724355101999038195993350032641446053470357293073912578481757987468353429629749652545426864234949270336399427519354240001973125098882419600095766257217621860474573769577649582201796258392376391717855799468922496750179251915218219624653575570564228220399546682648329822996167217080156801080799777126517156274295763666959661983507435667132218383358509536665806605597148376773866922551603463644386269977295750658468929599809168949981898588529537874489519527097766262684177088590284321676352132630838812766335363319004134332844347630067982023716933653652880580156390360562722752187272454764258840995216482554453662083811789117725225682611478014242896970967121967502094421226279437073328703410646312100557376727450271638975234111426287828736758358819056742163061523416789476056879277154789714326222041069587947186435439940738639948986836168919377836648327137363654676901173760246643082285362494712605173293777247276797635865806019396287718060679122426813922872134061694882029506831654589707623668302556167559477498715183426989208952182644710514911419441192277010977616645850068963849426165593473112961064282379048216056210094265076173838082479030510998790719611852832556787472942907151041468948104916751035295897242381802288151276582257190705537652455285511598636421244284176256230139538669970308943645907600684938040875210854159851278070333207779865635907968462191534944587677170063778573171211036517486371634098385626541555573292664616402279791195975248525300376741774056125700303625811704838385391207273191845064713669122576415213769896260940351804147432053600369234179035440735703058314741623452840188940808983125191307741823338981880316339159565954543405777784331681162551898060409183018907512170192983622897099598983405484962284289398469847938668614293324543983592637036699355184231661615244505980576745765335552338715678211466689996845227042954589710922163652573965950289645637766038988037941517917867910675199009966139206238732318786758420544279396366759104126821843375015743069045967947046685602358283919759975285865384338189120042853787549302768972168199113340697282255535300044743958830079799736518459131437946494086272149669719100359399974735262764126125995350902609540048669398955899487421379590802893196914845826873123710180229775301190684280440780938156598081694611679374425663244656799606363751546304833112722231812338371779800439731087402647536582575657351059978314264831879619843765495877803685261751835391844920488198629786329743136948511780579298636452193232481339393090754566368038513630619718033957979522539508697432546502659123585049283028832934489284591373621624852528877442891851104093746333590660233239711922814450735588373324057814862662207486215513375036775585494138678352928273109003823116855374520901095101174796663003330352534143230024288248051396631446632656081582045216883922312025671065388459503224002320453633895521539919011035217362720909565500846486605368975498478995875596103167696587161281951919668893326641203784750417081752273735270989343717167642329956935697166213782736138899530515711822960896394055380431939398453970864418654291655853168697537052760701061488025700785387150835779480952313152747735711713643356413242974208137266896149109564214803567792270566625834289773407718710649866150447478726164249976671481383053947984958938064202886667951943482750168192023591633247099185942520392818083953020434979919361853380201407072481627304313418985942503858404365993281651941497377286729589582881907490040331593436076189609669494800067194371424058105327517721952474344983414191979918179909864631583246021516575531754156198940698289315745851842783390581029411600498699307751428513021286202539508732388779357409781288187000829944831476678183644656510024467827445695591845768068704978044824105799710771577579093525803824227377612436908709875189149049904225568041463131309240101049368241449253427992201346380538342369643767428862595140146178201810734100565466708236854312816339049676558789901487477972479202502227218169405159042170892104287552188658308608452708423928652597536146290037780167001654671681605343292907573031466562485809639550080023347676187068086526878722783177420214068980703410506200235273632267291964034093571225623659496432076928058165514428643204955256838543079254299909353199329432966018220787933122323225928276556048763399988478426451731890365879756498207607478270258861409976050788036706732268192473513646356758611212953074644777149423343867876705824452296605797007134458987594126654609414211447540007211790607458330686866231309155780005966522736183536340439991445294960728379007338249976020630448806064574892740547730693971337007962746135534442514745423654662752252624869916077111131569725392943756732215758704952417232428206555322808868670153681482911738542735797154157943689491063759749151524510096986573825654899585216747260540468342338610760823605782941948009334370046866568258579827323875158302566720152604684361412652956519894291184887986819088277339147282063794512260294515707367105637720023427811802621502691790400488001808901847311751199425460594416773315777951735444490965752131026306836047140331442314298077895617051256930051804287472368435536402764392777908638966566390166776625678575354239947427919442544664643315554138265543388487778859972063679660692327601733858843763144148113561693030468420017434061395220072403658812798249143261731617813894970955038369479594617979829257740992171922783223006387384996138434398468502234780438733784470928703890536420557474836284616809363650973790900204118525835525201575239280826462555785658190226958376345342663420946214426672453987171047721482128157607275305173330963455909323664528978019175132987747952929099598069790148515839540444283988381797511245355548426126784217797728268989735007954505834273726937288386902125284843370917479603207479554080911491866208687184899550445210616155437083299502854903659617362726552868081324793106686855857401668022408227992433394360936223390321499357262507480617409173636062365464458476384647869520547719533384203403990244761056010612777546471464177412625548519830144627405538601855708359981544891286863480720710061787059669365218674805943569985859699554089329219507269337550235821561424994538234781138316591662683103065194730233419384164076823699357668723462219641322516076261161976034708844046473083172682611277723613381938490606534404043904909864126903479263503943531836741051762565704797064478004684323069430241749029731181951132935746854550484711078742905499870600373983113761544808189067620753424526993443755719446665453524088287267537759197074526286322840219629557247932987132852479994638938924943286917770190128914220188747760484939855471168524810559991574441551507431214406120333762869533792439547155394213121021954430556748370425907553004950664994802614794524739012802842646689229455664958621308118913500279654910344806150170407268010067948926855360944990373928383520627992820181576427054962997401900837493444950600754365525758905546552402103412862124809003162941975876195941956592556732874237856112669741771367104424821916671499611728903944393665340294226514575682907490402153401026923964977275904729573320027982816062130523130658731513076913832317193626664465502290735017347656293033318520949298475227462534564256702254695786484819977513326393221579478212493307051107367474918016345667888810782101151826314878755138027101379868751299375133303843885631415175908928986956197561123025310875057188962535763225834275763348421016668109884514141469311719314272028007223449941999003964948245457520704922091620614222912795322688239046498239081592961111003756999529251250673688233852648213896986384052437049402152187547825163347082430303521036927849762517317825860862215614519165573478940019558704784741658847364803865995119651409542615026615147651220820245816010801218275982577477652393859159165067449846149161165153821266726927461290533753163055654440793427876550267301214578324885948736899073512166118397877342715872870912311383472485146035661382188014840560716074652441118841800734067898587159273982452147328317214621907330492060817440914125388918087968538960627860118193099489240811702350413554126823863744341209267781729790694714759018264824761112414556423937732224538665992861551475342773370683344173073150805440138894084087253197595538897613986400165639906934600670780501058567196636796167140097031535132386972899001749862948883362389858632127176571330142071330179992326381982094042993377790345261665892577931395405145369730429462079488033141099249907113241694504241391265397274078984953073730364134893688060340009640631540701820289244667315059736321311926231179142794944897281477264038321021720718017561601025111179022163703476297572233435788863537030535008357679180120653016668316780269873860755423748298548246360981608957670421903145684942967286646362305101773132268579232832164818921732941553151386988781837232271364011755881332524294135348699384658137175857614330952147617551708342432434174779579226338663454959438736807839569911987059388085500837507984051126658973018149321061950769007587519836861526164087252594820126991923916722273718430385263107266000047367872474915828601694439920041571102706081507270147619679971490141639274282889578424398001497985658130305740620028554097382687819891158955487586486645709231721825870342960508203415938806006561845735081804032347750084214100574577342802985404049555529215986404933246481040773076611691605586804857302606467764258503301836174306413323887707999698641372275526317649662882467901094531117120243890323410259937511584651917675138077575448307953064925086002835629697045016137935696266759775923436166369375035368699454550392874449940328328128905560530091416446608691247256021455381248285307613556149618444364923014290938289373215312818797541139219415606631622784836152140668972661027123715779503062132916001988806369127647416567067485490795342762338253943990022498972883660263920518704790601584084302914787302246651371144395418253441269003331181914268070735159284180415100555199146564934872796969351992963117195821262627236458009708099166752820365818699111948365866102758375863322993225541477479210421324166848264953111826527351008031659958888814809945737293785681411438021523876706455063233067233939551964260397443829874822322662036352861302543796600943104500158604854027036789711934695579989189112302233381602302236277726084846296189550730850698061500281436425336666311433321645213882557346329366870956708432252564333895997812402164189946978348320376011613913855499933990786652305860332060641949298931012423081105800169745975038516887112037747631577311831360002742502722451570906304496369230938382329175076469684003556425503797106891999812319602533733677437970687713814747552190142928586781724044248049323750330957002929126630316970587409214456472022710796484778657310660832173093768033821742156446602190335203981531618935787083561603302255162155107179460621892674335641960083663483835896703409115513087820138723494714321400450513941428998350576038799343355677628023346565854351219361896876831439866735726040869511136649881229957801618882834124004126142251475184552502502640896823664946401177803776799157180146386554733265278569418005501363433953502870836220605121839418516239153709790768084909674194289061134979961034672077354959593868862427986411437928435620575955500144308051267664432183688321434583708549082240014585748228606859593502657405750939203135881722442164955416889785558265198046245527898343289578416968890756237467281044803018524217706136533236073856228166664597654076844715963930782091017090763377917711485205493367936868430832404126789220929930411890501756484917499452393770674524578019171841679541825554377930299249277892416277257788147974770446005423669346157135208417428211847353652367573702352791459837645712257646122605628127852169580892808988394594406165340521932514843306105322700231133680378433377389724881307874325614952744243584753011150345103737688223837573804282007358586938044331529253129961025096113761670187568525921208929131354473196308440066835155160913925692912175784379179004808848023029304392630921342768601226558630456913133560978156776098711809238440656353136182676923761613389237802972720736243967239854144480757286813436768000573823963610796223140429490728058551444771338682314499547929338131259971996894072233847404542592316639781608209399269744676323921370773991899853301483814622364299493902073285072098040905300059160091641710175605409814301906444379905831277826625762288108104414704097708248077905168225857235732665234414956169007985520848841886027352780861218049418060017941147110410688703738674378147161236141950474056521041002268987858525470689031657094677131822113205505046579701869337769278257145248837213394613987859786320048011792814546859096532616616068403160077901584946840224344163938313618742275417712170336151163782359059685168880561304838542087505126933144171705880517278127917564053282929427357971823360842784676292324980318169828654166132873909074116734612367109059236155113860447246378721244612580406931724769152219217409096880209008801535633471775664392125733993165330324425899852598966724744126503608416484160724482125980550754851232313331300621490042708542735985913041306918279258584509440150719217604794274047740253314305451367710311947544521321732225875550489799267468541529538871443696399406391099267018219539890685186755868574434469213792094590683677929528246795437302263472495359466300235998990248299853826140395410812427393530207575128774273992824866921285637240069184859771126480352376025469714309316636539718514623865421671429236191647402172547787238964043145364190541101514371773797752463632741619269990461595895793940622986041489302535678633503526382069821487003578061101552210224486633247184367035502326672749787730470216165019711937442505629639916559369593557640005236360445141148916155147776301876302136068825296274460238077523189646894043033182148655637014692476427395401909403584437251915352134557610698046469739424511797999048754951422010043090235713636892619493763602673645872492900162675597083797995647487354531686531900176427222751039446099641439322672532108666047912598938351926694497553568096931962642014042788365702610390456105151611792018698900673027082384103280213487456720062839744828713298223957579105420819286308176631987048287388639069922461848323992902685392499812367091421613488781501234093387999776097433615750910992585468475923085725368613605356762146929424264323906626708602846163376051573599050869800314239735368928435294958099434465414316189806451480849292695749412903363373410480943579407321266012450796613789442208485840536446021616517885568969302685188950832476793300404851688934411125834396590422211152736276278672366665845757559585409486248261694480201791748223085835007862255216359325125768382924978090431102048708975715033330963651576804501966025215527080352103848176167004443740572131294252820989545456276344353575741673638980108310579931697917916718271145837435222026387771805250290791645414791173616253155840768495583288190293564201219633684854080865928095131505012602919562576032932512847250469881908146475324342363863860247943921015193235101390117789997483527186469346024554247028375300033725403910085997650987642832802908445662021678362267272292737780213652404028817217012490974899454430826861772239385250883760749742195942655217301733355851389407457348144161511380845358039740277795072051893487170722955427683655826706766313911972211811528466502223383490906676554168336907959409404576472940901354356409277969379842065738891481990225399022315913388145851487225126560927576795873759207013915029216513720851137197522734365458411622066281660256333632074449918511469174455062297146086578736313585389023662557285424516018080487167823688885575325066254262367702604215835160174851981885460860036597606743233346410471991027562358645341748631726556391320606407754779439671383653877377610828300019937359760370467245737880967939894493795829602910746901609451288456550071458091887879542641820145369659962842686882363495879277007025298960996798975941955735253914237782443302746708282008722602053415292735847582937522487377937899136764642153727843553986244015856488692101644781661602962113570056638347990334049623875941092886778920270077504951511405782565295015024484968204744379710872943108541684540513016310902267112951959140520827546866418137305837933236150599142045255880213558474751516267815309465541240524091663857551298894834797423322854504140527354235070335984964593699534959698554244978249586929179182415068053002553370412778703476446244329205906832901886692400222391918714603175399666877477960121790688623311002908668305431787009355066944389131913333586368037447530664502418437136030852288582121720231274167009740351431532131803978033680228154223490183737494117973254478594157962104378787072154814091725163615415163381388912588517924237727229603497305533840942889918919161186249580560073570527227874940321250645426206304469470804277945973817146810395192821550688079136701210109944220737024613687196031491162370967939354636396448139025711768057799751751298979667073292674886430097398814873780767363792886767781170520534367705731566895899181530825761606591843760505051704242093231358724816618683821026679970982966436224723644898648976857100173643547336955619347638598187756855912376232580849341570570863450733443976604780386678461711520325115528237161469200634713570383377229877321365028868868859434051205798386937002783312365427450532283462669786446920780944052138528653384627970748017872477988461146015077617116261800781557915472305214759943058006652042710117125674185860274188801377931279938153727692612114066810156521441903567333926116697140453812010040811760123270513163743154487571768761575554916236601762880220601068655524141619314312671535587154866747899398685510873576261006923021359580838145290642217792987748784161516349497309700794368305080955621264592795333690631936594413261117944256602433064619312002953123619348034504503004315096798588111896950537335671086336886944665564112662287921812114121425167348136472449021275252555647623248505638391391630760976364990288930588053406631352470996993362568102360392264043588787550723319888417590521211390376609272658409023873553418516426444865247805763826160023858280693148922231457758783791564902227590699346481624734399733206013058796068136378152964615963260698744961105368384203105364183675373594176373955988088591188920114871545460924735613515979992999722298041707112256996310945945097765566409972722824015293663094891067963296735505830412258608050740410916678539569261234499102819759563955711753011823480304181029089719655278245770283085321733741593938595853203645590564229716679900322284081259569032886928291260139267587858284765599075828016611120063145411315144108875767081854894287737618991537664505164279985451077400771946398046265077776614053524831090497899859510873112620613018757108643735744708366215377470972660188656210681516328000908086198554303597948479869789466434027029290899143432223920333487108261968698934611177160561910681226015874410833093070377506876977485840324132474643763087889666151972556180371472590029550718424245405129246729039791532535999005557334600111693557020225722442772950263840538309433999383388018839553821540371447394465152512354603526742382254148328248990134023054550811390236768038649723899924257800315803725555410178461863478690646045865826036072306952576113184134225274786464852363324759102670562466350802553058142201552282050989197818420425028259521880098846231828512448393059455162005455907776121981297954040150653985341579053629101777939776957892084510979265382905626736402636703151957650493344879513766262192237185642999150828898080904189181015450813145034385734032579549707819385285699926238835221520814478940626889936085239827537174490903769904145555260249190126341431327373827075950390882531223536876389814182564965563294518709637484074360669912550026080424160562533591856230955376566866124027875883101021495284600804805028045254063691285010599912421270508133194975917146762267305044225075915290251742774636494555052325186322411388406191257012917881384181566918237215400893603475101448554254698937834239606460813666829750019379115061709452680984785152862123171377897417492087541064556959508967969794980679770961683057941674310519254486327358885118436597143583348756027405400165571178309126113117314169066606067613797690123141099672013123730329707678988740099317309687380126740538923612230370779727025191340850390101739924877352408881040807749924412635346413181858792480760553268122881584307471326768283097203149049868884456187976015468233715478415429742230166504759393312132256510189175368566338139736836336126010908419590215582111816677413843969205870515074254852744810154541079359513596653630049188769523677579147319184225806802539818418929888943038224766186405856591859943091324575886587044653095332668532261321209825839180538360814144791320319699276037194760191286674308615217243049852806380129834255379486287824758850820609389214668693729881191560115633701248675404205911464930888219050248857645752083363921499441937170268576222251074166230901665867067714568862793343153513505688216165112807318529333124070912343832502302341169501745502360505475824093175657701604884577017762183184615567978427541088499501610912720817913532406784267161792013428902861583277304794830971705537485109380418091491750245433432217445924133037928381694330975012918544596923388733288616144238100112755828623259628572648121538348900698511503485369544461542161283241700533583180520082915722904696365553178152398468725451306350506984981006205514844020769539324155096762680887603572463913955278222246439122592651921288446961107463586148252820017348957533954255019475442643148903233373926763409115527189768429887783617346613535388507656327107814312435018965109238453660236940276060642119384227665755210663671879603217527184404651560427289869560206997012906367847161654793068868305846508082886614111979138822898112498261434559408961813509226857611474609406147937240008842153535862052780125014270055274468359151840373309373580494342483940467505708347927948338133276237937844629209323999417593374917899786484958148818865149169302451512835579818112344900827168644548306546633975256079615935830821400021951611342337058359111545217293721664061708131602078213341260356852013161345136871600980378712556766143923146458085652084039744217352744813741215277475202259244561520365608268890193913957991844109971588312780020898275935898106482117936157951837937026741451400902833064466209280549839169261068975151083963132117128513257434964510681479694782619701483204392206140109523453209269311762298139422044308117317394338867965739135764377642819353621467837436136161591167926578700137748127848510041447845416464568496606699139509524527949914769441031612575776863713634644477006787131066832417871556281779122339077841275184193161188155887229676749605752053192594847679397486414128879475647133049543555044790277128690095643357913405127375570391806822344718167939329121448449553897728696601037841520390662890781218240141299368590465146519209198605347788576842696538459445700169758422531241268031418456268722581132040056433413524302102739213788415250475704533878002467378571470021087314693254557923134757243640544448132093266582986850659125571745568328831440322798049274104403921761438405750750288608423536966715191668510428001748971774811216784160854454400190449242294333666338347684438072624307319019363571067447363413698467328522605570126450123348367412135721830146848071241856625742852208909104583727386227300781566668914250733456373259567253354316171586533339843321723688126003809020585719930855573100508771533737446465211874481748868710652311198691114058503492239156755462142467550498676710264926176510110766876596258810039163948397811986615585196216487695936398904500383258041054420595482859955239065758108017936807080830518996468540836412752905182813744878769639548306385089756146421874889271294890398025623046812175145502330254086076115859321603465240763923593699949180470780496764486889980902123735780457040380820770357387588525976042434608851075199334470112741787878845674656640471901619633546770714090590826954225196409446319547658653032104723804625249971910690110456227579220926904132753699634145768795242244563973018311291451151322757841320376225862458224784696669785947914981610522628786944136373683125108310682898766123782697506343047263278453719024447970975017396831214493357290791648779915089163278018852504558488782722376705263811803792477835540018117452957747339714012352011459901984753358434861297092928529424139865507522507808919352104173963493428604871342370429572757862549365917805401652536330410692033704691093097588782938291296447890613200063096560747882082122140978472301680600835812336957051454650181292694364578357815608503303392466039553797630836137289498678842851139853615593352782103740733076818433040893624460576706096188294529171362940967592507631348636606011346115980434147450705511490716640635688739020690279453438236930531133440901381392849163507484449076828386687476663619303412376248380175840467851210698290605196112357188811150723607303158506622574566366740720668999061320627793994112805759798332878792144188725498543014546662945079670707688135022230580562225942983096887732856788971494623888272184647618153045844390967248232348259587963698908456664795754200195991919240707615823002328977439748112690476546256873684352229063217889227643289360535947903046811114130586348244566489159211382258867880972564351646404364328416076247766114349880319792230537889671148058968061594279189647401954989466232962162567264739015818692956765601444248501821713300527995551312539849919933907083138030214072556753022600033565715934283182650908979350869698950542635843046765145668997627989606295925119763672907762567862769469947280606094290314917493590511523235698715397127866718077578671910380368991445381484562682604003456798248689847811138328054940490519768008320299631757043011485087384048591850157264392187414592464617404735275250506783992273121600117160338604710710015235631159734711153198198710616109850375758965576728904060387168114313084172893710817412764581206119054145955378853200366615264923610030157044627231777788649806700723598889528747481372190175074700005571108178930354895017924552067329003818814068686247959272205591627902292600592107710510448103392878991286820705448979977319695574374529708195463942431669050083984398993036790655541596099324867822475424361758944371791403787168166189093900243862038610001362193667280872414291108080291896093127526202667881902085595708111853836166128848729527875143202956393295910508349687029060692838441522579419764824996318479414814660898281725690484184326061946254276693688953540732363428302189694947766126078346328490315128061501009539164530614554234923393806214007779256337619373052025699319099789404390847443596972052065999017828537676265683558625452697455260991024576619614037537859594506363227095122489241931813728141668427013096050734578659047904243852086508154491350136491698639048125666610843702294730266721499164849610746803261583352580352858275799038584091667618877199539888680431991650866887781701439663176815592262016991396613153738021294160006906947533431677802632207226265881842757216055461439677336258462997385077307751473833315101468395296411397329672457933540390136107395245686243008096720460995545708974893048753897955544443791303790422346037768729236001386569593952300768091377768847789746299699489949016141866131552200856673695770822720338936659590666350594330040363762591189195691561626122704788696510356062748423100605472091437069471661080277379848576543481249822444235828329813543645124092220896643987201997945619030397327254617823136363375927622656301565813545578319730419339269008282952718252138855126583037630477490625995514925943105307478901043009876580816508144862607975129633326675259272351611791836777128931053144471668835182920514343609292493191180249366051791485330421043899773019267686085347768149502299280938065840007311767895491286098112311307002535600347898600653805084532572431553654422067661352337408211307834360326940015926958459588297845649462271300855594293344520727007718206398887404742186697709349647758173683580193168322111365547392288184271373843690526638607662451284299368435082612881367358536293873792369928837047900484722240370919885912556341130849457067599032002751632513926694249485692320904596897775676762684224768120033279577059394613185252356456291805905295974791266162882381429824622654141067246487216174351317397697122228010100668178786776119825961537643641828573481088089988571570279722274734750248439022607880448075724807701621064670166965100202654371260046641935546165838945950143502160890185703558173661823437491622669077311800121188299737319891006060966841193266075165452741829459541189277264192546108246351931647783837078295218389645376236304858042774417907169146356546201215125418664885396161542055152375000426794253417764590821513675258479774465114750438460596325820468809667795709044645884673847481638045635188183210386594798204376334738389017759714236223057776395541011294523488098341476645559342209402059733452337956309441446698222457026367119493286653989491344225517746402732596722993581333110831711807234044326813737231209669052411856734897392234152750707954137453460386506786693396236535556479102508529284294227710593056660625152290924148057080971159783458351173168204129645967070633303569271821496292272073250126955216172649821895790908865085382490848904421755530946832055636316431893917626269931034289485184392539670922412565933079102365485294162132200251193795272480340133135247014182195618419055761030190199521647459734401211601239235679307823190770288415814605647291481745105388060109787505925537152356112290181284710137917215124667428500061818271276125025241876177485994084521492727902567005925854431027704636911098800554312457229683836980470864041706010966962231877065395275783874454229129966623016408054769705821417128636329650130416501278156397799631957412627634011130135082721772287129164002237230234809031485343677016544959380750634285293053131127965945266651960426350406454862543383772209428482543536823186182982713182489884498260285705690699045790998144649193654563259496570044689011049923939218088155626191834404362264965506449848521612498442375928443642612004256628602157801140467879662339228190804577624109076487087406157070486658398144845855803277997327929143195789110373530019873110486895656281917362036703039179710646309906285483702836118486672219457621775034511770110458001291255925462680537427727378863726783016568351092332280649908459179620305691566806180826586923920561895421631986004793961133953226395999749526798801074576466538377400437463695133685671362553184054638475191646737948743270916620098057717103475575333102702706317395612448413745782734376330101853438497450236265733191742446567787499665000938706441886733491099877926005340862442833450486907338279348425305698737469497333364267191968992849534561045719338665222471536681145666596959735075972188416698767321649331898967182978657974612216573922404856900225324160367805329990925438960169901664189038843548375648056012628830409421321300206164540821986138099462721214327234457806819925823202851398237118926541234460723597174777907172041523181575194793527456442984630888846385381068621715274531612303165705848974316209831401326306699896632888532682145204083110738032052784669279984003137878996525635126885368435559620598057278951754498694219326972133205286374577983487319388899574634252048213337552584571056619586932031563299451502519194559691231437579991138301656117185508816658756751184338145761060365142858427872190232598107834593970738225147111878311540875777560020664124562293239116606733386480367086953749244898068000217666674827426925968686433731916548717750106343608307376281613984107392410037196754833838054369880310983922140260514297591221159148505938770679068701351029862207502287721123345624421024715163941251258954337788492834236361124473822814504596821452253550035968325337489186278678359443979041598043992124889848660795045011701169092519383155609441705397900600291315024253848282782826223304151370929502192196508374714697845805550615914539506437316401173317807741497557116733034632008408954066541694665746735785483133770133628948904397670025863002540635264006601631712883920305576358989492412827022489373848906764385339931878608019223108328847459816417701264089078551777830131616162049792779670521847212730327970738223860581986744668610994383049960437407323195784473254857416239738852016202384784256163512597161783106850156299135559874758848151014815490937380933394074455700842090155903853444962128368313687375166780513082594599771257467939781491953642874321122421579851584491669362551569370916855252644720786527971466476760328471332985501945689772758983450586004316822658631176606237201721007922216410188299330808409384014213759697185976897042759041500946595252763487628135867117352364964121058854934496645898651826545634382851159137631569519895230262881794959971545221250667461174394884433312659432286710965281109501693028351496524082850120190831078678067061851145740970787563117610746428835593915985421673115153096948758378955979586132649569817205284291038172721213138681565524428109871168862743968021885581515367531218374119972919471325465199144188500672036481975944167950887487934416759598361960010994838744709079104099785974656112459851972157558134628546189728615020774374529539536929655449012953097288963767713353842429715394179547179095580120134210175150931491664699052366350233024087218654727629639065723341455005903913890253699317155917179823065162679744711857951506573868504088229934804445549850597823297898617029498418376255258757455303112991914341109413088238114443068843062655305601658801408561023324210300218460588586954418502977463085858496130037238190325162225570729975710727306066072916922978033647048840958711228045188511908718588299514331534128549297173849768523136276076868494780364948299904475715771141080958058141208956059471668626290036145602625334863284986816039463372436667112964460292915746181117789169695839947080954788863503281129626899231110099889317815313946681882028368363373822281414974006917942192888817139116283910295684918233358930813360131488748366464224381776081007739183393749346933644748150564933649323157235306109385796839902153381449126925350768211098738352197507736653475499431740580563099143218212547336281359488317681489194306530426029773885492974570569448783077945878865062970895499843760181694031056909587141386804846359853684034105948341788438963179956468815791937174656705047441528027712541569401365862097760735632832966564135817028088013546326104892768731829917950379944446328158595181380144716817284996793061814177131912099236282922612543236071226270324572637946863533391758737446552006008819975294017572421299723542069630427857950608911113416534893431149175314953530067419744979017235181671568754163484949491289001739377451431928382431183263265079530371177806185851153508809998200482761808307209649636476943066172549186143700971387567940218696710148540307471561091358933165600167252126542502898612259306484105898847129649230941215144563947889999327145875969555737090855150648002321476443037232466147111552578583071024936898814562568786834745518893385181791667579054210421036349316257870476543126790661216644142285017446278477132740595579600648343288827864837043456066966456899746910373987712891593313271266247505582258634928427718355831641593667712218537642376222104779338956378722902509543014182257180331300148113377736941508488867501893156994849838936052666818012783912005801431596441910546663236810148207799356523056490420711364192200177189107935243234322761787712568251126481332974354926568682748715986654943041648468220593921673359485057849622807932422649812705271398407720995707236227009245067665680069149966555737866411877079767754867028786431817941521796178310655030287157272282250812017060713380339641841211253856248920130010782462165136989511064611133562443838185366273563783436921279354709230119655914915800561707258518503167289370411936374780625824298250726464801821523430268081486978164824349353456855843696378384153838051184406043696871666416514036129729992912630842812149152469877429332305214999981829046119471676727503742221367186614654042534463141660649871499001000660041544868437352208483059495953182872280520828676300361091734508632133033647289584176588755345227938480297724485711815574893561311524926772006362198369980664159549388683836411891430443767715498026544959061738265591178545999378510861446014967645550103653971251138583505085112442517772923814396233043724036032603181442991365750246012787514117944901305803452199992701148071712847770301254994886841867572975189214295652512486943983729047410363121899124217339550688778643130750024823361832738729697376598820053895902935486054979802320400472236873557411858132734337978931582039412878989728973298812553514507641535360519462112217000676321611195841029252568536561813138784086477147099724553013170761712163186600291464501378587854802096244703771373587720086738054108140042311418525803293267396324596914044834665722042880679280616029884043400536534009706581694636096660911110968789751801325224478246957913251892122653056085866541115373584912790254654369020869419871125588453729063224423222287139122012248769976837147645598526739225904997885514250047585260297929306159913444898341973583316070107516452301310796620382579278533125161760789984630103493496981494261055367836366022561213767081421091373531780682420175737470287189310207606953355721704357535177461573524838432101571399813798596607129664438314791296359275429627129436142685922138993054980645399144588692472767598544271527788443836760149912897358259961869729756588978741082189422337344547375227693199222635973520722998387368484349176841191020246627479579564349615012657433845758638834735832242535328142047826934473129971189346354502994681747128179298167439644524956655532311649920677163664580318205849626132234652606175413532444702007661807418914040158148560001030119994109595492321434406067634769713089513389171050503856336503545166431774489640061738861761193622676890576955693918707703942304940038440622614449572516631017080642923345170422426679607075404028551182398361531383751432493056398381877995594942545196756559181968690885283434886050828529642437578712929439366177362830136595872723080969468398938676366226456791132977469812675226595621009318322081754694778878755356188335083870248295346078597023609865656376722755704495258739871812593441903785275571333409842450127258596692434317689018966145404453679047136294238156127656824247864736176671770647002431119711090007474065945650315375044177982192306323700872039212085499569681061379189029961178936752146022386905665481382858280449537530160921422195940638787074787991194920898374091788534417523064715030278397979864517336625329511775105559014160459873338186887977858817291976604516353353556047648420520888811722831990044504284486852338334530105533929637308039738230604714104525470094899407601215247602819963846343554852932377161410869591950786873276075400085220065031871239272857835807010762542769655355964789450166013816295177908531139811092831583216931563867459747449584385282701658246192092219529134323496779345585613140207765996142546463288677356891785576835169608392864188830094883324700447958316931533832382377876344426323456301679513671047510469669001217777128065522453689371871451567394733440447280450959433090683667110655953338602938000999949010642769859623260401863733572846679531229683156358145420890540651226419162015504500430562136991850941034609601030543816694795964585804425194905110733387679946734471718615647723811737035654917628707589456035519195603962301157866323750234725054461073979402475184415558178087962822231972692984516683306919505079993357259165675557294585962182052650473353712351623662770479333289322136141858785972771685682725303734836891911847197133753088446777943274857148827821608844765700041403499921376794209627560883081509438030705666022764678117533361028187800710219794428777313146387857817205661409023041499923248268982477222109852189758140879763486146763606368674611966620347304608917277240045953051376938375381543486981101990651706961774052218247422657652138152740612699012706880875386408669901461740890540981877671880076124151967064152117653084325544261017536348281196837493395825742541244634247233586360777980960199745187758845459645895956779558869098404768259253477849930457883128541747079059795909431627722327844578918694214929451540174214623240300841907975296782445969183509474202123617940309048634960534054931299919496087957952586977170236680033862505764938088740994009589948109397983231108838769236490221499111120870639202892490698435333152727991330986335454324971441378059132240814960156485679843966464780280409057580889190254236606774500413415794312112501275232250148067232979652230488493751166084976116412777395311302041566848265531411348993243747890268935173904043294851610659785832253168204202834993641595980197343889883020994152152288611175126686173051956249367180053845637855129171848417841594797435580617856680758491080185805695567990185198397660693358224779136504562705766735170961550493338390452612404395517449136885115987454340932040102218982707539212403241042424451570052968378815749468441508011138612561164102477190903050040240662278945607061512108266146098662040425010583978098192019726759010749924884966139441184159734610382401178556739080566483321039073867083298691078093495828888707110651559651222542929154212923108071159723275797510859911398076844732639426419452063138217862260999160086752446265457028969067192282283045169111363652774517975842147102219099906257373383472726498678244401048998507631630668050267115944636293525120269424810854530602810627264236538250773340575475701704367039596467715959261029438313074897245505729085688496091346323165819468660587092144653716755655531962091865952628448253731353698162517351930115341581171353292035873164168839107994000677266031617527582917398395852606454113318985505747847121053505795649095931672167565624818782002769963734155880000867852567422461511406015760115910256449002264980039498403358091309140197877843650167960167465370287466062584346329708303725980494653589318912163976013193079476972058034710553111117215859219066231028099212084069283091906017370764654655683413207556315315006453462321007133584907633048328153458698497332599801187479664273140279381289961720524540674695271948079930396730194274036466594154400092799908634806622334906695224044652158992864203435098858422692019340575496840904812955522654754650713532842543496616084954788090727649930252702815067862810825243222979985391759845188868387004477101866772159439708514664612871148749531862180941719676843144666435175837688436786081446319641912566574047718699160915550910878919431253671945651261878486910876729910565595155159739659034383628124629118117760949411880105946336671039049777312004243578115790429823045072038322781246413671297959415082918378213212876890545963586369344879749784841123274921331663162812456388238288715648447883142417650147980187858215768793063001153788998014623690135803753306246148576074932567807682651045738059018831237617271889933790487113395588485234240255002352200613574914318259142479829367775490496399350755839668967578364316618369307625603528602940662803255416535431518013714821941772672244005268401996533334184004345525296592918502940131600651124395297874364222806977720437363717873457948420238745151249157913139411148608416429347958793681868609689684640858334131017858142710955416293375915178392341303110543328703526599993904966822112768158316511246866451167351378214345336650598328347443536290312393672084593164394941881138607974670134709640378534907149089842317891739783650654751982883367395714360000003439863363212091718954899055748693397700245632475954504411422582410783866837655467400137324322809113692670682805397549111166171102397437749479335174036135005397581475520834285772800986189401984375446435081498218360112577632447389452051636938585136484259964518361856989088721789764694721246807900330925083496645841656554261294195108847197209106605105540933731954888406444080280579549008076040034154662137669606444293774985897353625591959618552448187940317374508256072895120945456562159540405425814886929842786582357673195799285293120866275922366115137445767916063621675267440451221051052090834707443986137829082352772895849625656881972792768694795806100573787084121444815034797422312103295359297822377134077549545477791813823542607184617108389097825964406170543546968567030745411634244134486308676327949177682923093183221341455482591367202823284396549001805653203960795517074496039006696990334199278212696767771835209083959545341866777944872740383733381985235884202840150981579594685874537989503257362809837592216229258598599123843993575573285028613155970362934249814178056461615863415338635077223269996508860870999964899373049307170967888740149746147542880387421250689212155876692242387434701120990859082164073576380817386959755176083877600277517253037133445654852635661720197563001580049790223419586738061442401502436288957503206533690825756785507020555105572381878574650371086308158185862815883054564662297694803970618265491385181326737485227188267917919091354407852685476254126683398240534022469989966652573155637645862251862823092085424412805997628505488913098331761884983352975136073772030571342739638126588567405013841074788943393996603591853934198416322617654857376671943132840050626295140357877264680649549355746326408186979718630218760025813995719923601345374229758918285167511358171472625828596940798518571870075823122317068134867930884899275181661399609753105295773584618525865211893339375771859916335112163441037910451845019023066893064178977808158101360449495409665363660370075881004450265734935127707426742578608784898185628869980851665713320835842613381142623855420315774246613108873106318111989880289722849790551075148403702290580483052731884959994156606537314021296702220821915862905952604040620011815269664910068587592655660567562963361434230232810747488395040380984981860056164646099819257616235478710913832967563761506732550860683433720438748186791668975746563456020002562889601191100980453350423842063824039434163502977688802779835087481178298349417211674919425601608685332435385951152061809031241698182079314615062073826097180458265687043623935757495737332781578904386011378078508110273049446611821957450170106059384336519458628360682108585130499820420578458577175933849015564447305834515291412561679970569657426139901681932056241927977282026714297258700193234337873153939403115411184101414292741703537542003698760608765500109345299007034032401334806388514095769557147190364152027721127070187421548123931953220997506553022646844227700020589045922742423904937051507367764629844971682121994198274794049092601715727439368569721862936007387077810797440975556627807371228030350048829843919546433753355787895064018998685060281902452191177018634505171087023903398550540704454189088472042376499749035038518949505897971286631644699407490959473411581934618336692169573605081585080837952036335619947691937965065016808710250735070825260046821242820434367245824478859256555487861614478717581068572356895150707602217433511627331709472765932413249132702425519391509083601346239612335001086614623850633127072987745618984384288764099836164964775714638573247333226653894523588365972955159905187411779288608760239306160016168434070611663449248395156319152882728822831375458678269830696691220130954815935450754923554167766876455212545681242936427474153815692219503331560151614492247512488957534835926226263545406704767033866410025277276800886383266629488582740369655329362236090572479794734434077704284318507901973469071141230364111729224929307731939309795452877412451183953480382210373644697046967493042810911797232448615413264031578430955396671061468083815548947146733652483679138566431084747848676243012018489329109615281108087617422779131629345494425395422727309645057976122885347393189600810965202090151104579377602529543130188938184010247010134929317443562883578609861545691161669857388024973756940558138630581099823372565164920155443216861690537054630176154809626620800633059320775897175589925862195462096455464624399535391743228225433267174308492508396461328929584567927365409119947616225155964704061297047759818551878441419948614013153859322060745185909608884280218943358691959604936409651570327527570641500776261323783648149005245481413195989296398441371781402764122087644989688629798910870164270169014007825748311598976330612951195680427485317886333041169767175063822135213839779138443325644288490872919067009802496281560626258636942322658490628628035057282983101266919109637258378149363774960594515216932644945188292639525772348420077356021656909077097264985642831778694777804964343991762549216500608626285329471055602670413384500507827390640287529864161287496473708235188892189612641279553536442286955430551308700009878557534223100547153412810957024870812654319123261956462149376527526356402127388765103883255007364899937167183280028398832319373301564123277185395654932422977953016534830128490677845037490891749347389015649588574802194996722621185874361039774946338633057887487405540005440439344888192044102134790034598411927024921557026873700970995205391930979319495883265922171508324621942300185974396706491149559411733728199869021311629886680267446443489233020607003821262841723679627307191405008084085703978151998148822390059948911946474438682533745889962375133378280532928272016815977970066488394482446332210928320504045983008943565954267256879714918703447338237767914829203283196838105907715727191903042365315650957464549643425328069510396558733549803850995143463506175361480050195045201350200180281506933241918267855737764414097080945745624854867704904368368717590918057269794010465019484853146726642978667687697789291431128505043098192949736165944259471754765135205245072597538577958372797702972231435199958499522344049394502115428867244188717409524554771867484911475031801773304689909317974472957035192387686405544278134169807249382219749124257510162187439772902147704638010731470653154201300583810458905006764557332998149945854655105526374914354195867992595981412218735238407957416123372264063860431988936249867649693592569592128495906254446474331759999685163660305216426770428154681777589339252115538590526823311608302751194384823861552852465010329467297198112105314125898165100120742688143577590825227466863206188376830450921784582526239594189673003640808624233657620979111641766331328852352062487922978959456450333733139422384778582717195412347860434376165241568717943562570215636666680088531006728947033079540804583324192188488870712275670333173939262509073556164513677064199539111948881240659821685787131385056850623094155206877987539740658484250135205615103489821873770245063583314243624807432542464195984647411575625441010389671576677263196442524931941806472423789334668561083789808830313571333157729435664956078125304917594015895146954965223118559669048559467607968190167266634650186182955669893965019614544401768162810604465068448139561667220729261210164692339016793399632833013163850830967942792934551268435760356901970523138364640961311774904600772840862214747547653221505518116489887879087780918009050706040061220010051271575991225725282523378026809030528461581739558198122397010092017202251606352922464781615533532275453264543087093320924631855976580561717446840450048285353396546862678852330044967795580761661801833668792312510460809773895565488962815089519622093675058841609752282328250433712970186608193748968699961301486924694482420723632912367052542145464162968910442981633373266871675946715392611950649224725627254543274193495995569590243279097174392258098103601486364409101491734183079646345064833303404765711827040276868271418084574998493392039317445402616663674646668754385093967129918067471909885312710726724428584870694307099756567949198418996425748884764622030325637751112534060087936904565779272035205921345924272965206683338510673615276261016026647772485083344719891986802656197236420847504962661607797092906844757798251795569758235084371746103310387911789239441630112634077535773520558040066982523191225570519133631407211349723226549151062961739050617857127509403623146700931176133132018631158730886798239298009805089491510788371194099750375473674305745187265414016446924576792185753680363289139664155342066705623272936001177781498886100830877849571709880858667023104043242526785955562077310543072298032125941107957349146684680220501816192150766649106862033378713826058987655210423668198670177861672671972374156917880001690656659046965316154923604061891820982414006103779407166342002735828911994182647812782659666207030384795881442790246669264032799404016800137293477301530941805070587421153284642203006550763966756168318897005152026656649929417382840327305940740147117478464839241225676523593418554066440983706083636457657081801664285044258224551650808864421212113914352453935225522162483791737330329812349528984098613273709957407786789349311975204237925022851375880436791854547836416773151821457226504640800104202100410766027807729152555503218182387221708112766208665317651926458452495269685376314437998340336947124447247796973890514941120010934140073794061859447165516612674930799374705772930521750426383798367668159183589049652163726492960837147204067428996276720315410211504333742057182854090136325721437592054640471894328548696883599785122262130812989581571391597464534806099601555877223193450760315411663112963843719400333736013305526352571490454327925190794007111504785378036370897340146753465517470747096935814912797188187854376797751675927822300312945518595042883902735494672667647506072643698761394806879080593531793001711000214417701504495496412454361656210150919997862972495905809191825255486358703529320142005857057855419217730505342687533799076038746689684283402648733290888881745453047194740939258407362058242849349024756883352446212456101562729065130618520732925434179252299417447855189995098959999877410951464170076989305620163502192692653166599093238118295411937545448509428621839424186218067457128099385258842631930670182098008050900019819621758458932516877698594110522845465835679362969619219080897536813210484518784516230623911878024604050824909336069998094776253792973597037759066145994638578378211017122446355845171941670344732162722443265914858595797823752976323442911242311368603724514438765801271594060878788638511089680883165505046309006148832545452819908256238805872042843941834687865142541377686054291079721004271658
diff --git a/libgo/go/compress/testdata/pi.txt b/libgo/go/compress/testdata/pi.txt
index 58d8f3b6dd4..ca99bbc2a25 100644
--- a/libgo/go/compress/testdata/pi.txt
+++ b/libgo/go/compress/testdata/pi.txt
@@ -1 +1 @@
-3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678
+3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678566722796619885782794848855834397518744545512965634434803966420557982936804352202770984294232533022576341807039476994159791594530069752148293366555661567873640053666564165473217043903521329543529169414599041608753201868379370234888689479151071637852902345292440773659495630510074210871426134974595615138498713757047101787957310422969066670214498637464595280824369445789772330048764765241339075920434019634039114732023380715095222010682563427471646024335440051521266932493419673977041595683753555166730273900749729736354964533288869844061196496162773449518273695588220757355176651589855190986665393549481068873206859907540792342402300925900701731960362254756478940647548346647760411463233905651343306844953979070903023460461470961696886885014083470405460742958699138296682468185710318879065287036650832431974404771855678934823089431068287027228097362480939962706074726455399253994428081137369433887294063079261595995462624629707062594845569034711972996409089418059534393251236235508134949004364278527138315912568989295196427287573946914272534366941532361004537304881985517065941217352462589548730167600298865925786628561249665523533829428785425340483083307016537228563559152534784459818313411290019992059813522051173365856407826484942764411376393866924803118364453698589175442647399882284621844900877769776312795722672655562596282542765318300134070922334365779160128093179401718598599933849235495640057099558561134980252499066984233017350358044081168552653117099570899427328709258487894436460050410892266917835258707859512983441729535195378855345737426085902908176515578039059464087350612322611200937310804854852635722825768203416050484662775045003126200800799804925485346941469775164932709504934639382432227188515974054702148289711177792376122578873477188196825462981268685817050740272550263329044976277894423621674119186269439650671515779586756482399391760426017633870454990176143641204692182370764887834196896861181558158736062938603810171215855272668300823834046564758804051380801633638874216371406435495561868964112282140753302655100424104896783528588290243670904887118190909494533144218287661810310073547705498159680772009474696134360928614849417850171807793068108546900094458995279424398139213505586422196483491512639012803832001097738680662877923971801461343244572640097374257007359210031541508936793008169980536520276007277496745840028362405346037263416554259027601834840306811381855105979705664007509426087885735796037324514146786703688098806097164258497595138069309449401515422221943291302173912538355915031003330325111749156969174502714943315155885403922164097229101129035521815762823283182342548326111912800928252561902052630163911477247331485739107775874425387611746578671169414776421441111263583553871361011023267987756410246824032264834641766369806637857681349204530224081972785647198396308781543221166912246415911776732253264335686146186545222681268872684459684424161078540167681420808850280054143613146230821025941737562389942075713627516745731891894562835257044133543758575342698699472547031656613991999682628247270641336222178923903176085428943733935618891651250424404008952719837873864805847268954624388234375178852014395600571048119498842390606136957342315590796703461491434478863604103182350736502778590897578272731305048893989009923913503373250855982655867089242612429473670193907727130706869170926462548423240748550366080136046689511840093668609546325002145852930950000907151058236267293264537382104938724996699339424685516483261134146110680267446637334375340764294026682973865220935701626384648528514903629320199199688285171839536691345222444708045923966028171565515656661113598231122506289058549145097157553900243931535190902107119457300243880176615035270862602537881797519478061013715004489917210022201335013106016391541589578037117792775225978742891917915522417189585361680594741234193398420218745649256443462392531953135103311476394911995072858430658361935369329699289837914941939406085724863968836903265564364216644257607914710869984315733749648835292769328220762947282381537409961545598798259891093717126218283025848112389011968221429457667580718653806506487026133892822994972574530332838963818439447707794022843598834100358385423897354243956475556840952248445541392394100016207693636846776413017819659379971557468541946334893748439129742391433659360410035234377706588867781139498616478747140793263858738624732889645643598774667638479466504074111825658378878454858148962961273998413442726086061872455452360643153710112746809778704464094758280348769758948328241239292960582948619196670918958089833201210318430340128495116203534280144127617285830243559830032042024512072872535581195840149180969253395075778400067465526031446167050827682772223534191102634163157147406123850425845988419907611287258059113935689601431668283176323567325417073420817332230462987992804908514094790368878687894930546955703072619009502076433493359106024545086453628935456862958531315337183868265617862273637169757741830239860065914816164049449650117321313895747062088474802365371031150898427992754426853277974311395143574172219759799359685252285745263796289612691572357986620573408375766873884266405990993505000813375432454635967504844235284874701443545419576258473564216198134073468541117668831186544893776979566517279662326714810338643913751865946730024434500544995399742372328712494834706044063471606325830649829795510109541836235030309453097335834462839476304775645015008507578949548931393944899216125525597701436858943585877526379625597081677643800125436502371412783467926101995585224717220177723700417808419423948725406801556035998390548985723546745642390585850216719031395262944554391316631345308939062046784387785054239390524731362012947691874975191011472315289326772533918146607300089027768963114810902209724520759167297007850580717186381054967973100167870850694207092232908070383263453452038027860990556900134137182368370991949516489600755049341267876436746384902063964019766685592335654639138363185745698147196210841080961884605456039038455343729141446513474940784884423772175154334260306698831768331001133108690421939031080143784334151370924353013677631084913516156422698475074303297167469640666531527035325467112667522460551199581831963763707617991919203579582007595605302346267757943936307463056901080114942714100939136913810725813781357894005599500183542511841721360557275221035268037357265279224173736057511278872181908449006178013889710770822931002797665935838758909395688148560263224393726562472776037890814458837855019702843779362407825052704875816470324581290878395232453237896029841669225489649715606981192186584926770403956481278102179913217416305810554598801300484562997651121241536374515005635070127815926714241342103301566165356024733807843028655257222753049998837015348793008062601809623815161366903341111386538510919367393835229345888322550887064507539473952043968079067086806445096986548801682874343786126453815834280753061845485903798217994599681154419742536344399602902510015888272164745006820704193761584547123183460072629339550548239557137256840232268213012476794522644820910235647752723082081063518899152692889108455571126603965034397896278250016110153235160519655904211844949907789992007329476905868577878720982901352956613978884860509786085957017731298155314951681467176959760994210036183559138777817698458758104466283998806006162298486169353373865787735983361613384133853684211978938900185295691967804554482858483701170967212535338758621582310133103877668272115726949518179589754693992642197915523385766231676275475703546994148929041301863861194391962838870543677743224276809132365449485366768000001065262485473055861598999140170769838548318875014293890899506854530765116803337322265175662207526951791442252808165171667766727930354851542040238174608923283917032754257508676551178593950027933895920576682789677644531840404185540104351348389531201326378369283580827193783126549617459970567450718332065034556644034490453627560011250184335607361222765949278393706478426456763388188075656121689605041611390390639601620221536849410926053876887148379895599991120991646464411918568277004574243434021672276445589330127781586869525069499364610175685060167145354315814801054588605645501332037586454858403240298717093480910556211671546848477803944756979804263180991756422809873998766973237695737015808068229045992123661689025962730430679316531149401764737693873514093361833216142802149763399189835484875625298752423873077559555955465196394401821840998412489826236737714672260616336432964063357281070788758164043814850188411431885988276944901193212968271588841338694346828590066640806314077757725705630729400492940302420498416565479736705485580445865720227637840466823379852827105784319753541795011347273625774080213476826045022851579795797647467022840999561601569108903845824502679265942055503958792298185264800706837650418365620945554346135134152570065974881916341359556719649654032187271602648593049039787489589066127250794828276938953521753621850796297785146188432719223223810158744450528665238022532843891375273845892384422535472653098171578447834215822327020690287232330053862163479885094695472004795231120150432932266282727632177908840087861480221475376578105819702226309717495072127248479478169572961423658595782090830733233560348465318730293026659645013718375428897557971449924654038681799213893469244741985097334626793321072686870768062639919361965044099542167627840914669856925715074315740793805323925239477557441591845821562518192155233709607483329234921034514626437449805596103307994145347784574699992128599999399612281615219314888769388022281083001986016549416542616968586788372609587745676182507275992950893180521872924610867639958916145855058397274209809097817293239301067663868240401113040247007350857828724627134946368531815469690466968693925472519413992914652423857762550047485295476814795467007050347999588867695016124972282040303995463278830695976249361510102436555352230690612949388599015734661023712235478911292547696176005047974928060721268039226911027772261025441492215765045081206771735712027180242968106203776578837166909109418074487814049075517820385653909910477594141321543284406250301802757169650820964273484146957263978842560084531214065935809041271135920041975985136254796160632288736181367373244506079244117639975974619383584574915988097667447093006546342423460634237474666080431701260052055928493695941434081468529815053947178900451835755154125223590590687264878635752541911288877371766374860276606349603536794702692322971868327717393236192007774522126247518698334951510198642698878471719396649769070825217423365662725928440620430214113719922785269984698847702323823840055655517889087661360130477098438611687052310553149162517283732728676007248172987637569816335415074608838663640693470437206688651275688266149730788657015685016918647488541679154596507234287730699853713904300266530783987763850323818215535597323530686043010675760838908627049841888595138091030423595782495143988590113185835840667472370297149785084145853085781339156270760356390763947311455495832266945702494139831634332378975955680856836297253867913275055542524491943589128405045226953812179131914513500993846311774017971512283785460116035955402864405902496466930707769055481028850208085800878115773817191741776017330738554758006056014337743299012728677253043182519757916792969965041460706645712588834697979642931622965520168797300035646304579308840327480771811555330909887025505207680463034608658165394876951960044084820659673794731680864156456505300498816164905788311543454850526600698230931577765003780704661264706021457505793270962047825615247145918965223608396645624105195510522357239739512881816405978591427914816542632892004281609136937773722299983327082082969955737727375667615527113922588055201898876201141680054687365580633471603734291703907986396522961312801782679717289822936070288069087768660593252746378405397691848082041021944719713869256084162451123980620113184541244782050110798760717155683154078865439041210873032402010685341947230476666721749869868547076781205124736792479193150856444775379853799732234456122785843296846647513336573692387201464723679427870042503255589926884349592876124007558756946413705625140011797133166207153715436006876477318675587148783989081074295309410605969443158477539700943988394914432353668539209946879645066533985738887866147629443414010498889931600512076781035886116602029611936396821349607501116498327856353161451684576956871090029997698412632665023477167286573785790857466460772283415403114415294188047825438761770790430001566986776795760909966936075594965152736349811896413043311662774712338817406037317439705406703109676765748695358789670031925866259410510533584384656023391796749267844763708474978333655579007384191473198862713525954625181604342253729962863267496824058060296421146386436864224724887283434170441573482481833301640566959668866769563491416328426414974533349999480002669987588815935073578151958899005395120853510357261373640343675347141048360175464883004078464167452167371904831096767113443494819262681110739948250607394950735031690197318521195526356325843390998224986240670310768318446607291248747540316179699411397387765899868554170318847788675929026070043212666179192235209382278788809886335991160819235355570464634911320859189796132791319756490976000139962344455350143464268604644958624769094347048293294140411146540923988344435159133201077394411184074107684981066347241048239358274019449356651610884631256785297769734684303061462418035852933159734583038455410337010916767763742762102137013548544509263071901147318485749233181672072137279355679528443925481560913728128406333039373562420016045664557414588166052166608738748047243391212955877763906969037078828527753894052460758496231574369171131761347838827194168606625721036851321566478001476752310393578606896111259960281839309548709059073861351914591819510297327875571049729011487171897180046961697770017913919613791417162707018958469214343696762927459109940060084983568425201915593703701011049747339493877885989417433031785348707603221982970579751191440510994235883034546353492349826883624043327267415540301619505680654180939409982020609994140216890900708213307230896621197755306659188141191577836272927461561857103721724710095214236964830864102592887457999322374955191221951903424452307535133806856807354464995127203174487195403976107308060269906258076020292731455252078079914184290638844373499681458273372072663917670201183004648190002413083508846584152148991276106513741539435657211390328574918769094413702090517031487773461652879848235338297260136110984514841823808120540996125274580881099486972216128524897425555516076371675054896173016809613803811914361143992106380050832140987604599309324851025168294467260666138151745712559754953580239983146982203613380828499356705575524712902745397762140493182014658008021566536067765508783804304134310591804606800834591136640834887408005741272586704792258319127415739080914383138456424150940849133918096840251163991936853225557338966953749026620923261318855891580832455571948453875628786128859004106006073746501402627824027346962528217174941582331749239683530136178653673760642166778137739951006589528877427662636841830680190804609849809469763667335662282915132352788806157768278159588669180238940333076441912403412022316368577860357276941541778826435238131905028087018575047046312933353757285386605888904583111450773942935201994321971171642235005644042979892081594307167019857469273848653833436145794634175922573898588001698014757420542995801242958105456510831046297282937584161162532562516572498078492099897990620035936509934721582965174135798491047111660791587436986541222348341887722929446335178653856731962559852026072947674072616767145573649812105677716893484917660771705277187601199908144113058645577910525684304811440261938402322470939249802933550731845890355397133088446174107959162511714864874468611247605428673436709046678468670274091881014249711149657817724279347070216688295610877794405048437528443375108828264771978540006509704033021862556147332117771174413350281608840351781452541964320309576018694649088681545285621346988355444560249556668436602922195124830910605377201980218310103270417838665447181260397190688462370857518080035327047185659499476124248110999288679158969049563947624608424065930948621507690314987020673533848349550836366017848771060809804269247132410009464014373603265645184566792456669551001502298330798496079949882497061723674493612262229617908143114146609412341593593095854079139087208322733549572080757165171876599449856937956238755516175754380917805280294642004472153962807463602113294255916002570735628126387331060058910652457080244749375431841494014821199962764531068006631183823761639663180931444671298615527598201451410275600689297502463040173514891945763607893528555053173314164570504996443890936308438744847839616840518452732884032345202470568516465716477139323775517294795126132398229602394548579754586517458787713318138752959809412174227300352296508089177705068259248822322154938048371454781647213976820963320508305647920482085920475499857320388876391601995240918938945576768749730856955958010659526503036266159750662225084067428898265907510637563569968211510949669744580547288693631020367823250182323708459790111548472087618212477813266330412076216587312970811230758159821248639807212407868878114501655825136178903070860870198975889807456643955157415363193191981070575336633738038272152798849350397480015890519420879711308051233933221903466249917169150948541401871060354603794643379005890957721180804465743962806186717861017156740967662080295766577051291209907944304632892947306159510430902221439371849560634056189342513057268291465783293340524635028929175470872564842600349629611654138230077313327298305001602567240141851520418907011542885799208121984493156999059182011819733500126187728036812481995877070207532406361259313438595542547781961142935163561223496661522614735399674051584998603552953329245752388810136202347624669055816438967863097627365504724348643071218494373485300606387644566272186661701238127715621379746149861328744117714552444708997144522885662942440230184791205478498574521634696448973892062401943518310088283480249249085403077863875165911302873958787098100772718271874529013972836614842142871705531796543076504534324600536361472618180969976933486264077435199928686323835088756683595097265574815431940195576850437248001020413749831872259677387154958399718444907279141965845930083942637020875635398216962055324803212267498911402678528599673405242031091797899905718821949391320753431707980023736590985375520238911643467185582906853711897952626234492483392496342449714656846591248918556629589329909035239233333647435203707701010843880032907598342170185542283861617210417603011645918780539367447472059985023582891833692922337323999480437108419659473162654825748099482509991833006976569367159689364493348864744213500840700660883597235039532340179582557036016936990988671132109798897070517280755855191269930673099250704070245568507786790694766126298082251633136399521170984528092630375922426742575599892892783704744452189363203489415521044597261883800300677617931381399162058062701651024458869247649246891924612125310275731390840470007143561362316992371694848132554200914530410371354532966206392105479824392125172540132314902740585892063217589494345489068463993137570910346332714153162232805522972979538018801628590735729554162788676498274186164218789885741071649069191851162815285486794173638906653885764229158342500673612453849160674137340173572779956341043326883569507814931378007362354180070619180267328551191942676091221035987469241172837493126163395001239599240508454375698507957046222664619000103500490183034153545842833764378111988556318777792537201166718539541835984438305203762819440761594106820716970302285152250573126093046898423433152732131361216582808075212631547730604423774753505952287174402666389148817173086436111389069420279088143119448799417154042103412190847094080254023932942945493878640230512927119097513536000921971105412096683111516328705423028470073120658032626417116165957613272351566662536672718998534199895236884830999302757419916463841427077988708874229277053891227172486322028898425125287217826030500994510824783572905691988555467886079462805371227042466543192145281760741482403827835829719301017888345674167811398954750448339314689630763396657226727043393216745421824557062524797219978668542798977992339579057581890622525473582205236424850783407110144980478726691990186438822932305382318559732869780922253529591017341407334884761005564018242392192695062083183814546983923664613639891012102177095976704908305081854704194664371312299692358895384930136356576186106062228705599423371631021278457446463989738188566746260879482018647487672727222062676465338099801966883680994159075776852639865146253336312450536402610569605513183813174261184420189088853196356986962795036738424313011331753305329802016688817481342988681585577810343231753064784983210629718425184385534427620128234570716988530518326179641178579608888150329602290705614476220915094739035946646916235396809201394578175891088931992112260073928149169481615273842736264298098234063200244024495894456129167049508235812487391799648641133480324757775219708932772262349486015046652681439877051615317026696929704928316285504212898146706195331970269507214378230476875280287354126166391708245925170010714180854800636923259462019002278087409859771921805158532147392653251559035410209284665925299914353791825314545290598415817637058927906909896911164381187809435371521332261443625314490127454772695739393481546916311624928873574718824071503995009446731954316193855485207665738825139639163576723151005556037263394867208207808653734942440115799667507360711159351331959197120948964717553024531364770942094635696982226673775209945168450643623824211853534887989395673187806606107885440005508276570305587448541805778891719207881423351138662929667179643468760077047999537883387870348718021842437342112273940255717690819603092018240188427057046092622564178375265263358324240661253311529423457965569502506810018310900411245379015332966156970522379210325706937051090830789479999004999395322153622748476603613677697978567386584670936679588583788795625946464891376652199588286933801836011932368578558558195556042156250883650203322024513762158204618106705195330653060606501054887167245377942831338871631395596905832083416898476065607118347136218123246227258841990286142087284956879639325464285343075301105285713829643709990356948885285190402956047346131138263878897551788560424998748316382804046848618938189590542039889872650697620201995548412650005394428203930127481638158530396439925470201672759328574366661644110962566337305409219519675148328734808957477775278344221091073111351828046036347198185655572957144747682552857863349342858423118749440003229690697758315903858039353521358860079600342097547392296733310649395601812237812854584317605561733861126734780745850676063048229409653041118306671081893031108871728167519579675347188537229309616143204006381322465841111157758358581135018569047815368938137718472814751998350504781297718599084707621974605887423256995828892535041937958260616211842368768511418316068315867994601652057740529423053601780313357263267054790338401257305912339601880137825421927094767337191987287385248057421248921183470876629667207272325650565129333126059505777727542471241648312832982072361750574673870128209575544305968395555686861188397135522084452852640081252027665557677495969626612604565245684086139238265768583384698499778726706555191854468698469478495734622606294219624557085371272776523098955450193037732166649182578154677292005212667143463209637891852323215018976126034373684067194193037746880999296877582441047878123266253181845960453853543839114496775312864260925211537673258866722604042523491087026958099647595805794663973419064010036361904042033113579336542426303561457009011244800890020801478056603710154122328891465722393145076071670643556827437743965789067972687438473076346451677562103098604092717090951280863090297385044527182892749689212106670081648583395537735919136950153162018908887484210798706899114804669270650940762046502772528650728905328548561433160812693005693785417861096969202538865034577183176686885923681488475276498468821949739729707737187188400414323127636504814531122850990020742409255859252926103021067368154347015252348786351643976235860419194129697690405264832347009911154242601273438022089331096686367898694977994001260164227609260823493041180643829138347354679725399262338791582998486459271734059225620749105308531537182911681637219395188700957788181586850464507699343940987433514431626330317247747486897918209239480833143970840673084079589358108966564775859905563769525232653614424780230826811831037735887089240613031336477371011628214614661679404090518615260360092521947218890918107335871964142144478654899528582343947050079830388538860831035719306002771194558021911942899922722353458707566246926177663178855144350218287026685610665003531050216318206017609217984684936863161293727951873078972637353717150256378733579771808184878458866504335824377004147710414934927438457587107159731559439426412570270965125108115548247939403597681188117282472158250109496096625393395380922195591918188552678062149923172763163218339896938075616855911752998450132067129392404144593862398809381240452191484831646210147389182510109096773869066404158973610476436500068077105656718486281496371118832192445663945814491486165500495676982690308911185687986929470513524816091743243015383684707292898982846022237301452655679898627767968091469798378268764311598832109043715611299766521539635464420869197567370005738764978437686287681792497469438427465256316323005551304174227341646455127812784577772457520386543754282825671412885834544435132562054464241011037955464190581168623059644769587054072141985212106734332410756767575818456990693046047522770167005684543969234041711089888993416350585157887353430815520811772071880379104046983069578685473937656433631979786803671873079693924236321448450354776315670255390065423117920153464977929066241508328858395290542637687668968805033317227800185885069736232403894700471897619347344308437443759925034178807972235859134245813144049847701732361694719765715353197754997162785663119046912609182591249890367654176979903623755286526375733763526969344354400473067198868901968147428767790866979688522501636949856730217523132529265375896415171479559538784278499866456302878831962099830494519874396369070682762657485810439112232618794059941554063270131989895703761105323606298674803779153767511583043208498720920280929752649812569163425000522908872646925284666104665392171482080130502298052637836426959733707053922789153510568883938113249757071331029504430346715989448786847116438328050692507766274500122003526203709466023414648998390252588830148678162196775194583167718762757200505439794412459900771152051546199305098386982542846407255540927403132571632640792934183342147090412542533523248021932277075355546795871638358750181593387174236061551171013123525633485820365146141870049205704372018261733194715700867578539336078622739558185797587258744102542077105475361294047460100094095444959662881486915903899071865980563617137692227290764197755177720104276496949611056220592502420217704269622154958726453989227697660310524980855759471631075870133208861463266412591148633881220284440694169488261529577625325019870359870674380469821942056381255833436421949232275937221289056420943082352544084110864545369404969271494003319782861318186188811118408257865928757426384450059944229568586460481033015388911499486935436030221810943466764000022362550573631294626296096198760564259963946138692330837196265954739234624134597795748524647837980795693198650815977675350553918991151335252298736112779182748542008689539658359421963331502869561192012298889887006079992795411188269023078913107603617634779489432032102773359416908650071932804017163840644987871753756781185321328408216571107549528294974936214608215583205687232185574065161096274874375098092230211609982633033915469494644491004515280925089745074896760324090768983652940657920198315265410658136823791984090645712468948470209357761193139980246813405200394781949866202624008902150166163813538381515037735022966074627952910384068685569070157516624192987244482719429331004854824454580718897633003232525821581280327467962002814762431828622171054352898348208273451680186131719593324711074662228508710666117703465352839577625997744672185715816126411143271794347885990892808486694914139097716736900277758502686646540565950394867841110790116104008572744562938425494167594605487117235946429105850909950214958793112196135908315882620682332156153086833730838173279328196983875087083483880463884784418840031847126974543709373298362402875197920802321878744882872843727378017827008058782410749357514889978911739746129320351081432703251409030487462262942344327571260086642508333187688650756429271605525289544921537651751492196367181049435317858383453865255656640657251363575064353236508936790431702597878177190314867963840828810209461490079715137717099061954969640070867667102330048672631475510537231757114322317411411680622864206388906210192355223546711662137499693269321737043105987225039456574924616978260970253359475020913836673772894438696400028110344026084712899000746807764844088711341352503367877316797709372778682166117865344231732264637847697875144332095340001650692130546476890985050203015044880834261845208730530973189492916425322933612431514306578264070283898409841602950309241897120971601649265613413433422298827909921786042679812457285345801338260995877178113102167340256562744007296834066198480676615805021691833723680399027931606420436812079900316264449146190219458229690992122788553948783538305646864881655562294315673128274390826450611628942803501661336697824051770155219626522725455850738640585299830379180350432876703809252167907571204061237596327685674845079151147313440001832570344920909712435809447900462494313455028900680648704293534037436032625820535790118395649089354345101342969617545249573960621490288728932792520696535386396443225388327522499605986974759882329916263545973324445163755334377492928990581175786355555626937426910947117002165411718219750519831787137106051063795558588905568852887989084750915764639074693619881507814685262133252473837651192990156109189777922008705793396463827490680698769168197492365624226087154176100430608904377976678519661891404144925270480881971498801542057787006521594009289777601330756847966992955433656139847738060394368895887646054983871478968482805384701730871117761159663505039979343869339119789887109156541709133082607647406305711411098839388095481437828474528838368079418884342666222070438722887413947801017721392281911992365405516395893474263953824829609036900288359327745855060801317988407162446563997948275783650195514221551339281978226984278638391679715091262410548725700924070045488485692950448110738087996547481568913935380943474556972128919827177020766613602489581468119133614121258783895577357194986317210844398901423948496659251731388171602663261931065366535041473070804414939169363262373767777095850313255990095762731957308648042467701212327020533742667053142448208168130306397378736642483672539837487690980602182785786216512738563513290148903509883270617258932575363993979055729175160097615459044771692265806315111028038436017374742152476085152099016158582312571590733421736576267142390478279587281505095633092802668458937649649770232973641319060982740633531089792464242134583740901169391964250459128813403498810635400887596820054408364386516617880557608956896727531538081942077332597917278437625661184319891025007491829086475149794003160703845549465385946027452447466812314687943441610993338908992638411847425257044572517459325738989565185716575961481266020310797628254165590506042479114016957900338356574869252800743025623419498286467914476322774005529460903940177536335655471931000175430047504719144899841040015867946179241610016454716551337074073950260442769538553834397550548871099785205401175169747581344926079433689543783221172450687344231989878844128542064742809735625807066983106979935260693392135685881391214807354728463227784908087002467776303605551232386656295178853719673034634701222939581606792509153217489030840886516061119011498443412350124646928028805996134283511884715449771278473361766285062169778717743824362565711779450064477718370221999106695021656757644044997940765037999954845002710665987813603802314126836905783190460792765297277694043613023051787080546511542469395265127101052927070306673024447125973939950514628404767431363739978259184541176413327906460636584152927019030276017339474866960348694976541752429306040727005059039503148522921392575594845078867977925253931765156416197168443524369794447355964260633391055126826061595726217036698506473281266724521989060549880280782881429796336696744124805982192146339565745722102298677599746738126069367069134081559412016115960190237753525556300606247983261249881288192937343476862689219239777833910733106588256813777172328315329082525092733047850724977139448333892552081175608452966590553940965568541706001179857293813998258319293679100391844099286575605993598910002969864460974714718470101531283762631146774209145574041815908800064943237855839308530828305476076799524357391631221886057549673832243195650655460852881201902363644712703748634421727257879503428486312944916318475347531435041392096108796057730987201352484075057637199253650470908582513936863463863368042891767107602111159828875539940120076013947033661793715396306139863655492213741597905119083588290097656647300733879314678913181465109316761575821351424860442292445304113160652700974330088499034675405518640677342603583409608605533747362760935658853109760994238347382222087292464497684560579562516765574088410321731345627735856052358236389532038534024842273371639123973215995440828421666636023296545694703577184873442034227706653837387506169212768015766181095420097708363604361110592409117889540338021426523948929686439808926114635414571535194342850721353453018315875628275733898268898523557799295727645229391567477566676051087887648453493636068278050564622813598885879259940946446041705204470046315137975431737187756039815962647501410906658866162180038266989961965580587208639721176995219466789857011798332440601811575658074284182910615193917630059194314434605154047710570054339000182453117733718955857603607182860506356479979004139761808955363669603162193113250223851791672055180659263518036251214575926238369348222665895576994660491938112486609099798128571823494006615552196112207203092277646200999315244273589488710576623894693889446495093960330454340842102462401048723328750081749179875543879387381439894238011762700837196053094383940063756116458560943129517597713935396074322792489221267045808183313764165818269562105872892447740035947009268662659651422050630078592002488291860839743732353849083964326147000532423540647042089499210250404726781059083644007466380020870126664209457181702946752278540074508552377720890581683918446592829417018288233014971554235235911774818628592967605048203864343108779562892925405638946621948268711042828163893975711757786915430165058602965217459581988878680408110328432739867198621306205559855266036405046282152306154594474489908839081999738747452969810776201487134000122535522246695409315213115337915798026979555710508507473874750758068765376445782524432638046143042889235934852961058269382103498000405248407084403561167817170512813378805705643450616119330424440798260377951198548694559152051960093041271007277849301555038895360338261929343797081874320949914159593396368110627557295278004254863060054523839151068998913578820019411786535682149118528207852130125518518493711503422159542244511900207393539627400208110465530207932867254740543652717595893500716336076321614725815407642053020045340183572338292661915308354095120226329165054426123619197051613839357326693760156914429944943744856809775696303129588719161129294681884936338647392747601226964158848900965717086160598147204467428664208765334799858222090619802173211614230419477754990738738567941189824660913091691772274207233367635032678340586301930193242996397204445179288122854478211953530898910125342975524727635730226281382091807439748671453590778633530160821559911314144205091447293535022230817193663509346865858656314855575862447818620108711889760652969899269328178705576435143382060141077329261063431525337182243385263520217735440715281898137698755157574546939727150488469793619500477720970561793913828989845327426227288647108883270173723258818244658436249580592560338105215606206155713299156084892064340303395262263451454283678698288074251422567451806184149564686111635404971897682154227722479474033571527436819409892050113653400123846714296551867344153741615042563256713430247655125219218035780169240326699541746087592409207004669340396510178134857835694440760470232540755557764728450751826890418293966113310160131119077398632462778219023650660374041606724962490137433217246454097412995570529142438208076098364823465973886691349919784013108015581343979194852830436739012482082444814128095443773898320059864909159505322857914576884962578665885999179867520554558099004556461178755249370124553217170194282884617402736649978475508294228020232901221630102309772151569446427909802190826689868834263071609207914085197695235553488657743425277531197247430873043619511396119080030255878387644206085044730631299277888942729189727169890575925244679660189707482960949190648764693702750773866432391919042254290235318923377293166736086996228032557185308919284403805071030064776847863243191000223929785255372375566213644740096760539439838235764606992465260089090624105904215453927904411529580345334500256244101006359530039598864466169595626351878060688513723462707997327233134693971456285542615467650632465676620279245208581347717608521691340946520307673391841147504140168924121319826881568664561485380287539331160232292555618941042995335640095786495340935115266454024418775949316930560448686420862757201172319526405023099774567647838488973464317215980626787671838005247696884084989185086149003432403476742686245952395890358582135006450998178244636087317754378859677672919526111213859194725451400301180503437875277664402762618941017576872680428176623860680477885242887430259145247073950546525135339459598789619778911041890292943818567205070964606263541732944649576612651953495701860015412623962286413897796733329070567376962156498184506842263690367849555970026079867996261019039331263768556968767029295371162528005543100786408728939225714512481135778627664902425161990277471090335933309304948380597856628844787441469841499067123764789582263294904679812089984857163571087831191848630254501620929805829208334813638405421720056121989353669371336733392464416125223196943471206417375491216357008573694397305979709719726666642267431117762176403068681310351899112271339724036887000996862922546465006385288620393800504778276912835603372548255793912985251506829969107754257647488325341412132800626717094009098223529657957997803018282428490221470748111124018607613415150387569830918652780658896682362523937845272634530420418802508442363190383318384550522367992357752929106925043261446950109861088899914658551881873582528164302520939285258077969737620845637482114433988162710031703151334402309526351929588680690821355853680161000213740851154484912685841268695899174149133820578492800698255195740201818105641297250836070356851055331787840829000041552511865779453963317538532092149720526607831260281961164858098684587525129997404092797683176639914655386108937587952214971731728131517932904431121815871023518740757222100123768721944747209349312324107065080618562372526732540733324875754482967573450019321902199119960797989373383673242576103938985349278777473980508080015544764061053522202325409443567718794565430406735896491017610775948364540823486130254718476485189575836674399791508512858020607820554462991723202028222914886959399729974297471155371858924238493855858595407438104882624648788053304271463011941589896328792678327322456103852197011130466587100500083285177311776489735230926661234588873102883515626446023671996644554727608310118788389151149340939344750073025855814756190881398752357812331342279866503522725367171230756861045004548970360079569827626392344107146584895780241408158405229536937499710665594894459246286619963556350652623405339439142111271810691052290024657423604130093691889255865784668461215679554256605416005071276641766056874274200329577160643448606201239821698271723197826816628249938714995449137302051843669076723577400053932662622760323659751718925901801104290384274185507894887438832703063283279963007200698012244365116394086922220745320244624121155804354542064215121585056896157356414313068883443185280853975927734433655384188340303517822946253702015782157373265523185763554098954033236382319219892171177449469403678296185920803403867575834111518824177439145077366384071880489358256868542011645031357633355509440319236720348651010561049872726472131986543435450409131859513145181276437310438972507004981987052176272494065214619959232142314439776546708351714749367986186552791715824080651063799500184295938799158350171580759883784962257398512129810326379376218322456594236685376799113140108043139732335449090824910499143325843298821033984698141715756010829706583065211347076803680695322971990599904451209087275776225351040902392888779424630483280319132710495478599180196967835321464441189260631526618167443193550817081875477050802654025294109218264858213857526688155584113198560022135158887210365696087515063187533002942118682221893775546027227291290504292259787710667873840000616772154638441292371193521828499824350920891801685572798156421858191197490985730570332667646460728757430565372602768982373259745084479649545648030771598153955827779139373601717422996027353102768719449444917939785144631597314435351850491413941557329382048542123508173912549749819308714396615132942045919380106231421774199184060180347949887691051557905554806953878540066453375981862846419905220452803306263695626490910827627115903856995051246529996062855443838330327638599800792922846659503551211245284087516229060262011857775313747949362055496401073001348853150735487353905602908933526400713274732621960311773433943673385759124508149335736911664541281788171454023054750667136518258284898099512139193995633241336556777098003081910272040997148687418134667006094051021462690280449159646545330107754695413088714165312544813061192407821188690056027781824235022696189344352547633573536485619363254417756613981703930632872166905722259745209192917262199844409646158269456380239502837121686446561785235565164127712826918688615572716201474934052276946595712198314943381622114006936307430444173284786101777743837977037231795255434107223445512555589998646183876764903972461167959018100035098928641204195163551108763204267612979826529425882951141275841262732790798807559751851576841264742209479721843309352972665210015662514552994745127631550917636730259462132930190402837954246323258550301096706922720227074863419005438302650681214142135057154175057508639907673946335146209082888934938376439399256900604067311422093312195936202982972351163259386772241477911629572780752395056251581603133359382311500518626890530658368129988108663263271980611271548858798093487912913707498230575929091862939195014721197586067270092547718025750337730799397134539532646195269996596385654917590458333585799102012713204583903200853878881633637685182083727885131175227769609787962142372162545214591281831798216044111311671406914827170981015457781939202311563871950805024679725792497605772625913328559726371211201905720771409148645074094926718035815157571514050397610963846755569298970383547314100223802583468767350129775413279532060971154506484212185936490997917766874774481882870632315515865032898164228288232746866106592732197907162384642153489852476216789050260998045266483929542357287343977680495774091449538391575565485459058976495198513801007958010783759945775299196700547602252552034453988712538780171960718164078124847847257912407824544361682345239570689514272269750431873633263011103053423335821609333191218806608268341428910415173247216053355849993224548730778822905252324234861531520976938461042582849714963475341837562003014915703279685301868631572488401526639835689563634657435321783493199825542117308467745297085839507616458229630324424328237737450517028560698067889521768198156710781633405266759539424926280756968326107495323390536223090807081455919837355377748742029039018142937311529334644468151212945097596534306284215319445727118614900017650558177095302468875263250119705209476159416768727784472000192789137251841622857783792284439084301181121496366424659033634194540657183544771912446621259392656620306888520055599121235363718226922531781458792593750441448933981608657900876165024635197045828895481793756681046474614105142498870252139936870509372305447734112641354892806841059107716677821238332810262185587751312721179344448201440425745083063944738363793906283008973306241380614589414227694747931665717623182472168350678076487573420491557628217583972975134478990696589532548940335615613167403276472469212505759116251529654568544633498114317670257295661844775487469378464233737238981920662048511894378868224807279352022501796545343757274163910791972952950812942922205347717304184477915673991738418311710362524395716152714669005814700002633010452643547865903290733205468338872078735444762647925297690170912007874183736735087713376977683496344252419949951388315074877537433849458259765560996555954318040920178497184685497370696212088524377013853757681416632722412634423982152941645378000492507262765150789085071265997036708726692764308377229685985169122305037462744310852934305273078865283977335246017463527703205938179125396915621063637625882937571373840754406468964783100704580613446731271591194608435935825987782835266531151065041623295329047772174083559349723758552138048305090009646676088301540612824308740645594431853413755220166305812111033453120745086824339432159043594430312431227471385842030390106070940315235556172767994160020393975099897629335325855575624808996691829864222677502360193257974726742578211119734709402357457222271212526852384295874273501563660093188045493338989741571490544182559738080871565281430102670460284316819230392535297795765862414392701549740879273131051636119137577008929564823323648298263024607975875767745377160102490804624301856524161756655600160859121534556267602192689982855377872583145144082654583484409478463178777374794653580169960779405568701192328608041130904629350871827125934668712766694873899824598527786499569165464029458935064964335809824765965165142090986755203808309203230487342703468288751604071546653834619611223013759451579252696743642531927390036038608236450762698827497618723575476762889950752114804852527950845033958570838130476937881321123674281319487950228066320170022460331989671970649163741175854851878484012054844672588851401562725019821719066960812627785485964818369621410721714214986361918774754509650308957099470934337856981674465828267911940611956037845397855839240761276344105766751024307559814552786167815949657062559755074306521085301597908073343736079432866757890533483669555486803913433720156498834220893399971641479746938696905480089193067138057171505857307148815649920714086758259602876056459782423770242469805328056632787041926768467116266879463486950464507420219373945259262668613552940624781361206202636498199999498405143868285258956342264328707663299304891723400725471764188685351372332667877921738347541480022803392997357936152412755829569276837231234798989446274330454566790062032420516396282588443085438307201495672106460533238537203143242112607424485845094580494081820927639140008540422023556260218564348994145439950410980591817948882628052066441086319001688568155169229486203010738897181007709290590480749092427141018933542818429995988169660993836961644381528877214085268088757488293258735809905670755817017949161906114001908553744882726200936685604475596557476485674008177381703307380305476973609786543859382187220583902344443508867499866506040645874346005331827436296177862518081893144363251205107094690813586440519229512932450078833398788429339342435126343365204385812912834345297308652909783300671261798130316794385535726296998740359570458452230856390098913179475948752126397078375944861139451960286751210561638976008880092746115860800207803341591451797073036835196977766076373785333012024120112046988609209339085365773222392412449051532780950955866459477634482269986074813297302630975028812103517723124465095349653693090018637764094094349837313251321862080214809922685502948454661814715557444709669530177690434272031892770604717784527939160472281534379803539679861424370956683221491465438014593829277393396032754048009552231816667380357183932757077142046723838624617803976292377131209580789363841447929802588065522129262093623930637313496640186619510811583471173312025805866727639992763579078063818813069156366274125431259589936119647626101405563503399523140323113819656236327198961837254845333702062563464223952766943568376761368711962921818754576081617053031590728828700712313666308722754918661395773730546065997437810987649802414011242142773668082751390959313404155826266789510846776118665957660165998178089414985754976284387856100263796543178313634025135814161151902096499133548733131115022700681930135929595971640197196053625033558479980963488718039111612813595968565478868325856437896173159762002419621552896297904819822199462269487137462444729093456470028537694958859591606789282491054412515996300781368367490209374915732896270028656829344431342347351239298259166739503425995868970697267332582735903121288746660451461487850346142827765991608090398652575717263081833494441820193533385071292345774375579344062178711330063106003324053991693682603746176638565758877580201229366353270267100681261825172914608202541892885935244491070138206211553827793565296914576502048643282865557934707209634807372692141186895467322767751335690190153723669036865389161291688887876407525493494249733427181178892759931596719354758988097924525262363659036320070854440784544797348291802082044926670634420437555325050527522833778887040804033531923407685630109347772125639088640413101073817853338316038135280828119040832564401842053746792992622037698718018061122624490909242641985820861751177113789051609140381575003366424156095216328197122335023167422600567941281406217219641842705784328959802882335059828208196666249035857789940333152274817776952843681630088531769694783690580671064828083598046698841098135158654906933319522394363287923990534810987830274500172065433699066117784554364687723631844464768069142828004551074686645392805399409108754939166095731619715033166968309929466349142798780842257220697148875580637480308862995118473187124777291910070227588893486939456289515802965372150409603107761289831263589964893410247036036645058687287589051406841238124247386385427908282733827973326885504935874303160274749063129572349742611221517417153133618622410913869500688835898962349276317316478340077460886655598733382113829928776911495492184192087771606068472874673681886167507221017261103830671787856694812948785048943063086169948798703160515884108282351274153538513365895332948629494495061868514779105804696039069372662670386512905201137810858616188886947957607413585534585151768051973334433495230120395770739623771316030242887200537320998253008977618973129817881944671731160647231476248457551928732782825127182446807824215216469567819294098238926284943760248852279003620219386696482215628093605373178040863727268426696421929946819214908701707533361094791381804063287387593848269535583077395761447997270003472880182785281389503217986345216111066608839314053226944905455527867894417579202440021450780192099804461382547805858048442416404775031536054906591430078158372430123137511562284015838644270890718284816757527123846782459534334449622010096071051370608461801187543120725491334994247617115633321408934609156561550600317384218701570226103101916603887064661438897736318780940711527528174689576401581047016965247557740891644568677717158500583269943401677202156767724068128366565264122982439465133197359199709403275938502669557470231813203243716420586141033606524536939160050644953060161267822648942437397166717661231048975031885732165554988342121802846912529086101485527815277625623750456375769497734336846015607727035509629049392487088406281067943622418704747008368842671022558302403599841645951122485272633632645114017395248086194635840783753556885622317115520947223065437092606797351000565549381224575483728545711797393615756167641692895805257297522338558611388322171107362265816218842443178857488798109026653793426664216990914056536432249301334867988154886628665052346997235574738424830590423677143278792316422403877764330192600192284778313837632536121025336935812624086866699738275977365682227907215832478888642369346396164363308730139814211430306008730666164803678984091335926293402304324974926887831643602681011309570716141912830686577323532639653677390317661361315965553584999398600565155921936759977717933019744688148371103206503693192894521402650915465184309936553493337183425298433679915939417466223900389527673813330617747629574943868716978453767219493506590875711917720875477107189937960894774512654757501871194870738736785890200617373321075693302216320628432065671192096950585761173961632326217708945426214609858410237813215817727602222738133495410481003073275107799948991977963883530734443457532975914263768405442264784216063122769646967156473999043715903323906560726644116438605404838847161912109008701019130726071044114143241976796828547885524779476481802959736049439700479596040292746299203572099761950140348315380947714601056333446998820822120587281510729182971211917876424880354672316916541852256729234429187128163232596965413548589577133208339911288775917226115273379010341362085614577992398778325083550730199818459025958355989260553299673770491722454935329683300002230181517226575787524058832249085821280089747909326100762578770428656006996176212176845478996440705066241710213327486796237430229155358200780141165348065647488230615003392068983794766255036549822805329662862117930628430170492402301985719978948836897183043805182174419147660429752437251683435411217038631379411422095295885798060152938752753799030938871683572095760715221900279379292786303637268765822681241993384808166021603722154710143007377537792699069587121289288019052031601285861825494413353820784883465311632650407642428390870121015194231961652268422003711230464300673442064747718021353070124098860353399152667923871101706221865883573781210935179775604425634694999787251125440854522274810914874307259869602040275941178942581281882159952359658979181144077653354321757595255536158128001163846720319346507296807990793963714961774312119402021297573125165253768017359101557338153772001952444543620071848475663415407442328621060997613243487548847434539665981338717466093020535070271952983943271425371155766600025784423031073429551533945060486222764966687624079324353192992639253731076892135352572321080889819339168668278948281170472624501948409700975760920983724090074717973340788141825195842598096241747610138252643955135259311885045636264188300338539652435997416931322894719878308427600401368074703904097238473945834896186539790594118599310356168436869219485382055780395773881360679549900085123259442529724486666766834641402189915944565309423440650667851948417766779470472041958822043295380326310537494883122180391279678446100139726753892195119117836587662528083690053249004597410947068772912328214304635337283519953648274325833119144459017809607782883583730111857543659958982724531925310588115026307542571493943024453931870179923608166611305426253995833897942971602070338767815033010280120095997252222280801423571094760351925544434929986767817891045559063015953809761875920358937341978962358931125983902598310267193304189215109689156225069659119828323455503059081730735195503721665870288053992138576037035377105178021280129566841984140362872725623214428754302210909472721073474134975514190737043318276626177275996888826027225247133683353452816692779591328861381766349857728936900965749562287103024362590772412219094300871755692625758065709912016659622436080242870024547362036394841255954881727272473653467783647201918303998717627037515724649922289467932322693619177641614618795613956699567783068290316589699430767333508234990790624100202506134057344300695745474682175690441651540636584680463692621274211075399042188716127617787014258864825775223889184599523376292377915585744549477361295525952226578636462118377598473700347971408206994145580719080213590732269233100831759510659019121294795408603640757358750205890208704579670007055262505811420663907459215273309406823649441590891009220296680523325266198911311842016291631076894084723564366808182168657219688268358402785500782804043453710183651096951782335743030504852653738073531074185917705610397395062640355442275156101107261779370634723804990666922161971194259120445084641746383589938239946517395509000859479990136026674261494290066467115067175422177038774507673563742154782905911012619157555870238957001405117822646989944917908301795475876760168094100135837613578591356924455647764464178667115391951357696104864922490083446715486383054477914330097680486878348184672733758436892724310447406807685278625585165092088263813233623148733336714764520450876627614950389949504809560460989604329123358348859990294526400284994280878624039811814884767301216754161106629995553668193123287425702063738352020086863691311733469731741219153633246745325630871347302792174956227014687325867891734558379964351358800959350877556356248810493852999007675135513527792412429277488565888566513247302514710210575352516511814850902750476845518252096331899068527614435138213662152368890578786699432288816028377482035506016029894009119713850179871683633744139275973644017007014763706655703504338121113576415018451821413619823495159601064752712575935185304332875537783057509567425442684712219618709178560783936144511383335649103256405733898667178123972237519316430617013859539474367843392670986712452211189690840236327411496601243483098929941738030588417166613073040067588380432111555379440605497721705942821514886165672771240903387727745629097110134885184374118695655449745736845218066982911045058004299887953899027804383596282409421860556287788428802127553884803728640019441614257499904272009595204654170598104989967504511936471172772220436102614079750809686975176600237187748348016120310234680567112644766123747627852190241202569943534716226660893675219833111813511146503854895025120655772636145473604426859498074396932331297127377157347099713952291182653485155587137336629120242714302503763269501350911612952993785864681307226486008270881333538193703682598867893321238327053297625857382790097826460545598555131836688844628265133798491667839409761353766251798258249663458771950124384040359140849209733754642474488176184070023569580177410177696925077814893386672557898564589851056891960924398841569280696983352240225634570497312245269354193837004843183357196516626721575524193401933099018319309196582920969656247667683659647019595754739345514337413708761517323677204227385674279170698204549953095918872434939524094441678998846319845504852393662972079777452814399418256789457795712552426826089940863317371538896262889629402112108884427376568624527612130371017300785135715404533041507959447776143597437803742436646973247138410492124314138903579092416036406314038149831481905251720937103964026808994832572297954564042701757722904173234796073618787889913318305843069394825961318713816423467218730845133877219086975104942843769325024981656673816260615941768252509993741672883951744066932549653403101452225316189009235376486378482881344209870048096227171226407489571939002918573307460104360729190945767994614929290427981687729426487729952858434647775386906950148984133924540394144680263625402118614317031251117577642829914644533408920976961699098372652361768745605894704968170136974909523072082682887890730190018253425805343421705928713931737993142410852647390948284596418093614138475831136130576108462366837237695913492615824516221552134879244145041756848064120636520170386330129532777699023118648020067556905682295016354931992305914246396217025329747573114094220180199368035026495636955866425906762685687372110339156793839895765565193177883000241613539562437777840801748819373095020699900890899328088397430367736595524891300156633294077907139615464534088791510300651321934486673248275907946807879819425019582622320395131252014109960531260696555404248670549986786923021746989009547850725672978794769888831093487464426400718183160331655511534276155622405474473378049246214952133258527698847336269182649174338987824789278468918828054669982303689939783413747587025805716349413568433929396068192061773331791738208562436433635359863494496890781064019674074436583667071586924521182997893804077137501290858646578905771426833582768978554717687184427726120509266486102051535642840632368481807287940717127966820060727559555904040233178749447346454760628189541512139162918444297651066947969354016866010055196077687335396511614930937570968554559381513789569039251014953265628147011998326992200066392875374713135236421589265126204072887716578358405219646054105435443642166562244565042999010256586927279142752931172082793937751326106052881235373451068372939893580871243869385934389175713376300720319760816604464683937725806909237297523486702916910426369262090199605204121024077648190316014085863558427609537086558164273995349346546314504040199528537252004957805254656251154109252437991326262713609099402902262062836752132305065183934057450112099341464918433323646569371725914489324159006242020612885732926133596808726500045628284557574596592120530341310111827501306961509835515632004310784601906565493806542525229161991819959602752327702249855738824899882707465936355768582560518068964285376850772012220347920993936179268206590142165615925306737944568949070853263568196831861772268249911472615732035807646298116244013316737892788689229032593349861797021994981925739617673075834417098559222170171825712777534491508205278430904619460835217402005838672849709411023266953921445461066215006410674740207009189911951376466904481267253691537162290791385403937560077835153374167747942100384002308951850994548779039346122220865060160500351776264831611153325587705073541279249909859373473787081194253055121436979749914951860535920403830235716352727630874693219622190064260886183676103346002255477477813641012691906569686495012688376296907233961276287223041141813610060264044030035996988919945827397624114613744804059697062576764723766065541618574690527229238228275186799156983390747671146103022776606020061246876477728819096791613354019881402757992174167678799231603963569492851513633647219540611171767387372555728522940054361785176502307544693869307873499110352182532929726044553210797887711449898870911511237250604238753734841257086064069052058452122754533848008205302450456517669518576913200042816758054924811780519832646032445792829730129105318385636821206215531288668564956512613892261367064093953334570526986959692350353094224543865278677673027540402702246384483553239914751363441044050092330361271496081355490531539021002299595756583705381261965683144286057956696622154721695620870013727768536960840704833325132793112232507148630206951245395003735723346807094656483089209801534878705633491092366057554050864111521441481434630437273271045027768661953107858323334857840297160925215326092558932655600672124359464255065996771770388445396181632879614460817789272171836908880126778207430106422524634807454300476492885553409062185153654355474125476152769772667769772777058315801412185688011705028365275543214803488004442979998062157904564161957212784508928489806426497427090579129069217807298769477975112447305991406050629946894280931034216416629935614828130998870745292716048433630818404126469637925843094185442216359084576146078558562473814931427078266215185541603870206876980461747400808324343665382354555109449498431093494759944672673665352517662706772194183191977196378015702169933675083760057163454643671776723387588643405644871566964321041282595645349841388412890420682047007615596916843038999348366793542549210328113363184722592305554383058206941675629992013373175489122037230349072681068534454035993561823576312837767640631013125335212141994611869350833176587852047112364331226765129964171325217513553261867681942338790365468908001827135283584888444111761234101179918709236507184857856221021104009776994453121795022479578069506532965940383987369907240797679040826794007618729547835963492793904576973661643405359792219285870574957481696694062334272619733518136626063735982575552496509807260123668283605928341855848026958413772558970883789942910549800331113884603401939166122186696058491571485733568286149500019097591125218800396419762163559375743718011480559442298730418196808085647265713547612831629200449880315402105530597076666362749328308916880932359290081787411985738317192616728834918402429721290434965526942726402559641463525914348400675867690350382320572934132981593533044446496829441367323442158380761694831219333119819061096142952201536170298575105594326461468505452684975764807808009221335811378197749271768545075538328768874474591593731162470601091244609829424841287520224462594477638749491997840446829257360968534549843266536862844489365704111817793806441616531223600214918768769467398407517176307516849856359201486892943105940202457969622924566644881967576294349535326382171613395757790766370764569570259738800438415805894336137106551859987600754924187211714889295221737721146081154344982665479872580056674724051122007383459271575727715218589946948117940644466399432370044291140747218180224825837736017346685300744985564715420036123593397312914458591522887408719508708632218837288262822884631843717261903305777147651564143822306791847386039147683108141358275755853643597721650028277803713422869688787349795096031108899196143386664068450697420787700280509367203387232629637856038653216432348815557557018469089074647879122436375556668678067610544955017260791142930831285761254481944449473244819093795369008206384631678225064809531810406570254327604385703505922818919878065865412184299217273720955103242251079718077833042609086794273428955735559252723805511440438001239041687716445180226491681641927401106451622431101700056691121733189423400547959684669804298017362570406733282129962153684881404102194463424646220745575643960452985313071409084608499653767803793201899140865814662175319337665970114330608625009829566917638846056762972931464911493704624469351984039534449135141193667933301936617663652555149174982307987072280860859626112660504289296966535652516688885572112276802772743708917389639772257564890533401038855931125679991516589025016486961427207005916056166159702451989051832969278935550303934681219761582183980483960562523091462638447386296039848924386187298507775928792722068554807210497817653286210187476766897248841139560349480376727036316921007350834073865261684507482496448597428134936480372426116704266870831925040997615319076855770327421785010006441984124207396400139603601583810565928413684574119102736420274163723488214524101347716529603128408658419787951116511529827814620379139855006399960326591248525308493690313130100799977191362230866011099929142871249388541612038020411340188887219693477904497527454288072803509305828754420755134816660927879353566521255620139988249628478726214432362853676502591450468377635282587652139156480972141929675549384375582600253168536356731379262475878049445944183429172756988376226261846365452743497662411138451305481449836311789784489732076719508784158618879692955819733250699951402601511675529750575437810242238957925786562128432731202200716730574069286869363930186765958251326499145950260917069347519408975357464016830811798846452473618956056479426358070562563281189269663026479535951097127659136233180866921535788607812759910537171402204506186075374866306350591483916467656723205714516886170790984695932236724946737583099607042589220481550799132752088583781117685214269334786921895240622657921043620348852926267984013953216458791151579050460579710838983371864038024417511347226472547010794793996953554669619726763255229914654933499663234185951450360980344092212206712567698723427940708857070474293173329188523896721971353924492426178641188637790962814486917869468177591717150669111480020759432012061969637795103227089029566085562225452602610460736131368869009281721068198618553780982018471154163630326265699283424155023600978046417108525537612728905335045506135684143775854429677977014660294387687225115363801191758154028120818255606485410787933598921064427244898618961629413418001295130683638609294100083136673372153008352696235737175330738653338204842190308186449184093723944033405244909554558016406460761581010301767488475017661908692946098769201691202181688291040870709560951470416921147027413390052253340834812870353031023919699978597413908593605433599697075604460134242453682496098772581311024732798562072126572499003468293886872304895562253204463602639854225258416464324271611419817802482595563544907219226583863662663750835944314877635156145710745528016159677048442714194435183275698407552677926411261765250615965235457187956673170913319358761628255920783080185206890151504713340386100310055914817852110384754542933389188444120517943969970194112695119526564919594189975418393234647424290702718875223534393673633663200307232747037407123982562024662651974090199762452056198557625760008708173083288344381831070054514493545885422678578551915372292379555494333410174420169600090696415612732297770221217951868376359082255128816470021992348864043959153018464004714321186360622527011541122283802778538911098490201342741014121559769965438877197485376431158229838533123071751132961904559007938064276695819014842627991221792947987348901868471676503827328552059082984529806259250352128451925927986593506132961946796252373972565584157853744567558998032405492186962888490332560851455344391660226257775512916200772796852629387937530454181080729285891989715381797343496187232927614747850192611450413274873242970583408471112333746274617274626582415324271059322506255302314738759251724787322881491455915605036334575424233779160374952502493022351481961381162563911415610326844958072508273431765944054098269765269344579863479709743124498271933113863873159636361218623497261409556079920628316999420072054811525353393946076850019909886553861433495781650089961649079678142901148387645682174914075623767618453775144031475411206760160726460556859257799322070337333398916369504346690694828436629980037414527627716547623825546170883189810868806847853705536480469350958818025360529740793538676511195079373282083146268960071075175520614433784114549950136432446328193346389050936545714506900864483440180428363390513578157273973334537284263372174065775771079830517555721036795976901889958494130195999573017901240193908681356585539661941371794487632079868800371607303220547423572266896801882123424391885984168972277652194032493227314793669234004848976059037958094696041754279613782553781223947646147832926976545162290281701100437846038756544151739433960048915318817576650500951697402415644771293656614253949368884230517400129920556854289853897942669956777027089146513736892206104415481662156804219838476730871787590279209175900695273456682026513373111518000181434120962601658629821076663523361774007837783423709152644063054071807843358061072961105550020415131696373046849213356837265400307509829089364612047891114753037049893952833457824082817386441322710002968311940203323456420826473276233830294639378998375836554559919340866235090967961134004867027123176526663710778725111860354037554487418693519733656621772359229396776463251562023487570113795712096237723431370212031004965152111976013176419408203437348512852602913334915125083119802850177855710725373149139215709105130965059885999931560863655477403551898166733535880048214665099741433761182777723351910741217572841592580872591315074606025634903777263373914461377038021318347447301113032670296917335047701632106616227830027269283365584011791419447808748253360714403296252285775009808599609040936312635621328162071453406104224112083010008587264252112262480142647519426184325853386753874054743491072710049754281159466017136122590440158991600229827801796035194080046513534752698777609527839984368086908989197839693532179980139135442552717910225397010810632143048511378291498511381969143043497500189980681644412123273328307192824362406733196554692677851193152775113446468905504248113361434984604849051258345683266441528489713972376040328212660253516693914082049947320486021627759791771234751097502403078935759937715095021751693555827072533911892334070223832077585802137174778378778391015234132098489423459613692340497998279304144463162707214796117456975719681239291913740982925805561955207434243295982898980529233366415419256367380689494201471241340525072204061794355252555225008748790086568314542835167750542294803274783044056438581591952666758282929705226127628711040134801787224801789684052407924360582742467443076721645270313451354167649668901274786801010295133862698649748212118629040337691568576240699296372493097201628707200189835423690364149270236961938547372480329855045112089192879829874467864129159417531675602533435310626745254507114181483239880607297140234725520713490798398982355268723950909365667878992383712578976248755990443228895388377317348941122757071410959790047919301046740750411435381782464630795989555638991884773781341347070246747362112048986226991888517456251732519341352038115863350123913054441910073628447567514161050410973505852762044489190978901984315485280533985777844313933883994310444465669244550885946314081751220331390681596592510546858013133838152176418210433429788826119630443111388796258746090226130900849975430395771243230616906262919403921439740270894777663702488155499322458825979020631257436910946393252806241642476868495455324938017639371615636847859823715902385421265840615367228607131702674740131145261063765383390315921943469817605358380310612887852051546933639241088467632009567089718367490578163085158138161966882222047570437590614338040725853862083565176998426774523195824182683698270160237414938363496629351576854061397342746470899685618170160551104880971554859118617189668025973541705423985135560018720335079060946421271143993196046527424050882225359773481519135438571253258540493946010865793798058620143366078825219717809025817370870916460452727977153509910340736425020386386718220522879694458387652947951048660717390229327455426785669776865939923416834122274663015062155320502655341460995249356050854921756549134830958906536175693817637473644183378974229700703545206663170929607591989627732423090252397443861014263098687733913882518684316501027964911497737582888913450341148865948670215492101084328080783428089417298008983297536940644969903125399863919581601468995220880662285408414864274786281975546629278814621607171381880180840572084715868906836919393381864278454537956719272397972364651667592011057995663962598535512763558768140213409829016296873429850792471846056874828331381259161962476156902875901072733103299140623864608333378638257926302391590003557609032477281338887339178096966601469615031754226751125993315529674213336300222964906480934582008181061802100227664580400278213336758573019011371754672763059044353131319036092489097246427928455549913490005180295707082919052556781889913899625138662319380053611346224294610248954072404857123256628888931722116432947816190554868054943441034090680716088028227959686950133643814268252170472870863010137301155236861416908375675747637239763185757038109443390564564468524183028148107998376918512127201935044041804604721626939445788377090105974693219720558114078775989772072009689382249303236830515862657281114637996983137517937623215111252349734305240622105244234353732905655163406669506165892878218707756794176080712973781335187117931650033155523822487730653444179453415395202424449703410120874072188109388268167512042299404948179449472732894770111574139441228455521828424922240658752689172272780607116754046973008037039618787796694882555614674384392570115829546661358678671897661297311267200072971553613027503556167817765442287442114729881614802705243806817653573275578602505847084013208837932816008769081300492491473682517035382219619039014999523495387105997351143478292339499187936608692301375596368532373806703591144243268561512109404259582639301678017128669239283231057658851714020211196957064799814031505633045141564414623163763809904402816256917576489142569714163598439317433270237812336938043012892626375382667795034169334323607500248175741808750388475094939454896209740485442635637164995949920980884294790363666297526003243856352945844728944547166209297495496616877414120882130477022816116456044007236351581149729739218966737382647204722642221242016560150284971306332795814302516013694825567014780935790889657134926158161346901806965089556310121218491805847922720691871696316330044858020102860657858591269974637661741463934159569539554203314628026518951167938074573315759846086173702687867602943677780500244673391332431669880354073232388281847501051641331189537036488422690270478052742490603492082954755054003457160184072574536938145531175354210726557835615499874447480427323457880061873149341566046352979779455075359304795687209316724536547208381685855606043801977030764246083489876101345709394877002946175792061952549255757109038525171488525265671045349813419803390641529876343695420256080277614421914318921393908834543131769685101840103844472348948869520981943531906506555354617335814045544837884752526253949665869992058417652780125341033896469818642430034146791380619028059607854888010789705516946215228773090104467462497979992627120951684779568482583341402266477210843362437593741610536734041954738964197895425335036301861400951534766961476255651873823292468547356935802896011536791787303553159378363082248615177770541577576561759358512016692943111138863582159667618830326104164651714846979385422621687161400122378213779774131268977266712992025922017408770076956283473932201088159356286281928563571893384958850603853158179760679479840878360975960149733420572704603521790605647603285569276273495182203236144112584182426247712012035776388895974318232827871314608053533574494297621796789034568169889553518504478325616380709476951699086247100019748809205009521943632378719764870339223811540363475488626845956159755193765410115014067001226927474393888589943859730245414801061235908036274585288493563251585384383242493252666087588908318700709100237377106576985056433928854337658342596750653715005333514489908293887737352051459333049626531415141386124437935885070944688045486975358170212908490787347806814366323322819415827345671356443171537967818058195852464840084032909981943781718177302317003989733050495387356116261023999433259780126893432605584710278764901070923443884634011735556865903585244919370181041626208504299258697435817098133894045934471937493877624232409852832762266604942385129709453245586252103600829286649724174919141988966129558076770979594795306013119159011773943104209049079424448868513086844493705909026006120649425744710353547657859242708130410618546219881830090634588187038755856274911587375421064667951346487586771543838018521348281915812462599335160198935595167968932852205824799421034512715877163345222995418839680448835529753361286837225935390079201666941339091168758803988828869216002373257361588207163516271332810518187602104852180675526648673908900907195138058626735124312215691637902277328705410842037841525683288718046987952513073266340278519059417338920358540395677035611329354482585628287610610698229721420961993509331312171187891078766872044548876089410174798647137882462153955933333275562009439580434537919782280590395959927436913793778664940964048777841748336432684026282932406260081908081804390914556351936856063045089142289645219987798849347477729132797266027658401667890136490508741142126861969862044126965282981087045479861559545338021201155646979976785738920186243599326777689454060508218838227909833627167124490026761178498264377033002081844590009717235204331994708242098771514449751017055643029542821819670009202515615844174205933658148134902693111517093872260026458630561325605792560927332265579346280805683443921373688405650434307396574061017779370141424615493070741360805442100295600095663588977899267630517718781943706761498217564186590116160865408635391513039201316805769034172596453692350806417446562351523929050409479953184074862151210561833854566176652606393713658802521666223576132201941701372664966073252010771947931265282763302413805164907174565964853748354669194523580315301969160480994606814904037819829732360930087135760798621425422096419004367905479049930078372421581954535418371129368658430553842717628035279128821129308351575656599944741788438381565148434229858704245592434693295232821803508333726283791830216591836181554217157448465778420134329982594566884558266171979012180849480332448787258183774805522268151011371745368417870280274452442905474518234674919564188551244421337783521423865979925988203287085109338386829906571994614906290257427686038850511032638544540419184958866538545040571323629681069146814847869659166861842756798460041868762298055562963045953227923051616721591968675849523635298935788507746081537321454642984792310511676357749494622952569497660359473962430995343310404994209677883827002714478494069037073249106444151696053256560586778757417472110827435774315194060757983563629143326397812218946287447798119807225646714664054850131009656786314880090303749338875364183165134982546694673316118123364854397649325026179549357204305402182974871251107404011611405899911093062492312813116340549262571356721818628932786138833718028535056503591952741400869510926167541476792668032109237467087213606278332922386413619594121339278036118276324106004740971111048140003623342714514483334641675466354699731494756643423659493496845884551524150756376605086632827424794136062876041290644913828519456402643153225858624043141838669590633245063000392213192647625962691510904457695301444054618037857503036686212462278639752746667870121003392984873375014475600322100622358029343774955032037012738468163061026570300872275462966796880890587127676361066225722352229739206443093524327228100859973095132528630601105497915644791845004618046762408928925680912930592960642357021061524646205023248966593987324933967376952023991760898474571843531936646529125848064480196520162838795189499336759241485626136995945307287254532463291529110128763770605570609531377527751867923292134955245133089867969165129073841302167573238637575820080363575728002754490327953079900799442541108725693188014667935595834676432868876966610097395749967836593397846346959948950610490383647409504695226063858046758073069912290474089879166872117147527644711604401952718169508289733537148530928937046384420893299771125856840846608339934045689026787516008775461267988015465856522061210953490796707365539702576199431376639960606061106406959330828171876426043573425361756943784848495250108266488395159700490598380812105221111091943323951136051446459834210799058082093716464523127704023160072138543723461267260997870385657091998507595634613248460188409850194287687902268734556500519121546544063829253851276317663922050938345204300773017029940362615434001322763910912988327863920412300445551684054889809080779174636092439334912641164240093880746356607262336695842764583698268734815881961058571835767462009650526065929263548291499045768307210893245857073701660717398194485028842603963660746031184786225831056580870870305567595861341700745402965687634774176431051751036732869245558582082372038601781739405175130437994868822320044378043103170921034261674998000073016094814586374488778522273076330495383944345382770608760763542098445008306247630253572781032783461766970544287155315340016497076657195985041748199087201490875686037783591994719343352772947285537925787684832301101859365800717291186967617655053775030293033830706448912811412025506150896411007623824574488655182581058140345320124754723269087547507078577659732542844459353044992070014538748948226556442223696365544194225441338212225477497535494624827680533336983284156138692363443358553868471111430498248398991803165458638289353799130535222833430137953372954016257623228081138499491876144141322933767106563492528814528239506209022357876684650116660097382753660405446941653422239052108314585847035529352219928272760574821266065291385530345549744551470344939486863429459658431024190785923680224560763936784166270518555178702904073557304620639692453307795782245949710420188043000183881429008173039450507342787013124466860092778581811040911511729374873627887874907465285565434748886831064110051023020875107768918781525622735251550379532444857787277617001964853703555167655209119339343762866284619844026295252183678522367475108809781507098978413086245881522660963551401874495836926917799047120726494905737264286005211403581231076006699518536124862746756375896225299116496066876508261734178484789337295056739007878617925351440621045366250640463728815698232317500596261080921955211150859302955654967538862612972339914628358476048627627027309739202001432248707582337354915246085608210328882974183906478869923273691360048837436615223517058437705545210815513361262142911815615301758882573594892507108879262128641392443309383797333867806131795237315266773820858024701433527009243803266951742119507670884326346442749127558907746863582162166042741315170212458586056233631493164646913946562497471741958354218607748711057338458433689939645913740603382159352243594751626239188685307822821763983237306180204246560477527943104796189724299533029792497481684052893791044947004590864991872727345413508101983881864673609392571930511968645601855782450218231065889437986522432050677379966196955472440585922417953006820451795370043472451762893566770508490213107736625751697335527462302943031203596260953423574397249659211010657817826108745318874803187430823573699195156340957162700992444929749105489851519658664740148225106335367949737142510229341882585117371994499115097583746130105505064197721531929354875371191630262030328588658528480193509225875775597425276584011721342323648084027143356367542046375182552524944329657043861387865901965738802868401894087672816714137033661732650120578653915780703088714261519075001492576112927675193096728453971160213606303090542243966320674323582797889332324405779199278484633339777737655901870574806828678347965624146102899508487399692970750432753029972872297327934442988646412725348160603779707298299173029296308695801996312413304939350493325412355071054461182591141116454534710329881047844067780138077131465400099386306481266614330858206811395838319169545558259426895769841428893743467084107946318932539106963955780706021245974898293564613560788983472419979478564362042094613412387613198865352358312996862268948608408456655606876954501274486631405054735351746873009806322780468912246821460806727627708402402266155485024008952891657117617439020337584877842911289623247059191874691042005848326140677333751027195653994697162517248312230633919328707983800748485726516123434933273356664473358556430235280883924348278760886164943289399166399210488307847777048045728491456303353265070029588906265915498509407972767567129795010098229476228961891591441520032283878773485130979081019129267227103778898053964156362364169154985768408398468861684375407065121039062506128107663799047908879674778069738473170475253442156390387201238806323688037017949308954900776331523063548374256816653361606641980030188287123767481898330246836371488309259283375902278942588060087286038859168849730693948020511221766359138251524278670094406942355120201568377778851824670025651708509249623747726813694284350062938814429987905301056217375459182679973217735029368928065210025396268807498092643458011655715886700443503976505323478287327368840863540002740676783821963522226539290939807367391364082898722017776747168118195856133721583119054682936083236976113450281757830202934845982925000895682630271263295866292147653142233351793093387951357095346377183684092444422096319331295620305575517340067973740614162107923633423805646850092037167152642556371853889571416419772387422610596667396997173168169415435095283193556417705668622215217991151355639707143312893657553844648326201206424338016955862698561022460646069330793847858814367407000599769703649019273328826135329363112403650698652160638987250267238087403396744397830258296894256896741864336134979475245526291426522842419243083388103580053787023999542172113686550275341362211693140694669513186928102574795985605145005021715913317751609957865551981886193211282110709442287240442481153406055895958355815232012184605820563592699303478851132068626627588771446035996656108430725696500563064489187599466596772847171539573612108180841547273142661748933134174632662354222072600146012701206934639520564445543291662986660783089068118790090815295063626782075614388815781351134695366303878412092346942868730839320432333872775496805210302821544324723388845215343727250128589747691460808314404125868181540049187772287869801853454537006526655649170915429522756709222217474112062720656622989806032891672068743654948246108697367225547404812889242471854323605753411672850757552057131156697954584887398742228135887985840783135060548290551482785294891121905383195624228719484759407859398047901094194070671764439032730712135887385049993638838205501683402777496070276844880281912220636888636811043569529300652195528261526991271637277388418993287130563464688227398288763198645709836308917786487086676185485680047672552675414742851028145807403152992197814557756843681110185317498167016426647884090262682824448258027532094549915104518517716546311804904567985713257528117913656278158111288816562285876030875974963849435275676612168959261485030785362045274507752950631012480341804584059432926079854435620093708091821523920371790678121992280496069738238743312626730306795943960954957189577217915597300588693646845576676092450906088202212235719254536715191834872587423919410890444115959932760044506556206461164655665487594247369252336955993030355095817626176231849561906494839673002037763874369343999829430209147073618947932692762445186560239559053705128978163455423320114975994896278424327483788032701418676952621180975006405149755889650293004867605208010491537885413909424531691719987628941277221129464568294860281493181560249677887949813777216229359437811004448060797672429276249510784153446429150842764520002042769470698041775832209097020291657347251582904630910359037842977572651720877244740952267166306005469716387943171196873484688738186656751279298575016363411314627530499019135646823804329970695770150789337728658035712790913767420805655493624646
diff --git a/libgo/go/compress/zlib/reader.go b/libgo/go/compress/zlib/reader.go
index f38ef5a885e..d54746f4c02 100644
--- a/libgo/go/compress/zlib/reader.go
+++ b/libgo/go/compress/zlib/reader.go
@@ -11,7 +11,7 @@ and compress during writing. For example, to write compressed data
to a buffer:
var b bytes.Buffer
- w, err := zlib.NewWriter(&b)
+ w := zlib.NewWriter(&b)
w.Write([]byte("hello, world\n"))
w.Close()
diff --git a/libgo/go/container/heap/heap.go b/libgo/go/container/heap/heap.go
index 67018e6baea..bbaf40a989d 100644
--- a/libgo/go/container/heap/heap.go
+++ b/libgo/go/container/heap/heap.go
@@ -79,7 +79,7 @@ func Remove(h Interface, i int) interface{} {
func up(h Interface, j int) {
for {
i := (j - 1) / 2 // parent
- if i == j || h.Less(i, j) {
+ if i == j || !h.Less(j, i) {
break
}
h.Swap(i, j)
@@ -97,7 +97,7 @@ func down(h Interface, i, n int) {
if j2 := j1 + 1; j2 < n && !h.Less(j1, j2) {
j = j2 // = 2*i + 2 // right child
}
- if h.Less(i, j) {
+ if !h.Less(j, i) {
break
}
h.Swap(i, j)
diff --git a/libgo/go/container/heap/heap_test.go b/libgo/go/container/heap/heap_test.go
index cb31ef6d30a..73f33e8d2cf 100644
--- a/libgo/go/container/heap/heap_test.go
+++ b/libgo/go/container/heap/heap_test.go
@@ -170,3 +170,16 @@ func TestRemove2(t *testing.T) {
}
}
}
+
+func BenchmarkDup(b *testing.B) {
+ const n = 10000
+ h := make(myHeap, n)
+ for i := 0; i < b.N; i++ {
+ for j := 0; j < n; j++ {
+ Push(&h, 0) // all elements are the same
+ }
+ for h.Len() > 0 {
+ Pop(&h)
+ }
+ }
+}
diff --git a/libgo/go/container/list/list.go b/libgo/go/container/list/list.go
index a3fd4b39f32..e29e3a79ac7 100755
--- a/libgo/go/container/list/list.go
+++ b/libgo/go/container/list/list.go
@@ -11,201 +11,185 @@
//
package list
-// Element is an element in the linked list.
+// Element is an element of a linked list.
type Element struct {
// Next and previous pointers in the doubly-linked list of elements.
- // The front of the list has prev = nil, and the back has next = nil.
+ // To simplify the implementation, internally a list l is implemented
+ // as a ring, such that &l.root is both the next element of the last
+ // list element (l.Back()) and the previous element of the first list
+ // element (l.Front()).
next, prev *Element
// The list to which this element belongs.
list *List
- // The contents of this list element.
+ // The value stored with this element.
Value interface{}
}
// Next returns the next list element or nil.
-func (e *Element) Next() *Element { return e.next }
+func (e *Element) Next() *Element {
+ if p := e.next; p != &e.list.root {
+ return p
+ }
+ return nil
+}
// Prev returns the previous list element or nil.
-func (e *Element) Prev() *Element { return e.prev }
+func (e *Element) Prev() *Element {
+ if p := e.prev; p != &e.list.root {
+ return p
+ }
+ return nil
+}
// List represents a doubly linked list.
// The zero value for List is an empty list ready to use.
type List struct {
- front, back *Element
- len int
+ root Element // sentinel list element, only &root, root.prev, and root.next are used
+ len int // current list length excluding (this) sentinel element
}
-// Init initializes or clears a List.
+// Init initializes or clears list l.
func (l *List) Init() *List {
- l.front = nil
- l.back = nil
+ l.root.next = &l.root
+ l.root.prev = &l.root
l.len = 0
return l
}
// New returns an initialized list.
-func New() *List { return new(List) }
-
-// Front returns the first element in the list.
-func (l *List) Front() *Element { return l.front }
+func New() *List { return new(List).Init() }
-// Back returns the last element in the list.
-func (l *List) Back() *Element { return l.back }
+// Len returns the number of elements of list l.
+func (l *List) Len() int { return l.len }
-// Remove removes the element from the list
-// and returns its Value.
-func (l *List) Remove(e *Element) interface{} {
- l.remove(e)
- e.list = nil // do what remove does not
- return e.Value
+// Front returns the first element of list l or nil
+func (l *List) Front() *Element {
+ if l.len == 0 {
+ return nil
+ }
+ return l.root.next
}
-// remove the element from the list, but do not clear the Element's list field.
-// This is so that other List methods may use remove when relocating Elements
-// without needing to restore the list field.
-func (l *List) remove(e *Element) {
- if e.list != l {
- return
- }
- if e.prev == nil {
- l.front = e.next
- } else {
- e.prev.next = e.next
- }
- if e.next == nil {
- l.back = e.prev
- } else {
- e.next.prev = e.prev
+// Back returns the last element of list l or nil.
+func (l *List) Back() *Element {
+ if l.len == 0 {
+ return nil
}
-
- e.prev = nil
- e.next = nil
- l.len--
+ return l.root.prev
}
-func (l *List) insertBefore(e *Element, mark *Element) {
- if mark.prev == nil {
- // new front of the list
- l.front = e
- } else {
- mark.prev.next = e
+// lazyInit lazily initializes a zero List value.
+func (l *List) lazyInit() {
+ if l.root.next == nil {
+ l.Init()
}
- e.prev = mark.prev
- mark.prev = e
- e.next = mark
- l.len++
}
-func (l *List) insertAfter(e *Element, mark *Element) {
- if mark.next == nil {
- // new back of the list
- l.back = e
- } else {
- mark.next.prev = e
- }
- e.next = mark.next
- mark.next = e
- e.prev = mark
+// insert inserts e after at, increments l.len, and returns e.
+func (l *List) insert(e, at *Element) *Element {
+ n := at.next
+ at.next = e
+ e.prev = at
+ e.next = n
+ n.prev = e
+ e.list = l
l.len++
+ return e
}
-func (l *List) insertFront(e *Element) {
- if l.front == nil {
- // empty list
- l.front, l.back = e, e
- e.prev, e.next = nil, nil
- l.len = 1
- return
- }
- l.insertBefore(e, l.front)
+// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
+func (l *List) insertValue(v interface{}, at *Element) *Element {
+ return l.insert(&Element{Value: v}, at)
}
-func (l *List) insertBack(e *Element) {
- if l.back == nil {
- // empty list
- l.front, l.back = e, e
- e.prev, e.next = nil, nil
- l.len = 1
- return
+// remove removes e from its list, decrements l.len, and returns e.
+func (l *List) remove(e *Element) *Element {
+ e.prev.next = e.next
+ e.next.prev = e.prev
+ e.list = nil
+ l.len--
+ return e
+}
+
+// Remove removes e from l if e is an element of list l.
+// It returns the element value e.Value.
+func (l *List) Remove(e *Element) interface{} {
+ if e.list == l {
+ // if e.list == l, l must have been initialized when e was inserted
+ // in l or l == nil (e is a zero Element) and l.remove will crash
+ l.remove(e)
}
- l.insertAfter(e, l.back)
+ return e.Value
}
-// PushFront inserts the value at the front of the list and returns a new Element containing the value.
-func (l *List) PushFront(value interface{}) *Element {
- e := &Element{nil, nil, l, value}
- l.insertFront(e)
- return e
+// Pushfront inserts a new element e with value v at the front of list l and returns e.
+func (l *List) PushFront(v interface{}) *Element {
+ l.lazyInit()
+ return l.insertValue(v, &l.root)
}
-// PushBack inserts the value at the back of the list and returns a new Element containing the value.
-func (l *List) PushBack(value interface{}) *Element {
- e := &Element{nil, nil, l, value}
- l.insertBack(e)
- return e
+// PushBack inserts a new element e with value v at the back of list l and returns e.
+func (l *List) PushBack(v interface{}) *Element {
+ l.lazyInit()
+ return l.insertValue(v, l.root.prev)
}
-// InsertBefore inserts the value immediately before mark and returns a new Element containing the value.
-func (l *List) InsertBefore(value interface{}, mark *Element) *Element {
+// InsertBefore inserts a new element e with value v immediately before mark and returns e.
+// If mark is not an element of l, the list is not modified.
+func (l *List) InsertBefore(v interface{}, mark *Element) *Element {
if mark.list != l {
return nil
}
- e := &Element{nil, nil, l, value}
- l.insertBefore(e, mark)
- return e
+ // see comment in List.Remove about initialization of l
+ return l.insertValue(v, mark.prev)
}
-// InsertAfter inserts the value immediately after mark and returns a new Element containing the value.
-func (l *List) InsertAfter(value interface{}, mark *Element) *Element {
+// InsertAfter inserts a new element e with value v immediately after mark and returns e.
+// If mark is not an element of l, the list is not modified.
+func (l *List) InsertAfter(v interface{}, mark *Element) *Element {
if mark.list != l {
return nil
}
- e := &Element{nil, nil, l, value}
- l.insertAfter(e, mark)
- return e
+ // see comment in List.Remove about initialization of l
+ return l.insertValue(v, mark)
}
-// MoveToFront moves the element to the front of the list.
+// MoveToFront moves element e to the front of list l.
+// If e is not an element of l, the list is not modified.
func (l *List) MoveToFront(e *Element) {
- if e.list != l || l.front == e {
+ if e.list != l || l.root.next == e {
return
}
- l.remove(e)
- l.insertFront(e)
+ // see comment in List.Remove about initialization of l
+ l.insert(l.remove(e), &l.root)
}
-// MoveToBack moves the element to the back of the list.
+// MoveToBack moves element e to the back of list l.
+// If e is not an element of l, the list is not modified.
func (l *List) MoveToBack(e *Element) {
- if e.list != l || l.back == e {
+ if e.list != l || l.root.prev == e {
return
}
- l.remove(e)
- l.insertBack(e)
+ // see comment in List.Remove about initialization of l
+ l.insert(l.remove(e), l.root.prev)
}
-// Len returns the number of elements in the list.
-func (l *List) Len() int { return l.len }
-
-// PushBackList inserts each element of ol at the back of the list.
-func (l *List) PushBackList(ol *List) {
- last := ol.Back()
- for e := ol.Front(); e != nil; e = e.Next() {
- l.PushBack(e.Value)
- if e == last {
- break
- }
+// PuchBackList inserts a copy of an other list at the back of list l.
+// The lists l and other may be the same.
+func (l *List) PushBackList(other *List) {
+ l.lazyInit()
+ for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
+ l.insertValue(e.Value, l.root.prev)
}
}
-// PushFrontList inserts each element of ol at the front of the list. The ordering of the passed list is preserved.
-func (l *List) PushFrontList(ol *List) {
- first := ol.Front()
- for e := ol.Back(); e != nil; e = e.Prev() {
- l.PushFront(e.Value)
- if e == first {
- break
- }
+// PushFrontList inserts a copy of an other list at the front of list l.
+// The lists l and other may be the same.
+func (l *List) PushFrontList(other *List) {
+ l.lazyInit()
+ for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
+ l.insertValue(e.Value, &l.root)
}
}
diff --git a/libgo/go/container/list/list_test.go b/libgo/go/container/list/list_test.go
index 1d44ff84e4a..b4fc77d1403 100755
--- a/libgo/go/container/list/list_test.go
+++ b/libgo/go/container/list/list_test.go
@@ -4,65 +4,75 @@
package list
-import (
- "testing"
-)
+import "testing"
+
+func checkListLen(t *testing.T, l *List, len int) bool {
+ if n := l.Len(); n != len {
+ t.Errorf("l.Len() = %d, want %d", n, len)
+ return false
+ }
+ return true
+}
func checkListPointers(t *testing.T, l *List, es []*Element) {
- if len(es) == 0 {
- if l.front != nil || l.back != nil {
- t.Errorf("l.front/l.back = %v/%v should be nil/nil", l.front, l.back)
- }
+ root := &l.root
+
+ if !checkListLen(t, l, len(es)) {
return
}
- if l.front != es[0] {
- t.Errorf("l.front = %v, want %v", l.front, es[0])
- }
- if last := es[len(es)-1]; l.back != last {
- t.Errorf("l.back = %v, want %v", l.back, last)
+ // zero length lists must be the zero value or properly initialized (sentinel circle)
+ if len(es) == 0 {
+ if l.root.next != nil && l.root.next != root || l.root.prev != nil && l.root.prev != root {
+ t.Errorf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p", l.root.next, l.root.prev, root)
+ }
+ return
}
+ // len(es) > 0
+ // check internal and external prev/next connections
for i, e := range es {
- var e_prev, e_next *Element = nil, nil
+ prev := root
+ Prev := (*Element)(nil)
if i > 0 {
- e_prev = es[i-1]
+ prev = es[i-1]
+ Prev = prev
+ }
+ if p := e.prev; p != prev {
+ t.Errorf("elt[%d](%p).prev = %p, want %p", i, e, p, prev)
+ }
+ if p := e.Prev(); p != Prev {
+ t.Errorf("elt[%d](%p).Prev() = %p, want %p", i, e, p, Prev)
}
+
+ next := root
+ Next := (*Element)(nil)
if i < len(es)-1 {
- e_next = es[i+1]
+ next = es[i+1]
+ Next = next
}
- if e.prev != e_prev {
- t.Errorf("elt #%d (%v) has prev=%v, want %v", i, e, e.prev, e_prev)
+ if n := e.next; n != next {
+ t.Errorf("elt[%d](%p).next = %p, want %p", i, e, n, next)
}
- if e.next != e_next {
- t.Errorf("elt #%d (%v) has next=%v, want %v", i, e, e.next, e_next)
+ if n := e.Next(); n != Next {
+ t.Errorf("elt[%d](%p).Next() = %p, want %p", i, e, n, Next)
}
}
}
-func checkListLen(t *testing.T, l *List, n int) {
- if an := l.Len(); an != n {
- t.Errorf("l.Len() = %d, want %d", an, n)
- }
-}
-
func TestList(t *testing.T) {
l := New()
checkListPointers(t, l, []*Element{})
- checkListLen(t, l, 0)
// Single element list
e := l.PushFront("a")
- checkListLen(t, l, 1)
checkListPointers(t, l, []*Element{e})
l.MoveToFront(e)
checkListPointers(t, l, []*Element{e})
l.MoveToBack(e)
checkListPointers(t, l, []*Element{e})
- checkListLen(t, l, 1)
l.Remove(e)
checkListPointers(t, l, []*Element{})
- checkListLen(t, l, 0)
// Bigger list
e2 := l.PushFront(2)
@@ -70,11 +80,9 @@ func TestList(t *testing.T) {
e3 := l.PushBack(3)
e4 := l.PushBack("banana")
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
- checkListLen(t, l, 4)
l.Remove(e2)
checkListPointers(t, l, []*Element{e1, e3, e4})
- checkListLen(t, l, 3)
l.MoveToFront(e3) // move from middle
checkListPointers(t, l, []*Element{e3, e1, e4})
@@ -121,7 +129,7 @@ func TestList(t *testing.T) {
}
}
if sum != 4 {
- t.Errorf("sum over l.Iter() = %d, want 4", sum)
+ t.Errorf("sum over l = %d, want 4", sum)
}
// Clear all elements by iterating
@@ -131,19 +139,18 @@ func TestList(t *testing.T) {
l.Remove(e)
}
checkListPointers(t, l, []*Element{})
- checkListLen(t, l, 0)
}
func checkList(t *testing.T, l *List, es []interface{}) {
- if l.Len() != len(es) {
- t.Errorf("list has len=%v, want %v", l.Len(), len(es))
+ if !checkListLen(t, l, len(es)) {
return
}
+
i := 0
for e := l.Front(); e != nil; e = e.Next() {
le := e.Value.(int)
if le != es[i] {
- t.Errorf("elt #%d has value=%v, want %v", i, le, es[i])
+ t.Errorf("elt[%d].Value = %v, want %v", i, le, es[i])
}
i++
}
@@ -202,8 +209,27 @@ func TestRemove(t *testing.T) {
e := l.Front()
l.Remove(e)
checkListPointers(t, l, []*Element{e2})
- checkListLen(t, l, 1)
l.Remove(e)
checkListPointers(t, l, []*Element{e2})
- checkListLen(t, l, 1)
+}
+
+func TestIssue4103(t *testing.T) {
+ l1 := New()
+ l1.PushBack(1)
+ l1.PushBack(2)
+
+ l2 := New()
+ l2.PushBack(3)
+ l2.PushBack(4)
+
+ e := l1.Front()
+ l2.Remove(e) // l2 should not change because e is not an element of l2
+ if n := l2.Len(); n != 2 {
+ t.Errorf("l2.Len() = %d, want 2", n)
+ }
+
+ l1.InsertBefore(8, e)
+ if n := l1.Len(); n != 3 {
+ t.Errorf("l1.Len() = %d, want 3", n)
+ }
}
diff --git a/libgo/go/crypto/aes/aes_test.go b/libgo/go/crypto/aes/aes_test.go
index e500c666d97..6261dd09fb5 100644
--- a/libgo/go/crypto/aes/aes_test.go
+++ b/libgo/go/crypto/aes/aes_test.go
@@ -221,7 +221,10 @@ L:
if tt.dec != nil {
dec = make([]uint32, len(tt.dec))
}
- expandKey(tt.key, enc, dec)
+ // This test could only test Go version of expandKey because asm
+ // version might use different memory layout for expanded keys
+ // This is OK because we don't expose expanded keys to the outside
+ expandKeyGo(tt.key, enc, dec)
for j, v := range enc {
if v != tt.enc[j] {
t.Errorf("key %d: enc[%d] = %#x, want %#x", i, j, v, tt.enc[j])
@@ -352,15 +355,39 @@ func TestCipherDecrypt(t *testing.T) {
}
func BenchmarkEncrypt(b *testing.B) {
- b.StopTimer()
tt := encryptTests[0]
c, err := NewCipher(tt.key)
if err != nil {
b.Fatal("NewCipher:", err)
}
out := make([]byte, len(tt.in))
- b.StartTimer()
+ b.SetBytes(int64(len(out)))
+ b.ResetTimer()
for i := 0; i < b.N; i++ {
c.Encrypt(out, tt.in)
}
}
+
+func BenchmarkDecrypt(b *testing.B) {
+ tt := encryptTests[0]
+ c, err := NewCipher(tt.key)
+ if err != nil {
+ b.Fatal("NewCipher:", err)
+ }
+ out := make([]byte, len(tt.out))
+ b.SetBytes(int64(len(out)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ c.Decrypt(out, tt.out)
+ }
+}
+
+func BenchmarkExpand(b *testing.B) {
+ tt := encryptTests[0]
+ n := len(tt.key) + 28
+ c := &aesCipher{make([]uint32, n), make([]uint32, n)}
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ expandKey(tt.key, c.enc, c.dec)
+ }
+}
diff --git a/libgo/go/crypto/aes/block.go b/libgo/go/crypto/aes/block.go
index b930787cec7..57a7e9e25f2 100644
--- a/libgo/go/crypto/aes/block.go
+++ b/libgo/go/crypto/aes/block.go
@@ -37,7 +37,7 @@
package aes
// Encrypt one block from src into dst, using the expanded key xk.
-func encryptBlock(xk []uint32, dst, src []byte) {
+func encryptBlockGo(xk []uint32, dst, src []byte) {
var s0, s1, s2, s3, t0, t1, t2, t3 uint32
s0 = uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
@@ -82,7 +82,7 @@ func encryptBlock(xk []uint32, dst, src []byte) {
}
// Decrypt one block from src into dst, using the expanded key xk.
-func decryptBlock(xk []uint32, dst, src []byte) {
+func decryptBlockGo(xk []uint32, dst, src []byte) {
var s0, s1, s2, s3, t0, t1, t2, t3 uint32
s0 = uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
@@ -139,7 +139,7 @@ func rotw(w uint32) uint32 { return w<<8 | w>>24 }
// Key expansion algorithm. See FIPS-197, Figure 11.
// Their rcon[i] is our powx[i-1] << 24.
-func expandKey(key []byte, enc, dec []uint32) {
+func expandKeyGo(key []byte, enc, dec []uint32) {
// Encryption key setup.
var i int
nk := len(key) / 4
diff --git a/libgo/go/crypto/aes/cipher.go b/libgo/go/crypto/aes/cipher.go
index 7d307c93a0b..d931134a70e 100644
--- a/libgo/go/crypto/aes/cipher.go
+++ b/libgo/go/crypto/aes/cipher.go
@@ -45,6 +45,10 @@ func NewCipher(key []byte) (cipher.Block, error) {
func (c *aesCipher) BlockSize() int { return BlockSize }
-func (c *aesCipher) Encrypt(dst, src []byte) { encryptBlock(c.enc, dst, src) }
+func (c *aesCipher) Encrypt(dst, src []byte) {
+ encryptBlock(c.enc, dst, src)
+}
-func (c *aesCipher) Decrypt(dst, src []byte) { decryptBlock(c.dec, dst, src) }
+func (c *aesCipher) Decrypt(dst, src []byte) {
+ decryptBlock(c.dec, dst, src)
+}
diff --git a/libgo/go/crypto/aes/cipher_asm.go b/libgo/go/crypto/aes/cipher_asm.go
new file mode 100644
index 00000000000..21369fc382c
--- /dev/null
+++ b/libgo/go/crypto/aes/cipher_asm.go
@@ -0,0 +1,46 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64
+
+package aes
+
+// defined in asm_$GOARCH.s
+func hasAsm() bool
+func encryptBlockAsm(nr int, xk *uint32, dst, src *byte)
+func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
+func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32)
+
+var useAsm = hasAsm()
+
+func encryptBlock(xk []uint32, dst, src []byte) {
+ if useAsm {
+ encryptBlockAsm(len(xk)/4-1, &xk[0], &dst[0], &src[0])
+ } else {
+ encryptBlockGo(xk, dst, src)
+ }
+}
+func decryptBlock(xk []uint32, dst, src []byte) {
+ if useAsm {
+ decryptBlockAsm(len(xk)/4-1, &xk[0], &dst[0], &src[0])
+ } else {
+ decryptBlockGo(xk, dst, src)
+ }
+}
+func expandKey(key []byte, enc, dec []uint32) {
+ if useAsm {
+ rounds := 10
+ switch len(key) {
+ case 128 / 8:
+ rounds = 10
+ case 192 / 8:
+ rounds = 12
+ case 256 / 8:
+ rounds = 14
+ }
+ expandKeyAsm(rounds, &key[0], &enc[0], &dec[0])
+ } else {
+ expandKeyGo(key, enc, dec)
+ }
+}
diff --git a/libgo/go/crypto/aes/cipher_generic.go b/libgo/go/crypto/aes/cipher_generic.go
new file mode 100644
index 00000000000..1714e0f1e5c
--- /dev/null
+++ b/libgo/go/crypto/aes/cipher_generic.go
@@ -0,0 +1,19 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64
+
+package aes
+
+func encryptBlock(xk []uint32, dst, src []byte) {
+ encryptBlockGo(xk, dst, src)
+}
+
+func decryptBlock(xk []uint32, dst, src []byte) {
+ decryptBlockGo(xk, dst, src)
+}
+
+func expandKey(key []byte, enc, dec []uint32) {
+ expandKeyGo(key, enc, dec)
+}
diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go
index 8508e3b4f8d..512d20c635c 100644
--- a/libgo/go/crypto/ecdsa/ecdsa.go
+++ b/libgo/go/crypto/ecdsa/ecdsa.go
@@ -140,14 +140,16 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
w := new(big.Int).ModInverse(s, N)
u1 := e.Mul(e, w)
+ u1.Mod(u1, N)
u2 := w.Mul(r, w)
+ u2.Mod(u2, N)
x1, y1 := c.ScalarBaseMult(u1.Bytes())
x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes())
- if x1.Cmp(x2) == 0 {
+ x, y := c.Add(x1, y1, x2, y2)
+ if x.Sign() == 0 && y.Sign() == 0 {
return false
}
- x, _ := c.Add(x1, y1, x2, y2)
x.Mod(x, N)
return x.Cmp(r) == 0
}
diff --git a/libgo/go/crypto/ecdsa/ecdsa_test.go b/libgo/go/crypto/ecdsa/ecdsa_test.go
index 3a2b3efbab3..0c064319324 100644
--- a/libgo/go/crypto/ecdsa/ecdsa_test.go
+++ b/libgo/go/crypto/ecdsa/ecdsa_test.go
@@ -5,11 +5,19 @@
package ecdsa
import (
+ "bufio"
+ "compress/bzip2"
"crypto/elliptic"
"crypto/rand"
"crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
"encoding/hex"
+ "hash"
+ "io"
"math/big"
+ "os"
+ "strings"
"testing"
)
@@ -72,156 +80,112 @@ func fromHex(s string) *big.Int {
return r
}
-// These test vectors were taken from
-// http://csrc.nist.gov/groups/STM/cavp/documents/dss/ecdsatestvectors.zip
-var testVectors = []struct {
- msg string
- Qx, Qy string
- r, s string
- ok bool
-}{
- {
- "09626b45493672e48f3d1226a3aff3201960e577d33a7f72c7eb055302db8fe8ed61685dd036b554942a5737cd1512cdf811ee0c00e6dd2f08c69f08643be396e85dafda664801e772cdb7396868ac47b172245b41986aa2648cb77fbbfa562581be06651355a0c4b090f9d17d8f0ab6cced4e0c9d386cf465a516630f0231bd",
- "9504b5b82d97a264d8b3735e0568decabc4b6ca275bc53cbadfc1c40",
- "03426f80e477603b10dee670939623e3da91a94267fc4e51726009ed",
- "81d3ac609f9575d742028dd496450a58a60eea2dcf8b9842994916e1",
- "96a8c5f382c992e8f30ccce9af120b067ec1d74678fa8445232f75a5",
- false,
- },
- {
- "96b2b6536f6df29be8567a72528aceeaccbaa66c66c534f3868ca9778b02faadb182e4ed34662e73b9d52ecbe9dc8e875fc05033c493108b380689ebf47e5b062e6a0cdb3dd34ce5fe347d92768d72f7b9b377c20aea927043b509c078ed2467d7113405d2ddd458811e6faf41c403a2a239240180f1430a6f4330df5d77de37",
- "851e3100368a22478a0029353045ae40d1d8202ef4d6533cfdddafd8",
- "205302ac69457dd345e86465afa72ee8c74ca97e2b0b999aec1f10c2",
- "4450c2d38b697e990721aa2dbb56578d32b4f5aeb3b9072baa955ee0",
- "e26d4b589166f7b4ba4b1c8fce823fa47aad22f8c9c396b8c6526e12",
- false,
- },
- {
- "86778dbb4a068a01047a8d245d632f636c11d2ad350740b36fad90428b454ad0f120cb558d12ea5c8a23db595d87543d06d1ef489263d01ee529871eb68737efdb8ff85bc7787b61514bed85b7e01d6be209e0a4eb0db5c8df58a5c5bf706d76cb2bdf7800208639e05b89517155d11688236e6a47ed37d8e5a2b1e0adea338e",
- "ad5bda09d319a717c1721acd6688d17020b31b47eef1edea57ceeffc",
- "c8ce98e181770a7c9418c73c63d01494b8b80a41098c5ea50692c984",
- "de5558c257ab4134e52c19d8db3b224a1899cbd08cc508ce8721d5e9",
- "745db7af5a477e5046705c0a5eff1f52cb94a79d481f0c5a5e108ecd",
- true,
- },
- {
- "4bc6ef1958556686dab1e39c3700054a304cbd8f5928603dcd97fafd1f29e69394679b638f71c9344ce6a535d104803d22119f57b5f9477e253817a52afa9bfbc9811d6cc8c8be6b6566c6ef48b439bbb532abe30627548c598867f3861ba0b154dc1c3deca06eb28df8efd28258554b5179883a36fbb1eecf4f93ee19d41e3d",
- "cc5eea2edf964018bdc0504a3793e4d2145142caa09a72ac5fb8d3e8",
- "a48d78ae5d08aa725342773975a00d4219cf7a8029bb8cf3c17c374a",
- "67b861344b4e416d4094472faf4272f6d54a497177fbc5f9ef292836",
- "1d54f3fcdad795bf3b23408ecbac3e1321d1d66f2e4e3d05f41f7020",
- false,
- },
- {
- "bb658732acbf3147729959eb7318a2058308b2739ec58907dd5b11cfa3ecf69a1752b7b7d806fe00ec402d18f96039f0b78dbb90a59c4414fb33f1f4e02e4089de4122cd93df5263a95be4d7084e2126493892816e6a5b4ed123cb705bf930c8f67af0fb4514d5769232a9b008a803af225160ce63f675bd4872c4c97b146e5e",
- "6234c936e27bf141fc7534bfc0a7eedc657f91308203f1dcbd642855",
- "27983d87ca785ef4892c3591ef4a944b1deb125dd58bd351034a6f84",
- "e94e05b42d01d0b965ffdd6c3a97a36a771e8ea71003de76c4ecb13f",
- "1dc6464ffeefbd7872a081a5926e9fc3e66d123f1784340ba17737e9",
- false,
- },
- {
- "7c00be9123bfa2c4290be1d8bc2942c7f897d9a5b7917e3aabd97ef1aab890f148400a89abd554d19bec9d8ed911ce57b22fbcf6d30ca2115f13ce0a3f569a23bad39ee645f624c49c60dcfc11e7d2be24de9c905596d8f23624d63dc46591d1f740e46f982bfae453f107e80db23545782be23ce43708245896fc54e1ee5c43",
- "9f3f037282aaf14d4772edffff331bbdda845c3f65780498cde334f1",
- "8308ee5a16e3bcb721b6bc30000a0419bc1aaedd761be7f658334066",
- "6381d7804a8808e3c17901e4d283b89449096a8fba993388fa11dc54",
- "8e858f6b5b253686a86b757bad23658cda53115ac565abca4e3d9f57",
- false,
- },
- {
- "cffc122a44840dc705bb37130069921be313d8bde0b66201aebc48add028ca131914ef2e705d6bedd19dc6cf9459bbb0f27cdfe3c50483808ffcdaffbeaa5f062e097180f07a40ef4ab6ed03fe07ed6bcfb8afeb42c97eafa2e8a8df469de07317c5e1494c41547478eff4d8c7d9f0f484ad90fedf6e1c35ee68fa73f1691601",
- "a03b88a10d930002c7b17ca6af2fd3e88fa000edf787dc594f8d4fd4",
- "e0cf7acd6ddc758e64847fe4df9915ebda2f67cdd5ec979aa57421f5",
- "387b84dcf37dc343c7d2c5beb82f0bf8bd894b395a7b894565d296c1",
- "4adc12ce7d20a89ce3925e10491c731b15ddb3f339610857a21b53b4",
- false,
- },
- {
- "26e0e0cafd85b43d16255908ccfd1f061c680df75aba3081246b337495783052ba06c60f4a486c1591a4048bae11b4d7fec4f161d80bdc9a7b79d23e44433ed625eab280521a37f23dd3e1bdc5c6a6cfaa026f3c45cf703e76dab57add93fe844dd4cda67dc3bddd01f9152579e49df60969b10f09ce9372fdd806b0c7301866",
- "9a8983c42f2b5a87c37a00458b5970320d247f0c8a88536440173f7d",
- "15e489ec6355351361900299088cfe8359f04fe0cab78dde952be80c",
- "929a21baa173d438ec9f28d6a585a2f9abcfc0a4300898668e476dc0",
- "59a853f046da8318de77ff43f26fe95a92ee296fa3f7e56ce086c872",
- true,
- },
- {
- "1078eac124f48ae4f807e946971d0de3db3748dd349b14cca5c942560fb25401b2252744f18ad5e455d2d97ed5ae745f55ff509c6c8e64606afe17809affa855c4c4cdcaf6b69ab4846aa5624ed0687541aee6f2224d929685736c6a23906d974d3c257abce1a3fb8db5951b89ecb0cda92b5207d93f6618fd0f893c32cf6a6e",
- "d6e55820bb62c2be97650302d59d667a411956138306bd566e5c3c2b",
- "631ab0d64eaf28a71b9cbd27a7a88682a2167cee6251c44e3810894f",
- "65af72bc7721eb71c2298a0eb4eed3cec96a737cc49125706308b129",
- "bd5a987c78e2d51598dbd9c34a9035b0069c580edefdacee17ad892a",
- false,
- },
- {
- "919deb1fdd831c23481dfdb2475dcbe325b04c34f82561ced3d2df0b3d749b36e255c4928973769d46de8b95f162b53cd666cad9ae145e7fcfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82130761231f536e6a3d59792f784902c469aa897aabf9a0678f93446610d56d5e0981e4c8a563556b",
- "269b455b1024eb92d860a420f143ac1286b8cce43031562ae7664574",
- "baeb6ca274a77c44a0247e5eb12ca72bdd9a698b3f3ae69c9f1aaa57",
- "cb4ec2160f04613eb0dfe4608486091a25eb12aa4dec1afe91cfb008",
- "40b01d8cd06589481574f958b98ca08ade9d2a8fe31024375c01bb40",
- false,
- },
- {
- "6e012361250dacf6166d2dd1aa7be544c3206a9d43464b3fcd90f3f8cf48d08ec099b59ba6fe7d9bdcfaf244120aed1695d8be32d1b1cd6f143982ab945d635fb48a7c76831c0460851a3d62b7209c30cd9c2abdbe3d2a5282a9fcde1a6f418dd23c409bc351896b9b34d7d3a1a63bbaf3d677e612d4a80fa14829386a64b33f",
- "6d2d695efc6b43b13c14111f2109608f1020e3e03b5e21cfdbc82fcd",
- "26a4859296b7e360b69cf40be7bd97ceaffa3d07743c8489fc47ca1b",
- "9a8cb5f2fdc288b7183c5b32d8e546fc2ed1ca4285eeae00c8b572ad",
- "8c623f357b5d0057b10cdb1a1593dab57cda7bdec9cf868157a79b97",
- true,
- },
- {
- "bf6bd7356a52b234fe24d25557200971fc803836f6fec3cade9642b13a8e7af10ab48b749de76aada9d8927f9b12f75a2c383ca7358e2566c4bb4f156fce1fd4e87ef8c8d2b6b1bdd351460feb22cdca0437ac10ca5e0abbbce9834483af20e4835386f8b1c96daaa41554ceee56730aac04f23a5c765812efa746051f396566",
- "14250131b2599939cf2d6bc491be80ddfe7ad9de644387ee67de2d40",
- "b5dc473b5d014cd504022043c475d3f93c319a8bdcb7262d9e741803",
- "4f21642f2201278a95339a80f75cc91f8321fcb3c9462562f6cbf145",
- "452a5f816ea1f75dee4fd514fa91a0d6a43622981966c59a1b371ff8",
- false,
- },
- {
- "0eb7f4032f90f0bd3cf9473d6d9525d264d14c031a10acd31a053443ed5fe919d5ac35e0be77813071b4062f0b5fdf58ad5f637b76b0b305aec18f82441b6e607b44cdf6e0e3c7c57f24e6fd565e39430af4a6b1d979821ed0175fa03e3125506847654d7e1ae904ce1190ae38dc5919e257bdac2db142a6e7cd4da6c2e83770",
- "d1f342b7790a1667370a1840255ac5bbbdc66f0bc00ae977d99260ac",
- "76416cabae2de9a1000b4646338b774baabfa3db4673790771220cdb",
- "bc85e3fc143d19a7271b2f9e1c04b86146073f3fab4dda1c3b1f35ca",
- "9a5c70ede3c48d5f43307a0c2a4871934424a3303b815df4bb0f128e",
- false,
- },
- {
- "5cc25348a05d85e56d4b03cec450128727bc537c66ec3a9fb613c151033b5e86878632249cba83adcefc6c1e35dcd31702929c3b57871cda5c18d1cf8f9650a25b917efaed56032e43b6fc398509f0d2997306d8f26675f3a8683b79ce17128e006aa0903b39eeb2f1001be65de0520115e6f919de902b32c38d691a69c58c92",
- "7e49a7abf16a792e4c7bbc4d251820a2abd22d9f2fc252a7bf59c9a6",
- "44236a8fb4791c228c26637c28ae59503a2f450d4cfb0dc42aa843b9",
- "084461b4050285a1a85b2113be76a17878d849e6bc489f4d84f15cd8",
- "079b5bddcc4d45de8dbdfd39f69817c7e5afa454a894d03ee1eaaac3",
- false,
- },
- {
- "1951533ce33afb58935e39e363d8497a8dd0442018fd96dff167b3b23d7206a3ee182a3194765df4768a3284e23b8696c199b4686e670d60c9d782f08794a4bccc05cffffbd1a12acd9eb1cfa01f7ebe124da66ecff4599ea7720c3be4bb7285daa1a86ebf53b042bd23208d468c1b3aa87381f8e1ad63e2b4c2ba5efcf05845",
- "31945d12ebaf4d81f02be2b1768ed80784bf35cf5e2ff53438c11493",
- "a62bebffac987e3b9d3ec451eb64c462cdf7b4aa0b1bbb131ceaa0a4",
- "bc3c32b19e42b710bca5c6aaa128564da3ddb2726b25f33603d2af3c",
- "ed1a719cc0c507edc5239d76fe50e2306c145ad252bd481da04180c0",
- false,
- },
-}
-
func TestVectors(t *testing.T) {
- sha := sha1.New()
+ // This test runs the full set of NIST test vectors from
+ // http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip
+ //
+ // The SigVer.rsp file has been edited to remove test vectors for
+ // unsupported algorithms and has been compressed.
+
+ if testing.Short() {
+ return
+ }
+
+ f, err := os.Open("testdata/SigVer.rsp.bz2")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ buf := bufio.NewReader(bzip2.NewReader(f))
+
+ lineNo := 1
+ var h hash.Hash
+ var msg []byte
+ var hashed []byte
+ var r, s *big.Int
+ pub := new(PublicKey)
- for i, test := range testVectors {
- pub := PublicKey{
- Curve: elliptic.P224(),
- X: fromHex(test.Qx),
- Y: fromHex(test.Qy),
+ for {
+ line, err := buf.ReadString('\n')
+ if len(line) == 0 {
+ if err == io.EOF {
+ break
+ }
+ t.Fatalf("error reading from input: %s", err)
}
- msg, _ := hex.DecodeString(test.msg)
- sha.Reset()
- sha.Write(msg)
- hashed := sha.Sum(nil)
- r := fromHex(test.r)
- s := fromHex(test.s)
- if Verify(&pub, hashed, r, s) != test.ok {
- t.Errorf("%d: bad result", i)
+ lineNo++
+ // Need to remove \r\n from the end of the line.
+ if !strings.HasSuffix(line, "\r\n") {
+ t.Fatalf("bad line ending (expected \\r\\n) on line %d", lineNo)
}
- if testing.Short() {
- break
+ line = line[:len(line)-2]
+
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+
+ if line[0] == '[' {
+ line = line[1 : len(line)-1]
+ parts := strings.SplitN(line, ",", 2)
+
+ switch parts[0] {
+ case "P-224":
+ pub.Curve = elliptic.P224()
+ case "P-256":
+ pub.Curve = elliptic.P256()
+ case "P-384":
+ pub.Curve = elliptic.P384()
+ case "P-521":
+ pub.Curve = elliptic.P521()
+ default:
+ pub.Curve = nil
+ }
+
+ switch parts[1] {
+ case "SHA-1":
+ h = sha1.New()
+ case "SHA-224":
+ h = sha256.New224()
+ case "SHA-256":
+ h = sha256.New()
+ case "SHA-384":
+ h = sha512.New384()
+ case "SHA-512":
+ h = sha512.New()
+ default:
+ h = nil
+ }
+
+ continue
+ }
+
+ if h == nil || pub.Curve == nil {
+ continue
+ }
+
+ switch {
+ case strings.HasPrefix(line, "Msg = "):
+ if msg, err = hex.DecodeString(line[6:]); err != nil {
+ t.Fatalf("failed to decode message on line %d: %s", lineNo, err)
+ }
+ case strings.HasPrefix(line, "Qx = "):
+ pub.X = fromHex(line[5:])
+ case strings.HasPrefix(line, "Qy = "):
+ pub.Y = fromHex(line[5:])
+ case strings.HasPrefix(line, "R = "):
+ r = fromHex(line[4:])
+ case strings.HasPrefix(line, "S = "):
+ s = fromHex(line[4:])
+ case strings.HasPrefix(line, "Result = "):
+ expected := line[9] == 'P'
+ h.Reset()
+ h.Write(msg)
+ hashed := h.Sum(hashed[:0])
+ if Verify(pub, hashed, r, s) != expected {
+ t.Fatalf("incorrect result on line %d", lineNo)
+ }
+ default:
+ t.Fatalf("unknown variable on line %d: %s", lineNo, line)
}
}
}
diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go
index a3990891be3..7a4ff6614c1 100644
--- a/libgo/go/crypto/elliptic/elliptic.go
+++ b/libgo/go/crypto/elliptic/elliptic.go
@@ -31,10 +31,10 @@ type Curve interface {
// Double returns 2*(x,y)
Double(x1, y1 *big.Int) (x, y *big.Int)
// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
- ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int)
- // ScalarBaseMult returns k*G, where G is the base point of the group and k
- // is an integer in big-endian form.
- ScalarBaseMult(scalar []byte) (x, y *big.Int)
+ ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int)
+ // ScalarBaseMult returns k*G, where G is the base point of the group
+ // and k is an integer in big-endian form.
+ ScalarBaseMult(k []byte) (x, y *big.Int)
}
// CurveParams contains the parameters of an elliptic curve and also provides
@@ -69,9 +69,24 @@ func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
return x3.Cmp(y2) == 0
}
+// zForAffine returns a Jacobian Z value for the affine point (x, y). If x and
+// y are zero, it assumes that they represent the point at infinity because (0,
+// 0) is not on the any of the curves handled here.
+func zForAffine(x, y *big.Int) *big.Int {
+ z := new(big.Int)
+ if x.Sign() != 0 || y.Sign() != 0 {
+ z.SetInt64(1)
+ }
+ return z
+}
+
// affineFromJacobian reverses the Jacobian transform. See the comment at the
-// top of the file.
+// top of the file. If the point is ∞ it returns 0, 0.
func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
+ if z.Sign() == 0 {
+ return new(big.Int), new(big.Int)
+ }
+
zinv := new(big.Int).ModInverse(z, curve.P)
zinvsq := new(big.Int).Mul(zinv, zinv)
@@ -84,14 +99,29 @@ func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.
}
func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
- z := new(big.Int).SetInt64(1)
- return curve.affineFromJacobian(curve.addJacobian(x1, y1, z, x2, y2, z))
+ z1 := zForAffine(x1, y1)
+ z2 := zForAffine(x2, y2)
+ return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2))
}
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
// (x2, y2, z2) and returns their sum, also in Jacobian form.
func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
+ x3, y3, z3 := new(big.Int), new(big.Int), new(big.Int)
+ if z1.Sign() == 0 {
+ x3.Set(x2)
+ y3.Set(y2)
+ z3.Set(z2)
+ return x3, y3, z3
+ }
+ if z2.Sign() == 0 {
+ x3.Set(x1)
+ y3.Set(y1)
+ z3.Set(z1)
+ return x3, y3, z3
+ }
+
z1z1 := new(big.Int).Mul(z1, z1)
z1z1.Mod(z1z1, curve.P)
z2z2 := new(big.Int).Mul(z2, z2)
@@ -102,6 +132,7 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
u2 := new(big.Int).Mul(x2, z1z1)
u2.Mod(u2, curve.P)
h := new(big.Int).Sub(u2, u1)
+ xEqual := h.Sign() == 0
if h.Sign() == -1 {
h.Add(h, curve.P)
}
@@ -119,17 +150,21 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
if r.Sign() == -1 {
r.Add(r, curve.P)
}
+ yEqual := r.Sign() == 0
+ if xEqual && yEqual {
+ return curve.doubleJacobian(x1, y1, z1)
+ }
r.Lsh(r, 1)
v := new(big.Int).Mul(u1, i)
- x3 := new(big.Int).Set(r)
+ x3.Set(r)
x3.Mul(x3, x3)
x3.Sub(x3, j)
x3.Sub(x3, v)
x3.Sub(x3, v)
x3.Mod(x3, curve.P)
- y3 := new(big.Int).Set(r)
+ y3.Set(r)
v.Sub(v, x3)
y3.Mul(y3, v)
s1.Mul(s1, j)
@@ -137,16 +172,10 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
y3.Sub(y3, s1)
y3.Mod(y3, curve.P)
- z3 := new(big.Int).Add(z1, z2)
+ z3.Add(z1, z2)
z3.Mul(z3, z3)
z3.Sub(z3, z1z1)
- if z3.Sign() == -1 {
- z3.Add(z3, curve.P)
- }
z3.Sub(z3, z2z2)
- if z3.Sign() == -1 {
- z3.Add(z3, curve.P)
- }
z3.Mul(z3, h)
z3.Mod(z3, curve.P)
@@ -154,7 +183,7 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
}
func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
- z1 := new(big.Int).SetInt64(1)
+ z1 := zForAffine(x1, y1)
return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1))
}
@@ -219,40 +248,19 @@ func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
}
func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
- // We have a slight problem in that the identity of the group (the
- // point at infinity) cannot be represented in (x, y) form on a finite
- // machine. Thus the standard add/double algorithm has to be tweaked
- // slightly: our initial state is not the identity, but x, and we
- // ignore the first true bit in |k|. If we don't find any true bits in
- // |k|, then we return nil, nil, because we cannot return the identity
- // element.
-
Bz := new(big.Int).SetInt64(1)
- x := Bx
- y := By
- z := Bz
+ x, y, z := new(big.Int), new(big.Int), new(big.Int)
- seenFirstTrue := false
for _, byte := range k {
for bitNum := 0; bitNum < 8; bitNum++ {
- if seenFirstTrue {
- x, y, z = curve.doubleJacobian(x, y, z)
- }
+ x, y, z = curve.doubleJacobian(x, y, z)
if byte&0x80 == 0x80 {
- if !seenFirstTrue {
- seenFirstTrue = true
- } else {
- x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z)
- }
+ x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z)
}
byte <<= 1
}
}
- if !seenFirstTrue {
- return nil, nil
- }
-
return curve.affineFromJacobian(x, y, z)
}
diff --git a/libgo/go/crypto/elliptic/elliptic_test.go b/libgo/go/crypto/elliptic/elliptic_test.go
index 1e3407ee0e7..58f903966ce 100644
--- a/libgo/go/crypto/elliptic/elliptic_test.go
+++ b/libgo/go/crypto/elliptic/elliptic_test.go
@@ -322,6 +322,44 @@ func TestGenericBaseMult(t *testing.T) {
}
}
+func TestInfinity(t *testing.T) {
+ tests := []struct {
+ name string
+ curve Curve
+ }{
+ {"p224", P224()},
+ {"p256", P256()},
+ }
+
+ for _, test := range tests {
+ curve := test.curve
+ x, y := curve.ScalarBaseMult(nil)
+ if x.Sign() != 0 || y.Sign() != 0 {
+ t.Errorf("%s: x^0 != ∞", test.name)
+ }
+ x.SetInt64(0)
+ y.SetInt64(0)
+
+ x2, y2 := curve.Double(x, y)
+ if x2.Sign() != 0 || y2.Sign() != 0 {
+ t.Errorf("%s: 2∞ != ∞", test.name)
+ }
+
+ baseX := curve.Params().Gx
+ baseY := curve.Params().Gy
+
+ x3, y3 := curve.Add(baseX, baseY, x, y)
+ if x3.Cmp(baseX) != 0 || y3.Cmp(baseY) != 0 {
+ t.Errorf("%s: x+∞ != x", test.name)
+ }
+
+ x4, y4 := curve.Add(x, y, baseX, baseY)
+ if x4.Cmp(baseX) != 0 || y4.Cmp(baseY) != 0 {
+ t.Errorf("%s: ∞+x != x", test.name)
+ }
+ }
+}
+
func BenchmarkBaseMult(b *testing.B) {
b.ResetTimer()
p224 := P224()
diff --git a/libgo/go/crypto/elliptic/p224.go b/libgo/go/crypto/elliptic/p224.go
index 17571c25288..1f7ff3f9da6 100644
--- a/libgo/go/crypto/elliptic/p224.go
+++ b/libgo/go/crypto/elliptic/p224.go
@@ -80,10 +80,14 @@ func (p224Curve) Add(bigX1, bigY1, bigX2, bigY2 *big.Int) (x, y *big.Int) {
p224FromBig(&x1, bigX1)
p224FromBig(&y1, bigY1)
- z1[0] = 1
+ if bigX1.Sign() != 0 || bigY1.Sign() != 0 {
+ z1[0] = 1
+ }
p224FromBig(&x2, bigX2)
p224FromBig(&y2, bigY2)
- z2[0] = 1
+ if bigX2.Sign() != 0 || bigY2.Sign() != 0 {
+ z2[0] = 1
+ }
p224AddJacobian(&x3, &y3, &z3, &x1, &y1, &z1, &x2, &y2, &z2)
return p224ToAffine(&x3, &y3, &z3)
@@ -132,6 +136,44 @@ func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
// exactly, making the reflections during a reduce much nicer.
type p224FieldElement [8]uint32
+// p224P is the order of the field, represented as a p224FieldElement.
+var p224P = [8]uint32{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
+
+// p224IsZero returns 1 if a == 0 mod p and 0 otherwise.
+//
+// a[i] < 2**29
+func p224IsZero(a *p224FieldElement) uint32 {
+ // Since a p224FieldElement contains 224 bits there are two possible
+ // representations of 0: 0 and p.
+ var minimal p224FieldElement
+ p224Contract(&minimal, a)
+
+ var isZero, isP uint32
+ for i, v := range minimal {
+ isZero |= v
+ isP |= v - p224P[i]
+ }
+
+ // If either isZero or isP is 0, then we should return 1.
+ isZero |= isZero >> 16
+ isZero |= isZero >> 8
+ isZero |= isZero >> 4
+ isZero |= isZero >> 2
+ isZero |= isZero >> 1
+
+ isP |= isP >> 16
+ isP |= isP >> 8
+ isP |= isP >> 4
+ isP |= isP >> 2
+ isP |= isP >> 1
+
+ // For isZero and isP, the LSB is 0 iff all the bits are zero.
+ result := isZero & isP
+ result = (^result) & 1
+
+ return result
+}
+
// p224Add computes *out = a+b
//
// a[i] + b[i] < 2**32
@@ -406,7 +448,7 @@ func p224Contract(out, in *p224FieldElement) {
// true.
top4AllOnes := uint32(0xffffffff)
for i := 4; i < 8; i++ {
- top4AllOnes &= (out[i] & bottom28Bits) - 1
+ top4AllOnes &= out[i]
}
top4AllOnes |= 0xf0000000
// Now we replicate any zero bits to all the bits in top4AllOnes.
@@ -441,7 +483,7 @@ func p224Contract(out, in *p224FieldElement) {
out3Equal = ^uint32(int32(out3Equal<<31) >> 31)
// If out[3] > 0xffff000 then n's MSB will be zero.
- out3GT := ^uint32(int32(n<<31) >> 31)
+ out3GT := ^uint32(int32(n) >> 31)
mask := top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT)
out[0] -= 1 & mask
@@ -463,6 +505,9 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement
var c p224LargeFieldElement
+ z1IsZero := p224IsZero(z1)
+ z2IsZero := p224IsZero(z2)
+
// Z1Z1 = Z1²
p224Square(&z1z1, z1, &c)
// Z2Z2 = Z2²
@@ -480,6 +525,7 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
// H = U2-U1
p224Sub(&h, &u2, &u1)
p224Reduce(&h)
+ xEqual := p224IsZero(&h)
// I = (2*H)²
for j := 0; j < 8; j++ {
i[j] = h[j] << 1
@@ -491,6 +537,11 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
// r = 2*(S2-S1)
p224Sub(&r, &s2, &s1)
p224Reduce(&r)
+ yEqual := p224IsZero(&r)
+ if xEqual == 1 && yEqual == 1 && z1IsZero == 0 && z2IsZero == 0 {
+ p224DoubleJacobian(x3, y3, z3, x1, y1, z1)
+ return
+ }
for i := 0; i < 8; i++ {
r[i] <<= 1
}
@@ -524,6 +575,13 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
p224Mul(&z1z1, &z1z1, &r, &c)
p224Sub(y3, &z1z1, &s1)
p224Reduce(y3)
+
+ p224CopyConditional(x3, x2, z1IsZero)
+ p224CopyConditional(x3, x1, z2IsZero)
+ p224CopyConditional(y3, y2, z1IsZero)
+ p224CopyConditional(y3, y1, z2IsZero)
+ p224CopyConditional(z3, z2, z1IsZero)
+ p224CopyConditional(z3, z1, z2IsZero)
}
// p224DoubleJacobian computes *out = a+a.
@@ -593,22 +651,19 @@ func p224CopyConditional(out, in *p224FieldElement, control uint32) {
func p224ScalarMult(outX, outY, outZ, inX, inY, inZ *p224FieldElement, scalar []byte) {
var xx, yy, zz p224FieldElement
for i := 0; i < 8; i++ {
+ outX[i] = 0
+ outY[i] = 0
outZ[i] = 0
}
- firstBit := uint32(1)
for _, byte := range scalar {
for bitNum := uint(0); bitNum < 8; bitNum++ {
p224DoubleJacobian(outX, outY, outZ, outX, outY, outZ)
bit := uint32((byte >> (7 - bitNum)) & 1)
p224AddJacobian(&xx, &yy, &zz, inX, inY, inZ, outX, outY, outZ)
- p224CopyConditional(outX, inX, firstBit&bit)
- p224CopyConditional(outY, inY, firstBit&bit)
- p224CopyConditional(outZ, inZ, firstBit&bit)
- p224CopyConditional(outX, &xx, ^firstBit&bit)
- p224CopyConditional(outY, &yy, ^firstBit&bit)
- p224CopyConditional(outZ, &zz, ^firstBit&bit)
- firstBit = firstBit & ^bit
+ p224CopyConditional(outX, &xx, bit)
+ p224CopyConditional(outY, &yy, bit)
+ p224CopyConditional(outZ, &zz, bit)
}
}
}
@@ -618,16 +673,8 @@ func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) {
var zinv, zinvsq, outx, outy p224FieldElement
var tmp p224LargeFieldElement
- isPointAtInfinity := true
- for i := 0; i < 8; i++ {
- if z[i] != 0 {
- isPointAtInfinity = false
- break
- }
- }
-
- if isPointAtInfinity {
- return nil, nil
+ if isPointAtInfinity := p224IsZero(z); isPointAtInfinity == 1 {
+ return new(big.Int), new(big.Int)
}
p224Invert(&zinv, z)
diff --git a/libgo/go/crypto/md5/gen.go b/libgo/go/crypto/md5/gen.go
new file mode 100644
index 00000000000..1a9c4ab33dd
--- /dev/null
+++ b/libgo/go/crypto/md5/gen.go
@@ -0,0 +1,298 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// This program generates md5block.go
+// Invoke as
+//
+// go run gen.go [-full] |gofmt >md5block.go
+//
+// The -full flag causes the generated code to do a full
+// (16x) unrolling instead of a 4x unrolling.
+
+package main
+
+import (
+ "flag"
+ "log"
+ "os"
+ "strings"
+ "text/template"
+)
+
+func main() {
+ flag.Parse()
+
+ t := template.Must(template.New("main").Funcs(funcs).Parse(program))
+ if err := t.Execute(os.Stdout, data); err != nil {
+ log.Fatal(err)
+ }
+}
+
+type Data struct {
+ a, b, c, d string
+ Shift1 []int
+ Shift2 []int
+ Shift3 []int
+ Shift4 []int
+ Table1 []uint32
+ Table2 []uint32
+ Table3 []uint32
+ Table4 []uint32
+ Full bool
+}
+
+var funcs = template.FuncMap{
+ "dup": dup,
+ "relabel": relabel,
+ "rotate": rotate,
+}
+
+func dup(count int, x []int) []int {
+ var out []int
+ for i := 0; i < count; i++ {
+ out = append(out, x...)
+ }
+ return out
+}
+
+func relabel(s string) string {
+ return strings.NewReplacer("a", data.a, "b", data.b, "c", data.c, "d", data.d).Replace(s)
+}
+
+func rotate() string {
+ data.a, data.b, data.c, data.d = data.d, data.a, data.b, data.c
+ return "" // no output
+}
+
+func init() {
+ flag.BoolVar(&data.Full, "full", false, "complete unrolling")
+}
+
+var data = Data{
+ a: "a",
+ b: "b",
+ c: "c",
+ d: "d",
+ Shift1: []int{7, 12, 17, 22},
+ Shift2: []int{5, 9, 14, 20},
+ Shift3: []int{4, 11, 16, 23},
+ Shift4: []int{6, 10, 15, 21},
+
+ // table[i] = int((1<<32) * abs(sin(i+1 radians))).
+ Table1: []uint32{
+ // round 1
+ 0xd76aa478,
+ 0xe8c7b756,
+ 0x242070db,
+ 0xc1bdceee,
+ 0xf57c0faf,
+ 0x4787c62a,
+ 0xa8304613,
+ 0xfd469501,
+ 0x698098d8,
+ 0x8b44f7af,
+ 0xffff5bb1,
+ 0x895cd7be,
+ 0x6b901122,
+ 0xfd987193,
+ 0xa679438e,
+ 0x49b40821,
+ },
+ Table2: []uint32{
+ // round 2
+ 0xf61e2562,
+ 0xc040b340,
+ 0x265e5a51,
+ 0xe9b6c7aa,
+ 0xd62f105d,
+ 0x2441453,
+ 0xd8a1e681,
+ 0xe7d3fbc8,
+ 0x21e1cde6,
+ 0xc33707d6,
+ 0xf4d50d87,
+ 0x455a14ed,
+ 0xa9e3e905,
+ 0xfcefa3f8,
+ 0x676f02d9,
+ 0x8d2a4c8a,
+ },
+ Table3: []uint32{
+ // round3
+ 0xfffa3942,
+ 0x8771f681,
+ 0x6d9d6122,
+ 0xfde5380c,
+ 0xa4beea44,
+ 0x4bdecfa9,
+ 0xf6bb4b60,
+ 0xbebfbc70,
+ 0x289b7ec6,
+ 0xeaa127fa,
+ 0xd4ef3085,
+ 0x4881d05,
+ 0xd9d4d039,
+ 0xe6db99e5,
+ 0x1fa27cf8,
+ 0xc4ac5665,
+ },
+ Table4: []uint32{
+ // round 4
+ 0xf4292244,
+ 0x432aff97,
+ 0xab9423a7,
+ 0xfc93a039,
+ 0x655b59c3,
+ 0x8f0ccc92,
+ 0xffeff47d,
+ 0x85845dd1,
+ 0x6fa87e4f,
+ 0xfe2ce6e0,
+ 0xa3014314,
+ 0x4e0811a1,
+ 0xf7537e82,
+ 0xbd3af235,
+ 0x2ad7d2bb,
+ 0xeb86d391,
+ },
+}
+
+var program = `
+package md5
+
+import (
+ "unsafe"
+ "runtime"
+)
+
+{{if not .Full}}
+ var t1 = [...]uint32{
+ {{range .Table1}}{{printf "\t%#x,\n" .}}{{end}}
+ }
+
+ var t2 = [...]uint32{
+ {{range .Table2}}{{printf "\t%#x,\n" .}}{{end}}
+ }
+
+ var t3 = [...]uint32{
+ {{range .Table3}}{{printf "\t%#x,\n" .}}{{end}}
+ }
+
+ var t4 = [...]uint32{
+ {{range .Table4}}{{printf "\t%#x,\n" .}}{{end}}
+ }
+{{end}}
+
+func block(dig *digest, p []byte) {
+ a := dig.s[0]
+ b := dig.s[1]
+ c := dig.s[2]
+ d := dig.s[3]
+ var X *[16]uint32
+ var xbuf [16]uint32
+ for len(p) >= chunk {
+ aa, bb, cc, dd := a, b, c, d
+
+ // This is a constant condition - it is not evaluated on each iteration.
+ if runtime.GOARCH == "amd64" || runtime.GOARCH == "386" {
+ // MD5 was designed so that x86 processors can just iterate
+ // over the block data directly as uint32s, and we generate
+ // less code and run 1.3x faster if we take advantage of that.
+ // My apologies.
+ X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+ } else {
+ X = &xbuf
+ j := 0
+ for i := 0; i < 16; i++ {
+ X[i&15] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+ j += 4
+ }
+ }
+
+ {{if .Full}}
+ // Round 1.
+ {{range $i, $s := dup 4 .Shift1}}
+ {{index $.Table1 $i | printf "a += (((c^d)&b)^d) + X[%d] + %d" $i | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ {{rotate}}
+ {{end}}
+
+ // Round 2.
+ {{range $i, $s := dup 4 .Shift2}}
+ {{index $.Table2 $i | printf "a += (((b^c)&d)^c) + X[(1+5*%d)&15] + %d" $i | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ {{rotate}}
+ {{end}}
+
+ // Round 3.
+ {{range $i, $s := dup 4 .Shift3}}
+ {{index $.Table3 $i | printf "a += (b^c^d) + X[(5+3*%d)&15] + %d" $i | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ {{rotate}}
+ {{end}}
+
+ // Round 4.
+ {{range $i, $s := dup 4 .Shift4}}
+ {{index $.Table4 $i | printf "a += (c^(b|^d)) + X[(7*%d)&15] + %d" $i | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ {{rotate}}
+ {{end}}
+ {{else}}
+ // Round 1.
+ for i := uint(0); i < 16; {
+ {{range $s := .Shift1}}
+ {{printf "a += (((c^d)&b)^d) + X[i&15] + t1[i&15]" | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ i++
+ {{rotate}}
+ {{end}}
+ }
+
+ // Round 2.
+ for i := uint(0); i < 16; {
+ {{range $s := .Shift2}}
+ {{printf "a += (((b^c)&d)^c) + X[(1+5*i)&15] + t2[i&15]" | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ i++
+ {{rotate}}
+ {{end}}
+ }
+
+ // Round 3.
+ for i := uint(0); i < 16; {
+ {{range $s := .Shift3}}
+ {{printf "a += (b^c^d) + X[(5+3*i)&15] + t3[i&15]" | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ i++
+ {{rotate}}
+ {{end}}
+ }
+
+ // Round 4.
+ for i := uint(0); i < 16; {
+ {{range $s := .Shift4}}
+ {{printf "a += (c^(b|^d)) + X[(7*i)&15] + t4[i&15]" | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ i++
+ {{rotate}}
+ {{end}}
+ }
+ {{end}}
+
+ a += aa
+ b += bb
+ c += cc
+ d += dd
+
+ p = p[chunk:]
+ }
+
+ dig.s[0] = a
+ dig.s[1] = b
+ dig.s[2] = c
+ dig.s[3] = d
+}
+`
diff --git a/libgo/go/crypto/md5/md5.go b/libgo/go/crypto/md5/md5.go
index cfb728c9441..825e5c8a282 100644
--- a/libgo/go/crypto/md5/md5.go
+++ b/libgo/go/crypto/md5/md5.go
@@ -21,26 +21,26 @@ const Size = 16
const BlockSize = 64
const (
- _Chunk = 64
- _Init0 = 0x67452301
- _Init1 = 0xEFCDAB89
- _Init2 = 0x98BADCFE
- _Init3 = 0x10325476
+ chunk = 64
+ init0 = 0x67452301
+ init1 = 0xEFCDAB89
+ init2 = 0x98BADCFE
+ init3 = 0x10325476
)
// digest represents the partial evaluation of a checksum.
type digest struct {
s [4]uint32
- x [_Chunk]byte
+ x [chunk]byte
nx int
len uint64
}
func (d *digest) Reset() {
- d.s[0] = _Init0
- d.s[1] = _Init1
- d.s[2] = _Init2
- d.s[3] = _Init3
+ d.s[0] = init0
+ d.s[1] = init1
+ d.s[2] = init2
+ d.s[3] = init3
d.nx = 0
d.len = 0
}
@@ -61,21 +61,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
d.len += uint64(nn)
if d.nx > 0 {
n := len(p)
- if n > _Chunk-d.nx {
- n = _Chunk - d.nx
+ if n > chunk-d.nx {
+ n = chunk - d.nx
}
for i := 0; i < n; i++ {
d.x[d.nx+i] = p[i]
}
d.nx += n
- if d.nx == _Chunk {
- _Block(d, d.x[0:])
+ if d.nx == chunk {
+ block(d, d.x[0:chunk])
d.nx = 0
}
p = p[n:]
}
- n := _Block(d, p)
- p = p[n:]
+ if len(p) >= chunk {
+ n := len(p) &^ (chunk - 1)
+ block(d, p[:n])
+ p = p[n:]
+ }
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
diff --git a/libgo/go/crypto/md5/md5_test.go b/libgo/go/crypto/md5/md5_test.go
index aae875464f9..b474a90d5a3 100644
--- a/libgo/go/crypto/md5/md5_test.go
+++ b/libgo/go/crypto/md5/md5_test.go
@@ -78,3 +78,28 @@ func ExampleNew() {
fmt.Printf("%x", h.Sum(nil))
// Output: e2c569be17396eca2a2e3c11578123ed
}
+
+var bench = md5.New()
+var buf = makeBuf()
+
+func makeBuf() []byte {
+ b := make([]byte, 8<<10)
+ for i := range b {
+ b[i] = byte(i)
+ }
+ return b
+}
+
+func BenchmarkHash1K(b *testing.B) {
+ b.SetBytes(1024)
+ for i := 0; i < b.N; i++ {
+ bench.Write(buf[:1024])
+ }
+}
+
+func BenchmarkHash8K(b *testing.B) {
+ b.SetBytes(int64(len(buf)))
+ for i := 0; i < b.N; i++ {
+ bench.Write(buf)
+ }
+}
diff --git a/libgo/go/crypto/md5/md5block.go b/libgo/go/crypto/md5/md5block.go
index a887e2e05ed..5dbdf5606b1 100644
--- a/libgo/go/crypto/md5/md5block.go
+++ b/libgo/go/crypto/md5/md5block.go
@@ -1,172 +1,246 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// MD5 block step.
-// In its own file so that a faster assembly or C version
-// can be substituted easily.
-
package md5
-// table[i] = int((1<<32) * abs(sin(i+1 radians))).
-var table = []uint32{
- // round 1
- 0xd76aa478,
- 0xe8c7b756,
- 0x242070db,
- 0xc1bdceee,
- 0xf57c0faf,
- 0x4787c62a,
- 0xa8304613,
- 0xfd469501,
- 0x698098d8,
- 0x8b44f7af,
- 0xffff5bb1,
- 0x895cd7be,
- 0x6b901122,
- 0xfd987193,
- 0xa679438e,
- 0x49b40821,
-
- // round 2
- 0xf61e2562,
- 0xc040b340,
- 0x265e5a51,
- 0xe9b6c7aa,
- 0xd62f105d,
- 0x2441453,
- 0xd8a1e681,
- 0xe7d3fbc8,
- 0x21e1cde6,
- 0xc33707d6,
- 0xf4d50d87,
- 0x455a14ed,
- 0xa9e3e905,
- 0xfcefa3f8,
- 0x676f02d9,
- 0x8d2a4c8a,
-
- // round3
- 0xfffa3942,
- 0x8771f681,
- 0x6d9d6122,
- 0xfde5380c,
- 0xa4beea44,
- 0x4bdecfa9,
- 0xf6bb4b60,
- 0xbebfbc70,
- 0x289b7ec6,
- 0xeaa127fa,
- 0xd4ef3085,
- 0x4881d05,
- 0xd9d4d039,
- 0xe6db99e5,
- 0x1fa27cf8,
- 0xc4ac5665,
-
- // round 4
- 0xf4292244,
- 0x432aff97,
- 0xab9423a7,
- 0xfc93a039,
- 0x655b59c3,
- 0x8f0ccc92,
- 0xffeff47d,
- 0x85845dd1,
- 0x6fa87e4f,
- 0xfe2ce6e0,
- 0xa3014314,
- 0x4e0811a1,
- 0xf7537e82,
- 0xbd3af235,
- 0x2ad7d2bb,
- 0xeb86d391,
-}
+import (
+ "runtime"
+ "unsafe"
+)
-var shift1 = []uint{7, 12, 17, 22}
-var shift2 = []uint{5, 9, 14, 20}
-var shift3 = []uint{4, 11, 16, 23}
-var shift4 = []uint{6, 10, 15, 21}
-
-func _Block(dig *digest, p []byte) int {
+func block(dig *digest, p []byte) {
a := dig.s[0]
b := dig.s[1]
c := dig.s[2]
d := dig.s[3]
- n := 0
- var X [16]uint32
- for len(p) >= _Chunk {
+ var X *[16]uint32
+ var xbuf [16]uint32
+ for len(p) >= chunk {
aa, bb, cc, dd := a, b, c, d
- j := 0
- for i := 0; i < 16; i++ {
- X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
- j += 4
+ // This is a constant condition - it is not evaluated on each iteration.
+ if runtime.GOARCH == "amd64" || runtime.GOARCH == "386" {
+ // MD5 was designed so that x86 processors can just iterate
+ // over the block data directly as uint32s, and we generate
+ // less code and run 1.3x faster if we take advantage of that.
+ // My apologies.
+ X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+ } else {
+ X = &xbuf
+ j := 0
+ for i := 0; i < 16; i++ {
+ X[i&15] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+ j += 4
+ }
}
- // If this needs to be made faster in the future,
- // the usual trick is to unroll each of these
- // loops by a factor of 4; that lets you replace
- // the shift[] lookups with constants and,
- // with suitable variable renaming in each
- // unrolled body, delete the a, b, c, d = d, a, b, c
- // (or you can let the optimizer do the renaming).
- //
- // The index variables are uint so that % by a power
- // of two can be optimized easily by a compiler.
-
// Round 1.
- for i := uint(0); i < 16; i++ {
- x := i
- s := shift1[i%4]
- f := ((c ^ d) & b) ^ d
- a += f + X[x] + table[i]
- a = a<<s | a>>(32-s) + b
- a, b, c, d = d, a, b, c
- }
+
+ a += (((c ^ d) & b) ^ d) + X[0] + 3614090360
+ a = a<<7 | a>>(32-7) + b
+
+ d += (((b ^ c) & a) ^ c) + X[1] + 3905402710
+ d = d<<12 | d>>(32-12) + a
+
+ c += (((a ^ b) & d) ^ b) + X[2] + 606105819
+ c = c<<17 | c>>(32-17) + d
+
+ b += (((d ^ a) & c) ^ a) + X[3] + 3250441966
+ b = b<<22 | b>>(32-22) + c
+
+ a += (((c ^ d) & b) ^ d) + X[4] + 4118548399
+ a = a<<7 | a>>(32-7) + b
+
+ d += (((b ^ c) & a) ^ c) + X[5] + 1200080426
+ d = d<<12 | d>>(32-12) + a
+
+ c += (((a ^ b) & d) ^ b) + X[6] + 2821735955
+ c = c<<17 | c>>(32-17) + d
+
+ b += (((d ^ a) & c) ^ a) + X[7] + 4249261313
+ b = b<<22 | b>>(32-22) + c
+
+ a += (((c ^ d) & b) ^ d) + X[8] + 1770035416
+ a = a<<7 | a>>(32-7) + b
+
+ d += (((b ^ c) & a) ^ c) + X[9] + 2336552879
+ d = d<<12 | d>>(32-12) + a
+
+ c += (((a ^ b) & d) ^ b) + X[10] + 4294925233
+ c = c<<17 | c>>(32-17) + d
+
+ b += (((d ^ a) & c) ^ a) + X[11] + 2304563134
+ b = b<<22 | b>>(32-22) + c
+
+ a += (((c ^ d) & b) ^ d) + X[12] + 1804603682
+ a = a<<7 | a>>(32-7) + b
+
+ d += (((b ^ c) & a) ^ c) + X[13] + 4254626195
+ d = d<<12 | d>>(32-12) + a
+
+ c += (((a ^ b) & d) ^ b) + X[14] + 2792965006
+ c = c<<17 | c>>(32-17) + d
+
+ b += (((d ^ a) & c) ^ a) + X[15] + 1236535329
+ b = b<<22 | b>>(32-22) + c
// Round 2.
- for i := uint(0); i < 16; i++ {
- x := (1 + 5*i) % 16
- s := shift2[i%4]
- g := ((b ^ c) & d) ^ c
- a += g + X[x] + table[i+16]
- a = a<<s | a>>(32-s) + b
- a, b, c, d = d, a, b, c
- }
+
+ a += (((b ^ c) & d) ^ c) + X[(1+5*0)&15] + 4129170786
+ a = a<<5 | a>>(32-5) + b
+
+ d += (((a ^ b) & c) ^ b) + X[(1+5*1)&15] + 3225465664
+ d = d<<9 | d>>(32-9) + a
+
+ c += (((d ^ a) & b) ^ a) + X[(1+5*2)&15] + 643717713
+ c = c<<14 | c>>(32-14) + d
+
+ b += (((c ^ d) & a) ^ d) + X[(1+5*3)&15] + 3921069994
+ b = b<<20 | b>>(32-20) + c
+
+ a += (((b ^ c) & d) ^ c) + X[(1+5*4)&15] + 3593408605
+ a = a<<5 | a>>(32-5) + b
+
+ d += (((a ^ b) & c) ^ b) + X[(1+5*5)&15] + 38016083
+ d = d<<9 | d>>(32-9) + a
+
+ c += (((d ^ a) & b) ^ a) + X[(1+5*6)&15] + 3634488961
+ c = c<<14 | c>>(32-14) + d
+
+ b += (((c ^ d) & a) ^ d) + X[(1+5*7)&15] + 3889429448
+ b = b<<20 | b>>(32-20) + c
+
+ a += (((b ^ c) & d) ^ c) + X[(1+5*8)&15] + 568446438
+ a = a<<5 | a>>(32-5) + b
+
+ d += (((a ^ b) & c) ^ b) + X[(1+5*9)&15] + 3275163606
+ d = d<<9 | d>>(32-9) + a
+
+ c += (((d ^ a) & b) ^ a) + X[(1+5*10)&15] + 4107603335
+ c = c<<14 | c>>(32-14) + d
+
+ b += (((c ^ d) & a) ^ d) + X[(1+5*11)&15] + 1163531501
+ b = b<<20 | b>>(32-20) + c
+
+ a += (((b ^ c) & d) ^ c) + X[(1+5*12)&15] + 2850285829
+ a = a<<5 | a>>(32-5) + b
+
+ d += (((a ^ b) & c) ^ b) + X[(1+5*13)&15] + 4243563512
+ d = d<<9 | d>>(32-9) + a
+
+ c += (((d ^ a) & b) ^ a) + X[(1+5*14)&15] + 1735328473
+ c = c<<14 | c>>(32-14) + d
+
+ b += (((c ^ d) & a) ^ d) + X[(1+5*15)&15] + 2368359562
+ b = b<<20 | b>>(32-20) + c
// Round 3.
- for i := uint(0); i < 16; i++ {
- x := (5 + 3*i) % 16
- s := shift3[i%4]
- h := b ^ c ^ d
- a += h + X[x] + table[i+32]
- a = a<<s | a>>(32-s) + b
- a, b, c, d = d, a, b, c
- }
+
+ a += (b ^ c ^ d) + X[(5+3*0)&15] + 4294588738
+ a = a<<4 | a>>(32-4) + b
+
+ d += (a ^ b ^ c) + X[(5+3*1)&15] + 2272392833
+ d = d<<11 | d>>(32-11) + a
+
+ c += (d ^ a ^ b) + X[(5+3*2)&15] + 1839030562
+ c = c<<16 | c>>(32-16) + d
+
+ b += (c ^ d ^ a) + X[(5+3*3)&15] + 4259657740
+ b = b<<23 | b>>(32-23) + c
+
+ a += (b ^ c ^ d) + X[(5+3*4)&15] + 2763975236
+ a = a<<4 | a>>(32-4) + b
+
+ d += (a ^ b ^ c) + X[(5+3*5)&15] + 1272893353
+ d = d<<11 | d>>(32-11) + a
+
+ c += (d ^ a ^ b) + X[(5+3*6)&15] + 4139469664
+ c = c<<16 | c>>(32-16) + d
+
+ b += (c ^ d ^ a) + X[(5+3*7)&15] + 3200236656
+ b = b<<23 | b>>(32-23) + c
+
+ a += (b ^ c ^ d) + X[(5+3*8)&15] + 681279174
+ a = a<<4 | a>>(32-4) + b
+
+ d += (a ^ b ^ c) + X[(5+3*9)&15] + 3936430074
+ d = d<<11 | d>>(32-11) + a
+
+ c += (d ^ a ^ b) + X[(5+3*10)&15] + 3572445317
+ c = c<<16 | c>>(32-16) + d
+
+ b += (c ^ d ^ a) + X[(5+3*11)&15] + 76029189
+ b = b<<23 | b>>(32-23) + c
+
+ a += (b ^ c ^ d) + X[(5+3*12)&15] + 3654602809
+ a = a<<4 | a>>(32-4) + b
+
+ d += (a ^ b ^ c) + X[(5+3*13)&15] + 3873151461
+ d = d<<11 | d>>(32-11) + a
+
+ c += (d ^ a ^ b) + X[(5+3*14)&15] + 530742520
+ c = c<<16 | c>>(32-16) + d
+
+ b += (c ^ d ^ a) + X[(5+3*15)&15] + 3299628645
+ b = b<<23 | b>>(32-23) + c
// Round 4.
- for i := uint(0); i < 16; i++ {
- x := (7 * i) % 16
- s := shift4[i%4]
- j := c ^ (b | ^d)
- a += j + X[x] + table[i+48]
- a = a<<s | a>>(32-s) + b
- a, b, c, d = d, a, b, c
- }
+
+ a += (c ^ (b | ^d)) + X[(7*0)&15] + 4096336452
+ a = a<<6 | a>>(32-6) + b
+
+ d += (b ^ (a | ^c)) + X[(7*1)&15] + 1126891415
+ d = d<<10 | d>>(32-10) + a
+
+ c += (a ^ (d | ^b)) + X[(7*2)&15] + 2878612391
+ c = c<<15 | c>>(32-15) + d
+
+ b += (d ^ (c | ^a)) + X[(7*3)&15] + 4237533241
+ b = b<<21 | b>>(32-21) + c
+
+ a += (c ^ (b | ^d)) + X[(7*4)&15] + 1700485571
+ a = a<<6 | a>>(32-6) + b
+
+ d += (b ^ (a | ^c)) + X[(7*5)&15] + 2399980690
+ d = d<<10 | d>>(32-10) + a
+
+ c += (a ^ (d | ^b)) + X[(7*6)&15] + 4293915773
+ c = c<<15 | c>>(32-15) + d
+
+ b += (d ^ (c | ^a)) + X[(7*7)&15] + 2240044497
+ b = b<<21 | b>>(32-21) + c
+
+ a += (c ^ (b | ^d)) + X[(7*8)&15] + 1873313359
+ a = a<<6 | a>>(32-6) + b
+
+ d += (b ^ (a | ^c)) + X[(7*9)&15] + 4264355552
+ d = d<<10 | d>>(32-10) + a
+
+ c += (a ^ (d | ^b)) + X[(7*10)&15] + 2734768916
+ c = c<<15 | c>>(32-15) + d
+
+ b += (d ^ (c | ^a)) + X[(7*11)&15] + 1309151649
+ b = b<<21 | b>>(32-21) + c
+
+ a += (c ^ (b | ^d)) + X[(7*12)&15] + 4149444226
+ a = a<<6 | a>>(32-6) + b
+
+ d += (b ^ (a | ^c)) + X[(7*13)&15] + 3174756917
+ d = d<<10 | d>>(32-10) + a
+
+ c += (a ^ (d | ^b)) + X[(7*14)&15] + 718787259
+ c = c<<15 | c>>(32-15) + d
+
+ b += (d ^ (c | ^a)) + X[(7*15)&15] + 3951481745
+ b = b<<21 | b>>(32-21) + c
a += aa
b += bb
c += cc
d += dd
- p = p[_Chunk:]
- n += _Chunk
+ p = p[chunk:]
}
dig.s[0] = a
dig.s[1] = b
dig.s[2] = c
dig.s[3] = d
- return n
}
diff --git a/libgo/go/crypto/rand/rand_unix.go b/libgo/go/crypto/rand/rand_unix.go
index 5eb4cda2b3a..18f482472d3 100644
--- a/libgo/go/crypto/rand/rand_unix.go
+++ b/libgo/go/crypto/rand/rand_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin freebsd linux netbsd openbsd plan9
// Unix cryptographically secure pseudorandom number
// generator.
@@ -15,6 +15,7 @@ import (
"crypto/cipher"
"io"
"os"
+ "runtime"
"sync"
"time"
)
@@ -22,7 +23,13 @@ import (
// Easy implementation: read from /dev/urandom.
// This is sufficient on Linux, OS X, and FreeBSD.
-func init() { Reader = &devReader{name: "/dev/urandom"} }
+func init() {
+ if runtime.GOOS == "plan9" {
+ Reader = newReader(nil)
+ } else {
+ Reader = &devReader{name: "/dev/urandom"}
+ }
+}
// A devReader satisfies reads by reading the file named name.
type devReader struct {
@@ -39,14 +46,17 @@ func (r *devReader) Read(b []byte) (n int, err error) {
if f == nil {
return 0, err
}
- r.f = bufio.NewReader(f)
+ if runtime.GOOS == "plan9" {
+ r.f = f
+ } else {
+ r.f = bufio.NewReader(f)
+ }
}
return r.f.Read(b)
}
// Alternate pseudo-random implementation for use on
-// systems without a reliable /dev/urandom. So far we
-// haven't needed it.
+// systems without a reliable /dev/urandom.
// newReader returns a new pseudorandom generator that
// seeds itself by reading from entropy. If entropy == nil,
diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go
index f39a48a6af6..28ca5d73b39 100644
--- a/libgo/go/crypto/rsa/pkcs1v15.go
+++ b/libgo/go/crypto/rsa/pkcs1v15.go
@@ -19,6 +19,9 @@ import (
// WARNING: use of this function to encrypt plaintexts other than session keys
// is dangerous. Use RSA OAEP in new protocols.
func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) {
+ if err := checkPub(pub); err != nil {
+ return nil, err
+ }
k := (pub.N.BitLen() + 7) / 8
if len(msg) > k-11 {
err = ErrMessageTooLong
@@ -47,6 +50,9 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
// DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) {
+ if err := checkPub(&priv.PublicKey); err != nil {
+ return nil, err
+ }
valid, out, err := decryptPKCS1v15(rand, priv, ciphertext)
if err == nil && valid == 0 {
err = ErrDecryption
@@ -69,6 +75,9 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [
// Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
// (Crypto '98).
func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
+ if err := checkPub(&priv.PublicKey); err != nil {
+ return err
+ }
k := (priv.N.BitLen() + 7) / 8
if k-(len(key)+3+8) < 0 {
err = ErrDecryption
@@ -238,11 +247,11 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
hashLen = hash.Size()
if inLen != hashLen {
- return 0, nil, errors.New("input must be hashed message")
+ return 0, nil, errors.New("crypto/rsa: input must be hashed message")
}
prefix, ok := hashPrefixes[hash]
if !ok {
- return 0, nil, errors.New("unsupported hash function")
+ return 0, nil, errors.New("crypto/rsa: unsupported hash function")
}
return
}
diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go
index ec77e68696b..7faae674304 100644
--- a/libgo/go/crypto/rsa/rsa.go
+++ b/libgo/go/crypto/rsa/rsa.go
@@ -25,6 +25,30 @@ type PublicKey struct {
E int // public exponent
}
+var (
+ errPublicModulus = errors.New("crypto/rsa: missing public modulus")
+ errPublicExponentSmall = errors.New("crypto/rsa: public exponent too small")
+ errPublicExponentLarge = errors.New("crypto/rsa: public exponent too large")
+)
+
+// checkPub sanity checks the public key before we use it.
+// We require pub.E to fit into a 32-bit integer so that we
+// do not have different behavior depending on whether
+// int is 32 or 64 bits. See also
+// http://www.imperialviolet.org/2012/03/16/rsae.html.
+func checkPub(pub *PublicKey) error {
+ if pub.N == nil {
+ return errPublicModulus
+ }
+ if pub.E < 2 {
+ return errPublicExponentSmall
+ }
+ if pub.E > 1<<31-1 {
+ return errPublicExponentLarge
+ }
+ return nil
+}
+
// A PrivateKey represents an RSA key
type PrivateKey struct {
PublicKey // public part.
@@ -57,13 +81,17 @@ type CRTValue struct {
// Validate performs basic sanity checks on the key.
// It returns nil if the key is valid, or else an error describing a problem.
func (priv *PrivateKey) Validate() error {
+ if err := checkPub(&priv.PublicKey); err != nil {
+ return err
+ }
+
// Check that the prime factors are actually prime. Note that this is
// just a sanity check. Since the random witnesses chosen by
// ProbablyPrime are deterministic, given the candidate number, it's
// easy for an attack to generate composites that pass this test.
for _, prime := range priv.Primes {
if !prime.ProbablyPrime(20) {
- return errors.New("prime factor is composite")
+ return errors.New("crypto/rsa: prime factor is composite")
}
}
@@ -73,27 +101,23 @@ func (priv *PrivateKey) Validate() error {
modulus.Mul(modulus, prime)
}
if modulus.Cmp(priv.N) != 0 {
- return errors.New("invalid modulus")
+ return errors.New("crypto/rsa: invalid modulus")
}
- // Check that e and totient(Πprimes) are coprime.
- totient := new(big.Int).Set(bigOne)
+
+ // Check that de ≡ 1 mod p-1, for each prime.
+ // This implies that e is coprime to each p-1 as e has a multiplicative
+ // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) =
+ // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1
+ // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required.
+ congruence := new(big.Int)
+ de := new(big.Int).SetInt64(int64(priv.E))
+ de.Mul(de, priv.D)
for _, prime := range priv.Primes {
pminus1 := new(big.Int).Sub(prime, bigOne)
- totient.Mul(totient, pminus1)
- }
- e := big.NewInt(int64(priv.E))
- gcd := new(big.Int)
- x := new(big.Int)
- y := new(big.Int)
- gcd.GCD(x, y, totient, e)
- if gcd.Cmp(bigOne) != 0 {
- return errors.New("invalid public exponent E")
- }
- // Check that de ≡ 1 (mod totient(Πprimes))
- de := new(big.Int).Mul(priv.D, e)
- de.Mod(de, totient)
- if de.Cmp(bigOne) != 0 {
- return errors.New("invalid private exponent D")
+ congruence.Mod(de, pminus1)
+ if congruence.Cmp(bigOne) != 0 {
+ return errors.New("crypto/rsa: invalid exponents")
+ }
}
return nil
}
@@ -118,7 +142,7 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *Priva
priv.E = 65537
if nprimes < 2 {
- return nil, errors.New("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
+ return nil, errors.New("crypto/rsa: GenerateMultiPrimeKey: nprimes must be >= 2")
}
primes := make([]*big.Int, nprimes)
@@ -220,6 +244,9 @@ func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
// The message must be no longer than the length of the public modulus less
// twice the hash length plus 2.
func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error) {
+ if err := checkPub(pub); err != nil {
+ return nil, err
+ }
hash.Reset()
k := (pub.N.BitLen() + 7) / 8
if len(msg) > k-2*hash.Size()-2 {
@@ -406,6 +433,9 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er
// DecryptOAEP decrypts ciphertext using RSA-OAEP.
// If random != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
+ if err := checkPub(&priv.PublicKey); err != nil {
+ return nil, err
+ }
k := (priv.N.BitLen() + 7) / 8
if len(ciphertext) > k ||
k < hash.Size()*2+2 {
diff --git a/libgo/go/crypto/rsa/rsa_test.go b/libgo/go/crypto/rsa/rsa_test.go
index 0fb9875d044..62bbdc4aec3 100644
--- a/libgo/go/crypto/rsa/rsa_test.go
+++ b/libgo/go/crypto/rsa/rsa_test.go
@@ -50,6 +50,24 @@ func Test4PrimeKeyGeneration(t *testing.T) {
testKeyBasics(t, priv)
}
+func TestGnuTLSKey(t *testing.T) {
+ // This is a key generated by `certtool --generate-privkey --bits 128`.
+ // It's such that de ≢ 1 mod φ(n), but is congruent mod the order of
+ // the group.
+ priv := &PrivateKey{
+ PublicKey: PublicKey{
+ N: fromBase10("290684273230919398108010081414538931343"),
+ E: 65537,
+ },
+ D: fromBase10("31877380284581499213530787347443987241"),
+ Primes: []*big.Int{
+ fromBase10("16775196964030542637"),
+ fromBase10("17328218193455850539"),
+ },
+ }
+ testKeyBasics(t, priv)
+}
+
func testKeyBasics(t *testing.T, priv *PrivateKey) {
if err := priv.Validate(); err != nil {
t.Errorf("Validate() failed: %s", err)
diff --git a/libgo/go/crypto/sha1/sha1.go b/libgo/go/crypto/sha1/sha1.go
index 876e7992a3a..7cfde47dc07 100644
--- a/libgo/go/crypto/sha1/sha1.go
+++ b/libgo/go/crypto/sha1/sha1.go
@@ -21,28 +21,28 @@ const Size = 20
const BlockSize = 64
const (
- _Chunk = 64
- _Init0 = 0x67452301
- _Init1 = 0xEFCDAB89
- _Init2 = 0x98BADCFE
- _Init3 = 0x10325476
- _Init4 = 0xC3D2E1F0
+ chunk = 64
+ init0 = 0x67452301
+ init1 = 0xEFCDAB89
+ init2 = 0x98BADCFE
+ init3 = 0x10325476
+ init4 = 0xC3D2E1F0
)
// digest represents the partial evaluation of a checksum.
type digest struct {
h [5]uint32
- x [_Chunk]byte
+ x [chunk]byte
nx int
len uint64
}
func (d *digest) Reset() {
- d.h[0] = _Init0
- d.h[1] = _Init1
- d.h[2] = _Init2
- d.h[3] = _Init3
- d.h[4] = _Init4
+ d.h[0] = init0
+ d.h[1] = init1
+ d.h[2] = init2
+ d.h[3] = init3
+ d.h[4] = init4
d.nx = 0
d.len = 0
}
@@ -63,21 +63,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
d.len += uint64(nn)
if d.nx > 0 {
n := len(p)
- if n > _Chunk-d.nx {
- n = _Chunk - d.nx
+ if n > chunk-d.nx {
+ n = chunk - d.nx
}
for i := 0; i < n; i++ {
d.x[d.nx+i] = p[i]
}
d.nx += n
- if d.nx == _Chunk {
- _Block(d, d.x[0:])
+ if d.nx == chunk {
+ block(d, d.x[0:])
d.nx = 0
}
p = p[n:]
}
- n := _Block(d, p)
- p = p[n:]
+ if len(p) >= chunk {
+ n := len(p) &^ (chunk - 1)
+ block(d, p[:n])
+ p = p[n:]
+ }
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
diff --git a/libgo/go/crypto/sha1/sha1_test.go b/libgo/go/crypto/sha1/sha1_test.go
index 2dc14ac9868..e3d03e52a31 100644
--- a/libgo/go/crypto/sha1/sha1_test.go
+++ b/libgo/go/crypto/sha1/sha1_test.go
@@ -79,3 +79,28 @@ func ExampleNew() {
fmt.Printf("% x", h.Sum(nil))
// Output: 59 7f 6a 54 00 10 f9 4c 15 d7 18 06 a9 9a 2c 87 10 e7 47 bd
}
+
+var bench = sha1.New()
+var buf = makeBuf()
+
+func makeBuf() []byte {
+ b := make([]byte, 8<<10)
+ for i := range b {
+ b[i] = byte(i)
+ }
+ return b
+}
+
+func BenchmarkHash1K(b *testing.B) {
+ b.SetBytes(1024)
+ for i := 0; i < b.N; i++ {
+ bench.Write(buf[:1024])
+ }
+}
+
+func BenchmarkHash8K(b *testing.B) {
+ b.SetBytes(int64(len(buf)))
+ for i := 0; i < b.N; i++ {
+ bench.Write(buf)
+ }
+}
diff --git a/libgo/go/crypto/sha1/sha1block.go b/libgo/go/crypto/sha1/sha1block.go
index b5d32af7094..b9fe21d9e3d 100644
--- a/libgo/go/crypto/sha1/sha1block.go
+++ b/libgo/go/crypto/sha1/sha1block.go
@@ -15,12 +15,11 @@ const (
_K3 = 0xCA62C1D6
)
-func _Block(dig *digest, p []byte) int {
+func block(dig *digest, p []byte) {
var w [80]uint32
- n := 0
h0, h1, h2, h3, h4 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4]
- for len(p) >= _Chunk {
+ for len(p) >= chunk {
// Can interlace the computation of w with the
// rounds below if needed for speed.
for i := 0; i < 16; i++ {
@@ -72,10 +71,8 @@ func _Block(dig *digest, p []byte) int {
h3 += d
h4 += e
- p = p[_Chunk:]
- n += _Chunk
+ p = p[chunk:]
}
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4] = h0, h1, h2, h3, h4
- return n
}
diff --git a/libgo/go/crypto/sha256/sha256.go b/libgo/go/crypto/sha256/sha256.go
index a61e30b4251..dc0e18f50df 100644
--- a/libgo/go/crypto/sha256/sha256.go
+++ b/libgo/go/crypto/sha256/sha256.go
@@ -26,29 +26,29 @@ const Size224 = 28
const BlockSize = 64
const (
- _Chunk = 64
- _Init0 = 0x6A09E667
- _Init1 = 0xBB67AE85
- _Init2 = 0x3C6EF372
- _Init3 = 0xA54FF53A
- _Init4 = 0x510E527F
- _Init5 = 0x9B05688C
- _Init6 = 0x1F83D9AB
- _Init7 = 0x5BE0CD19
- _Init0_224 = 0xC1059ED8
- _Init1_224 = 0x367CD507
- _Init2_224 = 0x3070DD17
- _Init3_224 = 0xF70E5939
- _Init4_224 = 0xFFC00B31
- _Init5_224 = 0x68581511
- _Init6_224 = 0x64F98FA7
- _Init7_224 = 0xBEFA4FA4
+ chunk = 64
+ init0 = 0x6A09E667
+ init1 = 0xBB67AE85
+ init2 = 0x3C6EF372
+ init3 = 0xA54FF53A
+ init4 = 0x510E527F
+ init5 = 0x9B05688C
+ init6 = 0x1F83D9AB
+ init7 = 0x5BE0CD19
+ init0_224 = 0xC1059ED8
+ init1_224 = 0x367CD507
+ init2_224 = 0x3070DD17
+ init3_224 = 0xF70E5939
+ init4_224 = 0xFFC00B31
+ init5_224 = 0x68581511
+ init6_224 = 0x64F98FA7
+ init7_224 = 0xBEFA4FA4
)
// digest represents the partial evaluation of a checksum.
type digest struct {
h [8]uint32
- x [_Chunk]byte
+ x [chunk]byte
nx int
len uint64
is224 bool // mark if this digest is SHA-224
@@ -56,23 +56,23 @@ type digest struct {
func (d *digest) Reset() {
if !d.is224 {
- d.h[0] = _Init0
- d.h[1] = _Init1
- d.h[2] = _Init2
- d.h[3] = _Init3
- d.h[4] = _Init4
- d.h[5] = _Init5
- d.h[6] = _Init6
- d.h[7] = _Init7
+ d.h[0] = init0
+ d.h[1] = init1
+ d.h[2] = init2
+ d.h[3] = init3
+ d.h[4] = init4
+ d.h[5] = init5
+ d.h[6] = init6
+ d.h[7] = init7
} else {
- d.h[0] = _Init0_224
- d.h[1] = _Init1_224
- d.h[2] = _Init2_224
- d.h[3] = _Init3_224
- d.h[4] = _Init4_224
- d.h[5] = _Init5_224
- d.h[6] = _Init6_224
- d.h[7] = _Init7_224
+ d.h[0] = init0_224
+ d.h[1] = init1_224
+ d.h[2] = init2_224
+ d.h[3] = init3_224
+ d.h[4] = init4_224
+ d.h[5] = init5_224
+ d.h[6] = init6_224
+ d.h[7] = init7_224
}
d.nx = 0
d.len = 0
@@ -107,21 +107,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
d.len += uint64(nn)
if d.nx > 0 {
n := len(p)
- if n > _Chunk-d.nx {
- n = _Chunk - d.nx
+ if n > chunk-d.nx {
+ n = chunk - d.nx
}
for i := 0; i < n; i++ {
d.x[d.nx+i] = p[i]
}
d.nx += n
- if d.nx == _Chunk {
- _Block(d, d.x[0:])
+ if d.nx == chunk {
+ block(d, d.x[0:])
d.nx = 0
}
p = p[n:]
}
- n := _Block(d, p)
- p = p[n:]
+ if len(p) >= chunk {
+ n := len(p) &^ (chunk - 1)
+ block(d, p[:n])
+ p = p[n:]
+ }
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
diff --git a/libgo/go/crypto/sha256/sha256_test.go b/libgo/go/crypto/sha256/sha256_test.go
index a6efb375456..8e66b4b306d 100644
--- a/libgo/go/crypto/sha256/sha256_test.go
+++ b/libgo/go/crypto/sha256/sha256_test.go
@@ -123,3 +123,28 @@ func TestGolden(t *testing.T) {
}
}
}
+
+var bench = New()
+var buf = makeBuf()
+
+func makeBuf() []byte {
+ b := make([]byte, 8<<10)
+ for i := range b {
+ b[i] = byte(i)
+ }
+ return b
+}
+
+func BenchmarkHash1K(b *testing.B) {
+ b.SetBytes(1024)
+ for i := 0; i < b.N; i++ {
+ bench.Write(buf[:1024])
+ }
+}
+
+func BenchmarkHash8K(b *testing.B) {
+ b.SetBytes(int64(len(buf)))
+ for i := 0; i < b.N; i++ {
+ bench.Write(buf)
+ }
+}
diff --git a/libgo/go/crypto/sha256/sha256block.go b/libgo/go/crypto/sha256/sha256block.go
index 7b0f5544453..2ac49100ac6 100644
--- a/libgo/go/crypto/sha256/sha256block.go
+++ b/libgo/go/crypto/sha256/sha256block.go
@@ -75,11 +75,10 @@ var _K = []uint32{
0xc67178f2,
}
-func _Block(dig *digest, p []byte) int {
+func block(dig *digest, p []byte) {
var w [64]uint32
- n := 0
h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
- for len(p) >= _Chunk {
+ for len(p) >= chunk {
// Can interlace the computation of w with the
// rounds below if needed for speed.
for i := 0; i < 16; i++ {
@@ -87,10 +86,10 @@ func _Block(dig *digest, p []byte) int {
w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
}
for i := 16; i < 64; i++ {
- t1 := (w[i-2]>>17 | w[i-2]<<(32-17)) ^ (w[i-2]>>19 | w[i-2]<<(32-19)) ^ (w[i-2] >> 10)
-
- t2 := (w[i-15]>>7 | w[i-15]<<(32-7)) ^ (w[i-15]>>18 | w[i-15]<<(32-18)) ^ (w[i-15] >> 3)
-
+ v1 := w[i-2]
+ t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10)
+ v2 := w[i-15]
+ t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3)
w[i] = t1 + w[i-7] + t2 + w[i-16]
}
@@ -120,10 +119,8 @@ func _Block(dig *digest, p []byte) int {
h6 += g
h7 += h
- p = p[_Chunk:]
- n += _Chunk
+ p = p[chunk:]
}
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
- return n
}
diff --git a/libgo/go/crypto/sha512/sha512.go b/libgo/go/crypto/sha512/sha512.go
index a245fd68e55..4aec5293858 100644
--- a/libgo/go/crypto/sha512/sha512.go
+++ b/libgo/go/crypto/sha512/sha512.go
@@ -26,29 +26,29 @@ const Size384 = 48
const BlockSize = 128
const (
- _Chunk = 128
- _Init0 = 0x6a09e667f3bcc908
- _Init1 = 0xbb67ae8584caa73b
- _Init2 = 0x3c6ef372fe94f82b
- _Init3 = 0xa54ff53a5f1d36f1
- _Init4 = 0x510e527fade682d1
- _Init5 = 0x9b05688c2b3e6c1f
- _Init6 = 0x1f83d9abfb41bd6b
- _Init7 = 0x5be0cd19137e2179
- _Init0_384 = 0xcbbb9d5dc1059ed8
- _Init1_384 = 0x629a292a367cd507
- _Init2_384 = 0x9159015a3070dd17
- _Init3_384 = 0x152fecd8f70e5939
- _Init4_384 = 0x67332667ffc00b31
- _Init5_384 = 0x8eb44a8768581511
- _Init6_384 = 0xdb0c2e0d64f98fa7
- _Init7_384 = 0x47b5481dbefa4fa4
+ chunk = 128
+ init0 = 0x6a09e667f3bcc908
+ init1 = 0xbb67ae8584caa73b
+ init2 = 0x3c6ef372fe94f82b
+ init3 = 0xa54ff53a5f1d36f1
+ init4 = 0x510e527fade682d1
+ init5 = 0x9b05688c2b3e6c1f
+ init6 = 0x1f83d9abfb41bd6b
+ init7 = 0x5be0cd19137e2179
+ init0_384 = 0xcbbb9d5dc1059ed8
+ init1_384 = 0x629a292a367cd507
+ init2_384 = 0x9159015a3070dd17
+ init3_384 = 0x152fecd8f70e5939
+ init4_384 = 0x67332667ffc00b31
+ init5_384 = 0x8eb44a8768581511
+ init6_384 = 0xdb0c2e0d64f98fa7
+ init7_384 = 0x47b5481dbefa4fa4
)
// digest represents the partial evaluation of a checksum.
type digest struct {
h [8]uint64
- x [_Chunk]byte
+ x [chunk]byte
nx int
len uint64
is384 bool // mark if this digest is SHA-384
@@ -56,23 +56,23 @@ type digest struct {
func (d *digest) Reset() {
if !d.is384 {
- d.h[0] = _Init0
- d.h[1] = _Init1
- d.h[2] = _Init2
- d.h[3] = _Init3
- d.h[4] = _Init4
- d.h[5] = _Init5
- d.h[6] = _Init6
- d.h[7] = _Init7
+ d.h[0] = init0
+ d.h[1] = init1
+ d.h[2] = init2
+ d.h[3] = init3
+ d.h[4] = init4
+ d.h[5] = init5
+ d.h[6] = init6
+ d.h[7] = init7
} else {
- d.h[0] = _Init0_384
- d.h[1] = _Init1_384
- d.h[2] = _Init2_384
- d.h[3] = _Init3_384
- d.h[4] = _Init4_384
- d.h[5] = _Init5_384
- d.h[6] = _Init6_384
- d.h[7] = _Init7_384
+ d.h[0] = init0_384
+ d.h[1] = init1_384
+ d.h[2] = init2_384
+ d.h[3] = init3_384
+ d.h[4] = init4_384
+ d.h[5] = init5_384
+ d.h[6] = init6_384
+ d.h[7] = init7_384
}
d.nx = 0
d.len = 0
@@ -107,21 +107,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
d.len += uint64(nn)
if d.nx > 0 {
n := len(p)
- if n > _Chunk-d.nx {
- n = _Chunk - d.nx
+ if n > chunk-d.nx {
+ n = chunk - d.nx
}
for i := 0; i < n; i++ {
d.x[d.nx+i] = p[i]
}
d.nx += n
- if d.nx == _Chunk {
- _Block(d, d.x[0:])
+ if d.nx == chunk {
+ block(d, d.x[0:])
d.nx = 0
}
p = p[n:]
}
- n := _Block(d, p)
- p = p[n:]
+ if len(p) >= chunk {
+ n := len(p) &^ (chunk - 1)
+ block(d, p[:n])
+ p = p[n:]
+ }
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
diff --git a/libgo/go/crypto/sha512/sha512_test.go b/libgo/go/crypto/sha512/sha512_test.go
index a70f7c54e39..977655ddb41 100644
--- a/libgo/go/crypto/sha512/sha512_test.go
+++ b/libgo/go/crypto/sha512/sha512_test.go
@@ -123,3 +123,28 @@ func TestGolden(t *testing.T) {
}
}
}
+
+var bench = New()
+var buf = makeBuf()
+
+func makeBuf() []byte {
+ b := make([]byte, 8<<10)
+ for i := range b {
+ b[i] = byte(i)
+ }
+ return b
+}
+
+func BenchmarkHash1K(b *testing.B) {
+ b.SetBytes(1024)
+ for i := 0; i < b.N; i++ {
+ bench.Write(buf[:1024])
+ }
+}
+
+func BenchmarkHash8K(b *testing.B) {
+ b.SetBytes(int64(len(buf)))
+ for i := 0; i < b.N; i++ {
+ bench.Write(buf)
+ }
+}
diff --git a/libgo/go/crypto/sha512/sha512block.go b/libgo/go/crypto/sha512/sha512block.go
index 6b7506287e2..3577b4f3df1 100644
--- a/libgo/go/crypto/sha512/sha512block.go
+++ b/libgo/go/crypto/sha512/sha512block.go
@@ -91,20 +91,20 @@ var _K = []uint64{
0x6c44198c4a475817,
}
-func _Block(dig *digest, p []byte) int {
+func block(dig *digest, p []byte) {
var w [80]uint64
- n := 0
h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
- for len(p) >= _Chunk {
+ for len(p) >= chunk {
for i := 0; i < 16; i++ {
j := i * 8
w[i] = uint64(p[j])<<56 | uint64(p[j+1])<<48 | uint64(p[j+2])<<40 | uint64(p[j+3])<<32 |
uint64(p[j+4])<<24 | uint64(p[j+5])<<16 | uint64(p[j+6])<<8 | uint64(p[j+7])
}
for i := 16; i < 80; i++ {
- t1 := (w[i-2]>>19 | w[i-2]<<(64-19)) ^ (w[i-2]>>61 | w[i-2]<<(64-61)) ^ (w[i-2] >> 6)
-
- t2 := (w[i-15]>>1 | w[i-15]<<(64-1)) ^ (w[i-15]>>8 | w[i-15]<<(64-8)) ^ (w[i-15] >> 7)
+ v1 := w[i-2]
+ t1 := (v1>>19 | v1<<(64-19)) ^ (v1>>61 | v1<<(64-61)) ^ (v1 >> 6)
+ v2 := w[i-15]
+ t2 := (v2>>1 | v2<<(64-1)) ^ (v2>>8 | v2<<(64-8)) ^ (v2 >> 7)
w[i] = t1 + w[i-7] + t2 + w[i-16]
}
@@ -135,10 +135,8 @@ func _Block(dig *digest, p []byte) int {
h6 += g
h7 += h
- p = p[_Chunk:]
- n += _Chunk
+ p = p[chunk:]
}
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
- return n
}
diff --git a/libgo/go/crypto/tls/cipher_suites.go b/libgo/go/crypto/tls/cipher_suites.go
index 5039f319f59..a647e19aa19 100644
--- a/libgo/go/crypto/tls/cipher_suites.go
+++ b/libgo/go/crypto/tls/cipher_suites.go
@@ -55,9 +55,11 @@ var cipherSuites = []*cipherSuite{
{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, false, cipher3DES, macSHA1},
{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1},
+ {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, false, cipherAES, macSHA1},
{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, true, cipher3DES, macSHA1},
{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
+ {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
}
func cipherRC4(key, iv []byte, isRead bool) interface{} {
@@ -182,7 +184,9 @@ const (
TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
+ TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
)
diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go
index 4ba0bf87481..cfe2f2227fb 100644
--- a/libgo/go/crypto/tls/common.go
+++ b/libgo/go/crypto/tls/common.go
@@ -41,6 +41,7 @@ const (
const (
typeClientHello uint8 = 1
typeServerHello uint8 = 2
+ typeNewSessionTicket uint8 = 4
typeCertificate uint8 = 11
typeServerKeyExchange uint8 = 12
typeCertificateRequest uint8 = 13
@@ -63,6 +64,7 @@ var (
extensionStatusRequest uint16 = 5
extensionSupportedCurves uint16 = 10
extensionSupportedPoints uint16 = 11
+ extensionSessionTicket uint16 = 35
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
)
@@ -97,6 +99,7 @@ const (
// ConnectionState records basic TLS details about the connection.
type ConnectionState struct {
HandshakeComplete bool
+ DidResume bool
CipherSuite uint16
NegotiatedProtocol string
NegotiatedProtocolIsMutual bool
@@ -180,6 +183,22 @@ type Config struct {
// CipherSuites is a list of supported cipher suites. If CipherSuites
// is nil, TLS uses a list of suites supported by the implementation.
CipherSuites []uint16
+
+ // SessionTicketsDisabled may be set to true to disable session ticket
+ // (resumption) support.
+ SessionTicketsDisabled bool
+
+ // SessionTicketKey is used by TLS servers to provide session
+ // resumption. See RFC 5077. If zero, it will be filled with
+ // random data before the first server handshake.
+ //
+ // If multiple servers are terminating connections for the same host
+ // they should all have the same SessionTicketKey. If the
+ // SessionTicketKey leaks, previously recorded and future TLS
+ // connections using that key are compromised.
+ SessionTicketKey [32]byte
+
+ serverInitOnce sync.Once
}
func (c *Config) rand() io.Reader {
diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go
index 455910af415..fd2ef1ecfa8 100644
--- a/libgo/go/crypto/tls/conn.go
+++ b/libgo/go/crypto/tls/conn.go
@@ -31,6 +31,7 @@ type Conn struct {
haveVers bool // version has been negotiated
config *Config // configuration passed to constructor
handshakeComplete bool
+ didResume bool // whether this connection was a session resumption
cipherSuite uint16
ocspResponse []byte // stapled OCSP response
peerCertificates []*x509.Certificate
@@ -44,8 +45,7 @@ type Conn struct {
clientProtocolFallback bool
// first permanent error
- errMutex sync.Mutex
- err error
+ connErr
// input/output
in, out halfConn // in.Mutex < out.Mutex
@@ -56,21 +56,25 @@ type Conn struct {
tmp [16]byte
}
-func (c *Conn) setError(err error) error {
- c.errMutex.Lock()
- defer c.errMutex.Unlock()
+type connErr struct {
+ mu sync.Mutex
+ value error
+}
+
+func (e *connErr) setError(err error) error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
- if c.err == nil {
- c.err = err
+ if e.value == nil {
+ e.value = err
}
return err
}
-func (c *Conn) error() error {
- c.errMutex.Lock()
- defer c.errMutex.Unlock()
-
- return c.err
+func (e *connErr) error() error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+ return e.value
}
// Access to net.Conn methods.
@@ -660,8 +664,7 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
c.tmp[0] = alertLevelError
c.tmp[1] = byte(err.(alert))
c.writeRecord(recordTypeAlert, c.tmp[0:2])
- c.err = &net.OpError{Op: "local error", Err: err}
- return n, c.err
+ return n, c.setError(&net.OpError{Op: "local error", Err: err})
}
}
return
@@ -672,8 +675,8 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
// c.in.Mutex < L; c.out.Mutex < L.
func (c *Conn) readHandshake() (interface{}, error) {
for c.hand.Len() < 4 {
- if c.err != nil {
- return nil, c.err
+ if err := c.error(); err != nil {
+ return nil, err
}
if err := c.readRecord(recordTypeHandshake); err != nil {
return nil, err
@@ -684,11 +687,11 @@ func (c *Conn) readHandshake() (interface{}, error) {
n := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
if n > maxHandshake {
c.sendAlert(alertInternalError)
- return nil, c.err
+ return nil, c.error()
}
for c.hand.Len() < 4+n {
- if c.err != nil {
- return nil, c.err
+ if err := c.error(); err != nil {
+ return nil, err
}
if err := c.readRecord(recordTypeHandshake); err != nil {
return nil, err
@@ -738,12 +741,12 @@ func (c *Conn) readHandshake() (interface{}, error) {
// Write writes data to the connection.
func (c *Conn) Write(b []byte) (int, error) {
- if c.err != nil {
- return 0, c.err
+ if err := c.error(); err != nil {
+ return 0, err
}
- if c.err = c.Handshake(); c.err != nil {
- return 0, c.err
+ if err := c.Handshake(); err != nil {
+ return 0, c.setError(err)
}
c.out.Lock()
@@ -753,9 +756,8 @@ func (c *Conn) Write(b []byte) (int, error) {
return 0, alertInternalError
}
- var n int
- n, c.err = c.writeRecord(recordTypeApplicationData, b)
- return n, c.err
+ n, err := c.writeRecord(recordTypeApplicationData, b)
+ return n, c.setError(err)
}
// Read can be made to time out and return a net.Error with Timeout() == true
@@ -768,14 +770,14 @@ func (c *Conn) Read(b []byte) (n int, err error) {
c.in.Lock()
defer c.in.Unlock()
- for c.input == nil && c.err == nil {
+ for c.input == nil && c.error() == nil {
if err := c.readRecord(recordTypeApplicationData); err != nil {
// Soft error, like EAGAIN
return 0, err
}
}
- if c.err != nil {
- return 0, c.err
+ if err := c.error(); err != nil {
+ return 0, err
}
n, err = c.input.Read(b)
if c.input.off >= len(c.input.data) {
@@ -829,6 +831,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.HandshakeComplete = c.handshakeComplete
if c.handshakeComplete {
state.NegotiatedProtocol = c.clientProtocol
+ state.DidResume = c.didResume
state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
state.CipherSuite = c.cipherSuite
state.PeerCertificates = c.peerCertificates
diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go
index 2877f17387d..7db13bf70d8 100644
--- a/libgo/go/crypto/tls/handshake_client.go
+++ b/libgo/go/crypto/tls/handshake_client.go
@@ -278,8 +278,9 @@ func (c *Conn) clientHandshake() error {
c.writeRecord(recordTypeHandshake, certVerify.marshal())
}
- masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
- keysFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
+ masterSecret := masterFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random)
+ clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+ keysFromMasterSecret(c.vers, masterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */)
clientHash := suite.mac(c.vers, clientMAC)
@@ -306,8 +307,8 @@ func (c *Conn) clientHandshake() error {
serverHash := suite.mac(c.vers, serverMAC)
c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
c.readRecord(recordTypeChangeCipherSpec)
- if c.err != nil {
- return c.err
+ if err := c.error(); err != nil {
+ return err
}
msg, err = c.readHandshake()
diff --git a/libgo/go/crypto/tls/handshake_client_test.go b/libgo/go/crypto/tls/handshake_client_test.go
index 8c56daaf619..e127049bb05 100644
--- a/libgo/go/crypto/tls/handshake_client_test.go
+++ b/libgo/go/crypto/tls/handshake_client_test.go
@@ -9,6 +9,7 @@ import (
"flag"
"io"
"net"
+ "os"
"testing"
)
@@ -39,7 +40,15 @@ func testClientScript(t *testing.T, name string, clientScript [][]byte, config *
}
func TestHandshakeClientRC4(t *testing.T) {
- testClientScript(t, "RC4", rc4ClientScript, testConfig)
+ var config = *testConfig
+ config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
+ testClientScript(t, "RC4", rc4ClientScript, &config)
+}
+
+func TestHandshakeClientECDHEAES(t *testing.T) {
+ var config = *testConfig
+ config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}
+ testClientScript(t, "ECDHE-AES", ecdheAESClientScript, &config)
}
var connect = flag.Bool("connect", false, "connect to a TLS server on :10443")
@@ -49,25 +58,33 @@ func TestRunClient(t *testing.T) {
return
}
- testConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}
-
- conn, err := Dial("tcp", "127.0.0.1:10443", testConfig)
+ tcpConn, err := net.Dial("tcp", "127.0.0.1:10443")
if err != nil {
t.Fatal(err)
}
+ record := &recordingConn{
+ Conn: tcpConn,
+ }
+
+ config := GetTestConfig()
+ conn := Client(record, config)
+ if err := conn.Handshake(); err != nil {
+ t.Fatalf("error from TLS handshake: %s", err)
+ }
+
conn.Write([]byte("hello\n"))
conn.Close()
+
+ record.WriteTo(os.Stdout)
}
// Script of interaction with gnutls implementation.
// The values for this test are obtained by building and running in client mode:
-// % go test -run "TestRunClient" -connect
-// and then:
-// % gnutls-serv -p 10443 --debug 100 --x509keyfile key.pem --x509certfile cert.pem -a > /tmp/log 2>&1
-// % python parse-gnutls-cli-debug-log.py < /tmp/log
+// % go test -test.run "TestRunClient" -connect
+// The recorded bytes are written to stdout.
//
-// Where key.pem is:
+// The server private key is:
// -----BEGIN RSA PRIVATE KEY-----
// MIIBPAIBAAJBAJ+zw4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVD
// TGiXav6ooKXfX3j/7tdkuD8Ey2//Kv7+ue0CAwEAAQJAN6W31vDEP2DjdqhzCDDu
@@ -78,17 +95,20 @@ func TestRunClient(t *testing.T) {
// vnlEGo8K85u+KwIOimM48ZG8oTk7iFdkqLJR1utT3aU=
// -----END RSA PRIVATE KEY-----
//
-// and cert.pem is:
+// and certificate is:
// -----BEGIN CERTIFICATE-----
-// MIIBoDCCAUoCAQAwDQYJKoZIhvcNAQEEBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV
-// BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD
-// VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw05NzA5MDkwMzQxMjZa
-// Fw05NzEwMDkwMzQxMjZaMF4xCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0
-// YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMT
-// DkVyaWMgdGhlIFlvdW5nMFEwCQYFKw4DAgwFAANEAAJBALVEqPODnpI4rShlY8S7
-// tB713JNvabvn6Gned7zylwLLiXQAo/PAT6mfdWPTyCX9RlId/Aroh1ou893BA32Q
-// sggwDQYJKoZIhvcNAQEEBQADQQCU5SSgapJSdRXJoX+CpCvFy+JVh9HpSjCpSNKO
-// 19raHv98hKAUJuP9HyM+SUsffO6mAIgitUaqW8/wDMePhEC3
+// MIICKzCCAdWgAwIBAgIJALE1E2URIMWSMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+// BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+// aWRnaXRzIFB0eSBMdGQwHhcNMTIwNDA2MTcxMDEzWhcNMTUwNDA2MTcxMDEzWjBF
+// MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+// ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+z
+// w4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/
+// 7tdkuD8Ey2//Kv7+ue0CAwEAAaOBpzCBpDAdBgNVHQ4EFgQUeKaXmmO1xaGlM7oi
+// fCNuWxt6zCswdQYDVR0jBG4wbIAUeKaXmmO1xaGlM7oifCNuWxt6zCuhSaRHMEUx
+// CzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRl
+// cm5ldCBXaWRnaXRzIFB0eSBMdGSCCQCxNRNlESDFkjAMBgNVHRMEBTADAQH/MA0G
+// CSqGSIb3DQEBBQUAA0EAhTZAc8G7GtrUWZ8tonAxRnTsg26oyDxRrzms7EC86CJG
+// HZnWRiok1IsFCEv7NRFukrt3uuQSu/TIXpyBqJdgTA==
// -----END CERTIFICATE-----
var rc4ClientScript = [][]byte{
{
@@ -210,3 +230,163 @@ var rc4ClientScript = [][]byte{
0x59, 0xac, 0xc6, 0xb5, 0x56, 0x55, 0x96,
},
}
+
+var ecdheAESClientScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 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, 0x02, 0xc0, 0x13,
+ 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x54, 0x02, 0x00, 0x00,
+ 0x50, 0x03, 0x01, 0x4f, 0x7f, 0x24, 0x25, 0x10,
+ 0xa8, 0x9d, 0xb1, 0x33, 0xd6, 0x53, 0x81, 0xce,
+ 0xb0, 0x69, 0xed, 0x1b, 0x9c, 0x5e, 0x40, 0x3a,
+ 0x4d, 0x06, 0xbc, 0xc7, 0x84, 0x51, 0x5a, 0x30,
+ 0x40, 0x50, 0x48, 0x20, 0xcd, 0x91, 0x80, 0x08,
+ 0xff, 0x82, 0x38, 0xc6, 0x03, 0x2d, 0x45, 0x4c,
+ 0x91, 0xbb, 0xcc, 0x27, 0x3d, 0x58, 0xff, 0x0d,
+ 0x26, 0x34, 0x7b, 0x48, 0x7a, 0xce, 0x25, 0x20,
+ 0x90, 0x0f, 0x35, 0x9f, 0xc0, 0x13, 0x00, 0x00,
+ 0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
+ 0x02, 0x16, 0x03, 0x01, 0x02, 0x39, 0x0b, 0x00,
+ 0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f,
+ 0x30, 0x82, 0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5,
+ 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
+ 0xb1, 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92,
+ 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, 0x32, 0x30, 0x34, 0x30, 0x36,
+ 0x31, 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x17,
+ 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30, 0x36, 0x31,
+ 0x37, 0x31, 0x30, 0x31, 0x33, 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, 0x5c, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b,
+ 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3,
+ 0xc3, 0x84, 0x27, 0x95, 0xff, 0x12, 0x31, 0x52,
+ 0x0f, 0x15, 0xef, 0x46, 0x11, 0xc4, 0xad, 0x80,
+ 0xe6, 0x36, 0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61,
+ 0x8d, 0xe0, 0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe,
+ 0x55, 0x66, 0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a,
+ 0xfe, 0xa8, 0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff,
+ 0xee, 0xd7, 0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f,
+ 0xff, 0x2a, 0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a,
+ 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22,
+ 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97,
+ 0x9a, 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba,
+ 0x22, 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc,
+ 0x2b, 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, 0xb1,
+ 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 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, 0x41, 0x00, 0x85,
+ 0x36, 0x40, 0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4,
+ 0x59, 0x9f, 0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74,
+ 0xec, 0x83, 0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf,
+ 0x39, 0xac, 0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46,
+ 0x1d, 0x99, 0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b,
+ 0x05, 0x08, 0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92,
+ 0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8,
+ 0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16,
+ 0x03, 0x01, 0x00, 0x8b, 0x0c, 0x00, 0x00, 0x87,
+ 0x03, 0x00, 0x17, 0x41, 0x04, 0x0b, 0xe5, 0x39,
+ 0xde, 0x17, 0x7a, 0xaf, 0x96, 0xd5, 0x16, 0x01,
+ 0xa8, 0x06, 0x80, 0x98, 0x75, 0x52, 0x56, 0x92,
+ 0x15, 0xf9, 0x8d, 0xc0, 0x98, 0x62, 0xed, 0x54,
+ 0xb7, 0xef, 0x03, 0x11, 0x34, 0x82, 0x65, 0xd1,
+ 0xde, 0x25, 0x15, 0x4c, 0xf3, 0xdf, 0x4d, 0xbd,
+ 0x6c, 0xed, 0x3d, 0xd6, 0x04, 0xcc, 0xd1, 0xf7,
+ 0x6d, 0x32, 0xb1, 0x1c, 0x59, 0xca, 0xfb, 0xbc,
+ 0x61, 0xeb, 0x4b, 0xe6, 0x00, 0x00, 0x40, 0x3e,
+ 0xe6, 0x23, 0x54, 0x61, 0x3f, 0x63, 0x16, 0xeb,
+ 0x5c, 0xc3, 0xba, 0x8a, 0x19, 0x13, 0x60, 0x9f,
+ 0x23, 0xbf, 0x36, 0x1a, 0x32, 0x7a, 0xae, 0x34,
+ 0x7f, 0x2f, 0x89, 0x85, 0xe1, 0x0e, 0x93, 0xd7,
+ 0xf0, 0xab, 0xa1, 0x0d, 0x54, 0x95, 0x79, 0x0b,
+ 0xb4, 0xf1, 0x1c, 0x1d, 0x0f, 0x8c, 0x16, 0xec,
+ 0x82, 0x60, 0xee, 0xa3, 0x71, 0x2f, 0xaf, 0x3e,
+ 0xf1, 0xbd, 0xb5, 0x1b, 0x7f, 0xe0, 0xd2, 0x16,
+ 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x46, 0x10, 0x00, 0x00,
+ 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d,
+ 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5,
+ 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd,
+ 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce,
+ 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e,
+ 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56,
+ 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49,
+ 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
+ 0xdc, 0x5a, 0x89, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0x09, 0xac,
+ 0xbe, 0x94, 0x75, 0x4d, 0x73, 0x45, 0xbd, 0xa8,
+ 0x0c, 0xe3, 0x5f, 0x72, 0x0b, 0x40, 0x4f, 0xd0,
+ 0xd2, 0xcb, 0x16, 0x50, 0xfe, 0xdd, 0x1a, 0x33,
+ 0x5c, 0x18, 0x37, 0x98, 0x42, 0xfc, 0x25, 0x42,
+ 0x33, 0xce, 0x60, 0xcf, 0x8e, 0x95, 0x6e, 0x48,
+ 0xed, 0x00, 0x35, 0x50, 0x26, 0x7f,
+ },
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x30, 0xf6, 0x6a, 0xdb, 0x83, 0xd4,
+ 0x3c, 0x77, 0x52, 0xad, 0xc0, 0x0f, 0x3a, 0x2c,
+ 0x42, 0xb9, 0x60, 0x4b, 0xb2, 0xf6, 0x84, 0xfd,
+ 0x4e, 0x96, 0xfc, 0x15, 0xe7, 0x94, 0x25, 0xb0,
+ 0x59, 0x9f, 0xdd, 0xb6, 0x58, 0x03, 0x13, 0x8d,
+ 0xeb, 0xb0, 0xad, 0x30, 0x31, 0x58, 0x6c, 0xa0,
+ 0x8f, 0x57, 0x50,
+ },
+ {
+ 0x17, 0x03, 0x01, 0x00, 0x20, 0xab, 0x64, 0x3d,
+ 0x79, 0x69, 0x3e, 0xba, 0xc4, 0x24, 0x7b, 0xe5,
+ 0xe5, 0x23, 0x66, 0x6f, 0x32, 0xdf, 0x50, 0x7c,
+ 0x06, 0x2a, 0x02, 0x82, 0x79, 0x40, 0xdb, 0xb1,
+ 0x04, 0xc0, 0x2b, 0xdc, 0x3a, 0x15, 0x03, 0x01,
+ 0x00, 0x20, 0xf8, 0xad, 0xca, 0xd7, 0x96, 0xf0,
+ 0xd6, 0xa3, 0x62, 0xe1, 0x03, 0x44, 0xdb, 0xd0,
+ 0xc9, 0x63, 0x3e, 0x1b, 0x70, 0x41, 0x57, 0x0c,
+ 0xd8, 0x8e, 0x71, 0x49, 0x68, 0xe3, 0x04, 0x53,
+ 0x5a, 0xbe,
+ },
+}
diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go
index 54c7a3e6316..cdd49170777 100644
--- a/libgo/go/crypto/tls/handshake_messages.go
+++ b/libgo/go/crypto/tls/handshake_messages.go
@@ -18,6 +18,8 @@ type clientHelloMsg struct {
ocspStapling bool
supportedCurves []uint16
supportedPoints []uint8
+ ticketSupported bool
+ sessionTicket []uint8
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -36,7 +38,9 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
m.serverName == m1.serverName &&
m.ocspStapling == m1.ocspStapling &&
eqUint16s(m.supportedCurves, m1.supportedCurves) &&
- bytes.Equal(m.supportedPoints, m1.supportedPoints)
+ bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
+ m.ticketSupported == m1.ticketSupported &&
+ bytes.Equal(m.sessionTicket, m1.sessionTicket)
}
func (m *clientHelloMsg) marshal() []byte {
@@ -66,6 +70,10 @@ func (m *clientHelloMsg) marshal() []byte {
extensionsLength += 1 + len(m.supportedPoints)
numExtensions++
}
+ if m.ticketSupported {
+ extensionsLength += len(m.sessionTicket)
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -180,6 +188,17 @@ func (m *clientHelloMsg) marshal() []byte {
z = z[1:]
}
}
+ if m.ticketSupported {
+ // http://tools.ietf.org/html/rfc5077#section-3.2
+ z[0] = byte(extensionSessionTicket >> 8)
+ z[1] = byte(extensionSessionTicket)
+ l := len(m.sessionTicket)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ z = z[4:]
+ copy(z, m.sessionTicket)
+ z = z[len(m.sessionTicket):]
+ }
m.raw = x
@@ -228,6 +247,8 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.nextProtoNeg = false
m.serverName = ""
m.ocspStapling = false
+ m.ticketSupported = false
+ m.sessionTicket = nil
if len(data) == 0 {
// ClientHello is optionally followed by extension data
@@ -311,6 +332,10 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
}
m.supportedPoints = make([]uint8, l)
copy(m.supportedPoints, data[1:])
+ case extensionSessionTicket:
+ // http://tools.ietf.org/html/rfc5077#section-3.2
+ m.ticketSupported = true
+ m.sessionTicket = data[:length]
}
data = data[length:]
}
@@ -328,6 +353,7 @@ type serverHelloMsg struct {
nextProtoNeg bool
nextProtos []string
ocspStapling bool
+ ticketSupported bool
}
func (m *serverHelloMsg) equal(i interface{}) bool {
@@ -344,7 +370,8 @@ func (m *serverHelloMsg) equal(i interface{}) bool {
m.compressionMethod == m1.compressionMethod &&
m.nextProtoNeg == m1.nextProtoNeg &&
eqStrings(m.nextProtos, m1.nextProtos) &&
- m.ocspStapling == m1.ocspStapling
+ m.ocspStapling == m1.ocspStapling &&
+ m.ticketSupported == m1.ticketSupported
}
func (m *serverHelloMsg) marshal() []byte {
@@ -368,6 +395,9 @@ func (m *serverHelloMsg) marshal() []byte {
if m.ocspStapling {
numExtensions++
}
+ if m.ticketSupported {
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -416,6 +446,11 @@ func (m *serverHelloMsg) marshal() []byte {
z[1] = byte(extensionStatusRequest)
z = z[4:]
}
+ if m.ticketSupported {
+ z[0] = byte(extensionSessionTicket >> 8)
+ z[1] = byte(extensionSessionTicket)
+ z = z[4:]
+ }
m.raw = x
@@ -445,6 +480,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.nextProtoNeg = false
m.nextProtos = nil
m.ocspStapling = false
+ m.ticketSupported = false
if len(data) == 0 {
// ServerHello is optionally followed by extension data
@@ -474,14 +510,14 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
switch extension {
case extensionNextProtoNeg:
m.nextProtoNeg = true
- d := data
+ d := data[:length]
for len(d) > 0 {
l := int(d[0])
d = d[1:]
if l == 0 || l > len(d) {
return false
}
- m.nextProtos = append(m.nextProtos, string(d[0:l]))
+ m.nextProtos = append(m.nextProtos, string(d[:l]))
d = d[l:]
}
case extensionStatusRequest:
@@ -489,6 +525,11 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
return false
}
m.ocspStapling = true
+ case extensionSessionTicket:
+ if length > 0 {
+ return false
+ }
+ m.ticketSupported = true
}
data = data[length:]
}
@@ -1030,6 +1071,65 @@ func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
return true
}
+type newSessionTicketMsg struct {
+ raw []byte
+ ticket []byte
+}
+
+func (m *newSessionTicketMsg) equal(i interface{}) bool {
+ m1, ok := i.(*newSessionTicketMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.ticket, m1.ticket)
+}
+
+func (m *newSessionTicketMsg) marshal() (x []byte) {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ // See http://tools.ietf.org/html/rfc5077#section-3.3
+ ticketLen := len(m.ticket)
+ length := 2 + 4 + ticketLen
+ x = make([]byte, 4+length)
+ x[0] = typeNewSessionTicket
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ x[8] = uint8(ticketLen >> 8)
+ x[9] = uint8(ticketLen)
+ copy(x[10:], m.ticket)
+
+ m.raw = x
+
+ return
+}
+
+func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
+ m.raw = data
+
+ if len(data) < 10 {
+ return false
+ }
+
+ length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+ if uint32(len(data))-4 != length {
+ return false
+ }
+
+ ticketLen := int(data[8])<<8 + int(data[9])
+ if len(data)-10 != ticketLen {
+ return false
+ }
+
+ m.ticket = data[10:]
+
+ return true
+}
+
func eqUint16s(x, y []uint16) bool {
if len(x) != len(y) {
return false
diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go
index e62a9d581b3..3434bad9fba 100644
--- a/libgo/go/crypto/tls/handshake_messages_test.go
+++ b/libgo/go/crypto/tls/handshake_messages_test.go
@@ -22,6 +22,8 @@ var tests = []interface{}{
&certificateStatusMsg{},
&clientKeyExchangeMsg{},
&nextProtoMsg{},
+ &newSessionTicketMsg{},
+ &sessionState{},
}
type testMessage interface {
@@ -127,6 +129,12 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
for i := range m.supportedCurves {
m.supportedCurves[i] = uint16(rand.Intn(30000))
}
+ if rand.Intn(10) > 5 {
+ m.ticketSupported = true
+ if rand.Intn(10) > 5 {
+ m.sessionTicket = randomBytes(rand.Intn(300), rand)
+ }
+ }
return reflect.ValueOf(m)
}
@@ -149,6 +157,13 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
}
}
+ if rand.Intn(10) > 5 {
+ m.ocspStapling = true
+ }
+ if rand.Intn(10) > 5 {
+ m.ticketSupported = true
+ }
+
return reflect.ValueOf(m)
}
@@ -207,3 +222,22 @@ func (*nextProtoMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m.proto = randomString(rand.Intn(255), rand)
return reflect.ValueOf(m)
}
+
+func (*newSessionTicketMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+ m := &newSessionTicketMsg{}
+ m.ticket = randomBytes(rand.Intn(4), rand)
+ return reflect.ValueOf(m)
+}
+
+func (*sessionState) Generate(rand *rand.Rand, size int) reflect.Value {
+ s := &sessionState{}
+ s.vers = uint16(rand.Intn(10000))
+ s.cipherSuite = uint16(rand.Intn(10000))
+ s.masterSecret = randomBytes(rand.Intn(100), rand)
+ numCerts := rand.Intn(20)
+ s.certificates = make([][]byte, numCerts)
+ for i := 0; i < numCerts; i++ {
+ s.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
+ }
+ return reflect.ValueOf(s)
+}
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go
index 76adc540c71..d8410345020 100644
--- a/libgo/go/crypto/tls/handshake_server.go
+++ b/libgo/go/crypto/tls/handshake_server.go
@@ -13,31 +13,120 @@ import (
"io"
)
+// serverHandshakeState contains details of a server handshake in progress.
+// It's discarded once the handshake has completed.
+type serverHandshakeState struct {
+ c *Conn
+ clientHello *clientHelloMsg
+ hello *serverHelloMsg
+ suite *cipherSuite
+ ellipticOk bool
+ sessionState *sessionState
+ finishedHash finishedHash
+ masterSecret []byte
+ certsFromClient [][]byte
+}
+
+// serverHandshake performs a TLS handshake as a server.
func (c *Conn) serverHandshake() error {
config := c.config
- msg, err := c.readHandshake()
+
+ // If this is the first server handshake, we generate a random key to
+ // encrypt the tickets with.
+ config.serverInitOnce.Do(func() {
+ if config.SessionTicketsDisabled {
+ return
+ }
+
+ // If the key has already been set then we have nothing to do.
+ for _, b := range config.SessionTicketKey {
+ if b != 0 {
+ return
+ }
+ }
+
+ if _, err := io.ReadFull(config.rand(), config.SessionTicketKey[:]); err != nil {
+ config.SessionTicketsDisabled = true
+ }
+ })
+
+ hs := serverHandshakeState{
+ c: c,
+ }
+ isResume, err := hs.readClientHello()
if err != nil {
return err
}
- clientHello, ok := msg.(*clientHelloMsg)
+
+ // For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
+ if isResume {
+ // The client has included a session ticket and so we do an abbreviated handshake.
+ if err := hs.doResumeHandshake(); err != nil {
+ return err
+ }
+ if err := hs.establishKeys(); err != nil {
+ return err
+ }
+ if err := hs.sendFinished(); err != nil {
+ return err
+ }
+ if err := hs.readFinished(); err != nil {
+ return err
+ }
+ c.didResume = true
+ } else {
+ // The client didn't include a session ticket, or it wasn't
+ // valid so we do a full handshake.
+ if err := hs.doFullHandshake(); err != nil {
+ return err
+ }
+ if err := hs.establishKeys(); err != nil {
+ return err
+ }
+ if err := hs.readFinished(); err != nil {
+ return err
+ }
+ if err := hs.sendSessionTicket(); err != nil {
+ return err
+ }
+ if err := hs.sendFinished(); err != nil {
+ return err
+ }
+ }
+ c.handshakeComplete = true
+
+ return nil
+}
+
+// readClientHello reads a ClientHello message from the client and decides
+// whether we will perform session resumption.
+func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
+ config := hs.c.config
+ c := hs.c
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return false, err
+ }
+ var ok bool
+ hs.clientHello, ok = msg.(*clientHelloMsg)
if !ok {
- return c.sendAlert(alertUnexpectedMessage)
+ return false, c.sendAlert(alertUnexpectedMessage)
}
- vers, ok := mutualVersion(clientHello.vers)
+ c.vers, ok = mutualVersion(hs.clientHello.vers)
if !ok {
- return c.sendAlert(alertProtocolVersion)
+ return false, c.sendAlert(alertProtocolVersion)
}
- c.vers = vers
c.haveVers = true
- finishedHash := newFinishedHash(vers)
- finishedHash.Write(clientHello.marshal())
+ hs.finishedHash = newFinishedHash(c.vers)
+ hs.finishedHash.Write(hs.clientHello.marshal())
- hello := new(serverHelloMsg)
+ hs.hello = new(serverHelloMsg)
supportedCurve := false
Curves:
- for _, curve := range clientHello.supportedCurves {
+ for _, curve := range hs.clientHello.supportedCurves {
switch curve {
case curveP256, curveP384, curveP521:
supportedCurve = true
@@ -46,110 +135,173 @@ Curves:
}
supportedPointFormat := false
- for _, pointFormat := range clientHello.supportedPoints {
+ for _, pointFormat := range hs.clientHello.supportedPoints {
if pointFormat == pointFormatUncompressed {
supportedPointFormat = true
break
}
}
-
- ellipticOk := supportedCurve && supportedPointFormat
-
- var suite *cipherSuite
-FindCipherSuite:
- for _, id := range clientHello.cipherSuites {
- for _, supported := range config.cipherSuites() {
- if id == supported {
- var candidate *cipherSuite
-
- for _, s := range cipherSuites {
- if s.id == id {
- candidate = s
- break
- }
- }
- if candidate == nil {
- continue
- }
- // Don't select a ciphersuite which we can't
- // support for this client.
- if candidate.elliptic && !ellipticOk {
- continue
- }
- suite = candidate
- break FindCipherSuite
- }
- }
- }
+ hs.ellipticOk = supportedCurve && supportedPointFormat
foundCompression := false
// We only support null compression, so check that the client offered it.
- for _, compression := range clientHello.compressionMethods {
+ for _, compression := range hs.clientHello.compressionMethods {
if compression == compressionNone {
foundCompression = true
break
}
}
- if suite == nil || !foundCompression {
- return c.sendAlert(alertHandshakeFailure)
+ if !foundCompression {
+ return false, c.sendAlert(alertHandshakeFailure)
}
- hello.vers = vers
- hello.cipherSuite = suite.id
+ hs.hello.vers = c.vers
t := uint32(config.time().Unix())
- hello.random = make([]byte, 32)
- hello.random[0] = byte(t >> 24)
- hello.random[1] = byte(t >> 16)
- hello.random[2] = byte(t >> 8)
- hello.random[3] = byte(t)
- _, err = io.ReadFull(config.rand(), hello.random[4:])
+ hs.hello.random = make([]byte, 32)
+ hs.hello.random[0] = byte(t >> 24)
+ hs.hello.random[1] = byte(t >> 16)
+ hs.hello.random[2] = byte(t >> 8)
+ hs.hello.random[3] = byte(t)
+ _, err = io.ReadFull(config.rand(), hs.hello.random[4:])
if err != nil {
- return c.sendAlert(alertInternalError)
+ return false, c.sendAlert(alertInternalError)
+ }
+ hs.hello.compressionMethod = compressionNone
+ if len(hs.clientHello.serverName) > 0 {
+ c.serverName = hs.clientHello.serverName
+ }
+ if hs.clientHello.nextProtoNeg {
+ hs.hello.nextProtoNeg = true
+ hs.hello.nextProtos = config.NextProtos
+ }
+
+ if hs.checkForResumption() {
+ return true, nil
+ }
+
+ for _, id := range hs.clientHello.cipherSuites {
+ if hs.suite = c.tryCipherSuite(id, hs.ellipticOk); hs.suite != nil {
+ break
+ }
+ }
+
+ if hs.suite == nil {
+ return false, c.sendAlert(alertHandshakeFailure)
+ }
+
+ return false, nil
+}
+
+// checkForResumption returns true if we should perform resumption on this connection.
+func (hs *serverHandshakeState) checkForResumption() bool {
+ c := hs.c
+
+ var ok bool
+ if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
+ return false
+ }
+
+ if hs.sessionState.vers > hs.clientHello.vers {
+ return false
+ }
+ if vers, ok := mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
+ return false
+ }
+
+ cipherSuiteOk := false
+ // Check that the client is still offering the ciphersuite in the session.
+ for _, id := range hs.clientHello.cipherSuites {
+ if id == hs.sessionState.cipherSuite {
+ cipherSuiteOk = true
+ break
+ }
}
- hello.compressionMethod = compressionNone
- if clientHello.nextProtoNeg {
- hello.nextProtoNeg = true
- hello.nextProtos = config.NextProtos
+ if !cipherSuiteOk {
+ return false
}
+ // Check that we also support the ciphersuite from the session.
+ hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, hs.ellipticOk)
+ if hs.suite == nil {
+ return false
+ }
+
+ sessionHasClientCerts := len(hs.sessionState.certificates) != 0
+ needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
+ if needClientCerts && !sessionHasClientCerts {
+ return false
+ }
+ if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
+ return false
+ }
+
+ return true
+}
+
+func (hs *serverHandshakeState) doResumeHandshake() error {
+ c := hs.c
+
+ hs.hello.cipherSuite = hs.suite.id
+ // We echo the client's session ID in the ServerHello to let it know
+ // that we're doing a resumption.
+ hs.hello.sessionId = hs.clientHello.sessionId
+ hs.finishedHash.Write(hs.hello.marshal())
+ c.writeRecord(recordTypeHandshake, hs.hello.marshal())
+
+ if len(hs.sessionState.certificates) > 0 {
+ if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
+ return err
+ }
+ }
+
+ hs.masterSecret = hs.sessionState.masterSecret
+
+ return nil
+}
+
+func (hs *serverHandshakeState) doFullHandshake() error {
+ config := hs.c.config
+ c := hs.c
+
if len(config.Certificates) == 0 {
return c.sendAlert(alertInternalError)
}
cert := &config.Certificates[0]
- if len(clientHello.serverName) > 0 {
- c.serverName = clientHello.serverName
- cert = config.getCertificateForName(clientHello.serverName)
+ if len(hs.clientHello.serverName) > 0 {
+ cert = config.getCertificateForName(hs.clientHello.serverName)
}
- if clientHello.ocspStapling && len(cert.OCSPStaple) > 0 {
- hello.ocspStapling = true
+ if hs.clientHello.ocspStapling && len(cert.OCSPStaple) > 0 {
+ hs.hello.ocspStapling = true
}
- finishedHash.Write(hello.marshal())
- c.writeRecord(recordTypeHandshake, hello.marshal())
+ hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled
+ hs.hello.cipherSuite = hs.suite.id
+ hs.finishedHash.Write(hs.hello.marshal())
+ c.writeRecord(recordTypeHandshake, hs.hello.marshal())
certMsg := new(certificateMsg)
certMsg.certificates = cert.Certificate
- finishedHash.Write(certMsg.marshal())
+ hs.finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
- if hello.ocspStapling {
+ if hs.hello.ocspStapling {
certStatus := new(certificateStatusMsg)
certStatus.statusType = statusTypeOCSP
certStatus.response = cert.OCSPStaple
- finishedHash.Write(certStatus.marshal())
+ hs.finishedHash.Write(certStatus.marshal())
c.writeRecord(recordTypeHandshake, certStatus.marshal())
}
- keyAgreement := suite.ka()
- skx, err := keyAgreement.generateServerKeyExchange(config, cert, clientHello, hello)
+ keyAgreement := hs.suite.ka()
+ skx, err := keyAgreement.generateServerKeyExchange(config, cert, hs.clientHello, hs.hello)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
}
if skx != nil {
- finishedHash.Write(skx.marshal())
+ hs.finishedHash.Write(skx.marshal())
c.writeRecord(recordTypeHandshake, skx.marshal())
}
@@ -166,28 +318,29 @@ FindCipherSuite:
if config.ClientCAs != nil {
certReq.certificateAuthorities = config.ClientCAs.Subjects()
}
- finishedHash.Write(certReq.marshal())
+ hs.finishedHash.Write(certReq.marshal())
c.writeRecord(recordTypeHandshake, certReq.marshal())
}
helloDone := new(serverHelloDoneMsg)
- finishedHash.Write(helloDone.marshal())
+ hs.finishedHash.Write(helloDone.marshal())
c.writeRecord(recordTypeHandshake, helloDone.marshal())
var pub *rsa.PublicKey // public key for client auth, if any
- msg, err = c.readHandshake()
+ msg, err := c.readHandshake()
if err != nil {
return err
}
+ var ok bool
// If we requested a client certificate, then the client must send a
// certificate message, even if it's empty.
if config.ClientAuth >= RequestClientCert {
if certMsg, ok = msg.(*certificateMsg); !ok {
return c.sendAlert(alertHandshakeFailure)
}
- finishedHash.Write(certMsg.marshal())
+ hs.finishedHash.Write(certMsg.marshal())
if len(certMsg.certificates) == 0 {
// The client didn't actually send a certificate
@@ -198,54 +351,9 @@ FindCipherSuite:
}
}
- certs := make([]*x509.Certificate, len(certMsg.certificates))
- for i, asn1Data := range certMsg.certificates {
- if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
- c.sendAlert(alertBadCertificate)
- return errors.New("tls: failed to parse client certificate: " + err.Error())
- }
- }
-
- if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
- opts := x509.VerifyOptions{
- Roots: c.config.ClientCAs,
- CurrentTime: c.config.time(),
- Intermediates: x509.NewCertPool(),
- }
-
- for i, cert := range certs {
- if i == 0 {
- continue
- }
- opts.Intermediates.AddCert(cert)
- }
-
- chains, err := certs[0].Verify(opts)
- if err != nil {
- c.sendAlert(alertBadCertificate)
- return errors.New("tls: failed to verify client's certificate: " + err.Error())
- }
-
- ok := false
- for _, ku := range certs[0].ExtKeyUsage {
- if ku == x509.ExtKeyUsageClientAuth {
- ok = true
- break
- }
- }
- if !ok {
- c.sendAlert(alertHandshakeFailure)
- return errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
- }
-
- c.verifiedChains = chains
- }
-
- if len(certs) > 0 {
- if pub, ok = certs[0].PublicKey.(*rsa.PublicKey); !ok {
- return c.sendAlert(alertUnsupportedCertificate)
- }
- c.peerCertificates = certs
+ pub, err = hs.processCertsFromClient(certMsg.certificates)
+ if err != nil {
+ return err
}
msg, err = c.readHandshake()
@@ -259,7 +367,7 @@ FindCipherSuite:
if !ok {
return c.sendAlert(alertUnexpectedMessage)
}
- finishedHash.Write(ckx.marshal())
+ hs.finishedHash.Write(ckx.marshal())
// If we received a client cert in response to our certificate request message,
// the client will send us a certificateVerifyMsg immediately after the
@@ -278,15 +386,15 @@ FindCipherSuite:
}
digest := make([]byte, 0, 36)
- digest = finishedHash.serverMD5.Sum(digest)
- digest = finishedHash.serverSHA1.Sum(digest)
+ digest = hs.finishedHash.serverMD5.Sum(digest)
+ digest = hs.finishedHash.serverSHA1.Sum(digest)
err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
if err != nil {
c.sendAlert(alertBadCertificate)
return errors.New("could not validate signature of connection nonces: " + err.Error())
}
- finishedHash.Write(certVerify.marshal())
+ hs.finishedHash.Write(certVerify.marshal())
}
preMasterSecret, err := keyAgreement.processClientKeyExchange(config, cert, ckx, c.vers)
@@ -294,20 +402,38 @@ FindCipherSuite:
c.sendAlert(alertHandshakeFailure)
return err
}
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, preMasterSecret, hs.clientHello.random, hs.hello.random)
+
+ return nil
+}
+
+func (hs *serverHandshakeState) establishKeys() error {
+ c := hs.c
- masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
- keysFromPreMasterSecret(c.vers, preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
+ clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+ keysFromMasterSecret(c.vers, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
- clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */)
- clientHash := suite.mac(c.vers, clientMAC)
+ clientCipher := hs.suite.cipher(clientKey, clientIV, true /* for reading */)
+ clientHash := hs.suite.mac(c.vers, clientMAC)
c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
+
+ serverCipher := hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
+ serverHash := hs.suite.mac(c.vers, serverMAC)
+ c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
+
+ return nil
+}
+
+func (hs *serverHandshakeState) readFinished() error {
+ c := hs.c
+
c.readRecord(recordTypeChangeCipherSpec)
if err := c.error(); err != nil {
return err
}
- if hello.nextProtoNeg {
- msg, err = c.readHandshake()
+ if hs.hello.nextProtoNeg {
+ msg, err := c.readHandshake()
if err != nil {
return err
}
@@ -315,11 +441,11 @@ FindCipherSuite:
if !ok {
return c.sendAlert(alertUnexpectedMessage)
}
- finishedHash.Write(nextProto.marshal())
+ hs.finishedHash.Write(nextProto.marshal())
c.clientProtocol = nextProto.proto
}
- msg, err = c.readHandshake()
+ msg, err := c.readHandshake()
if err != nil {
return err
}
@@ -328,25 +454,142 @@ FindCipherSuite:
return c.sendAlert(alertUnexpectedMessage)
}
- verify := finishedHash.clientSum(masterSecret)
+ verify := hs.finishedHash.clientSum(hs.masterSecret)
if len(verify) != len(clientFinished.verifyData) ||
subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
return c.sendAlert(alertHandshakeFailure)
}
- finishedHash.Write(clientFinished.marshal())
+ hs.finishedHash.Write(clientFinished.marshal())
+ return nil
+}
+
+func (hs *serverHandshakeState) sendSessionTicket() error {
+ if !hs.hello.ticketSupported {
+ return nil
+ }
+
+ c := hs.c
+ m := new(newSessionTicketMsg)
+
+ var err error
+ state := sessionState{
+ vers: c.vers,
+ cipherSuite: hs.suite.id,
+ masterSecret: hs.masterSecret,
+ certificates: hs.certsFromClient,
+ }
+ m.ticket, err = c.encryptTicket(&state)
+ if err != nil {
+ return err
+ }
+
+ hs.finishedHash.Write(m.marshal())
+ c.writeRecord(recordTypeHandshake, m.marshal())
+
+ return nil
+}
+
+func (hs *serverHandshakeState) sendFinished() error {
+ c := hs.c
- serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */)
- serverHash := suite.mac(c.vers, serverMAC)
- c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
finished := new(finishedMsg)
- finished.verifyData = finishedHash.serverSum(masterSecret)
+ finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
+ hs.finishedHash.Write(finished.marshal())
c.writeRecord(recordTypeHandshake, finished.marshal())
- c.handshakeComplete = true
- c.cipherSuite = suite.id
+ c.cipherSuite = hs.suite.id
+
+ return nil
+}
+
+// processCertsFromClient takes a chain of client certificates either from a
+// Certificates message or from a sessionState and verifies them. It returns
+// the public key of the leaf certificate.
+func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (*rsa.PublicKey, error) {
+ c := hs.c
+
+ hs.certsFromClient = certificates
+ certs := make([]*x509.Certificate, len(certificates))
+ var err error
+ for i, asn1Data := range certificates {
+ if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
+ c.sendAlert(alertBadCertificate)
+ return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
+ }
+ }
+
+ if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
+ opts := x509.VerifyOptions{
+ Roots: c.config.ClientCAs,
+ CurrentTime: c.config.time(),
+ Intermediates: x509.NewCertPool(),
+ KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
+ }
+
+ for _, cert := range certs[1:] {
+ opts.Intermediates.AddCert(cert)
+ }
+
+ chains, err := certs[0].Verify(opts)
+ if err != nil {
+ c.sendAlert(alertBadCertificate)
+ return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
+ }
+
+ ok := false
+ for _, ku := range certs[0].ExtKeyUsage {
+ if ku == x509.ExtKeyUsageClientAuth {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ c.sendAlert(alertHandshakeFailure)
+ return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
+ }
+
+ c.verifiedChains = chains
+ }
+
+ if len(certs) > 0 {
+ pub, ok := certs[0].PublicKey.(*rsa.PublicKey)
+ if !ok {
+ return nil, c.sendAlert(alertUnsupportedCertificate)
+ }
+ c.peerCertificates = certs
+ return pub, nil
+ }
+
+ return nil, nil
+}
+
+// tryCipherSuite returns a cipherSuite with the given id if that cipher suite
+// is acceptable to use.
+func (c *Conn) tryCipherSuite(id uint16, ellipticOk bool) *cipherSuite {
+ for _, supported := range c.config.cipherSuites() {
+ if id == supported {
+ var candidate *cipherSuite
+
+ for _, s := range cipherSuites {
+ if s.id == id {
+ candidate = s
+ break
+ }
+ }
+ if candidate == nil {
+ continue
+ }
+ // Don't select a ciphersuite which we can't
+ // support for this client.
+ if candidate.elliptic && !ellipticOk {
+ continue
+ }
+ return candidate
+ }
+ }
return nil
}
diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go
index 7c1267101cf..8ca3c2cf191 100644
--- a/libgo/go/crypto/tls/handshake_server_test.go
+++ b/libgo/go/crypto/tls/handshake_server_test.go
@@ -11,12 +11,15 @@ import (
"encoding/hex"
"encoding/pem"
"flag"
+ "fmt"
"io"
"log"
"math/big"
"net"
+ "os"
"strconv"
"strings"
+ "sync"
"testing"
"time"
)
@@ -80,13 +83,20 @@ func TestRejectBadProtocolVersion(t *testing.T) {
}
func TestNoSuiteOverlap(t *testing.T) {
- clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{0xff00}, []uint8{0}, false, "", false, nil, nil}
+ clientHello := &clientHelloMsg{
+ vers: 0x0301,
+ cipherSuites: []uint16{0xff00},
+ compressionMethods: []uint8{0},
+ }
testClientHelloFailure(t, clientHello, alertHandshakeFailure)
-
}
func TestNoCompressionOverlap(t *testing.T) {
- clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{TLS_RSA_WITH_RC4_128_SHA}, []uint8{0xff}, false, "", false, nil, nil}
+ clientHello := &clientHelloMsg{
+ vers: 0x0301,
+ cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ compressionMethods: []uint8{0xff},
+ }
testClientHelloFailure(t, clientHello, alertHandshakeFailure)
}
@@ -186,6 +196,11 @@ func TestHandshakeServerSNI(t *testing.T) {
testServerScript(t, "SNI", selectCertificateBySNIScript, testConfig, nil)
}
+func TestResumption(t *testing.T) {
+ testServerScript(t, "IssueTicket", issueSessionTicketTest, testConfig, nil)
+ testServerScript(t, "Resume", serverResumeTest, testConfig, nil)
+}
+
type clientauthTest struct {
name string
clientauth ClientAuthType
@@ -203,55 +218,133 @@ func TestClientAuth(t *testing.T) {
}
}
+// recordingConn is a net.Conn that records the traffic that passes through it.
+// WriteTo can be used to produce Go code that contains the recorded traffic.
+type recordingConn struct {
+ net.Conn
+ lock sync.Mutex
+ flows [][]byte
+ currentlyReading bool
+}
+
+func (r *recordingConn) Read(b []byte) (n int, err error) {
+ if n, err = r.Conn.Read(b); n == 0 {
+ return
+ }
+ b = b[:n]
+
+ r.lock.Lock()
+ defer r.lock.Unlock()
+
+ if l := len(r.flows); l == 0 || !r.currentlyReading {
+ buf := make([]byte, len(b))
+ copy(buf, b)
+ r.flows = append(r.flows, buf)
+ } else {
+ r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+ }
+ r.currentlyReading = true
+ return
+}
+
+func (r *recordingConn) Write(b []byte) (n int, err error) {
+ if n, err = r.Conn.Write(b); n == 0 {
+ return
+ }
+ b = b[:n]
+
+ r.lock.Lock()
+ defer r.lock.Unlock()
+
+ if l := len(r.flows); l == 0 || r.currentlyReading {
+ buf := make([]byte, len(b))
+ copy(buf, b)
+ r.flows = append(r.flows, buf)
+ } else {
+ r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+ }
+ r.currentlyReading = false
+ return
+}
+
+// WriteTo writes Go source code to w that contains the recorded traffic.
+func (r *recordingConn) WriteTo(w io.Writer) {
+ fmt.Fprintf(w, "var changeMe = [][]byte {\n")
+ for _, buf := range r.flows {
+ fmt.Fprintf(w, "\t{")
+ for i, b := range buf {
+ if i%8 == 0 {
+ fmt.Fprintf(w, "\n\t\t")
+ }
+ fmt.Fprintf(w, "0x%02x, ", b)
+ }
+ fmt.Fprintf(w, "\n\t},\n")
+ }
+ fmt.Fprintf(w, "}\n")
+}
+
var serve = flag.Bool("serve", false, "run a TLS server on :10443")
var testCipherSuites = flag.String("ciphersuites",
"0x"+strconv.FormatInt(int64(TLS_RSA_WITH_RC4_128_SHA), 16),
"cipher suites to accept in serving mode")
var testClientAuth = flag.Int("clientauth", 0, "value for tls.Config.ClientAuth")
-func TestRunServer(t *testing.T) {
- if !*serve {
- return
- }
-
+func GetTestConfig() *Config {
+ var config = *testConfig
suites := strings.Split(*testCipherSuites, ",")
- testConfig.CipherSuites = make([]uint16, len(suites))
+ config.CipherSuites = make([]uint16, len(suites))
for i := range suites {
suite, err := strconv.ParseUint(suites[i], 0, 64)
if err != nil {
panic(err)
}
- testConfig.CipherSuites[i] = uint16(suite)
+ config.CipherSuites[i] = uint16(suite)
}
- testConfig.ClientAuth = ClientAuthType(*testClientAuth)
+ config.ClientAuth = ClientAuthType(*testClientAuth)
+ return &config
+}
- l, err := Listen("tcp", ":10443", testConfig)
+func TestRunServer(t *testing.T) {
+ if !*serve {
+ return
+ }
+
+ config := GetTestConfig()
+
+ const addr = ":10443"
+ l, err := net.Listen("tcp", addr)
if err != nil {
t.Fatal(err)
}
+ log.Printf("Now listening for connections on %s", addr)
for {
- c, err := l.Accept()
+ tcpConn, err := l.Accept()
if err != nil {
+ log.Printf("error accepting connection: %s", err)
+ break
+ }
+
+ record := &recordingConn{
+ Conn: tcpConn,
+ }
+
+ conn := Server(record, config)
+ if err := conn.Handshake(); err != nil {
log.Printf("error from TLS handshake: %s", err)
break
}
- _, err = c.Write([]byte("hello, world\n"))
+ _, err = conn.Write([]byte("hello, world\n"))
if err != nil {
- log.Printf("error from TLS: %s", err)
+ log.Printf("error from Write: %s", err)
continue
}
- st := c.(*Conn).ConnectionState()
- if len(st.PeerCertificates) > 0 {
- log.Print("Handling request from client ", st.PeerCertificates[0].Subject.CommonName)
- } else {
- log.Print("Handling request from anon client")
- }
+ conn.Close()
- c.Close()
+ record.WriteTo(os.Stdout)
}
}
@@ -296,10 +389,8 @@ func loadPEMCert(in string) *x509.Certificate {
// Script of interaction with gnutls implementation.
// The values for this test are obtained by building and running in server mode:
-// % go test -run "TestRunServer" -serve
-// and then:
-// % gnutls-cli --insecure --debug 100 -p 10443 localhost > /tmp/log 2>&1
-// % python parse-gnutls-cli-debug-log.py < /tmp/log
+// % go test -test.run "TestRunServer" -serve
+// The recorded bytes are written to stdout.
var rc4ServerScript = [][]byte{
{
0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
@@ -961,21 +1052,37 @@ var sslv3ServerScript = [][]byte{
var selectCertificateBySNIScript = [][]byte{
{
- 0x16, 0x03, 0x01, 0x00, 0x6e, 0x01, 0x00, 0x00,
- 0x6a, 0x03, 0x01, 0x4f, 0x85, 0xc4, 0xc2, 0xb9,
- 0x39, 0x80, 0x91, 0x66, 0x65, 0x56, 0x8e, 0xdd,
- 0x48, 0xe9, 0xca, 0x34, 0x02, 0x3c, 0xaf, 0x0d,
- 0x73, 0xb5, 0x2a, 0x05, 0x6e, 0xbd, 0x5e, 0x8f,
- 0x38, 0xf9, 0xe5, 0x00, 0x00, 0x28, 0x00, 0x39,
- 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
- 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
- 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
- 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
- 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
- 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x0e, 0x00, 0x00, 0x0b, 0x73, 0x6e, 0x69, 0x74,
- 0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x00,
- 0x23, 0x00, 0x00,
+ 0x16, 0x03, 0x01, 0x00, 0xed, 0x01, 0x00, 0x00,
+ 0xe9, 0x03, 0x02, 0x50, 0x5a, 0x1c, 0x90, 0x2b,
+ 0xc8, 0xf1, 0xd9, 0x4b, 0xd0, 0x18, 0x69, 0xed,
+ 0x5a, 0xbd, 0x68, 0xf6, 0xf7, 0xe3, 0xf0, 0x6e,
+ 0xd1, 0xcc, 0xf1, 0x2d, 0x94, 0xa4, 0x01, 0x63,
+ 0x91, 0xbe, 0xd0, 0x00, 0x00, 0x66, 0xc0, 0x14,
+ 0xc0, 0x0a, 0xc0, 0x22, 0xc0, 0x21, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x88, 0x00, 0x87, 0xc0, 0x0f,
+ 0xc0, 0x05, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x12,
+ 0xc0, 0x08, 0xc0, 0x1c, 0xc0, 0x1b, 0x00, 0x16,
+ 0x00, 0x13, 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a,
+ 0xc0, 0x13, 0xc0, 0x09, 0xc0, 0x1f, 0xc0, 0x1e,
+ 0x00, 0x33, 0x00, 0x32, 0x00, 0x9a, 0x00, 0x99,
+ 0x00, 0x45, 0x00, 0x44, 0xc0, 0x0e, 0xc0, 0x04,
+ 0x00, 0x2f, 0x00, 0x96, 0x00, 0x41, 0xc0, 0x11,
+ 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02, 0x00, 0x05,
+ 0x00, 0x04, 0x00, 0x15, 0x00, 0x12, 0x00, 0x09,
+ 0x00, 0x14, 0x00, 0x11, 0x00, 0x08, 0x00, 0x06,
+ 0x00, 0x03, 0x00, 0xff, 0x02, 0x01, 0x00, 0x00,
+ 0x59, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0e, 0x00,
+ 0x00, 0x0b, 0x73, 0x6e, 0x69, 0x74, 0x65, 0x73,
+ 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x0b, 0x00,
+ 0x04, 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, 0x00,
+ 0x34, 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18, 0x00,
+ 0x09, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, 0x00,
+ 0x15, 0x00, 0x04, 0x00, 0x05, 0x00, 0x12, 0x00,
+ 0x13, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00,
+ 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x0f, 0x00,
+ 0x01, 0x01,
},
{
0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
@@ -1053,45 +1160,323 @@ var selectCertificateBySNIScript = [][]byte{
},
{
0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
- 0x82, 0x00, 0x80, 0x70, 0x1d, 0x34, 0x75, 0xa2,
- 0xe7, 0xe3, 0x2f, 0x3d, 0xc1, 0x1d, 0xca, 0x0b,
- 0xe3, 0x64, 0xb9, 0x1a, 0x00, 0x69, 0xc4, 0x14,
- 0x05, 0x07, 0x7e, 0xc3, 0x51, 0x43, 0x52, 0x66,
- 0xe3, 0xbd, 0xff, 0x1b, 0x1a, 0x6a, 0x84, 0xf2,
- 0x07, 0x24, 0xd7, 0x12, 0xa8, 0x58, 0xcf, 0x8a,
- 0x50, 0x30, 0xe8, 0xc8, 0xb2, 0xf9, 0x58, 0x1c,
- 0x56, 0x53, 0x76, 0x21, 0xe0, 0x03, 0x7f, 0x77,
- 0xa7, 0xf1, 0xad, 0x67, 0xd4, 0xe2, 0x8f, 0xa0,
- 0x58, 0x6c, 0xe0, 0x28, 0x59, 0xf3, 0xd1, 0x53,
- 0x2b, 0x21, 0xbd, 0xa3, 0x84, 0x31, 0x73, 0xbf,
- 0x84, 0x0f, 0x83, 0xf4, 0xc4, 0xd0, 0xe5, 0x3c,
- 0x2d, 0x3e, 0xf2, 0x8a, 0x1e, 0xe7, 0xe9, 0x1f,
- 0x12, 0x13, 0xad, 0x29, 0xd6, 0x0c, 0xc7, 0xc6,
- 0x05, 0x53, 0x7d, 0x5e, 0xc6, 0x92, 0x72, 0xba,
- 0xd2, 0x93, 0x8f, 0x53, 0x84, 0x87, 0x44, 0x05,
- 0x9f, 0x5d, 0x66, 0x14, 0x03, 0x01, 0x00, 0x01,
- 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xfc, 0x71,
- 0xaa, 0xa8, 0x37, 0xa8, 0xbd, 0x63, 0xb7, 0xbc,
- 0x95, 0xef, 0x0c, 0xcf, 0x39, 0x31, 0x93, 0xe6,
- 0x86, 0xbd, 0x3f, 0x56, 0x9d, 0xf0, 0xb2, 0xb5,
- 0xd1, 0xa7, 0xc6, 0x45, 0x89, 0x18, 0xfb, 0xa0,
- 0x7f, 0xc1,
+ 0x82, 0x00, 0x80, 0x45, 0x6d, 0x68, 0x61, 0xb9,
+ 0x1a, 0xe5, 0xeb, 0x67, 0x22, 0x3b, 0x87, 0x19,
+ 0x52, 0x86, 0x31, 0x91, 0xee, 0xcd, 0x17, 0x75,
+ 0xc6, 0x44, 0xaf, 0x23, 0xef, 0xd9, 0xfa, 0xd2,
+ 0x0b, 0xa2, 0xbb, 0xbf, 0x8b, 0x4b, 0x34, 0x50,
+ 0xf6, 0x2e, 0x05, 0x09, 0x7e, 0xbf, 0xb3, 0xa6,
+ 0x10, 0xe3, 0xc3, 0x49, 0x55, 0xa8, 0xdf, 0x6c,
+ 0xaa, 0xab, 0x11, 0x4c, 0x80, 0x0a, 0x45, 0xf8,
+ 0x37, 0xbb, 0xd3, 0x18, 0x4e, 0xec, 0x51, 0xbf,
+ 0x1a, 0xf6, 0x11, 0x1b, 0xcf, 0x2c, 0xaf, 0x5f,
+ 0x0b, 0x52, 0x4e, 0x92, 0x0c, 0x7a, 0xb2, 0x5d,
+ 0xe2, 0x1f, 0x83, 0xbe, 0xf5, 0xbf, 0x05, 0xbf,
+ 0x99, 0xd6, 0x9c, 0x86, 0x47, 0x5e, 0xb4, 0xff,
+ 0xe7, 0xac, 0xad, 0x1e, 0x3c, 0xaa, 0x91, 0x39,
+ 0xca, 0xad, 0xc5, 0x54, 0x64, 0x7e, 0xc2, 0x8a,
+ 0x48, 0xee, 0xb6, 0x4e, 0xf9, 0x33, 0x82, 0x52,
+ 0xe8, 0xed, 0x48, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xc1, 0x2f,
+ 0x34, 0x03, 0x2a, 0xf2, 0xfd, 0x83, 0x69, 0x23,
+ 0x8c, 0x9e, 0x66, 0x3b, 0xbb, 0xd1, 0xab, 0xbb,
+ 0x51, 0x89, 0x27, 0x88, 0x0f, 0x08, 0x3e, 0x00,
+ 0xdc, 0xc7, 0x47, 0x82, 0x13, 0x34, 0xec, 0xca,
+ 0x68, 0x6a,
+ },
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x24, 0xda, 0x61, 0x76, 0x9f, 0x7a,
+ 0x8a, 0xd0, 0x5f, 0x9b, 0x3d, 0xa7, 0xd5, 0xdd,
+ 0x95, 0x4b, 0xd4, 0x64, 0x2d, 0x2d, 0x6a, 0x98,
+ 0x9e, 0xfe, 0x77, 0x76, 0xe3, 0x02, 0x05, 0x0c,
+ 0xb2, 0xa6, 0x15, 0x82, 0x28, 0x25, 0xc5, 0x17,
+ 0x03, 0x01, 0x00, 0x21, 0x4e, 0x66, 0x2d, 0x50,
+ 0x00, 0xa2, 0x44, 0x4d, 0xee, 0x5f, 0x81, 0x67,
+ 0x21, 0x5d, 0x94, 0xc0, 0xfb, 0xdc, 0xbd, 0xf6,
+ 0xa8, 0x32, 0x8e, 0x2c, 0x22, 0x58, 0x37, 0xb6,
+ 0xa3, 0x1e, 0xf8, 0xdd, 0x83, 0x15, 0x03, 0x01,
+ 0x00, 0x16, 0x68, 0x3b, 0x3a, 0xd0, 0x1e, 0xc4,
+ 0x5e, 0x97, 0x6a, 0x47, 0x38, 0xfe, 0x17, 0x8e,
+ 0xc0, 0xb6, 0x4a, 0x94, 0x00, 0xb5, 0x91, 0xbf,
+ },
+}
+
+var issueSessionTicketTest = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0xdd, 0x01, 0x00, 0x00,
+ 0xd9, 0x03, 0x02, 0x50, 0x5a, 0x32, 0xb6, 0x36,
+ 0x0e, 0x94, 0x63, 0x57, 0x93, 0xd7, 0x1e, 0xb2,
+ 0xa7, 0xd3, 0x20, 0x24, 0x30, 0x3f, 0x46, 0xf9,
+ 0xfe, 0x22, 0x02, 0xa1, 0xff, 0x57, 0xf8, 0x8f,
+ 0x95, 0x4c, 0xdd, 0x00, 0x00, 0x66, 0xc0, 0x14,
+ 0xc0, 0x0a, 0xc0, 0x22, 0xc0, 0x21, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x88, 0x00, 0x87, 0xc0, 0x0f,
+ 0xc0, 0x05, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x12,
+ 0xc0, 0x08, 0xc0, 0x1c, 0xc0, 0x1b, 0x00, 0x16,
+ 0x00, 0x13, 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a,
+ 0xc0, 0x13, 0xc0, 0x09, 0xc0, 0x1f, 0xc0, 0x1e,
+ 0x00, 0x33, 0x00, 0x32, 0x00, 0x9a, 0x00, 0x99,
+ 0x00, 0x45, 0x00, 0x44, 0xc0, 0x0e, 0xc0, 0x04,
+ 0x00, 0x2f, 0x00, 0x96, 0x00, 0x41, 0xc0, 0x11,
+ 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02, 0x00, 0x05,
+ 0x00, 0x04, 0x00, 0x15, 0x00, 0x12, 0x00, 0x09,
+ 0x00, 0x14, 0x00, 0x11, 0x00, 0x08, 0x00, 0x06,
+ 0x00, 0x03, 0x00, 0xff, 0x02, 0x01, 0x00, 0x00,
+ 0x49, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
+ 0x02, 0x00, 0x0a, 0x00, 0x34, 0x00, 0x32, 0x00,
+ 0x0e, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x0b, 0x00,
+ 0x0c, 0x00, 0x18, 0x00, 0x09, 0x00, 0x0a, 0x00,
+ 0x16, 0x00, 0x17, 0x00, 0x08, 0x00, 0x06, 0x00,
+ 0x07, 0x00, 0x14, 0x00, 0x15, 0x00, 0x04, 0x00,
+ 0x05, 0x00, 0x12, 0x00, 0x13, 0x00, 0x01, 0x00,
+ 0x02, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, 0x00,
+ 0x11, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0f, 0x00,
+ 0x01, 0x01,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x01, 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, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+ 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, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00,
+ 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+ 0x82, 0x00, 0x80, 0x92, 0x3f, 0xcc, 0x4d, 0x2f,
+ 0xb2, 0x12, 0xc4, 0xf5, 0x72, 0xf3, 0x5a, 0x3c,
+ 0x5a, 0xbb, 0x99, 0x89, 0xe6, 0x21, 0x0f, 0xdf,
+ 0xf3, 0xa3, 0xd0, 0xce, 0x76, 0x55, 0xfd, 0xec,
+ 0x38, 0x80, 0xf0, 0x46, 0x0b, 0xfa, 0x61, 0x7c,
+ 0xc2, 0xb5, 0xe2, 0x89, 0x7b, 0xeb, 0xcf, 0x3e,
+ 0x97, 0xab, 0x72, 0xf6, 0xfd, 0xcf, 0x10, 0x82,
+ 0x3a, 0x05, 0x55, 0x7c, 0x2d, 0x7f, 0x44, 0x38,
+ 0x9d, 0xeb, 0xa4, 0x7e, 0x53, 0x35, 0xda, 0xe0,
+ 0x7c, 0x24, 0x66, 0x42, 0x5d, 0x85, 0xcf, 0xa6,
+ 0x98, 0x81, 0xec, 0x42, 0x94, 0x4e, 0x25, 0xb1,
+ 0x64, 0xac, 0x89, 0x98, 0x74, 0xd2, 0xeb, 0x51,
+ 0x5a, 0xb3, 0xbd, 0x14, 0xf6, 0xc6, 0xec, 0x0b,
+ 0xdd, 0x8b, 0x89, 0xdc, 0xde, 0xf3, 0xd6, 0x62,
+ 0xee, 0xe3, 0xcf, 0xf5, 0x39, 0x23, 0x46, 0x4f,
+ 0xb8, 0xef, 0x14, 0x39, 0x06, 0x36, 0xad, 0x84,
+ 0x42, 0xb9, 0xd7, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xa1, 0xf0,
+ 0x68, 0xf5, 0x29, 0x7e, 0x78, 0xaa, 0xbd, 0x59,
+ 0xdc, 0x32, 0xab, 0x8e, 0x25, 0x54, 0x64, 0x9e,
+ 0x2b, 0x08, 0xf9, 0xb8, 0xe3, 0x89, 0x09, 0xa4,
+ 0xfd, 0x05, 0x78, 0x59, 0xcb, 0x33, 0xfc, 0x66,
+ 0xb5, 0x73,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xe8, 0x4b, 0xd1, 0xef, 0xba, 0xfc, 0x00, 0xd4,
+ 0x2f, 0xf5, 0x6f, 0xba, 0xdc, 0xb7, 0xd7, 0x87,
+ 0x59, 0x58, 0x05, 0x06, 0x36, 0x8f, 0x47, 0xc7,
+ 0x9e, 0x4c, 0xf8, 0xb5, 0xd7, 0x55, 0x84, 0x64,
+ 0x0b, 0x4c, 0x0b, 0xad, 0x8d, 0x9b, 0x79, 0x4d,
+ 0xd7, 0x61, 0xf7, 0x2b, 0x89, 0x46, 0x2b, 0x52,
+ 0x1a, 0x3f, 0x51, 0x58, 0xce, 0x59, 0x23, 0xef,
+ 0x60, 0x55, 0x07, 0xc0, 0x46, 0x97, 0xad, 0x0a,
+ 0xe3, 0x55, 0x10, 0x06, 0xff, 0x57, 0x0c, 0xb1,
+ 0x49, 0xac, 0x80, 0xc6, 0xc3, 0x95, 0x5f, 0x12,
+ 0xe2, 0xe5, 0xaa, 0x9f, 0x78, 0xc2, 0x20, 0x14,
+ 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+ 0x00, 0x24, 0x47, 0x51, 0xf1, 0x13, 0xc8, 0xa6,
+ 0xd2, 0x2c, 0xad, 0x35, 0xff, 0x53, 0xe2, 0x72,
+ 0x01, 0xcb, 0x33, 0xcd, 0xf4, 0xa0, 0x9c, 0x03,
+ 0x47, 0xfe, 0xcd, 0xc1, 0x46, 0x8d, 0x41, 0x5e,
+ 0x54, 0xf7, 0xc3, 0x85, 0x2b, 0x2f, 0x17, 0x03,
+ 0x01, 0x00, 0x21, 0xf4, 0xbf, 0x94, 0x3e, 0x93,
+ 0x0b, 0x1b, 0x75, 0x3a, 0xd9, 0xd0, 0x57, 0x75,
+ 0xf3, 0xa7, 0x82, 0xc9, 0x6b, 0x9e, 0x43, 0x98,
+ 0x44, 0x9e, 0x9f, 0xad, 0x03, 0xa8, 0xb9, 0xa3,
+ 0x0a, 0xd1, 0xc4, 0xb4, 0x15, 0x03, 0x01, 0x00,
+ 0x16, 0xee, 0x57, 0xbd, 0xd3, 0xb7, 0x20, 0x29,
+ 0xd1, 0x24, 0xe2, 0xdc, 0x24, 0xc3, 0x73, 0x86,
+ 0x81, 0x8e, 0x40, 0xc3, 0x6e, 0x99, 0x9e,
+ },
+}
+
+var serverResumeTest = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x01, 0x65, 0x01, 0x00, 0x01,
+ 0x61, 0x03, 0x01, 0x50, 0x5a, 0x32, 0xe2, 0xde,
+ 0x19, 0x5c, 0xb6, 0x51, 0x87, 0xa4, 0x30, 0x2e,
+ 0x95, 0x26, 0xd6, 0xed, 0xbf, 0xbf, 0x24, 0xbb,
+ 0xd1, 0x1a, 0x29, 0x9f, 0x37, 0xfd, 0xfb, 0xae,
+ 0xc2, 0xba, 0x2b, 0x20, 0xb5, 0x7a, 0x00, 0x96,
+ 0x92, 0x51, 0xfc, 0x41, 0x16, 0x29, 0xc0, 0x54,
+ 0x5e, 0xa7, 0xa9, 0x1f, 0xf8, 0xbf, 0x79, 0xfa,
+ 0x49, 0x5a, 0x15, 0x28, 0x72, 0x9a, 0x59, 0xf9,
+ 0x9b, 0xc4, 0x3a, 0xa8, 0x00, 0x66, 0xc0, 0x14,
+ 0xc0, 0x0a, 0xc0, 0x22, 0xc0, 0x21, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x88, 0x00, 0x87, 0xc0, 0x0f,
+ 0xc0, 0x05, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x12,
+ 0xc0, 0x08, 0xc0, 0x1c, 0xc0, 0x1b, 0x00, 0x16,
+ 0x00, 0x13, 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a,
+ 0xc0, 0x13, 0xc0, 0x09, 0xc0, 0x1f, 0xc0, 0x1e,
+ 0x00, 0x33, 0x00, 0x32, 0x00, 0x9a, 0x00, 0x99,
+ 0x00, 0x45, 0x00, 0x44, 0xc0, 0x0e, 0xc0, 0x04,
+ 0x00, 0x2f, 0x00, 0x96, 0x00, 0x41, 0xc0, 0x11,
+ 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02, 0x00, 0x05,
+ 0x00, 0x04, 0x00, 0x15, 0x00, 0x12, 0x00, 0x09,
+ 0x00, 0x14, 0x00, 0x11, 0x00, 0x08, 0x00, 0x06,
+ 0x00, 0x03, 0x00, 0xff, 0x02, 0x01, 0x00, 0x00,
+ 0xb1, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
+ 0x02, 0x00, 0x0a, 0x00, 0x34, 0x00, 0x32, 0x00,
+ 0x0e, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x0b, 0x00,
+ 0x0c, 0x00, 0x18, 0x00, 0x09, 0x00, 0x0a, 0x00,
+ 0x16, 0x00, 0x17, 0x00, 0x08, 0x00, 0x06, 0x00,
+ 0x07, 0x00, 0x14, 0x00, 0x15, 0x00, 0x04, 0x00,
+ 0x05, 0x00, 0x12, 0x00, 0x13, 0x00, 0x01, 0x00,
+ 0x02, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, 0x00,
+ 0x11, 0x00, 0x23, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xe8, 0x4b,
+ 0xd1, 0xef, 0xba, 0xfc, 0x00, 0xd4, 0x2f, 0xf5,
+ 0x6f, 0xba, 0xdc, 0xb7, 0xd7, 0x87, 0x59, 0x58,
+ 0x05, 0x06, 0x36, 0x8f, 0x47, 0xc7, 0x9e, 0x4c,
+ 0xf8, 0xb5, 0xd7, 0x55, 0x84, 0x64, 0x0b, 0x4c,
+ 0x0b, 0xad, 0x8d, 0x9b, 0x79, 0x4d, 0xd7, 0x61,
+ 0xf7, 0x2b, 0x89, 0x46, 0x2b, 0x52, 0x1a, 0x3f,
+ 0x51, 0x58, 0xce, 0x59, 0x23, 0xef, 0x60, 0x55,
+ 0x07, 0xc0, 0x46, 0x97, 0xad, 0x0a, 0xe3, 0x55,
+ 0x10, 0x06, 0xff, 0x57, 0x0c, 0xb1, 0x49, 0xac,
+ 0x80, 0xc6, 0xc3, 0x95, 0x5f, 0x12, 0xe2, 0xe5,
+ 0xaa, 0x9f, 0x78, 0xc2, 0x20, 0x00, 0x0f, 0x00,
+ 0x01, 0x01,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 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, 0x20, 0xb5, 0x7a, 0x00, 0x96,
+ 0x92, 0x51, 0xfc, 0x41, 0x16, 0x29, 0xc0, 0x54,
+ 0x5e, 0xa7, 0xa9, 0x1f, 0xf8, 0xbf, 0x79, 0xfa,
+ 0x49, 0x5a, 0x15, 0x28, 0x72, 0x9a, 0x59, 0xf9,
+ 0x9b, 0xc4, 0x3a, 0xa8, 0x00, 0x05, 0x00, 0x14,
+ 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+ 0x00, 0x24, 0x2c, 0x86, 0xdd, 0x85, 0x21, 0xa7,
+ 0xda, 0x25, 0xf5, 0x55, 0x62, 0x2d, 0x82, 0x6b,
+ 0x9d, 0x67, 0x22, 0x28, 0xf4, 0x55, 0x33, 0xd0,
+ 0x77, 0xc0, 0x9e, 0xb7, 0xf4, 0x96, 0x07, 0x8c,
+ 0xf5, 0xea, 0x5b, 0x50, 0xa4, 0xb7,
},
{
0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x01, 0x00, 0x24, 0xb8, 0x6d, 0x9a, 0x90, 0x3c,
- 0x45, 0xe0, 0xff, 0x63, 0xba, 0xab, 0x3d, 0x7a,
- 0xa6, 0x49, 0x5a, 0x13, 0xdc, 0x0e, 0xa3, 0xba,
- 0x7f, 0x04, 0x19, 0x45, 0xfd, 0xfb, 0xbd, 0x00,
- 0xa3, 0xa7, 0x78, 0x81, 0x38, 0x9f, 0x10, 0x17,
- 0x03, 0x01, 0x00, 0x21, 0x43, 0xc3, 0x91, 0xb7,
- 0xbf, 0x50, 0x0b, 0x04, 0xb4, 0x5d, 0xc6, 0x20,
- 0x64, 0xb8, 0x01, 0x09, 0x25, 0x2c, 0x03, 0x30,
- 0xc0, 0x77, 0xc9, 0x5e, 0xe6, 0xe0, 0x99, 0xdc,
- 0xcd, 0x75, 0x9d, 0x51, 0x82, 0x15, 0x03, 0x01,
- 0x00, 0x16, 0x2d, 0x7a, 0x89, 0x7b, 0x36, 0x85,
- 0x2a, 0x93, 0xcb, 0x83, 0xa7, 0x2f, 0x9e, 0x91,
- 0xfc, 0xad, 0x57, 0xca, 0xf5, 0xbc, 0x13, 0x2f,
+ 0x01, 0x00, 0x24, 0x15, 0x14, 0x9c, 0x21, 0xdd,
+ 0x47, 0x61, 0x52, 0xf9, 0x22, 0x15, 0x55, 0x3c,
+ 0xbd, 0xd7, 0xff, 0xf9, 0xbd, 0x84, 0xec, 0x97,
+ 0x2d, 0x4e, 0xa9, 0x6a, 0xb9, 0x9b, 0x96, 0xc6,
+ 0x9e, 0x5c, 0x77, 0xa8, 0x5d, 0x7a, 0x08,
+ },
+ {
+ 0x17, 0x03, 0x01, 0x00, 0x21, 0x04, 0xab, 0x0f,
+ 0x7c, 0x54, 0x20, 0xab, 0x34, 0xa3, 0x73, 0x92,
+ 0xc5, 0xaa, 0xdd, 0x5b, 0xf5, 0x0c, 0xe4, 0x4f,
+ 0xf1, 0x93, 0x07, 0xe5, 0xe8, 0x72, 0xc2, 0x03,
+ 0x60, 0xfa, 0x64, 0x01, 0x00, 0x25, 0x15, 0x03,
+ 0x01, 0x00, 0x16, 0xc7, 0xd9, 0xff, 0x67, 0xfc,
+ 0x7a, 0xac, 0x8a, 0xe6, 0x23, 0xfe, 0x32, 0xbf,
+ 0x84, 0xe1, 0xe2, 0xf5, 0x6a, 0xc8, 0xda, 0x30,
+ 0x8f,
},
}
diff --git a/libgo/go/crypto/tls/prf.go b/libgo/go/crypto/tls/prf.go
index 637ef03e2d7..df1eaad0586 100644
--- a/libgo/go/crypto/tls/prf.go
+++ b/libgo/go/crypto/tls/prf.go
@@ -106,10 +106,9 @@ var keyExpansionLabel = []byte("key expansion")
var clientFinishedLabel = []byte("client finished")
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 keysFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+// masterFromPreMasterSecret generates the master secret from the pre-master
+// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
+func masterFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte) []byte {
prf := pRF10
if version == versionSSL30 {
prf = pRF30
@@ -118,9 +117,21 @@ func keysFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serv
var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], clientRandom)
copy(seed[len(clientRandom):], serverRandom)
- masterSecret = make([]byte, masterSecretLength)
+ masterSecret := make([]byte, masterSecretLength)
prf(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+ return masterSecret
+}
+// keysFromMasterSecret generates the connection keys from the master
+// secret, given the lengths of the MAC key, cipher key and IV, as defined in
+// RFC 2246, section 6.3.
+func keysFromMasterSecret(version uint16, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+ prf := pRF10
+ if version == versionSSL30 {
+ prf = pRF30
+ }
+
+ var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], serverRandom)
copy(seed[len(serverRandom):], clientRandom)
diff --git a/libgo/go/crypto/tls/prf_test.go b/libgo/go/crypto/tls/prf_test.go
index a32392cef79..ce6e36de8a1 100644
--- a/libgo/go/crypto/tls/prf_test.go
+++ b/libgo/go/crypto/tls/prf_test.go
@@ -48,18 +48,23 @@ 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, _, _ := keysFromPreMasterSecret(test.version, in, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
- masterString := hex.EncodeToString(master)
+
+ masterSecret := masterFromPreMasterSecret(test.version, in, clientRandom, serverRandom)
+ if s := hex.EncodeToString(masterSecret); s != test.masterSecret {
+ t.Errorf("#%d: bad master secret %s, want %s", s, test.masterSecret)
+ continue
+ }
+
+ clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromMasterSecret(test.version, masterSecret, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
clientMACString := hex.EncodeToString(clientMAC)
serverMACString := hex.EncodeToString(serverMAC)
clientKeyString := hex.EncodeToString(clientKey)
serverKeyString := hex.EncodeToString(serverKey)
- if masterString != test.masterSecret ||
- clientMACString != test.clientMAC ||
+ if clientMACString != test.clientMAC ||
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, serverKeyString, test.masterSecret, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey)
+ t.Errorf("#%d: got: (%s, %s, %s, %s) want: (%s, %s, %s, %s)", i, clientMACString, serverMACString, clientKeyString, serverKeyString, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey)
}
}
}
diff --git a/libgo/go/crypto/tls/root_test.go b/libgo/go/crypto/tls/root_test.go
deleted file mode 100644
index e61c2185126..00000000000
--- a/libgo/go/crypto/tls/root_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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 tls
-
-import (
- "crypto/x509"
- "runtime"
- "testing"
-)
-
-var tlsServers = []string{
- "google.com",
- "github.com",
- "twitter.com",
-}
-
-func TestOSCertBundles(t *testing.T) {
- if testing.Short() {
- t.Logf("skipping certificate tests in short mode")
- return
- }
-
- for _, addr := range tlsServers {
- conn, err := Dial("tcp", addr+":443", &Config{ServerName: addr})
- if err != nil {
- t.Errorf("unable to verify %v: %v", addr, err)
- continue
- }
- err = conn.Close()
- if err != nil {
- t.Error(err)
- }
- }
-}
-
-func TestCertHostnameVerifyWindows(t *testing.T) {
- if runtime.GOOS != "windows" {
- return
- }
-
- if testing.Short() {
- t.Logf("skipping certificate tests in short mode")
- return
- }
-
- for _, addr := range tlsServers {
- cfg := &Config{ServerName: "example.com"}
- conn, err := Dial("tcp", addr+":443", cfg)
- if err == nil {
- conn.Close()
- t.Errorf("should fail to verify for example.com: %v", addr)
- continue
- }
- _, ok := err.(x509.HostnameError)
- if !ok {
- t.Errorf("error type mismatch, got: %v", err)
- }
- }
-}
diff --git a/libgo/go/crypto/tls/ticket.go b/libgo/go/crypto/tls/ticket.go
new file mode 100644
index 00000000000..4cfc5a53ffe
--- /dev/null
+++ b/libgo/go/crypto/tls/ticket.go
@@ -0,0 +1,182 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/hmac"
+ "crypto/sha256"
+ "crypto/subtle"
+ "errors"
+ "io"
+)
+
+// sessionState contains the information that is serialized into a session
+// ticket in order to later resume a connection.
+type sessionState struct {
+ vers uint16
+ cipherSuite uint16
+ masterSecret []byte
+ certificates [][]byte
+}
+
+func (s *sessionState) equal(i interface{}) bool {
+ s1, ok := i.(*sessionState)
+ if !ok {
+ return false
+ }
+
+ if s.vers != s1.vers ||
+ s.cipherSuite != s1.cipherSuite ||
+ !bytes.Equal(s.masterSecret, s1.masterSecret) {
+ return false
+ }
+
+ if len(s.certificates) != len(s1.certificates) {
+ return false
+ }
+
+ for i := range s.certificates {
+ if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
+ return false
+ }
+ }
+
+ return true
+}
+
+func (s *sessionState) marshal() []byte {
+ length := 2 + 2 + 2 + len(s.masterSecret) + 2
+ for _, cert := range s.certificates {
+ length += 4 + len(cert)
+ }
+
+ ret := make([]byte, length)
+ x := ret
+ x[0] = byte(s.vers >> 8)
+ x[1] = byte(s.vers)
+ x[2] = byte(s.cipherSuite >> 8)
+ x[3] = byte(s.cipherSuite)
+ x[4] = byte(len(s.masterSecret) >> 8)
+ x[5] = byte(len(s.masterSecret))
+ x = x[6:]
+ copy(x, s.masterSecret)
+ x = x[len(s.masterSecret):]
+
+ x[0] = byte(len(s.certificates) >> 8)
+ x[1] = byte(len(s.certificates))
+ x = x[2:]
+
+ for _, cert := range s.certificates {
+ x[0] = byte(len(cert) >> 24)
+ x[1] = byte(len(cert) >> 16)
+ x[2] = byte(len(cert) >> 8)
+ x[3] = byte(len(cert))
+ copy(x[4:], cert)
+ x = x[4+len(cert):]
+ }
+
+ return ret
+}
+
+func (s *sessionState) unmarshal(data []byte) bool {
+ if len(data) < 8 {
+ return false
+ }
+
+ s.vers = uint16(data[0])<<8 | uint16(data[1])
+ s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
+ masterSecretLen := int(data[4])<<8 | int(data[5])
+ data = data[6:]
+ if len(data) < masterSecretLen {
+ return false
+ }
+
+ s.masterSecret = data[:masterSecretLen]
+ data = data[masterSecretLen:]
+
+ if len(data) < 2 {
+ return false
+ }
+
+ numCerts := int(data[0])<<8 | int(data[1])
+ data = data[2:]
+
+ s.certificates = make([][]byte, numCerts)
+ for i := range s.certificates {
+ if len(data) < 4 {
+ return false
+ }
+ certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+ data = data[4:]
+ if certLen < 0 {
+ return false
+ }
+ if len(data) < certLen {
+ return false
+ }
+ s.certificates[i] = data[:certLen]
+ data = data[certLen:]
+ }
+
+ if len(data) > 0 {
+ return false
+ }
+
+ return true
+}
+
+func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) {
+ serialized := state.marshal()
+ encrypted := make([]byte, aes.BlockSize+len(serialized)+sha256.Size)
+ iv := encrypted[:aes.BlockSize]
+ macBytes := encrypted[len(encrypted)-sha256.Size:]
+
+ if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
+ return nil, err
+ }
+ block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
+ if err != nil {
+ return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
+ }
+ cipher.NewCTR(block, iv).XORKeyStream(encrypted[aes.BlockSize:], serialized)
+
+ mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
+ mac.Write(encrypted[:len(encrypted)-sha256.Size])
+ mac.Sum(macBytes[:0])
+
+ return encrypted, nil
+}
+
+func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
+ if len(encrypted) < aes.BlockSize+sha256.Size {
+ return nil, false
+ }
+
+ iv := encrypted[:aes.BlockSize]
+ macBytes := encrypted[len(encrypted)-sha256.Size:]
+
+ mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
+ mac.Write(encrypted[:len(encrypted)-sha256.Size])
+ expected := mac.Sum(nil)
+
+ if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
+ return nil, false
+ }
+
+ block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
+ if err != nil {
+ return nil, false
+ }
+ ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size]
+ plaintext := ciphertext
+ cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
+
+ state := new(sessionState)
+ ok := state.unmarshal(plaintext)
+ return state, ok
+}
diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go
index 09df5ad445c..80f852edf7b 100644
--- a/libgo/go/crypto/tls/tls.go
+++ b/libgo/go/crypto/tls/tls.go
@@ -146,10 +146,16 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error)
return
}
- keyDERBlock, _ := pem.Decode(keyPEMBlock)
- if keyDERBlock == nil {
- err = errors.New("crypto/tls: failed to parse key PEM data")
- return
+ var keyDERBlock *pem.Block
+ for {
+ keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
+ if keyDERBlock == nil {
+ err = errors.New("crypto/tls: failed to parse key PEM data")
+ return
+ }
+ if keyDERBlock.Type != "CERTIFICATE" {
+ break
+ }
}
// OpenSSL 0.9.8 generates PKCS#1 private keys by default, while
diff --git a/libgo/go/crypto/tls/tls_test.go b/libgo/go/crypto/tls/tls_test.go
new file mode 100644
index 00000000000..5df43c385fd
--- /dev/null
+++ b/libgo/go/crypto/tls/tls_test.go
@@ -0,0 +1,47 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "testing"
+)
+
+var certPEM = `-----BEGIN CERTIFICATE-----
+MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ
+hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa
+rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv
+zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW
+r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V
+-----END CERTIFICATE-----
+`
+
+var keyPEM = `-----BEGIN RSA PRIVATE KEY-----
+MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
+k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
+6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
+MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
+SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
+xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
+D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
+-----END RSA PRIVATE KEY-----
+`
+
+func TestX509KeyPair(t *testing.T) {
+ _, err := X509KeyPair([]byte(keyPEM+certPEM), []byte(keyPEM+certPEM))
+ if err != nil {
+ t.Errorf("Failed to load key followed by cert: %s", err)
+ }
+
+ _, err = X509KeyPair([]byte(certPEM+keyPEM), []byte(certPEM+keyPEM))
+ if err != nil {
+ t.Errorf("Failed to load cert followed by key: %s", err)
+ println(err.Error())
+ }
+}
diff --git a/libgo/go/crypto/x509/pem_decrypt.go b/libgo/go/crypto/x509/pem_decrypt.go
new file mode 100644
index 00000000000..21f62e5d76b
--- /dev/null
+++ b/libgo/go/crypto/x509/pem_decrypt.go
@@ -0,0 +1,133 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x509
+
+// RFC 1423 describes the encryption of PEM blocks. The algorithm used to
+// generate a key from the password was derived by looking at the OpenSSL
+// implementation.
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/des"
+ "crypto/md5"
+ "encoding/hex"
+ "encoding/pem"
+ "errors"
+ "strings"
+)
+
+// rfc1423Algos represents how to create a block cipher for a decryption mode.
+type rfc1423Algo struct {
+ cipherFunc func([]byte) (cipher.Block, error)
+ keySize int
+}
+
+// deriveKey uses a key derivation function to stretch the password into a key
+// with the number of bits our cipher requires. This algorithm was derived from
+// the OpenSSL source.
+func (c rfc1423Algo) deriveKey(password, salt []byte) []byte {
+ hash := md5.New()
+ out := make([]byte, c.keySize)
+ var digest []byte
+
+ for i := 0; i < len(out); i += len(digest) {
+ hash.Reset()
+ hash.Write(digest)
+ hash.Write(password)
+ hash.Write(salt)
+ digest = hash.Sum(digest[:0])
+ copy(out[i:], digest)
+ }
+
+ return out
+}
+
+// rfc1423Algos is a mapping of encryption algorithm to an rfc1423Algo that can
+// create block ciphers for that mode.
+var rfc1423Algos = map[string]rfc1423Algo{
+ "DES-CBC": {des.NewCipher, 8},
+ "DES-EDE3-CBC": {des.NewTripleDESCipher, 24},
+ "AES-128-CBC": {aes.NewCipher, 16},
+ "AES-192-CBC": {aes.NewCipher, 24},
+ "AES-256-CBC": {aes.NewCipher, 32},
+}
+
+// IsEncryptedPEMBlock returns if the PEM block is password encrypted.
+func IsEncryptedPEMBlock(b *pem.Block) bool {
+ _, ok := b.Headers["DEK-Info"]
+ return ok
+}
+
+// IncorrectPasswordError is returned when an incorrect password is detected.
+var IncorrectPasswordError = errors.New("x509: decryption password incorrect")
+
+// DecryptPEMBlock takes a password encrypted PEM block and the password used to
+// encrypt it and returns a slice of decrypted DER encoded bytes. It inspects
+// the DEK-Info header to determine the algorithm used for decryption. If no
+// DEK-Info header is present, an error is returned. If an incorrect password
+// is detected an IncorrectPasswordError is returned.
+func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) {
+ dek, ok := b.Headers["DEK-Info"]
+ if !ok {
+ return nil, errors.New("x509: no DEK-Info header in block")
+ }
+
+ idx := strings.Index(dek, ",")
+ if idx == -1 {
+ return nil, errors.New("x509: malformed DEK-Info header")
+ }
+
+ mode, hexIV := dek[:idx], dek[idx+1:]
+ iv, err := hex.DecodeString(hexIV)
+ if err != nil {
+ return nil, err
+ }
+ if len(iv) < 8 {
+ return nil, errors.New("x509: not enough bytes in IV")
+ }
+
+ ciph, ok := rfc1423Algos[mode]
+ if !ok {
+ return nil, errors.New("x509: unknown encryption mode")
+ }
+
+ // Based on the OpenSSL implementation. The salt is the first 8 bytes
+ // of the initialization vector.
+ key := ciph.deriveKey(password, iv[:8])
+ block, err := ciph.cipherFunc(key)
+ if err != nil {
+ return nil, err
+ }
+
+ data := make([]byte, len(b.Bytes))
+ dec := cipher.NewCBCDecrypter(block, iv)
+ dec.CryptBlocks(data, b.Bytes)
+
+ // Blocks are padded using a scheme where the last n bytes of padding are all
+ // equal to n. It can pad from 1 to 8 bytes inclusive. See RFC 1423.
+ // For example:
+ // [x y z 2 2]
+ // [x y 7 7 7 7 7 7 7]
+ // If we detect a bad padding, we assume it is an invalid password.
+ dlen := len(data)
+ if dlen == 0 {
+ return nil, errors.New("x509: invalid padding")
+ }
+ last := data[dlen-1]
+ if dlen < int(last) {
+ return nil, IncorrectPasswordError
+ }
+ if last == 0 || last > 8 {
+ return nil, IncorrectPasswordError
+ }
+ for _, val := range data[dlen-int(last):] {
+ if val != last {
+ return nil, IncorrectPasswordError
+ }
+ }
+
+ return data[:dlen-int(last)], nil
+}
diff --git a/libgo/go/crypto/x509/pem_decrypt_test.go b/libgo/go/crypto/x509/pem_decrypt_test.go
new file mode 100644
index 00000000000..2cb99836eae
--- /dev/null
+++ b/libgo/go/crypto/x509/pem_decrypt_test.go
@@ -0,0 +1,119 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x509
+
+import (
+ "encoding/pem"
+ "testing"
+)
+
+func TestDecrypt(t *testing.T) {
+ for _, data := range testData {
+ block, rest := pem.Decode(data.pemData)
+ if len(rest) > 0 {
+ t.Error(data.kind, "extra data")
+ }
+ der, err := DecryptPEMBlock(block, data.password)
+ if err != nil {
+ t.Error(data.kind, err)
+ continue
+ }
+ if _, err := ParsePKCS1PrivateKey(der); err != nil {
+ t.Error(data.kind, "Invalid private key")
+ }
+ }
+}
+
+var testData = []struct {
+ kind string
+ password []byte
+ pemData []byte
+}{
+ {
+ kind: "DES-CBC",
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CBC,34F09A4FC8DE22B5
+
+WXxy8kbZdiZvANtKvhmPBLV7eVFj2A5z6oAxvI9KGyhG0ZK0skfnt00C24vfU7m5
+ICXeoqP67lzJ18xCzQfHjDaBNs53DSDT+Iz4e8QUep1xQ30+8QKX2NA2coee3nwc
+6oM1cuvhNUDemBH2i3dKgMVkfaga0zQiiOq6HJyGSncCMSruQ7F9iWEfRbFcxFCx
+qtHb1kirfGKEtgWTF+ynyco6+2gMXNu70L7nJcnxnV/RLFkHt7AUU1yrclxz7eZz
+XOH9VfTjb52q/I8Suozq9coVQwg4tXfIoYUdT//O+mB7zJb9HI9Ps77b9TxDE6Gm
+4C9brwZ3zg2vqXcwwV6QRZMtyll9rOpxkbw6NPlpfBqkc3xS51bbxivbO/Nve4KD
+r12ymjFNF4stXCfJnNqKoZ50BHmEEUDu5Wb0fpVn82XrGw7CYc4iug==
+-----END RSA PRIVATE KEY-----`),
+ },
+ {
+ kind: "DES-EDE3-CBC",
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C1F4A6A03682C2C7
+
+0JqVdBEH6iqM7drTkj+e2W/bE3LqakaiWhb9WUVonFkhyu8ca/QzebY3b5gCvAZQ
+YwBvDcT/GHospKqPx+cxDHJNsUASDZws6bz8ZXWJGwZGExKzr0+Qx5fgXn44Ms3x
+8g1ENFuTXtxo+KoNK0zuAMAqp66Llcds3Fjl4XR18QaD0CrVNAfOdgATWZm5GJxk
+Fgx5f84nT+/ovvreG+xeOzWgvtKo0UUZVrhGOgfKLpa57adumcJ6SkUuBtEFpZFB
+ldw5w7WC7d13x2LsRkwo8ZrDKgIV+Y9GNvhuCCkTzNP0V3gNeJpd201HZHR+9n3w
+3z0VjR/MGqsfcy1ziEWMNOO53At3zlG6zP05aHMnMcZoVXadEK6L1gz++inSSDCq
+gI0UJP4e3JVB7AkgYymYAwiYALAkoEIuanxoc50njJk=
+-----END RSA PRIVATE KEY-----`),
+ },
+ {
+ kind: "AES-128-CBC",
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,D4492E793FC835CC038A728ED174F78A
+
+EyfQSzXSjv6BaNH+NHdXRlkHdimpF9izWlugVJAPApgXrq5YldPe2aGIOFXyJ+QE
+ZIG20DYqaPzJRjTEbPNZ6Es0S2JJ5yCpKxwJuDkgJZKtF39Q2i36JeGbSZQIuWJE
+GZbBpf1jDH/pr0iGonuAdl2PCCZUiy+8eLsD2tyviHUkFLOB+ykYoJ5t8ngZ/B6D
+33U43LLb7+9zD4y3Q9OVHqBFGyHcxCY9+9Qh4ZnFp7DTf6RY5TNEvE3s4g6aDpBs
+3NbvRVvYTgs8K9EPk4K+5R+P2kD8J8KvEIGxVa1vz8QoCJ/jr7Ka2rvNgPCex5/E
+080LzLHPCrXKdlr/f50yhNWq08ZxMWQFkui+FDHPDUaEELKAXV8/5PDxw80Rtybo
+AVYoCVIbZXZCuCO81op8UcOgEpTtyU5Lgh3Mw5scQL0=
+-----END RSA PRIVATE KEY-----`),
+ },
+ {
+ kind: "AES-192-CBC",
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,E2C9FB02BCA23ADE1829F8D8BC5F5369
+
+cqVslvHqDDM6qwU6YjezCRifXmKsrgEev7ng6Qs7UmDJOpHDgJQZI9fwMFUhIyn5
+FbCu1SHkLMW52Ld3CuEqMnzWMlhPrW8tFvUOrMWPYSisv7nNq88HobZEJcUNL2MM
+Y15XmHW6IJwPqhKyLHpWXyOCVEh4ODND2nV15PCoi18oTa475baxSk7+1qH7GuIs
+Rb7tshNTMqHbCpyo9Rn3UxeFIf9efdl8YLiMoIqc7J8E5e9VlbeQSdLMQOgDAQJG
+ReUtTw8exmKsY4gsSjhkg5uiw7/ZB1Ihto0qnfQJgjGc680qGkT1d6JfvOfeYAk6
+xn5RqS/h8rYAYm64KnepfC9vIujo4NqpaREDmaLdX5MJPQ+SlytITQvgUsUq3q/t
+Ss85xjQEZH3hzwjQqdJvmA4hYP6SUjxYpBM+02xZ1Xw=
+-----END RSA PRIVATE KEY-----`),
+ },
+ {
+ kind: "AES-256-CBC",
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,8E7ED5CD731902CE938957A886A5FFBD
+
+4Mxr+KIzRVwoOP0wwq6caSkvW0iS+GE2h2Ov/u+n9ZTMwL83PRnmjfjzBgfRZLVf
+JFPXxUK26kMNpIdssNnqGOds+DhB+oSrsNKoxgxSl5OBoYv9eJTVYm7qOyAFIsjr
+DRKAcjYCmzfesr7PVTowwy0RtHmYwyXMGDlAzzZrEvaiySFFmMyKKvtoavwaFoc7
+Pz3RZScwIuubzTGJ1x8EzdffYOsdCa9Mtgpp3L136+23dOd6L/qK2EG2fzrJSHs/
+2XugkleBFSMKzEp9mxXKRfa++uidQvMZTFLDK9w5YjrRvMBo/l2BoZIsq0jAIE1N
+sv5Z/KwlX+3MDEpPQpUwGPlGGdLnjI3UZ+cjgqBcoMiNc6HfgbBgYJSU6aDSHuCk
+clCwByxWkBNgJ2GrkwNrF26v+bGJJJNR4SKouY1jQf0=
+-----END RSA PRIVATE KEY-----`),
+ },
+}
diff --git a/libgo/go/crypto/x509/pkcs8.go b/libgo/go/crypto/x509/pkcs8.go
index 4d8e0518e02..8c3b65f8078 100644
--- a/libgo/go/crypto/x509/pkcs8.go
+++ b/libgo/go/crypto/x509/pkcs8.go
@@ -28,7 +28,7 @@ func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
return nil, err
}
switch {
- case privKey.Algo.Algorithm.Equal(oidRSA):
+ case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA):
key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
if err != nil {
return nil, errors.New("crypto/x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
diff --git a/libgo/go/crypto/x509/root_plan9.go b/libgo/go/crypto/x509/root_plan9.go
new file mode 100644
index 00000000000..677927a3b63
--- /dev/null
+++ b/libgo/go/crypto/x509/root_plan9.go
@@ -0,0 +1,31 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build plan9
+
+package x509
+
+import "io/ioutil"
+
+// Possible certificate files; stop after finding one.
+var certFiles = []string{
+ "/sys/lib/tls/ca.pem",
+}
+
+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
+ return nil, nil
+}
+
+func initSystemRoots() {
+ roots := NewCertPool()
+ for _, file := range certFiles {
+ data, err := ioutil.ReadFile(file)
+ if err == nil {
+ roots.AppendCertsFromPEM(data)
+ break
+ }
+ }
+
+ systemRoots = roots
+}
diff --git a/libgo/go/crypto/x509/root_stub.go b/libgo/go/crypto/x509/root_stub.go
index 568004108b5..756732f7d4f 100644
--- a/libgo/go/crypto/x509/root_stub.go
+++ b/libgo/go/crypto/x509/root_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build plan9 darwin,!cgo
+// +build darwin,!cgo
package x509
diff --git a/libgo/go/crypto/x509/root_windows.go b/libgo/go/crypto/x509/root_windows.go
index 7e8f2af4b0e..96ca57b420d 100644
--- a/libgo/go/crypto/x509/root_windows.go
+++ b/libgo/go/crypto/x509/root_windows.go
@@ -98,9 +98,13 @@ func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) e
// checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for
// use as a certificate chain for a SSL/TLS server.
func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error {
+ servernamep, err := syscall.UTF16PtrFromString(opts.DNSName)
+ if err != nil {
+ return err
+ }
sslPara := &syscall.SSLExtraCertChainPolicyPara{
AuthType: syscall.AUTHTYPE_SERVER,
- ServerName: syscall.StringToUTF16Ptr(opts.DNSName),
+ ServerName: servernamep,
}
sslPara.Size = uint32(unsafe.Sizeof(*sslPara))
@@ -110,7 +114,7 @@ func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContex
para.Size = uint32(unsafe.Sizeof(*para))
status := syscall.CertChainPolicyStatus{}
- err := syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status)
+ err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status)
if err != nil {
return err
}
diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go
index 28814539d13..68929c7bb68 100644
--- a/libgo/go/crypto/x509/verify.go
+++ b/libgo/go/crypto/x509/verify.go
@@ -27,6 +27,9 @@ const (
// TooManyIntermediates results when a path length constraint is
// violated.
TooManyIntermediates
+ // IncompatibleUsage results when the certificate's key usage indicates
+ // that it may only be used for a different purpose.
+ IncompatibleUsage
)
// CertificateInvalidError results when an odd error occurs. Users of this
@@ -46,6 +49,8 @@ func (e CertificateInvalidError) Error() string {
return "x509: a root or intermediate certificate is not authorized to sign in this domain"
case TooManyIntermediates:
return "x509: too many intermediates for path length constraint"
+ case IncompatibleUsage:
+ return "x509: certificate specifies an incompatible key usage"
}
return "x509: unknown error"
}
@@ -84,6 +89,11 @@ type VerifyOptions struct {
Intermediates *CertPool
Roots *CertPool // if nil, the system roots are used
CurrentTime time.Time // if zero, the current time is used
+ // KeyUsage specifies which Extended Key Usage values are acceptable.
+ // An empty list means ExtKeyUsageServerAuth. Key usage is considered a
+ // constraint down the chain which mirrors Windows CryptoAPI behaviour,
+ // but not the spec. To accept any key usage, include ExtKeyUsageAny.
+ KeyUsages []ExtKeyUsage
}
const (
@@ -174,7 +184,35 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
}
}
- return c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
+ candidateChains, err := c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
+ if err != nil {
+ return
+ }
+
+ keyUsages := opts.KeyUsages
+ if len(keyUsages) == 0 {
+ keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
+ }
+
+ // If any key usage is acceptable then we're done.
+ for _, usage := range keyUsages {
+ if usage == ExtKeyUsageAny {
+ chains = candidateChains
+ return
+ }
+ }
+
+ for _, candidate := range candidateChains {
+ if checkChainForKeyUsage(candidate, keyUsages) {
+ chains = append(chains, candidate)
+ }
+ }
+
+ if len(chains) == 0 {
+ err = CertificateInvalidError{c, IncompatibleUsage}
+ }
+
+ return
}
func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
@@ -300,3 +338,56 @@ func (c *Certificate) VerifyHostname(h string) error {
return HostnameError{c, h}
}
+
+func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
+ usages := make([]ExtKeyUsage, len(keyUsages))
+ copy(usages, keyUsages)
+
+ if len(chain) == 0 {
+ return false
+ }
+
+ usagesRemaining := len(usages)
+
+ // We walk down the list and cross out any usages that aren't supported
+ // by each certificate. If we cross out all the usages, then the chain
+ // is unacceptable.
+
+ for i := len(chain) - 1; i >= 0; i-- {
+ cert := chain[i]
+ if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
+ // The certificate doesn't have any extended key usage specified.
+ continue
+ }
+
+ for _, usage := range cert.ExtKeyUsage {
+ if usage == ExtKeyUsageAny {
+ // The certificate is explicitly good for any usage.
+ continue
+ }
+ }
+
+ const invalidUsage ExtKeyUsage = -1
+
+ NextRequestedUsage:
+ for i, requestedUsage := range usages {
+ if requestedUsage == invalidUsage {
+ continue
+ }
+
+ for _, usage := range cert.ExtKeyUsage {
+ if requestedUsage == usage {
+ continue NextRequestedUsage
+ }
+ }
+
+ usages[i] = invalidUsage
+ usagesRemaining--
+ if usagesRemaining == 0 {
+ return false
+ }
+ }
+ }
+
+ return true
+}
diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go
index 7b171b291a4..510a119ff7c 100644
--- a/libgo/go/crypto/x509/verify_test.go
+++ b/libgo/go/crypto/x509/verify_test.go
@@ -21,6 +21,7 @@ type verifyTest struct {
currentTime int64
dnsName string
systemSkip bool
+ keyUsages []ExtKeyUsage
errorCallback func(*testing.T, int, error) bool
expectedChains [][]string
@@ -113,6 +114,38 @@ var verifyTests = []verifyTest{
{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority", "StartCom Certification Authority"},
},
},
+ {
+ // The default configuration should reject an S/MIME chain.
+ leaf: smimeLeaf,
+ roots: []string{smimeIntermediate},
+ currentTime: 1339436154,
+
+ // Key usage not implemented for Windows yet.
+ systemSkip: true,
+ errorCallback: expectUsageError,
+ },
+ {
+ leaf: smimeLeaf,
+ roots: []string{smimeIntermediate},
+ currentTime: 1339436154,
+ keyUsages: []ExtKeyUsage{ExtKeyUsageServerAuth},
+
+ // Key usage not implemented for Windows yet.
+ systemSkip: true,
+ errorCallback: expectUsageError,
+ },
+ {
+ leaf: smimeLeaf,
+ roots: []string{smimeIntermediate},
+ currentTime: 1339436154,
+ keyUsages: []ExtKeyUsage{ExtKeyUsageEmailProtection},
+
+ // Key usage not implemented for Windows yet.
+ systemSkip: true,
+ expectedChains: [][]string{
+ {"Ryan Hurst", "GlobalSign PersonalSign 2 CA - G2"},
+ },
+ },
}
func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
@@ -131,6 +164,14 @@ func expectExpired(t *testing.T, i int, err error) (ok bool) {
return true
}
+func expectUsageError(t *testing.T, i int, err error) (ok bool) {
+ if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != IncompatibleUsage {
+ t.Errorf("#%d: error was not IncompatibleUsage: %s", i, err)
+ return false
+ }
+ return true
+}
+
func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) {
if _, ok := err.(UnknownAuthorityError); !ok {
t.Errorf("#%d: error was not UnknownAuthorityError: %s", i, err)
@@ -157,6 +198,7 @@ func testVerify(t *testing.T, useSystemRoots bool) {
Intermediates: NewCertPool(),
DNSName: test.dnsName,
CurrentTime: time.Unix(test.currentTime, 0),
+ KeyUsages: test.keyUsages,
}
if !useSystemRoots {
@@ -433,3 +475,58 @@ O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
-----END CERTIFICATE-----`
+
+const smimeLeaf = `-----BEGIN CERTIFICATE-----
+MIIFBjCCA+6gAwIBAgISESFvrjT8XcJTEe6rBlPptILlMA0GCSqGSIb3DQEBBQUA
+MFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSowKAYD
+VQQDEyFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiAyIENBIC0gRzIwHhcNMTIwMTIz
+MTYzNjU5WhcNMTUwMTIzMTYzNjU5WjCBlDELMAkGA1UEBhMCVVMxFjAUBgNVBAgT
+DU5ldyBIYW1zcGhpcmUxEzARBgNVBAcTClBvcnRzbW91dGgxGTAXBgNVBAoTEEds
+b2JhbFNpZ24sIEluYy4xEzARBgNVBAMTClJ5YW4gSHVyc3QxKDAmBgkqhkiG9w0B
+CQEWGXJ5YW4uaHVyc3RAZ2xvYmFsc2lnbi5jb20wggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQC4ASSTvavmsFQAob60ukSSwOAL9nT/s99ltNUCAf5fPH5j
+NceMKxaQse2miOmRRIXaykcq1p/TbI70Ztce38r2mbOwqDHHPVi13GxJEyUXWgaR
+BteDMu5OGyWNG1kchVsGWpbstT0Z4v0md5m1BYFnxB20ebJyOR2lXDxsFK28nnKV
++5eMj76U8BpPQ4SCH7yTMG6y0XXsB3cCrBKr2o3TOYgEKv+oNnbaoMt3UxMt9nSf
+9jyIshjqfnT5Aew3CUNMatO55g5FXXdIukAweg1YSb1ls05qW3sW00T3d7dQs9/7
+NuxCg/A2elmVJSoy8+MLR8JSFEf/aMgjO/TyLg/jAgMBAAGjggGPMIIBizAOBgNV
+HQ8BAf8EBAMCBaAwTQYDVR0gBEYwRDBCBgorBgEEAaAyASgKMDQwMgYIKwYBBQUH
+AgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMCQGA1Ud
+EQQdMBuBGXJ5YW4uaHVyc3RAZ2xvYmFsc2lnbi5jb20wCQYDVR0TBAIwADAdBgNV
+HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwQwYDVR0fBDwwOjA4oDagNIYyaHR0
+cDovL2NybC5nbG9iYWxzaWduLmNvbS9ncy9nc3BlcnNvbmFsc2lnbjJnMi5jcmww
+VQYIKwYBBQUHAQEESTBHMEUGCCsGAQUFBzAChjlodHRwOi8vc2VjdXJlLmdsb2Jh
+bHNpZ24uY29tL2NhY2VydC9nc3BlcnNvbmFsc2lnbjJnMi5jcnQwHQYDVR0OBBYE
+FFWiECe0/L72eVYqcWYnLV6SSjzhMB8GA1UdIwQYMBaAFD8V0m18L+cxnkMKBqiU
+bCw7xe5lMA0GCSqGSIb3DQEBBQUAA4IBAQAhQi6hLPeudmf3IBF4IDzCvRI0FaYd
+BKfprSk/H0PDea4vpsLbWpA0t0SaijiJYtxKjlM4bPd+2chb7ejatDdyrZIzmDVy
+q4c30/xMninGKokpYA11/Ve+i2dvjulu65qasrtQRGybAuuZ67lrp/K3OMFgjV5N
+C3AHYLzvNU4Dwc4QQ1BaMOg6KzYSrKbABRZajfrpC9uiePsv7mDIXLx/toBPxWNl
+a5vJm5DrZdn7uHdvBCE6kMykbOLN5pmEK0UIlwKh6Qi5XD0pzlVkEZliFkBMJgub
+d/eF7xeg7TKPWC5xyOFp9SdMolJM7LTC3wnSO3frBAev+q/nGs9Xxyvs
+-----END CERTIFICATE-----`
+
+const smimeIntermediate = `-----BEGIN CERTIFICATE-----
+MIIEFjCCAv6gAwIBAgILBAAAAAABL07hL1IwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0MTMxMDAw
+MDBaFw0xOTA0MTMxMDAwMDBaMFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMSowKAYDVQQDEyFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiAy
+IENBIC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBa0H5Nez4
+En3dIlFpX7e5E0YndxQ74xOBbz7kdBd+DLX0LOQMjVPU3DAgKL9ujhH+ZhHkURbH
+3X/94TQSUL/z2JjsaQvS0NqyZXHhM5eeuquzOJRzEQ8+odETzHg2G0Erv7yjSeww
+gkwDWDJnYUDlOjYTDUEG6+i+8Mn425reo4I0E277wD542kmVWeW7+oHv5dZo9e1Q
+yWwiKTEP6BEQVVSBgThXMG4traSSDRUt3T1eQTZx5EObpiBEBO4OTqiBTJfg4vEI
+YgkXzKLpnfszTB6YMDpR9/QS6p3ANB3kfAb+t6udSO3WCst0DGrwHDLBFGDR4UeY
+T5KGGnI7cWL7AgMBAAGjgeUwgeIwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI
+MAYBAf8CAQAwHQYDVR0OBBYEFD8V0m18L+cxnkMKBqiUbCw7xe5lMEcGA1UdIARA
+MD4wPAYEVR0gADA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWdu
+LmNvbS9yZXBvc2l0b3J5LzAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmds
+b2JhbHNpZ24ubmV0L3Jvb3QuY3JsMB8GA1UdIwQYMBaAFGB7ZhpFDZfKiVAvfQTN
+NKj//P1LMA0GCSqGSIb3DQEBBQUAA4IBAQBDc3nMpMxJMQMcYUCB3+C73UpvwDE8
+eCOr7t2F/uaQKKcyqqstqLZc6vPwI/rcE9oDHugY5QEjQzIBIEaTnN6P0vege2IX
+eCOr7t2F/uaQKKcyqqstqLZc6vPwI/rcE9oDHugY5QEjQzIBIEaTnN6P0vege2IX
+YEvTWbWwGdPytDFPYIl3/6OqNSXSnZ7DxPcdLJq2uyiga8PB/TTIIHYkdM2+1DE0
+7y3rH/7TjwDVD7SLu5/SdOfKskuMPTjOEvz3K161mymW06klVhubCIWOro/Gx1Q2
+2FQOZ7/2k4uYoOdBTSlb8kTAuzZNgIE0rB2BIYCTz/P6zZIKW0ogbRSH
+-----END CERTIFICATE-----`
diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go
index e6b0c58eef5..cfefbc5acec 100644
--- a/libgo/go/crypto/x509/x509.go
+++ b/libgo/go/crypto/x509/x509.go
@@ -9,6 +9,8 @@ import (
"bytes"
"crypto"
"crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
"crypto/rsa"
"crypto/sha1"
"crypto/x509/pkix"
@@ -106,6 +108,8 @@ type dsaSignature struct {
R, S *big.Int
}
+type ecdsaSignature dsaSignature
+
type validity struct {
NotBefore, NotAfter time.Time
}
@@ -133,6 +137,10 @@ const (
SHA512WithRSA
DSAWithSHA1
DSAWithSHA256
+ ECDSAWithSHA1
+ ECDSAWithSHA256
+ ECDSAWithSHA384
+ ECDSAWithSHA512
)
type PublicKeyAlgorithm int
@@ -141,6 +149,7 @@ const (
UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota
RSA
DSA
+ ECDSA
)
// OIDs for signature algorithms
@@ -160,6 +169,12 @@ const (
// dsaWithSha1 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 }
//
+// RFC 3279 2.2.3 ECDSA Signature Algorithm
+//
+// ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
+// iso(1) member-body(2) us(840) ansi-x962(10045)
+// signatures(4) ecdsa-with-SHA1(1)}
+//
//
// RFC 4055 5 PKCS #1 Version 1.5
//
@@ -176,15 +191,30 @@ const (
// joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101)
// csor(3) algorithms(4) id-dsa-with-sha2(3) 2}
//
+// RFC 5758 3.2 ECDSA Signature Algorithm
+//
+// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
+//
+// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
+//
+// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
+
var (
- oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
- oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
- oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
- oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
- oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
- oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
- oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
- oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
+ oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
+ oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
+ oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
+ oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
+ oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
+ oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
+ oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
+ oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
+ oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
+ oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
+ oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
+ oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
)
func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm {
@@ -205,6 +235,14 @@ func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm
return DSAWithSHA1
case oid.Equal(oidSignatureDSAWithSHA256):
return DSAWithSHA256
+ case oid.Equal(oidSignatureECDSAWithSHA1):
+ return ECDSAWithSHA1
+ case oid.Equal(oidSignatureECDSAWithSHA256):
+ return ECDSAWithSHA256
+ case oid.Equal(oidSignatureECDSAWithSHA384):
+ return ECDSAWithSHA384
+ case oid.Equal(oidSignatureECDSAWithSHA512):
+ return ECDSAWithSHA512
}
return UnknownSignatureAlgorithm
}
@@ -218,21 +256,81 @@ func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm
//
// id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
// x9-57(10040) x9cm(4) 1 }
+//
+// RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters
+//
+// id-ecPublicKey OBJECT IDENTIFIER ::= {
+// iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
var (
- oidPublicKeyRsa = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
- oidPublicKeyDsa = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
+ oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
+ oidPublicKeyDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
+ oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
)
func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm {
switch {
- case oid.Equal(oidPublicKeyRsa):
+ case oid.Equal(oidPublicKeyRSA):
return RSA
- case oid.Equal(oidPublicKeyDsa):
+ case oid.Equal(oidPublicKeyDSA):
return DSA
+ case oid.Equal(oidPublicKeyECDSA):
+ return ECDSA
}
return UnknownPublicKeyAlgorithm
}
+// RFC 5480, 2.1.1.1. Named Curve
+//
+// secp224r1 OBJECT IDENTIFIER ::= {
+// iso(1) identified-organization(3) certicom(132) curve(0) 33 }
+//
+// secp256r1 OBJECT IDENTIFIER ::= {
+// iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
+// prime(1) 7 }
+//
+// secp384r1 OBJECT IDENTIFIER ::= {
+// iso(1) identified-organization(3) certicom(132) curve(0) 34 }
+//
+// secp521r1 OBJECT IDENTIFIER ::= {
+// iso(1) identified-organization(3) certicom(132) curve(0) 35 }
+//
+// NB: secp256r1 is equivalent to prime256v1
+var (
+ oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
+ oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
+ oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
+ oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
+)
+
+func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
+ switch {
+ case oid.Equal(oidNamedCurveP224):
+ return elliptic.P224()
+ case oid.Equal(oidNamedCurveP256):
+ return elliptic.P256()
+ case oid.Equal(oidNamedCurveP384):
+ return elliptic.P384()
+ case oid.Equal(oidNamedCurveP521):
+ return elliptic.P521()
+ }
+ return nil
+}
+
+func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
+ switch curve {
+ case elliptic.P224():
+ return oidNamedCurveP224, true
+ case elliptic.P256():
+ return oidNamedCurveP256, true
+ case elliptic.P384():
+ return oidNamedCurveP384, true
+ case elliptic.P521():
+ return oidNamedCurveP521, true
+ }
+
+ return nil, false
+}
+
// KeyUsage represents the set of actions that are valid for a given key. It's
// a bitmap of the KeyUsage* constants.
type KeyUsage int
@@ -267,6 +365,9 @@ var (
oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
+ oidExtKeyUsageIPSECEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5}
+ oidExtKeyUsageIPSECTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6}
+ oidExtKeyUsageIPSECUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7}
oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
)
@@ -281,10 +382,48 @@ const (
ExtKeyUsageClientAuth
ExtKeyUsageCodeSigning
ExtKeyUsageEmailProtection
+ ExtKeyUsageIPSECEndSystem
+ ExtKeyUsageIPSECTunnel
+ ExtKeyUsageIPSECUser
ExtKeyUsageTimeStamping
ExtKeyUsageOCSPSigning
)
+// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID.
+var extKeyUsageOIDs = []struct {
+ extKeyUsage ExtKeyUsage
+ oid asn1.ObjectIdentifier
+}{
+ {ExtKeyUsageAny, oidExtKeyUsageAny},
+ {ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth},
+ {ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth},
+ {ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning},
+ {ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection},
+ {ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem},
+ {ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel},
+ {ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser},
+ {ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping},
+ {ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning},
+}
+
+func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) {
+ for _, pair := range extKeyUsageOIDs {
+ if oid.Equal(pair.oid) {
+ return pair.extKeyUsage, true
+ }
+ }
+ return
+}
+
+func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) {
+ for _, pair := range extKeyUsageOIDs {
+ if eku == pair.extKeyUsage {
+ return pair.oid, true
+ }
+ }
+ return
+}
+
// A Certificate represents an X.509 certificate.
type Certificate struct {
Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
@@ -427,13 +566,13 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
var hashType crypto.Hash
switch algo {
- case SHA1WithRSA, DSAWithSHA1:
+ case SHA1WithRSA, DSAWithSHA1, ECDSAWithSHA1:
hashType = crypto.SHA1
- case SHA256WithRSA, DSAWithSHA256:
+ case SHA256WithRSA, DSAWithSHA256, ECDSAWithSHA256:
hashType = crypto.SHA256
- case SHA384WithRSA:
+ case SHA384WithRSA, ECDSAWithSHA384:
hashType = crypto.SHA384
- case SHA512WithRSA:
+ case SHA512WithRSA, ECDSAWithSHA512:
hashType = crypto.SHA512
default:
return ErrUnsupportedAlgorithm
@@ -462,6 +601,18 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
return errors.New("DSA verification failure")
}
return
+ case *ecdsa.PublicKey:
+ ecdsaSig := new(ecdsaSignature)
+ if _, err := asn1.Unmarshal(signature, ecdsaSig); err != nil {
+ return err
+ }
+ if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+ return errors.New("crypto/x509: ECDSA signature contained zero or negative values")
+ }
+ if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) {
+ return errors.New("crypto/x509: ECDSA verification failure")
+ }
+ return
}
return ErrUnsupportedAlgorithm
}
@@ -497,8 +648,6 @@ type nameConstraints struct {
type generalSubtree struct {
Name string `asn1:"tag:2,optional,ia5"`
- Min int `asn1:"optional,tag:0"`
- Max int `asn1:"optional,tag:1"`
}
func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
@@ -540,6 +689,27 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
Y: p,
}
return pub, nil
+ case ECDSA:
+ paramsData := keyData.Algorithm.Parameters.FullBytes
+ namedCurveOID := new(asn1.ObjectIdentifier)
+ _, err := asn1.Unmarshal(paramsData, namedCurveOID)
+ if err != nil {
+ return nil, err
+ }
+ namedCurve := namedCurveFromOID(*namedCurveOID)
+ if namedCurve == nil {
+ return nil, errors.New("crypto/x509: unsupported elliptic curve")
+ }
+ x, y := elliptic.Unmarshal(namedCurve, asn1Data)
+ if x == nil {
+ return nil, errors.New("crypto/x509: failed to unmarshal elliptic curve point")
+ }
+ pub := &ecdsa.PublicKey{
+ Curve: namedCurve,
+ X: x,
+ Y: y,
+ }
+ return pub, nil
default:
return nil, nil
}
@@ -694,7 +864,7 @@ func parseCertificate(in *certificate) (*Certificate, error) {
}
for _, subtree := range constraints.Permitted {
- if subtree.Min > 0 || subtree.Max > 0 || len(subtree.Name) == 0 {
+ if len(subtree.Name) == 0 {
if e.Critical {
return out, UnhandledCriticalExtension{}
}
@@ -730,22 +900,9 @@ func parseCertificate(in *certificate) (*Certificate, error) {
}
for _, u := range keyUsage {
- switch {
- case u.Equal(oidExtKeyUsageAny):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageAny)
- case u.Equal(oidExtKeyUsageServerAuth):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageServerAuth)
- case u.Equal(oidExtKeyUsageClientAuth):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageClientAuth)
- case u.Equal(oidExtKeyUsageCodeSigning):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageCodeSigning)
- case u.Equal(oidExtKeyUsageEmailProtection):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageEmailProtection)
- case u.Equal(oidExtKeyUsageTimeStamping):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageTimeStamping)
- case u.Equal(oidExtKeyUsageOCSPSigning):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageOCSPSigning)
- default:
+ if extKeyUsage, ok := extKeyUsageFromOID(u); ok {
+ out.ExtKeyUsage = append(out.ExtKeyUsage, extKeyUsage)
+ } else {
out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u)
}
}
@@ -834,6 +991,7 @@ func reverseBitsInAByte(in byte) byte {
var (
oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
oidExtensionKeyUsage = []int{2, 5, 29, 15}
+ oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37}
oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
oidExtensionBasicConstraints = []int{2, 5, 29, 19}
oidExtensionSubjectAltName = []int{2, 5, 29, 17}
@@ -842,7 +1000,7 @@ var (
)
func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
- ret = make([]pkix.Extension, 7 /* maximum number of elements. */)
+ ret = make([]pkix.Extension, 8 /* maximum number of elements. */)
n := 0
if template.KeyUsage != 0 {
@@ -865,6 +1023,27 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
+ if len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0 {
+ ret[n].Id = oidExtensionExtendedKeyUsage
+
+ var oids []asn1.ObjectIdentifier
+ for _, u := range template.ExtKeyUsage {
+ if oid, ok := oidFromExtKeyUsage(u); ok {
+ oids = append(oids, oid)
+ } else {
+ panic("internal error")
+ }
+ }
+
+ oids = append(oids, template.UnknownExtKeyUsage...)
+
+ ret[n].Value, err = asn1.Marshal(oids)
+ if err != nil {
+ return
+ }
+ n++
+ }
+
if template.BasicConstraintsValid {
ret[n].Id = oidExtensionBasicConstraints
ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, template.MaxPathLen})
@@ -941,11 +1120,6 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
return ret[0:n], nil
}
-var (
- oidSHA1WithRSA = []int{1, 2, 840, 113549, 1, 1, 5}
- oidRSA = []int{1, 2, 840, 113549, 1, 1, 1}
-)
-
func subjectBytes(cert *Certificate) ([]byte, error) {
if len(cert.RawSubject) > 0 {
return cert.RawSubject, nil
@@ -956,8 +1130,9 @@ func subjectBytes(cert *Certificate) ([]byte, error) {
// CreateCertificate creates a new certificate based on a template. The
// following members of template are used: SerialNumber, Subject, NotBefore,
-// NotAfter, KeyUsage, BasicConstraintsValid, IsCA, MaxPathLen, SubjectKeyId,
-// DNSNames, PermittedDNSDomainsCritical, PermittedDNSDomains.
+// NotAfter, KeyUsage, ExtKeyUsage, UnknownExtKeyUsage, BasicConstraintsValid,
+// IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
+// PermittedDNSDomains.
//
// The certificate is signed by parent. If parent is equal to template then the
// certificate is self-signed. The parameter pub is the public key of the
@@ -965,23 +1140,61 @@ func subjectBytes(cert *Certificate) ([]byte, error) {
//
// The returned slice is the certificate in DER encoding.
//
-// The only supported key type is RSA (*rsa.PublicKey for pub, *rsa.PrivateKey
-// for priv).
+// The only supported key types are RSA and ECDSA (*rsa.PublicKey or
+// *ecdsa.PublicKey for pub, *rsa.PrivateKey or *ecdsa.PublicKey for priv).
func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interface{}, priv interface{}) (cert []byte, err error) {
- rsaPub, ok := pub.(*rsa.PublicKey)
- if !ok {
- return nil, errors.New("x509: non-RSA public keys not supported")
+ var publicKeyBytes []byte
+ var publicKeyAlgorithm pkix.AlgorithmIdentifier
+
+ switch pub := pub.(type) {
+ case *rsa.PublicKey:
+ publicKeyBytes, err = asn1.Marshal(rsaPublicKey{
+ N: pub.N,
+ E: pub.E,
+ })
+ publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
+ case *ecdsa.PublicKey:
+ oid, ok := oidFromNamedCurve(pub.Curve)
+ if !ok {
+ return nil, errors.New("x509: unknown elliptic curve")
+ }
+ publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
+ var paramBytes []byte
+ paramBytes, err = asn1.Marshal(oid)
+ if err != nil {
+ return
+ }
+ publicKeyAlgorithm.Parameters.FullBytes = paramBytes
+ publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
+ default:
+ return nil, errors.New("x509: only RSA and ECDSA public keys supported")
}
- rsaPriv, ok := priv.(*rsa.PrivateKey)
- if !ok {
- return nil, errors.New("x509: non-RSA private keys not supported")
+ var signatureAlgorithm pkix.AlgorithmIdentifier
+ var hashFunc crypto.Hash
+
+ switch priv := priv.(type) {
+ case *rsa.PrivateKey:
+ signatureAlgorithm.Algorithm = oidSignatureSHA1WithRSA
+ hashFunc = crypto.SHA1
+ case *ecdsa.PrivateKey:
+ switch priv.Curve {
+ case elliptic.P224(), elliptic.P256():
+ hashFunc = crypto.SHA256
+ signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA256
+ case elliptic.P384():
+ hashFunc = crypto.SHA384
+ signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA384
+ case elliptic.P521():
+ hashFunc = crypto.SHA512
+ signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA512
+ default:
+ return nil, errors.New("x509: unknown elliptic curve")
+ }
+ default:
+ return nil, errors.New("x509: only RSA and ECDSA private keys supported")
}
- asn1PublicKey, err := asn1.Marshal(rsaPublicKey{
- N: rsaPub.N,
- E: rsaPub.E,
- })
if err != nil {
return
}
@@ -1005,15 +1218,15 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
return
}
- encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey}
+ encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
c := tbsCertificate{
Version: 2,
SerialNumber: template.SerialNumber,
- SignatureAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
+ SignatureAlgorithm: signatureAlgorithm,
Issuer: asn1.RawValue{FullBytes: asn1Issuer},
Validity: validity{template.NotBefore, template.NotAfter},
Subject: asn1.RawValue{FullBytes: asn1Subject},
- PublicKey: publicKeyInfo{nil, pkix.AlgorithmIdentifier{Algorithm: oidRSA}, encodedPublicKey},
+ PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
Extensions: extensions,
}
@@ -1024,11 +1237,24 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
c.Raw = tbsCertContents
- h := sha1.New()
+ h := hashFunc.New()
h.Write(tbsCertContents)
digest := h.Sum(nil)
- signature, err := rsa.SignPKCS1v15(rand, rsaPriv, crypto.SHA1, digest)
+ var signature []byte
+
+ switch priv := priv.(type) {
+ case *rsa.PrivateKey:
+ signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest)
+ case *ecdsa.PrivateKey:
+ var r, s *big.Int
+ if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil {
+ signature, err = asn1.Marshal(ecdsaSignature{r, s})
+ }
+ default:
+ panic("internal error")
+ }
+
if err != nil {
return
}
@@ -1036,7 +1262,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
cert, err = asn1.Marshal(certificate{
nil,
c,
- pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
+ signatureAlgorithm,
asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
})
return
diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go
index f0327b0124d..a13f4598d58 100644
--- a/libgo/go/crypto/x509/x509_test.go
+++ b/libgo/go/crypto/x509/x509_test.go
@@ -7,14 +7,19 @@ package x509
import (
"bytes"
"crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
"crypto/rand"
"crypto/rsa"
+ _ "crypto/sha256"
+ _ "crypto/sha512"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/base64"
"encoding/hex"
"encoding/pem"
"math/big"
+ "reflect"
"testing"
"time"
)
@@ -237,65 +242,205 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
random := rand.Reader
block, _ := pem.Decode([]byte(pemPrivateKey))
- priv, err := ParsePKCS1PrivateKey(block.Bytes)
+ rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
- t.Errorf("Failed to parse private key: %s", err)
- return
+ t.Fatalf("Failed to parse private key: %s", err)
}
- commonName := "test.example.com"
- template := Certificate{
- SerialNumber: big.NewInt(1),
- Subject: pkix.Name{
- CommonName: commonName,
- Organization: []string{"Acme Co"},
- },
- NotBefore: time.Unix(1000, 0),
- NotAfter: time.Unix(100000, 0),
+ ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatalf("Failed to generate ECDSA key: %s", err)
+ }
+
+ tests := []struct {
+ name string
+ pub, priv interface{}
+ checkSig bool
+ }{
+ {"RSA/RSA", &rsaPriv.PublicKey, rsaPriv, true},
+ {"RSA/ECDSA", &rsaPriv.PublicKey, ecdsaPriv, false},
+ {"ECDSA/RSA", &ecdsaPriv.PublicKey, rsaPriv, false},
+ {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true},
+ }
+
+ testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
+ testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{3, 2, 1}}
+
+ for _, test := range tests {
+ commonName := "test.example.com"
+ template := Certificate{
+ SerialNumber: big.NewInt(1),
+ Subject: pkix.Name{
+ CommonName: commonName,
+ Organization: []string{"Σ Acme Co"},
+ },
+ NotBefore: time.Unix(1000, 0),
+ NotAfter: time.Unix(100000, 0),
+
+ SubjectKeyId: []byte{1, 2, 3, 4},
+ KeyUsage: KeyUsageCertSign,
+
+ ExtKeyUsage: testExtKeyUsage,
+ UnknownExtKeyUsage: testUnknownExtKeyUsage,
+
+ BasicConstraintsValid: true,
+ IsCA: true,
+ DNSNames: []string{"test.example.com"},
+
+ PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
+ PermittedDNSDomains: []string{".example.com", "example.com"},
+ }
- SubjectKeyId: []byte{1, 2, 3, 4},
- KeyUsage: KeyUsageCertSign,
+ derBytes, err := CreateCertificate(random, &template, &template, test.pub, test.priv)
+ if err != nil {
+ t.Errorf("%s: failed to create certificate: %s", test.name, err)
+ continue
+ }
- BasicConstraintsValid: true,
- IsCA: true,
- DNSNames: []string{"test.example.com"},
+ cert, err := ParseCertificate(derBytes)
+ if err != nil {
+ t.Errorf("%s: failed to parse certificate: %s", test.name, err)
+ continue
+ }
- PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
- PermittedDNSDomains: []string{".example.com", "example.com"},
- }
+ if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
+ t.Errorf("%s: failed to parse policy identifiers: got:%#v want:%#v", test.name, cert.PolicyIdentifiers, template.PolicyIdentifiers)
+ }
- derBytes, err := CreateCertificate(random, &template, &template, &priv.PublicKey, priv)
- if err != nil {
- t.Errorf("Failed to create certificate: %s", err)
- return
- }
+ if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
+ t.Errorf("%s: failed to parse name constraints: %#v", test.name, cert.PermittedDNSDomains)
+ }
- cert, err := ParseCertificate(derBytes)
- if err != nil {
- t.Errorf("Failed to parse certificate: %s", err)
- return
- }
+ if cert.Subject.CommonName != commonName {
+ t.Errorf("%s: subject wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Subject.CommonName, commonName)
+ }
- if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
- t.Errorf("Failed to parse policy identifiers: got:%#v want:%#v", cert.PolicyIdentifiers, template.PolicyIdentifiers)
- }
+ if cert.Issuer.CommonName != commonName {
+ t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName)
+ }
- if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
- t.Errorf("Failed to parse name constraints: %#v", cert.PermittedDNSDomains)
- }
+ if !reflect.DeepEqual(cert.ExtKeyUsage, testExtKeyUsage) {
+ t.Errorf("%s: extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.ExtKeyUsage, testExtKeyUsage)
+ }
- if cert.Subject.CommonName != commonName {
- t.Errorf("Subject wasn't correctly copied from the template. Got %s, want %s", cert.Subject.CommonName, commonName)
- }
+ if !reflect.DeepEqual(cert.UnknownExtKeyUsage, testUnknownExtKeyUsage) {
+ t.Errorf("%s: unknown extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.UnknownExtKeyUsage, testUnknownExtKeyUsage)
+ }
- if cert.Issuer.CommonName != commonName {
- t.Errorf("Issuer wasn't correctly copied from the template. Got %s, want %s", cert.Issuer.CommonName, commonName)
+ if test.checkSig {
+ err = cert.CheckSignatureFrom(cert)
+ if err != nil {
+ t.Errorf("%s: signature verification failed: %s", test.name, err)
+ }
+ }
}
+}
- err = cert.CheckSignatureFrom(cert)
- if err != nil {
- t.Errorf("Signature verification failed: %s", err)
- return
+// Self-signed certificate using ECDSA with SHA1 & secp256r1
+var ecdsaSHA1CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICDjCCAbUCCQDF6SfN0nsnrjAJBgcqhkjOPQQBMIGPMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMG
+A1UECgwMR29vZ2xlLCBJbmMuMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIwMjAyMDUw
+WhcNMjIwNTE4MjAyMDUwWjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTATBgNVBAoMDEdvb2dsZSwg
+SW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAhBgkqhkiG9w0BCQEWFGdv
+bGFuZy1kZXZAZ21haWwuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/Wgn
+WQDo5+bz71T0327ERgd5SDDXFbXLpzIZDXTkjpe8QTEbsF+ezsQfrekrpDPC4Cd3
+P9LY0tG+aI8IyVKdUjAJBgcqhkjOPQQBA0gAMEUCIGlsqMcRqWVIWTD6wXwe6Jk2
+DKxL46r/FLgJYnzBEH99AiEA3fBouObsvV1R3oVkb4BQYnD4/4LeId6lAT43YvyV
+a/A=
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA256 & secp256r1
+var ecdsaSHA256p256CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICDzCCAbYCCQDlsuMWvgQzhTAKBggqhkjOPQQDAjCBjzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
+BgNVBAoMDEdvb2dsZSwgSW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAh
+BgkqhkiG9w0BCQEWFGdvbGFuZy1kZXZAZ21haWwuY29tMB4XDTEyMDUyMTAwMTkx
+NloXDTIyMDUxOTAwMTkxNlowgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYDVQQKDAxHb29nbGUs
+IEluYy4xFzAVBgNVBAMMDnd3dy5nb29nbGUuY29tMSMwIQYJKoZIhvcNAQkBFhRn
+b2xhbmctZGV2QGdtYWlsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPMt
+2ErhxAty5EJRu9yM+MTy+hUXm3pdW1ensAv382KoGExSXAFWP7pjJnNtHO+XSwVm
+YNtqjcAGFKpweoN//kQwCgYIKoZIzj0EAwIDRwAwRAIgIYSaUA/IB81gjbIw/hUV
+70twxJr5EcgOo0hLp3Jm+EYCIFDO3NNcgmURbJ1kfoS3N/0O+irUtoPw38YoNkqJ
+h5wi
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA256 & secp384r1
+var ecdsaSHA256p384CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICSjCCAdECCQDje/no7mXkVzAKBggqhkjOPQQDAjCBjjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
+BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMDYxMDM0
+WhcNMjIwNTE5MDYxMDM0WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
+SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
+YW5nLWRldkBnbWFpbC5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARRuzRNIKRK
+jIktEmXanNmrTR/q/FaHXLhWRZ6nHWe26Fw7Rsrbk+VjGy4vfWtNn7xSFKrOu5ze
+qxKnmE0h5E480MNgrUiRkaGO2GMJJVmxx20aqkXOk59U8yGA4CghE6MwCgYIKoZI
+zj0EAwIDZwAwZAIwBZEN8gvmRmfeP/9C1PRLzODIY4JqWub2PLRT4mv9GU+yw3Gr
+PU9A3CHMdEcdw/MEAjBBO1lId8KOCh9UZunsSMfqXiVurpzmhWd6VYZ/32G+M+Mh
+3yILeYQzllt/g0rKVRk=
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA384 & secp521r1
+var ecdsaSHA384p521CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICljCCAfcCCQDhp1AFD/ahKjAKBggqhkjOPQQDAzCBjjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
+BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMTUwNDI5
+WhcNMjIwNTE5MTUwNDI5WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
+SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
+YW5nLWRldkBnbWFpbC5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACqx9Rv
+IssRs1LWYcNN+WffwlHw4Tv3y8/LIAA9MF1ZScIonU9nRMxt4a2uGJVCPDw6JHpz
+PaYc0E9puLoE9AfKpwFr59Jkot7dBg55SKPEFkddoip/rvmN7NPAWjMBirOwjOkm
+8FPthvPhGPqsu9AvgVuHu3PosWiHGNrhh379pva8MzAKBggqhkjOPQQDAwOBjAAw
+gYgCQgEHNmswkUdPpHqrVxp9PvLVl+xxPuHBkT+75z9JizyxtqykHQo9Uh6SWCYH
+BF9KLolo01wMt8DjoYP5Fb3j5MH7xwJCAbWZzTOp4l4DPkIvAh4LeC4VWbwPPyqh
+kBg71w/iEcSY3wUKgHGcJJrObZw7wys91I5kENljqw/Samdr3ka+jBJa
+-----END CERTIFICATE-----
+`
+
+var ecdsaTests = []struct {
+ sigAlgo SignatureAlgorithm
+ pemCert string
+}{
+ {ECDSAWithSHA1, ecdsaSHA1CertPem},
+ {ECDSAWithSHA256, ecdsaSHA256p256CertPem},
+ {ECDSAWithSHA256, ecdsaSHA256p384CertPem},
+ {ECDSAWithSHA384, ecdsaSHA384p521CertPem},
+}
+
+func TestECDSA(t *testing.T) {
+ for i, test := range ecdsaTests {
+ pemBlock, _ := pem.Decode([]byte(test.pemCert))
+ cert, err := ParseCertificate(pemBlock.Bytes)
+ if err != nil {
+ t.Errorf("%d: failed to parse certificate: %s", i, err)
+ continue
+ }
+ if sa := cert.SignatureAlgorithm; sa != test.sigAlgo {
+ t.Errorf("%d: signature algorithm is %v, want %v", i, sa, test.sigAlgo)
+ }
+ if parsedKey, ok := cert.PublicKey.(*ecdsa.PublicKey); !ok {
+ t.Errorf("%d: wanted an ECDSA public key but found: %#v", i, parsedKey)
+ }
+ if pka := cert.PublicKeyAlgorithm; pka != ECDSA {
+ t.Errorf("%d: public key algorithm is %v, want ECDSA", i, pka)
+ }
+ if err = cert.CheckSignatureFrom(cert); err != nil {
+ t.Errorf("%d: certificate verfication failed: %s", i, err)
+ }
}
}
diff --git a/libgo/go/database/sql/convert.go b/libgo/go/database/sql/convert.go
index bfcb03ccf8d..964dc184850 100644
--- a/libgo/go/database/sql/convert.go
+++ b/libgo/go/database/sql/convert.go
@@ -14,19 +14,61 @@ import (
"strconv"
)
-// subsetTypeArgs takes a slice of arguments from callers of the sql
-// package and converts them into a slice of the driver package's
-// "subset types".
-func subsetTypeArgs(args []interface{}) ([]driver.Value, error) {
- out := make([]driver.Value, len(args))
+// driverArgs converts arguments from callers of Stmt.Exec and
+// Stmt.Query into driver Values.
+//
+// The statement si may be nil, if no statement is available.
+func driverArgs(si driver.Stmt, args []interface{}) ([]driver.Value, error) {
+ dargs := make([]driver.Value, len(args))
+ cc, ok := si.(driver.ColumnConverter)
+
+ // Normal path, for a driver.Stmt that is not a ColumnConverter.
+ if !ok {
+ for n, arg := range args {
+ var err error
+ dargs[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
+ if err != nil {
+ return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
+ }
+ }
+ return dargs, nil
+ }
+
+ // Let the Stmt convert its own arguments.
for n, arg := range args {
+ // First, see if the value itself knows how to convert
+ // itself to a driver type. For example, a NullString
+ // struct changing into a string or nil.
+ if svi, ok := arg.(driver.Valuer); ok {
+ sv, err := svi.Value()
+ if err != nil {
+ return nil, fmt.Errorf("sql: argument index %d from Value: %v", n, err)
+ }
+ if !driver.IsValue(sv) {
+ return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from Value", n, sv)
+ }
+ arg = sv
+ }
+
+ // Second, ask the column to sanity check itself. For
+ // example, drivers might use this to make sure that
+ // an int64 values being inserted into a 16-bit
+ // integer field is in range (before getting
+ // truncated), or that a nil can't go into a NOT NULL
+ // column before going across the network to get the
+ // same error.
var err error
- out[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
+ dargs[n], err = cc.ColumnConverter(n).ConvertValue(arg)
if err != nil {
- return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n+1, err)
+ return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n, err)
+ }
+ if !driver.IsValue(dargs[n]) {
+ return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T",
+ arg, dargs[n])
}
}
- return out, nil
+
+ return dargs, nil
}
// convertAssign copies to dest the value in src, converting it if possible.
diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go
index a11fb788ef7..aec572760fe 100644
--- a/libgo/go/database/sql/fakedb_test.go
+++ b/libgo/go/database/sql/fakedb_test.go
@@ -383,6 +383,9 @@ func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
}
func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
+ if len(s.placeholderConverter) == 0 {
+ return driver.DefaultParameterConverter
+ }
return s.placeholderConverter[idx]
}
@@ -598,6 +601,28 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
return nil
}
+// fakeDriverString is like driver.String, but indirects pointers like
+// DefaultValueConverter.
+//
+// This could be surprising behavior to retroactively apply to
+// driver.String now that Go1 is out, but this is convenient for
+// our TestPointerParamsAndScans.
+//
+type fakeDriverString struct{}
+
+func (fakeDriverString) ConvertValue(v interface{}) (driver.Value, error) {
+ switch c := v.(type) {
+ case string, []byte:
+ return v, nil
+ case *string:
+ if c == nil {
+ return nil, nil
+ }
+ return *c, nil
+ }
+ return fmt.Sprintf("%v", v), nil
+}
+
func converterForType(typ string) driver.ValueConverter {
switch typ {
case "bool":
@@ -607,9 +632,9 @@ func converterForType(typ string) driver.ValueConverter {
case "int32":
return driver.Int32
case "string":
- return driver.NotNull{Converter: driver.String}
+ return driver.NotNull{Converter: fakeDriverString{}}
case "nullstring":
- return driver.Null{Converter: driver.String}
+ return driver.Null{Converter: fakeDriverString{}}
case "int64":
// TODO(coopernurse): add type-specific converter
return driver.NotNull{Converter: driver.DefaultParameterConverter}
diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go
index d557fc83034..b0cba949c6b 100644
--- a/libgo/go/database/sql/sql.go
+++ b/libgo/go/database/sql/sql.go
@@ -329,13 +329,10 @@ func (db *DB) prepare(query string) (stmt *Stmt, err error) {
// Exec executes a query without returning any rows.
func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
- sargs, err := subsetTypeArgs(args)
- if err != nil {
- return nil, err
- }
var res Result
+ var err error
for i := 0; i < 10; i++ {
- res, err = db.exec(query, sargs)
+ res, err = db.exec(query, args)
if err != driver.ErrBadConn {
break
}
@@ -343,7 +340,7 @@ func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
return res, err
}
-func (db *DB) exec(query string, sargs []driver.Value) (res Result, err error) {
+func (db *DB) exec(query string, args []interface{}) (res Result, err error) {
ci, err := db.conn()
if err != nil {
return nil, err
@@ -353,7 +350,11 @@ func (db *DB) exec(query string, sargs []driver.Value) (res Result, err error) {
}()
if execer, ok := ci.(driver.Execer); ok {
- resi, err := execer.Exec(query, sargs)
+ dargs, err := driverArgs(nil, args)
+ if err != nil {
+ return nil, err
+ }
+ resi, err := execer.Exec(query, dargs)
if err != driver.ErrSkip {
if err != nil {
return nil, err
@@ -368,7 +369,12 @@ func (db *DB) exec(query string, sargs []driver.Value) (res Result, err error) {
}
defer sti.Close()
- resi, err := sti.Exec(sargs)
+ dargs, err := driverArgs(sti, args)
+ if err != nil {
+ return nil, err
+ }
+
+ resi, err := sti.Exec(dargs)
if err != nil {
return nil, err
}
@@ -582,13 +588,12 @@ func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
}
defer tx.releaseConn()
- sargs, err := subsetTypeArgs(args)
- if err != nil {
- return nil, err
- }
-
if execer, ok := ci.(driver.Execer); ok {
- resi, err := execer.Exec(query, sargs)
+ dargs, err := driverArgs(nil, args)
+ if err != nil {
+ return nil, err
+ }
+ resi, err := execer.Exec(query, dargs)
if err == nil {
return result{resi}, nil
}
@@ -603,7 +608,12 @@ func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
}
defer sti.Close()
- resi, err := sti.Exec(sargs)
+ dargs, err := driverArgs(sti, args)
+ if err != nil {
+ return nil, err
+ }
+
+ resi, err := sti.Exec(dargs)
if err != nil {
return nil, err
}
@@ -679,51 +689,12 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) {
return nil, fmt.Errorf("sql: expected %d arguments, got %d", want, len(args))
}
- sargs := make([]driver.Value, len(args))
-
- // Convert args to subset types.
- if cc, ok := si.(driver.ColumnConverter); ok {
- for n, arg := range args {
- // First, see if the value itself knows how to convert
- // itself to a driver type. For example, a NullString
- // struct changing into a string or nil.
- if svi, ok := arg.(driver.Valuer); ok {
- sv, err := svi.Value()
- if err != nil {
- return nil, fmt.Errorf("sql: argument index %d from Value: %v", n, err)
- }
- if !driver.IsValue(sv) {
- return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from Value", n, sv)
- }
- arg = sv
- }
-
- // Second, ask the column to sanity check itself. For
- // example, drivers might use this to make sure that
- // an int64 values being inserted into a 16-bit
- // integer field is in range (before getting
- // truncated), or that a nil can't go into a NOT NULL
- // column before going across the network to get the
- // same error.
- sargs[n], err = cc.ColumnConverter(n).ConvertValue(arg)
- if err != nil {
- return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
- }
- if !driver.IsValue(sargs[n]) {
- return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T",
- arg, sargs[n])
- }
- }
- } else {
- for n, arg := range args {
- sargs[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
- if err != nil {
- return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
- }
- }
+ dargs, err := driverArgs(si, args)
+ if err != nil {
+ return nil, err
}
- resi, err := si.Exec(sargs)
+ resi, err := si.Exec(dargs)
if err != nil {
return nil, err
}
@@ -810,11 +781,13 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
if want := si.NumInput(); want != -1 && len(args) != want {
return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", si.NumInput(), len(args))
}
- sargs, err := subsetTypeArgs(args)
+
+ dargs, err := driverArgs(si, args)
if err != nil {
return nil, err
}
- rowsi, err := si.Query(sargs)
+
+ rowsi, err := si.Query(dargs)
if err != nil {
releaseConn(err)
return nil, err
diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go
index b296705865f..1bfb59020b4 100644
--- a/libgo/go/database/sql/sql_test.go
+++ b/libgo/go/database/sql/sql_test.go
@@ -306,8 +306,8 @@ func TestExec(t *testing.T) {
{[]interface{}{7, 9}, ""},
// Invalid conversions:
- {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting Exec argument #1's type: sql/driver: value 4294967295 overflows int32"},
- {[]interface{}{"Brad", "strconv fail"}, "sql: converting Exec argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
+ {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument #1's type: sql/driver: value 4294967295 overflows int32"},
+ {[]interface{}{"Brad", "strconv fail"}, "sql: converting argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
// Wrong number of args:
{[]interface{}{}, "sql: expected 2 arguments, got 0"},
diff --git a/libgo/go/debug/elf/file.go b/libgo/go/debug/elf/file.go
index 31895f192c5..7b66730bed7 100644
--- a/libgo/go/debug/elf/file.go
+++ b/libgo/go/debug/elf/file.go
@@ -31,6 +31,7 @@ type FileHeader struct {
ByteOrder binary.ByteOrder
Type Type
Machine Machine
+ Entry uint64
}
// A File represents an open ELF file.
@@ -240,6 +241,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
}
f.Type = Type(hdr.Type)
f.Machine = Machine(hdr.Machine)
+ f.Entry = uint64(hdr.Entry)
if v := Version(hdr.Version); v != f.Version {
return nil, &FormatError{0, "mismatched ELF version", v}
}
@@ -258,6 +260,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
}
f.Type = Type(hdr.Type)
f.Machine = Machine(hdr.Machine)
+ f.Entry = uint64(hdr.Entry)
if v := Version(hdr.Version); v != f.Version {
return nil, &FormatError{0, "mismatched ELF version", v}
}
@@ -723,6 +726,20 @@ func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
// referred to by the binary f that are expected to be
// linked with the binary at dynamic link time.
func (f *File) ImportedLibraries() ([]string, error) {
+ return f.DynString(DT_NEEDED)
+}
+
+// DynString returns the strings listed for the given tag in the file's dynamic
+// section.
+//
+// The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or
+// DT_RUNPATH.
+func (f *File) DynString(tag DynTag) ([]string, error) {
+ switch tag {
+ case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH:
+ default:
+ return nil, fmt.Errorf("non-string-valued tag %v", tag)
+ }
ds := f.SectionByType(SHT_DYNAMIC)
if ds == nil {
// not dynamic, so no libraries
@@ -738,25 +755,24 @@ func (f *File) ImportedLibraries() ([]string, error) {
}
var all []string
for len(d) > 0 {
- var tag DynTag
- var value uint64
+ var t DynTag
+ var v uint64
switch f.Class {
case ELFCLASS32:
- tag = DynTag(f.ByteOrder.Uint32(d[0:4]))
- value = uint64(f.ByteOrder.Uint32(d[4:8]))
+ t = DynTag(f.ByteOrder.Uint32(d[0:4]))
+ v = uint64(f.ByteOrder.Uint32(d[4:8]))
d = d[8:]
case ELFCLASS64:
- tag = DynTag(f.ByteOrder.Uint64(d[0:8]))
- value = f.ByteOrder.Uint64(d[8:16])
+ t = DynTag(f.ByteOrder.Uint64(d[0:8]))
+ v = f.ByteOrder.Uint64(d[8:16])
d = d[16:]
}
- if tag == DT_NEEDED {
- s, ok := getString(str, int(value))
+ if t == tag {
+ s, ok := getString(str, int(v))
if ok {
all = append(all, s)
}
}
}
-
return all, nil
}
diff --git a/libgo/go/debug/elf/file_test.go b/libgo/go/debug/elf/file_test.go
index 98f2723c86e..12036e816b4 100644
--- a/libgo/go/debug/elf/file_test.go
+++ b/libgo/go/debug/elf/file_test.go
@@ -19,12 +19,13 @@ type fileTest struct {
hdr FileHeader
sections []SectionHeader
progs []ProgHeader
+ needed []string
}
var fileTests = []fileTest{
{
"testdata/gcc-386-freebsd-exec",
- FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386},
+ FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc},
[]SectionHeader{
{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0},
@@ -64,10 +65,11 @@ var fileTests = []fileTest{
{PT_LOAD, PF_R + PF_W, 0x5fc, 0x80495fc, 0x80495fc, 0xd8, 0xf8, 0x1000},
{PT_DYNAMIC, PF_R + PF_W, 0x60c, 0x804960c, 0x804960c, 0x98, 0x98, 0x4},
},
+ []string{"libc.so.6"},
},
{
"testdata/gcc-amd64-linux-exec",
- FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64},
+ FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0},
[]SectionHeader{
{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0},
@@ -117,6 +119,7 @@ var fileTests = []fileTest{
{PT_LOOS + 0x474E550, PF_R, 0x5b8, 0x4005b8, 0x4005b8, 0x24, 0x24, 0x4},
{PT_LOOS + 0x474E551, PF_R + PF_W, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8},
},
+ []string{"libc.so.6"},
},
}
@@ -161,6 +164,14 @@ func TestOpen(t *testing.T) {
if tn != fn {
t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn)
}
+ tl := tt.needed
+ fl, err := f.ImportedLibraries()
+ if err != nil {
+ t.Error(err)
+ }
+ if !reflect.DeepEqual(tl, fl) {
+ t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl)
+ }
}
}
diff --git a/libgo/go/debug/pe/file.go b/libgo/go/debug/pe/file.go
index 6b98a5f45b9..f521566efa7 100644
--- a/libgo/go/debug/pe/file.go
+++ b/libgo/go/debug/pe/file.go
@@ -19,6 +19,7 @@ import (
type File struct {
FileHeader
Sections []*Section
+ Symbols []*Symbol
closer io.Closer
}
@@ -49,6 +50,14 @@ type Section struct {
sr *io.SectionReader
}
+type Symbol struct {
+ Name string
+ Value uint32
+ SectionNumber int16
+ Type uint16
+ StorageClass uint8
+}
+
type ImportDirectory struct {
OriginalFirstThunk uint32
TimeDateStamp uint32
@@ -122,12 +131,13 @@ func NewFile(r io.ReaderAt) (*File, error) {
}
var base int64
if dosheader[0] == 'M' && dosheader[1] == 'Z' {
+ signoff := int64(binary.LittleEndian.Uint32(dosheader[0x3c:]))
var sign [4]byte
- r.ReadAt(sign[0:], int64(dosheader[0x3c]))
+ r.ReadAt(sign[:], signoff)
if !(sign[0] == 'P' && sign[1] == 'E' && sign[2] == 0 && sign[3] == 0) {
return nil, errors.New("Invalid PE File Format.")
}
- base = int64(dosheader[0x3c]) + 4
+ base = signoff + 4
} else {
base = int64(0)
}
@@ -138,16 +148,52 @@ func NewFile(r io.ReaderAt) (*File, error) {
if f.FileHeader.Machine != IMAGE_FILE_MACHINE_UNKNOWN && f.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64 && f.FileHeader.Machine != IMAGE_FILE_MACHINE_I386 {
return nil, errors.New("Invalid PE File Format.")
}
- // get symbol string table
- sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), os.SEEK_SET)
- var l uint32
- if err := binary.Read(sr, binary.LittleEndian, &l); err != nil {
- return nil, err
- }
- ss := make([]byte, l)
- if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols)); err != nil {
- return nil, err
+
+ var ss []byte
+ if f.FileHeader.NumberOfSymbols > 0 {
+ // Get COFF string table, which is located at the end of the COFF symbol table.
+ sr.Seek(int64(f.FileHeader.PointerToSymbolTable+COFFSymbolSize*f.FileHeader.NumberOfSymbols), os.SEEK_SET)
+ var l uint32
+ if err := binary.Read(sr, binary.LittleEndian, &l); err != nil {
+ return nil, err
+ }
+ ss = make([]byte, l)
+ if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+COFFSymbolSize*f.FileHeader.NumberOfSymbols)); err != nil {
+ return nil, err
+ }
+
+ // Process COFF symbol table.
+ sr.Seek(int64(f.FileHeader.PointerToSymbolTable), os.SEEK_SET)
+ aux := uint8(0)
+ for i := 0; i < int(f.FileHeader.NumberOfSymbols); i++ {
+ cs := new(COFFSymbol)
+ if err := binary.Read(sr, binary.LittleEndian, cs); err != nil {
+ return nil, err
+ }
+ if aux > 0 {
+ aux--
+ continue
+ }
+ var name string
+ if cs.Name[0] == 0 && cs.Name[1] == 0 && cs.Name[2] == 0 && cs.Name[3] == 0 {
+ si := int(binary.LittleEndian.Uint32(cs.Name[4:]))
+ name, _ = getString(ss, si)
+ } else {
+ name = cstring(cs.Name[:])
+ }
+ aux = cs.NumberOfAuxSymbols
+ s := &Symbol{
+ Name: name,
+ Value: cs.Value,
+ SectionNumber: cs.SectionNumber,
+ Type: cs.Type,
+ StorageClass: cs.StorageClass,
+ }
+ f.Symbols = append(f.Symbols, s)
+ }
}
+
+ // Process sections.
sr.Seek(base, os.SEEK_SET)
binary.Read(sr, binary.LittleEndian, &f.FileHeader)
sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), os.SEEK_CUR) //Skip OptionalHeader
diff --git a/libgo/go/debug/pe/file_test.go b/libgo/go/debug/pe/file_test.go
index 2815d720bb6..c0f9fcb95db 100644
--- a/libgo/go/debug/pe/file_test.go
+++ b/libgo/go/debug/pe/file_test.go
@@ -13,6 +13,7 @@ type fileTest struct {
file string
hdr FileHeader
sections []*SectionHeader
+ symbols []*Symbol
}
var fileTests = []fileTest{
@@ -33,6 +34,24 @@ var fileTests = []fileTest{
{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
},
+ []*Symbol{
+ {".file", 0x0, -2, 0x0, 0x67},
+ {"_main", 0x0, 1, 0x20, 0x2},
+ {".text", 0x0, 1, 0x0, 0x3},
+ {".data", 0x0, 2, 0x0, 0x3},
+ {".bss", 0x0, 3, 0x0, 0x3},
+ {".debug_abbrev", 0x0, 4, 0x0, 0x3},
+ {".debug_info", 0x0, 5, 0x0, 0x3},
+ {".debug_line", 0x0, 6, 0x0, 0x3},
+ {".rdata", 0x0, 7, 0x0, 0x3},
+ {".debug_frame", 0x0, 8, 0x0, 0x3},
+ {".debug_loc", 0x0, 9, 0x0, 0x3},
+ {".debug_pubnames", 0x0, 10, 0x0, 0x3},
+ {".debug_pubtypes", 0x0, 11, 0x0, 0x3},
+ {".debug_aranges", 0x0, 12, 0x0, 0x3},
+ {"___main", 0x0, 0, 0x20, 0x2},
+ {"_puts", 0x0, 0, 0x20, 0x2},
+ },
},
{
"testdata/gcc-386-mingw-exec",
@@ -54,6 +73,7 @@ var fileTests = []fileTest{
{Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000},
{Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
},
+ []*Symbol{},
},
}
@@ -86,7 +106,15 @@ func TestOpen(t *testing.T) {
if tn != fn {
t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
}
-
+ for i, have := range f.Symbols {
+ if i >= len(tt.symbols) {
+ break
+ }
+ want := tt.symbols[i]
+ if !reflect.DeepEqual(have, want) {
+ t.Errorf("open %s, symbol %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
+ }
+ }
}
}
diff --git a/libgo/go/debug/pe/pe.go b/libgo/go/debug/pe/pe.go
index b3dab739ae9..0606217b3bf 100644
--- a/libgo/go/debug/pe/pe.go
+++ b/libgo/go/debug/pe/pe.go
@@ -27,6 +27,17 @@ type SectionHeader32 struct {
Characteristics uint32
}
+const COFFSymbolSize = 18
+
+type COFFSymbol struct {
+ Name [8]uint8
+ Value uint32
+ SectionNumber int16
+ Type uint16
+ StorageClass uint8
+ NumberOfAuxSymbols uint8
+}
+
const (
IMAGE_FILE_MACHINE_UNKNOWN = 0x0
IMAGE_FILE_MACHINE_AM33 = 0x1d3
diff --git a/libgo/go/encoding/asn1/asn1.go b/libgo/go/encoding/asn1/asn1.go
index ac2b5f8daa6..cac9d64b5e9 100644
--- a/libgo/go/encoding/asn1/asn1.go
+++ b/libgo/go/encoding/asn1/asn1.go
@@ -77,15 +77,15 @@ func parseInt64(bytes []byte) (ret int64, err error) {
// parseInt treats the given bytes as a big-endian, signed integer and returns
// the result.
-func parseInt(bytes []byte) (int, error) {
+func parseInt32(bytes []byte) (int32, error) {
ret64, err := parseInt64(bytes)
if err != nil {
return 0, err
}
- if ret64 != int64(int(ret64)) {
+ if ret64 != int64(int32(ret64)) {
return 0, StructuralError{"integer too large"}
}
- return int(ret64), nil
+ return int32(ret64), nil
}
var bigOne = big.NewInt(1)
@@ -670,7 +670,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
err = err1
return
case enumeratedType:
- parsedInt, err1 := parseInt(innerBytes)
+ parsedInt, err1 := parseInt32(innerBytes)
if err1 == nil {
v.SetInt(int64(parsedInt))
}
@@ -692,19 +692,20 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
}
err = err1
return
- case reflect.Int, reflect.Int32:
- parsedInt, err1 := parseInt(innerBytes)
- if err1 == nil {
- val.SetInt(int64(parsedInt))
- }
- err = err1
- return
- case reflect.Int64:
- parsedInt, err1 := parseInt64(innerBytes)
- if err1 == nil {
- val.SetInt(parsedInt)
+ case reflect.Int, reflect.Int32, reflect.Int64:
+ if val.Type().Size() == 4 {
+ parsedInt, err1 := parseInt32(innerBytes)
+ if err1 == nil {
+ val.SetInt(int64(parsedInt))
+ }
+ err = err1
+ } else {
+ parsedInt, err1 := parseInt64(innerBytes)
+ if err1 == nil {
+ val.SetInt(parsedInt)
+ }
+ err = err1
}
- err = err1
return
// TODO(dfc) Add support for the remaining integer types
case reflect.Struct:
diff --git a/libgo/go/encoding/asn1/asn1_test.go b/libgo/go/encoding/asn1/asn1_test.go
index eb848bdb4af..cabdf03b482 100644
--- a/libgo/go/encoding/asn1/asn1_test.go
+++ b/libgo/go/encoding/asn1/asn1_test.go
@@ -64,7 +64,7 @@ var int32TestData = []int32Test{
func TestParseInt32(t *testing.T) {
for i, test := range int32TestData {
- ret, err := parseInt(test.in)
+ ret, err := parseInt32(test.in)
if (err == nil) != test.ok {
t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
}
diff --git a/libgo/go/encoding/asn1/common.go b/libgo/go/encoding/asn1/common.go
index 03856bc55c5..33a117ece19 100644
--- a/libgo/go/encoding/asn1/common.go
+++ b/libgo/go/encoding/asn1/common.go
@@ -98,6 +98,8 @@ func parseFieldParameters(str string) (ret fieldParameters) {
ret.stringType = tagIA5String
case part == "printable":
ret.stringType = tagPrintableString
+ case part == "utf8":
+ ret.stringType = tagUTF8String
case strings.HasPrefix(part, "default:"):
i, err := strconv.ParseInt(part[8:], 10, 64)
if err == nil {
diff --git a/libgo/go/encoding/asn1/marshal.go b/libgo/go/encoding/asn1/marshal.go
index 163bca575de..3fd6be8ad92 100644
--- a/libgo/go/encoding/asn1/marshal.go
+++ b/libgo/go/encoding/asn1/marshal.go
@@ -6,11 +6,13 @@ package asn1
import (
"bytes"
+ "errors"
"fmt"
"io"
"math/big"
"reflect"
"time"
+ "unicode/utf8"
)
// A forkableWriter is an in-memory buffer that can be
@@ -280,6 +282,11 @@ func marshalIA5String(out *forkableWriter, s string) (err error) {
return
}
+func marshalUTF8String(out *forkableWriter, s string) (err error) {
+ _, err = out.Write([]byte(s))
+ return
+}
+
func marshalTwoDigits(out *forkableWriter, v int) (err error) {
err = out.WriteByte(byte('0' + (v/10)%10))
if err != nil {
@@ -446,10 +453,13 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
}
return
case reflect.String:
- if params.stringType == tagIA5String {
+ switch params.stringType {
+ case tagIA5String:
return marshalIA5String(out, v.String())
- } else {
+ case tagPrintableString:
return marshalPrintableString(out, v.String())
+ default:
+ return marshalUTF8String(out, v.String())
}
return
}
@@ -492,11 +502,27 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
}
class := classUniversal
- if params.stringType != 0 {
- if tag != tagPrintableString {
- return StructuralError{"Explicit string type given to non-string member"}
+ if params.stringType != 0 && tag != tagPrintableString {
+ return StructuralError{"Explicit string type given to non-string member"}
+ }
+
+ if tag == tagPrintableString {
+ if params.stringType == 0 {
+ // This is a string without an explicit string type. We'll use
+ // a PrintableString if the character set in the string is
+ // sufficiently limited, otherwise we'll use a UTF8String.
+ for _, r := range v.String() {
+ if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
+ if !utf8.ValidString(v.String()) {
+ return errors.New("asn1: string not valid UTF-8")
+ }
+ tag = tagUTF8String
+ break
+ }
+ }
+ } else {
+ tag = params.stringType
}
- tag = params.stringType
}
if params.set {
diff --git a/libgo/go/encoding/asn1/marshal_test.go b/libgo/go/encoding/asn1/marshal_test.go
index f43bcae681a..c203533a917 100644
--- a/libgo/go/encoding/asn1/marshal_test.go
+++ b/libgo/go/encoding/asn1/marshal_test.go
@@ -122,6 +122,7 @@ var marshalTests = []marshalTest{
{testSET([]int{10}), "310302010a"},
{omitEmptyTest{[]string{}}, "3000"},
{omitEmptyTest{[]string{"1"}}, "30053003130131"},
+ {"Σ", "0c02cea3"},
}
func TestMarshal(t *testing.T) {
@@ -137,3 +138,10 @@ func TestMarshal(t *testing.T) {
}
}
}
+
+func TestInvalidUTF8(t *testing.T) {
+ _, err := Marshal(string([]byte{0xff, 0xff}))
+ if err == nil {
+ t.Errorf("invalid UTF8 string was accepted")
+ }
+}
diff --git a/libgo/go/encoding/base32/base32.go b/libgo/go/encoding/base32/base32.go
index 71da6e22b12..dbefc48fa37 100644
--- a/libgo/go/encoding/base32/base32.go
+++ b/libgo/go/encoding/base32/base32.go
@@ -237,7 +237,6 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
dlen := 8
// do the top bytes contain any data?
- dbufloop:
for j := 0; j < 8; {
if len(src) == 0 {
return n, false, CorruptInputError(len(osrc) - len(src) - j)
@@ -258,7 +257,7 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
}
dlen = j
end = true
- break dbufloop
+ break
}
dbuf[j] = enc.decodeMap[in]
if dbuf[j] == 0xFF {
diff --git a/libgo/go/encoding/base64/base64.go b/libgo/go/encoding/base64/base64.go
index 0b842f06610..e66672a1c93 100644
--- a/libgo/go/encoding/base64/base64.go
+++ b/libgo/go/encoding/base64/base64.go
@@ -216,7 +216,6 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
var dbuf [4]byte
dlen := 4
- dbufloop:
for j := 0; j < 4; {
if len(src) == 0 {
return n, false, CorruptInputError(len(osrc) - len(src) - j)
@@ -240,7 +239,7 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
}
dlen = j
end = true
- break dbufloop
+ break
}
dbuf[j] = enc.decodeMap[in]
if dbuf[j] == 0xFF {
diff --git a/libgo/go/encoding/csv/writer.go b/libgo/go/encoding/csv/writer.go
index c4dcba5668a..324944cc829 100644
--- a/libgo/go/encoding/csv/writer.go
+++ b/libgo/go/encoding/csv/writer.go
@@ -101,11 +101,10 @@ func (w *Writer) WriteAll(records [][]string) (err error) {
for _, record := range records {
err = w.Write(record)
if err != nil {
- break
+ return err
}
}
- w.Flush()
- return nil
+ return w.w.Flush()
}
// fieldNeedsQuotes returns true if our field must be enclosed in quotes.
diff --git a/libgo/go/encoding/gob/codec_test.go b/libgo/go/encoding/gob/codec_test.go
index ebcbb78ebe6..482212b7467 100644
--- a/libgo/go/encoding/gob/codec_test.go
+++ b/libgo/go/encoding/gob/codec_test.go
@@ -7,6 +7,7 @@ package gob
import (
"bytes"
"errors"
+ "flag"
"math"
"math/rand"
"reflect"
@@ -16,6 +17,8 @@ import (
"unsafe"
)
+var doFuzzTests = flag.Bool("gob.fuzz", false, "run the fuzz tests, which are large and very slow")
+
// Guarantee encoding format by comparing some encodings to hand-written values
type EncodeT struct {
x uint64
@@ -1434,7 +1437,8 @@ func encFuzzDec(rng *rand.Rand, in interface{}) error {
// This does some "fuzz testing" by attempting to decode a sequence of random bytes.
func TestFuzz(t *testing.T) {
- if testing.Short() {
+ if !*doFuzzTests {
+ t.Logf("disabled; run with -gob.fuzz to enable")
return
}
@@ -1453,11 +1457,16 @@ func TestFuzz(t *testing.T) {
}
func TestFuzzRegressions(t *testing.T) {
+ if !*doFuzzTests {
+ t.Logf("disabled; run with -gob.fuzz to enable")
+ return
+ }
+
// An instance triggering a type name of length ~102 GB.
testFuzz(t, 1328492090837718000, 100, new(float32))
// An instance triggering a type name of 1.6 GB.
- // Commented out because it takes 5m to run.
- //testFuzz(t, 1330522872628565000, 100, new(int))
+ // Note: can take several minutes to run.
+ testFuzz(t, 1330522872628565000, 100, new(int))
}
func testFuzz(t *testing.T, seed int64, n int, input ...interface{}) {
diff --git a/libgo/go/encoding/gob/decode.go b/libgo/go/encoding/gob/decode.go
index 8690b35d714..900c69ddb47 100644
--- a/libgo/go/encoding/gob/decode.go
+++ b/libgo/go/encoding/gob/decode.go
@@ -717,7 +717,9 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p ui
errorf("name too long (%d bytes): %.20q...", len(name), name)
}
// The concrete type must be registered.
+ registerLock.RLock()
typ, ok := nameToConcreteType[name]
+ registerLock.RUnlock()
if !ok {
errorf("name not registered for interface: %q", name)
}
diff --git a/libgo/go/encoding/gob/decoder.go b/libgo/go/encoding/gob/decoder.go
index c5c7d3fdb10..04f706ca540 100644
--- a/libgo/go/encoding/gob/decoder.go
+++ b/libgo/go/encoding/gob/decoder.go
@@ -87,21 +87,38 @@ func (dec *Decoder) recvMessage() bool {
// readMessage reads the next nbytes bytes from the input.
func (dec *Decoder) readMessage(nbytes int) {
- // Allocate the buffer.
- if cap(dec.tmp) < nbytes {
- dec.tmp = make([]byte, nbytes+100) // room to grow
+ // Allocate the dec.tmp buffer, up to 10KB.
+ const maxBuf = 10 * 1024
+ nTmp := nbytes
+ if nTmp > maxBuf {
+ nTmp = maxBuf
}
- dec.tmp = dec.tmp[:nbytes]
+ if cap(dec.tmp) < nTmp {
+ nAlloc := nTmp + 100 // A little extra for growth.
+ if nAlloc > maxBuf {
+ nAlloc = maxBuf
+ }
+ dec.tmp = make([]byte, nAlloc)
+ }
+ dec.tmp = dec.tmp[:nTmp]
// Read the data
- _, dec.err = io.ReadFull(dec.r, dec.tmp)
- if dec.err != nil {
- if dec.err == io.EOF {
- dec.err = io.ErrUnexpectedEOF
+ dec.buf.Grow(nbytes)
+ for nbytes > 0 {
+ if nbytes < nTmp {
+ dec.tmp = dec.tmp[:nbytes]
}
- return
+ var nRead int
+ nRead, dec.err = io.ReadFull(dec.r, dec.tmp)
+ if dec.err != nil {
+ if dec.err == io.EOF {
+ dec.err = io.ErrUnexpectedEOF
+ }
+ return
+ }
+ dec.buf.Write(dec.tmp)
+ nbytes -= nRead
}
- dec.buf.Write(dec.tmp)
}
// toInt turns an encoded uint64 into an int, according to the marshaling rules.
diff --git a/libgo/go/encoding/gob/encode.go b/libgo/go/encoding/gob/encode.go
index 168e08b137a..ea37a6cbd58 100644
--- a/libgo/go/encoding/gob/encode.go
+++ b/libgo/go/encoding/gob/encode.go
@@ -426,6 +426,12 @@ func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp e
// by the concrete value. A nil value gets sent as the empty string for the name,
// followed by no value.
func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
+ // Gobs can encode nil interface values but not typed interface
+ // values holding nil pointers, since nil pointers point to no value.
+ elem := iv.Elem()
+ if elem.Kind() == reflect.Ptr && elem.IsNil() {
+ errorf("gob: cannot encode nil pointer of type %s inside interface", iv.Elem().Type())
+ }
state := enc.newEncoderState(b)
state.fieldnum = -1
state.sendZero = true
@@ -435,7 +441,9 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
}
ut := userType(iv.Elem().Type())
+ registerLock.RLock()
name, ok := concreteTypeToName[ut.base]
+ registerLock.RUnlock()
if !ok {
errorf("type not registered for interface: %s", ut.base)
}
@@ -454,7 +462,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
enc.pushWriter(b)
data := new(bytes.Buffer)
data.Write(spaceForLength)
- enc.encode(data, iv.Elem(), ut)
+ enc.encode(data, elem, ut)
if enc.err != nil {
error_(enc.err)
}
@@ -698,9 +706,20 @@ func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine {
error_(err1)
}
if info.encoder == nil {
- // mark this engine as underway before compiling to handle recursive types.
+ // Assign the encEngine now, so recursive types work correctly. But...
info.encoder = new(encEngine)
+ // ... if we fail to complete building the engine, don't cache the half-built machine.
+ // Doing this here means we won't cache a type that is itself OK but
+ // that contains a nested type that won't compile. The result is consistent
+ // error behavior when Encode is called multiple times on the top-level type.
+ ok := false
+ defer func() {
+ if !ok {
+ info.encoder = nil
+ }
+ }()
info.encoder = enc.compileEnc(ut)
+ ok = true
}
return info.encoder
}
diff --git a/libgo/go/encoding/gob/encoder.go b/libgo/go/encoding/gob/encoder.go
index a15b5a1f9a1..51444bb5269 100644
--- a/libgo/go/encoding/gob/encoder.go
+++ b/libgo/go/encoding/gob/encoder.go
@@ -218,6 +218,12 @@ func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) {
// EncodeValue transmits the data item represented by the reflection value,
// guaranteeing that all necessary type information has been transmitted first.
func (enc *Encoder) EncodeValue(value reflect.Value) error {
+ // Gobs contain values. They cannot represent nil pointers, which
+ // have no value to encode.
+ if value.Kind() == reflect.Ptr && value.IsNil() {
+ panic("gob: cannot encode nil pointer of type " + value.Type().String())
+ }
+
// Make sure we're single-threaded through here, so multiple
// goroutines can share an encoder.
enc.mutex.Lock()
diff --git a/libgo/go/encoding/gob/encoder_test.go b/libgo/go/encoding/gob/encoder_test.go
index db824d99917..b684772c691 100644
--- a/libgo/go/encoding/gob/encoder_test.go
+++ b/libgo/go/encoding/gob/encoder_test.go
@@ -737,6 +737,83 @@ func TestPtrToMapOfMap(t *testing.T) {
}
}
+// A top-level nil pointer generates a panic with a helpful string-valued message.
+func TestTopLevelNilPointer(t *testing.T) {
+ errMsg := topLevelNilPanic(t)
+ if errMsg == "" {
+ t.Fatal("top-level nil pointer did not panic")
+ }
+ if !strings.Contains(errMsg, "nil pointer") {
+ t.Fatal("expected nil pointer error, got:", errMsg)
+ }
+}
+
+func topLevelNilPanic(t *testing.T) (panicErr string) {
+ defer func() {
+ e := recover()
+ if err, ok := e.(string); ok {
+ panicErr = err
+ }
+ }()
+ var ip *int
+ buf := new(bytes.Buffer)
+ if err := NewEncoder(buf).Encode(ip); err != nil {
+ t.Fatal("error in encode:", err)
+ }
+ return
+}
+
+func TestNilPointerInsideInterface(t *testing.T) {
+ var ip *int
+ si := struct {
+ I interface{}
+ }{
+ I: ip,
+ }
+ buf := new(bytes.Buffer)
+ err := NewEncoder(buf).Encode(si)
+ if err == nil {
+ t.Fatal("expected error, got none")
+ }
+ errMsg := err.Error()
+ if !strings.Contains(errMsg, "nil pointer") || !strings.Contains(errMsg, "interface") {
+ t.Fatal("expected error about nil pointer and interface, got:", errMsg)
+ }
+}
+
+type Bug4Public struct {
+ Name string
+ Secret Bug4Secret
+}
+
+type Bug4Secret struct {
+ a int // error: no exported fields.
+}
+
+// Test that a failed compilation doesn't leave around an executable encoder.
+// Issue 3273.
+func TestMutipleEncodingsOfBadType(t *testing.T) {
+ x := Bug4Public{
+ Name: "name",
+ Secret: Bug4Secret{1},
+ }
+ buf := new(bytes.Buffer)
+ enc := NewEncoder(buf)
+ err := enc.Encode(x)
+ if err == nil {
+ t.Fatal("first encoding: expected error")
+ }
+ buf.Reset()
+ enc = NewEncoder(buf)
+ err = enc.Encode(x)
+ if err == nil {
+ t.Fatal("second encoding: expected error")
+ }
+ if !strings.Contains(err.Error(), "no exported fields") {
+ t.Errorf("expected error about no exported fields; got %v", err)
+ }
+}
+
// There was an error check comparing the length of the input with the
// length of the slice being decoded. It was wrong because the next
// thing in the input might be a type definition, which would lead to
diff --git a/libgo/go/encoding/gob/type.go b/libgo/go/encoding/gob/type.go
index a8ee2fa4a5a..ea0db4eac45 100644
--- a/libgo/go/encoding/gob/type.go
+++ b/libgo/go/encoding/gob/type.go
@@ -712,6 +712,7 @@ type GobDecoder interface {
}
var (
+ registerLock sync.RWMutex
nameToConcreteType = make(map[string]reflect.Type)
concreteTypeToName = make(map[reflect.Type]string)
)
@@ -723,6 +724,8 @@ func RegisterName(name string, value interface{}) {
// reserved for nil
panic("attempt to register empty name")
}
+ registerLock.Lock()
+ defer registerLock.Unlock()
ut := userType(reflect.TypeOf(value))
// Check for incompatible duplicates. The name must refer to the
// same user type, and vice versa.
diff --git a/libgo/go/encoding/gob/type_test.go b/libgo/go/encoding/gob/type_test.go
index 42bdb4cf7bb..e230d22d431 100644
--- a/libgo/go/encoding/gob/type_test.go
+++ b/libgo/go/encoding/gob/type_test.go
@@ -5,6 +5,7 @@
package gob
import (
+ "bytes"
"reflect"
"testing"
)
@@ -159,3 +160,63 @@ func TestRegistration(t *testing.T) {
Register(new(T))
Register(new(T))
}
+
+type N1 struct{}
+type N2 struct{}
+
+// See comment in type.go/Register.
+func TestRegistrationNaming(t *testing.T) {
+ testCases := []struct {
+ t interface{}
+ name string
+ }{
+ {&N1{}, "*gob.N1"},
+ {N2{}, "encoding/gob.N2"},
+ }
+
+ for _, tc := range testCases {
+ Register(tc.t)
+
+ tct := reflect.TypeOf(tc.t)
+ registerLock.RLock()
+ ct := nameToConcreteType[tc.name]
+ registerLock.RUnlock()
+ if ct != tct {
+ t.Errorf("nameToConcreteType[%q] = %v, want %v", tc.name, ct, tct)
+ }
+ // concreteTypeToName is keyed off the base type.
+ if tct.Kind() == reflect.Ptr {
+ tct = tct.Elem()
+ }
+ if n := concreteTypeToName[tct]; n != tc.name {
+ t.Errorf("concreteTypeToName[%v] got %v, want %v", tct, n, tc.name)
+ }
+ }
+}
+
+func TestStressParallel(t *testing.T) {
+ type T2 struct{ A int }
+ c := make(chan bool)
+ const N = 10
+ for i := 0; i < N; i++ {
+ go func() {
+ p := new(T2)
+ Register(p)
+ b := new(bytes.Buffer)
+ enc := NewEncoder(b)
+ err := enc.Encode(p)
+ if err != nil {
+ t.Error("encoder fail:", err)
+ }
+ dec := NewDecoder(b)
+ err = dec.Decode(p)
+ if err != nil {
+ t.Error("decoder fail:", err)
+ }
+ c <- true
+ }()
+ }
+ for i := 0; i < N; i++ {
+ <-c
+ }
+}
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go
index d61f8870646..47e3d89aa35 100644
--- a/libgo/go/encoding/json/decode.go
+++ b/libgo/go/encoding/json/decode.go
@@ -137,6 +137,22 @@ func (d *decodeState) unmarshal(v interface{}) (err error) {
return d.savedError
}
+// A Number represents a JSON number literal.
+type Number string
+
+// String returns the literal text of the number.
+func (n Number) String() string { return string(n) }
+
+// Float64 returns the number as a float64.
+func (n Number) Float64() (float64, error) {
+ return strconv.ParseFloat(string(n), 64)
+}
+
+// Int64 returns the number as an int64.
+func (n Number) Int64() (int64, error) {
+ return strconv.ParseInt(string(n), 10, 64)
+}
+
// decodeState represents the state while decoding a JSON value.
type decodeState struct {
data []byte
@@ -145,6 +161,7 @@ type decodeState struct {
nextscan scanner // for calls to nextValue
savedError error
tempstr string // scratch space to avoid some allocations
+ useNumber bool
}
// errPhase is used for errors that should not happen unless
@@ -265,47 +282,32 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler,
v = v.Addr()
}
for {
- var isUnmarshaler bool
- if v.Type().NumMethod() > 0 {
- // Remember that this is an unmarshaler,
- // but wait to return it until after allocating
- // the pointer (if necessary).
- _, isUnmarshaler = v.Interface().(Unmarshaler)
- }
-
// Load value from interface, but only if the result will be
// usefully addressable.
- if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() {
- e := iv.Elem()
+ if v.Kind() == reflect.Interface && !v.IsNil() {
+ e := v.Elem()
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
v = e
continue
}
}
- pv := v
- if pv.Kind() != reflect.Ptr {
+ if v.Kind() != reflect.Ptr {
break
}
- if pv.Elem().Kind() != reflect.Ptr && decodingNull && pv.CanSet() {
- return nil, pv
+ if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
+ break
}
- if pv.IsNil() {
- pv.Set(reflect.New(pv.Type().Elem()))
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
}
- if isUnmarshaler {
- // Using v.Interface().(Unmarshaler)
- // here means that we have to use a pointer
- // as the struct field. We cannot use a value inside
- // a pointer to a struct, because in that case
- // v.Interface() is the value (x.f) not the pointer (&x.f).
- // This is an unfortunate consequence of reflect.
- // An alternative would be to look up the
- // UnmarshalJSON method and return a FuncValue.
- return v.Interface().(Unmarshaler), reflect.Value{}
+ if v.Type().NumMethod() > 0 {
+ if unmarshaler, ok := v.Interface().(Unmarshaler); ok {
+ return unmarshaler, reflect.Value{}
+ }
}
- v = pv.Elem()
+ v = v.Elem()
}
return nil, v
}
@@ -491,51 +493,39 @@ func (d *decodeState) object(v reflect.Value) {
}
subv = mapElem
} else {
- var f reflect.StructField
- var ok bool
- st := sv.Type()
- for i := 0; i < sv.NumField(); i++ {
- sf := st.Field(i)
- tag := sf.Tag.Get("json")
- if tag == "-" {
- // Pretend this field doesn't exist.
- continue
+ var f *field
+ fields := cachedTypeFields(sv.Type())
+ for i := range fields {
+ ff := &fields[i]
+ if ff.name == key {
+ f = ff
+ break
}
- if sf.Anonymous {
- // Pretend this field doesn't exist,
- // so that we can do a good job with
- // these in a later version.
- continue
- }
- // First, tag match
- tagName, _ := parseTag(tag)
- if tagName == key {
- f = sf
- ok = true
- break // no better match possible
- }
- // Second, exact field name match
- if sf.Name == key {
- f = sf
- ok = true
- }
- // Third, case-insensitive field name match,
- // but only if a better match hasn't already been seen
- if !ok && strings.EqualFold(sf.Name, key) {
- f = sf
- ok = true
+ if f == nil && strings.EqualFold(ff.name, key) {
+ f = ff
}
}
-
- // Extract value; name must be exported.
- if ok {
- if f.PkgPath != "" {
- d.saveError(&UnmarshalFieldError{key, st, f})
- } else {
- subv = sv.FieldByIndex(f.Index)
+ if f != nil {
+ subv = sv
+ destring = f.quoted
+ for _, i := range f.index {
+ if subv.Kind() == reflect.Ptr {
+ if subv.IsNil() {
+ subv.Set(reflect.New(subv.Type().Elem()))
+ }
+ subv = subv.Elem()
+ }
+ subv = subv.Field(i)
+ }
+ } else {
+ // To give a good error, a quick scan for unexported fields in top level.
+ st := sv.Type()
+ for i := 0; i < st.NumField(); i++ {
+ f := st.Field(i)
+ if f.PkgPath != "" && strings.EqualFold(f.Name, key) {
+ d.saveError(&UnmarshalFieldError{key, st, f})
+ }
}
- _, opts := parseTag(f.Tag.Get("json"))
- destring = opts.Contains("string")
}
}
@@ -586,6 +576,21 @@ func (d *decodeState) literal(v reflect.Value) {
d.literalStore(d.data[start:d.off], v, false)
}
+// convertNumber converts the number literal s to a float64 or a Number
+// depending on the setting of d.useNumber.
+func (d *decodeState) convertNumber(s string) (interface{}, error) {
+ if d.useNumber {
+ return Number(s), nil
+ }
+ f, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0)}
+ }
+ return f, nil
+}
+
+var numberType = reflect.TypeOf(Number(""))
+
// literalStore decodes a literal stored in item into v.
//
// fromQuoted indicates whether this literal came from unwrapping a
@@ -674,15 +679,19 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
s := string(item)
switch v.Kind() {
default:
+ if v.Kind() == reflect.String && v.Type() == numberType {
+ v.SetString(s)
+ break
+ }
if fromQuoted {
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
d.error(&UnmarshalTypeError{"number", v.Type()})
}
case reflect.Interface:
- n, err := strconv.ParseFloat(s, 64)
+ n, err := d.convertNumber(s)
if err != nil {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+ d.saveError(err)
break
}
v.Set(reflect.ValueOf(n))
@@ -836,9 +845,9 @@ func (d *decodeState) literalInterface() interface{} {
if c != '-' && (c < '0' || c > '9') {
d.error(errPhase)
}
- n, err := strconv.ParseFloat(string(item), 64)
+ n, err := d.convertNumber(string(item))
if err != nil {
- d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)})
+ d.saveError(err)
}
return n
}
@@ -979,11 +988,3 @@ func unquoteBytes(s []byte) (t []byte, ok bool) {
}
return b[0:w], true
}
-
-// The following is issue 3069.
-
-// BUG(rsc): This package ignores anonymous (embedded) struct fields
-// during encoding and decoding. A future version may assign meaning
-// to them. To force an anonymous field to be ignored in all future
-// versions of this package, use an explicit `json:"-"` tag in the struct
-// definition.
diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go
index 6fac22c4a35..f2da141b8f9 100644
--- a/libgo/go/encoding/json/decode_test.go
+++ b/libgo/go/encoding/json/decode_test.go
@@ -7,6 +7,7 @@ package json
import (
"bytes"
"fmt"
+ "image"
"reflect"
"strings"
"testing"
@@ -18,6 +19,32 @@ type T struct {
Z int `json:"-"`
}
+type U struct {
+ Alphabet string `json:"alpha"`
+}
+
+type V struct {
+ F1 interface{}
+ F2 int32
+ F3 Number
+}
+
+// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshalling with and
+// without UseNumber
+var ifaceNumAsFloat64 = map[string]interface{}{
+ "k1": float64(1),
+ "k2": "s",
+ "k3": []interface{}{float64(1), float64(2.0), float64(3e-3)},
+ "k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)},
+}
+
+var ifaceNumAsNumber = map[string]interface{}{
+ "k1": Number("1"),
+ "k2": "s",
+ "k3": []interface{}{Number("1"), Number("2.0"), Number("3e-3")},
+ "k4": map[string]interface{}{"kk1": "s", "kk2": Number("2")},
+}
+
type tx struct {
x int
}
@@ -48,55 +75,237 @@ var (
umstruct = ustruct{unmarshaler{true}}
)
+// Test data structures for anonymous fields.
+
+type Point struct {
+ Z int
+}
+
+type Top struct {
+ Level0 int
+ Embed0
+ *Embed0a
+ *Embed0b `json:"e,omitempty"` // treated as named
+ Embed0c `json:"-"` // ignored
+ Loop
+ Embed0p // has Point with X, Y, used
+ Embed0q // has Point with Z, used
+}
+
+type Embed0 struct {
+ Level1a int // overridden by Embed0a's Level1a with json tag
+ Level1b int // used because Embed0a's Level1b is renamed
+ Level1c int // used because Embed0a's Level1c is ignored
+ Level1d int // annihilated by Embed0a's Level1d
+ Level1e int `json:"x"` // annihilated by Embed0a.Level1e
+}
+
+type Embed0a struct {
+ Level1a int `json:"Level1a,omitempty"`
+ Level1b int `json:"LEVEL1B,omitempty"`
+ Level1c int `json:"-"`
+ Level1d int // annihilated by Embed0's Level1d
+ Level1f int `json:"x"` // annihilated by Embed0's Level1e
+}
+
+type Embed0b Embed0
+
+type Embed0c Embed0
+
+type Embed0p struct {
+ image.Point
+}
+
+type Embed0q struct {
+ Point
+}
+
+type Loop struct {
+ Loop1 int `json:",omitempty"`
+ Loop2 int `json:",omitempty"`
+ *Loop
+}
+
+// From reflect test:
+// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
+type S5 struct {
+ S6
+ S7
+ S8
+}
+
+type S6 struct {
+ X int
+}
+
+type S7 S6
+
+type S8 struct {
+ S9
+}
+
+type S9 struct {
+ X int
+ Y int
+}
+
+// From reflect test:
+// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
+type S10 struct {
+ S11
+ S12
+ S13
+}
+
+type S11 struct {
+ S6
+}
+
+type S12 struct {
+ S6
+}
+
+type S13 struct {
+ S8
+}
+
type unmarshalTest struct {
- in string
- ptr interface{}
- out interface{}
- err error
+ in string
+ ptr interface{}
+ out interface{}
+ err error
+ useNumber bool
+}
+
+type Ambig struct {
+ // Given "hello", the first match should win.
+ First int `json:"HELLO"`
+ Second int `json:"Hello"`
}
var unmarshalTests = []unmarshalTest{
// basic types
- {`true`, new(bool), true, nil},
- {`1`, new(int), 1, nil},
- {`1.2`, new(float64), 1.2, nil},
- {`-5`, new(int16), int16(-5), nil},
- {`"a\u1234"`, new(string), "a\u1234", nil},
- {`"http:\/\/"`, new(string), "http://", nil},
- {`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil},
- {`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
- {"null", new(interface{}), nil, nil},
- {`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}},
- {`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
+ {in: `true`, ptr: new(bool), out: true},
+ {in: `1`, ptr: new(int), out: 1},
+ {in: `1.2`, ptr: new(float64), out: 1.2},
+ {in: `-5`, ptr: new(int16), out: int16(-5)},
+ {in: `2`, ptr: new(Number), out: Number("2"), useNumber: true},
+ {in: `2`, ptr: new(Number), out: Number("2")},
+ {in: `2`, ptr: new(interface{}), out: float64(2.0)},
+ {in: `2`, ptr: new(interface{}), out: Number("2"), useNumber: true},
+ {in: `"a\u1234"`, ptr: new(string), out: "a\u1234"},
+ {in: `"http:\/\/"`, ptr: new(string), out: "http://"},
+ {in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
+ {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
+ {in: "null", ptr: new(interface{}), out: nil},
+ {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf("")}},
+ {in: `{"x": 1}`, ptr: new(tx), out: tx{}, err: &UnmarshalFieldError{"x", txType, txType.Field(0)}},
+ {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
+ {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
+ {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64},
+ {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true},
// Z has a "-" tag.
- {`{"Y": 1, "Z": 2}`, new(T), T{Y: 1}, nil},
+ {in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}},
+
+ {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}},
+ {in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}},
+ {in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}},
// syntax errors
- {`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
- {`[1, 2, 3+]`, nil, nil, &SyntaxError{"invalid character '+' after array element", 9}},
+ {in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}},
+ {in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
+ {in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true},
// array tests
- {`[1, 2, 3]`, new([3]int), [3]int{1, 2, 3}, nil},
- {`[1, 2, 3]`, new([1]int), [1]int{1}, nil},
- {`[1, 2, 3]`, new([5]int), [5]int{1, 2, 3, 0, 0}, nil},
+ {in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
+ {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
+ {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
// composite tests
- {allValueIndent, new(All), allValue, nil},
- {allValueCompact, new(All), allValue, nil},
- {allValueIndent, new(*All), &allValue, nil},
- {allValueCompact, new(*All), &allValue, nil},
- {pallValueIndent, new(All), pallValue, nil},
- {pallValueCompact, new(All), pallValue, nil},
- {pallValueIndent, new(*All), &pallValue, nil},
- {pallValueCompact, new(*All), &pallValue, nil},
+ {in: allValueIndent, ptr: new(All), out: allValue},
+ {in: allValueCompact, ptr: new(All), out: allValue},
+ {in: allValueIndent, ptr: new(*All), out: &allValue},
+ {in: allValueCompact, ptr: new(*All), out: &allValue},
+ {in: pallValueIndent, ptr: new(All), out: pallValue},
+ {in: pallValueCompact, ptr: new(All), out: pallValue},
+ {in: pallValueIndent, ptr: new(*All), out: &pallValue},
+ {in: pallValueCompact, ptr: new(*All), out: &pallValue},
// unmarshal interface test
- {`{"T":false}`, &um0, umtrue, nil}, // use "false" so test will fail if custom unmarshaler is not called
- {`{"T":false}`, &ump, &umtrue, nil},
- {`[{"T":false}]`, &umslice, umslice, nil},
- {`[{"T":false}]`, &umslicep, &umslice, nil},
- {`{"M":{"T":false}}`, &umstruct, umstruct, nil},
+ {in: `{"T":false}`, ptr: &um0, out: umtrue}, // use "false" so test will fail if custom unmarshaler is not called
+ {in: `{"T":false}`, ptr: &ump, out: &umtrue},
+ {in: `[{"T":false}]`, ptr: &umslice, out: umslice},
+ {in: `[{"T":false}]`, ptr: &umslicep, out: &umslice},
+ {in: `{"M":{"T":false}}`, ptr: &umstruct, out: umstruct},
+
+ {
+ in: `{
+ "Level0": 1,
+ "Level1b": 2,
+ "Level1c": 3,
+ "x": 4,
+ "Level1a": 5,
+ "LEVEL1B": 6,
+ "e": {
+ "Level1a": 8,
+ "Level1b": 9,
+ "Level1c": 10,
+ "Level1d": 11,
+ "x": 12
+ },
+ "Loop1": 13,
+ "Loop2": 14,
+ "X": 15,
+ "Y": 16,
+ "Z": 17
+ }`,
+ ptr: new(Top),
+ out: Top{
+ Level0: 1,
+ Embed0: Embed0{
+ Level1b: 2,
+ Level1c: 3,
+ },
+ Embed0a: &Embed0a{
+ Level1a: 5,
+ Level1b: 6,
+ },
+ Embed0b: &Embed0b{
+ Level1a: 8,
+ Level1b: 9,
+ Level1c: 10,
+ Level1d: 11,
+ Level1e: 12,
+ },
+ Loop: Loop{
+ Loop1: 13,
+ Loop2: 14,
+ },
+ Embed0p: Embed0p{
+ Point: image.Point{X: 15, Y: 16},
+ },
+ Embed0q: Embed0q{
+ Point: Point{Z: 17},
+ },
+ },
+ },
+ {
+ in: `{"hello": 1}`,
+ ptr: new(Ambig),
+ out: Ambig{First: 1},
+ },
+
+ {
+ in: `{"X": 1,"Y":2}`,
+ ptr: new(S5),
+ out: S5{S8: S8{S9: S9{Y: 2}}},
+ },
+ {
+ in: `{"X": 1,"Y":2}`,
+ ptr: new(S10),
+ out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}},
+ },
}
func TestMarshal(t *testing.T) {
@@ -135,6 +344,18 @@ func TestMarshalBadUTF8(t *testing.T) {
}
}
+func TestMarshalNumberZeroVal(t *testing.T) {
+ var n Number
+ out, err := Marshal(n)
+ if err != nil {
+ t.Fatal(err)
+ }
+ outStr := string(out)
+ if outStr != "0" {
+ t.Fatalf("Invalid zero val for Number: %q", outStr)
+ }
+}
+
func TestUnmarshal(t *testing.T) {
for i, tt := range unmarshalTests {
var scan scanner
@@ -150,7 +371,11 @@ func TestUnmarshal(t *testing.T) {
}
// v = new(right-type)
v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
- if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
+ dec := NewDecoder(bytes.NewBuffer(in))
+ if tt.useNumber {
+ dec.UseNumber()
+ }
+ if err := dec.Decode(v.Interface()); !reflect.DeepEqual(err, tt.err) {
t.Errorf("#%d: %v want %v", i, err, tt.err)
continue
}
@@ -162,6 +387,28 @@ func TestUnmarshal(t *testing.T) {
println(string(data))
continue
}
+
+ // Check round trip.
+ if tt.err == nil {
+ enc, err := Marshal(v.Interface())
+ if err != nil {
+ t.Errorf("#%d: error re-marshaling: %v", i, err)
+ continue
+ }
+ vv := reflect.New(reflect.TypeOf(tt.ptr).Elem())
+ dec = NewDecoder(bytes.NewBuffer(enc))
+ if tt.useNumber {
+ dec.UseNumber()
+ }
+ if err := dec.Decode(vv.Interface()); err != nil {
+ t.Errorf("#%d: error re-unmarshaling: %v", i, err)
+ continue
+ }
+ if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) {
+ t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface())
+ continue
+ }
+ }
}
}
@@ -182,6 +429,38 @@ func TestUnmarshalMarshal(t *testing.T) {
}
}
+var numberTests = []struct {
+ in string
+ i int64
+ intErr string
+ f float64
+ floatErr string
+}{
+ {in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1},
+ {in: "-12", i: -12, f: -12.0},
+ {in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"},
+}
+
+// Independent of Decode, basic coverage of the accessors in Number
+func TestNumberAccessors(t *testing.T) {
+ for _, tt := range numberTests {
+ n := Number(tt.in)
+ if s := n.String(); s != tt.in {
+ t.Errorf("Number(%q).String() is %q", tt.in, s)
+ }
+ if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i {
+ t.Errorf("Number(%q).Int64() is %d", tt.in, i)
+ } else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) {
+ t.Errorf("Number(%q).Int64() wanted error %q but got: %v", tt.in, tt.intErr, err)
+ }
+ if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f {
+ t.Errorf("Number(%q).Float64() is %g", tt.in, f)
+ } else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) {
+ t.Errorf("Number(%q).Float64() wanted error %q but got: %v", tt.in, tt.floatErr, err)
+ }
+ }
+}
+
func TestLargeByteSlice(t *testing.T) {
s0 := make([]byte, 2000)
for i := range s0 {
@@ -610,35 +889,6 @@ func TestRefUnmarshal(t *testing.T) {
}
}
-// Test that anonymous fields are ignored.
-// We may assign meaning to them later.
-func TestAnonymous(t *testing.T) {
- type S struct {
- T
- N int
- }
-
- data, err := Marshal(new(S))
- if err != nil {
- t.Fatalf("Marshal: %v", err)
- }
- want := `{"N":0}`
- if string(data) != want {
- t.Fatalf("Marshal = %#q, want %#q", string(data), want)
- }
-
- var s S
- if err := Unmarshal([]byte(`{"T": 1, "T": {"Y": 1}, "N": 2}`), &s); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if s.N != 2 {
- t.Fatal("Unmarshal: did not set N")
- }
- if s.T.Y != 0 {
- t.Fatal("Unmarshal: did set T.Y")
- }
-}
-
// Test that the empty string doesn't panic decoding when ,string is specified
// Issue 3450
func TestEmptyString(t *testing.T) {
diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go
index d2c1c4424c7..c8535ef79d6 100644
--- a/libgo/go/encoding/json/encode.go
+++ b/libgo/go/encoding/json/encode.go
@@ -36,7 +36,7 @@ import (
//
// Boolean values encode as JSON booleans.
//
-// Floating point and integer values encode as JSON numbers.
+// Floating point, integer, and Number values encode as JSON numbers.
//
// String values encode as JSON strings, with each invalid UTF-8 sequence
// replaced by the encoding of the Unicode replacement character U+FFFD.
@@ -84,6 +84,16 @@ import (
// only Unicode letters, digits, dollar signs, percent signs, hyphens,
// underscores and slashes.
//
+// Anonymous struct fields are usually marshaled as if their inner exported fields
+// were fields in the outer struct, subject to the usual Go visibility rules.
+// An anonymous struct field with a name given in its JSON tag is treated as
+// having that name instead of as anonymous.
+//
+// Handling of anonymous struct fields is new in Go 1.1.
+// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
+// an anonymous struct field in both current and earlier versions, give the field
+// a JSON tag of "-".
+//
// Map values encode as JSON objects.
// The map's key type must be string; the object keys are used directly
// as map keys.
@@ -312,6 +322,14 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
e.Write(b)
}
case reflect.String:
+ if v.Type() == numberType {
+ numStr := v.String()
+ if numStr == "" {
+ numStr = "0" // Number's zero-val
+ }
+ e.WriteString(numStr)
+ break
+ }
if quoted {
sb, err := Marshal(v.String())
if err != nil {
@@ -325,9 +343,9 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
case reflect.Struct:
e.WriteByte('{')
first := true
- for _, ef := range encodeFields(v.Type()) {
- fieldValue := v.Field(ef.i)
- if ef.omitEmpty && isEmptyValue(fieldValue) {
+ for _, f := range cachedTypeFields(v.Type()) {
+ fv := fieldByIndex(v, f.index)
+ if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
continue
}
if first {
@@ -335,9 +353,9 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
} else {
e.WriteByte(',')
}
- e.string(ef.tag)
+ e.string(f.name)
e.WriteByte(':')
- e.reflectValueQuoted(fieldValue, ef.quoted)
+ e.reflectValueQuoted(fv, f.quoted)
}
e.WriteByte('}')
@@ -432,6 +450,19 @@ func isValidTag(s string) bool {
return true
}
+func fieldByIndex(v reflect.Value, index []int) reflect.Value {
+ for _, i := range index {
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return reflect.Value{}
+ }
+ v = v.Elem()
+ }
+ v = v.Field(i)
+ }
+ return v
+}
+
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
// It implements the methods to sort by string.
type stringValues []reflect.Value
@@ -490,67 +521,183 @@ func (e *encodeState) string(s string) (int, error) {
return e.Len() - len0, nil
}
-// encodeField contains information about how to encode a field of a
-// struct.
-type encodeField struct {
- i int // field index in struct
- tag string
- quoted bool
+// A field represents a single field found in a struct.
+type field struct {
+ name string
+ tag bool
+ index []int
+ typ reflect.Type
omitEmpty bool
+ quoted bool
}
-var (
- typeCacheLock sync.RWMutex
- encodeFieldsCache = make(map[reflect.Type][]encodeField)
-)
+// byName sorts field by name, breaking ties with depth,
+// then breaking ties with "name came from json tag", then
+// breaking ties with index sequence.
+type byName []field
-// encodeFields returns a slice of encodeField for a given
-// struct type.
-func encodeFields(t reflect.Type) []encodeField {
- typeCacheLock.RLock()
- fs, ok := encodeFieldsCache[t]
- typeCacheLock.RUnlock()
- if ok {
- return fs
- }
+func (x byName) Len() int { return len(x) }
+
+func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
- typeCacheLock.Lock()
- defer typeCacheLock.Unlock()
- fs, ok = encodeFieldsCache[t]
- if ok {
- return fs
+func (x byName) Less(i, j int) bool {
+ if x[i].name != x[j].name {
+ return x[i].name < x[j].name
}
+ if len(x[i].index) != len(x[j].index) {
+ return len(x[i].index) < len(x[j].index)
+ }
+ if x[i].tag != x[j].tag {
+ return x[i].tag
+ }
+ return byIndex(x).Less(i, j)
+}
- v := reflect.Zero(t)
- n := v.NumField()
- for i := 0; i < n; i++ {
- f := t.Field(i)
- if f.PkgPath != "" {
- continue
+// byIndex sorts field by index sequence.
+type byIndex []field
+
+func (x byIndex) Len() int { return len(x) }
+
+func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+func (x byIndex) Less(i, j int) bool {
+ for k, xik := range x[i].index {
+ if k >= len(x[j].index) {
+ return false
}
- if f.Anonymous {
- // We want to do a better job with these later,
- // so for now pretend they don't exist.
- continue
+ if xik != x[j].index[k] {
+ return xik < x[j].index[k]
}
- var ef encodeField
- ef.i = i
- ef.tag = f.Name
+ }
+ return len(x[i].index) < len(x[j].index)
+}
+
+// typeFields returns a list of fields that JSON should recognize for the given type.
+// The algorithm is breadth-first search over the set of structs to include - the top struct
+// and then any reachable anonymous structs.
+func typeFields(t reflect.Type) []field {
+ // Anonymous fields to explore at the current level and the next.
+ current := []field{}
+ next := []field{{typ: t}}
+
+ // Count of queued names for current level and the next.
+ count := map[reflect.Type]int{}
+ nextCount := map[reflect.Type]int{}
+
+ // Types already visited at an earlier level.
+ visited := map[reflect.Type]bool{}
+
+ // Fields found.
+ var fields []field
+
+ for len(next) > 0 {
+ current, next = next, current[:0]
+ count, nextCount = nextCount, map[reflect.Type]int{}
- tv := f.Tag.Get("json")
- if tv != "" {
- if tv == "-" {
+ for _, f := range current {
+ if visited[f.typ] {
continue
}
- name, opts := parseTag(tv)
- if isValidTag(name) {
- ef.tag = name
+ visited[f.typ] = true
+
+ // Scan f.typ for fields to include.
+ for i := 0; i < f.typ.NumField(); i++ {
+ sf := f.typ.Field(i)
+ if sf.PkgPath != "" { // unexported
+ continue
+ }
+ tag := sf.Tag.Get("json")
+ if tag == "-" {
+ continue
+ }
+ name, opts := parseTag(tag)
+ if !isValidTag(name) {
+ name = ""
+ }
+ index := make([]int, len(f.index)+1)
+ copy(index, f.index)
+ index[len(f.index)] = i
+ // Record found field and index sequence.
+ if name != "" || !sf.Anonymous {
+ tagged := name != ""
+ if name == "" {
+ name = sf.Name
+ }
+ fields = append(fields, field{name, tagged, index, sf.Type,
+ opts.Contains("omitempty"), opts.Contains("string")})
+ if count[f.typ] > 1 {
+ // If there were multiple instances, add a second,
+ // so that the annihilation code will see a duplicate.
+ // It only cares about the distinction between 1 or 2,
+ // so don't bother generating any more copies.
+ fields = append(fields, fields[len(fields)-1])
+ }
+ continue
+ }
+
+ // Record new anonymous struct to explore in next round.
+ ft := sf.Type
+ if ft.Name() == "" {
+ // Must be pointer.
+ ft = ft.Elem()
+ }
+ nextCount[ft]++
+ if nextCount[ft] == 1 {
+ next = append(next, field{name: ft.Name(), index: index, typ: ft})
+ }
}
- ef.omitEmpty = opts.Contains("omitempty")
- ef.quoted = opts.Contains("string")
}
- fs = append(fs, ef)
}
- encodeFieldsCache[t] = fs
- return fs
+
+ sort.Sort(byName(fields))
+
+ // Remove fields with annihilating name collisions
+ // and also fields shadowed by fields with explicit JSON tags.
+ name := ""
+ out := fields[:0]
+ for _, f := range fields {
+ if f.name != name {
+ name = f.name
+ out = append(out, f)
+ continue
+ }
+ if n := len(out); n > 0 && out[n-1].name == name && (!out[n-1].tag || f.tag) {
+ out = out[:n-1]
+ }
+ }
+ fields = out
+
+ sort.Sort(byIndex(fields))
+
+ return fields
+}
+
+var fieldCache struct {
+ sync.RWMutex
+ m map[reflect.Type][]field
+}
+
+// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
+func cachedTypeFields(t reflect.Type) []field {
+ fieldCache.RLock()
+ f := fieldCache.m[t]
+ fieldCache.RUnlock()
+ if f != nil {
+ return f
+ }
+
+ // Compute fields without lock.
+ // Might duplicate effort but won't hold other computations back.
+ f = typeFields(t)
+ if f == nil {
+ f = []field{}
+ }
+
+ fieldCache.Lock()
+ if fieldCache.m == nil {
+ fieldCache.m = map[reflect.Type][]field{}
+ }
+ fieldCache.m[t] = f
+ fieldCache.Unlock()
+ return f
}
diff --git a/libgo/go/encoding/json/stream.go b/libgo/go/encoding/json/stream.go
index 7d1cc5f119c..9592467d25b 100644
--- a/libgo/go/encoding/json/stream.go
+++ b/libgo/go/encoding/json/stream.go
@@ -26,6 +26,10 @@ func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
+// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
+// Number instead of as a float64.
+func (dec *Decoder) UseNumber() { dec.d.useNumber = true }
+
// Decode reads the next JSON-encoded value from its
// input and stores it in the value pointed to by v.
//
@@ -74,7 +78,7 @@ Input:
// scanEnd is delayed one byte.
// We might block trying to get that byte from src,
// so instead invent a space byte.
- if v == scanEndObject && dec.scan.step(&dec.scan, ' ') == scanEnd {
+ if (v == scanEndObject || v == scanEndArray) && dec.scan.step(&dec.scan, ' ') == scanEnd {
scanp += i + 1
break Input
}
diff --git a/libgo/go/encoding/json/stream_test.go b/libgo/go/encoding/json/stream_test.go
index ce5a7e6d656..4d66f556767 100644
--- a/libgo/go/encoding/json/stream_test.go
+++ b/libgo/go/encoding/json/stream_test.go
@@ -6,6 +6,7 @@ package json
import (
"bytes"
+ "net"
"reflect"
"testing"
)
@@ -145,3 +146,24 @@ func TestNullRawMessage(t *testing.T) {
t.Fatalf("Marshal: have %#q want %#q", b, msg)
}
}
+
+var blockingTests = []string{
+ `{"x": 1}`,
+ `[1, 2, 3]`,
+}
+
+func TestBlocking(t *testing.T) {
+ for _, enc := range blockingTests {
+ r, w := net.Pipe()
+ go w.Write([]byte(enc))
+ var val interface{}
+
+ // If Decode reads beyond what w.Write writes above,
+ // it will block, and the test will deadlock.
+ if err := NewDecoder(r).Decode(&val); err != nil {
+ t.Errorf("decoding %s: %v", enc, err)
+ }
+ r.Close()
+ w.Close()
+ }
+}
diff --git a/libgo/go/encoding/xml/marshal.go b/libgo/go/encoding/xml/marshal.go
index 6c3170bdda3..8592a0c15cb 100644
--- a/libgo/go/encoding/xml/marshal.go
+++ b/libgo/go/encoding/xml/marshal.go
@@ -57,8 +57,8 @@ const (
// if the field value is empty. The empty values are false, 0, any
// nil pointer or interface value, and any array, slice, map, or
// string of length zero.
-// - a non-pointer anonymous struct field is handled as if the
-// fields of its value were part of the outer struct.
+// - an anonymous struct field is handled as if the fields of its
+// value were part of the outer struct.
//
// If a field uses a tag "a>b>c", then the element c will be nested inside
// parent elements a and b. Fields that appear next to each other that name
@@ -83,9 +83,7 @@ func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
enc := NewEncoder(&b)
enc.prefix = prefix
enc.indent = indent
- err := enc.marshalValue(reflect.ValueOf(v), nil)
- enc.Flush()
- if err != nil {
+ if err := enc.Encode(v); err != nil {
return nil, err
}
return b.Bytes(), nil
@@ -107,8 +105,10 @@ func NewEncoder(w io.Writer) *Encoder {
// of Go values to XML.
func (enc *Encoder) Encode(v interface{}) error {
err := enc.marshalValue(reflect.ValueOf(v), nil)
- enc.Flush()
- return err
+ if err != nil {
+ return err
+ }
+ return enc.Flush()
}
type printer struct {
@@ -164,7 +164,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
xmlname := tinfo.xmlname
if xmlname.name != "" {
xmlns, name = xmlname.xmlns, xmlname.name
- } else if v, ok := val.FieldByIndex(xmlname.idx).Interface().(Name); ok && v.Local != "" {
+ } else if v, ok := xmlname.value(val).Interface().(Name); ok && v.Local != "" {
xmlns, name = v.Space, v.Local
}
}
@@ -195,7 +195,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
if finfo.flags&fAttr == 0 {
continue
}
- fv := val.FieldByIndex(finfo.idx)
+ fv := finfo.value(val)
if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
continue
}
@@ -224,7 +224,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
p.WriteString(name)
p.WriteByte('>')
- return nil
+ return p.cachedWriteError()
}
var timeType = reflect.TypeOf(time.Time{})
@@ -260,15 +260,15 @@ func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error {
default:
return &UnsupportedTypeError{typ}
}
- return nil
+ return p.cachedWriteError()
}
var ddBytes = []byte("--")
func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
if val.Type() == timeType {
- p.WriteString(val.Interface().(time.Time).Format(time.RFC3339Nano))
- return nil
+ _, err := p.WriteString(val.Interface().(time.Time).Format(time.RFC3339Nano))
+ return err
}
s := parentStack{printer: p}
for i := range tinfo.fields {
@@ -276,7 +276,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
if finfo.flags&(fAttr|fAny) != 0 {
continue
}
- vf := val.FieldByIndex(finfo.idx)
+ vf := finfo.value(val)
switch finfo.flags & fMode {
case fCharData:
switch vf.Kind() {
@@ -353,7 +353,13 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
}
}
s.trim(nil)
- return nil
+ return p.cachedWriteError()
+}
+
+// return the bufio Writer's cached write error
+func (p *printer) cachedWriteError() error {
+ _, err := p.Write(nil)
+ return err
}
func (p *printer) writeIndent(depthDelta int) {
diff --git a/libgo/go/encoding/xml/marshal_test.go b/libgo/go/encoding/xml/marshal_test.go
index b6978a1e65b..e729a247af4 100644
--- a/libgo/go/encoding/xml/marshal_test.go
+++ b/libgo/go/encoding/xml/marshal_test.go
@@ -5,6 +5,9 @@
package xml
import (
+ "bytes"
+ "errors"
+ "io"
"reflect"
"strconv"
"strings"
@@ -108,7 +111,7 @@ type EmbedA struct {
type EmbedB struct {
FieldB string
- EmbedC
+ *EmbedC
}
type EmbedC struct {
@@ -493,7 +496,7 @@ var marshalTests = []struct {
},
EmbedB: EmbedB{
FieldB: "A.B.B",
- EmbedC: EmbedC{
+ EmbedC: &EmbedC{
FieldA1: "A.B.C.A1",
FieldA2: "A.B.C.A2",
FieldB: "", // Shadowed by A.B.B
@@ -779,6 +782,55 @@ func TestUnmarshal(t *testing.T) {
}
}
+type limitedBytesWriter struct {
+ w io.Writer
+ remain int // until writes fail
+}
+
+func (lw *limitedBytesWriter) Write(p []byte) (n int, err error) {
+ if lw.remain <= 0 {
+ println("error")
+ return 0, errors.New("write limit hit")
+ }
+ if len(p) > lw.remain {
+ p = p[:lw.remain]
+ n, _ = lw.w.Write(p)
+ lw.remain = 0
+ return n, errors.New("write limit hit")
+ }
+ n, err = lw.w.Write(p)
+ lw.remain -= n
+ return n, err
+}
+
+func TestMarshalWriteErrors(t *testing.T) {
+ var buf bytes.Buffer
+ const writeCap = 1024
+ w := &limitedBytesWriter{&buf, writeCap}
+ enc := NewEncoder(w)
+ var err error
+ var i int
+ const n = 4000
+ for i = 1; i <= n; i++ {
+ err = enc.Encode(&Passenger{
+ Name: []string{"Alice", "Bob"},
+ Weight: 5,
+ })
+ if err != nil {
+ break
+ }
+ }
+ if err == nil {
+ t.Error("expected an error")
+ }
+ if i == n {
+ t.Errorf("expected to fail before the end")
+ }
+ if buf.Len() != writeCap {
+ t.Errorf("buf.Len() = %d; want %d", buf.Len(), writeCap)
+ }
+}
+
func BenchmarkMarshal(b *testing.B) {
for i := 0; i < b.N; i++ {
Marshal(atomValue)
diff --git a/libgo/go/encoding/xml/read.go b/libgo/go/encoding/xml/read.go
index c2168242091..0e6761d66ad 100644
--- a/libgo/go/encoding/xml/read.go
+++ b/libgo/go/encoding/xml/read.go
@@ -81,8 +81,8 @@ import (
// of the above rules and the struct has a field with tag ",any",
// unmarshal maps the sub-element to that struct field.
//
-// * A non-pointer anonymous struct field is handled as if the
-// fields of its value were part of the outer struct.
+// * An anonymous struct field is handled as if the fields of its
+// value were part of the outer struct.
//
// * A struct field with tag "-" is never unmarshalled into.
//
@@ -248,7 +248,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
}
return UnmarshalError(e)
}
- fv := sv.FieldByIndex(finfo.idx)
+ fv := finfo.value(sv)
if _, ok := fv.Interface().(Name); ok {
fv.Set(reflect.ValueOf(start.Name))
}
@@ -260,7 +260,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
finfo := &tinfo.fields[i]
switch finfo.flags & fMode {
case fAttr:
- strv := sv.FieldByIndex(finfo.idx)
+ strv := finfo.value(sv)
// Look for attribute.
for _, a := range start.Attr {
if a.Name.Local == finfo.name {
@@ -271,22 +271,22 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
case fCharData:
if !saveData.IsValid() {
- saveData = sv.FieldByIndex(finfo.idx)
+ saveData = finfo.value(sv)
}
case fComment:
if !saveComment.IsValid() {
- saveComment = sv.FieldByIndex(finfo.idx)
+ saveComment = finfo.value(sv)
}
case fAny:
if !saveAny.IsValid() {
- saveAny = sv.FieldByIndex(finfo.idx)
+ saveAny = finfo.value(sv)
}
case fInnerXml:
if !saveXML.IsValid() {
- saveXML = sv.FieldByIndex(finfo.idx)
+ saveXML = finfo.value(sv)
if p.saved == nil {
saveXMLIndex = 0
p.saved = new(bytes.Buffer)
@@ -461,7 +461,7 @@ Loop:
}
if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
// It's a perfect match, unmarshal the field.
- return true, p.unmarshal(sv.FieldByIndex(finfo.idx), start)
+ return true, p.unmarshal(finfo.value(sv), start)
}
if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
// It's a prefix for the field. Break and recurse
diff --git a/libgo/go/encoding/xml/typeinfo.go b/libgo/go/encoding/xml/typeinfo.go
index 8e2e4508b10..970d1701932 100644
--- a/libgo/go/encoding/xml/typeinfo.go
+++ b/libgo/go/encoding/xml/typeinfo.go
@@ -66,10 +66,14 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
// For embedded structs, embed its fields.
if f.Anonymous {
- if f.Type.Kind() != reflect.Struct {
+ t := f.Type
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+ if t.Kind() != reflect.Struct {
continue
}
- inner, err := getTypeInfo(f.Type)
+ inner, err := getTypeInfo(t)
if err != nil {
return nil, err
}
@@ -327,3 +331,22 @@ type TagPathError struct {
func (e *TagPathError) Error() string {
return fmt.Sprintf("%s field %q with tag %q conflicts with field %q with tag %q", e.Struct, e.Field1, e.Tag1, e.Field2, e.Tag2)
}
+
+// value returns v's field value corresponding to finfo.
+// It's equivalent to v.FieldByIndex(finfo.idx), but initializes
+// and dereferences pointers as necessary.
+func (finfo *fieldInfo) value(v reflect.Value) reflect.Value {
+ for i, x := range finfo.idx {
+ if i > 0 {
+ t := v.Type()
+ if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ }
+ }
+ v = v.Field(x)
+ }
+ return v
+}
diff --git a/libgo/go/encoding/xml/xml.go b/libgo/go/encoding/xml/xml.go
index 5066f5c0106..fbd2208e334 100644
--- a/libgo/go/encoding/xml/xml.go
+++ b/libgo/go/encoding/xml/xml.go
@@ -584,6 +584,7 @@ func (d *Decoder) RawToken() (Token, error) {
if inquote == 0 && b == '>' && depth == 0 {
break
}
+ HandleB:
d.buf.WriteByte(b)
switch {
case b == inquote:
@@ -599,7 +600,35 @@ func (d *Decoder) RawToken() (Token, error) {
depth--
case b == '<' && inquote == 0:
- depth++
+ // Look for <!-- to begin comment.
+ s := "!--"
+ for i := 0; i < len(s); i++ {
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if b != s[i] {
+ for j := 0; j < i; j++ {
+ d.buf.WriteByte(s[j])
+ }
+ depth++
+ goto HandleB
+ }
+ }
+
+ // Remove < that was written above.
+ d.buf.Truncate(d.buf.Len() - 1)
+
+ // Look for terminator.
+ var b0, b1 byte
+ for {
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if b0 == '-' && b1 == '-' && b == '>' {
+ break
+ }
+ b0, b1 = b1, b
+ }
}
}
return Directive(d.buf.Bytes()), nil
@@ -850,6 +879,8 @@ Input:
// Parsers are required to recognize lt, gt, amp, apos, and quot
// even if they have not been declared. That's all we allow.
var i int
+ var semicolon bool
+ var valid bool
for i = 0; i < len(d.tmp); i++ {
var ok bool
d.tmp[i], ok = d.getc()
@@ -861,6 +892,8 @@ Input:
}
c := d.tmp[i]
if c == ';' {
+ semicolon = true
+ valid = i > 0
break
}
if 'a' <= c && c <= 'z' ||
@@ -873,14 +906,25 @@ Input:
break
}
s := string(d.tmp[0:i])
- if i >= len(d.tmp) {
+ if !valid {
if !d.Strict {
b0, b1 = 0, 0
d.buf.WriteByte('&')
d.buf.Write(d.tmp[0:i])
+ if semicolon {
+ d.buf.WriteByte(';')
+ }
continue Input
}
- d.err = d.syntaxError("character entity expression &" + s + "... too long")
+ semi := ";"
+ if !semicolon {
+ semi = " (no semicolon)"
+ }
+ if i < len(d.tmp) {
+ d.err = d.syntaxError("invalid character entity &" + s + semi)
+ } else {
+ d.err = d.syntaxError("invalid character entity &" + s + "... too long")
+ }
return nil
}
var haveText bool
@@ -910,6 +954,7 @@ Input:
b0, b1 = 0, 0
d.buf.WriteByte('&')
d.buf.Write(d.tmp[0:i])
+ d.buf.WriteByte(';')
continue Input
}
d.err = d.syntaxError("invalid character entity &" + s + ";")
diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go
index 1d0696ce087..2ad4d4af5df 100644
--- a/libgo/go/encoding/xml/xml_test.go
+++ b/libgo/go/encoding/xml/xml_test.go
@@ -5,6 +5,7 @@
package xml
import (
+ "fmt"
"io"
"reflect"
"strings"
@@ -158,6 +159,39 @@ func TestRawToken(t *testing.T) {
testRawToken(t, d, rawTokens)
}
+const nonStrictInput = `
+<tag>non&entity</tag>
+<tag>&unknown;entity</tag>
+<tag>&#123</tag>
+<tag>&#zzz;</tag>
+`
+
+var nonStrictTokens = []Token{
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("non&entity"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("&unknown;entity"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("&#123"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("&#zzz;"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+}
+
+func TestNonStrictRawToken(t *testing.T) {
+ d := NewDecoder(strings.NewReader(nonStrictInput))
+ d.Strict = false
+ testRawToken(t, d, nonStrictTokens)
+}
+
type downCaser struct {
t *testing.T
r io.ByteReader
@@ -219,7 +253,18 @@ func testRawToken(t *testing.T, d *Decoder, rawTokens []Token) {
t.Fatalf("token %d: unexpected error: %s", i, err)
}
if !reflect.DeepEqual(have, want) {
- t.Errorf("token %d = %#v want %#v", i, have, want)
+ var shave, swant string
+ if _, ok := have.(CharData); ok {
+ shave = fmt.Sprintf("CharData(%q)", have)
+ } else {
+ shave = fmt.Sprintf("%#v", have)
+ }
+ if _, ok := want.(CharData); ok {
+ swant = fmt.Sprintf("CharData(%q)", want)
+ } else {
+ swant = fmt.Sprintf("%#v", want)
+ }
+ t.Errorf("token %d = %s, want %s", i, shave, swant)
}
}
}
@@ -531,8 +576,8 @@ var characterTests = []struct {
{"\xef\xbf\xbe<doc/>", "illegal character code U+FFFE"},
{"<?xml version=\"1.0\"?><doc>\r\n<hiya/>\x07<toots/></doc>", "illegal character code U+0007"},
{"<?xml version=\"1.0\"?><doc \x12='value'>what's up</doc>", "expected attribute name in element"},
- {"<doc>&\x01;</doc>", "invalid character entity &;"},
- {"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity &;"},
+ {"<doc>&\x01;</doc>", "invalid character entity & (no semicolon)"},
+ {"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity & (no semicolon)"},
}
func TestDisallowedCharacters(t *testing.T) {
@@ -576,3 +621,36 @@ func TestProcInstEncoding(t *testing.T) {
}
}
}
+
+// Ensure that directives with comments include the complete
+// text of any nested directives.
+
+var directivesWithCommentsInput = `
+<!DOCTYPE [<!-- a comment --><!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]>
+<!DOCTYPE [<!ENTITY go "Golang"><!-- a comment-->]>
+<!DOCTYPE <!-> <!> <!----> <!-->--> <!--->--> [<!ENTITY go "Golang"><!-- a comment-->]>
+`
+
+var directivesWithCommentsTokens = []Token{
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`),
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY go "Golang">]`),
+ CharData("\n"),
+ Directive(`DOCTYPE <!-> <!> [<!ENTITY go "Golang">]`),
+ CharData("\n"),
+}
+
+func TestDirectivesWithComments(t *testing.T) {
+ d := NewDecoder(strings.NewReader(directivesWithCommentsInput))
+
+ for i, want := range directivesWithCommentsTokens {
+ have, err := d.Token()
+ if err != nil {
+ t.Fatalf("token %d: unexpected error: %s", i, err)
+ }
+ if !reflect.DeepEqual(have, want) {
+ t.Errorf("token %d = %#v want %#v", i, have, want)
+ }
+ }
+}
diff --git a/libgo/go/exp/html/atom/atom.go b/libgo/go/exp/html/atom/atom.go
new file mode 100644
index 00000000000..2dbd0fbf7f5
--- /dev/null
+++ b/libgo/go/exp/html/atom/atom.go
@@ -0,0 +1,81 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package atom provides integer codes (also known as atoms) for a fixed set of
+// frequently occurring HTML strings: tag names and attribute keys such as "p"
+// and "id".
+//
+// Sharing an atom's name between all elements with the same tag can result in
+// fewer string allocations when tokenizing and parsing HTML. Integer
+// comparisons are also generally faster than string comparisons.
+//
+// The value of an atom's particular code is not guaranteed to stay the same
+// between versions of this package. Neither is any ordering guaranteed:
+// whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to
+// be dense. The only guarantees are that e.g. looking up "div" will yield
+// atom.Div, calling atom.Div.String will return "div", and atom.Div != 0.
+//
+// TODO(rsc): When this package moves out of exp we need to freeze atom values
+// across releases.
+package atom
+
+// Atom is an integer code for a string. The zero value maps to "".
+type Atom uint32
+
+// String returns the atom's name.
+func (a Atom) String() string {
+ start := uint32(a >> 8)
+ n := uint32(a & 0xff)
+ if start+n > uint32(len(atomText)) {
+ return ""
+ }
+ return atomText[start : start+n]
+}
+
+func (a Atom) string() string {
+ return atomText[a>>8 : a>>8+a&0xff]
+}
+
+// fnv computes the FNV hash with an arbitrary starting value h.
+func fnv(h uint32, s []byte) uint32 {
+ for i := range s {
+ h ^= uint32(s[i])
+ h *= 16777619
+ }
+ return h
+}
+
+func match(s string, t []byte) bool {
+ for i, c := range t {
+ if s[i] != c {
+ return false
+ }
+ }
+ return true
+}
+
+// Lookup returns the atom whose name is s. It returns zero if there is no
+// such atom. The lookup is case sensitive.
+func Lookup(s []byte) Atom {
+ if len(s) == 0 || len(s) > maxAtomLen {
+ return 0
+ }
+ h := fnv(hash0, s)
+ if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
+ return a
+ }
+ if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
+ return a
+ }
+ return 0
+}
+
+// String returns a string whose contents are equal to s. In that sense, it is
+// equivalent to string(s) but may be more efficient.
+func String(s []byte) string {
+ if a := Lookup(s); a != 0 {
+ return a.String()
+ }
+ return string(s)
+}
diff --git a/libgo/go/exp/html/atom/atom_test.go b/libgo/go/exp/html/atom/atom_test.go
new file mode 100644
index 00000000000..6e33704dd5e
--- /dev/null
+++ b/libgo/go/exp/html/atom/atom_test.go
@@ -0,0 +1,109 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package atom
+
+import (
+ "sort"
+ "testing"
+)
+
+func TestKnown(t *testing.T) {
+ for _, s := range testAtomList {
+ if atom := Lookup([]byte(s)); atom.String() != s {
+ t.Errorf("Lookup(%q) = %#x (%q)", s, uint32(atom), atom.String())
+ }
+ }
+}
+
+func TestHits(t *testing.T) {
+ for _, a := range table {
+ if a == 0 {
+ continue
+ }
+ got := Lookup([]byte(a.String()))
+ if got != a {
+ t.Errorf("Lookup(%q) = %#x, want %#x", a.String(), uint32(got), uint32(a))
+ }
+ }
+}
+
+func TestMisses(t *testing.T) {
+ testCases := []string{
+ "",
+ "\x00",
+ "\xff",
+ "A",
+ "DIV",
+ "Div",
+ "dIV",
+ "aa",
+ "a\x00",
+ "ab",
+ "abb",
+ "abbr0",
+ "abbr ",
+ " abbr",
+ " a",
+ "acceptcharset",
+ "acceptCharset",
+ "accept_charset",
+ "h0",
+ "h1h2",
+ "h7",
+ "onClick",
+ "λ",
+ // The following string has the same hash (0xa1d7fab7) as "onmouseover".
+ "\x00\x00\x00\x00\x00\x50\x18\xae\x38\xd0\xb7",
+ }
+ for _, tc := range testCases {
+ got := Lookup([]byte(tc))
+ if got != 0 {
+ t.Errorf("Lookup(%q): got %d, want 0", tc, got)
+ }
+ }
+}
+
+func TestForeignObject(t *testing.T) {
+ const (
+ afo = Foreignobject
+ afO = ForeignObject
+ sfo = "foreignobject"
+ sfO = "foreignObject"
+ )
+ if got := Lookup([]byte(sfo)); got != afo {
+ t.Errorf("Lookup(%q): got %#v, want %#v", sfo, got, afo)
+ }
+ if got := Lookup([]byte(sfO)); got != afO {
+ t.Errorf("Lookup(%q): got %#v, want %#v", sfO, got, afO)
+ }
+ if got := afo.String(); got != sfo {
+ t.Errorf("Atom(%#v).String(): got %q, want %q", afo, got, sfo)
+ }
+ if got := afO.String(); got != sfO {
+ t.Errorf("Atom(%#v).String(): got %q, want %q", afO, got, sfO)
+ }
+}
+
+func BenchmarkLookup(b *testing.B) {
+ sortedTable := make([]string, 0, len(table))
+ for _, a := range table {
+ if a != 0 {
+ sortedTable = append(sortedTable, a.String())
+ }
+ }
+ sort.Strings(sortedTable)
+
+ x := make([][]byte, 1000)
+ for i := range x {
+ x[i] = []byte(sortedTable[i%len(sortedTable)])
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ for _, s := range x {
+ Lookup(s)
+ }
+ }
+}
diff --git a/libgo/go/exp/html/atom/gen.go b/libgo/go/exp/html/atom/gen.go
new file mode 100644
index 00000000000..9958a718842
--- /dev/null
+++ b/libgo/go/exp/html/atom/gen.go
@@ -0,0 +1,636 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+// This program generates table.go and table_test.go.
+// Invoke as
+//
+// go run gen.go |gofmt >table.go
+// go run gen.go -test |gofmt >table_test.go
+
+import (
+ "flag"
+ "fmt"
+ "math/rand"
+ "os"
+ "sort"
+ "strings"
+)
+
+// identifier converts s to a Go exported identifier.
+// It converts "div" to "Div" and "accept-charset" to "AcceptCharset".
+func identifier(s string) string {
+ b := make([]byte, 0, len(s))
+ cap := true
+ for _, c := range s {
+ if c == '-' {
+ cap = true
+ continue
+ }
+ if cap && 'a' <= c && c <= 'z' {
+ c -= 'a' - 'A'
+ }
+ cap = false
+ b = append(b, byte(c))
+ }
+ return string(b)
+}
+
+var test = flag.Bool("test", false, "generate table_test.go")
+
+func main() {
+ flag.Parse()
+
+ var all []string
+ all = append(all, elements...)
+ all = append(all, attributes...)
+ all = append(all, eventHandlers...)
+ all = append(all, extra...)
+ sort.Strings(all)
+
+ if *test {
+ fmt.Printf("// generated by go run gen.go -test; DO NOT EDIT\n\n")
+ fmt.Printf("package atom\n\n")
+ fmt.Printf("var testAtomList = []string{\n")
+ for _, s := range all {
+ fmt.Printf("\t%q,\n", s)
+ }
+ fmt.Printf("}\n")
+ return
+ }
+
+ // uniq - lists have dups
+ // compute max len too
+ maxLen := 0
+ w := 0
+ for _, s := range all {
+ if w == 0 || all[w-1] != s {
+ if maxLen < len(s) {
+ maxLen = len(s)
+ }
+ all[w] = s
+ w++
+ }
+ }
+ all = all[:w]
+
+ // Find hash that minimizes table size.
+ var best *table
+ for i := 0; i < 1000000; i++ {
+ if best != nil && 1<<(best.k-1) < len(all) {
+ break
+ }
+ h := rand.Uint32()
+ for k := uint(0); k <= 16; k++ {
+ if best != nil && k >= best.k {
+ break
+ }
+ var t table
+ if t.init(h, k, all) {
+ best = &t
+ break
+ }
+ }
+ }
+ if best == nil {
+ fmt.Fprintf(os.Stderr, "failed to construct string table\n")
+ os.Exit(1)
+ }
+
+ // Lay out strings, using overlaps when possible.
+ layout := append([]string{}, all...)
+
+ // Remove strings that are substrings of other strings
+ for changed := true; changed; {
+ changed = false
+ for i, s := range layout {
+ if s == "" {
+ continue
+ }
+ for j, t := range layout {
+ if i != j && t != "" && strings.Contains(s, t) {
+ changed = true
+ layout[j] = ""
+ }
+ }
+ }
+ }
+
+ // Join strings where one suffix matches another prefix.
+ for {
+ // Find best i, j, k such that layout[i][len-k:] == layout[j][:k],
+ // maximizing overlap length k.
+ besti := -1
+ bestj := -1
+ bestk := 0
+ for i, s := range layout {
+ if s == "" {
+ continue
+ }
+ for j, t := range layout {
+ if i == j {
+ continue
+ }
+ for k := bestk + 1; k <= len(s) && k <= len(t); k++ {
+ if s[len(s)-k:] == t[:k] {
+ besti = i
+ bestj = j
+ bestk = k
+ }
+ }
+ }
+ }
+ if bestk > 0 {
+ layout[besti] += layout[bestj][bestk:]
+ layout[bestj] = ""
+ continue
+ }
+ break
+ }
+
+ text := strings.Join(layout, "")
+
+ atom := map[string]uint32{}
+ for _, s := range all {
+ off := strings.Index(text, s)
+ if off < 0 {
+ panic("lost string " + s)
+ }
+ atom[s] = uint32(off<<8 | len(s))
+ }
+
+ // Generate the Go code.
+ fmt.Printf("// generated by go run gen.go; DO NOT EDIT\n\n")
+ fmt.Printf("package atom\n\nconst (\n")
+ for _, s := range all {
+ fmt.Printf("\t%s Atom = %#x\n", identifier(s), atom[s])
+ }
+ fmt.Printf(")\n\n")
+
+ fmt.Printf("const hash0 = %#x\n\n", best.h0)
+ fmt.Printf("const maxAtomLen = %d\n\n", maxLen)
+
+ fmt.Printf("var table = [1<<%d]Atom{\n", best.k)
+ for i, s := range best.tab {
+ if s == "" {
+ continue
+ }
+ fmt.Printf("\t%#x: %#x, // %s\n", i, atom[s], s)
+ }
+ fmt.Printf("}\n")
+ datasize := (1 << best.k) * 4
+
+ fmt.Printf("const atomText =\n")
+ textsize := len(text)
+ for len(text) > 60 {
+ fmt.Printf("\t%q +\n", text[:60])
+ text = text[60:]
+ }
+ fmt.Printf("\t%q\n\n", text)
+
+ fmt.Fprintf(os.Stderr, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize)
+}
+
+type byLen []string
+
+func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) }
+func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x byLen) Len() int { return len(x) }
+
+// fnv computes the FNV hash with an arbitrary starting value h.
+func fnv(h uint32, s string) uint32 {
+ for i := 0; i < len(s); i++ {
+ h ^= uint32(s[i])
+ h *= 16777619
+ }
+ return h
+}
+
+// A table represents an attempt at constructing the lookup table.
+// The lookup table uses cuckoo hashing, meaning that each string
+// can be found in one of two positions.
+type table struct {
+ h0 uint32
+ k uint
+ mask uint32
+ tab []string
+}
+
+// hash returns the two hashes for s.
+func (t *table) hash(s string) (h1, h2 uint32) {
+ h := fnv(t.h0, s)
+ h1 = h & t.mask
+ h2 = (h >> 16) & t.mask
+ return
+}
+
+// init initializes the table with the given parameters.
+// h0 is the initial hash value,
+// k is the number of bits of hash value to use, and
+// x is the list of strings to store in the table.
+// init returns false if the table cannot be constructed.
+func (t *table) init(h0 uint32, k uint, x []string) bool {
+ t.h0 = h0
+ t.k = k
+ t.tab = make([]string, 1<<k)
+ t.mask = 1<<k - 1
+ for _, s := range x {
+ if !t.insert(s) {
+ return false
+ }
+ }
+ return true
+}
+
+// insert inserts s in the table.
+func (t *table) insert(s string) bool {
+ h1, h2 := t.hash(s)
+ if t.tab[h1] == "" {
+ t.tab[h1] = s
+ return true
+ }
+ if t.tab[h2] == "" {
+ t.tab[h2] = s
+ return true
+ }
+ if t.push(h1, 0) {
+ t.tab[h1] = s
+ return true
+ }
+ if t.push(h2, 0) {
+ t.tab[h2] = s
+ return true
+ }
+ return false
+}
+
+// push attempts to push aside the entry in slot i.
+func (t *table) push(i uint32, depth int) bool {
+ if depth > len(t.tab) {
+ return false
+ }
+ s := t.tab[i]
+ h1, h2 := t.hash(s)
+ j := h1 + h2 - i
+ if t.tab[j] != "" && !t.push(j, depth+1) {
+ return false
+ }
+ t.tab[j] = s
+ return true
+}
+
+// The lists of element names and attribute keys were taken from
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/section-index.html
+// as of the "HTML Living Standard - Last Updated 30 May 2012" version.
+
+var elements = []string{
+ "a",
+ "abbr",
+ "address",
+ "area",
+ "article",
+ "aside",
+ "audio",
+ "b",
+ "base",
+ "bdi",
+ "bdo",
+ "blockquote",
+ "body",
+ "br",
+ "button",
+ "canvas",
+ "caption",
+ "cite",
+ "code",
+ "col",
+ "colgroup",
+ "command",
+ "data",
+ "datalist",
+ "dd",
+ "del",
+ "details",
+ "dfn",
+ "dialog",
+ "div",
+ "dl",
+ "dt",
+ "em",
+ "embed",
+ "fieldset",
+ "figcaption",
+ "figure",
+ "footer",
+ "form",
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6",
+ "head",
+ "header",
+ "hgroup",
+ "hr",
+ "html",
+ "i",
+ "iframe",
+ "img",
+ "input",
+ "ins",
+ "kbd",
+ "keygen",
+ "label",
+ "legend",
+ "li",
+ "link",
+ "map",
+ "mark",
+ "menu",
+ "meta",
+ "meter",
+ "nav",
+ "noscript",
+ "object",
+ "ol",
+ "optgroup",
+ "option",
+ "output",
+ "p",
+ "param",
+ "pre",
+ "progress",
+ "q",
+ "rp",
+ "rt",
+ "ruby",
+ "s",
+ "samp",
+ "script",
+ "section",
+ "select",
+ "small",
+ "source",
+ "span",
+ "strong",
+ "style",
+ "sub",
+ "summary",
+ "sup",
+ "table",
+ "tbody",
+ "td",
+ "textarea",
+ "tfoot",
+ "th",
+ "thead",
+ "time",
+ "title",
+ "tr",
+ "track",
+ "u",
+ "ul",
+ "var",
+ "video",
+ "wbr",
+}
+
+var attributes = []string{
+ "accept",
+ "accept-charset",
+ "accesskey",
+ "action",
+ "alt",
+ "async",
+ "autocomplete",
+ "autofocus",
+ "autoplay",
+ "border",
+ "challenge",
+ "charset",
+ "checked",
+ "cite",
+ "class",
+ "cols",
+ "colspan",
+ "command",
+ "content",
+ "contenteditable",
+ "contextmenu",
+ "controls",
+ "coords",
+ "crossorigin",
+ "data",
+ "datetime",
+ "default",
+ "defer",
+ "dir",
+ "dirname",
+ "disabled",
+ "download",
+ "draggable",
+ "dropzone",
+ "enctype",
+ "for",
+ "form",
+ "formaction",
+ "formenctype",
+ "formmethod",
+ "formnovalidate",
+ "formtarget",
+ "headers",
+ "height",
+ "hidden",
+ "high",
+ "href",
+ "hreflang",
+ "http-equiv",
+ "icon",
+ "id",
+ "inert",
+ "ismap",
+ "itemid",
+ "itemprop",
+ "itemref",
+ "itemscope",
+ "itemtype",
+ "keytype",
+ "kind",
+ "label",
+ "lang",
+ "list",
+ "loop",
+ "low",
+ "manifest",
+ "max",
+ "maxlength",
+ "media",
+ "mediagroup",
+ "method",
+ "min",
+ "multiple",
+ "muted",
+ "name",
+ "novalidate",
+ "open",
+ "optimum",
+ "pattern",
+ "ping",
+ "placeholder",
+ "poster",
+ "preload",
+ "radiogroup",
+ "readonly",
+ "rel",
+ "required",
+ "reversed",
+ "rows",
+ "rowspan",
+ "sandbox",
+ "spellcheck",
+ "scope",
+ "scoped",
+ "seamless",
+ "selected",
+ "shape",
+ "size",
+ "sizes",
+ "span",
+ "src",
+ "srcdoc",
+ "srclang",
+ "start",
+ "step",
+ "style",
+ "tabindex",
+ "target",
+ "title",
+ "translate",
+ "type",
+ "typemustmatch",
+ "usemap",
+ "value",
+ "width",
+ "wrap",
+}
+
+var eventHandlers = []string{
+ "onabort",
+ "onafterprint",
+ "onbeforeprint",
+ "onbeforeunload",
+ "onblur",
+ "oncancel",
+ "oncanplay",
+ "oncanplaythrough",
+ "onchange",
+ "onclick",
+ "onclose",
+ "oncontextmenu",
+ "oncuechange",
+ "ondblclick",
+ "ondrag",
+ "ondragend",
+ "ondragenter",
+ "ondragleave",
+ "ondragover",
+ "ondragstart",
+ "ondrop",
+ "ondurationchange",
+ "onemptied",
+ "onended",
+ "onerror",
+ "onfocus",
+ "onhashchange",
+ "oninput",
+ "oninvalid",
+ "onkeydown",
+ "onkeypress",
+ "onkeyup",
+ "onload",
+ "onloadeddata",
+ "onloadedmetadata",
+ "onloadstart",
+ "onmessage",
+ "onmousedown",
+ "onmousemove",
+ "onmouseout",
+ "onmouseover",
+ "onmouseup",
+ "onmousewheel",
+ "onoffline",
+ "ononline",
+ "onpagehide",
+ "onpageshow",
+ "onpause",
+ "onplay",
+ "onplaying",
+ "onpopstate",
+ "onprogress",
+ "onratechange",
+ "onreset",
+ "onresize",
+ "onscroll",
+ "onseeked",
+ "onseeking",
+ "onselect",
+ "onshow",
+ "onstalled",
+ "onstorage",
+ "onsubmit",
+ "onsuspend",
+ "ontimeupdate",
+ "onunload",
+ "onvolumechange",
+ "onwaiting",
+}
+
+// extra are ad-hoc values not covered by any of the lists above.
+var extra = []string{
+ "align",
+ "annotation",
+ "annotation-xml",
+ "applet",
+ "basefont",
+ "bgsound",
+ "big",
+ "blink",
+ "center",
+ "color",
+ "desc",
+ "face",
+ "font",
+ "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive.
+ "foreignobject",
+ "frame",
+ "frameset",
+ "image",
+ "isindex",
+ "listing",
+ "malignmark",
+ "marquee",
+ "math",
+ "mglyph",
+ "mi",
+ "mn",
+ "mo",
+ "ms",
+ "mtext",
+ "nobr",
+ "noembed",
+ "noframes",
+ "plaintext",
+ "prompt",
+ "public",
+ "spacer",
+ "strike",
+ "svg",
+ "system",
+ "tt",
+ "xmp",
+}
diff --git a/libgo/go/exp/html/atom/table.go b/libgo/go/exp/html/atom/table.go
new file mode 100644
index 00000000000..20b8b8a5903
--- /dev/null
+++ b/libgo/go/exp/html/atom/table.go
@@ -0,0 +1,694 @@
+// generated by go run gen.go; DO NOT EDIT
+
+package atom
+
+const (
+ A Atom = 0x1
+ Abbr Atom = 0x4
+ Accept Atom = 0x2106
+ AcceptCharset Atom = 0x210e
+ Accesskey Atom = 0x3309
+ Action Atom = 0x21b06
+ Address Atom = 0x5d507
+ Align Atom = 0x1105
+ Alt Atom = 0x4503
+ Annotation Atom = 0x18d0a
+ AnnotationXml Atom = 0x18d0e
+ Applet Atom = 0x2d106
+ Area Atom = 0x31804
+ Article Atom = 0x39907
+ Aside Atom = 0x4f05
+ Async Atom = 0x9305
+ Audio Atom = 0xaf05
+ Autocomplete Atom = 0xd50c
+ Autofocus Atom = 0xe109
+ Autoplay Atom = 0x10c08
+ B Atom = 0x101
+ Base Atom = 0x11404
+ Basefont Atom = 0x11408
+ Bdi Atom = 0x1a03
+ Bdo Atom = 0x12503
+ Bgsound Atom = 0x13807
+ Big Atom = 0x14403
+ Blink Atom = 0x14705
+ Blockquote Atom = 0x14c0a
+ Body Atom = 0x2f04
+ Border Atom = 0x15606
+ Br Atom = 0x202
+ Button Atom = 0x15c06
+ Canvas Atom = 0x4b06
+ Caption Atom = 0x1e007
+ Center Atom = 0x2df06
+ Challenge Atom = 0x23e09
+ Charset Atom = 0x2807
+ Checked Atom = 0x33f07
+ Cite Atom = 0x9704
+ Class Atom = 0x3d905
+ Code Atom = 0x16f04
+ Col Atom = 0x17603
+ Colgroup Atom = 0x17608
+ Color Atom = 0x18305
+ Cols Atom = 0x18804
+ Colspan Atom = 0x18807
+ Command Atom = 0x19b07
+ Content Atom = 0x42c07
+ Contenteditable Atom = 0x42c0f
+ Contextmenu Atom = 0x3480b
+ Controls Atom = 0x1ae08
+ Coords Atom = 0x1ba06
+ Crossorigin Atom = 0x1c40b
+ Data Atom = 0x44304
+ Datalist Atom = 0x44308
+ Datetime Atom = 0x25b08
+ Dd Atom = 0x28802
+ Default Atom = 0x5207
+ Defer Atom = 0x17105
+ Del Atom = 0x4d603
+ Desc Atom = 0x4804
+ Details Atom = 0x6507
+ Dfn Atom = 0x8303
+ Dialog Atom = 0x1b06
+ Dir Atom = 0x9d03
+ Dirname Atom = 0x9d07
+ Disabled Atom = 0x10008
+ Div Atom = 0x10703
+ Dl Atom = 0x13e02
+ Download Atom = 0x40908
+ Draggable Atom = 0x1a109
+ Dropzone Atom = 0x3a208
+ Dt Atom = 0x4e402
+ Em Atom = 0x7f02
+ Embed Atom = 0x7f05
+ Enctype Atom = 0x23007
+ Face Atom = 0x2dd04
+ Fieldset Atom = 0x1d508
+ Figcaption Atom = 0x1dd0a
+ Figure Atom = 0x1f106
+ Font Atom = 0x11804
+ Footer Atom = 0x5906
+ For Atom = 0x1fd03
+ ForeignObject Atom = 0x1fd0d
+ Foreignobject Atom = 0x20a0d
+ Form Atom = 0x21704
+ Formaction Atom = 0x2170a
+ Formenctype Atom = 0x22c0b
+ Formmethod Atom = 0x2470a
+ Formnovalidate Atom = 0x2510e
+ Formtarget Atom = 0x2660a
+ Frame Atom = 0x8705
+ Frameset Atom = 0x8708
+ H1 Atom = 0x13602
+ H2 Atom = 0x29602
+ H3 Atom = 0x2c502
+ H4 Atom = 0x30e02
+ H5 Atom = 0x4e602
+ H6 Atom = 0x27002
+ Head Atom = 0x2fa04
+ Header Atom = 0x2fa06
+ Headers Atom = 0x2fa07
+ Height Atom = 0x27206
+ Hgroup Atom = 0x27a06
+ Hidden Atom = 0x28606
+ High Atom = 0x29304
+ Hr Atom = 0x13102
+ Href Atom = 0x29804
+ Hreflang Atom = 0x29808
+ Html Atom = 0x27604
+ HttpEquiv Atom = 0x2a00a
+ I Atom = 0x601
+ Icon Atom = 0x42b04
+ Id Atom = 0x5102
+ Iframe Atom = 0x2b406
+ Image Atom = 0x2ba05
+ Img Atom = 0x2bf03
+ Inert Atom = 0x4c105
+ Input Atom = 0x3f605
+ Ins Atom = 0x1cd03
+ Isindex Atom = 0x2c707
+ Ismap Atom = 0x2ce05
+ Itemid Atom = 0x9806
+ Itemprop Atom = 0x57e08
+ Itemref Atom = 0x2d707
+ Itemscope Atom = 0x2e509
+ Itemtype Atom = 0x2ef08
+ Kbd Atom = 0x1903
+ Keygen Atom = 0x3906
+ Keytype Atom = 0x51207
+ Kind Atom = 0xfd04
+ Label Atom = 0xba05
+ Lang Atom = 0x29c04
+ Legend Atom = 0x1a806
+ Li Atom = 0x1202
+ Link Atom = 0x14804
+ List Atom = 0x44704
+ Listing Atom = 0x44707
+ Loop Atom = 0xbe04
+ Low Atom = 0x13f03
+ Malignmark Atom = 0x100a
+ Manifest Atom = 0x5b608
+ Map Atom = 0x2d003
+ Mark Atom = 0x1604
+ Marquee Atom = 0x5f207
+ Math Atom = 0x2f704
+ Max Atom = 0x30603
+ Maxlength Atom = 0x30609
+ Media Atom = 0xa205
+ Mediagroup Atom = 0xa20a
+ Menu Atom = 0x34f04
+ Meta Atom = 0x45604
+ Meter Atom = 0x26105
+ Method Atom = 0x24b06
+ Mglyph Atom = 0x2c006
+ Mi Atom = 0x9b02
+ Min Atom = 0x31003
+ Mn Atom = 0x25402
+ Mo Atom = 0x47a02
+ Ms Atom = 0x2e802
+ Mtext Atom = 0x31305
+ Multiple Atom = 0x32108
+ Muted Atom = 0x32905
+ Name Atom = 0xa004
+ Nav Atom = 0x3e03
+ Nobr Atom = 0x7404
+ Noembed Atom = 0x7d07
+ Noframes Atom = 0x8508
+ Noscript Atom = 0x28b08
+ Novalidate Atom = 0x2550a
+ Object Atom = 0x21106
+ Ol Atom = 0xcd02
+ Onabort Atom = 0x16007
+ Onafterprint Atom = 0x1e50c
+ Onbeforeprint Atom = 0x21f0d
+ Onbeforeunload Atom = 0x5c90e
+ Onblur Atom = 0x3e206
+ Oncancel Atom = 0xb308
+ Oncanplay Atom = 0x12709
+ Oncanplaythrough Atom = 0x12710
+ Onchange Atom = 0x3b808
+ Onclick Atom = 0x2ad07
+ Onclose Atom = 0x32e07
+ Oncontextmenu Atom = 0x3460d
+ Oncuechange Atom = 0x3530b
+ Ondblclick Atom = 0x35e0a
+ Ondrag Atom = 0x36806
+ Ondragend Atom = 0x36809
+ Ondragenter Atom = 0x3710b
+ Ondragleave Atom = 0x37c0b
+ Ondragover Atom = 0x3870a
+ Ondragstart Atom = 0x3910b
+ Ondrop Atom = 0x3a006
+ Ondurationchange Atom = 0x3b010
+ Onemptied Atom = 0x3a709
+ Onended Atom = 0x3c007
+ Onerror Atom = 0x3c707
+ Onfocus Atom = 0x3ce07
+ Onhashchange Atom = 0x3e80c
+ Oninput Atom = 0x3f407
+ Oninvalid Atom = 0x3fb09
+ Onkeydown Atom = 0x40409
+ Onkeypress Atom = 0x4110a
+ Onkeyup Atom = 0x42107
+ Onload Atom = 0x43b06
+ Onloadeddata Atom = 0x43b0c
+ Onloadedmetadata Atom = 0x44e10
+ Onloadstart Atom = 0x4640b
+ Onmessage Atom = 0x46f09
+ Onmousedown Atom = 0x4780b
+ Onmousemove Atom = 0x4830b
+ Onmouseout Atom = 0x48e0a
+ Onmouseover Atom = 0x49b0b
+ Onmouseup Atom = 0x4a609
+ Onmousewheel Atom = 0x4af0c
+ Onoffline Atom = 0x4bb09
+ Ononline Atom = 0x4c608
+ Onpagehide Atom = 0x4ce0a
+ Onpageshow Atom = 0x4d90a
+ Onpause Atom = 0x4e807
+ Onplay Atom = 0x4f206
+ Onplaying Atom = 0x4f209
+ Onpopstate Atom = 0x4fb0a
+ Onprogress Atom = 0x5050a
+ Onratechange Atom = 0x5190c
+ Onreset Atom = 0x52507
+ Onresize Atom = 0x52c08
+ Onscroll Atom = 0x53a08
+ Onseeked Atom = 0x54208
+ Onseeking Atom = 0x54a09
+ Onselect Atom = 0x55308
+ Onshow Atom = 0x55d06
+ Onstalled Atom = 0x56609
+ Onstorage Atom = 0x56f09
+ Onsubmit Atom = 0x57808
+ Onsuspend Atom = 0x58809
+ Ontimeupdate Atom = 0x1190c
+ Onunload Atom = 0x59108
+ Onvolumechange Atom = 0x5990e
+ Onwaiting Atom = 0x5a709
+ Open Atom = 0x58404
+ Optgroup Atom = 0xc008
+ Optimum Atom = 0x5b007
+ Option Atom = 0x5c506
+ Output Atom = 0x49506
+ P Atom = 0xc01
+ Param Atom = 0xc05
+ Pattern Atom = 0x6e07
+ Ping Atom = 0xab04
+ Placeholder Atom = 0xc70b
+ Plaintext Atom = 0xf109
+ Poster Atom = 0x17d06
+ Pre Atom = 0x27f03
+ Preload Atom = 0x27f07
+ Progress Atom = 0x50708
+ Prompt Atom = 0x5bf06
+ Public Atom = 0x42706
+ Q Atom = 0x15101
+ Radiogroup Atom = 0x30a
+ Readonly Atom = 0x31908
+ Rel Atom = 0x28003
+ Required Atom = 0x1f508
+ Reversed Atom = 0x5e08
+ Rows Atom = 0x7704
+ Rowspan Atom = 0x7707
+ Rp Atom = 0x1eb02
+ Rt Atom = 0x16502
+ Ruby Atom = 0xd104
+ S Atom = 0x2c01
+ Samp Atom = 0x6b04
+ Sandbox Atom = 0xe907
+ Scope Atom = 0x2e905
+ Scoped Atom = 0x2e906
+ Script Atom = 0x28d06
+ Seamless Atom = 0x33308
+ Section Atom = 0x3dd07
+ Select Atom = 0x55506
+ Selected Atom = 0x55508
+ Shape Atom = 0x1b505
+ Size Atom = 0x53004
+ Sizes Atom = 0x53005
+ Small Atom = 0x1bf05
+ Source Atom = 0x1cf06
+ Spacer Atom = 0x30006
+ Span Atom = 0x7a04
+ Spellcheck Atom = 0x33a0a
+ Src Atom = 0x3d403
+ Srcdoc Atom = 0x3d406
+ Srclang Atom = 0x41a07
+ Start Atom = 0x39705
+ Step Atom = 0x5bc04
+ Strike Atom = 0x50e06
+ Strong Atom = 0x53406
+ Style Atom = 0x5db05
+ Sub Atom = 0x57a03
+ Summary Atom = 0x5e007
+ Sup Atom = 0x5e703
+ Svg Atom = 0x5ea03
+ System Atom = 0x5ed06
+ Tabindex Atom = 0x45c08
+ Table Atom = 0x43605
+ Target Atom = 0x26a06
+ Tbody Atom = 0x2e05
+ Td Atom = 0x4702
+ Textarea Atom = 0x31408
+ Tfoot Atom = 0x5805
+ Th Atom = 0x13002
+ Thead Atom = 0x2f905
+ Time Atom = 0x11b04
+ Title Atom = 0x8e05
+ Tr Atom = 0xf902
+ Track Atom = 0xf905
+ Translate Atom = 0x16609
+ Tt Atom = 0x7002
+ Type Atom = 0x23304
+ Typemustmatch Atom = 0x2330d
+ U Atom = 0xb01
+ Ul Atom = 0x5602
+ Usemap Atom = 0x4ec06
+ Value Atom = 0x4005
+ Var Atom = 0x10903
+ Video Atom = 0x2a905
+ Wbr Atom = 0x14103
+ Width Atom = 0x4e205
+ Wrap Atom = 0x56204
+ Xmp Atom = 0xef03
+)
+
+const hash0 = 0xc17da63e
+
+const maxAtomLen = 16
+
+var table = [1 << 9]Atom{
+ 0x1: 0x4830b, // onmousemove
+ 0x2: 0x5a709, // onwaiting
+ 0x4: 0x5bf06, // prompt
+ 0x7: 0x5b007, // optimum
+ 0x8: 0x1604, // mark
+ 0xa: 0x2d707, // itemref
+ 0xb: 0x4d90a, // onpageshow
+ 0xc: 0x55506, // select
+ 0xd: 0x1a109, // draggable
+ 0xe: 0x3e03, // nav
+ 0xf: 0x19b07, // command
+ 0x11: 0xb01, // u
+ 0x14: 0x2fa07, // headers
+ 0x15: 0x44308, // datalist
+ 0x17: 0x6b04, // samp
+ 0x1a: 0x40409, // onkeydown
+ 0x1b: 0x53a08, // onscroll
+ 0x1c: 0x17603, // col
+ 0x20: 0x57e08, // itemprop
+ 0x21: 0x2a00a, // http-equiv
+ 0x22: 0x5e703, // sup
+ 0x24: 0x1f508, // required
+ 0x2b: 0x27f07, // preload
+ 0x2c: 0x21f0d, // onbeforeprint
+ 0x2d: 0x3710b, // ondragenter
+ 0x2e: 0x4e402, // dt
+ 0x2f: 0x57808, // onsubmit
+ 0x30: 0x13102, // hr
+ 0x31: 0x3460d, // oncontextmenu
+ 0x33: 0x2ba05, // image
+ 0x34: 0x4e807, // onpause
+ 0x35: 0x27a06, // hgroup
+ 0x36: 0xab04, // ping
+ 0x37: 0x55308, // onselect
+ 0x3a: 0x10703, // div
+ 0x40: 0x9b02, // mi
+ 0x41: 0x33308, // seamless
+ 0x42: 0x2807, // charset
+ 0x43: 0x5102, // id
+ 0x44: 0x4fb0a, // onpopstate
+ 0x45: 0x4d603, // del
+ 0x46: 0x5f207, // marquee
+ 0x47: 0x3309, // accesskey
+ 0x49: 0x5906, // footer
+ 0x4a: 0x2d106, // applet
+ 0x4b: 0x2ce05, // ismap
+ 0x51: 0x34f04, // menu
+ 0x52: 0x2f04, // body
+ 0x55: 0x8708, // frameset
+ 0x56: 0x52507, // onreset
+ 0x57: 0x14705, // blink
+ 0x58: 0x8e05, // title
+ 0x59: 0x39907, // article
+ 0x5b: 0x13002, // th
+ 0x5d: 0x15101, // q
+ 0x5e: 0x58404, // open
+ 0x5f: 0x31804, // area
+ 0x61: 0x43b06, // onload
+ 0x62: 0x3f605, // input
+ 0x63: 0x11404, // base
+ 0x64: 0x18807, // colspan
+ 0x65: 0x51207, // keytype
+ 0x66: 0x13e02, // dl
+ 0x68: 0x1d508, // fieldset
+ 0x6a: 0x31003, // min
+ 0x6b: 0x10903, // var
+ 0x6f: 0x2fa06, // header
+ 0x70: 0x16502, // rt
+ 0x71: 0x17608, // colgroup
+ 0x72: 0x25402, // mn
+ 0x74: 0x16007, // onabort
+ 0x75: 0x3906, // keygen
+ 0x76: 0x4bb09, // onoffline
+ 0x77: 0x23e09, // challenge
+ 0x78: 0x2d003, // map
+ 0x7a: 0x30e02, // h4
+ 0x7b: 0x3c707, // onerror
+ 0x7c: 0x30609, // maxlength
+ 0x7d: 0x31305, // mtext
+ 0x7e: 0x5805, // tfoot
+ 0x7f: 0x11804, // font
+ 0x80: 0x100a, // malignmark
+ 0x81: 0x45604, // meta
+ 0x82: 0x9305, // async
+ 0x83: 0x2c502, // h3
+ 0x84: 0x28802, // dd
+ 0x85: 0x29804, // href
+ 0x86: 0xa20a, // mediagroup
+ 0x87: 0x1ba06, // coords
+ 0x88: 0x41a07, // srclang
+ 0x89: 0x35e0a, // ondblclick
+ 0x8a: 0x4005, // value
+ 0x8c: 0xb308, // oncancel
+ 0x8e: 0x33a0a, // spellcheck
+ 0x8f: 0x8705, // frame
+ 0x91: 0x14403, // big
+ 0x94: 0x21b06, // action
+ 0x95: 0x9d03, // dir
+ 0x97: 0x31908, // readonly
+ 0x99: 0x43605, // table
+ 0x9a: 0x5e007, // summary
+ 0x9b: 0x14103, // wbr
+ 0x9c: 0x30a, // radiogroup
+ 0x9d: 0xa004, // name
+ 0x9f: 0x5ed06, // system
+ 0xa1: 0x18305, // color
+ 0xa2: 0x4b06, // canvas
+ 0xa3: 0x27604, // html
+ 0xa5: 0x54a09, // onseeking
+ 0xac: 0x1b505, // shape
+ 0xad: 0x28003, // rel
+ 0xae: 0x12710, // oncanplaythrough
+ 0xaf: 0x3870a, // ondragover
+ 0xb1: 0x1fd0d, // foreignObject
+ 0xb3: 0x7704, // rows
+ 0xb6: 0x44707, // listing
+ 0xb7: 0x49506, // output
+ 0xb9: 0x3480b, // contextmenu
+ 0xbb: 0x13f03, // low
+ 0xbc: 0x1eb02, // rp
+ 0xbd: 0x58809, // onsuspend
+ 0xbe: 0x15c06, // button
+ 0xbf: 0x4804, // desc
+ 0xc1: 0x3dd07, // section
+ 0xc2: 0x5050a, // onprogress
+ 0xc3: 0x56f09, // onstorage
+ 0xc4: 0x2f704, // math
+ 0xc5: 0x4f206, // onplay
+ 0xc7: 0x5602, // ul
+ 0xc8: 0x6e07, // pattern
+ 0xc9: 0x4af0c, // onmousewheel
+ 0xca: 0x36809, // ondragend
+ 0xcb: 0xd104, // ruby
+ 0xcc: 0xc01, // p
+ 0xcd: 0x32e07, // onclose
+ 0xce: 0x26105, // meter
+ 0xcf: 0x13807, // bgsound
+ 0xd2: 0x27206, // height
+ 0xd4: 0x101, // b
+ 0xd5: 0x2ef08, // itemtype
+ 0xd8: 0x1e007, // caption
+ 0xd9: 0x10008, // disabled
+ 0xdc: 0x5ea03, // svg
+ 0xdd: 0x1bf05, // small
+ 0xde: 0x44304, // data
+ 0xe0: 0x4c608, // ononline
+ 0xe1: 0x2c006, // mglyph
+ 0xe3: 0x7f05, // embed
+ 0xe4: 0xf902, // tr
+ 0xe5: 0x4640b, // onloadstart
+ 0xe7: 0x3b010, // ondurationchange
+ 0xed: 0x12503, // bdo
+ 0xee: 0x4702, // td
+ 0xef: 0x4f05, // aside
+ 0xf0: 0x29602, // h2
+ 0xf1: 0x50708, // progress
+ 0xf2: 0x14c0a, // blockquote
+ 0xf4: 0xba05, // label
+ 0xf5: 0x601, // i
+ 0xf7: 0x7707, // rowspan
+ 0xfb: 0x4f209, // onplaying
+ 0xfd: 0x2bf03, // img
+ 0xfe: 0xc008, // optgroup
+ 0xff: 0x42c07, // content
+ 0x101: 0x5190c, // onratechange
+ 0x103: 0x3e80c, // onhashchange
+ 0x104: 0x6507, // details
+ 0x106: 0x40908, // download
+ 0x109: 0xe907, // sandbox
+ 0x10b: 0x42c0f, // contenteditable
+ 0x10d: 0x37c0b, // ondragleave
+ 0x10e: 0x2106, // accept
+ 0x10f: 0x55508, // selected
+ 0x112: 0x2170a, // formaction
+ 0x113: 0x2df06, // center
+ 0x115: 0x44e10, // onloadedmetadata
+ 0x116: 0x14804, // link
+ 0x117: 0x11b04, // time
+ 0x118: 0x1c40b, // crossorigin
+ 0x119: 0x3ce07, // onfocus
+ 0x11a: 0x56204, // wrap
+ 0x11b: 0x42b04, // icon
+ 0x11d: 0x2a905, // video
+ 0x11e: 0x3d905, // class
+ 0x121: 0x5990e, // onvolumechange
+ 0x122: 0x3e206, // onblur
+ 0x123: 0x2e509, // itemscope
+ 0x124: 0x5db05, // style
+ 0x127: 0x42706, // public
+ 0x129: 0x2510e, // formnovalidate
+ 0x12a: 0x55d06, // onshow
+ 0x12c: 0x16609, // translate
+ 0x12d: 0x9704, // cite
+ 0x12e: 0x2e802, // ms
+ 0x12f: 0x1190c, // ontimeupdate
+ 0x130: 0xfd04, // kind
+ 0x131: 0x2660a, // formtarget
+ 0x135: 0x3c007, // onended
+ 0x136: 0x28606, // hidden
+ 0x137: 0x2c01, // s
+ 0x139: 0x2470a, // formmethod
+ 0x13a: 0x44704, // list
+ 0x13c: 0x27002, // h6
+ 0x13d: 0xcd02, // ol
+ 0x13e: 0x3530b, // oncuechange
+ 0x13f: 0x20a0d, // foreignobject
+ 0x143: 0x5c90e, // onbeforeunload
+ 0x145: 0x3a709, // onemptied
+ 0x146: 0x17105, // defer
+ 0x147: 0xef03, // xmp
+ 0x148: 0xaf05, // audio
+ 0x149: 0x1903, // kbd
+ 0x14c: 0x46f09, // onmessage
+ 0x14d: 0x5c506, // option
+ 0x14e: 0x4503, // alt
+ 0x14f: 0x33f07, // checked
+ 0x150: 0x10c08, // autoplay
+ 0x152: 0x202, // br
+ 0x153: 0x2550a, // novalidate
+ 0x156: 0x7d07, // noembed
+ 0x159: 0x2ad07, // onclick
+ 0x15a: 0x4780b, // onmousedown
+ 0x15b: 0x3b808, // onchange
+ 0x15e: 0x3fb09, // oninvalid
+ 0x15f: 0x2e906, // scoped
+ 0x160: 0x1ae08, // controls
+ 0x161: 0x32905, // muted
+ 0x163: 0x4ec06, // usemap
+ 0x164: 0x1dd0a, // figcaption
+ 0x165: 0x36806, // ondrag
+ 0x166: 0x29304, // high
+ 0x168: 0x3d403, // src
+ 0x169: 0x17d06, // poster
+ 0x16b: 0x18d0e, // annotation-xml
+ 0x16c: 0x5bc04, // step
+ 0x16d: 0x4, // abbr
+ 0x16e: 0x1b06, // dialog
+ 0x170: 0x1202, // li
+ 0x172: 0x47a02, // mo
+ 0x175: 0x1fd03, // for
+ 0x176: 0x1cd03, // ins
+ 0x178: 0x53004, // size
+ 0x17a: 0x5207, // default
+ 0x17b: 0x1a03, // bdi
+ 0x17c: 0x4ce0a, // onpagehide
+ 0x17d: 0x9d07, // dirname
+ 0x17e: 0x23304, // type
+ 0x17f: 0x21704, // form
+ 0x180: 0x4c105, // inert
+ 0x181: 0x12709, // oncanplay
+ 0x182: 0x8303, // dfn
+ 0x183: 0x45c08, // tabindex
+ 0x186: 0x7f02, // em
+ 0x187: 0x29c04, // lang
+ 0x189: 0x3a208, // dropzone
+ 0x18a: 0x4110a, // onkeypress
+ 0x18b: 0x25b08, // datetime
+ 0x18c: 0x18804, // cols
+ 0x18d: 0x1, // a
+ 0x18e: 0x43b0c, // onloadeddata
+ 0x191: 0x15606, // border
+ 0x192: 0x2e05, // tbody
+ 0x193: 0x24b06, // method
+ 0x195: 0xbe04, // loop
+ 0x196: 0x2b406, // iframe
+ 0x198: 0x2fa04, // head
+ 0x19e: 0x5b608, // manifest
+ 0x19f: 0xe109, // autofocus
+ 0x1a0: 0x16f04, // code
+ 0x1a1: 0x53406, // strong
+ 0x1a2: 0x32108, // multiple
+ 0x1a3: 0xc05, // param
+ 0x1a6: 0x23007, // enctype
+ 0x1a7: 0x2dd04, // face
+ 0x1a8: 0xf109, // plaintext
+ 0x1a9: 0x13602, // h1
+ 0x1aa: 0x56609, // onstalled
+ 0x1ad: 0x28d06, // script
+ 0x1ae: 0x30006, // spacer
+ 0x1af: 0x52c08, // onresize
+ 0x1b0: 0x49b0b, // onmouseover
+ 0x1b1: 0x59108, // onunload
+ 0x1b2: 0x54208, // onseeked
+ 0x1b4: 0x2330d, // typemustmatch
+ 0x1b5: 0x1f106, // figure
+ 0x1b6: 0x48e0a, // onmouseout
+ 0x1b7: 0x27f03, // pre
+ 0x1b8: 0x4e205, // width
+ 0x1bb: 0x7404, // nobr
+ 0x1be: 0x7002, // tt
+ 0x1bf: 0x1105, // align
+ 0x1c0: 0x3f407, // oninput
+ 0x1c3: 0x42107, // onkeyup
+ 0x1c6: 0x1e50c, // onafterprint
+ 0x1c7: 0x210e, // accept-charset
+ 0x1c8: 0x9806, // itemid
+ 0x1cb: 0x50e06, // strike
+ 0x1cc: 0x57a03, // sub
+ 0x1cd: 0xf905, // track
+ 0x1ce: 0x39705, // start
+ 0x1d0: 0x11408, // basefont
+ 0x1d6: 0x1cf06, // source
+ 0x1d7: 0x1a806, // legend
+ 0x1d8: 0x2f905, // thead
+ 0x1da: 0x2e905, // scope
+ 0x1dd: 0x21106, // object
+ 0x1de: 0xa205, // media
+ 0x1df: 0x18d0a, // annotation
+ 0x1e0: 0x22c0b, // formenctype
+ 0x1e2: 0x28b08, // noscript
+ 0x1e4: 0x53005, // sizes
+ 0x1e5: 0xd50c, // autocomplete
+ 0x1e6: 0x7a04, // span
+ 0x1e7: 0x8508, // noframes
+ 0x1e8: 0x26a06, // target
+ 0x1e9: 0x3a006, // ondrop
+ 0x1ea: 0x3d406, // srcdoc
+ 0x1ec: 0x5e08, // reversed
+ 0x1f0: 0x2c707, // isindex
+ 0x1f3: 0x29808, // hreflang
+ 0x1f5: 0x4e602, // h5
+ 0x1f6: 0x5d507, // address
+ 0x1fa: 0x30603, // max
+ 0x1fb: 0xc70b, // placeholder
+ 0x1fc: 0x31408, // textarea
+ 0x1fe: 0x4a609, // onmouseup
+ 0x1ff: 0x3910b, // ondragstart
+}
+
+const atomText = "abbradiogrouparamalignmarkbdialogaccept-charsetbodyaccesskey" +
+ "genavaluealtdescanvasidefaultfootereversedetailsampatternobr" +
+ "owspanoembedfnoframesetitleasyncitemidirnamediagroupingaudio" +
+ "ncancelabelooptgrouplaceholderubyautocompleteautofocusandbox" +
+ "mplaintextrackindisabledivarautoplaybasefontimeupdatebdoncan" +
+ "playthrough1bgsoundlowbrbigblinkblockquoteborderbuttonabortr" +
+ "anslatecodefercolgroupostercolorcolspannotation-xmlcommandra" +
+ "ggablegendcontrolshapecoordsmallcrossoriginsourcefieldsetfig" +
+ "captionafterprintfigurequiredforeignObjectforeignobjectforma" +
+ "ctionbeforeprintformenctypemustmatchallengeformmethodformnov" +
+ "alidatetimeterformtargeth6heightmlhgroupreloadhiddenoscripth" +
+ "igh2hreflanghttp-equivideonclickiframeimageimglyph3isindexis" +
+ "mappletitemrefacenteritemscopeditemtypematheaderspacermaxlen" +
+ "gth4minmtextareadonlymultiplemutedoncloseamlesspellcheckedon" +
+ "contextmenuoncuechangeondblclickondragendondragenterondragle" +
+ "aveondragoverondragstarticleondropzonemptiedondurationchange" +
+ "onendedonerroronfocusrcdoclassectionbluronhashchangeoninputo" +
+ "ninvalidonkeydownloadonkeypressrclangonkeyupublicontentedita" +
+ "bleonloadeddatalistingonloadedmetadatabindexonloadstartonmes" +
+ "sageonmousedownonmousemoveonmouseoutputonmouseoveronmouseupo" +
+ "nmousewheelonofflinertononlineonpagehidelonpageshowidth5onpa" +
+ "usemaponplayingonpopstateonprogresstrikeytypeonratechangeonr" +
+ "esetonresizestrongonscrollonseekedonseekingonselectedonshowr" +
+ "aponstalledonstorageonsubmitempropenonsuspendonunloadonvolum" +
+ "echangeonwaitingoptimumanifestepromptoptionbeforeunloaddress" +
+ "tylesummarysupsvgsystemarquee"
diff --git a/libgo/go/exp/html/atom/table_test.go b/libgo/go/exp/html/atom/table_test.go
new file mode 100644
index 00000000000..db016a1c01c
--- /dev/null
+++ b/libgo/go/exp/html/atom/table_test.go
@@ -0,0 +1,341 @@
+// generated by go run gen.go -test; DO NOT EDIT
+
+package atom
+
+var testAtomList = []string{
+ "a",
+ "abbr",
+ "accept",
+ "accept-charset",
+ "accesskey",
+ "action",
+ "address",
+ "align",
+ "alt",
+ "annotation",
+ "annotation-xml",
+ "applet",
+ "area",
+ "article",
+ "aside",
+ "async",
+ "audio",
+ "autocomplete",
+ "autofocus",
+ "autoplay",
+ "b",
+ "base",
+ "basefont",
+ "bdi",
+ "bdo",
+ "bgsound",
+ "big",
+ "blink",
+ "blockquote",
+ "body",
+ "border",
+ "br",
+ "button",
+ "canvas",
+ "caption",
+ "center",
+ "challenge",
+ "charset",
+ "checked",
+ "cite",
+ "cite",
+ "class",
+ "code",
+ "col",
+ "colgroup",
+ "color",
+ "cols",
+ "colspan",
+ "command",
+ "command",
+ "content",
+ "contenteditable",
+ "contextmenu",
+ "controls",
+ "coords",
+ "crossorigin",
+ "data",
+ "data",
+ "datalist",
+ "datetime",
+ "dd",
+ "default",
+ "defer",
+ "del",
+ "desc",
+ "details",
+ "dfn",
+ "dialog",
+ "dir",
+ "dirname",
+ "disabled",
+ "div",
+ "dl",
+ "download",
+ "draggable",
+ "dropzone",
+ "dt",
+ "em",
+ "embed",
+ "enctype",
+ "face",
+ "fieldset",
+ "figcaption",
+ "figure",
+ "font",
+ "footer",
+ "for",
+ "foreignObject",
+ "foreignobject",
+ "form",
+ "form",
+ "formaction",
+ "formenctype",
+ "formmethod",
+ "formnovalidate",
+ "formtarget",
+ "frame",
+ "frameset",
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6",
+ "head",
+ "header",
+ "headers",
+ "height",
+ "hgroup",
+ "hidden",
+ "high",
+ "hr",
+ "href",
+ "hreflang",
+ "html",
+ "http-equiv",
+ "i",
+ "icon",
+ "id",
+ "iframe",
+ "image",
+ "img",
+ "inert",
+ "input",
+ "ins",
+ "isindex",
+ "ismap",
+ "itemid",
+ "itemprop",
+ "itemref",
+ "itemscope",
+ "itemtype",
+ "kbd",
+ "keygen",
+ "keytype",
+ "kind",
+ "label",
+ "label",
+ "lang",
+ "legend",
+ "li",
+ "link",
+ "list",
+ "listing",
+ "loop",
+ "low",
+ "malignmark",
+ "manifest",
+ "map",
+ "mark",
+ "marquee",
+ "math",
+ "max",
+ "maxlength",
+ "media",
+ "mediagroup",
+ "menu",
+ "meta",
+ "meter",
+ "method",
+ "mglyph",
+ "mi",
+ "min",
+ "mn",
+ "mo",
+ "ms",
+ "mtext",
+ "multiple",
+ "muted",
+ "name",
+ "nav",
+ "nobr",
+ "noembed",
+ "noframes",
+ "noscript",
+ "novalidate",
+ "object",
+ "ol",
+ "onabort",
+ "onafterprint",
+ "onbeforeprint",
+ "onbeforeunload",
+ "onblur",
+ "oncancel",
+ "oncanplay",
+ "oncanplaythrough",
+ "onchange",
+ "onclick",
+ "onclose",
+ "oncontextmenu",
+ "oncuechange",
+ "ondblclick",
+ "ondrag",
+ "ondragend",
+ "ondragenter",
+ "ondragleave",
+ "ondragover",
+ "ondragstart",
+ "ondrop",
+ "ondurationchange",
+ "onemptied",
+ "onended",
+ "onerror",
+ "onfocus",
+ "onhashchange",
+ "oninput",
+ "oninvalid",
+ "onkeydown",
+ "onkeypress",
+ "onkeyup",
+ "onload",
+ "onloadeddata",
+ "onloadedmetadata",
+ "onloadstart",
+ "onmessage",
+ "onmousedown",
+ "onmousemove",
+ "onmouseout",
+ "onmouseover",
+ "onmouseup",
+ "onmousewheel",
+ "onoffline",
+ "ononline",
+ "onpagehide",
+ "onpageshow",
+ "onpause",
+ "onplay",
+ "onplaying",
+ "onpopstate",
+ "onprogress",
+ "onratechange",
+ "onreset",
+ "onresize",
+ "onscroll",
+ "onseeked",
+ "onseeking",
+ "onselect",
+ "onshow",
+ "onstalled",
+ "onstorage",
+ "onsubmit",
+ "onsuspend",
+ "ontimeupdate",
+ "onunload",
+ "onvolumechange",
+ "onwaiting",
+ "open",
+ "optgroup",
+ "optimum",
+ "option",
+ "output",
+ "p",
+ "param",
+ "pattern",
+ "ping",
+ "placeholder",
+ "plaintext",
+ "poster",
+ "pre",
+ "preload",
+ "progress",
+ "prompt",
+ "public",
+ "q",
+ "radiogroup",
+ "readonly",
+ "rel",
+ "required",
+ "reversed",
+ "rows",
+ "rowspan",
+ "rp",
+ "rt",
+ "ruby",
+ "s",
+ "samp",
+ "sandbox",
+ "scope",
+ "scoped",
+ "script",
+ "seamless",
+ "section",
+ "select",
+ "selected",
+ "shape",
+ "size",
+ "sizes",
+ "small",
+ "source",
+ "spacer",
+ "span",
+ "span",
+ "spellcheck",
+ "src",
+ "srcdoc",
+ "srclang",
+ "start",
+ "step",
+ "strike",
+ "strong",
+ "style",
+ "style",
+ "sub",
+ "summary",
+ "sup",
+ "svg",
+ "system",
+ "tabindex",
+ "table",
+ "target",
+ "tbody",
+ "td",
+ "textarea",
+ "tfoot",
+ "th",
+ "thead",
+ "time",
+ "title",
+ "title",
+ "tr",
+ "track",
+ "translate",
+ "tt",
+ "type",
+ "typemustmatch",
+ "u",
+ "ul",
+ "usemap",
+ "value",
+ "var",
+ "video",
+ "wbr",
+ "width",
+ "wrap",
+ "xmp",
+}
diff --git a/libgo/go/exp/html/doc.go b/libgo/go/exp/html/doc.go
index 56b194ffb90..4dd453091c6 100644
--- a/libgo/go/exp/html/doc.go
+++ b/libgo/go/exp/html/doc.go
@@ -84,7 +84,7 @@ example, to process each anchor node in depth-first order:
if n.Type == html.ElementNode && n.Data == "a" {
// Do something with n...
}
- for _, c := range n.Child {
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
diff --git a/libgo/go/exp/html/entity.go b/libgo/go/exp/html/entity.go
index bd830752359..af8a007ed04 100644
--- a/libgo/go/exp/html/entity.go
+++ b/libgo/go/exp/html/entity.go
@@ -75,2083 +75,2083 @@ var entity = map[string]rune{
"Copf;": '\U00002102',
"Coproduct;": '\U00002210',
"CounterClockwiseContourIntegral;": '\U00002233',
- "Cross;": '\U00002A2F',
- "Cscr;": '\U0001D49E',
- "Cup;": '\U000022D3',
- "CupCap;": '\U0000224D',
- "DD;": '\U00002145',
- "DDotrahd;": '\U00002911',
- "DJcy;": '\U00000402',
- "DScy;": '\U00000405',
- "DZcy;": '\U0000040F',
- "Dagger;": '\U00002021',
- "Darr;": '\U000021A1',
- "Dashv;": '\U00002AE4',
- "Dcaron;": '\U0000010E',
- "Dcy;": '\U00000414',
- "Del;": '\U00002207',
- "Delta;": '\U00000394',
- "Dfr;": '\U0001D507',
- "DiacriticalAcute;": '\U000000B4',
- "DiacriticalDot;": '\U000002D9',
- "DiacriticalDoubleAcute;": '\U000002DD',
- "DiacriticalGrave;": '\U00000060',
- "DiacriticalTilde;": '\U000002DC',
- "Diamond;": '\U000022C4',
- "DifferentialD;": '\U00002146',
- "Dopf;": '\U0001D53B',
- "Dot;": '\U000000A8',
- "DotDot;": '\U000020DC',
- "DotEqual;": '\U00002250',
- "DoubleContourIntegral;": '\U0000222F',
- "DoubleDot;": '\U000000A8',
- "DoubleDownArrow;": '\U000021D3',
- "DoubleLeftArrow;": '\U000021D0',
- "DoubleLeftRightArrow;": '\U000021D4',
- "DoubleLeftTee;": '\U00002AE4',
- "DoubleLongLeftArrow;": '\U000027F8',
- "DoubleLongLeftRightArrow;": '\U000027FA',
- "DoubleLongRightArrow;": '\U000027F9',
- "DoubleRightArrow;": '\U000021D2',
- "DoubleRightTee;": '\U000022A8',
- "DoubleUpArrow;": '\U000021D1',
- "DoubleUpDownArrow;": '\U000021D5',
- "DoubleVerticalBar;": '\U00002225',
- "DownArrow;": '\U00002193',
- "DownArrowBar;": '\U00002913',
- "DownArrowUpArrow;": '\U000021F5',
- "DownBreve;": '\U00000311',
- "DownLeftRightVector;": '\U00002950',
- "DownLeftTeeVector;": '\U0000295E',
- "DownLeftVector;": '\U000021BD',
- "DownLeftVectorBar;": '\U00002956',
- "DownRightTeeVector;": '\U0000295F',
- "DownRightVector;": '\U000021C1',
- "DownRightVectorBar;": '\U00002957',
- "DownTee;": '\U000022A4',
- "DownTeeArrow;": '\U000021A7',
- "Downarrow;": '\U000021D3',
- "Dscr;": '\U0001D49F',
- "Dstrok;": '\U00000110',
- "ENG;": '\U0000014A',
- "ETH;": '\U000000D0',
- "Eacute;": '\U000000C9',
- "Ecaron;": '\U0000011A',
- "Ecirc;": '\U000000CA',
- "Ecy;": '\U0000042D',
- "Edot;": '\U00000116',
- "Efr;": '\U0001D508',
- "Egrave;": '\U000000C8',
- "Element;": '\U00002208',
- "Emacr;": '\U00000112',
- "EmptySmallSquare;": '\U000025FB',
- "EmptyVerySmallSquare;": '\U000025AB',
- "Eogon;": '\U00000118',
- "Eopf;": '\U0001D53C',
- "Epsilon;": '\U00000395',
- "Equal;": '\U00002A75',
- "EqualTilde;": '\U00002242',
- "Equilibrium;": '\U000021CC',
- "Escr;": '\U00002130',
- "Esim;": '\U00002A73',
- "Eta;": '\U00000397',
- "Euml;": '\U000000CB',
- "Exists;": '\U00002203',
- "ExponentialE;": '\U00002147',
- "Fcy;": '\U00000424',
- "Ffr;": '\U0001D509',
- "FilledSmallSquare;": '\U000025FC',
- "FilledVerySmallSquare;": '\U000025AA',
- "Fopf;": '\U0001D53D',
- "ForAll;": '\U00002200',
- "Fouriertrf;": '\U00002131',
- "Fscr;": '\U00002131',
- "GJcy;": '\U00000403',
- "GT;": '\U0000003E',
- "Gamma;": '\U00000393',
- "Gammad;": '\U000003DC',
- "Gbreve;": '\U0000011E',
- "Gcedil;": '\U00000122',
- "Gcirc;": '\U0000011C',
- "Gcy;": '\U00000413',
- "Gdot;": '\U00000120',
- "Gfr;": '\U0001D50A',
- "Gg;": '\U000022D9',
- "Gopf;": '\U0001D53E',
- "GreaterEqual;": '\U00002265',
- "GreaterEqualLess;": '\U000022DB',
- "GreaterFullEqual;": '\U00002267',
- "GreaterGreater;": '\U00002AA2',
- "GreaterLess;": '\U00002277',
- "GreaterSlantEqual;": '\U00002A7E',
- "GreaterTilde;": '\U00002273',
- "Gscr;": '\U0001D4A2',
- "Gt;": '\U0000226B',
- "HARDcy;": '\U0000042A',
- "Hacek;": '\U000002C7',
- "Hat;": '\U0000005E',
- "Hcirc;": '\U00000124',
- "Hfr;": '\U0000210C',
- "HilbertSpace;": '\U0000210B',
- "Hopf;": '\U0000210D',
- "HorizontalLine;": '\U00002500',
- "Hscr;": '\U0000210B',
- "Hstrok;": '\U00000126',
- "HumpDownHump;": '\U0000224E',
- "HumpEqual;": '\U0000224F',
- "IEcy;": '\U00000415',
- "IJlig;": '\U00000132',
- "IOcy;": '\U00000401',
- "Iacute;": '\U000000CD',
- "Icirc;": '\U000000CE',
- "Icy;": '\U00000418',
- "Idot;": '\U00000130',
- "Ifr;": '\U00002111',
- "Igrave;": '\U000000CC',
- "Im;": '\U00002111',
- "Imacr;": '\U0000012A',
- "ImaginaryI;": '\U00002148',
- "Implies;": '\U000021D2',
- "Int;": '\U0000222C',
- "Integral;": '\U0000222B',
- "Intersection;": '\U000022C2',
- "InvisibleComma;": '\U00002063',
- "InvisibleTimes;": '\U00002062',
- "Iogon;": '\U0000012E',
- "Iopf;": '\U0001D540',
- "Iota;": '\U00000399',
- "Iscr;": '\U00002110',
- "Itilde;": '\U00000128',
- "Iukcy;": '\U00000406',
- "Iuml;": '\U000000CF',
- "Jcirc;": '\U00000134',
- "Jcy;": '\U00000419',
- "Jfr;": '\U0001D50D',
- "Jopf;": '\U0001D541',
- "Jscr;": '\U0001D4A5',
- "Jsercy;": '\U00000408',
- "Jukcy;": '\U00000404',
- "KHcy;": '\U00000425',
- "KJcy;": '\U0000040C',
- "Kappa;": '\U0000039A',
- "Kcedil;": '\U00000136',
- "Kcy;": '\U0000041A',
- "Kfr;": '\U0001D50E',
- "Kopf;": '\U0001D542',
- "Kscr;": '\U0001D4A6',
- "LJcy;": '\U00000409',
- "LT;": '\U0000003C',
- "Lacute;": '\U00000139',
- "Lambda;": '\U0000039B',
- "Lang;": '\U000027EA',
- "Laplacetrf;": '\U00002112',
- "Larr;": '\U0000219E',
- "Lcaron;": '\U0000013D',
- "Lcedil;": '\U0000013B',
- "Lcy;": '\U0000041B',
- "LeftAngleBracket;": '\U000027E8',
- "LeftArrow;": '\U00002190',
- "LeftArrowBar;": '\U000021E4',
- "LeftArrowRightArrow;": '\U000021C6',
- "LeftCeiling;": '\U00002308',
- "LeftDoubleBracket;": '\U000027E6',
- "LeftDownTeeVector;": '\U00002961',
- "LeftDownVector;": '\U000021C3',
- "LeftDownVectorBar;": '\U00002959',
- "LeftFloor;": '\U0000230A',
- "LeftRightArrow;": '\U00002194',
- "LeftRightVector;": '\U0000294E',
- "LeftTee;": '\U000022A3',
- "LeftTeeArrow;": '\U000021A4',
- "LeftTeeVector;": '\U0000295A',
- "LeftTriangle;": '\U000022B2',
- "LeftTriangleBar;": '\U000029CF',
- "LeftTriangleEqual;": '\U000022B4',
- "LeftUpDownVector;": '\U00002951',
- "LeftUpTeeVector;": '\U00002960',
- "LeftUpVector;": '\U000021BF',
- "LeftUpVectorBar;": '\U00002958',
- "LeftVector;": '\U000021BC',
- "LeftVectorBar;": '\U00002952',
- "Leftarrow;": '\U000021D0',
- "Leftrightarrow;": '\U000021D4',
- "LessEqualGreater;": '\U000022DA',
- "LessFullEqual;": '\U00002266',
- "LessGreater;": '\U00002276',
- "LessLess;": '\U00002AA1',
- "LessSlantEqual;": '\U00002A7D',
- "LessTilde;": '\U00002272',
- "Lfr;": '\U0001D50F',
- "Ll;": '\U000022D8',
- "Lleftarrow;": '\U000021DA',
- "Lmidot;": '\U0000013F',
- "LongLeftArrow;": '\U000027F5',
- "LongLeftRightArrow;": '\U000027F7',
- "LongRightArrow;": '\U000027F6',
- "Longleftarrow;": '\U000027F8',
- "Longleftrightarrow;": '\U000027FA',
- "Longrightarrow;": '\U000027F9',
- "Lopf;": '\U0001D543',
- "LowerLeftArrow;": '\U00002199',
- "LowerRightArrow;": '\U00002198',
- "Lscr;": '\U00002112',
- "Lsh;": '\U000021B0',
- "Lstrok;": '\U00000141',
- "Lt;": '\U0000226A',
- "Map;": '\U00002905',
- "Mcy;": '\U0000041C',
- "MediumSpace;": '\U0000205F',
- "Mellintrf;": '\U00002133',
- "Mfr;": '\U0001D510',
- "MinusPlus;": '\U00002213',
- "Mopf;": '\U0001D544',
- "Mscr;": '\U00002133',
- "Mu;": '\U0000039C',
- "NJcy;": '\U0000040A',
- "Nacute;": '\U00000143',
- "Ncaron;": '\U00000147',
- "Ncedil;": '\U00000145',
- "Ncy;": '\U0000041D',
- "NegativeMediumSpace;": '\U0000200B',
- "NegativeThickSpace;": '\U0000200B',
- "NegativeThinSpace;": '\U0000200B',
- "NegativeVeryThinSpace;": '\U0000200B',
- "NestedGreaterGreater;": '\U0000226B',
- "NestedLessLess;": '\U0000226A',
- "NewLine;": '\U0000000A',
- "Nfr;": '\U0001D511',
- "NoBreak;": '\U00002060',
- "NonBreakingSpace;": '\U000000A0',
- "Nopf;": '\U00002115',
- "Not;": '\U00002AEC',
- "NotCongruent;": '\U00002262',
- "NotCupCap;": '\U0000226D',
- "NotDoubleVerticalBar;": '\U00002226',
- "NotElement;": '\U00002209',
- "NotEqual;": '\U00002260',
- "NotExists;": '\U00002204',
- "NotGreater;": '\U0000226F',
- "NotGreaterEqual;": '\U00002271',
- "NotGreaterLess;": '\U00002279',
- "NotGreaterTilde;": '\U00002275',
- "NotLeftTriangle;": '\U000022EA',
- "NotLeftTriangleEqual;": '\U000022EC',
- "NotLess;": '\U0000226E',
- "NotLessEqual;": '\U00002270',
- "NotLessGreater;": '\U00002278',
- "NotLessTilde;": '\U00002274',
- "NotPrecedes;": '\U00002280',
- "NotPrecedesSlantEqual;": '\U000022E0',
- "NotReverseElement;": '\U0000220C',
- "NotRightTriangle;": '\U000022EB',
- "NotRightTriangleEqual;": '\U000022ED',
- "NotSquareSubsetEqual;": '\U000022E2',
- "NotSquareSupersetEqual;": '\U000022E3',
- "NotSubsetEqual;": '\U00002288',
- "NotSucceeds;": '\U00002281',
- "NotSucceedsSlantEqual;": '\U000022E1',
- "NotSupersetEqual;": '\U00002289',
- "NotTilde;": '\U00002241',
- "NotTildeEqual;": '\U00002244',
- "NotTildeFullEqual;": '\U00002247',
- "NotTildeTilde;": '\U00002249',
- "NotVerticalBar;": '\U00002224',
- "Nscr;": '\U0001D4A9',
- "Ntilde;": '\U000000D1',
- "Nu;": '\U0000039D',
- "OElig;": '\U00000152',
- "Oacute;": '\U000000D3',
- "Ocirc;": '\U000000D4',
- "Ocy;": '\U0000041E',
- "Odblac;": '\U00000150',
- "Ofr;": '\U0001D512',
- "Ograve;": '\U000000D2',
- "Omacr;": '\U0000014C',
- "Omega;": '\U000003A9',
- "Omicron;": '\U0000039F',
- "Oopf;": '\U0001D546',
- "OpenCurlyDoubleQuote;": '\U0000201C',
- "OpenCurlyQuote;": '\U00002018',
- "Or;": '\U00002A54',
- "Oscr;": '\U0001D4AA',
- "Oslash;": '\U000000D8',
- "Otilde;": '\U000000D5',
- "Otimes;": '\U00002A37',
- "Ouml;": '\U000000D6',
- "OverBar;": '\U0000203E',
- "OverBrace;": '\U000023DE',
- "OverBracket;": '\U000023B4',
- "OverParenthesis;": '\U000023DC',
- "PartialD;": '\U00002202',
- "Pcy;": '\U0000041F',
- "Pfr;": '\U0001D513',
- "Phi;": '\U000003A6',
- "Pi;": '\U000003A0',
- "PlusMinus;": '\U000000B1',
- "Poincareplane;": '\U0000210C',
- "Popf;": '\U00002119',
- "Pr;": '\U00002ABB',
- "Precedes;": '\U0000227A',
- "PrecedesEqual;": '\U00002AAF',
- "PrecedesSlantEqual;": '\U0000227C',
- "PrecedesTilde;": '\U0000227E',
- "Prime;": '\U00002033',
- "Product;": '\U0000220F',
- "Proportion;": '\U00002237',
- "Proportional;": '\U0000221D',
- "Pscr;": '\U0001D4AB',
- "Psi;": '\U000003A8',
- "QUOT;": '\U00000022',
- "Qfr;": '\U0001D514',
- "Qopf;": '\U0000211A',
- "Qscr;": '\U0001D4AC',
- "RBarr;": '\U00002910',
- "REG;": '\U000000AE',
- "Racute;": '\U00000154',
- "Rang;": '\U000027EB',
- "Rarr;": '\U000021A0',
- "Rarrtl;": '\U00002916',
- "Rcaron;": '\U00000158',
- "Rcedil;": '\U00000156',
- "Rcy;": '\U00000420',
- "Re;": '\U0000211C',
- "ReverseElement;": '\U0000220B',
- "ReverseEquilibrium;": '\U000021CB',
- "ReverseUpEquilibrium;": '\U0000296F',
- "Rfr;": '\U0000211C',
- "Rho;": '\U000003A1',
- "RightAngleBracket;": '\U000027E9',
- "RightArrow;": '\U00002192',
- "RightArrowBar;": '\U000021E5',
- "RightArrowLeftArrow;": '\U000021C4',
- "RightCeiling;": '\U00002309',
- "RightDoubleBracket;": '\U000027E7',
- "RightDownTeeVector;": '\U0000295D',
- "RightDownVector;": '\U000021C2',
- "RightDownVectorBar;": '\U00002955',
- "RightFloor;": '\U0000230B',
- "RightTee;": '\U000022A2',
- "RightTeeArrow;": '\U000021A6',
- "RightTeeVector;": '\U0000295B',
- "RightTriangle;": '\U000022B3',
- "RightTriangleBar;": '\U000029D0',
- "RightTriangleEqual;": '\U000022B5',
- "RightUpDownVector;": '\U0000294F',
- "RightUpTeeVector;": '\U0000295C',
- "RightUpVector;": '\U000021BE',
- "RightUpVectorBar;": '\U00002954',
- "RightVector;": '\U000021C0',
- "RightVectorBar;": '\U00002953',
- "Rightarrow;": '\U000021D2',
- "Ropf;": '\U0000211D',
- "RoundImplies;": '\U00002970',
- "Rrightarrow;": '\U000021DB',
- "Rscr;": '\U0000211B',
- "Rsh;": '\U000021B1',
- "RuleDelayed;": '\U000029F4',
- "SHCHcy;": '\U00000429',
- "SHcy;": '\U00000428',
- "SOFTcy;": '\U0000042C',
- "Sacute;": '\U0000015A',
- "Sc;": '\U00002ABC',
- "Scaron;": '\U00000160',
- "Scedil;": '\U0000015E',
- "Scirc;": '\U0000015C',
- "Scy;": '\U00000421',
- "Sfr;": '\U0001D516',
- "ShortDownArrow;": '\U00002193',
- "ShortLeftArrow;": '\U00002190',
- "ShortRightArrow;": '\U00002192',
- "ShortUpArrow;": '\U00002191',
- "Sigma;": '\U000003A3',
- "SmallCircle;": '\U00002218',
- "Sopf;": '\U0001D54A',
- "Sqrt;": '\U0000221A',
- "Square;": '\U000025A1',
- "SquareIntersection;": '\U00002293',
- "SquareSubset;": '\U0000228F',
- "SquareSubsetEqual;": '\U00002291',
- "SquareSuperset;": '\U00002290',
- "SquareSupersetEqual;": '\U00002292',
- "SquareUnion;": '\U00002294',
- "Sscr;": '\U0001D4AE',
- "Star;": '\U000022C6',
- "Sub;": '\U000022D0',
- "Subset;": '\U000022D0',
- "SubsetEqual;": '\U00002286',
- "Succeeds;": '\U0000227B',
- "SucceedsEqual;": '\U00002AB0',
- "SucceedsSlantEqual;": '\U0000227D',
- "SucceedsTilde;": '\U0000227F',
- "SuchThat;": '\U0000220B',
- "Sum;": '\U00002211',
- "Sup;": '\U000022D1',
- "Superset;": '\U00002283',
- "SupersetEqual;": '\U00002287',
- "Supset;": '\U000022D1',
- "THORN;": '\U000000DE',
- "TRADE;": '\U00002122',
- "TSHcy;": '\U0000040B',
- "TScy;": '\U00000426',
- "Tab;": '\U00000009',
- "Tau;": '\U000003A4',
- "Tcaron;": '\U00000164',
- "Tcedil;": '\U00000162',
- "Tcy;": '\U00000422',
- "Tfr;": '\U0001D517',
- "Therefore;": '\U00002234',
- "Theta;": '\U00000398',
- "ThinSpace;": '\U00002009',
- "Tilde;": '\U0000223C',
- "TildeEqual;": '\U00002243',
- "TildeFullEqual;": '\U00002245',
- "TildeTilde;": '\U00002248',
- "Topf;": '\U0001D54B',
- "TripleDot;": '\U000020DB',
- "Tscr;": '\U0001D4AF',
- "Tstrok;": '\U00000166',
- "Uacute;": '\U000000DA',
- "Uarr;": '\U0000219F',
- "Uarrocir;": '\U00002949',
- "Ubrcy;": '\U0000040E',
- "Ubreve;": '\U0000016C',
- "Ucirc;": '\U000000DB',
- "Ucy;": '\U00000423',
- "Udblac;": '\U00000170',
- "Ufr;": '\U0001D518',
- "Ugrave;": '\U000000D9',
- "Umacr;": '\U0000016A',
- "UnderBar;": '\U0000005F',
- "UnderBrace;": '\U000023DF',
- "UnderBracket;": '\U000023B5',
- "UnderParenthesis;": '\U000023DD',
- "Union;": '\U000022C3',
- "UnionPlus;": '\U0000228E',
- "Uogon;": '\U00000172',
- "Uopf;": '\U0001D54C',
- "UpArrow;": '\U00002191',
- "UpArrowBar;": '\U00002912',
- "UpArrowDownArrow;": '\U000021C5',
- "UpDownArrow;": '\U00002195',
- "UpEquilibrium;": '\U0000296E',
- "UpTee;": '\U000022A5',
- "UpTeeArrow;": '\U000021A5',
- "Uparrow;": '\U000021D1',
- "Updownarrow;": '\U000021D5',
- "UpperLeftArrow;": '\U00002196',
- "UpperRightArrow;": '\U00002197',
- "Upsi;": '\U000003D2',
- "Upsilon;": '\U000003A5',
- "Uring;": '\U0000016E',
- "Uscr;": '\U0001D4B0',
- "Utilde;": '\U00000168',
- "Uuml;": '\U000000DC',
- "VDash;": '\U000022AB',
- "Vbar;": '\U00002AEB',
- "Vcy;": '\U00000412',
- "Vdash;": '\U000022A9',
- "Vdashl;": '\U00002AE6',
- "Vee;": '\U000022C1',
- "Verbar;": '\U00002016',
- "Vert;": '\U00002016',
- "VerticalBar;": '\U00002223',
- "VerticalLine;": '\U0000007C',
- "VerticalSeparator;": '\U00002758',
- "VerticalTilde;": '\U00002240',
- "VeryThinSpace;": '\U0000200A',
- "Vfr;": '\U0001D519',
- "Vopf;": '\U0001D54D',
- "Vscr;": '\U0001D4B1',
- "Vvdash;": '\U000022AA',
- "Wcirc;": '\U00000174',
- "Wedge;": '\U000022C0',
- "Wfr;": '\U0001D51A',
- "Wopf;": '\U0001D54E',
- "Wscr;": '\U0001D4B2',
- "Xfr;": '\U0001D51B',
- "Xi;": '\U0000039E',
- "Xopf;": '\U0001D54F',
- "Xscr;": '\U0001D4B3',
- "YAcy;": '\U0000042F',
- "YIcy;": '\U00000407',
- "YUcy;": '\U0000042E',
- "Yacute;": '\U000000DD',
- "Ycirc;": '\U00000176',
- "Ycy;": '\U0000042B',
- "Yfr;": '\U0001D51C',
- "Yopf;": '\U0001D550',
- "Yscr;": '\U0001D4B4',
- "Yuml;": '\U00000178',
- "ZHcy;": '\U00000416',
- "Zacute;": '\U00000179',
- "Zcaron;": '\U0000017D',
- "Zcy;": '\U00000417',
- "Zdot;": '\U0000017B',
- "ZeroWidthSpace;": '\U0000200B',
- "Zeta;": '\U00000396',
- "Zfr;": '\U00002128',
- "Zopf;": '\U00002124',
- "Zscr;": '\U0001D4B5',
- "aacute;": '\U000000E1',
- "abreve;": '\U00000103',
- "ac;": '\U0000223E',
- "acd;": '\U0000223F',
- "acirc;": '\U000000E2',
- "acute;": '\U000000B4',
- "acy;": '\U00000430',
- "aelig;": '\U000000E6',
- "af;": '\U00002061',
- "afr;": '\U0001D51E',
- "agrave;": '\U000000E0',
- "alefsym;": '\U00002135',
- "aleph;": '\U00002135',
- "alpha;": '\U000003B1',
- "amacr;": '\U00000101',
- "amalg;": '\U00002A3F',
- "amp;": '\U00000026',
- "and;": '\U00002227',
- "andand;": '\U00002A55',
- "andd;": '\U00002A5C',
- "andslope;": '\U00002A58',
- "andv;": '\U00002A5A',
- "ang;": '\U00002220',
- "ange;": '\U000029A4',
- "angle;": '\U00002220',
- "angmsd;": '\U00002221',
- "angmsdaa;": '\U000029A8',
- "angmsdab;": '\U000029A9',
- "angmsdac;": '\U000029AA',
- "angmsdad;": '\U000029AB',
- "angmsdae;": '\U000029AC',
- "angmsdaf;": '\U000029AD',
- "angmsdag;": '\U000029AE',
- "angmsdah;": '\U000029AF',
- "angrt;": '\U0000221F',
- "angrtvb;": '\U000022BE',
- "angrtvbd;": '\U0000299D',
- "angsph;": '\U00002222',
- "angst;": '\U000000C5',
- "angzarr;": '\U0000237C',
- "aogon;": '\U00000105',
- "aopf;": '\U0001D552',
- "ap;": '\U00002248',
- "apE;": '\U00002A70',
- "apacir;": '\U00002A6F',
- "ape;": '\U0000224A',
- "apid;": '\U0000224B',
- "apos;": '\U00000027',
- "approx;": '\U00002248',
- "approxeq;": '\U0000224A',
- "aring;": '\U000000E5',
- "ascr;": '\U0001D4B6',
- "ast;": '\U0000002A',
- "asymp;": '\U00002248',
- "asympeq;": '\U0000224D',
- "atilde;": '\U000000E3',
- "auml;": '\U000000E4',
- "awconint;": '\U00002233',
- "awint;": '\U00002A11',
- "bNot;": '\U00002AED',
- "backcong;": '\U0000224C',
- "backepsilon;": '\U000003F6',
- "backprime;": '\U00002035',
- "backsim;": '\U0000223D',
- "backsimeq;": '\U000022CD',
- "barvee;": '\U000022BD',
- "barwed;": '\U00002305',
- "barwedge;": '\U00002305',
- "bbrk;": '\U000023B5',
- "bbrktbrk;": '\U000023B6',
- "bcong;": '\U0000224C',
- "bcy;": '\U00000431',
- "bdquo;": '\U0000201E',
- "becaus;": '\U00002235',
- "because;": '\U00002235',
- "bemptyv;": '\U000029B0',
- "bepsi;": '\U000003F6',
- "bernou;": '\U0000212C',
- "beta;": '\U000003B2',
- "beth;": '\U00002136',
- "between;": '\U0000226C',
- "bfr;": '\U0001D51F',
- "bigcap;": '\U000022C2',
- "bigcirc;": '\U000025EF',
- "bigcup;": '\U000022C3',
- "bigodot;": '\U00002A00',
- "bigoplus;": '\U00002A01',
- "bigotimes;": '\U00002A02',
- "bigsqcup;": '\U00002A06',
- "bigstar;": '\U00002605',
- "bigtriangledown;": '\U000025BD',
- "bigtriangleup;": '\U000025B3',
- "biguplus;": '\U00002A04',
- "bigvee;": '\U000022C1',
- "bigwedge;": '\U000022C0',
- "bkarow;": '\U0000290D',
- "blacklozenge;": '\U000029EB',
- "blacksquare;": '\U000025AA',
- "blacktriangle;": '\U000025B4',
- "blacktriangledown;": '\U000025BE',
- "blacktriangleleft;": '\U000025C2',
- "blacktriangleright;": '\U000025B8',
- "blank;": '\U00002423',
- "blk12;": '\U00002592',
- "blk14;": '\U00002591',
- "blk34;": '\U00002593',
- "block;": '\U00002588',
- "bnot;": '\U00002310',
- "bopf;": '\U0001D553',
- "bot;": '\U000022A5',
- "bottom;": '\U000022A5',
- "bowtie;": '\U000022C8',
- "boxDL;": '\U00002557',
- "boxDR;": '\U00002554',
- "boxDl;": '\U00002556',
- "boxDr;": '\U00002553',
- "boxH;": '\U00002550',
- "boxHD;": '\U00002566',
- "boxHU;": '\U00002569',
- "boxHd;": '\U00002564',
- "boxHu;": '\U00002567',
- "boxUL;": '\U0000255D',
- "boxUR;": '\U0000255A',
- "boxUl;": '\U0000255C',
- "boxUr;": '\U00002559',
- "boxV;": '\U00002551',
- "boxVH;": '\U0000256C',
- "boxVL;": '\U00002563',
- "boxVR;": '\U00002560',
- "boxVh;": '\U0000256B',
- "boxVl;": '\U00002562',
- "boxVr;": '\U0000255F',
- "boxbox;": '\U000029C9',
- "boxdL;": '\U00002555',
- "boxdR;": '\U00002552',
- "boxdl;": '\U00002510',
- "boxdr;": '\U0000250C',
- "boxh;": '\U00002500',
- "boxhD;": '\U00002565',
- "boxhU;": '\U00002568',
- "boxhd;": '\U0000252C',
- "boxhu;": '\U00002534',
- "boxminus;": '\U0000229F',
- "boxplus;": '\U0000229E',
- "boxtimes;": '\U000022A0',
- "boxuL;": '\U0000255B',
- "boxuR;": '\U00002558',
- "boxul;": '\U00002518',
- "boxur;": '\U00002514',
- "boxv;": '\U00002502',
- "boxvH;": '\U0000256A',
- "boxvL;": '\U00002561',
- "boxvR;": '\U0000255E',
- "boxvh;": '\U0000253C',
- "boxvl;": '\U00002524',
- "boxvr;": '\U0000251C',
- "bprime;": '\U00002035',
- "breve;": '\U000002D8',
- "brvbar;": '\U000000A6',
- "bscr;": '\U0001D4B7',
- "bsemi;": '\U0000204F',
- "bsim;": '\U0000223D',
- "bsime;": '\U000022CD',
- "bsol;": '\U0000005C',
- "bsolb;": '\U000029C5',
- "bsolhsub;": '\U000027C8',
- "bull;": '\U00002022',
- "bullet;": '\U00002022',
- "bump;": '\U0000224E',
- "bumpE;": '\U00002AAE',
- "bumpe;": '\U0000224F',
- "bumpeq;": '\U0000224F',
- "cacute;": '\U00000107',
- "cap;": '\U00002229',
- "capand;": '\U00002A44',
- "capbrcup;": '\U00002A49',
- "capcap;": '\U00002A4B',
- "capcup;": '\U00002A47',
- "capdot;": '\U00002A40',
- "caret;": '\U00002041',
- "caron;": '\U000002C7',
- "ccaps;": '\U00002A4D',
- "ccaron;": '\U0000010D',
- "ccedil;": '\U000000E7',
- "ccirc;": '\U00000109',
- "ccups;": '\U00002A4C',
- "ccupssm;": '\U00002A50',
- "cdot;": '\U0000010B',
- "cedil;": '\U000000B8',
- "cemptyv;": '\U000029B2',
- "cent;": '\U000000A2',
- "centerdot;": '\U000000B7',
- "cfr;": '\U0001D520',
- "chcy;": '\U00000447',
- "check;": '\U00002713',
- "checkmark;": '\U00002713',
- "chi;": '\U000003C7',
- "cir;": '\U000025CB',
- "cirE;": '\U000029C3',
- "circ;": '\U000002C6',
- "circeq;": '\U00002257',
- "circlearrowleft;": '\U000021BA',
- "circlearrowright;": '\U000021BB',
- "circledR;": '\U000000AE',
- "circledS;": '\U000024C8',
- "circledast;": '\U0000229B',
- "circledcirc;": '\U0000229A',
- "circleddash;": '\U0000229D',
- "cire;": '\U00002257',
- "cirfnint;": '\U00002A10',
- "cirmid;": '\U00002AEF',
- "cirscir;": '\U000029C2',
- "clubs;": '\U00002663',
- "clubsuit;": '\U00002663',
- "colon;": '\U0000003A',
- "colone;": '\U00002254',
- "coloneq;": '\U00002254',
- "comma;": '\U0000002C',
- "commat;": '\U00000040',
- "comp;": '\U00002201',
- "compfn;": '\U00002218',
- "complement;": '\U00002201',
- "complexes;": '\U00002102',
- "cong;": '\U00002245',
- "congdot;": '\U00002A6D',
- "conint;": '\U0000222E',
- "copf;": '\U0001D554',
- "coprod;": '\U00002210',
- "copy;": '\U000000A9',
- "copysr;": '\U00002117',
- "crarr;": '\U000021B5',
- "cross;": '\U00002717',
- "cscr;": '\U0001D4B8',
- "csub;": '\U00002ACF',
- "csube;": '\U00002AD1',
- "csup;": '\U00002AD0',
- "csupe;": '\U00002AD2',
- "ctdot;": '\U000022EF',
- "cudarrl;": '\U00002938',
- "cudarrr;": '\U00002935',
- "cuepr;": '\U000022DE',
- "cuesc;": '\U000022DF',
- "cularr;": '\U000021B6',
- "cularrp;": '\U0000293D',
- "cup;": '\U0000222A',
- "cupbrcap;": '\U00002A48',
- "cupcap;": '\U00002A46',
- "cupcup;": '\U00002A4A',
- "cupdot;": '\U0000228D',
- "cupor;": '\U00002A45',
- "curarr;": '\U000021B7',
- "curarrm;": '\U0000293C',
- "curlyeqprec;": '\U000022DE',
- "curlyeqsucc;": '\U000022DF',
- "curlyvee;": '\U000022CE',
- "curlywedge;": '\U000022CF',
- "curren;": '\U000000A4',
- "curvearrowleft;": '\U000021B6',
- "curvearrowright;": '\U000021B7',
- "cuvee;": '\U000022CE',
- "cuwed;": '\U000022CF',
- "cwconint;": '\U00002232',
- "cwint;": '\U00002231',
- "cylcty;": '\U0000232D',
- "dArr;": '\U000021D3',
- "dHar;": '\U00002965',
- "dagger;": '\U00002020',
- "daleth;": '\U00002138',
- "darr;": '\U00002193',
- "dash;": '\U00002010',
- "dashv;": '\U000022A3',
- "dbkarow;": '\U0000290F',
- "dblac;": '\U000002DD',
- "dcaron;": '\U0000010F',
- "dcy;": '\U00000434',
- "dd;": '\U00002146',
- "ddagger;": '\U00002021',
- "ddarr;": '\U000021CA',
- "ddotseq;": '\U00002A77',
- "deg;": '\U000000B0',
- "delta;": '\U000003B4',
- "demptyv;": '\U000029B1',
- "dfisht;": '\U0000297F',
- "dfr;": '\U0001D521',
- "dharl;": '\U000021C3',
- "dharr;": '\U000021C2',
- "diam;": '\U000022C4',
- "diamond;": '\U000022C4',
- "diamondsuit;": '\U00002666',
- "diams;": '\U00002666',
- "die;": '\U000000A8',
- "digamma;": '\U000003DD',
- "disin;": '\U000022F2',
- "div;": '\U000000F7',
- "divide;": '\U000000F7',
- "divideontimes;": '\U000022C7',
- "divonx;": '\U000022C7',
- "djcy;": '\U00000452',
- "dlcorn;": '\U0000231E',
- "dlcrop;": '\U0000230D',
- "dollar;": '\U00000024',
- "dopf;": '\U0001D555',
- "dot;": '\U000002D9',
- "doteq;": '\U00002250',
- "doteqdot;": '\U00002251',
- "dotminus;": '\U00002238',
- "dotplus;": '\U00002214',
- "dotsquare;": '\U000022A1',
- "doublebarwedge;": '\U00002306',
- "downarrow;": '\U00002193',
- "downdownarrows;": '\U000021CA',
- "downharpoonleft;": '\U000021C3',
- "downharpoonright;": '\U000021C2',
- "drbkarow;": '\U00002910',
- "drcorn;": '\U0000231F',
- "drcrop;": '\U0000230C',
- "dscr;": '\U0001D4B9',
- "dscy;": '\U00000455',
- "dsol;": '\U000029F6',
- "dstrok;": '\U00000111',
- "dtdot;": '\U000022F1',
- "dtri;": '\U000025BF',
- "dtrif;": '\U000025BE',
- "duarr;": '\U000021F5',
- "duhar;": '\U0000296F',
- "dwangle;": '\U000029A6',
- "dzcy;": '\U0000045F',
- "dzigrarr;": '\U000027FF',
- "eDDot;": '\U00002A77',
- "eDot;": '\U00002251',
- "eacute;": '\U000000E9',
- "easter;": '\U00002A6E',
- "ecaron;": '\U0000011B',
- "ecir;": '\U00002256',
- "ecirc;": '\U000000EA',
- "ecolon;": '\U00002255',
- "ecy;": '\U0000044D',
- "edot;": '\U00000117',
- "ee;": '\U00002147',
- "efDot;": '\U00002252',
- "efr;": '\U0001D522',
- "eg;": '\U00002A9A',
- "egrave;": '\U000000E8',
- "egs;": '\U00002A96',
- "egsdot;": '\U00002A98',
- "el;": '\U00002A99',
- "elinters;": '\U000023E7',
- "ell;": '\U00002113',
- "els;": '\U00002A95',
- "elsdot;": '\U00002A97',
- "emacr;": '\U00000113',
- "empty;": '\U00002205',
- "emptyset;": '\U00002205',
- "emptyv;": '\U00002205',
- "emsp;": '\U00002003',
- "emsp13;": '\U00002004',
- "emsp14;": '\U00002005',
- "eng;": '\U0000014B',
- "ensp;": '\U00002002',
- "eogon;": '\U00000119',
- "eopf;": '\U0001D556',
- "epar;": '\U000022D5',
- "eparsl;": '\U000029E3',
- "eplus;": '\U00002A71',
- "epsi;": '\U000003B5',
- "epsilon;": '\U000003B5',
- "epsiv;": '\U000003F5',
- "eqcirc;": '\U00002256',
- "eqcolon;": '\U00002255',
- "eqsim;": '\U00002242',
- "eqslantgtr;": '\U00002A96',
- "eqslantless;": '\U00002A95',
- "equals;": '\U0000003D',
- "equest;": '\U0000225F',
- "equiv;": '\U00002261',
- "equivDD;": '\U00002A78',
- "eqvparsl;": '\U000029E5',
- "erDot;": '\U00002253',
- "erarr;": '\U00002971',
- "escr;": '\U0000212F',
- "esdot;": '\U00002250',
- "esim;": '\U00002242',
- "eta;": '\U000003B7',
- "eth;": '\U000000F0',
- "euml;": '\U000000EB',
- "euro;": '\U000020AC',
- "excl;": '\U00000021',
- "exist;": '\U00002203',
- "expectation;": '\U00002130',
- "exponentiale;": '\U00002147',
- "fallingdotseq;": '\U00002252',
- "fcy;": '\U00000444',
- "female;": '\U00002640',
- "ffilig;": '\U0000FB03',
- "fflig;": '\U0000FB00',
- "ffllig;": '\U0000FB04',
- "ffr;": '\U0001D523',
- "filig;": '\U0000FB01',
- "flat;": '\U0000266D',
- "fllig;": '\U0000FB02',
- "fltns;": '\U000025B1',
- "fnof;": '\U00000192',
- "fopf;": '\U0001D557',
- "forall;": '\U00002200',
- "fork;": '\U000022D4',
- "forkv;": '\U00002AD9',
- "fpartint;": '\U00002A0D',
- "frac12;": '\U000000BD',
- "frac13;": '\U00002153',
- "frac14;": '\U000000BC',
- "frac15;": '\U00002155',
- "frac16;": '\U00002159',
- "frac18;": '\U0000215B',
- "frac23;": '\U00002154',
- "frac25;": '\U00002156',
- "frac34;": '\U000000BE',
- "frac35;": '\U00002157',
- "frac38;": '\U0000215C',
- "frac45;": '\U00002158',
- "frac56;": '\U0000215A',
- "frac58;": '\U0000215D',
- "frac78;": '\U0000215E',
- "frasl;": '\U00002044',
- "frown;": '\U00002322',
- "fscr;": '\U0001D4BB',
- "gE;": '\U00002267',
- "gEl;": '\U00002A8C',
- "gacute;": '\U000001F5',
- "gamma;": '\U000003B3',
- "gammad;": '\U000003DD',
- "gap;": '\U00002A86',
- "gbreve;": '\U0000011F',
- "gcirc;": '\U0000011D',
- "gcy;": '\U00000433',
- "gdot;": '\U00000121',
- "ge;": '\U00002265',
- "gel;": '\U000022DB',
- "geq;": '\U00002265',
- "geqq;": '\U00002267',
- "geqslant;": '\U00002A7E',
- "ges;": '\U00002A7E',
- "gescc;": '\U00002AA9',
- "gesdot;": '\U00002A80',
- "gesdoto;": '\U00002A82',
- "gesdotol;": '\U00002A84',
- "gesles;": '\U00002A94',
- "gfr;": '\U0001D524',
- "gg;": '\U0000226B',
- "ggg;": '\U000022D9',
- "gimel;": '\U00002137',
- "gjcy;": '\U00000453',
- "gl;": '\U00002277',
- "glE;": '\U00002A92',
- "gla;": '\U00002AA5',
- "glj;": '\U00002AA4',
- "gnE;": '\U00002269',
- "gnap;": '\U00002A8A',
- "gnapprox;": '\U00002A8A',
- "gne;": '\U00002A88',
- "gneq;": '\U00002A88',
- "gneqq;": '\U00002269',
- "gnsim;": '\U000022E7',
- "gopf;": '\U0001D558',
- "grave;": '\U00000060',
- "gscr;": '\U0000210A',
- "gsim;": '\U00002273',
- "gsime;": '\U00002A8E',
- "gsiml;": '\U00002A90',
- "gt;": '\U0000003E',
- "gtcc;": '\U00002AA7',
- "gtcir;": '\U00002A7A',
- "gtdot;": '\U000022D7',
- "gtlPar;": '\U00002995',
- "gtquest;": '\U00002A7C',
- "gtrapprox;": '\U00002A86',
- "gtrarr;": '\U00002978',
- "gtrdot;": '\U000022D7',
- "gtreqless;": '\U000022DB',
- "gtreqqless;": '\U00002A8C',
- "gtrless;": '\U00002277',
- "gtrsim;": '\U00002273',
- "hArr;": '\U000021D4',
- "hairsp;": '\U0000200A',
- "half;": '\U000000BD',
- "hamilt;": '\U0000210B',
- "hardcy;": '\U0000044A',
- "harr;": '\U00002194',
- "harrcir;": '\U00002948',
- "harrw;": '\U000021AD',
- "hbar;": '\U0000210F',
- "hcirc;": '\U00000125',
- "hearts;": '\U00002665',
- "heartsuit;": '\U00002665',
- "hellip;": '\U00002026',
- "hercon;": '\U000022B9',
- "hfr;": '\U0001D525',
- "hksearow;": '\U00002925',
- "hkswarow;": '\U00002926',
- "hoarr;": '\U000021FF',
- "homtht;": '\U0000223B',
- "hookleftarrow;": '\U000021A9',
- "hookrightarrow;": '\U000021AA',
- "hopf;": '\U0001D559',
- "horbar;": '\U00002015',
- "hscr;": '\U0001D4BD',
- "hslash;": '\U0000210F',
- "hstrok;": '\U00000127',
- "hybull;": '\U00002043',
- "hyphen;": '\U00002010',
- "iacute;": '\U000000ED',
- "ic;": '\U00002063',
- "icirc;": '\U000000EE',
- "icy;": '\U00000438',
- "iecy;": '\U00000435',
- "iexcl;": '\U000000A1',
- "iff;": '\U000021D4',
- "ifr;": '\U0001D526',
- "igrave;": '\U000000EC',
- "ii;": '\U00002148',
- "iiiint;": '\U00002A0C',
- "iiint;": '\U0000222D',
- "iinfin;": '\U000029DC',
- "iiota;": '\U00002129',
- "ijlig;": '\U00000133',
- "imacr;": '\U0000012B',
- "image;": '\U00002111',
- "imagline;": '\U00002110',
- "imagpart;": '\U00002111',
- "imath;": '\U00000131',
- "imof;": '\U000022B7',
- "imped;": '\U000001B5',
- "in;": '\U00002208',
- "incare;": '\U00002105',
- "infin;": '\U0000221E',
- "infintie;": '\U000029DD',
- "inodot;": '\U00000131',
- "int;": '\U0000222B',
- "intcal;": '\U000022BA',
- "integers;": '\U00002124',
- "intercal;": '\U000022BA',
- "intlarhk;": '\U00002A17',
- "intprod;": '\U00002A3C',
- "iocy;": '\U00000451',
- "iogon;": '\U0000012F',
- "iopf;": '\U0001D55A',
- "iota;": '\U000003B9',
- "iprod;": '\U00002A3C',
- "iquest;": '\U000000BF',
- "iscr;": '\U0001D4BE',
- "isin;": '\U00002208',
- "isinE;": '\U000022F9',
- "isindot;": '\U000022F5',
- "isins;": '\U000022F4',
- "isinsv;": '\U000022F3',
- "isinv;": '\U00002208',
- "it;": '\U00002062',
- "itilde;": '\U00000129',
- "iukcy;": '\U00000456',
- "iuml;": '\U000000EF',
- "jcirc;": '\U00000135',
- "jcy;": '\U00000439',
- "jfr;": '\U0001D527',
- "jmath;": '\U00000237',
- "jopf;": '\U0001D55B',
- "jscr;": '\U0001D4BF',
- "jsercy;": '\U00000458',
- "jukcy;": '\U00000454',
- "kappa;": '\U000003BA',
- "kappav;": '\U000003F0',
- "kcedil;": '\U00000137',
- "kcy;": '\U0000043A',
- "kfr;": '\U0001D528',
- "kgreen;": '\U00000138',
- "khcy;": '\U00000445',
- "kjcy;": '\U0000045C',
- "kopf;": '\U0001D55C',
- "kscr;": '\U0001D4C0',
- "lAarr;": '\U000021DA',
- "lArr;": '\U000021D0',
- "lAtail;": '\U0000291B',
- "lBarr;": '\U0000290E',
- "lE;": '\U00002266',
- "lEg;": '\U00002A8B',
- "lHar;": '\U00002962',
- "lacute;": '\U0000013A',
- "laemptyv;": '\U000029B4',
- "lagran;": '\U00002112',
- "lambda;": '\U000003BB',
- "lang;": '\U000027E8',
- "langd;": '\U00002991',
- "langle;": '\U000027E8',
- "lap;": '\U00002A85',
- "laquo;": '\U000000AB',
- "larr;": '\U00002190',
- "larrb;": '\U000021E4',
- "larrbfs;": '\U0000291F',
- "larrfs;": '\U0000291D',
- "larrhk;": '\U000021A9',
- "larrlp;": '\U000021AB',
- "larrpl;": '\U00002939',
- "larrsim;": '\U00002973',
- "larrtl;": '\U000021A2',
- "lat;": '\U00002AAB',
- "latail;": '\U00002919',
- "late;": '\U00002AAD',
- "lbarr;": '\U0000290C',
- "lbbrk;": '\U00002772',
- "lbrace;": '\U0000007B',
- "lbrack;": '\U0000005B',
- "lbrke;": '\U0000298B',
- "lbrksld;": '\U0000298F',
- "lbrkslu;": '\U0000298D',
- "lcaron;": '\U0000013E',
- "lcedil;": '\U0000013C',
- "lceil;": '\U00002308',
- "lcub;": '\U0000007B',
- "lcy;": '\U0000043B',
- "ldca;": '\U00002936',
- "ldquo;": '\U0000201C',
- "ldquor;": '\U0000201E',
- "ldrdhar;": '\U00002967',
- "ldrushar;": '\U0000294B',
- "ldsh;": '\U000021B2',
- "le;": '\U00002264',
- "leftarrow;": '\U00002190',
- "leftarrowtail;": '\U000021A2',
- "leftharpoondown;": '\U000021BD',
- "leftharpoonup;": '\U000021BC',
- "leftleftarrows;": '\U000021C7',
- "leftrightarrow;": '\U00002194',
- "leftrightarrows;": '\U000021C6',
- "leftrightharpoons;": '\U000021CB',
- "leftrightsquigarrow;": '\U000021AD',
- "leftthreetimes;": '\U000022CB',
- "leg;": '\U000022DA',
- "leq;": '\U00002264',
- "leqq;": '\U00002266',
- "leqslant;": '\U00002A7D',
- "les;": '\U00002A7D',
- "lescc;": '\U00002AA8',
- "lesdot;": '\U00002A7F',
- "lesdoto;": '\U00002A81',
- "lesdotor;": '\U00002A83',
- "lesges;": '\U00002A93',
- "lessapprox;": '\U00002A85',
- "lessdot;": '\U000022D6',
- "lesseqgtr;": '\U000022DA',
- "lesseqqgtr;": '\U00002A8B',
- "lessgtr;": '\U00002276',
- "lesssim;": '\U00002272',
- "lfisht;": '\U0000297C',
- "lfloor;": '\U0000230A',
- "lfr;": '\U0001D529',
- "lg;": '\U00002276',
- "lgE;": '\U00002A91',
- "lhard;": '\U000021BD',
- "lharu;": '\U000021BC',
- "lharul;": '\U0000296A',
- "lhblk;": '\U00002584',
- "ljcy;": '\U00000459',
- "ll;": '\U0000226A',
- "llarr;": '\U000021C7',
- "llcorner;": '\U0000231E',
- "llhard;": '\U0000296B',
- "lltri;": '\U000025FA',
- "lmidot;": '\U00000140',
- "lmoust;": '\U000023B0',
- "lmoustache;": '\U000023B0',
- "lnE;": '\U00002268',
- "lnap;": '\U00002A89',
- "lnapprox;": '\U00002A89',
- "lne;": '\U00002A87',
- "lneq;": '\U00002A87',
- "lneqq;": '\U00002268',
- "lnsim;": '\U000022E6',
- "loang;": '\U000027EC',
- "loarr;": '\U000021FD',
- "lobrk;": '\U000027E6',
- "longleftarrow;": '\U000027F5',
- "longleftrightarrow;": '\U000027F7',
- "longmapsto;": '\U000027FC',
- "longrightarrow;": '\U000027F6',
- "looparrowleft;": '\U000021AB',
- "looparrowright;": '\U000021AC',
- "lopar;": '\U00002985',
- "lopf;": '\U0001D55D',
- "loplus;": '\U00002A2D',
- "lotimes;": '\U00002A34',
- "lowast;": '\U00002217',
- "lowbar;": '\U0000005F',
- "loz;": '\U000025CA',
- "lozenge;": '\U000025CA',
- "lozf;": '\U000029EB',
- "lpar;": '\U00000028',
- "lparlt;": '\U00002993',
- "lrarr;": '\U000021C6',
- "lrcorner;": '\U0000231F',
- "lrhar;": '\U000021CB',
- "lrhard;": '\U0000296D',
- "lrm;": '\U0000200E',
- "lrtri;": '\U000022BF',
- "lsaquo;": '\U00002039',
- "lscr;": '\U0001D4C1',
- "lsh;": '\U000021B0',
- "lsim;": '\U00002272',
- "lsime;": '\U00002A8D',
- "lsimg;": '\U00002A8F',
- "lsqb;": '\U0000005B',
- "lsquo;": '\U00002018',
- "lsquor;": '\U0000201A',
- "lstrok;": '\U00000142',
- "lt;": '\U0000003C',
- "ltcc;": '\U00002AA6',
- "ltcir;": '\U00002A79',
- "ltdot;": '\U000022D6',
- "lthree;": '\U000022CB',
- "ltimes;": '\U000022C9',
- "ltlarr;": '\U00002976',
- "ltquest;": '\U00002A7B',
- "ltrPar;": '\U00002996',
- "ltri;": '\U000025C3',
- "ltrie;": '\U000022B4',
- "ltrif;": '\U000025C2',
- "lurdshar;": '\U0000294A',
- "luruhar;": '\U00002966',
- "mDDot;": '\U0000223A',
- "macr;": '\U000000AF',
- "male;": '\U00002642',
- "malt;": '\U00002720',
- "maltese;": '\U00002720',
- "map;": '\U000021A6',
- "mapsto;": '\U000021A6',
- "mapstodown;": '\U000021A7',
- "mapstoleft;": '\U000021A4',
- "mapstoup;": '\U000021A5',
- "marker;": '\U000025AE',
- "mcomma;": '\U00002A29',
- "mcy;": '\U0000043C',
- "mdash;": '\U00002014',
- "measuredangle;": '\U00002221',
- "mfr;": '\U0001D52A',
- "mho;": '\U00002127',
- "micro;": '\U000000B5',
- "mid;": '\U00002223',
- "midast;": '\U0000002A',
- "midcir;": '\U00002AF0',
- "middot;": '\U000000B7',
- "minus;": '\U00002212',
- "minusb;": '\U0000229F',
- "minusd;": '\U00002238',
- "minusdu;": '\U00002A2A',
- "mlcp;": '\U00002ADB',
- "mldr;": '\U00002026',
- "mnplus;": '\U00002213',
- "models;": '\U000022A7',
- "mopf;": '\U0001D55E',
- "mp;": '\U00002213',
- "mscr;": '\U0001D4C2',
- "mstpos;": '\U0000223E',
- "mu;": '\U000003BC',
- "multimap;": '\U000022B8',
- "mumap;": '\U000022B8',
- "nLeftarrow;": '\U000021CD',
- "nLeftrightarrow;": '\U000021CE',
- "nRightarrow;": '\U000021CF',
- "nVDash;": '\U000022AF',
- "nVdash;": '\U000022AE',
- "nabla;": '\U00002207',
- "nacute;": '\U00000144',
- "nap;": '\U00002249',
- "napos;": '\U00000149',
- "napprox;": '\U00002249',
- "natur;": '\U0000266E',
- "natural;": '\U0000266E',
- "naturals;": '\U00002115',
- "nbsp;": '\U000000A0',
- "ncap;": '\U00002A43',
- "ncaron;": '\U00000148',
- "ncedil;": '\U00000146',
- "ncong;": '\U00002247',
- "ncup;": '\U00002A42',
- "ncy;": '\U0000043D',
- "ndash;": '\U00002013',
- "ne;": '\U00002260',
- "neArr;": '\U000021D7',
- "nearhk;": '\U00002924',
- "nearr;": '\U00002197',
- "nearrow;": '\U00002197',
- "nequiv;": '\U00002262',
- "nesear;": '\U00002928',
- "nexist;": '\U00002204',
- "nexists;": '\U00002204',
- "nfr;": '\U0001D52B',
- "nge;": '\U00002271',
- "ngeq;": '\U00002271',
- "ngsim;": '\U00002275',
- "ngt;": '\U0000226F',
- "ngtr;": '\U0000226F',
- "nhArr;": '\U000021CE',
- "nharr;": '\U000021AE',
- "nhpar;": '\U00002AF2',
- "ni;": '\U0000220B',
- "nis;": '\U000022FC',
- "nisd;": '\U000022FA',
- "niv;": '\U0000220B',
- "njcy;": '\U0000045A',
- "nlArr;": '\U000021CD',
- "nlarr;": '\U0000219A',
- "nldr;": '\U00002025',
- "nle;": '\U00002270',
- "nleftarrow;": '\U0000219A',
- "nleftrightarrow;": '\U000021AE',
- "nleq;": '\U00002270',
- "nless;": '\U0000226E',
- "nlsim;": '\U00002274',
- "nlt;": '\U0000226E',
- "nltri;": '\U000022EA',
- "nltrie;": '\U000022EC',
- "nmid;": '\U00002224',
- "nopf;": '\U0001D55F',
- "not;": '\U000000AC',
- "notin;": '\U00002209',
- "notinva;": '\U00002209',
- "notinvb;": '\U000022F7',
- "notinvc;": '\U000022F6',
- "notni;": '\U0000220C',
- "notniva;": '\U0000220C',
- "notnivb;": '\U000022FE',
- "notnivc;": '\U000022FD',
- "npar;": '\U00002226',
- "nparallel;": '\U00002226',
- "npolint;": '\U00002A14',
- "npr;": '\U00002280',
- "nprcue;": '\U000022E0',
- "nprec;": '\U00002280',
- "nrArr;": '\U000021CF',
- "nrarr;": '\U0000219B',
- "nrightarrow;": '\U0000219B',
- "nrtri;": '\U000022EB',
- "nrtrie;": '\U000022ED',
- "nsc;": '\U00002281',
- "nsccue;": '\U000022E1',
- "nscr;": '\U0001D4C3',
- "nshortmid;": '\U00002224',
- "nshortparallel;": '\U00002226',
- "nsim;": '\U00002241',
- "nsime;": '\U00002244',
- "nsimeq;": '\U00002244',
- "nsmid;": '\U00002224',
- "nspar;": '\U00002226',
- "nsqsube;": '\U000022E2',
- "nsqsupe;": '\U000022E3',
- "nsub;": '\U00002284',
- "nsube;": '\U00002288',
- "nsubseteq;": '\U00002288',
- "nsucc;": '\U00002281',
- "nsup;": '\U00002285',
- "nsupe;": '\U00002289',
- "nsupseteq;": '\U00002289',
- "ntgl;": '\U00002279',
- "ntilde;": '\U000000F1',
- "ntlg;": '\U00002278',
- "ntriangleleft;": '\U000022EA',
- "ntrianglelefteq;": '\U000022EC',
- "ntriangleright;": '\U000022EB',
- "ntrianglerighteq;": '\U000022ED',
- "nu;": '\U000003BD',
- "num;": '\U00000023',
- "numero;": '\U00002116',
- "numsp;": '\U00002007',
- "nvDash;": '\U000022AD',
- "nvHarr;": '\U00002904',
- "nvdash;": '\U000022AC',
- "nvinfin;": '\U000029DE',
- "nvlArr;": '\U00002902',
- "nvrArr;": '\U00002903',
- "nwArr;": '\U000021D6',
- "nwarhk;": '\U00002923',
- "nwarr;": '\U00002196',
- "nwarrow;": '\U00002196',
- "nwnear;": '\U00002927',
- "oS;": '\U000024C8',
- "oacute;": '\U000000F3',
- "oast;": '\U0000229B',
- "ocir;": '\U0000229A',
- "ocirc;": '\U000000F4',
- "ocy;": '\U0000043E',
- "odash;": '\U0000229D',
- "odblac;": '\U00000151',
- "odiv;": '\U00002A38',
- "odot;": '\U00002299',
- "odsold;": '\U000029BC',
- "oelig;": '\U00000153',
- "ofcir;": '\U000029BF',
- "ofr;": '\U0001D52C',
- "ogon;": '\U000002DB',
- "ograve;": '\U000000F2',
- "ogt;": '\U000029C1',
- "ohbar;": '\U000029B5',
- "ohm;": '\U000003A9',
- "oint;": '\U0000222E',
- "olarr;": '\U000021BA',
- "olcir;": '\U000029BE',
- "olcross;": '\U000029BB',
- "oline;": '\U0000203E',
- "olt;": '\U000029C0',
- "omacr;": '\U0000014D',
- "omega;": '\U000003C9',
- "omicron;": '\U000003BF',
- "omid;": '\U000029B6',
- "ominus;": '\U00002296',
- "oopf;": '\U0001D560',
- "opar;": '\U000029B7',
- "operp;": '\U000029B9',
- "oplus;": '\U00002295',
- "or;": '\U00002228',
- "orarr;": '\U000021BB',
- "ord;": '\U00002A5D',
- "order;": '\U00002134',
- "orderof;": '\U00002134',
- "ordf;": '\U000000AA',
- "ordm;": '\U000000BA',
- "origof;": '\U000022B6',
- "oror;": '\U00002A56',
- "orslope;": '\U00002A57',
- "orv;": '\U00002A5B',
- "oscr;": '\U00002134',
- "oslash;": '\U000000F8',
- "osol;": '\U00002298',
- "otilde;": '\U000000F5',
- "otimes;": '\U00002297',
- "otimesas;": '\U00002A36',
- "ouml;": '\U000000F6',
- "ovbar;": '\U0000233D',
- "par;": '\U00002225',
- "para;": '\U000000B6',
- "parallel;": '\U00002225',
- "parsim;": '\U00002AF3',
- "parsl;": '\U00002AFD',
- "part;": '\U00002202',
- "pcy;": '\U0000043F',
- "percnt;": '\U00000025',
- "period;": '\U0000002E',
- "permil;": '\U00002030',
- "perp;": '\U000022A5',
- "pertenk;": '\U00002031',
- "pfr;": '\U0001D52D',
- "phi;": '\U000003C6',
- "phiv;": '\U000003D5',
- "phmmat;": '\U00002133',
- "phone;": '\U0000260E',
- "pi;": '\U000003C0',
- "pitchfork;": '\U000022D4',
- "piv;": '\U000003D6',
- "planck;": '\U0000210F',
- "planckh;": '\U0000210E',
- "plankv;": '\U0000210F',
- "plus;": '\U0000002B',
- "plusacir;": '\U00002A23',
- "plusb;": '\U0000229E',
- "pluscir;": '\U00002A22',
- "plusdo;": '\U00002214',
- "plusdu;": '\U00002A25',
- "pluse;": '\U00002A72',
- "plusmn;": '\U000000B1',
- "plussim;": '\U00002A26',
- "plustwo;": '\U00002A27',
- "pm;": '\U000000B1',
- "pointint;": '\U00002A15',
- "popf;": '\U0001D561',
- "pound;": '\U000000A3',
- "pr;": '\U0000227A',
- "prE;": '\U00002AB3',
- "prap;": '\U00002AB7',
- "prcue;": '\U0000227C',
- "pre;": '\U00002AAF',
- "prec;": '\U0000227A',
- "precapprox;": '\U00002AB7',
- "preccurlyeq;": '\U0000227C',
- "preceq;": '\U00002AAF',
- "precnapprox;": '\U00002AB9',
- "precneqq;": '\U00002AB5',
- "precnsim;": '\U000022E8',
- "precsim;": '\U0000227E',
- "prime;": '\U00002032',
- "primes;": '\U00002119',
- "prnE;": '\U00002AB5',
- "prnap;": '\U00002AB9',
- "prnsim;": '\U000022E8',
- "prod;": '\U0000220F',
- "profalar;": '\U0000232E',
- "profline;": '\U00002312',
- "profsurf;": '\U00002313',
- "prop;": '\U0000221D',
- "propto;": '\U0000221D',
- "prsim;": '\U0000227E',
- "prurel;": '\U000022B0',
- "pscr;": '\U0001D4C5',
- "psi;": '\U000003C8',
- "puncsp;": '\U00002008',
- "qfr;": '\U0001D52E',
- "qint;": '\U00002A0C',
- "qopf;": '\U0001D562',
- "qprime;": '\U00002057',
- "qscr;": '\U0001D4C6',
- "quaternions;": '\U0000210D',
- "quatint;": '\U00002A16',
- "quest;": '\U0000003F',
- "questeq;": '\U0000225F',
- "quot;": '\U00000022',
- "rAarr;": '\U000021DB',
- "rArr;": '\U000021D2',
- "rAtail;": '\U0000291C',
- "rBarr;": '\U0000290F',
- "rHar;": '\U00002964',
- "racute;": '\U00000155',
- "radic;": '\U0000221A',
- "raemptyv;": '\U000029B3',
- "rang;": '\U000027E9',
- "rangd;": '\U00002992',
- "range;": '\U000029A5',
- "rangle;": '\U000027E9',
- "raquo;": '\U000000BB',
- "rarr;": '\U00002192',
- "rarrap;": '\U00002975',
- "rarrb;": '\U000021E5',
- "rarrbfs;": '\U00002920',
- "rarrc;": '\U00002933',
- "rarrfs;": '\U0000291E',
- "rarrhk;": '\U000021AA',
- "rarrlp;": '\U000021AC',
- "rarrpl;": '\U00002945',
- "rarrsim;": '\U00002974',
- "rarrtl;": '\U000021A3',
- "rarrw;": '\U0000219D',
- "ratail;": '\U0000291A',
- "ratio;": '\U00002236',
- "rationals;": '\U0000211A',
- "rbarr;": '\U0000290D',
- "rbbrk;": '\U00002773',
- "rbrace;": '\U0000007D',
- "rbrack;": '\U0000005D',
- "rbrke;": '\U0000298C',
- "rbrksld;": '\U0000298E',
- "rbrkslu;": '\U00002990',
- "rcaron;": '\U00000159',
- "rcedil;": '\U00000157',
- "rceil;": '\U00002309',
- "rcub;": '\U0000007D',
- "rcy;": '\U00000440',
- "rdca;": '\U00002937',
- "rdldhar;": '\U00002969',
- "rdquo;": '\U0000201D',
- "rdquor;": '\U0000201D',
- "rdsh;": '\U000021B3',
- "real;": '\U0000211C',
- "realine;": '\U0000211B',
- "realpart;": '\U0000211C',
- "reals;": '\U0000211D',
- "rect;": '\U000025AD',
- "reg;": '\U000000AE',
- "rfisht;": '\U0000297D',
- "rfloor;": '\U0000230B',
- "rfr;": '\U0001D52F',
- "rhard;": '\U000021C1',
- "rharu;": '\U000021C0',
- "rharul;": '\U0000296C',
- "rho;": '\U000003C1',
- "rhov;": '\U000003F1',
- "rightarrow;": '\U00002192',
- "rightarrowtail;": '\U000021A3',
- "rightharpoondown;": '\U000021C1',
- "rightharpoonup;": '\U000021C0',
- "rightleftarrows;": '\U000021C4',
- "rightleftharpoons;": '\U000021CC',
- "rightrightarrows;": '\U000021C9',
- "rightsquigarrow;": '\U0000219D',
- "rightthreetimes;": '\U000022CC',
- "ring;": '\U000002DA',
- "risingdotseq;": '\U00002253',
- "rlarr;": '\U000021C4',
- "rlhar;": '\U000021CC',
- "rlm;": '\U0000200F',
- "rmoust;": '\U000023B1',
- "rmoustache;": '\U000023B1',
- "rnmid;": '\U00002AEE',
- "roang;": '\U000027ED',
- "roarr;": '\U000021FE',
- "robrk;": '\U000027E7',
- "ropar;": '\U00002986',
- "ropf;": '\U0001D563',
- "roplus;": '\U00002A2E',
- "rotimes;": '\U00002A35',
- "rpar;": '\U00000029',
- "rpargt;": '\U00002994',
- "rppolint;": '\U00002A12',
- "rrarr;": '\U000021C9',
- "rsaquo;": '\U0000203A',
- "rscr;": '\U0001D4C7',
- "rsh;": '\U000021B1',
- "rsqb;": '\U0000005D',
- "rsquo;": '\U00002019',
- "rsquor;": '\U00002019',
- "rthree;": '\U000022CC',
- "rtimes;": '\U000022CA',
- "rtri;": '\U000025B9',
- "rtrie;": '\U000022B5',
- "rtrif;": '\U000025B8',
- "rtriltri;": '\U000029CE',
- "ruluhar;": '\U00002968',
- "rx;": '\U0000211E',
- "sacute;": '\U0000015B',
- "sbquo;": '\U0000201A',
- "sc;": '\U0000227B',
- "scE;": '\U00002AB4',
- "scap;": '\U00002AB8',
- "scaron;": '\U00000161',
- "sccue;": '\U0000227D',
- "sce;": '\U00002AB0',
- "scedil;": '\U0000015F',
- "scirc;": '\U0000015D',
- "scnE;": '\U00002AB6',
- "scnap;": '\U00002ABA',
- "scnsim;": '\U000022E9',
- "scpolint;": '\U00002A13',
- "scsim;": '\U0000227F',
- "scy;": '\U00000441',
- "sdot;": '\U000022C5',
- "sdotb;": '\U000022A1',
- "sdote;": '\U00002A66',
- "seArr;": '\U000021D8',
- "searhk;": '\U00002925',
- "searr;": '\U00002198',
- "searrow;": '\U00002198',
- "sect;": '\U000000A7',
- "semi;": '\U0000003B',
- "seswar;": '\U00002929',
- "setminus;": '\U00002216',
- "setmn;": '\U00002216',
- "sext;": '\U00002736',
- "sfr;": '\U0001D530',
- "sfrown;": '\U00002322',
- "sharp;": '\U0000266F',
- "shchcy;": '\U00000449',
- "shcy;": '\U00000448',
- "shortmid;": '\U00002223',
- "shortparallel;": '\U00002225',
- "shy;": '\U000000AD',
- "sigma;": '\U000003C3',
- "sigmaf;": '\U000003C2',
- "sigmav;": '\U000003C2',
- "sim;": '\U0000223C',
- "simdot;": '\U00002A6A',
- "sime;": '\U00002243',
- "simeq;": '\U00002243',
- "simg;": '\U00002A9E',
- "simgE;": '\U00002AA0',
- "siml;": '\U00002A9D',
- "simlE;": '\U00002A9F',
- "simne;": '\U00002246',
- "simplus;": '\U00002A24',
- "simrarr;": '\U00002972',
- "slarr;": '\U00002190',
- "smallsetminus;": '\U00002216',
- "smashp;": '\U00002A33',
- "smeparsl;": '\U000029E4',
- "smid;": '\U00002223',
- "smile;": '\U00002323',
- "smt;": '\U00002AAA',
- "smte;": '\U00002AAC',
- "softcy;": '\U0000044C',
- "sol;": '\U0000002F',
- "solb;": '\U000029C4',
- "solbar;": '\U0000233F',
- "sopf;": '\U0001D564',
- "spades;": '\U00002660',
- "spadesuit;": '\U00002660',
- "spar;": '\U00002225',
- "sqcap;": '\U00002293',
- "sqcup;": '\U00002294',
- "sqsub;": '\U0000228F',
- "sqsube;": '\U00002291',
- "sqsubset;": '\U0000228F',
- "sqsubseteq;": '\U00002291',
- "sqsup;": '\U00002290',
- "sqsupe;": '\U00002292',
- "sqsupset;": '\U00002290',
- "sqsupseteq;": '\U00002292',
- "squ;": '\U000025A1',
- "square;": '\U000025A1',
- "squarf;": '\U000025AA',
- "squf;": '\U000025AA',
- "srarr;": '\U00002192',
- "sscr;": '\U0001D4C8',
- "ssetmn;": '\U00002216',
- "ssmile;": '\U00002323',
- "sstarf;": '\U000022C6',
- "star;": '\U00002606',
- "starf;": '\U00002605',
- "straightepsilon;": '\U000003F5',
- "straightphi;": '\U000003D5',
- "strns;": '\U000000AF',
- "sub;": '\U00002282',
- "subE;": '\U00002AC5',
- "subdot;": '\U00002ABD',
- "sube;": '\U00002286',
- "subedot;": '\U00002AC3',
- "submult;": '\U00002AC1',
- "subnE;": '\U00002ACB',
- "subne;": '\U0000228A',
- "subplus;": '\U00002ABF',
- "subrarr;": '\U00002979',
- "subset;": '\U00002282',
- "subseteq;": '\U00002286',
- "subseteqq;": '\U00002AC5',
- "subsetneq;": '\U0000228A',
- "subsetneqq;": '\U00002ACB',
- "subsim;": '\U00002AC7',
- "subsub;": '\U00002AD5',
- "subsup;": '\U00002AD3',
- "succ;": '\U0000227B',
- "succapprox;": '\U00002AB8',
- "succcurlyeq;": '\U0000227D',
- "succeq;": '\U00002AB0',
- "succnapprox;": '\U00002ABA',
- "succneqq;": '\U00002AB6',
- "succnsim;": '\U000022E9',
- "succsim;": '\U0000227F',
- "sum;": '\U00002211',
- "sung;": '\U0000266A',
- "sup;": '\U00002283',
- "sup1;": '\U000000B9',
- "sup2;": '\U000000B2',
- "sup3;": '\U000000B3',
- "supE;": '\U00002AC6',
- "supdot;": '\U00002ABE',
- "supdsub;": '\U00002AD8',
- "supe;": '\U00002287',
- "supedot;": '\U00002AC4',
- "suphsol;": '\U000027C9',
- "suphsub;": '\U00002AD7',
- "suplarr;": '\U0000297B',
- "supmult;": '\U00002AC2',
- "supnE;": '\U00002ACC',
- "supne;": '\U0000228B',
- "supplus;": '\U00002AC0',
- "supset;": '\U00002283',
- "supseteq;": '\U00002287',
- "supseteqq;": '\U00002AC6',
- "supsetneq;": '\U0000228B',
- "supsetneqq;": '\U00002ACC',
- "supsim;": '\U00002AC8',
- "supsub;": '\U00002AD4',
- "supsup;": '\U00002AD6',
- "swArr;": '\U000021D9',
- "swarhk;": '\U00002926',
- "swarr;": '\U00002199',
- "swarrow;": '\U00002199',
- "swnwar;": '\U0000292A',
- "szlig;": '\U000000DF',
- "target;": '\U00002316',
- "tau;": '\U000003C4',
- "tbrk;": '\U000023B4',
- "tcaron;": '\U00000165',
- "tcedil;": '\U00000163',
- "tcy;": '\U00000442',
- "tdot;": '\U000020DB',
- "telrec;": '\U00002315',
- "tfr;": '\U0001D531',
- "there4;": '\U00002234',
- "therefore;": '\U00002234',
- "theta;": '\U000003B8',
- "thetasym;": '\U000003D1',
- "thetav;": '\U000003D1',
- "thickapprox;": '\U00002248',
- "thicksim;": '\U0000223C',
- "thinsp;": '\U00002009',
- "thkap;": '\U00002248',
- "thksim;": '\U0000223C',
- "thorn;": '\U000000FE',
- "tilde;": '\U000002DC',
- "times;": '\U000000D7',
- "timesb;": '\U000022A0',
- "timesbar;": '\U00002A31',
- "timesd;": '\U00002A30',
- "tint;": '\U0000222D',
- "toea;": '\U00002928',
- "top;": '\U000022A4',
- "topbot;": '\U00002336',
- "topcir;": '\U00002AF1',
- "topf;": '\U0001D565',
- "topfork;": '\U00002ADA',
- "tosa;": '\U00002929',
- "tprime;": '\U00002034',
- "trade;": '\U00002122',
- "triangle;": '\U000025B5',
- "triangledown;": '\U000025BF',
- "triangleleft;": '\U000025C3',
- "trianglelefteq;": '\U000022B4',
- "triangleq;": '\U0000225C',
- "triangleright;": '\U000025B9',
- "trianglerighteq;": '\U000022B5',
- "tridot;": '\U000025EC',
- "trie;": '\U0000225C',
- "triminus;": '\U00002A3A',
- "triplus;": '\U00002A39',
- "trisb;": '\U000029CD',
- "tritime;": '\U00002A3B',
- "trpezium;": '\U000023E2',
- "tscr;": '\U0001D4C9',
- "tscy;": '\U00000446',
- "tshcy;": '\U0000045B',
- "tstrok;": '\U00000167',
- "twixt;": '\U0000226C',
- "twoheadleftarrow;": '\U0000219E',
- "twoheadrightarrow;": '\U000021A0',
- "uArr;": '\U000021D1',
- "uHar;": '\U00002963',
- "uacute;": '\U000000FA',
- "uarr;": '\U00002191',
- "ubrcy;": '\U0000045E',
- "ubreve;": '\U0000016D',
- "ucirc;": '\U000000FB',
- "ucy;": '\U00000443',
- "udarr;": '\U000021C5',
- "udblac;": '\U00000171',
- "udhar;": '\U0000296E',
- "ufisht;": '\U0000297E',
- "ufr;": '\U0001D532',
- "ugrave;": '\U000000F9',
- "uharl;": '\U000021BF',
- "uharr;": '\U000021BE',
- "uhblk;": '\U00002580',
- "ulcorn;": '\U0000231C',
- "ulcorner;": '\U0000231C',
- "ulcrop;": '\U0000230F',
- "ultri;": '\U000025F8',
- "umacr;": '\U0000016B',
- "uml;": '\U000000A8',
- "uogon;": '\U00000173',
- "uopf;": '\U0001D566',
- "uparrow;": '\U00002191',
- "updownarrow;": '\U00002195',
- "upharpoonleft;": '\U000021BF',
- "upharpoonright;": '\U000021BE',
- "uplus;": '\U0000228E',
- "upsi;": '\U000003C5',
- "upsih;": '\U000003D2',
- "upsilon;": '\U000003C5',
- "upuparrows;": '\U000021C8',
- "urcorn;": '\U0000231D',
- "urcorner;": '\U0000231D',
- "urcrop;": '\U0000230E',
- "uring;": '\U0000016F',
- "urtri;": '\U000025F9',
- "uscr;": '\U0001D4CA',
- "utdot;": '\U000022F0',
- "utilde;": '\U00000169',
- "utri;": '\U000025B5',
- "utrif;": '\U000025B4',
- "uuarr;": '\U000021C8',
- "uuml;": '\U000000FC',
- "uwangle;": '\U000029A7',
- "vArr;": '\U000021D5',
- "vBar;": '\U00002AE8',
- "vBarv;": '\U00002AE9',
- "vDash;": '\U000022A8',
- "vangrt;": '\U0000299C',
- "varepsilon;": '\U000003F5',
- "varkappa;": '\U000003F0',
- "varnothing;": '\U00002205',
- "varphi;": '\U000003D5',
- "varpi;": '\U000003D6',
- "varpropto;": '\U0000221D',
- "varr;": '\U00002195',
- "varrho;": '\U000003F1',
- "varsigma;": '\U000003C2',
- "vartheta;": '\U000003D1',
- "vartriangleleft;": '\U000022B2',
- "vartriangleright;": '\U000022B3',
- "vcy;": '\U00000432',
- "vdash;": '\U000022A2',
- "vee;": '\U00002228',
- "veebar;": '\U000022BB',
- "veeeq;": '\U0000225A',
- "vellip;": '\U000022EE',
- "verbar;": '\U0000007C',
- "vert;": '\U0000007C',
- "vfr;": '\U0001D533',
- "vltri;": '\U000022B2',
- "vopf;": '\U0001D567',
- "vprop;": '\U0000221D',
- "vrtri;": '\U000022B3',
- "vscr;": '\U0001D4CB',
- "vzigzag;": '\U0000299A',
- "wcirc;": '\U00000175',
- "wedbar;": '\U00002A5F',
- "wedge;": '\U00002227',
- "wedgeq;": '\U00002259',
- "weierp;": '\U00002118',
- "wfr;": '\U0001D534',
- "wopf;": '\U0001D568',
- "wp;": '\U00002118',
- "wr;": '\U00002240',
- "wreath;": '\U00002240',
- "wscr;": '\U0001D4CC',
- "xcap;": '\U000022C2',
- "xcirc;": '\U000025EF',
- "xcup;": '\U000022C3',
- "xdtri;": '\U000025BD',
- "xfr;": '\U0001D535',
- "xhArr;": '\U000027FA',
- "xharr;": '\U000027F7',
- "xi;": '\U000003BE',
- "xlArr;": '\U000027F8',
- "xlarr;": '\U000027F5',
- "xmap;": '\U000027FC',
- "xnis;": '\U000022FB',
- "xodot;": '\U00002A00',
- "xopf;": '\U0001D569',
- "xoplus;": '\U00002A01',
- "xotime;": '\U00002A02',
- "xrArr;": '\U000027F9',
- "xrarr;": '\U000027F6',
- "xscr;": '\U0001D4CD',
- "xsqcup;": '\U00002A06',
- "xuplus;": '\U00002A04',
- "xutri;": '\U000025B3',
- "xvee;": '\U000022C1',
- "xwedge;": '\U000022C0',
- "yacute;": '\U000000FD',
- "yacy;": '\U0000044F',
- "ycirc;": '\U00000177',
- "ycy;": '\U0000044B',
- "yen;": '\U000000A5',
- "yfr;": '\U0001D536',
- "yicy;": '\U00000457',
- "yopf;": '\U0001D56A',
- "yscr;": '\U0001D4CE',
- "yucy;": '\U0000044E',
- "yuml;": '\U000000FF',
- "zacute;": '\U0000017A',
- "zcaron;": '\U0000017E',
- "zcy;": '\U00000437',
- "zdot;": '\U0000017C',
- "zeetrf;": '\U00002128',
- "zeta;": '\U000003B6',
- "zfr;": '\U0001D537',
- "zhcy;": '\U00000436',
- "zigrarr;": '\U000021DD',
- "zopf;": '\U0001D56B',
- "zscr;": '\U0001D4CF',
- "zwj;": '\U0000200D',
- "zwnj;": '\U0000200C',
- "AElig": '\U000000C6',
- "AMP": '\U00000026',
- "Aacute": '\U000000C1',
- "Acirc": '\U000000C2',
- "Agrave": '\U000000C0',
- "Aring": '\U000000C5',
- "Atilde": '\U000000C3',
- "Auml": '\U000000C4',
- "COPY": '\U000000A9',
- "Ccedil": '\U000000C7',
- "ETH": '\U000000D0',
- "Eacute": '\U000000C9',
- "Ecirc": '\U000000CA',
- "Egrave": '\U000000C8',
- "Euml": '\U000000CB',
- "GT": '\U0000003E',
- "Iacute": '\U000000CD',
- "Icirc": '\U000000CE',
- "Igrave": '\U000000CC',
- "Iuml": '\U000000CF',
- "LT": '\U0000003C',
- "Ntilde": '\U000000D1',
- "Oacute": '\U000000D3',
- "Ocirc": '\U000000D4',
- "Ograve": '\U000000D2',
- "Oslash": '\U000000D8',
- "Otilde": '\U000000D5',
- "Ouml": '\U000000D6',
- "QUOT": '\U00000022',
- "REG": '\U000000AE',
- "THORN": '\U000000DE',
- "Uacute": '\U000000DA',
- "Ucirc": '\U000000DB',
- "Ugrave": '\U000000D9',
- "Uuml": '\U000000DC',
- "Yacute": '\U000000DD',
- "aacute": '\U000000E1',
- "acirc": '\U000000E2',
- "acute": '\U000000B4',
- "aelig": '\U000000E6',
- "agrave": '\U000000E0',
- "amp": '\U00000026',
- "aring": '\U000000E5',
- "atilde": '\U000000E3',
- "auml": '\U000000E4',
- "brvbar": '\U000000A6',
- "ccedil": '\U000000E7',
- "cedil": '\U000000B8',
- "cent": '\U000000A2',
- "copy": '\U000000A9',
- "curren": '\U000000A4',
- "deg": '\U000000B0',
- "divide": '\U000000F7',
- "eacute": '\U000000E9',
- "ecirc": '\U000000EA',
- "egrave": '\U000000E8',
- "eth": '\U000000F0',
- "euml": '\U000000EB',
- "frac12": '\U000000BD',
- "frac14": '\U000000BC',
- "frac34": '\U000000BE',
- "gt": '\U0000003E',
- "iacute": '\U000000ED',
- "icirc": '\U000000EE',
- "iexcl": '\U000000A1',
- "igrave": '\U000000EC',
- "iquest": '\U000000BF',
- "iuml": '\U000000EF',
- "laquo": '\U000000AB',
- "lt": '\U0000003C',
- "macr": '\U000000AF',
- "micro": '\U000000B5',
- "middot": '\U000000B7',
- "nbsp": '\U000000A0',
- "not": '\U000000AC',
- "ntilde": '\U000000F1',
- "oacute": '\U000000F3',
- "ocirc": '\U000000F4',
- "ograve": '\U000000F2',
- "ordf": '\U000000AA',
- "ordm": '\U000000BA',
- "oslash": '\U000000F8',
- "otilde": '\U000000F5',
- "ouml": '\U000000F6',
- "para": '\U000000B6',
- "plusmn": '\U000000B1',
- "pound": '\U000000A3',
- "quot": '\U00000022',
- "raquo": '\U000000BB',
- "reg": '\U000000AE',
- "sect": '\U000000A7',
- "shy": '\U000000AD',
- "sup1": '\U000000B9',
- "sup2": '\U000000B2',
- "sup3": '\U000000B3',
- "szlig": '\U000000DF',
- "thorn": '\U000000FE',
- "times": '\U000000D7',
- "uacute": '\U000000FA',
- "ucirc": '\U000000FB',
- "ugrave": '\U000000F9',
- "uml": '\U000000A8',
- "uuml": '\U000000FC',
- "yacute": '\U000000FD',
- "yen": '\U000000A5',
- "yuml": '\U000000FF',
+ "Cross;": '\U00002A2F',
+ "Cscr;": '\U0001D49E',
+ "Cup;": '\U000022D3',
+ "CupCap;": '\U0000224D',
+ "DD;": '\U00002145',
+ "DDotrahd;": '\U00002911',
+ "DJcy;": '\U00000402',
+ "DScy;": '\U00000405',
+ "DZcy;": '\U0000040F',
+ "Dagger;": '\U00002021',
+ "Darr;": '\U000021A1',
+ "Dashv;": '\U00002AE4',
+ "Dcaron;": '\U0000010E',
+ "Dcy;": '\U00000414',
+ "Del;": '\U00002207',
+ "Delta;": '\U00000394',
+ "Dfr;": '\U0001D507',
+ "DiacriticalAcute;": '\U000000B4',
+ "DiacriticalDot;": '\U000002D9',
+ "DiacriticalDoubleAcute;": '\U000002DD',
+ "DiacriticalGrave;": '\U00000060',
+ "DiacriticalTilde;": '\U000002DC',
+ "Diamond;": '\U000022C4',
+ "DifferentialD;": '\U00002146',
+ "Dopf;": '\U0001D53B',
+ "Dot;": '\U000000A8',
+ "DotDot;": '\U000020DC',
+ "DotEqual;": '\U00002250',
+ "DoubleContourIntegral;": '\U0000222F',
+ "DoubleDot;": '\U000000A8',
+ "DoubleDownArrow;": '\U000021D3',
+ "DoubleLeftArrow;": '\U000021D0',
+ "DoubleLeftRightArrow;": '\U000021D4',
+ "DoubleLeftTee;": '\U00002AE4',
+ "DoubleLongLeftArrow;": '\U000027F8',
+ "DoubleLongLeftRightArrow;": '\U000027FA',
+ "DoubleLongRightArrow;": '\U000027F9',
+ "DoubleRightArrow;": '\U000021D2',
+ "DoubleRightTee;": '\U000022A8',
+ "DoubleUpArrow;": '\U000021D1',
+ "DoubleUpDownArrow;": '\U000021D5',
+ "DoubleVerticalBar;": '\U00002225',
+ "DownArrow;": '\U00002193',
+ "DownArrowBar;": '\U00002913',
+ "DownArrowUpArrow;": '\U000021F5',
+ "DownBreve;": '\U00000311',
+ "DownLeftRightVector;": '\U00002950',
+ "DownLeftTeeVector;": '\U0000295E',
+ "DownLeftVector;": '\U000021BD',
+ "DownLeftVectorBar;": '\U00002956',
+ "DownRightTeeVector;": '\U0000295F',
+ "DownRightVector;": '\U000021C1',
+ "DownRightVectorBar;": '\U00002957',
+ "DownTee;": '\U000022A4',
+ "DownTeeArrow;": '\U000021A7',
+ "Downarrow;": '\U000021D3',
+ "Dscr;": '\U0001D49F',
+ "Dstrok;": '\U00000110',
+ "ENG;": '\U0000014A',
+ "ETH;": '\U000000D0',
+ "Eacute;": '\U000000C9',
+ "Ecaron;": '\U0000011A',
+ "Ecirc;": '\U000000CA',
+ "Ecy;": '\U0000042D',
+ "Edot;": '\U00000116',
+ "Efr;": '\U0001D508',
+ "Egrave;": '\U000000C8',
+ "Element;": '\U00002208',
+ "Emacr;": '\U00000112',
+ "EmptySmallSquare;": '\U000025FB',
+ "EmptyVerySmallSquare;": '\U000025AB',
+ "Eogon;": '\U00000118',
+ "Eopf;": '\U0001D53C',
+ "Epsilon;": '\U00000395',
+ "Equal;": '\U00002A75',
+ "EqualTilde;": '\U00002242',
+ "Equilibrium;": '\U000021CC',
+ "Escr;": '\U00002130',
+ "Esim;": '\U00002A73',
+ "Eta;": '\U00000397',
+ "Euml;": '\U000000CB',
+ "Exists;": '\U00002203',
+ "ExponentialE;": '\U00002147',
+ "Fcy;": '\U00000424',
+ "Ffr;": '\U0001D509',
+ "FilledSmallSquare;": '\U000025FC',
+ "FilledVerySmallSquare;": '\U000025AA',
+ "Fopf;": '\U0001D53D',
+ "ForAll;": '\U00002200',
+ "Fouriertrf;": '\U00002131',
+ "Fscr;": '\U00002131',
+ "GJcy;": '\U00000403',
+ "GT;": '\U0000003E',
+ "Gamma;": '\U00000393',
+ "Gammad;": '\U000003DC',
+ "Gbreve;": '\U0000011E',
+ "Gcedil;": '\U00000122',
+ "Gcirc;": '\U0000011C',
+ "Gcy;": '\U00000413',
+ "Gdot;": '\U00000120',
+ "Gfr;": '\U0001D50A',
+ "Gg;": '\U000022D9',
+ "Gopf;": '\U0001D53E',
+ "GreaterEqual;": '\U00002265',
+ "GreaterEqualLess;": '\U000022DB',
+ "GreaterFullEqual;": '\U00002267',
+ "GreaterGreater;": '\U00002AA2',
+ "GreaterLess;": '\U00002277',
+ "GreaterSlantEqual;": '\U00002A7E',
+ "GreaterTilde;": '\U00002273',
+ "Gscr;": '\U0001D4A2',
+ "Gt;": '\U0000226B',
+ "HARDcy;": '\U0000042A',
+ "Hacek;": '\U000002C7',
+ "Hat;": '\U0000005E',
+ "Hcirc;": '\U00000124',
+ "Hfr;": '\U0000210C',
+ "HilbertSpace;": '\U0000210B',
+ "Hopf;": '\U0000210D',
+ "HorizontalLine;": '\U00002500',
+ "Hscr;": '\U0000210B',
+ "Hstrok;": '\U00000126',
+ "HumpDownHump;": '\U0000224E',
+ "HumpEqual;": '\U0000224F',
+ "IEcy;": '\U00000415',
+ "IJlig;": '\U00000132',
+ "IOcy;": '\U00000401',
+ "Iacute;": '\U000000CD',
+ "Icirc;": '\U000000CE',
+ "Icy;": '\U00000418',
+ "Idot;": '\U00000130',
+ "Ifr;": '\U00002111',
+ "Igrave;": '\U000000CC',
+ "Im;": '\U00002111',
+ "Imacr;": '\U0000012A',
+ "ImaginaryI;": '\U00002148',
+ "Implies;": '\U000021D2',
+ "Int;": '\U0000222C',
+ "Integral;": '\U0000222B',
+ "Intersection;": '\U000022C2',
+ "InvisibleComma;": '\U00002063',
+ "InvisibleTimes;": '\U00002062',
+ "Iogon;": '\U0000012E',
+ "Iopf;": '\U0001D540',
+ "Iota;": '\U00000399',
+ "Iscr;": '\U00002110',
+ "Itilde;": '\U00000128',
+ "Iukcy;": '\U00000406',
+ "Iuml;": '\U000000CF',
+ "Jcirc;": '\U00000134',
+ "Jcy;": '\U00000419',
+ "Jfr;": '\U0001D50D',
+ "Jopf;": '\U0001D541',
+ "Jscr;": '\U0001D4A5',
+ "Jsercy;": '\U00000408',
+ "Jukcy;": '\U00000404',
+ "KHcy;": '\U00000425',
+ "KJcy;": '\U0000040C',
+ "Kappa;": '\U0000039A',
+ "Kcedil;": '\U00000136',
+ "Kcy;": '\U0000041A',
+ "Kfr;": '\U0001D50E',
+ "Kopf;": '\U0001D542',
+ "Kscr;": '\U0001D4A6',
+ "LJcy;": '\U00000409',
+ "LT;": '\U0000003C',
+ "Lacute;": '\U00000139',
+ "Lambda;": '\U0000039B',
+ "Lang;": '\U000027EA',
+ "Laplacetrf;": '\U00002112',
+ "Larr;": '\U0000219E',
+ "Lcaron;": '\U0000013D',
+ "Lcedil;": '\U0000013B',
+ "Lcy;": '\U0000041B',
+ "LeftAngleBracket;": '\U000027E8',
+ "LeftArrow;": '\U00002190',
+ "LeftArrowBar;": '\U000021E4',
+ "LeftArrowRightArrow;": '\U000021C6',
+ "LeftCeiling;": '\U00002308',
+ "LeftDoubleBracket;": '\U000027E6',
+ "LeftDownTeeVector;": '\U00002961',
+ "LeftDownVector;": '\U000021C3',
+ "LeftDownVectorBar;": '\U00002959',
+ "LeftFloor;": '\U0000230A',
+ "LeftRightArrow;": '\U00002194',
+ "LeftRightVector;": '\U0000294E',
+ "LeftTee;": '\U000022A3',
+ "LeftTeeArrow;": '\U000021A4',
+ "LeftTeeVector;": '\U0000295A',
+ "LeftTriangle;": '\U000022B2',
+ "LeftTriangleBar;": '\U000029CF',
+ "LeftTriangleEqual;": '\U000022B4',
+ "LeftUpDownVector;": '\U00002951',
+ "LeftUpTeeVector;": '\U00002960',
+ "LeftUpVector;": '\U000021BF',
+ "LeftUpVectorBar;": '\U00002958',
+ "LeftVector;": '\U000021BC',
+ "LeftVectorBar;": '\U00002952',
+ "Leftarrow;": '\U000021D0',
+ "Leftrightarrow;": '\U000021D4',
+ "LessEqualGreater;": '\U000022DA',
+ "LessFullEqual;": '\U00002266',
+ "LessGreater;": '\U00002276',
+ "LessLess;": '\U00002AA1',
+ "LessSlantEqual;": '\U00002A7D',
+ "LessTilde;": '\U00002272',
+ "Lfr;": '\U0001D50F',
+ "Ll;": '\U000022D8',
+ "Lleftarrow;": '\U000021DA',
+ "Lmidot;": '\U0000013F',
+ "LongLeftArrow;": '\U000027F5',
+ "LongLeftRightArrow;": '\U000027F7',
+ "LongRightArrow;": '\U000027F6',
+ "Longleftarrow;": '\U000027F8',
+ "Longleftrightarrow;": '\U000027FA',
+ "Longrightarrow;": '\U000027F9',
+ "Lopf;": '\U0001D543',
+ "LowerLeftArrow;": '\U00002199',
+ "LowerRightArrow;": '\U00002198',
+ "Lscr;": '\U00002112',
+ "Lsh;": '\U000021B0',
+ "Lstrok;": '\U00000141',
+ "Lt;": '\U0000226A',
+ "Map;": '\U00002905',
+ "Mcy;": '\U0000041C',
+ "MediumSpace;": '\U0000205F',
+ "Mellintrf;": '\U00002133',
+ "Mfr;": '\U0001D510',
+ "MinusPlus;": '\U00002213',
+ "Mopf;": '\U0001D544',
+ "Mscr;": '\U00002133',
+ "Mu;": '\U0000039C',
+ "NJcy;": '\U0000040A',
+ "Nacute;": '\U00000143',
+ "Ncaron;": '\U00000147',
+ "Ncedil;": '\U00000145',
+ "Ncy;": '\U0000041D',
+ "NegativeMediumSpace;": '\U0000200B',
+ "NegativeThickSpace;": '\U0000200B',
+ "NegativeThinSpace;": '\U0000200B',
+ "NegativeVeryThinSpace;": '\U0000200B',
+ "NestedGreaterGreater;": '\U0000226B',
+ "NestedLessLess;": '\U0000226A',
+ "NewLine;": '\U0000000A',
+ "Nfr;": '\U0001D511',
+ "NoBreak;": '\U00002060',
+ "NonBreakingSpace;": '\U000000A0',
+ "Nopf;": '\U00002115',
+ "Not;": '\U00002AEC',
+ "NotCongruent;": '\U00002262',
+ "NotCupCap;": '\U0000226D',
+ "NotDoubleVerticalBar;": '\U00002226',
+ "NotElement;": '\U00002209',
+ "NotEqual;": '\U00002260',
+ "NotExists;": '\U00002204',
+ "NotGreater;": '\U0000226F',
+ "NotGreaterEqual;": '\U00002271',
+ "NotGreaterLess;": '\U00002279',
+ "NotGreaterTilde;": '\U00002275',
+ "NotLeftTriangle;": '\U000022EA',
+ "NotLeftTriangleEqual;": '\U000022EC',
+ "NotLess;": '\U0000226E',
+ "NotLessEqual;": '\U00002270',
+ "NotLessGreater;": '\U00002278',
+ "NotLessTilde;": '\U00002274',
+ "NotPrecedes;": '\U00002280',
+ "NotPrecedesSlantEqual;": '\U000022E0',
+ "NotReverseElement;": '\U0000220C',
+ "NotRightTriangle;": '\U000022EB',
+ "NotRightTriangleEqual;": '\U000022ED',
+ "NotSquareSubsetEqual;": '\U000022E2',
+ "NotSquareSupersetEqual;": '\U000022E3',
+ "NotSubsetEqual;": '\U00002288',
+ "NotSucceeds;": '\U00002281',
+ "NotSucceedsSlantEqual;": '\U000022E1',
+ "NotSupersetEqual;": '\U00002289',
+ "NotTilde;": '\U00002241',
+ "NotTildeEqual;": '\U00002244',
+ "NotTildeFullEqual;": '\U00002247',
+ "NotTildeTilde;": '\U00002249',
+ "NotVerticalBar;": '\U00002224',
+ "Nscr;": '\U0001D4A9',
+ "Ntilde;": '\U000000D1',
+ "Nu;": '\U0000039D',
+ "OElig;": '\U00000152',
+ "Oacute;": '\U000000D3',
+ "Ocirc;": '\U000000D4',
+ "Ocy;": '\U0000041E',
+ "Odblac;": '\U00000150',
+ "Ofr;": '\U0001D512',
+ "Ograve;": '\U000000D2',
+ "Omacr;": '\U0000014C',
+ "Omega;": '\U000003A9',
+ "Omicron;": '\U0000039F',
+ "Oopf;": '\U0001D546',
+ "OpenCurlyDoubleQuote;": '\U0000201C',
+ "OpenCurlyQuote;": '\U00002018',
+ "Or;": '\U00002A54',
+ "Oscr;": '\U0001D4AA',
+ "Oslash;": '\U000000D8',
+ "Otilde;": '\U000000D5',
+ "Otimes;": '\U00002A37',
+ "Ouml;": '\U000000D6',
+ "OverBar;": '\U0000203E',
+ "OverBrace;": '\U000023DE',
+ "OverBracket;": '\U000023B4',
+ "OverParenthesis;": '\U000023DC',
+ "PartialD;": '\U00002202',
+ "Pcy;": '\U0000041F',
+ "Pfr;": '\U0001D513',
+ "Phi;": '\U000003A6',
+ "Pi;": '\U000003A0',
+ "PlusMinus;": '\U000000B1',
+ "Poincareplane;": '\U0000210C',
+ "Popf;": '\U00002119',
+ "Pr;": '\U00002ABB',
+ "Precedes;": '\U0000227A',
+ "PrecedesEqual;": '\U00002AAF',
+ "PrecedesSlantEqual;": '\U0000227C',
+ "PrecedesTilde;": '\U0000227E',
+ "Prime;": '\U00002033',
+ "Product;": '\U0000220F',
+ "Proportion;": '\U00002237',
+ "Proportional;": '\U0000221D',
+ "Pscr;": '\U0001D4AB',
+ "Psi;": '\U000003A8',
+ "QUOT;": '\U00000022',
+ "Qfr;": '\U0001D514',
+ "Qopf;": '\U0000211A',
+ "Qscr;": '\U0001D4AC',
+ "RBarr;": '\U00002910',
+ "REG;": '\U000000AE',
+ "Racute;": '\U00000154',
+ "Rang;": '\U000027EB',
+ "Rarr;": '\U000021A0',
+ "Rarrtl;": '\U00002916',
+ "Rcaron;": '\U00000158',
+ "Rcedil;": '\U00000156',
+ "Rcy;": '\U00000420',
+ "Re;": '\U0000211C',
+ "ReverseElement;": '\U0000220B',
+ "ReverseEquilibrium;": '\U000021CB',
+ "ReverseUpEquilibrium;": '\U0000296F',
+ "Rfr;": '\U0000211C',
+ "Rho;": '\U000003A1',
+ "RightAngleBracket;": '\U000027E9',
+ "RightArrow;": '\U00002192',
+ "RightArrowBar;": '\U000021E5',
+ "RightArrowLeftArrow;": '\U000021C4',
+ "RightCeiling;": '\U00002309',
+ "RightDoubleBracket;": '\U000027E7',
+ "RightDownTeeVector;": '\U0000295D',
+ "RightDownVector;": '\U000021C2',
+ "RightDownVectorBar;": '\U00002955',
+ "RightFloor;": '\U0000230B',
+ "RightTee;": '\U000022A2',
+ "RightTeeArrow;": '\U000021A6',
+ "RightTeeVector;": '\U0000295B',
+ "RightTriangle;": '\U000022B3',
+ "RightTriangleBar;": '\U000029D0',
+ "RightTriangleEqual;": '\U000022B5',
+ "RightUpDownVector;": '\U0000294F',
+ "RightUpTeeVector;": '\U0000295C',
+ "RightUpVector;": '\U000021BE',
+ "RightUpVectorBar;": '\U00002954',
+ "RightVector;": '\U000021C0',
+ "RightVectorBar;": '\U00002953',
+ "Rightarrow;": '\U000021D2',
+ "Ropf;": '\U0000211D',
+ "RoundImplies;": '\U00002970',
+ "Rrightarrow;": '\U000021DB',
+ "Rscr;": '\U0000211B',
+ "Rsh;": '\U000021B1',
+ "RuleDelayed;": '\U000029F4',
+ "SHCHcy;": '\U00000429',
+ "SHcy;": '\U00000428',
+ "SOFTcy;": '\U0000042C',
+ "Sacute;": '\U0000015A',
+ "Sc;": '\U00002ABC',
+ "Scaron;": '\U00000160',
+ "Scedil;": '\U0000015E',
+ "Scirc;": '\U0000015C',
+ "Scy;": '\U00000421',
+ "Sfr;": '\U0001D516',
+ "ShortDownArrow;": '\U00002193',
+ "ShortLeftArrow;": '\U00002190',
+ "ShortRightArrow;": '\U00002192',
+ "ShortUpArrow;": '\U00002191',
+ "Sigma;": '\U000003A3',
+ "SmallCircle;": '\U00002218',
+ "Sopf;": '\U0001D54A',
+ "Sqrt;": '\U0000221A',
+ "Square;": '\U000025A1',
+ "SquareIntersection;": '\U00002293',
+ "SquareSubset;": '\U0000228F',
+ "SquareSubsetEqual;": '\U00002291',
+ "SquareSuperset;": '\U00002290',
+ "SquareSupersetEqual;": '\U00002292',
+ "SquareUnion;": '\U00002294',
+ "Sscr;": '\U0001D4AE',
+ "Star;": '\U000022C6',
+ "Sub;": '\U000022D0',
+ "Subset;": '\U000022D0',
+ "SubsetEqual;": '\U00002286',
+ "Succeeds;": '\U0000227B',
+ "SucceedsEqual;": '\U00002AB0',
+ "SucceedsSlantEqual;": '\U0000227D',
+ "SucceedsTilde;": '\U0000227F',
+ "SuchThat;": '\U0000220B',
+ "Sum;": '\U00002211',
+ "Sup;": '\U000022D1',
+ "Superset;": '\U00002283',
+ "SupersetEqual;": '\U00002287',
+ "Supset;": '\U000022D1',
+ "THORN;": '\U000000DE',
+ "TRADE;": '\U00002122',
+ "TSHcy;": '\U0000040B',
+ "TScy;": '\U00000426',
+ "Tab;": '\U00000009',
+ "Tau;": '\U000003A4',
+ "Tcaron;": '\U00000164',
+ "Tcedil;": '\U00000162',
+ "Tcy;": '\U00000422',
+ "Tfr;": '\U0001D517',
+ "Therefore;": '\U00002234',
+ "Theta;": '\U00000398',
+ "ThinSpace;": '\U00002009',
+ "Tilde;": '\U0000223C',
+ "TildeEqual;": '\U00002243',
+ "TildeFullEqual;": '\U00002245',
+ "TildeTilde;": '\U00002248',
+ "Topf;": '\U0001D54B',
+ "TripleDot;": '\U000020DB',
+ "Tscr;": '\U0001D4AF',
+ "Tstrok;": '\U00000166',
+ "Uacute;": '\U000000DA',
+ "Uarr;": '\U0000219F',
+ "Uarrocir;": '\U00002949',
+ "Ubrcy;": '\U0000040E',
+ "Ubreve;": '\U0000016C',
+ "Ucirc;": '\U000000DB',
+ "Ucy;": '\U00000423',
+ "Udblac;": '\U00000170',
+ "Ufr;": '\U0001D518',
+ "Ugrave;": '\U000000D9',
+ "Umacr;": '\U0000016A',
+ "UnderBar;": '\U0000005F',
+ "UnderBrace;": '\U000023DF',
+ "UnderBracket;": '\U000023B5',
+ "UnderParenthesis;": '\U000023DD',
+ "Union;": '\U000022C3',
+ "UnionPlus;": '\U0000228E',
+ "Uogon;": '\U00000172',
+ "Uopf;": '\U0001D54C',
+ "UpArrow;": '\U00002191',
+ "UpArrowBar;": '\U00002912',
+ "UpArrowDownArrow;": '\U000021C5',
+ "UpDownArrow;": '\U00002195',
+ "UpEquilibrium;": '\U0000296E',
+ "UpTee;": '\U000022A5',
+ "UpTeeArrow;": '\U000021A5',
+ "Uparrow;": '\U000021D1',
+ "Updownarrow;": '\U000021D5',
+ "UpperLeftArrow;": '\U00002196',
+ "UpperRightArrow;": '\U00002197',
+ "Upsi;": '\U000003D2',
+ "Upsilon;": '\U000003A5',
+ "Uring;": '\U0000016E',
+ "Uscr;": '\U0001D4B0',
+ "Utilde;": '\U00000168',
+ "Uuml;": '\U000000DC',
+ "VDash;": '\U000022AB',
+ "Vbar;": '\U00002AEB',
+ "Vcy;": '\U00000412',
+ "Vdash;": '\U000022A9',
+ "Vdashl;": '\U00002AE6',
+ "Vee;": '\U000022C1',
+ "Verbar;": '\U00002016',
+ "Vert;": '\U00002016',
+ "VerticalBar;": '\U00002223',
+ "VerticalLine;": '\U0000007C',
+ "VerticalSeparator;": '\U00002758',
+ "VerticalTilde;": '\U00002240',
+ "VeryThinSpace;": '\U0000200A',
+ "Vfr;": '\U0001D519',
+ "Vopf;": '\U0001D54D',
+ "Vscr;": '\U0001D4B1',
+ "Vvdash;": '\U000022AA',
+ "Wcirc;": '\U00000174',
+ "Wedge;": '\U000022C0',
+ "Wfr;": '\U0001D51A',
+ "Wopf;": '\U0001D54E',
+ "Wscr;": '\U0001D4B2',
+ "Xfr;": '\U0001D51B',
+ "Xi;": '\U0000039E',
+ "Xopf;": '\U0001D54F',
+ "Xscr;": '\U0001D4B3',
+ "YAcy;": '\U0000042F',
+ "YIcy;": '\U00000407',
+ "YUcy;": '\U0000042E',
+ "Yacute;": '\U000000DD',
+ "Ycirc;": '\U00000176',
+ "Ycy;": '\U0000042B',
+ "Yfr;": '\U0001D51C',
+ "Yopf;": '\U0001D550',
+ "Yscr;": '\U0001D4B4',
+ "Yuml;": '\U00000178',
+ "ZHcy;": '\U00000416',
+ "Zacute;": '\U00000179',
+ "Zcaron;": '\U0000017D',
+ "Zcy;": '\U00000417',
+ "Zdot;": '\U0000017B',
+ "ZeroWidthSpace;": '\U0000200B',
+ "Zeta;": '\U00000396',
+ "Zfr;": '\U00002128',
+ "Zopf;": '\U00002124',
+ "Zscr;": '\U0001D4B5',
+ "aacute;": '\U000000E1',
+ "abreve;": '\U00000103',
+ "ac;": '\U0000223E',
+ "acd;": '\U0000223F',
+ "acirc;": '\U000000E2',
+ "acute;": '\U000000B4',
+ "acy;": '\U00000430',
+ "aelig;": '\U000000E6',
+ "af;": '\U00002061',
+ "afr;": '\U0001D51E',
+ "agrave;": '\U000000E0',
+ "alefsym;": '\U00002135',
+ "aleph;": '\U00002135',
+ "alpha;": '\U000003B1',
+ "amacr;": '\U00000101',
+ "amalg;": '\U00002A3F',
+ "amp;": '\U00000026',
+ "and;": '\U00002227',
+ "andand;": '\U00002A55',
+ "andd;": '\U00002A5C',
+ "andslope;": '\U00002A58',
+ "andv;": '\U00002A5A',
+ "ang;": '\U00002220',
+ "ange;": '\U000029A4',
+ "angle;": '\U00002220',
+ "angmsd;": '\U00002221',
+ "angmsdaa;": '\U000029A8',
+ "angmsdab;": '\U000029A9',
+ "angmsdac;": '\U000029AA',
+ "angmsdad;": '\U000029AB',
+ "angmsdae;": '\U000029AC',
+ "angmsdaf;": '\U000029AD',
+ "angmsdag;": '\U000029AE',
+ "angmsdah;": '\U000029AF',
+ "angrt;": '\U0000221F',
+ "angrtvb;": '\U000022BE',
+ "angrtvbd;": '\U0000299D',
+ "angsph;": '\U00002222',
+ "angst;": '\U000000C5',
+ "angzarr;": '\U0000237C',
+ "aogon;": '\U00000105',
+ "aopf;": '\U0001D552',
+ "ap;": '\U00002248',
+ "apE;": '\U00002A70',
+ "apacir;": '\U00002A6F',
+ "ape;": '\U0000224A',
+ "apid;": '\U0000224B',
+ "apos;": '\U00000027',
+ "approx;": '\U00002248',
+ "approxeq;": '\U0000224A',
+ "aring;": '\U000000E5',
+ "ascr;": '\U0001D4B6',
+ "ast;": '\U0000002A',
+ "asymp;": '\U00002248',
+ "asympeq;": '\U0000224D',
+ "atilde;": '\U000000E3',
+ "auml;": '\U000000E4',
+ "awconint;": '\U00002233',
+ "awint;": '\U00002A11',
+ "bNot;": '\U00002AED',
+ "backcong;": '\U0000224C',
+ "backepsilon;": '\U000003F6',
+ "backprime;": '\U00002035',
+ "backsim;": '\U0000223D',
+ "backsimeq;": '\U000022CD',
+ "barvee;": '\U000022BD',
+ "barwed;": '\U00002305',
+ "barwedge;": '\U00002305',
+ "bbrk;": '\U000023B5',
+ "bbrktbrk;": '\U000023B6',
+ "bcong;": '\U0000224C',
+ "bcy;": '\U00000431',
+ "bdquo;": '\U0000201E',
+ "becaus;": '\U00002235',
+ "because;": '\U00002235',
+ "bemptyv;": '\U000029B0',
+ "bepsi;": '\U000003F6',
+ "bernou;": '\U0000212C',
+ "beta;": '\U000003B2',
+ "beth;": '\U00002136',
+ "between;": '\U0000226C',
+ "bfr;": '\U0001D51F',
+ "bigcap;": '\U000022C2',
+ "bigcirc;": '\U000025EF',
+ "bigcup;": '\U000022C3',
+ "bigodot;": '\U00002A00',
+ "bigoplus;": '\U00002A01',
+ "bigotimes;": '\U00002A02',
+ "bigsqcup;": '\U00002A06',
+ "bigstar;": '\U00002605',
+ "bigtriangledown;": '\U000025BD',
+ "bigtriangleup;": '\U000025B3',
+ "biguplus;": '\U00002A04',
+ "bigvee;": '\U000022C1',
+ "bigwedge;": '\U000022C0',
+ "bkarow;": '\U0000290D',
+ "blacklozenge;": '\U000029EB',
+ "blacksquare;": '\U000025AA',
+ "blacktriangle;": '\U000025B4',
+ "blacktriangledown;": '\U000025BE',
+ "blacktriangleleft;": '\U000025C2',
+ "blacktriangleright;": '\U000025B8',
+ "blank;": '\U00002423',
+ "blk12;": '\U00002592',
+ "blk14;": '\U00002591',
+ "blk34;": '\U00002593',
+ "block;": '\U00002588',
+ "bnot;": '\U00002310',
+ "bopf;": '\U0001D553',
+ "bot;": '\U000022A5',
+ "bottom;": '\U000022A5',
+ "bowtie;": '\U000022C8',
+ "boxDL;": '\U00002557',
+ "boxDR;": '\U00002554',
+ "boxDl;": '\U00002556',
+ "boxDr;": '\U00002553',
+ "boxH;": '\U00002550',
+ "boxHD;": '\U00002566',
+ "boxHU;": '\U00002569',
+ "boxHd;": '\U00002564',
+ "boxHu;": '\U00002567',
+ "boxUL;": '\U0000255D',
+ "boxUR;": '\U0000255A',
+ "boxUl;": '\U0000255C',
+ "boxUr;": '\U00002559',
+ "boxV;": '\U00002551',
+ "boxVH;": '\U0000256C',
+ "boxVL;": '\U00002563',
+ "boxVR;": '\U00002560',
+ "boxVh;": '\U0000256B',
+ "boxVl;": '\U00002562',
+ "boxVr;": '\U0000255F',
+ "boxbox;": '\U000029C9',
+ "boxdL;": '\U00002555',
+ "boxdR;": '\U00002552',
+ "boxdl;": '\U00002510',
+ "boxdr;": '\U0000250C',
+ "boxh;": '\U00002500',
+ "boxhD;": '\U00002565',
+ "boxhU;": '\U00002568',
+ "boxhd;": '\U0000252C',
+ "boxhu;": '\U00002534',
+ "boxminus;": '\U0000229F',
+ "boxplus;": '\U0000229E',
+ "boxtimes;": '\U000022A0',
+ "boxuL;": '\U0000255B',
+ "boxuR;": '\U00002558',
+ "boxul;": '\U00002518',
+ "boxur;": '\U00002514',
+ "boxv;": '\U00002502',
+ "boxvH;": '\U0000256A',
+ "boxvL;": '\U00002561',
+ "boxvR;": '\U0000255E',
+ "boxvh;": '\U0000253C',
+ "boxvl;": '\U00002524',
+ "boxvr;": '\U0000251C',
+ "bprime;": '\U00002035',
+ "breve;": '\U000002D8',
+ "brvbar;": '\U000000A6',
+ "bscr;": '\U0001D4B7',
+ "bsemi;": '\U0000204F',
+ "bsim;": '\U0000223D',
+ "bsime;": '\U000022CD',
+ "bsol;": '\U0000005C',
+ "bsolb;": '\U000029C5',
+ "bsolhsub;": '\U000027C8',
+ "bull;": '\U00002022',
+ "bullet;": '\U00002022',
+ "bump;": '\U0000224E',
+ "bumpE;": '\U00002AAE',
+ "bumpe;": '\U0000224F',
+ "bumpeq;": '\U0000224F',
+ "cacute;": '\U00000107',
+ "cap;": '\U00002229',
+ "capand;": '\U00002A44',
+ "capbrcup;": '\U00002A49',
+ "capcap;": '\U00002A4B',
+ "capcup;": '\U00002A47',
+ "capdot;": '\U00002A40',
+ "caret;": '\U00002041',
+ "caron;": '\U000002C7',
+ "ccaps;": '\U00002A4D',
+ "ccaron;": '\U0000010D',
+ "ccedil;": '\U000000E7',
+ "ccirc;": '\U00000109',
+ "ccups;": '\U00002A4C',
+ "ccupssm;": '\U00002A50',
+ "cdot;": '\U0000010B',
+ "cedil;": '\U000000B8',
+ "cemptyv;": '\U000029B2',
+ "cent;": '\U000000A2',
+ "centerdot;": '\U000000B7',
+ "cfr;": '\U0001D520',
+ "chcy;": '\U00000447',
+ "check;": '\U00002713',
+ "checkmark;": '\U00002713',
+ "chi;": '\U000003C7',
+ "cir;": '\U000025CB',
+ "cirE;": '\U000029C3',
+ "circ;": '\U000002C6',
+ "circeq;": '\U00002257',
+ "circlearrowleft;": '\U000021BA',
+ "circlearrowright;": '\U000021BB',
+ "circledR;": '\U000000AE',
+ "circledS;": '\U000024C8',
+ "circledast;": '\U0000229B',
+ "circledcirc;": '\U0000229A',
+ "circleddash;": '\U0000229D',
+ "cire;": '\U00002257',
+ "cirfnint;": '\U00002A10',
+ "cirmid;": '\U00002AEF',
+ "cirscir;": '\U000029C2',
+ "clubs;": '\U00002663',
+ "clubsuit;": '\U00002663',
+ "colon;": '\U0000003A',
+ "colone;": '\U00002254',
+ "coloneq;": '\U00002254',
+ "comma;": '\U0000002C',
+ "commat;": '\U00000040',
+ "comp;": '\U00002201',
+ "compfn;": '\U00002218',
+ "complement;": '\U00002201',
+ "complexes;": '\U00002102',
+ "cong;": '\U00002245',
+ "congdot;": '\U00002A6D',
+ "conint;": '\U0000222E',
+ "copf;": '\U0001D554',
+ "coprod;": '\U00002210',
+ "copy;": '\U000000A9',
+ "copysr;": '\U00002117',
+ "crarr;": '\U000021B5',
+ "cross;": '\U00002717',
+ "cscr;": '\U0001D4B8',
+ "csub;": '\U00002ACF',
+ "csube;": '\U00002AD1',
+ "csup;": '\U00002AD0',
+ "csupe;": '\U00002AD2',
+ "ctdot;": '\U000022EF',
+ "cudarrl;": '\U00002938',
+ "cudarrr;": '\U00002935',
+ "cuepr;": '\U000022DE',
+ "cuesc;": '\U000022DF',
+ "cularr;": '\U000021B6',
+ "cularrp;": '\U0000293D',
+ "cup;": '\U0000222A',
+ "cupbrcap;": '\U00002A48',
+ "cupcap;": '\U00002A46',
+ "cupcup;": '\U00002A4A',
+ "cupdot;": '\U0000228D',
+ "cupor;": '\U00002A45',
+ "curarr;": '\U000021B7',
+ "curarrm;": '\U0000293C',
+ "curlyeqprec;": '\U000022DE',
+ "curlyeqsucc;": '\U000022DF',
+ "curlyvee;": '\U000022CE',
+ "curlywedge;": '\U000022CF',
+ "curren;": '\U000000A4',
+ "curvearrowleft;": '\U000021B6',
+ "curvearrowright;": '\U000021B7',
+ "cuvee;": '\U000022CE',
+ "cuwed;": '\U000022CF',
+ "cwconint;": '\U00002232',
+ "cwint;": '\U00002231',
+ "cylcty;": '\U0000232D',
+ "dArr;": '\U000021D3',
+ "dHar;": '\U00002965',
+ "dagger;": '\U00002020',
+ "daleth;": '\U00002138',
+ "darr;": '\U00002193',
+ "dash;": '\U00002010',
+ "dashv;": '\U000022A3',
+ "dbkarow;": '\U0000290F',
+ "dblac;": '\U000002DD',
+ "dcaron;": '\U0000010F',
+ "dcy;": '\U00000434',
+ "dd;": '\U00002146',
+ "ddagger;": '\U00002021',
+ "ddarr;": '\U000021CA',
+ "ddotseq;": '\U00002A77',
+ "deg;": '\U000000B0',
+ "delta;": '\U000003B4',
+ "demptyv;": '\U000029B1',
+ "dfisht;": '\U0000297F',
+ "dfr;": '\U0001D521',
+ "dharl;": '\U000021C3',
+ "dharr;": '\U000021C2',
+ "diam;": '\U000022C4',
+ "diamond;": '\U000022C4',
+ "diamondsuit;": '\U00002666',
+ "diams;": '\U00002666',
+ "die;": '\U000000A8',
+ "digamma;": '\U000003DD',
+ "disin;": '\U000022F2',
+ "div;": '\U000000F7',
+ "divide;": '\U000000F7',
+ "divideontimes;": '\U000022C7',
+ "divonx;": '\U000022C7',
+ "djcy;": '\U00000452',
+ "dlcorn;": '\U0000231E',
+ "dlcrop;": '\U0000230D',
+ "dollar;": '\U00000024',
+ "dopf;": '\U0001D555',
+ "dot;": '\U000002D9',
+ "doteq;": '\U00002250',
+ "doteqdot;": '\U00002251',
+ "dotminus;": '\U00002238',
+ "dotplus;": '\U00002214',
+ "dotsquare;": '\U000022A1',
+ "doublebarwedge;": '\U00002306',
+ "downarrow;": '\U00002193',
+ "downdownarrows;": '\U000021CA',
+ "downharpoonleft;": '\U000021C3',
+ "downharpoonright;": '\U000021C2',
+ "drbkarow;": '\U00002910',
+ "drcorn;": '\U0000231F',
+ "drcrop;": '\U0000230C',
+ "dscr;": '\U0001D4B9',
+ "dscy;": '\U00000455',
+ "dsol;": '\U000029F6',
+ "dstrok;": '\U00000111',
+ "dtdot;": '\U000022F1',
+ "dtri;": '\U000025BF',
+ "dtrif;": '\U000025BE',
+ "duarr;": '\U000021F5',
+ "duhar;": '\U0000296F',
+ "dwangle;": '\U000029A6',
+ "dzcy;": '\U0000045F',
+ "dzigrarr;": '\U000027FF',
+ "eDDot;": '\U00002A77',
+ "eDot;": '\U00002251',
+ "eacute;": '\U000000E9',
+ "easter;": '\U00002A6E',
+ "ecaron;": '\U0000011B',
+ "ecir;": '\U00002256',
+ "ecirc;": '\U000000EA',
+ "ecolon;": '\U00002255',
+ "ecy;": '\U0000044D',
+ "edot;": '\U00000117',
+ "ee;": '\U00002147',
+ "efDot;": '\U00002252',
+ "efr;": '\U0001D522',
+ "eg;": '\U00002A9A',
+ "egrave;": '\U000000E8',
+ "egs;": '\U00002A96',
+ "egsdot;": '\U00002A98',
+ "el;": '\U00002A99',
+ "elinters;": '\U000023E7',
+ "ell;": '\U00002113',
+ "els;": '\U00002A95',
+ "elsdot;": '\U00002A97',
+ "emacr;": '\U00000113',
+ "empty;": '\U00002205',
+ "emptyset;": '\U00002205',
+ "emptyv;": '\U00002205',
+ "emsp;": '\U00002003',
+ "emsp13;": '\U00002004',
+ "emsp14;": '\U00002005',
+ "eng;": '\U0000014B',
+ "ensp;": '\U00002002',
+ "eogon;": '\U00000119',
+ "eopf;": '\U0001D556',
+ "epar;": '\U000022D5',
+ "eparsl;": '\U000029E3',
+ "eplus;": '\U00002A71',
+ "epsi;": '\U000003B5',
+ "epsilon;": '\U000003B5',
+ "epsiv;": '\U000003F5',
+ "eqcirc;": '\U00002256',
+ "eqcolon;": '\U00002255',
+ "eqsim;": '\U00002242',
+ "eqslantgtr;": '\U00002A96',
+ "eqslantless;": '\U00002A95',
+ "equals;": '\U0000003D',
+ "equest;": '\U0000225F',
+ "equiv;": '\U00002261',
+ "equivDD;": '\U00002A78',
+ "eqvparsl;": '\U000029E5',
+ "erDot;": '\U00002253',
+ "erarr;": '\U00002971',
+ "escr;": '\U0000212F',
+ "esdot;": '\U00002250',
+ "esim;": '\U00002242',
+ "eta;": '\U000003B7',
+ "eth;": '\U000000F0',
+ "euml;": '\U000000EB',
+ "euro;": '\U000020AC',
+ "excl;": '\U00000021',
+ "exist;": '\U00002203',
+ "expectation;": '\U00002130',
+ "exponentiale;": '\U00002147',
+ "fallingdotseq;": '\U00002252',
+ "fcy;": '\U00000444',
+ "female;": '\U00002640',
+ "ffilig;": '\U0000FB03',
+ "fflig;": '\U0000FB00',
+ "ffllig;": '\U0000FB04',
+ "ffr;": '\U0001D523',
+ "filig;": '\U0000FB01',
+ "flat;": '\U0000266D',
+ "fllig;": '\U0000FB02',
+ "fltns;": '\U000025B1',
+ "fnof;": '\U00000192',
+ "fopf;": '\U0001D557',
+ "forall;": '\U00002200',
+ "fork;": '\U000022D4',
+ "forkv;": '\U00002AD9',
+ "fpartint;": '\U00002A0D',
+ "frac12;": '\U000000BD',
+ "frac13;": '\U00002153',
+ "frac14;": '\U000000BC',
+ "frac15;": '\U00002155',
+ "frac16;": '\U00002159',
+ "frac18;": '\U0000215B',
+ "frac23;": '\U00002154',
+ "frac25;": '\U00002156',
+ "frac34;": '\U000000BE',
+ "frac35;": '\U00002157',
+ "frac38;": '\U0000215C',
+ "frac45;": '\U00002158',
+ "frac56;": '\U0000215A',
+ "frac58;": '\U0000215D',
+ "frac78;": '\U0000215E',
+ "frasl;": '\U00002044',
+ "frown;": '\U00002322',
+ "fscr;": '\U0001D4BB',
+ "gE;": '\U00002267',
+ "gEl;": '\U00002A8C',
+ "gacute;": '\U000001F5',
+ "gamma;": '\U000003B3',
+ "gammad;": '\U000003DD',
+ "gap;": '\U00002A86',
+ "gbreve;": '\U0000011F',
+ "gcirc;": '\U0000011D',
+ "gcy;": '\U00000433',
+ "gdot;": '\U00000121',
+ "ge;": '\U00002265',
+ "gel;": '\U000022DB',
+ "geq;": '\U00002265',
+ "geqq;": '\U00002267',
+ "geqslant;": '\U00002A7E',
+ "ges;": '\U00002A7E',
+ "gescc;": '\U00002AA9',
+ "gesdot;": '\U00002A80',
+ "gesdoto;": '\U00002A82',
+ "gesdotol;": '\U00002A84',
+ "gesles;": '\U00002A94',
+ "gfr;": '\U0001D524',
+ "gg;": '\U0000226B',
+ "ggg;": '\U000022D9',
+ "gimel;": '\U00002137',
+ "gjcy;": '\U00000453',
+ "gl;": '\U00002277',
+ "glE;": '\U00002A92',
+ "gla;": '\U00002AA5',
+ "glj;": '\U00002AA4',
+ "gnE;": '\U00002269',
+ "gnap;": '\U00002A8A',
+ "gnapprox;": '\U00002A8A',
+ "gne;": '\U00002A88',
+ "gneq;": '\U00002A88',
+ "gneqq;": '\U00002269',
+ "gnsim;": '\U000022E7',
+ "gopf;": '\U0001D558',
+ "grave;": '\U00000060',
+ "gscr;": '\U0000210A',
+ "gsim;": '\U00002273',
+ "gsime;": '\U00002A8E',
+ "gsiml;": '\U00002A90',
+ "gt;": '\U0000003E',
+ "gtcc;": '\U00002AA7',
+ "gtcir;": '\U00002A7A',
+ "gtdot;": '\U000022D7',
+ "gtlPar;": '\U00002995',
+ "gtquest;": '\U00002A7C',
+ "gtrapprox;": '\U00002A86',
+ "gtrarr;": '\U00002978',
+ "gtrdot;": '\U000022D7',
+ "gtreqless;": '\U000022DB',
+ "gtreqqless;": '\U00002A8C',
+ "gtrless;": '\U00002277',
+ "gtrsim;": '\U00002273',
+ "hArr;": '\U000021D4',
+ "hairsp;": '\U0000200A',
+ "half;": '\U000000BD',
+ "hamilt;": '\U0000210B',
+ "hardcy;": '\U0000044A',
+ "harr;": '\U00002194',
+ "harrcir;": '\U00002948',
+ "harrw;": '\U000021AD',
+ "hbar;": '\U0000210F',
+ "hcirc;": '\U00000125',
+ "hearts;": '\U00002665',
+ "heartsuit;": '\U00002665',
+ "hellip;": '\U00002026',
+ "hercon;": '\U000022B9',
+ "hfr;": '\U0001D525',
+ "hksearow;": '\U00002925',
+ "hkswarow;": '\U00002926',
+ "hoarr;": '\U000021FF',
+ "homtht;": '\U0000223B',
+ "hookleftarrow;": '\U000021A9',
+ "hookrightarrow;": '\U000021AA',
+ "hopf;": '\U0001D559',
+ "horbar;": '\U00002015',
+ "hscr;": '\U0001D4BD',
+ "hslash;": '\U0000210F',
+ "hstrok;": '\U00000127',
+ "hybull;": '\U00002043',
+ "hyphen;": '\U00002010',
+ "iacute;": '\U000000ED',
+ "ic;": '\U00002063',
+ "icirc;": '\U000000EE',
+ "icy;": '\U00000438',
+ "iecy;": '\U00000435',
+ "iexcl;": '\U000000A1',
+ "iff;": '\U000021D4',
+ "ifr;": '\U0001D526',
+ "igrave;": '\U000000EC',
+ "ii;": '\U00002148',
+ "iiiint;": '\U00002A0C',
+ "iiint;": '\U0000222D',
+ "iinfin;": '\U000029DC',
+ "iiota;": '\U00002129',
+ "ijlig;": '\U00000133',
+ "imacr;": '\U0000012B',
+ "image;": '\U00002111',
+ "imagline;": '\U00002110',
+ "imagpart;": '\U00002111',
+ "imath;": '\U00000131',
+ "imof;": '\U000022B7',
+ "imped;": '\U000001B5',
+ "in;": '\U00002208',
+ "incare;": '\U00002105',
+ "infin;": '\U0000221E',
+ "infintie;": '\U000029DD',
+ "inodot;": '\U00000131',
+ "int;": '\U0000222B',
+ "intcal;": '\U000022BA',
+ "integers;": '\U00002124',
+ "intercal;": '\U000022BA',
+ "intlarhk;": '\U00002A17',
+ "intprod;": '\U00002A3C',
+ "iocy;": '\U00000451',
+ "iogon;": '\U0000012F',
+ "iopf;": '\U0001D55A',
+ "iota;": '\U000003B9',
+ "iprod;": '\U00002A3C',
+ "iquest;": '\U000000BF',
+ "iscr;": '\U0001D4BE',
+ "isin;": '\U00002208',
+ "isinE;": '\U000022F9',
+ "isindot;": '\U000022F5',
+ "isins;": '\U000022F4',
+ "isinsv;": '\U000022F3',
+ "isinv;": '\U00002208',
+ "it;": '\U00002062',
+ "itilde;": '\U00000129',
+ "iukcy;": '\U00000456',
+ "iuml;": '\U000000EF',
+ "jcirc;": '\U00000135',
+ "jcy;": '\U00000439',
+ "jfr;": '\U0001D527',
+ "jmath;": '\U00000237',
+ "jopf;": '\U0001D55B',
+ "jscr;": '\U0001D4BF',
+ "jsercy;": '\U00000458',
+ "jukcy;": '\U00000454',
+ "kappa;": '\U000003BA',
+ "kappav;": '\U000003F0',
+ "kcedil;": '\U00000137',
+ "kcy;": '\U0000043A',
+ "kfr;": '\U0001D528',
+ "kgreen;": '\U00000138',
+ "khcy;": '\U00000445',
+ "kjcy;": '\U0000045C',
+ "kopf;": '\U0001D55C',
+ "kscr;": '\U0001D4C0',
+ "lAarr;": '\U000021DA',
+ "lArr;": '\U000021D0',
+ "lAtail;": '\U0000291B',
+ "lBarr;": '\U0000290E',
+ "lE;": '\U00002266',
+ "lEg;": '\U00002A8B',
+ "lHar;": '\U00002962',
+ "lacute;": '\U0000013A',
+ "laemptyv;": '\U000029B4',
+ "lagran;": '\U00002112',
+ "lambda;": '\U000003BB',
+ "lang;": '\U000027E8',
+ "langd;": '\U00002991',
+ "langle;": '\U000027E8',
+ "lap;": '\U00002A85',
+ "laquo;": '\U000000AB',
+ "larr;": '\U00002190',
+ "larrb;": '\U000021E4',
+ "larrbfs;": '\U0000291F',
+ "larrfs;": '\U0000291D',
+ "larrhk;": '\U000021A9',
+ "larrlp;": '\U000021AB',
+ "larrpl;": '\U00002939',
+ "larrsim;": '\U00002973',
+ "larrtl;": '\U000021A2',
+ "lat;": '\U00002AAB',
+ "latail;": '\U00002919',
+ "late;": '\U00002AAD',
+ "lbarr;": '\U0000290C',
+ "lbbrk;": '\U00002772',
+ "lbrace;": '\U0000007B',
+ "lbrack;": '\U0000005B',
+ "lbrke;": '\U0000298B',
+ "lbrksld;": '\U0000298F',
+ "lbrkslu;": '\U0000298D',
+ "lcaron;": '\U0000013E',
+ "lcedil;": '\U0000013C',
+ "lceil;": '\U00002308',
+ "lcub;": '\U0000007B',
+ "lcy;": '\U0000043B',
+ "ldca;": '\U00002936',
+ "ldquo;": '\U0000201C',
+ "ldquor;": '\U0000201E',
+ "ldrdhar;": '\U00002967',
+ "ldrushar;": '\U0000294B',
+ "ldsh;": '\U000021B2',
+ "le;": '\U00002264',
+ "leftarrow;": '\U00002190',
+ "leftarrowtail;": '\U000021A2',
+ "leftharpoondown;": '\U000021BD',
+ "leftharpoonup;": '\U000021BC',
+ "leftleftarrows;": '\U000021C7',
+ "leftrightarrow;": '\U00002194',
+ "leftrightarrows;": '\U000021C6',
+ "leftrightharpoons;": '\U000021CB',
+ "leftrightsquigarrow;": '\U000021AD',
+ "leftthreetimes;": '\U000022CB',
+ "leg;": '\U000022DA',
+ "leq;": '\U00002264',
+ "leqq;": '\U00002266',
+ "leqslant;": '\U00002A7D',
+ "les;": '\U00002A7D',
+ "lescc;": '\U00002AA8',
+ "lesdot;": '\U00002A7F',
+ "lesdoto;": '\U00002A81',
+ "lesdotor;": '\U00002A83',
+ "lesges;": '\U00002A93',
+ "lessapprox;": '\U00002A85',
+ "lessdot;": '\U000022D6',
+ "lesseqgtr;": '\U000022DA',
+ "lesseqqgtr;": '\U00002A8B',
+ "lessgtr;": '\U00002276',
+ "lesssim;": '\U00002272',
+ "lfisht;": '\U0000297C',
+ "lfloor;": '\U0000230A',
+ "lfr;": '\U0001D529',
+ "lg;": '\U00002276',
+ "lgE;": '\U00002A91',
+ "lhard;": '\U000021BD',
+ "lharu;": '\U000021BC',
+ "lharul;": '\U0000296A',
+ "lhblk;": '\U00002584',
+ "ljcy;": '\U00000459',
+ "ll;": '\U0000226A',
+ "llarr;": '\U000021C7',
+ "llcorner;": '\U0000231E',
+ "llhard;": '\U0000296B',
+ "lltri;": '\U000025FA',
+ "lmidot;": '\U00000140',
+ "lmoust;": '\U000023B0',
+ "lmoustache;": '\U000023B0',
+ "lnE;": '\U00002268',
+ "lnap;": '\U00002A89',
+ "lnapprox;": '\U00002A89',
+ "lne;": '\U00002A87',
+ "lneq;": '\U00002A87',
+ "lneqq;": '\U00002268',
+ "lnsim;": '\U000022E6',
+ "loang;": '\U000027EC',
+ "loarr;": '\U000021FD',
+ "lobrk;": '\U000027E6',
+ "longleftarrow;": '\U000027F5',
+ "longleftrightarrow;": '\U000027F7',
+ "longmapsto;": '\U000027FC',
+ "longrightarrow;": '\U000027F6',
+ "looparrowleft;": '\U000021AB',
+ "looparrowright;": '\U000021AC',
+ "lopar;": '\U00002985',
+ "lopf;": '\U0001D55D',
+ "loplus;": '\U00002A2D',
+ "lotimes;": '\U00002A34',
+ "lowast;": '\U00002217',
+ "lowbar;": '\U0000005F',
+ "loz;": '\U000025CA',
+ "lozenge;": '\U000025CA',
+ "lozf;": '\U000029EB',
+ "lpar;": '\U00000028',
+ "lparlt;": '\U00002993',
+ "lrarr;": '\U000021C6',
+ "lrcorner;": '\U0000231F',
+ "lrhar;": '\U000021CB',
+ "lrhard;": '\U0000296D',
+ "lrm;": '\U0000200E',
+ "lrtri;": '\U000022BF',
+ "lsaquo;": '\U00002039',
+ "lscr;": '\U0001D4C1',
+ "lsh;": '\U000021B0',
+ "lsim;": '\U00002272',
+ "lsime;": '\U00002A8D',
+ "lsimg;": '\U00002A8F',
+ "lsqb;": '\U0000005B',
+ "lsquo;": '\U00002018',
+ "lsquor;": '\U0000201A',
+ "lstrok;": '\U00000142',
+ "lt;": '\U0000003C',
+ "ltcc;": '\U00002AA6',
+ "ltcir;": '\U00002A79',
+ "ltdot;": '\U000022D6',
+ "lthree;": '\U000022CB',
+ "ltimes;": '\U000022C9',
+ "ltlarr;": '\U00002976',
+ "ltquest;": '\U00002A7B',
+ "ltrPar;": '\U00002996',
+ "ltri;": '\U000025C3',
+ "ltrie;": '\U000022B4',
+ "ltrif;": '\U000025C2',
+ "lurdshar;": '\U0000294A',
+ "luruhar;": '\U00002966',
+ "mDDot;": '\U0000223A',
+ "macr;": '\U000000AF',
+ "male;": '\U00002642',
+ "malt;": '\U00002720',
+ "maltese;": '\U00002720',
+ "map;": '\U000021A6',
+ "mapsto;": '\U000021A6',
+ "mapstodown;": '\U000021A7',
+ "mapstoleft;": '\U000021A4',
+ "mapstoup;": '\U000021A5',
+ "marker;": '\U000025AE',
+ "mcomma;": '\U00002A29',
+ "mcy;": '\U0000043C',
+ "mdash;": '\U00002014',
+ "measuredangle;": '\U00002221',
+ "mfr;": '\U0001D52A',
+ "mho;": '\U00002127',
+ "micro;": '\U000000B5',
+ "mid;": '\U00002223',
+ "midast;": '\U0000002A',
+ "midcir;": '\U00002AF0',
+ "middot;": '\U000000B7',
+ "minus;": '\U00002212',
+ "minusb;": '\U0000229F',
+ "minusd;": '\U00002238',
+ "minusdu;": '\U00002A2A',
+ "mlcp;": '\U00002ADB',
+ "mldr;": '\U00002026',
+ "mnplus;": '\U00002213',
+ "models;": '\U000022A7',
+ "mopf;": '\U0001D55E',
+ "mp;": '\U00002213',
+ "mscr;": '\U0001D4C2',
+ "mstpos;": '\U0000223E',
+ "mu;": '\U000003BC',
+ "multimap;": '\U000022B8',
+ "mumap;": '\U000022B8',
+ "nLeftarrow;": '\U000021CD',
+ "nLeftrightarrow;": '\U000021CE',
+ "nRightarrow;": '\U000021CF',
+ "nVDash;": '\U000022AF',
+ "nVdash;": '\U000022AE',
+ "nabla;": '\U00002207',
+ "nacute;": '\U00000144',
+ "nap;": '\U00002249',
+ "napos;": '\U00000149',
+ "napprox;": '\U00002249',
+ "natur;": '\U0000266E',
+ "natural;": '\U0000266E',
+ "naturals;": '\U00002115',
+ "nbsp;": '\U000000A0',
+ "ncap;": '\U00002A43',
+ "ncaron;": '\U00000148',
+ "ncedil;": '\U00000146',
+ "ncong;": '\U00002247',
+ "ncup;": '\U00002A42',
+ "ncy;": '\U0000043D',
+ "ndash;": '\U00002013',
+ "ne;": '\U00002260',
+ "neArr;": '\U000021D7',
+ "nearhk;": '\U00002924',
+ "nearr;": '\U00002197',
+ "nearrow;": '\U00002197',
+ "nequiv;": '\U00002262',
+ "nesear;": '\U00002928',
+ "nexist;": '\U00002204',
+ "nexists;": '\U00002204',
+ "nfr;": '\U0001D52B',
+ "nge;": '\U00002271',
+ "ngeq;": '\U00002271',
+ "ngsim;": '\U00002275',
+ "ngt;": '\U0000226F',
+ "ngtr;": '\U0000226F',
+ "nhArr;": '\U000021CE',
+ "nharr;": '\U000021AE',
+ "nhpar;": '\U00002AF2',
+ "ni;": '\U0000220B',
+ "nis;": '\U000022FC',
+ "nisd;": '\U000022FA',
+ "niv;": '\U0000220B',
+ "njcy;": '\U0000045A',
+ "nlArr;": '\U000021CD',
+ "nlarr;": '\U0000219A',
+ "nldr;": '\U00002025',
+ "nle;": '\U00002270',
+ "nleftarrow;": '\U0000219A',
+ "nleftrightarrow;": '\U000021AE',
+ "nleq;": '\U00002270',
+ "nless;": '\U0000226E',
+ "nlsim;": '\U00002274',
+ "nlt;": '\U0000226E',
+ "nltri;": '\U000022EA',
+ "nltrie;": '\U000022EC',
+ "nmid;": '\U00002224',
+ "nopf;": '\U0001D55F',
+ "not;": '\U000000AC',
+ "notin;": '\U00002209',
+ "notinva;": '\U00002209',
+ "notinvb;": '\U000022F7',
+ "notinvc;": '\U000022F6',
+ "notni;": '\U0000220C',
+ "notniva;": '\U0000220C',
+ "notnivb;": '\U000022FE',
+ "notnivc;": '\U000022FD',
+ "npar;": '\U00002226',
+ "nparallel;": '\U00002226',
+ "npolint;": '\U00002A14',
+ "npr;": '\U00002280',
+ "nprcue;": '\U000022E0',
+ "nprec;": '\U00002280',
+ "nrArr;": '\U000021CF',
+ "nrarr;": '\U0000219B',
+ "nrightarrow;": '\U0000219B',
+ "nrtri;": '\U000022EB',
+ "nrtrie;": '\U000022ED',
+ "nsc;": '\U00002281',
+ "nsccue;": '\U000022E1',
+ "nscr;": '\U0001D4C3',
+ "nshortmid;": '\U00002224',
+ "nshortparallel;": '\U00002226',
+ "nsim;": '\U00002241',
+ "nsime;": '\U00002244',
+ "nsimeq;": '\U00002244',
+ "nsmid;": '\U00002224',
+ "nspar;": '\U00002226',
+ "nsqsube;": '\U000022E2',
+ "nsqsupe;": '\U000022E3',
+ "nsub;": '\U00002284',
+ "nsube;": '\U00002288',
+ "nsubseteq;": '\U00002288',
+ "nsucc;": '\U00002281',
+ "nsup;": '\U00002285',
+ "nsupe;": '\U00002289',
+ "nsupseteq;": '\U00002289',
+ "ntgl;": '\U00002279',
+ "ntilde;": '\U000000F1',
+ "ntlg;": '\U00002278',
+ "ntriangleleft;": '\U000022EA',
+ "ntrianglelefteq;": '\U000022EC',
+ "ntriangleright;": '\U000022EB',
+ "ntrianglerighteq;": '\U000022ED',
+ "nu;": '\U000003BD',
+ "num;": '\U00000023',
+ "numero;": '\U00002116',
+ "numsp;": '\U00002007',
+ "nvDash;": '\U000022AD',
+ "nvHarr;": '\U00002904',
+ "nvdash;": '\U000022AC',
+ "nvinfin;": '\U000029DE',
+ "nvlArr;": '\U00002902',
+ "nvrArr;": '\U00002903',
+ "nwArr;": '\U000021D6',
+ "nwarhk;": '\U00002923',
+ "nwarr;": '\U00002196',
+ "nwarrow;": '\U00002196',
+ "nwnear;": '\U00002927',
+ "oS;": '\U000024C8',
+ "oacute;": '\U000000F3',
+ "oast;": '\U0000229B',
+ "ocir;": '\U0000229A',
+ "ocirc;": '\U000000F4',
+ "ocy;": '\U0000043E',
+ "odash;": '\U0000229D',
+ "odblac;": '\U00000151',
+ "odiv;": '\U00002A38',
+ "odot;": '\U00002299',
+ "odsold;": '\U000029BC',
+ "oelig;": '\U00000153',
+ "ofcir;": '\U000029BF',
+ "ofr;": '\U0001D52C',
+ "ogon;": '\U000002DB',
+ "ograve;": '\U000000F2',
+ "ogt;": '\U000029C1',
+ "ohbar;": '\U000029B5',
+ "ohm;": '\U000003A9',
+ "oint;": '\U0000222E',
+ "olarr;": '\U000021BA',
+ "olcir;": '\U000029BE',
+ "olcross;": '\U000029BB',
+ "oline;": '\U0000203E',
+ "olt;": '\U000029C0',
+ "omacr;": '\U0000014D',
+ "omega;": '\U000003C9',
+ "omicron;": '\U000003BF',
+ "omid;": '\U000029B6',
+ "ominus;": '\U00002296',
+ "oopf;": '\U0001D560',
+ "opar;": '\U000029B7',
+ "operp;": '\U000029B9',
+ "oplus;": '\U00002295',
+ "or;": '\U00002228',
+ "orarr;": '\U000021BB',
+ "ord;": '\U00002A5D',
+ "order;": '\U00002134',
+ "orderof;": '\U00002134',
+ "ordf;": '\U000000AA',
+ "ordm;": '\U000000BA',
+ "origof;": '\U000022B6',
+ "oror;": '\U00002A56',
+ "orslope;": '\U00002A57',
+ "orv;": '\U00002A5B',
+ "oscr;": '\U00002134',
+ "oslash;": '\U000000F8',
+ "osol;": '\U00002298',
+ "otilde;": '\U000000F5',
+ "otimes;": '\U00002297',
+ "otimesas;": '\U00002A36',
+ "ouml;": '\U000000F6',
+ "ovbar;": '\U0000233D',
+ "par;": '\U00002225',
+ "para;": '\U000000B6',
+ "parallel;": '\U00002225',
+ "parsim;": '\U00002AF3',
+ "parsl;": '\U00002AFD',
+ "part;": '\U00002202',
+ "pcy;": '\U0000043F',
+ "percnt;": '\U00000025',
+ "period;": '\U0000002E',
+ "permil;": '\U00002030',
+ "perp;": '\U000022A5',
+ "pertenk;": '\U00002031',
+ "pfr;": '\U0001D52D',
+ "phi;": '\U000003C6',
+ "phiv;": '\U000003D5',
+ "phmmat;": '\U00002133',
+ "phone;": '\U0000260E',
+ "pi;": '\U000003C0',
+ "pitchfork;": '\U000022D4',
+ "piv;": '\U000003D6',
+ "planck;": '\U0000210F',
+ "planckh;": '\U0000210E',
+ "plankv;": '\U0000210F',
+ "plus;": '\U0000002B',
+ "plusacir;": '\U00002A23',
+ "plusb;": '\U0000229E',
+ "pluscir;": '\U00002A22',
+ "plusdo;": '\U00002214',
+ "plusdu;": '\U00002A25',
+ "pluse;": '\U00002A72',
+ "plusmn;": '\U000000B1',
+ "plussim;": '\U00002A26',
+ "plustwo;": '\U00002A27',
+ "pm;": '\U000000B1',
+ "pointint;": '\U00002A15',
+ "popf;": '\U0001D561',
+ "pound;": '\U000000A3',
+ "pr;": '\U0000227A',
+ "prE;": '\U00002AB3',
+ "prap;": '\U00002AB7',
+ "prcue;": '\U0000227C',
+ "pre;": '\U00002AAF',
+ "prec;": '\U0000227A',
+ "precapprox;": '\U00002AB7',
+ "preccurlyeq;": '\U0000227C',
+ "preceq;": '\U00002AAF',
+ "precnapprox;": '\U00002AB9',
+ "precneqq;": '\U00002AB5',
+ "precnsim;": '\U000022E8',
+ "precsim;": '\U0000227E',
+ "prime;": '\U00002032',
+ "primes;": '\U00002119',
+ "prnE;": '\U00002AB5',
+ "prnap;": '\U00002AB9',
+ "prnsim;": '\U000022E8',
+ "prod;": '\U0000220F',
+ "profalar;": '\U0000232E',
+ "profline;": '\U00002312',
+ "profsurf;": '\U00002313',
+ "prop;": '\U0000221D',
+ "propto;": '\U0000221D',
+ "prsim;": '\U0000227E',
+ "prurel;": '\U000022B0',
+ "pscr;": '\U0001D4C5',
+ "psi;": '\U000003C8',
+ "puncsp;": '\U00002008',
+ "qfr;": '\U0001D52E',
+ "qint;": '\U00002A0C',
+ "qopf;": '\U0001D562',
+ "qprime;": '\U00002057',
+ "qscr;": '\U0001D4C6',
+ "quaternions;": '\U0000210D',
+ "quatint;": '\U00002A16',
+ "quest;": '\U0000003F',
+ "questeq;": '\U0000225F',
+ "quot;": '\U00000022',
+ "rAarr;": '\U000021DB',
+ "rArr;": '\U000021D2',
+ "rAtail;": '\U0000291C',
+ "rBarr;": '\U0000290F',
+ "rHar;": '\U00002964',
+ "racute;": '\U00000155',
+ "radic;": '\U0000221A',
+ "raemptyv;": '\U000029B3',
+ "rang;": '\U000027E9',
+ "rangd;": '\U00002992',
+ "range;": '\U000029A5',
+ "rangle;": '\U000027E9',
+ "raquo;": '\U000000BB',
+ "rarr;": '\U00002192',
+ "rarrap;": '\U00002975',
+ "rarrb;": '\U000021E5',
+ "rarrbfs;": '\U00002920',
+ "rarrc;": '\U00002933',
+ "rarrfs;": '\U0000291E',
+ "rarrhk;": '\U000021AA',
+ "rarrlp;": '\U000021AC',
+ "rarrpl;": '\U00002945',
+ "rarrsim;": '\U00002974',
+ "rarrtl;": '\U000021A3',
+ "rarrw;": '\U0000219D',
+ "ratail;": '\U0000291A',
+ "ratio;": '\U00002236',
+ "rationals;": '\U0000211A',
+ "rbarr;": '\U0000290D',
+ "rbbrk;": '\U00002773',
+ "rbrace;": '\U0000007D',
+ "rbrack;": '\U0000005D',
+ "rbrke;": '\U0000298C',
+ "rbrksld;": '\U0000298E',
+ "rbrkslu;": '\U00002990',
+ "rcaron;": '\U00000159',
+ "rcedil;": '\U00000157',
+ "rceil;": '\U00002309',
+ "rcub;": '\U0000007D',
+ "rcy;": '\U00000440',
+ "rdca;": '\U00002937',
+ "rdldhar;": '\U00002969',
+ "rdquo;": '\U0000201D',
+ "rdquor;": '\U0000201D',
+ "rdsh;": '\U000021B3',
+ "real;": '\U0000211C',
+ "realine;": '\U0000211B',
+ "realpart;": '\U0000211C',
+ "reals;": '\U0000211D',
+ "rect;": '\U000025AD',
+ "reg;": '\U000000AE',
+ "rfisht;": '\U0000297D',
+ "rfloor;": '\U0000230B',
+ "rfr;": '\U0001D52F',
+ "rhard;": '\U000021C1',
+ "rharu;": '\U000021C0',
+ "rharul;": '\U0000296C',
+ "rho;": '\U000003C1',
+ "rhov;": '\U000003F1',
+ "rightarrow;": '\U00002192',
+ "rightarrowtail;": '\U000021A3',
+ "rightharpoondown;": '\U000021C1',
+ "rightharpoonup;": '\U000021C0',
+ "rightleftarrows;": '\U000021C4',
+ "rightleftharpoons;": '\U000021CC',
+ "rightrightarrows;": '\U000021C9',
+ "rightsquigarrow;": '\U0000219D',
+ "rightthreetimes;": '\U000022CC',
+ "ring;": '\U000002DA',
+ "risingdotseq;": '\U00002253',
+ "rlarr;": '\U000021C4',
+ "rlhar;": '\U000021CC',
+ "rlm;": '\U0000200F',
+ "rmoust;": '\U000023B1',
+ "rmoustache;": '\U000023B1',
+ "rnmid;": '\U00002AEE',
+ "roang;": '\U000027ED',
+ "roarr;": '\U000021FE',
+ "robrk;": '\U000027E7',
+ "ropar;": '\U00002986',
+ "ropf;": '\U0001D563',
+ "roplus;": '\U00002A2E',
+ "rotimes;": '\U00002A35',
+ "rpar;": '\U00000029',
+ "rpargt;": '\U00002994',
+ "rppolint;": '\U00002A12',
+ "rrarr;": '\U000021C9',
+ "rsaquo;": '\U0000203A',
+ "rscr;": '\U0001D4C7',
+ "rsh;": '\U000021B1',
+ "rsqb;": '\U0000005D',
+ "rsquo;": '\U00002019',
+ "rsquor;": '\U00002019',
+ "rthree;": '\U000022CC',
+ "rtimes;": '\U000022CA',
+ "rtri;": '\U000025B9',
+ "rtrie;": '\U000022B5',
+ "rtrif;": '\U000025B8',
+ "rtriltri;": '\U000029CE',
+ "ruluhar;": '\U00002968',
+ "rx;": '\U0000211E',
+ "sacute;": '\U0000015B',
+ "sbquo;": '\U0000201A',
+ "sc;": '\U0000227B',
+ "scE;": '\U00002AB4',
+ "scap;": '\U00002AB8',
+ "scaron;": '\U00000161',
+ "sccue;": '\U0000227D',
+ "sce;": '\U00002AB0',
+ "scedil;": '\U0000015F',
+ "scirc;": '\U0000015D',
+ "scnE;": '\U00002AB6',
+ "scnap;": '\U00002ABA',
+ "scnsim;": '\U000022E9',
+ "scpolint;": '\U00002A13',
+ "scsim;": '\U0000227F',
+ "scy;": '\U00000441',
+ "sdot;": '\U000022C5',
+ "sdotb;": '\U000022A1',
+ "sdote;": '\U00002A66',
+ "seArr;": '\U000021D8',
+ "searhk;": '\U00002925',
+ "searr;": '\U00002198',
+ "searrow;": '\U00002198',
+ "sect;": '\U000000A7',
+ "semi;": '\U0000003B',
+ "seswar;": '\U00002929',
+ "setminus;": '\U00002216',
+ "setmn;": '\U00002216',
+ "sext;": '\U00002736',
+ "sfr;": '\U0001D530',
+ "sfrown;": '\U00002322',
+ "sharp;": '\U0000266F',
+ "shchcy;": '\U00000449',
+ "shcy;": '\U00000448',
+ "shortmid;": '\U00002223',
+ "shortparallel;": '\U00002225',
+ "shy;": '\U000000AD',
+ "sigma;": '\U000003C3',
+ "sigmaf;": '\U000003C2',
+ "sigmav;": '\U000003C2',
+ "sim;": '\U0000223C',
+ "simdot;": '\U00002A6A',
+ "sime;": '\U00002243',
+ "simeq;": '\U00002243',
+ "simg;": '\U00002A9E',
+ "simgE;": '\U00002AA0',
+ "siml;": '\U00002A9D',
+ "simlE;": '\U00002A9F',
+ "simne;": '\U00002246',
+ "simplus;": '\U00002A24',
+ "simrarr;": '\U00002972',
+ "slarr;": '\U00002190',
+ "smallsetminus;": '\U00002216',
+ "smashp;": '\U00002A33',
+ "smeparsl;": '\U000029E4',
+ "smid;": '\U00002223',
+ "smile;": '\U00002323',
+ "smt;": '\U00002AAA',
+ "smte;": '\U00002AAC',
+ "softcy;": '\U0000044C',
+ "sol;": '\U0000002F',
+ "solb;": '\U000029C4',
+ "solbar;": '\U0000233F',
+ "sopf;": '\U0001D564',
+ "spades;": '\U00002660',
+ "spadesuit;": '\U00002660',
+ "spar;": '\U00002225',
+ "sqcap;": '\U00002293',
+ "sqcup;": '\U00002294',
+ "sqsub;": '\U0000228F',
+ "sqsube;": '\U00002291',
+ "sqsubset;": '\U0000228F',
+ "sqsubseteq;": '\U00002291',
+ "sqsup;": '\U00002290',
+ "sqsupe;": '\U00002292',
+ "sqsupset;": '\U00002290',
+ "sqsupseteq;": '\U00002292',
+ "squ;": '\U000025A1',
+ "square;": '\U000025A1',
+ "squarf;": '\U000025AA',
+ "squf;": '\U000025AA',
+ "srarr;": '\U00002192',
+ "sscr;": '\U0001D4C8',
+ "ssetmn;": '\U00002216',
+ "ssmile;": '\U00002323',
+ "sstarf;": '\U000022C6',
+ "star;": '\U00002606',
+ "starf;": '\U00002605',
+ "straightepsilon;": '\U000003F5',
+ "straightphi;": '\U000003D5',
+ "strns;": '\U000000AF',
+ "sub;": '\U00002282',
+ "subE;": '\U00002AC5',
+ "subdot;": '\U00002ABD',
+ "sube;": '\U00002286',
+ "subedot;": '\U00002AC3',
+ "submult;": '\U00002AC1',
+ "subnE;": '\U00002ACB',
+ "subne;": '\U0000228A',
+ "subplus;": '\U00002ABF',
+ "subrarr;": '\U00002979',
+ "subset;": '\U00002282',
+ "subseteq;": '\U00002286',
+ "subseteqq;": '\U00002AC5',
+ "subsetneq;": '\U0000228A',
+ "subsetneqq;": '\U00002ACB',
+ "subsim;": '\U00002AC7',
+ "subsub;": '\U00002AD5',
+ "subsup;": '\U00002AD3',
+ "succ;": '\U0000227B',
+ "succapprox;": '\U00002AB8',
+ "succcurlyeq;": '\U0000227D',
+ "succeq;": '\U00002AB0',
+ "succnapprox;": '\U00002ABA',
+ "succneqq;": '\U00002AB6',
+ "succnsim;": '\U000022E9',
+ "succsim;": '\U0000227F',
+ "sum;": '\U00002211',
+ "sung;": '\U0000266A',
+ "sup;": '\U00002283',
+ "sup1;": '\U000000B9',
+ "sup2;": '\U000000B2',
+ "sup3;": '\U000000B3',
+ "supE;": '\U00002AC6',
+ "supdot;": '\U00002ABE',
+ "supdsub;": '\U00002AD8',
+ "supe;": '\U00002287',
+ "supedot;": '\U00002AC4',
+ "suphsol;": '\U000027C9',
+ "suphsub;": '\U00002AD7',
+ "suplarr;": '\U0000297B',
+ "supmult;": '\U00002AC2',
+ "supnE;": '\U00002ACC',
+ "supne;": '\U0000228B',
+ "supplus;": '\U00002AC0',
+ "supset;": '\U00002283',
+ "supseteq;": '\U00002287',
+ "supseteqq;": '\U00002AC6',
+ "supsetneq;": '\U0000228B',
+ "supsetneqq;": '\U00002ACC',
+ "supsim;": '\U00002AC8',
+ "supsub;": '\U00002AD4',
+ "supsup;": '\U00002AD6',
+ "swArr;": '\U000021D9',
+ "swarhk;": '\U00002926',
+ "swarr;": '\U00002199',
+ "swarrow;": '\U00002199',
+ "swnwar;": '\U0000292A',
+ "szlig;": '\U000000DF',
+ "target;": '\U00002316',
+ "tau;": '\U000003C4',
+ "tbrk;": '\U000023B4',
+ "tcaron;": '\U00000165',
+ "tcedil;": '\U00000163',
+ "tcy;": '\U00000442',
+ "tdot;": '\U000020DB',
+ "telrec;": '\U00002315',
+ "tfr;": '\U0001D531',
+ "there4;": '\U00002234',
+ "therefore;": '\U00002234',
+ "theta;": '\U000003B8',
+ "thetasym;": '\U000003D1',
+ "thetav;": '\U000003D1',
+ "thickapprox;": '\U00002248',
+ "thicksim;": '\U0000223C',
+ "thinsp;": '\U00002009',
+ "thkap;": '\U00002248',
+ "thksim;": '\U0000223C',
+ "thorn;": '\U000000FE',
+ "tilde;": '\U000002DC',
+ "times;": '\U000000D7',
+ "timesb;": '\U000022A0',
+ "timesbar;": '\U00002A31',
+ "timesd;": '\U00002A30',
+ "tint;": '\U0000222D',
+ "toea;": '\U00002928',
+ "top;": '\U000022A4',
+ "topbot;": '\U00002336',
+ "topcir;": '\U00002AF1',
+ "topf;": '\U0001D565',
+ "topfork;": '\U00002ADA',
+ "tosa;": '\U00002929',
+ "tprime;": '\U00002034',
+ "trade;": '\U00002122',
+ "triangle;": '\U000025B5',
+ "triangledown;": '\U000025BF',
+ "triangleleft;": '\U000025C3',
+ "trianglelefteq;": '\U000022B4',
+ "triangleq;": '\U0000225C',
+ "triangleright;": '\U000025B9',
+ "trianglerighteq;": '\U000022B5',
+ "tridot;": '\U000025EC',
+ "trie;": '\U0000225C',
+ "triminus;": '\U00002A3A',
+ "triplus;": '\U00002A39',
+ "trisb;": '\U000029CD',
+ "tritime;": '\U00002A3B',
+ "trpezium;": '\U000023E2',
+ "tscr;": '\U0001D4C9',
+ "tscy;": '\U00000446',
+ "tshcy;": '\U0000045B',
+ "tstrok;": '\U00000167',
+ "twixt;": '\U0000226C',
+ "twoheadleftarrow;": '\U0000219E',
+ "twoheadrightarrow;": '\U000021A0',
+ "uArr;": '\U000021D1',
+ "uHar;": '\U00002963',
+ "uacute;": '\U000000FA',
+ "uarr;": '\U00002191',
+ "ubrcy;": '\U0000045E',
+ "ubreve;": '\U0000016D',
+ "ucirc;": '\U000000FB',
+ "ucy;": '\U00000443',
+ "udarr;": '\U000021C5',
+ "udblac;": '\U00000171',
+ "udhar;": '\U0000296E',
+ "ufisht;": '\U0000297E',
+ "ufr;": '\U0001D532',
+ "ugrave;": '\U000000F9',
+ "uharl;": '\U000021BF',
+ "uharr;": '\U000021BE',
+ "uhblk;": '\U00002580',
+ "ulcorn;": '\U0000231C',
+ "ulcorner;": '\U0000231C',
+ "ulcrop;": '\U0000230F',
+ "ultri;": '\U000025F8',
+ "umacr;": '\U0000016B',
+ "uml;": '\U000000A8',
+ "uogon;": '\U00000173',
+ "uopf;": '\U0001D566',
+ "uparrow;": '\U00002191',
+ "updownarrow;": '\U00002195',
+ "upharpoonleft;": '\U000021BF',
+ "upharpoonright;": '\U000021BE',
+ "uplus;": '\U0000228E',
+ "upsi;": '\U000003C5',
+ "upsih;": '\U000003D2',
+ "upsilon;": '\U000003C5',
+ "upuparrows;": '\U000021C8',
+ "urcorn;": '\U0000231D',
+ "urcorner;": '\U0000231D',
+ "urcrop;": '\U0000230E',
+ "uring;": '\U0000016F',
+ "urtri;": '\U000025F9',
+ "uscr;": '\U0001D4CA',
+ "utdot;": '\U000022F0',
+ "utilde;": '\U00000169',
+ "utri;": '\U000025B5',
+ "utrif;": '\U000025B4',
+ "uuarr;": '\U000021C8',
+ "uuml;": '\U000000FC',
+ "uwangle;": '\U000029A7',
+ "vArr;": '\U000021D5',
+ "vBar;": '\U00002AE8',
+ "vBarv;": '\U00002AE9',
+ "vDash;": '\U000022A8',
+ "vangrt;": '\U0000299C',
+ "varepsilon;": '\U000003F5',
+ "varkappa;": '\U000003F0',
+ "varnothing;": '\U00002205',
+ "varphi;": '\U000003D5',
+ "varpi;": '\U000003D6',
+ "varpropto;": '\U0000221D',
+ "varr;": '\U00002195',
+ "varrho;": '\U000003F1',
+ "varsigma;": '\U000003C2',
+ "vartheta;": '\U000003D1',
+ "vartriangleleft;": '\U000022B2',
+ "vartriangleright;": '\U000022B3',
+ "vcy;": '\U00000432',
+ "vdash;": '\U000022A2',
+ "vee;": '\U00002228',
+ "veebar;": '\U000022BB',
+ "veeeq;": '\U0000225A',
+ "vellip;": '\U000022EE',
+ "verbar;": '\U0000007C',
+ "vert;": '\U0000007C',
+ "vfr;": '\U0001D533',
+ "vltri;": '\U000022B2',
+ "vopf;": '\U0001D567',
+ "vprop;": '\U0000221D',
+ "vrtri;": '\U000022B3',
+ "vscr;": '\U0001D4CB',
+ "vzigzag;": '\U0000299A',
+ "wcirc;": '\U00000175',
+ "wedbar;": '\U00002A5F',
+ "wedge;": '\U00002227',
+ "wedgeq;": '\U00002259',
+ "weierp;": '\U00002118',
+ "wfr;": '\U0001D534',
+ "wopf;": '\U0001D568',
+ "wp;": '\U00002118',
+ "wr;": '\U00002240',
+ "wreath;": '\U00002240',
+ "wscr;": '\U0001D4CC',
+ "xcap;": '\U000022C2',
+ "xcirc;": '\U000025EF',
+ "xcup;": '\U000022C3',
+ "xdtri;": '\U000025BD',
+ "xfr;": '\U0001D535',
+ "xhArr;": '\U000027FA',
+ "xharr;": '\U000027F7',
+ "xi;": '\U000003BE',
+ "xlArr;": '\U000027F8',
+ "xlarr;": '\U000027F5',
+ "xmap;": '\U000027FC',
+ "xnis;": '\U000022FB',
+ "xodot;": '\U00002A00',
+ "xopf;": '\U0001D569',
+ "xoplus;": '\U00002A01',
+ "xotime;": '\U00002A02',
+ "xrArr;": '\U000027F9',
+ "xrarr;": '\U000027F6',
+ "xscr;": '\U0001D4CD',
+ "xsqcup;": '\U00002A06',
+ "xuplus;": '\U00002A04',
+ "xutri;": '\U000025B3',
+ "xvee;": '\U000022C1',
+ "xwedge;": '\U000022C0',
+ "yacute;": '\U000000FD',
+ "yacy;": '\U0000044F',
+ "ycirc;": '\U00000177',
+ "ycy;": '\U0000044B',
+ "yen;": '\U000000A5',
+ "yfr;": '\U0001D536',
+ "yicy;": '\U00000457',
+ "yopf;": '\U0001D56A',
+ "yscr;": '\U0001D4CE',
+ "yucy;": '\U0000044E',
+ "yuml;": '\U000000FF',
+ "zacute;": '\U0000017A',
+ "zcaron;": '\U0000017E',
+ "zcy;": '\U00000437',
+ "zdot;": '\U0000017C',
+ "zeetrf;": '\U00002128',
+ "zeta;": '\U000003B6',
+ "zfr;": '\U0001D537',
+ "zhcy;": '\U00000436',
+ "zigrarr;": '\U000021DD',
+ "zopf;": '\U0001D56B',
+ "zscr;": '\U0001D4CF',
+ "zwj;": '\U0000200D',
+ "zwnj;": '\U0000200C',
+ "AElig": '\U000000C6',
+ "AMP": '\U00000026',
+ "Aacute": '\U000000C1',
+ "Acirc": '\U000000C2',
+ "Agrave": '\U000000C0',
+ "Aring": '\U000000C5',
+ "Atilde": '\U000000C3',
+ "Auml": '\U000000C4',
+ "COPY": '\U000000A9',
+ "Ccedil": '\U000000C7',
+ "ETH": '\U000000D0',
+ "Eacute": '\U000000C9',
+ "Ecirc": '\U000000CA',
+ "Egrave": '\U000000C8',
+ "Euml": '\U000000CB',
+ "GT": '\U0000003E',
+ "Iacute": '\U000000CD',
+ "Icirc": '\U000000CE',
+ "Igrave": '\U000000CC',
+ "Iuml": '\U000000CF',
+ "LT": '\U0000003C',
+ "Ntilde": '\U000000D1',
+ "Oacute": '\U000000D3',
+ "Ocirc": '\U000000D4',
+ "Ograve": '\U000000D2',
+ "Oslash": '\U000000D8',
+ "Otilde": '\U000000D5',
+ "Ouml": '\U000000D6',
+ "QUOT": '\U00000022',
+ "REG": '\U000000AE',
+ "THORN": '\U000000DE',
+ "Uacute": '\U000000DA',
+ "Ucirc": '\U000000DB',
+ "Ugrave": '\U000000D9',
+ "Uuml": '\U000000DC',
+ "Yacute": '\U000000DD',
+ "aacute": '\U000000E1',
+ "acirc": '\U000000E2',
+ "acute": '\U000000B4',
+ "aelig": '\U000000E6',
+ "agrave": '\U000000E0',
+ "amp": '\U00000026',
+ "aring": '\U000000E5',
+ "atilde": '\U000000E3',
+ "auml": '\U000000E4',
+ "brvbar": '\U000000A6',
+ "ccedil": '\U000000E7',
+ "cedil": '\U000000B8',
+ "cent": '\U000000A2',
+ "copy": '\U000000A9',
+ "curren": '\U000000A4',
+ "deg": '\U000000B0',
+ "divide": '\U000000F7',
+ "eacute": '\U000000E9',
+ "ecirc": '\U000000EA',
+ "egrave": '\U000000E8',
+ "eth": '\U000000F0',
+ "euml": '\U000000EB',
+ "frac12": '\U000000BD',
+ "frac14": '\U000000BC',
+ "frac34": '\U000000BE',
+ "gt": '\U0000003E',
+ "iacute": '\U000000ED',
+ "icirc": '\U000000EE',
+ "iexcl": '\U000000A1',
+ "igrave": '\U000000EC',
+ "iquest": '\U000000BF',
+ "iuml": '\U000000EF',
+ "laquo": '\U000000AB',
+ "lt": '\U0000003C',
+ "macr": '\U000000AF',
+ "micro": '\U000000B5',
+ "middot": '\U000000B7',
+ "nbsp": '\U000000A0',
+ "not": '\U000000AC',
+ "ntilde": '\U000000F1',
+ "oacute": '\U000000F3',
+ "ocirc": '\U000000F4',
+ "ograve": '\U000000F2',
+ "ordf": '\U000000AA',
+ "ordm": '\U000000BA',
+ "oslash": '\U000000F8',
+ "otilde": '\U000000F5',
+ "ouml": '\U000000F6',
+ "para": '\U000000B6',
+ "plusmn": '\U000000B1',
+ "pound": '\U000000A3',
+ "quot": '\U00000022',
+ "raquo": '\U000000BB',
+ "reg": '\U000000AE',
+ "sect": '\U000000A7',
+ "shy": '\U000000AD',
+ "sup1": '\U000000B9',
+ "sup2": '\U000000B2',
+ "sup3": '\U000000B3',
+ "szlig": '\U000000DF',
+ "thorn": '\U000000FE',
+ "times": '\U000000D7',
+ "uacute": '\U000000FA',
+ "ucirc": '\U000000FB',
+ "ugrave": '\U000000F9',
+ "uml": '\U000000A8',
+ "uuml": '\U000000FC',
+ "yacute": '\U000000FD',
+ "yen": '\U000000A5',
+ "yuml": '\U000000FF',
}
// HTML entities that are two unicode codepoints.
diff --git a/libgo/go/exp/html/escape.go b/libgo/go/exp/html/escape.go
index 8f62a8c2880..7827dc2d506 100644
--- a/libgo/go/exp/html/escape.go
+++ b/libgo/go/exp/html/escape.go
@@ -163,14 +163,15 @@ func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
}
// unescape unescapes b's entities in-place, so that "a&lt;b" becomes "a<b".
-func unescape(b []byte) []byte {
+// attribute should be true if parsing an attribute value.
+func unescape(b []byte, attribute bool) []byte {
for i, c := range b {
if c == '&' {
- dst, src := unescapeEntity(b, i, i, false)
+ dst, src := unescapeEntity(b, i, i, attribute)
for src < len(b) {
c := b[src]
if c == '&' {
- dst, src = unescapeEntity(b, dst, src, false)
+ dst, src = unescapeEntity(b, dst, src, attribute)
} else {
b[dst] = c
dst, src = dst+1, src+1
@@ -192,7 +193,7 @@ func lower(b []byte) []byte {
return b
}
-const escapedChars = `&'<>"`
+const escapedChars = "&'<>\"\r"
func escape(w writer, s string) error {
i := strings.IndexAny(s, escapedChars)
@@ -205,13 +206,17 @@ func escape(w writer, s string) error {
case '&':
esc = "&amp;"
case '\'':
- esc = "&apos;"
+ // "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
+ esc = "&#39;"
case '<':
esc = "&lt;"
case '>':
esc = "&gt;"
case '"':
- esc = "&quot;"
+ // "&#34;" is shorter than "&quot;".
+ esc = "&#34;"
+ case '\r':
+ esc = "&#13;"
default:
panic("unrecognized escape character")
}
@@ -226,7 +231,7 @@ func escape(w writer, s string) error {
}
// EscapeString escapes special characters like "<" to become "&lt;". It
-// escapes only five such characters: amp, apos, lt, gt and quot.
+// escapes only five such characters: <, >, &, ' and ".
// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
// always true.
func EscapeString(s string) string {
@@ -246,7 +251,7 @@ func EscapeString(s string) string {
func UnescapeString(s string) string {
for _, c := range s {
if c == '&' {
- return string(unescape([]byte(s)))
+ return string(unescape([]byte(s), false))
}
}
return s
diff --git a/libgo/go/exp/html/foreign.go b/libgo/go/exp/html/foreign.go
index 3ba81ce4d6f..d3b3844099b 100644
--- a/libgo/go/exp/html/foreign.go
+++ b/libgo/go/exp/html/foreign.go
@@ -8,6 +8,14 @@ import (
"strings"
)
+func adjustAttributeNames(aa []Attribute, nameMap map[string]string) {
+ for i := range aa {
+ if newName, ok := nameMap[aa[i].Key]; ok {
+ aa[i].Key = newName
+ }
+ }
+}
+
func adjustForeignAttributes(aa []Attribute) {
for i, a := range aa {
if a.Key == "" || a.Key[0] != 'x' {
@@ -29,8 +37,16 @@ func htmlIntegrationPoint(n *Node) bool {
}
switch n.Namespace {
case "math":
- // TODO: annotation-xml elements whose start tags have "text/html" or
- // "application/xhtml+xml" encodings.
+ if n.Data == "annotation-xml" {
+ for _, a := range n.Attr {
+ if a.Key == "encoding" {
+ val := strings.ToLower(a.Val)
+ if val == "text/html" || val == "application/xhtml+xml" {
+ return true
+ }
+ }
+ }
+ }
case "svg":
switch n.Data {
case "desc", "foreignObject", "title":
@@ -40,6 +56,17 @@ func htmlIntegrationPoint(n *Node) bool {
return false
}
+func mathMLTextIntegrationPoint(n *Node) bool {
+ if n.Namespace != "math" {
+ return false
+ }
+ switch n.Data {
+ case "mi", "mo", "mn", "ms", "mtext":
+ return true
+ }
+ return false
+}
+
// Section 12.2.5.5.
var breakout = map[string]bool{
"b": true,
@@ -55,7 +82,6 @@ var breakout = map[string]bool{
"dt": true,
"em": true,
"embed": true,
- "font": true,
"h1": true,
"h2": true,
"h3": true,
@@ -129,4 +155,72 @@ var svgTagNameAdjustments = map[string]string{
"textpath": "textPath",
}
-// TODO: add look-up tables for MathML and SVG attribute adjustments.
+// Section 12.2.5.1
+var mathMLAttributeAdjustments = map[string]string{
+ "definitionurl": "definitionURL",
+}
+
+var svgAttributeAdjustments = map[string]string{
+ "attributename": "attributeName",
+ "attributetype": "attributeType",
+ "basefrequency": "baseFrequency",
+ "baseprofile": "baseProfile",
+ "calcmode": "calcMode",
+ "clippathunits": "clipPathUnits",
+ "contentscripttype": "contentScriptType",
+ "contentstyletype": "contentStyleType",
+ "diffuseconstant": "diffuseConstant",
+ "edgemode": "edgeMode",
+ "externalresourcesrequired": "externalResourcesRequired",
+ "filterres": "filterRes",
+ "filterunits": "filterUnits",
+ "glyphref": "glyphRef",
+ "gradienttransform": "gradientTransform",
+ "gradientunits": "gradientUnits",
+ "kernelmatrix": "kernelMatrix",
+ "kernelunitlength": "kernelUnitLength",
+ "keypoints": "keyPoints",
+ "keysplines": "keySplines",
+ "keytimes": "keyTimes",
+ "lengthadjust": "lengthAdjust",
+ "limitingconeangle": "limitingConeAngle",
+ "markerheight": "markerHeight",
+ "markerunits": "markerUnits",
+ "markerwidth": "markerWidth",
+ "maskcontentunits": "maskContentUnits",
+ "maskunits": "maskUnits",
+ "numoctaves": "numOctaves",
+ "pathlength": "pathLength",
+ "patterncontentunits": "patternContentUnits",
+ "patterntransform": "patternTransform",
+ "patternunits": "patternUnits",
+ "pointsatx": "pointsAtX",
+ "pointsaty": "pointsAtY",
+ "pointsatz": "pointsAtZ",
+ "preservealpha": "preserveAlpha",
+ "preserveaspectratio": "preserveAspectRatio",
+ "primitiveunits": "primitiveUnits",
+ "refx": "refX",
+ "refy": "refY",
+ "repeatcount": "repeatCount",
+ "repeatdur": "repeatDur",
+ "requiredextensions": "requiredExtensions",
+ "requiredfeatures": "requiredFeatures",
+ "specularconstant": "specularConstant",
+ "specularexponent": "specularExponent",
+ "spreadmethod": "spreadMethod",
+ "startoffset": "startOffset",
+ "stddeviation": "stdDeviation",
+ "stitchtiles": "stitchTiles",
+ "surfacescale": "surfaceScale",
+ "systemlanguage": "systemLanguage",
+ "tablevalues": "tableValues",
+ "targetx": "targetX",
+ "targety": "targetY",
+ "textlength": "textLength",
+ "viewbox": "viewBox",
+ "viewtarget": "viewTarget",
+ "xchannelselector": "xChannelSelector",
+ "ychannelselector": "yChannelSelector",
+ "zoomandpan": "zoomAndPan",
+}
diff --git a/libgo/go/exp/html/node.go b/libgo/go/exp/html/node.go
index c105a4e709a..01f8c42ce3a 100644
--- a/libgo/go/exp/html/node.go
+++ b/libgo/go/exp/html/node.go
@@ -4,8 +4,12 @@
package html
+import (
+ "exp/html/atom"
+)
+
// A NodeType is the type of a Node.
-type NodeType int
+type NodeType uint32
const (
ErrorNode NodeType = iota
@@ -25,67 +29,115 @@ var scopeMarker = Node{Type: scopeMarkerNode}
// A Node consists of a NodeType and some Data (tag name for element nodes,
// content for text) and are part of a tree of Nodes. Element nodes may also
// have a Namespace and contain a slice of Attributes. Data is unescaped, so
-// that it looks like "a<b" rather than "a&lt;b".
+// that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
+// is the atom for Data, or zero if Data is not a known tag name.
//
// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
// "svg" is short for "http://www.w3.org/2000/svg".
type Node struct {
- Parent *Node
- Child []*Node
+ Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
+
Type NodeType
+ DataAtom atom.Atom
Data string
Namespace string
Attr []Attribute
}
-// Add adds a node as a child of n.
-// It will panic if the child's parent is not nil.
-func (n *Node) Add(child *Node) {
- if child.Parent != nil {
- panic("html: Node.Add called for a child Node that already has a parent")
+// InsertBefore inserts newChild as a child of n, immediately before oldChild
+// in the sequence of n's children. oldChild may be nil, in which case newChild
+// is appended to the end of n's children.
+//
+// It will panic if newChild already has a parent or siblings.
+func (n *Node) InsertBefore(newChild, oldChild *Node) {
+ if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {
+ panic("html: InsertBefore called for an attached child Node")
+ }
+ var prev, next *Node
+ if oldChild != nil {
+ prev, next = oldChild.PrevSibling, oldChild
+ } else {
+ prev = n.LastChild
+ }
+ if prev != nil {
+ prev.NextSibling = newChild
+ } else {
+ n.FirstChild = newChild
+ }
+ if next != nil {
+ next.PrevSibling = newChild
+ } else {
+ n.LastChild = newChild
}
- child.Parent = n
- n.Child = append(n.Child, child)
+ newChild.Parent = n
+ newChild.PrevSibling = prev
+ newChild.NextSibling = next
}
-// Remove removes a node as a child of n.
-// It will panic if the child's parent is not n.
-func (n *Node) Remove(child *Node) {
- if child.Parent == n {
- child.Parent = nil
- for i, m := range n.Child {
- if m == child {
- copy(n.Child[i:], n.Child[i+1:])
- j := len(n.Child) - 1
- n.Child[j] = nil
- n.Child = n.Child[:j]
- return
- }
- }
+// AppendChild adds a node c as a child of n.
+//
+// It will panic if c already has a parent or siblings.
+func (n *Node) AppendChild(c *Node) {
+ if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
+ panic("html: AppendChild called for an attached child Node")
+ }
+ last := n.LastChild
+ if last != nil {
+ last.NextSibling = c
+ } else {
+ n.FirstChild = c
}
- panic("html: Node.Remove called for a non-child Node")
+ n.LastChild = c
+ c.Parent = n
+ c.PrevSibling = last
+}
+
+// RemoveChild removes a node c that is a child of n. Afterwards, c will have
+// no parent and no siblings.
+//
+// It will panic if c's parent is not n.
+func (n *Node) RemoveChild(c *Node) {
+ if c.Parent != n {
+ panic("html: RemoveChild called for a non-child Node")
+ }
+ if n.FirstChild == c {
+ n.FirstChild = c.NextSibling
+ }
+ if c.NextSibling != nil {
+ c.NextSibling.PrevSibling = c.PrevSibling
+ }
+ if n.LastChild == c {
+ n.LastChild = c.PrevSibling
+ }
+ if c.PrevSibling != nil {
+ c.PrevSibling.NextSibling = c.NextSibling
+ }
+ c.Parent = nil
+ c.PrevSibling = nil
+ c.NextSibling = nil
}
// reparentChildren reparents all of src's child nodes to dst.
func reparentChildren(dst, src *Node) {
- for _, n := range src.Child {
- if n.Parent != src {
- panic("html: nodes have an inconsistent parent/child relationship")
+ for {
+ child := src.FirstChild
+ if child == nil {
+ break
}
- n.Parent = dst
+ src.RemoveChild(child)
+ dst.AppendChild(child)
}
- dst.Child = append(dst.Child, src.Child...)
- src.Child = nil
}
// clone returns a new node with the same type, data and attributes.
-// The clone has no parent and no children.
+// The clone has no parent, no siblings and no children.
func (n *Node) clone() *Node {
m := &Node{
- Type: n.Type,
- Data: n.Data,
- Attr: make([]Attribute, len(n.Attr)),
+ Type: n.Type,
+ DataAtom: n.DataAtom,
+ Data: n.Data,
+ Attr: make([]Attribute, len(n.Attr)),
}
copy(m.Attr, n.Attr)
return m
@@ -139,16 +191,3 @@ func (s *nodeStack) remove(n *Node) {
(*s)[j] = nil
*s = (*s)[:j]
}
-
-// TODO(nigeltao): forTag no longer used. Should it be deleted?
-
-// forTag returns the top-most element node with the given tag.
-func (s *nodeStack) forTag(tag string) *Node {
- for i := len(*s) - 1; i >= 0; i-- {
- n := (*s)[i]
- if n.Type == ElementNode && n.Data == tag {
- return n
- }
- }
- return nil
-}
diff --git a/libgo/go/exp/html/node_test.go b/libgo/go/exp/html/node_test.go
new file mode 100644
index 00000000000..471102f3a22
--- /dev/null
+++ b/libgo/go/exp/html/node_test.go
@@ -0,0 +1,146 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "fmt"
+)
+
+// checkTreeConsistency checks that a node and its descendants are all
+// consistent in their parent/child/sibling relationships.
+func checkTreeConsistency(n *Node) error {
+ return checkTreeConsistency1(n, 0)
+}
+
+func checkTreeConsistency1(n *Node, depth int) error {
+ if depth == 1e4 {
+ return fmt.Errorf("html: tree looks like it contains a cycle")
+ }
+ if err := checkNodeConsistency(n); err != nil {
+ return err
+ }
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if err := checkTreeConsistency1(c, depth+1); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// checkNodeConsistency checks that a node's parent/child/sibling relationships
+// are consistent.
+func checkNodeConsistency(n *Node) error {
+ if n == nil {
+ return nil
+ }
+
+ nParent := 0
+ for p := n.Parent; p != nil; p = p.Parent {
+ nParent++
+ if nParent == 1e4 {
+ return fmt.Errorf("html: parent list looks like an infinite loop")
+ }
+ }
+
+ nForward := 0
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ nForward++
+ if nForward == 1e6 {
+ return fmt.Errorf("html: forward list of children looks like an infinite loop")
+ }
+ if c.Parent != n {
+ return fmt.Errorf("html: inconsistent child/parent relationship")
+ }
+ }
+
+ nBackward := 0
+ for c := n.LastChild; c != nil; c = c.PrevSibling {
+ nBackward++
+ if nBackward == 1e6 {
+ return fmt.Errorf("html: backward list of children looks like an infinite loop")
+ }
+ if c.Parent != n {
+ return fmt.Errorf("html: inconsistent child/parent relationship")
+ }
+ }
+
+ if n.Parent != nil {
+ if n.Parent == n {
+ return fmt.Errorf("html: inconsistent parent relationship")
+ }
+ if n.Parent == n.FirstChild {
+ return fmt.Errorf("html: inconsistent parent/first relationship")
+ }
+ if n.Parent == n.LastChild {
+ return fmt.Errorf("html: inconsistent parent/last relationship")
+ }
+ if n.Parent == n.PrevSibling {
+ return fmt.Errorf("html: inconsistent parent/prev relationship")
+ }
+ if n.Parent == n.NextSibling {
+ return fmt.Errorf("html: inconsistent parent/next relationship")
+ }
+
+ parentHasNAsAChild := false
+ for c := n.Parent.FirstChild; c != nil; c = c.NextSibling {
+ if c == n {
+ parentHasNAsAChild = true
+ break
+ }
+ }
+ if !parentHasNAsAChild {
+ return fmt.Errorf("html: inconsistent parent/child relationship")
+ }
+ }
+
+ if n.PrevSibling != nil && n.PrevSibling.NextSibling != n {
+ return fmt.Errorf("html: inconsistent prev/next relationship")
+ }
+ if n.NextSibling != nil && n.NextSibling.PrevSibling != n {
+ return fmt.Errorf("html: inconsistent next/prev relationship")
+ }
+
+ if (n.FirstChild == nil) != (n.LastChild == nil) {
+ return fmt.Errorf("html: inconsistent first/last relationship")
+ }
+ if n.FirstChild != nil && n.FirstChild == n.LastChild {
+ // We have a sole child.
+ if n.FirstChild.PrevSibling != nil || n.FirstChild.NextSibling != nil {
+ return fmt.Errorf("html: inconsistent sole child's sibling relationship")
+ }
+ }
+
+ seen := map[*Node]bool{}
+
+ var last *Node
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if seen[c] {
+ return fmt.Errorf("html: inconsistent repeated child")
+ }
+ seen[c] = true
+ last = c
+ }
+ if last != n.LastChild {
+ return fmt.Errorf("html: inconsistent last relationship")
+ }
+
+ var first *Node
+ for c := n.LastChild; c != nil; c = c.PrevSibling {
+ if !seen[c] {
+ return fmt.Errorf("html: inconsistent missing child")
+ }
+ delete(seen, c)
+ first = c
+ }
+ if first != n.FirstChild {
+ return fmt.Errorf("html: inconsistent first relationship")
+ }
+
+ if len(seen) != 0 {
+ return fmt.Errorf("html: inconsistent forwards/backwards child list")
+ }
+
+ return nil
+}
diff --git a/libgo/go/exp/html/parse.go b/libgo/go/exp/html/parse.go
index 04f4ae75334..cae836e14b4 100644
--- a/libgo/go/exp/html/parse.go
+++ b/libgo/go/exp/html/parse.go
@@ -5,6 +5,9 @@
package html
import (
+ "errors"
+ a "exp/html/atom"
+ "fmt"
"io"
"strings"
)
@@ -16,9 +19,8 @@ type parser struct {
tokenizer *Tokenizer
// tok is the most recently read token.
tok Token
- // Self-closing tags like <hr/> are re-interpreted as a two-token sequence:
- // <hr> followed by </hr>. hasSelfClosingToken is true if we have just read
- // the synthetic start tag and the next one due is the matching end tag.
+ // Self-closing tags like <hr/> are treated as start tags, except that
+ // hasSelfClosingToken is set while they are being processed.
hasSelfClosingToken bool
// doc is the document root element.
doc *Node
@@ -39,6 +41,8 @@ type parser struct {
fosterParenting bool
// quirks is whether the parser is operating in "quirks mode."
quirks bool
+ // fragment is whether the parser is parsing an HTML fragment.
+ fragment bool
// context is the context element when parsing an HTML fragment
// (section 12.4).
context *Node
@@ -53,10 +57,10 @@ func (p *parser) top() *Node {
// Stop tags for use in popUntil. These come from section 12.2.3.2.
var (
- defaultScopeStopTags = map[string][]string{
- "": {"applet", "caption", "html", "table", "td", "th", "marquee", "object"},
- "math": {"annotation-xml", "mi", "mn", "mo", "ms", "mtext"},
- "svg": {"desc", "foreignObject", "title"},
+ defaultScopeStopTags = map[string][]a.Atom{
+ "": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object},
+ "math": {a.AnnotationXml, a.Mi, a.Mn, a.Mo, a.Ms, a.Mtext},
+ "svg": {a.Desc, a.ForeignObject, a.Title},
}
)
@@ -68,6 +72,8 @@ const (
buttonScope
tableScope
tableRowScope
+ tableBodyScope
+ selectScope
)
// popUntil pops the stack of open elements at the highest element whose tag
@@ -87,7 +93,7 @@ const (
// no higher element in the stack that was also in the stop tags). For example,
// popUntil(tableScope, "table") returns true and leaves:
// ["html", "body", "font"]
-func (p *parser) popUntil(s scope, matchTags ...string) bool {
+func (p *parser) popUntil(s scope, matchTags ...a.Atom) bool {
if i := p.indexOfElementInScope(s, matchTags...); i != -1 {
p.oe = p.oe[:i]
return true
@@ -98,12 +104,12 @@ func (p *parser) popUntil(s scope, matchTags ...string) bool {
// indexOfElementInScope returns the index in p.oe of the highest element whose
// tag is in matchTags that is in scope. If no matching element is in scope, it
// returns -1.
-func (p *parser) indexOfElementInScope(s scope, matchTags ...string) int {
+func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
for i := len(p.oe) - 1; i >= 0; i-- {
- tag := p.oe[i].Data
+ tagAtom := p.oe[i].DataAtom
if p.oe[i].Namespace == "" {
for _, t := range matchTags {
- if t == tag {
+ if t == tagAtom {
return i
}
}
@@ -111,15 +117,19 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...string) int {
case defaultScope:
// No-op.
case listItemScope:
- if tag == "ol" || tag == "ul" {
+ if tagAtom == a.Ol || tagAtom == a.Ul {
return -1
}
case buttonScope:
- if tag == "button" {
+ if tagAtom == a.Button {
return -1
}
case tableScope:
- if tag == "html" || tag == "table" {
+ if tagAtom == a.Html || tagAtom == a.Table {
+ return -1
+ }
+ case selectScope:
+ if tagAtom != a.Optgroup && tagAtom != a.Option {
return -1
}
default:
@@ -129,7 +139,7 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...string) int {
switch s {
case defaultScope, listItemScope, buttonScope:
for _, t := range defaultScopeStopTags[p.oe[i].Namespace] {
- if t == tag {
+ if t == tagAtom {
return -1
}
}
@@ -140,7 +150,7 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...string) int {
// elementInScope is like popUntil, except that it doesn't modify the stack of
// open elements.
-func (p *parser) elementInScope(s scope, matchTags ...string) bool {
+func (p *parser) elementInScope(s scope, matchTags ...a.Atom) bool {
return p.indexOfElementInScope(s, matchTags...) != -1
}
@@ -148,15 +158,20 @@ func (p *parser) elementInScope(s scope, matchTags ...string) bool {
// scope-defined element is found.
func (p *parser) clearStackToContext(s scope) {
for i := len(p.oe) - 1; i >= 0; i-- {
- tag := p.oe[i].Data
+ tagAtom := p.oe[i].DataAtom
switch s {
case tableScope:
- if tag == "html" || tag == "table" {
+ if tagAtom == a.Html || tagAtom == a.Table {
p.oe = p.oe[:i+1]
return
}
case tableRowScope:
- if tag == "html" || tag == "tr" {
+ if tagAtom == a.Html || tagAtom == a.Tr {
+ p.oe = p.oe[:i+1]
+ return
+ }
+ case tableBodyScope:
+ if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead {
p.oe = p.oe[:i+1]
return
}
@@ -166,13 +181,38 @@ func (p *parser) clearStackToContext(s scope) {
}
}
+// generateImpliedEndTags pops nodes off the stack of open elements as long as
+// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt.
+// If exceptions are specified, nodes with that name will not be popped off.
+func (p *parser) generateImpliedEndTags(exceptions ...string) {
+ var i int
+loop:
+ for i = len(p.oe) - 1; i >= 0; i-- {
+ n := p.oe[i]
+ if n.Type == ElementNode {
+ switch n.DataAtom {
+ case a.Dd, a.Dt, a.Li, a.Option, a.Optgroup, a.P, a.Rp, a.Rt:
+ for _, except := range exceptions {
+ if n.Data == except {
+ break loop
+ }
+ }
+ continue
+ }
+ }
+ break
+ }
+
+ p.oe = p.oe[:i+1]
+}
+
// addChild adds a child node n to the top element, and pushes n onto the stack
// of open elements if it is an element node.
func (p *parser) addChild(n *Node) {
- if p.fosterParenting {
+ if p.shouldFosterParent() {
p.fosterParent(n)
} else {
- p.top().Add(n)
+ p.top().AppendChild(n)
}
if n.Type == ElementNode {
@@ -180,14 +220,25 @@ func (p *parser) addChild(n *Node) {
}
}
+// shouldFosterParent returns whether the next node to be added should be
+// foster parented.
+func (p *parser) shouldFosterParent() bool {
+ if p.fosterParenting {
+ switch p.top().DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ return true
+ }
+ }
+ return false
+}
+
// fosterParent adds a child node according to the foster parenting rules.
// Section 12.2.5.3, "foster parenting".
func (p *parser) fosterParent(n *Node) {
- p.fosterParenting = false
- var table, parent *Node
+ var table, parent, prev *Node
var i int
for i = len(p.oe) - 1; i >= 0; i-- {
- if p.oe[i].Data == "table" {
+ if p.oe[i].DataAtom == a.Table {
table = p.oe[i]
break
}
@@ -203,35 +254,37 @@ func (p *parser) fosterParent(n *Node) {
parent = p.oe[i-1]
}
- var child *Node
- for i, child = range parent.Child {
- if child == table {
- break
- }
+ if table != nil {
+ prev = table.PrevSibling
+ } else {
+ prev = parent.LastChild
}
-
- if i > 0 && parent.Child[i-1].Type == TextNode && n.Type == TextNode {
- parent.Child[i-1].Data += n.Data
+ if prev != nil && prev.Type == TextNode && n.Type == TextNode {
+ prev.Data += n.Data
return
}
- if i == len(parent.Child) {
- parent.Add(n)
- } else {
- // Insert n into parent.Child at index i.
- parent.Child = append(parent.Child[:i+1], parent.Child[i:]...)
- parent.Child[i] = n
- n.Parent = parent
- }
+ parent.InsertBefore(n, table)
}
// addText adds text to the preceding node if it is a text node, or else it
// calls addChild with a new text node.
func (p *parser) addText(text string) {
- // TODO: distinguish whitespace text from others.
+ if text == "" {
+ return
+ }
+
+ if p.shouldFosterParent() {
+ p.fosterParent(&Node{
+ Type: TextNode,
+ Data: text,
+ })
+ return
+ }
+
t := p.top()
- if i := len(t.Child); i > 0 && t.Child[i-1].Type == TextNode {
- t.Child[i-1].Data += text
+ if n := t.LastChild; n != nil && n.Type == TextNode {
+ n.Data += text
return
}
p.addChild(&Node{
@@ -240,20 +293,61 @@ func (p *parser) addText(text string) {
})
}
-// addElement calls addChild with an element node.
-func (p *parser) addElement(tag string, attr []Attribute) {
+// addElement adds a child element based on the current token.
+func (p *parser) addElement() {
p.addChild(&Node{
- Type: ElementNode,
- Data: tag,
- Attr: attr,
+ Type: ElementNode,
+ DataAtom: p.tok.DataAtom,
+ Data: p.tok.Data,
+ Attr: p.tok.Attr,
})
}
// Section 12.2.3.3.
-func (p *parser) addFormattingElement(tag string, attr []Attribute) {
- p.addElement(tag, attr)
+func (p *parser) addFormattingElement() {
+ tagAtom, attr := p.tok.DataAtom, p.tok.Attr
+ p.addElement()
+
+ // Implement the Noah's Ark clause, but with three per family instead of two.
+ identicalElements := 0
+findIdenticalElements:
+ for i := len(p.afe) - 1; i >= 0; i-- {
+ n := p.afe[i]
+ if n.Type == scopeMarkerNode {
+ break
+ }
+ if n.Type != ElementNode {
+ continue
+ }
+ if n.Namespace != "" {
+ continue
+ }
+ if n.DataAtom != tagAtom {
+ continue
+ }
+ if len(n.Attr) != len(attr) {
+ continue
+ }
+ compareAttributes:
+ for _, t0 := range n.Attr {
+ for _, t1 := range attr {
+ if t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val {
+ // Found a match for this attribute, continue with the next attribute.
+ continue compareAttributes
+ }
+ }
+ // If we get here, there is no attribute that matches a.
+ // Therefore the element is not identical to the new one.
+ continue findIdenticalElements
+ }
+
+ identicalElements++
+ if identicalElements >= 3 {
+ p.afe.remove(n)
+ }
+ }
+
p.afe = append(p.afe, p.top())
- // TODO.
}
// Section 12.2.3.3.
@@ -295,27 +389,6 @@ func (p *parser) reconstructActiveFormattingElements() {
}
}
-// read reads the next token. This is usually from the tokenizer, but it may
-// be the synthesized end tag implied by a self-closing tag.
-func (p *parser) read() error {
- if p.hasSelfClosingToken {
- p.hasSelfClosingToken = false
- p.tok.Type = EndTagToken
- p.tok.Attr = nil
- return nil
- }
- p.tokenizer.Next()
- p.tok = p.tokenizer.Token()
- switch p.tok.Type {
- case ErrorToken:
- return p.tokenizer.Err()
- case SelfClosingTagToken:
- p.hasSelfClosingToken = true
- p.tok.Type = StartTagToken
- }
- return nil
-}
-
// Section 12.2.4.
func (p *parser) acknowledgeSelfClosingTag() {
p.hasSelfClosingToken = false
@@ -345,28 +418,28 @@ func (p *parser) resetInsertionMode() {
n = p.context
}
- switch n.Data {
- case "select":
+ switch n.DataAtom {
+ case a.Select:
p.im = inSelectIM
- case "td", "th":
+ case a.Td, a.Th:
p.im = inCellIM
- case "tr":
+ case a.Tr:
p.im = inRowIM
- case "tbody", "thead", "tfoot":
+ case a.Tbody, a.Thead, a.Tfoot:
p.im = inTableBodyIM
- case "caption":
+ case a.Caption:
p.im = inCaptionIM
- case "colgroup":
+ case a.Colgroup:
p.im = inColumnGroupIM
- case "table":
+ case a.Table:
p.im = inTableIM
- case "head":
+ case a.Head:
p.im = inBodyIM
- case "body":
+ case a.Body:
p.im = inBodyIM
- case "frameset":
+ case a.Frameset:
p.im = inFramesetIM
- case "html":
+ case a.Html:
p.im = beforeHeadIM
default:
continue
@@ -388,14 +461,14 @@ func initialIM(p *parser) bool {
return true
}
case CommentToken:
- p.doc.Add(&Node{
+ p.doc.AppendChild(&Node{
Type: CommentNode,
Data: p.tok.Data,
})
return true
case DoctypeToken:
n, quirks := parseDoctype(p.tok.Data)
- p.doc.Add(n)
+ p.doc.AppendChild(n)
p.quirks = quirks
p.im = beforeHTMLIM
return true
@@ -408,6 +481,9 @@ func initialIM(p *parser) bool {
// Section 12.2.5.4.2.
func beforeHTMLIM(p *parser) bool {
switch p.tok.Type {
+ case DoctypeToken:
+ // Ignore the token.
+ return true
case TextToken:
p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
if len(p.tok.Data) == 0 {
@@ -415,65 +491,58 @@ func beforeHTMLIM(p *parser) bool {
return true
}
case StartTagToken:
- if p.tok.Data == "html" {
- p.addElement(p.tok.Data, p.tok.Attr)
+ if p.tok.DataAtom == a.Html {
+ p.addElement()
p.im = beforeHeadIM
return true
}
case EndTagToken:
- switch p.tok.Data {
- case "head", "body", "html", "br":
- // Drop down to creating an implied <html> tag.
+ switch p.tok.DataAtom {
+ case a.Head, a.Body, a.Html, a.Br:
+ p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
+ return false
default:
// Ignore the token.
return true
}
case CommentToken:
- p.doc.Add(&Node{
+ p.doc.AppendChild(&Node{
Type: CommentNode,
Data: p.tok.Data,
})
return true
}
- // Create an implied <html> tag.
- p.addElement("html", nil)
- p.im = beforeHeadIM
+ p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
return false
}
// Section 12.2.5.4.3.
func beforeHeadIM(p *parser) bool {
- var (
- add bool
- attr []Attribute
- implied bool
- )
switch p.tok.Type {
- case ErrorToken:
- implied = true
case TextToken:
p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
if len(p.tok.Data) == 0 {
// It was all whitespace, so ignore it.
return true
}
- implied = true
case StartTagToken:
- switch p.tok.Data {
- case "head":
- add = true
- attr = p.tok.Attr
- case "html":
+ switch p.tok.DataAtom {
+ case a.Head:
+ p.addElement()
+ p.head = p.top()
+ p.im = inHeadIM
+ return true
+ case a.Html:
return inBodyIM(p)
- default:
- implied = true
}
case EndTagToken:
- switch p.tok.Data {
- case "head", "body", "html", "br":
- implied = true
+ switch p.tok.DataAtom {
+ case a.Head, a.Body, a.Html, a.Br:
+ p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
+ return false
default:
// Ignore the token.
+ return true
}
case CommentToken:
p.addChild(&Node{
@@ -481,24 +550,18 @@ func beforeHeadIM(p *parser) bool {
Data: p.tok.Data,
})
return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
}
- if add || implied {
- p.addElement("head", attr)
- p.head = p.top()
- }
- p.im = inHeadIM
- return !implied
+
+ p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
+ return false
}
// Section 12.2.5.4.4.
func inHeadIM(p *parser) bool {
- var (
- pop bool
- implied bool
- )
switch p.tok.Type {
- case ErrorToken:
- implied = true
case TextToken:
s := strings.TrimLeft(p.tok.Data, whitespace)
if len(s) < len(p.tok.Data) {
@@ -509,32 +572,36 @@ func inHeadIM(p *parser) bool {
}
p.tok.Data = s
}
- implied = true
case StartTagToken:
- switch p.tok.Data {
- case "html":
+ switch p.tok.DataAtom {
+ case a.Html:
return inBodyIM(p)
- case "base", "basefont", "bgsound", "command", "link", "meta":
- p.addElement(p.tok.Data, p.tok.Attr)
+ case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta:
+ p.addElement()
p.oe.pop()
p.acknowledgeSelfClosingTag()
- case "script", "title", "noscript", "noframes", "style":
- p.addElement(p.tok.Data, p.tok.Attr)
+ return true
+ case a.Script, a.Title, a.Noscript, a.Noframes, a.Style:
+ p.addElement()
p.setOriginalIM()
p.im = textIM
return true
- case "head":
+ case a.Head:
// Ignore the token.
return true
- default:
- implied = true
}
case EndTagToken:
- switch p.tok.Data {
- case "head":
- pop = true
- case "body", "html", "br":
- implied = true
+ switch p.tok.DataAtom {
+ case a.Head:
+ n := p.oe.pop()
+ if n.DataAtom != a.Head {
+ panic("html: bad parser state: <head> element not found, in the in-head insertion mode")
+ }
+ p.im = afterHeadIM
+ return true
+ case a.Body, a.Html, a.Br:
+ p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
+ return false
default:
// Ignore the token.
return true
@@ -545,30 +612,18 @@ func inHeadIM(p *parser) bool {
Data: p.tok.Data,
})
return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
}
- if pop || implied {
- n := p.oe.pop()
- if n.Data != "head" {
- panic("html: bad parser state: <head> element not found, in the in-head insertion mode")
- }
- p.im = afterHeadIM
- return !implied
- }
- return true
+
+ p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
+ return false
}
// Section 12.2.5.4.6.
func afterHeadIM(p *parser) bool {
- var (
- add bool
- attr []Attribute
- framesetOK bool
- implied bool
- )
switch p.tok.Type {
- case ErrorToken:
- implied = true
- framesetOK = true
case TextToken:
s := strings.TrimLeft(p.tok.Data, whitespace)
if len(s) < len(p.tok.Data) {
@@ -579,36 +634,31 @@ func afterHeadIM(p *parser) bool {
}
p.tok.Data = s
}
- implied = true
- framesetOK = true
case StartTagToken:
- switch p.tok.Data {
- case "html":
- // TODO.
- case "body":
- add = true
- attr = p.tok.Attr
- framesetOK = false
- case "frameset":
- p.addElement(p.tok.Data, p.tok.Attr)
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Body:
+ p.addElement()
+ p.framesetOK = false
+ p.im = inBodyIM
+ return true
+ case a.Frameset:
+ p.addElement()
p.im = inFramesetIM
return true
- case "base", "basefont", "bgsound", "link", "meta", "noframes", "script", "style", "title":
+ case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:
p.oe = append(p.oe, p.head)
- defer p.oe.pop()
+ defer p.oe.remove(p.head)
return inHeadIM(p)
- case "head":
+ case a.Head:
// Ignore the token.
return true
- default:
- implied = true
- framesetOK = true
}
case EndTagToken:
- switch p.tok.Data {
- case "body", "html", "br":
- implied = true
- framesetOK = true
+ switch p.tok.DataAtom {
+ case a.Body, a.Html, a.Br:
+ // Drop down to creating an implied <body> tag.
default:
// Ignore the token.
return true
@@ -619,13 +669,14 @@ func afterHeadIM(p *parser) bool {
Data: p.tok.Data,
})
return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
}
- if add || implied {
- p.addElement("body", attr)
- p.framesetOK = framesetOK
- }
- p.im = inBodyIM
- return !implied
+
+ p.parseImpliedToken(StartTagToken, a.Body, a.Body.String())
+ p.framesetOK = true
+ return false
}
// copyAttributes copies attributes of src not found on dst to dst.
@@ -634,13 +685,13 @@ func copyAttributes(dst *Node, src Token) {
return
}
attr := map[string]string{}
- for _, a := range dst.Attr {
- attr[a.Key] = a.Val
+ for _, t := range dst.Attr {
+ attr[t.Key] = t.Val
}
- for _, a := range src.Attr {
- if _, ok := attr[a.Key]; !ok {
- dst.Attr = append(dst.Attr, a)
- attr[a.Key] = a.Val
+ for _, t := range src.Attr {
+ if _, ok := attr[t.Key]; !ok {
+ dst.Attr = append(dst.Attr, t)
+ attr[t.Key] = t.Val
}
}
}
@@ -649,106 +700,85 @@ func copyAttributes(dst *Node, src Token) {
func inBodyIM(p *parser) bool {
switch p.tok.Type {
case TextToken:
- switch n := p.oe.top(); n.Data {
- case "pre", "listing", "textarea":
- if len(n.Child) == 0 {
+ d := p.tok.Data
+ switch n := p.oe.top(); n.DataAtom {
+ case a.Pre, a.Listing:
+ if n.FirstChild == nil {
// Ignore a newline at the start of a <pre> block.
- d := p.tok.Data
if d != "" && d[0] == '\r' {
d = d[1:]
}
if d != "" && d[0] == '\n' {
d = d[1:]
}
- if d == "" {
- return true
- }
- p.tok.Data = d
}
}
+ d = strings.Replace(d, "\x00", "", -1)
+ if d == "" {
+ return true
+ }
p.reconstructActiveFormattingElements()
- p.addText(p.tok.Data)
- p.framesetOK = false
+ p.addText(d)
+ if p.framesetOK && strings.TrimLeft(d, whitespace) != "" {
+ // There were non-whitespace characters inserted.
+ p.framesetOK = false
+ }
case StartTagToken:
- switch p.tok.Data {
- case "html":
+ switch p.tok.DataAtom {
+ case a.Html:
copyAttributes(p.oe[0], p.tok)
- case "address", "article", "aside", "blockquote", "center", "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "menu", "nav", "ol", "p", "section", "summary", "ul":
- p.popUntil(buttonScope, "p")
- p.addElement(p.tok.Data, p.tok.Attr)
- case "h1", "h2", "h3", "h4", "h5", "h6":
- p.popUntil(buttonScope, "p")
- switch n := p.top(); n.Data {
- case "h1", "h2", "h3", "h4", "h5", "h6":
- p.oe.pop()
- }
- p.addElement(p.tok.Data, p.tok.Attr)
- case "a":
- for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
- if n := p.afe[i]; n.Type == ElementNode && n.Data == "a" {
- p.inBodyEndTagFormatting("a")
- p.oe.remove(n)
- p.afe.remove(n)
- break
+ case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:
+ return inHeadIM(p)
+ case a.Body:
+ if len(p.oe) >= 2 {
+ body := p.oe[1]
+ if body.Type == ElementNode && body.DataAtom == a.Body {
+ p.framesetOK = false
+ copyAttributes(body, p.tok)
}
}
- p.reconstructActiveFormattingElements()
- p.addFormattingElement(p.tok.Data, p.tok.Attr)
- case "b", "big", "code", "em", "font", "i", "s", "small", "strike", "strong", "tt", "u":
- p.reconstructActiveFormattingElements()
- p.addFormattingElement(p.tok.Data, p.tok.Attr)
- case "nobr":
- p.reconstructActiveFormattingElements()
- if p.elementInScope(defaultScope, "nobr") {
- p.inBodyEndTagFormatting("nobr")
- p.reconstructActiveFormattingElements()
+ case a.Frameset:
+ if !p.framesetOK || len(p.oe) < 2 || p.oe[1].DataAtom != a.Body {
+ // Ignore the token.
+ return true
}
- p.addFormattingElement(p.tok.Data, p.tok.Attr)
- case "applet", "marquee", "object":
- p.reconstructActiveFormattingElements()
- p.addElement(p.tok.Data, p.tok.Attr)
- p.afe = append(p.afe, &scopeMarker)
- p.framesetOK = false
- case "area", "br", "embed", "img", "input", "keygen", "wbr":
- p.reconstructActiveFormattingElements()
- p.addElement(p.tok.Data, p.tok.Attr)
- p.oe.pop()
- p.acknowledgeSelfClosingTag()
- p.framesetOK = false
- case "table":
- if !p.quirks {
- p.popUntil(buttonScope, "p")
+ body := p.oe[1]
+ if body.Parent != nil {
+ body.Parent.RemoveChild(body)
}
- p.addElement(p.tok.Data, p.tok.Attr)
- p.framesetOK = false
- p.im = inTableIM
+ p.oe = p.oe[:1]
+ p.addElement()
+ p.im = inFramesetIM
return true
- case "hr":
- p.popUntil(buttonScope, "p")
- p.addElement(p.tok.Data, p.tok.Attr)
- p.oe.pop()
- p.acknowledgeSelfClosingTag()
- p.framesetOK = false
- case "select":
- p.reconstructActiveFormattingElements()
- p.addElement(p.tok.Data, p.tok.Attr)
+ case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
+ p.popUntil(buttonScope, a.P)
+ switch n := p.top(); n.DataAtom {
+ case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
+ p.oe.pop()
+ }
+ p.addElement()
+ case a.Pre, a.Listing:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ // The newline, if any, will be dealt with by the TextToken case.
p.framesetOK = false
- p.im = inSelectIM
- return true
- case "form":
+ case a.Form:
if p.form == nil {
- p.popUntil(buttonScope, "p")
- p.addElement(p.tok.Data, p.tok.Attr)
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
p.form = p.top()
}
- case "li":
+ case a.Li:
p.framesetOK = false
for i := len(p.oe) - 1; i >= 0; i-- {
node := p.oe[i]
- switch node.Data {
- case "li":
- p.popUntil(listItemScope, "li")
- case "address", "div", "p":
+ switch node.DataAtom {
+ case a.Li:
+ p.oe = p.oe[:i]
+ case a.Address, a.Div, a.P:
continue
default:
if !isSpecialElement(node) {
@@ -757,16 +787,16 @@ func inBodyIM(p *parser) bool {
}
break
}
- p.popUntil(buttonScope, "p")
- p.addElement(p.tok.Data, p.tok.Attr)
- case "dd", "dt":
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.Dd, a.Dt:
p.framesetOK = false
for i := len(p.oe) - 1; i >= 0; i-- {
node := p.oe[i]
- switch node.Data {
- case "dd", "dt":
+ switch node.DataAtom {
+ case a.Dd, a.Dt:
p.oe = p.oe[:i]
- case "address", "div", "p":
+ case a.Address, a.Div, a.P:
continue
default:
if !isSpecialElement(node) {
@@ -775,49 +805,81 @@ func inBodyIM(p *parser) bool {
}
break
}
- p.popUntil(buttonScope, "p")
- p.addElement(p.tok.Data, p.tok.Attr)
- case "plaintext":
- p.popUntil(buttonScope, "p")
- p.addElement(p.tok.Data, p.tok.Attr)
- case "button":
- p.popUntil(defaultScope, "button")
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.Plaintext:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.Button:
+ p.popUntil(defaultScope, a.Button)
p.reconstructActiveFormattingElements()
- p.addElement(p.tok.Data, p.tok.Attr)
+ p.addElement()
p.framesetOK = false
- case "optgroup", "option":
- if p.top().Data == "option" {
- p.oe.pop()
- }
- p.reconstructActiveFormattingElements()
- p.addElement(p.tok.Data, p.tok.Attr)
- case "body":
- if len(p.oe) >= 2 {
- body := p.oe[1]
- if body.Type == ElementNode && body.Data == "body" {
- p.framesetOK = false
- copyAttributes(body, p.tok)
+ case a.A:
+ for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
+ if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A {
+ p.inBodyEndTagFormatting(a.A)
+ p.oe.remove(n)
+ p.afe.remove(n)
+ break
}
}
- case "frameset":
- if !p.framesetOK || len(p.oe) < 2 || p.oe[1].Data != "body" {
- // Ignore the token.
- return true
+ p.reconstructActiveFormattingElements()
+ p.addFormattingElement()
+ case a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
+ p.reconstructActiveFormattingElements()
+ p.addFormattingElement()
+ case a.Nobr:
+ p.reconstructActiveFormattingElements()
+ if p.elementInScope(defaultScope, a.Nobr) {
+ p.inBodyEndTagFormatting(a.Nobr)
+ p.reconstructActiveFormattingElements()
}
- body := p.oe[1]
- if body.Parent != nil {
- body.Parent.Remove(body)
+ p.addFormattingElement()
+ case a.Applet, a.Marquee, a.Object:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.afe = append(p.afe, &scopeMarker)
+ p.framesetOK = false
+ case a.Table:
+ if !p.quirks {
+ p.popUntil(buttonScope, a.P)
}
- p.oe = p.oe[:1]
- p.addElement(p.tok.Data, p.tok.Attr)
- p.im = inFramesetIM
+ p.addElement()
+ p.framesetOK = false
+ p.im = inTableIM
return true
- case "base", "basefont", "bgsound", "command", "link", "meta", "noframes", "script", "style", "title":
- return inHeadIM(p)
- case "image":
- p.tok.Data = "img"
+ case a.Area, a.Br, a.Embed, a.Img, a.Input, a.Keygen, a.Wbr:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ if p.tok.DataAtom == a.Input {
+ for _, t := range p.tok.Attr {
+ if t.Key == "type" {
+ if strings.ToLower(t.Val) == "hidden" {
+ // Skip setting framesetOK = false
+ return true
+ }
+ }
+ }
+ }
+ p.framesetOK = false
+ case a.Param, a.Source, a.Track:
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ case a.Hr:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ p.framesetOK = false
+ case a.Image:
+ p.tok.DataAtom = a.Img
+ p.tok.Data = a.Img.String()
return false
- case "isindex":
+ case a.Isindex:
if p.form != nil {
// Ignore the token.
return true
@@ -825,82 +887,142 @@ func inBodyIM(p *parser) bool {
action := ""
prompt := "This is a searchable index. Enter search keywords: "
attr := []Attribute{{Key: "name", Val: "isindex"}}
- for _, a := range p.tok.Attr {
- switch a.Key {
+ for _, t := range p.tok.Attr {
+ switch t.Key {
case "action":
- action = a.Val
+ action = t.Val
case "name":
// Ignore the attribute.
case "prompt":
- prompt = a.Val
+ prompt = t.Val
default:
- attr = append(attr, a)
+ attr = append(attr, t)
}
}
p.acknowledgeSelfClosingTag()
- p.popUntil(buttonScope, "p")
- p.addElement("form", nil)
- p.form = p.top()
+ p.popUntil(buttonScope, a.P)
+ p.parseImpliedToken(StartTagToken, a.Form, a.Form.String())
if action != "" {
p.form.Attr = []Attribute{{Key: "action", Val: action}}
}
- p.addElement("hr", nil)
- p.oe.pop()
- p.addElement("label", nil)
+ p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
+ p.parseImpliedToken(StartTagToken, a.Label, a.Label.String())
p.addText(prompt)
- p.addElement("input", attr)
- p.oe.pop()
- p.oe.pop()
- p.addElement("hr", nil)
- p.oe.pop()
+ p.addChild(&Node{
+ Type: ElementNode,
+ DataAtom: a.Input,
+ Data: a.Input.String(),
+ Attr: attr,
+ })
p.oe.pop()
- p.form = nil
- case "xmp":
- p.popUntil(buttonScope, "p")
+ p.parseImpliedToken(EndTagToken, a.Label, a.Label.String())
+ p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
+ p.parseImpliedToken(EndTagToken, a.Form, a.Form.String())
+ case a.Textarea:
+ p.addElement()
+ p.setOriginalIM()
+ p.framesetOK = false
+ p.im = textIM
+ case a.Xmp:
+ p.popUntil(buttonScope, a.P)
+ p.reconstructActiveFormattingElements()
+ p.framesetOK = false
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ case a.Iframe:
+ p.framesetOK = false
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ case a.Noembed, a.Noscript:
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ case a.Select:
p.reconstructActiveFormattingElements()
+ p.addElement()
p.framesetOK = false
- p.addElement(p.tok.Data, p.tok.Attr)
- case "math", "svg":
+ p.im = inSelectIM
+ return true
+ case a.Optgroup, a.Option:
+ if p.top().DataAtom == a.Option {
+ p.oe.pop()
+ }
p.reconstructActiveFormattingElements()
- if p.tok.Data == "math" {
- // TODO: adjust MathML attributes.
+ p.addElement()
+ case a.Rp, a.Rt:
+ if p.elementInScope(defaultScope, a.Ruby) {
+ p.generateImpliedEndTags()
+ }
+ p.addElement()
+ case a.Math, a.Svg:
+ p.reconstructActiveFormattingElements()
+ if p.tok.DataAtom == a.Math {
+ adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
} else {
- // TODO: adjust SVG attributes.
+ adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
}
adjustForeignAttributes(p.tok.Attr)
- p.addElement(p.tok.Data, p.tok.Attr)
+ p.addElement()
p.top().Namespace = p.tok.Data
+ if p.hasSelfClosingToken {
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ }
return true
- case "caption", "col", "colgroup", "frame", "head", "tbody", "td", "tfoot", "th", "thead", "tr":
+ case a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
// Ignore the token.
default:
- // TODO.
- p.addElement(p.tok.Data, p.tok.Attr)
+ p.reconstructActiveFormattingElements()
+ p.addElement()
}
case EndTagToken:
- switch p.tok.Data {
- case "body":
- // TODO: autoclose the stack of open elements.
- p.im = afterBodyIM
+ switch p.tok.DataAtom {
+ case a.Body:
+ if p.elementInScope(defaultScope, a.Body) {
+ p.im = afterBodyIM
+ }
+ case a.Html:
+ if p.elementInScope(defaultScope, a.Body) {
+ p.parseImpliedToken(EndTagToken, a.Body, a.Body.String())
+ return false
+ }
return true
- case "p":
- if !p.elementInScope(buttonScope, "p") {
- p.addElement("p", nil)
- }
- p.popUntil(buttonScope, "p")
- case "a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u":
- p.inBodyEndTagFormatting(p.tok.Data)
- case "address", "article", "aside", "blockquote", "button", "center", "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "listing", "menu", "nav", "ol", "pre", "section", "summary", "ul":
- p.popUntil(defaultScope, p.tok.Data)
- case "applet", "marquee", "object":
- if p.popUntil(defaultScope, p.tok.Data) {
+ case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
+ p.popUntil(defaultScope, p.tok.DataAtom)
+ case a.Form:
+ node := p.form
+ p.form = nil
+ i := p.indexOfElementInScope(defaultScope, a.Form)
+ if node == nil || i == -1 || p.oe[i] != node {
+ // Ignore the token.
+ return true
+ }
+ p.generateImpliedEndTags()
+ p.oe.remove(node)
+ case a.P:
+ if !p.elementInScope(buttonScope, a.P) {
+ p.parseImpliedToken(StartTagToken, a.P, a.P.String())
+ }
+ p.popUntil(buttonScope, a.P)
+ case a.Li:
+ p.popUntil(listItemScope, a.Li)
+ case a.Dd, a.Dt:
+ p.popUntil(defaultScope, p.tok.DataAtom)
+ case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
+ p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)
+ case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
+ p.inBodyEndTagFormatting(p.tok.DataAtom)
+ case a.Applet, a.Marquee, a.Object:
+ if p.popUntil(defaultScope, p.tok.DataAtom) {
p.clearActiveFormattingElements()
}
- case "br":
+ case a.Br:
p.tok.Type = StartTagToken
return false
default:
- p.inBodyEndTagOther(p.tok.Data)
+ p.inBodyEndTagOther(p.tok.DataAtom)
}
case CommentToken:
p.addChild(&Node{
@@ -912,7 +1034,7 @@ func inBodyIM(p *parser) bool {
return true
}
-func (p *parser) inBodyEndTagFormatting(tag string) {
+func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
// This is the "adoption agency" algorithm, described at
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#adoptionAgency
@@ -928,13 +1050,13 @@ func (p *parser) inBodyEndTagFormatting(tag string) {
if p.afe[j].Type == scopeMarkerNode {
break
}
- if p.afe[j].Data == tag {
+ if p.afe[j].DataAtom == tagAtom {
formattingElement = p.afe[j]
break
}
}
if formattingElement == nil {
- p.inBodyEndTagOther(tag)
+ p.inBodyEndTagOther(tagAtom)
return
}
feIndex := p.oe.index(formattingElement)
@@ -942,7 +1064,7 @@ func (p *parser) inBodyEndTagFormatting(tag string) {
p.afe.remove(formattingElement)
return
}
- if !p.elementInScope(defaultScope, tag) {
+ if !p.elementInScope(defaultScope, tagAtom) {
// Ignore the tag.
return
}
@@ -997,9 +1119,9 @@ func (p *parser) inBodyEndTagFormatting(tag string) {
}
// Step 9.9.
if lastNode.Parent != nil {
- lastNode.Parent.Remove(lastNode)
+ lastNode.Parent.RemoveChild(lastNode)
}
- node.Add(lastNode)
+ node.AppendChild(lastNode)
// Step 9.10.
lastNode = node
}
@@ -1007,20 +1129,20 @@ func (p *parser) inBodyEndTagFormatting(tag string) {
// Step 10. Reparent lastNode to the common ancestor,
// or for misnested table nodes, to the foster parent.
if lastNode.Parent != nil {
- lastNode.Parent.Remove(lastNode)
+ lastNode.Parent.RemoveChild(lastNode)
}
- switch commonAncestor.Data {
- case "table", "tbody", "tfoot", "thead", "tr":
+ switch commonAncestor.DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
p.fosterParent(lastNode)
default:
- commonAncestor.Add(lastNode)
+ commonAncestor.AppendChild(lastNode)
}
// Steps 11-13. Reparent nodes from the furthest block's children
// to a clone of the formatting element.
clone := formattingElement.clone()
reparentChildren(clone, furthestBlock)
- furthestBlock.Add(clone)
+ furthestBlock.AppendChild(clone)
// Step 14. Fix up the list of active formatting elements.
if oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark {
@@ -1037,9 +1159,9 @@ func (p *parser) inBodyEndTagFormatting(tag string) {
}
// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
-func (p *parser) inBodyEndTagOther(tag string) {
+func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
for i := len(p.oe) - 1; i >= 0; i-- {
- if p.oe[i].Data == tag {
+ if p.oe[i].DataAtom == tagAtom {
p.oe = p.oe[:i]
break
}
@@ -1055,7 +1177,20 @@ func textIM(p *parser) bool {
case ErrorToken:
p.oe.pop()
case TextToken:
- p.addText(p.tok.Data)
+ d := p.tok.Data
+ if n := p.oe.top(); n.DataAtom == a.Textarea && n.FirstChild == nil {
+ // Ignore a newline at the start of a <textarea> block.
+ if d != "" && d[0] == '\r' {
+ d = d[1:]
+ }
+ if d != "" && d[0] == '\n' {
+ d = d[1:]
+ }
+ }
+ if d == "" {
+ return true
+ }
+ p.addText(d)
return true
case EndTagToken:
p.oe.pop()
@@ -1072,66 +1207,85 @@ func inTableIM(p *parser) bool {
// Stop parsing.
return true
case TextToken:
- // TODO.
+ p.tok.Data = strings.Replace(p.tok.Data, "\x00", "", -1)
+ switch p.oe.top().DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ if strings.Trim(p.tok.Data, whitespace) == "" {
+ p.addText(p.tok.Data)
+ return true
+ }
+ }
case StartTagToken:
- switch p.tok.Data {
- case "caption":
+ switch p.tok.DataAtom {
+ case a.Caption:
p.clearStackToContext(tableScope)
p.afe = append(p.afe, &scopeMarker)
- p.addElement(p.tok.Data, p.tok.Attr)
+ p.addElement()
p.im = inCaptionIM
return true
- case "tbody", "tfoot", "thead":
+ case a.Colgroup:
p.clearStackToContext(tableScope)
- p.addElement(p.tok.Data, p.tok.Attr)
- p.im = inTableBodyIM
+ p.addElement()
+ p.im = inColumnGroupIM
return true
- case "td", "th", "tr":
+ case a.Col:
+ p.parseImpliedToken(StartTagToken, a.Colgroup, a.Colgroup.String())
+ return false
+ case a.Tbody, a.Tfoot, a.Thead:
p.clearStackToContext(tableScope)
- p.addElement("tbody", nil)
+ p.addElement()
p.im = inTableBodyIM
+ return true
+ case a.Td, a.Th, a.Tr:
+ p.parseImpliedToken(StartTagToken, a.Tbody, a.Tbody.String())
return false
- case "table":
- if p.popUntil(tableScope, "table") {
+ case a.Table:
+ if p.popUntil(tableScope, a.Table) {
p.resetInsertionMode()
return false
}
// Ignore the token.
return true
- case "colgroup":
- p.clearStackToContext(tableScope)
- p.addElement(p.tok.Data, p.tok.Attr)
- p.im = inColumnGroupIM
- return true
- case "col":
- p.clearStackToContext(tableScope)
- p.addElement("colgroup", p.tok.Attr)
- p.im = inColumnGroupIM
- return false
- case "select":
+ case a.Style, a.Script:
+ return inHeadIM(p)
+ case a.Input:
+ for _, t := range p.tok.Attr {
+ if t.Key == "type" && strings.ToLower(t.Val) == "hidden" {
+ p.addElement()
+ p.oe.pop()
+ return true
+ }
+ }
+ // Otherwise drop down to the default action.
+ case a.Form:
+ if p.form != nil {
+ // Ignore the token.
+ return true
+ }
+ p.addElement()
+ p.form = p.oe.pop()
+ case a.Select:
p.reconstructActiveFormattingElements()
- switch p.top().Data {
- case "table", "tbody", "tfoot", "thead", "tr":
+ switch p.top().DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
p.fosterParenting = true
}
- p.addElement(p.tok.Data, p.tok.Attr)
+ p.addElement()
p.fosterParenting = false
p.framesetOK = false
p.im = inSelectInTableIM
return true
- default:
- // TODO.
}
case EndTagToken:
- switch p.tok.Data {
- case "table":
- if p.popUntil(tableScope, "table") {
+ switch p.tok.DataAtom {
+ case a.Table:
+ if p.popUntil(tableScope, a.Table) {
p.resetInsertionMode()
return true
}
// Ignore the token.
return true
- case "body", "caption", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr":
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
// Ignore the token.
return true
}
@@ -1141,13 +1295,13 @@ func inTableIM(p *parser) bool {
Data: p.tok.Data,
})
return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
}
- switch p.top().Data {
- case "table", "tbody", "tfoot", "thead", "tr":
- p.fosterParenting = true
- defer func() { p.fosterParenting = false }()
- }
+ p.fosterParenting = true
+ defer func() { p.fosterParenting = false }()
return inBodyIM(p)
}
@@ -1156,9 +1310,9 @@ func inTableIM(p *parser) bool {
func inCaptionIM(p *parser) bool {
switch p.tok.Type {
case StartTagToken:
- switch p.tok.Data {
- case "caption", "col", "colgroup", "tbody", "td", "tfoot", "thead", "tr":
- if p.popUntil(tableScope, "caption") {
+ switch p.tok.DataAtom {
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Thead, a.Tr:
+ if p.popUntil(tableScope, a.Caption) {
p.clearActiveFormattingElements()
p.im = inTableIM
return false
@@ -1166,23 +1320,23 @@ func inCaptionIM(p *parser) bool {
// Ignore the token.
return true
}
- case "select":
+ case a.Select:
p.reconstructActiveFormattingElements()
- p.addElement(p.tok.Data, p.tok.Attr)
+ p.addElement()
p.framesetOK = false
p.im = inSelectInTableIM
return true
}
case EndTagToken:
- switch p.tok.Data {
- case "caption":
- if p.popUntil(tableScope, "caption") {
+ switch p.tok.DataAtom {
+ case a.Caption:
+ if p.popUntil(tableScope, a.Caption) {
p.clearActiveFormattingElements()
p.im = inTableIM
}
return true
- case "table":
- if p.popUntil(tableScope, "caption") {
+ case a.Table:
+ if p.popUntil(tableScope, a.Caption) {
p.clearActiveFormattingElements()
p.im = inTableIM
return false
@@ -1190,7 +1344,7 @@ func inCaptionIM(p *parser) bool {
// Ignore the token.
return true
}
- case "body", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr":
+ case a.Body, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
// Ignore the token.
return true
}
@@ -1201,6 +1355,16 @@ func inCaptionIM(p *parser) bool {
// Section 12.2.5.4.12.
func inColumnGroupIM(p *parser) bool {
switch p.tok.Type {
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) < len(p.tok.Data) {
+ // Add the initial whitespace to the current node.
+ p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
+ if s == "" {
+ return true
+ }
+ p.tok.Data = s
+ }
case CommentToken:
p.addChild(&Node{
Type: CommentNode,
@@ -1211,29 +1375,29 @@ func inColumnGroupIM(p *parser) bool {
// Ignore the token.
return true
case StartTagToken:
- switch p.tok.Data {
- case "html":
+ switch p.tok.DataAtom {
+ case a.Html:
return inBodyIM(p)
- case "col":
- p.addElement(p.tok.Data, p.tok.Attr)
+ case a.Col:
+ p.addElement()
p.oe.pop()
p.acknowledgeSelfClosingTag()
return true
}
case EndTagToken:
- switch p.tok.Data {
- case "colgroup":
- if p.oe.top().Data != "html" {
+ switch p.tok.DataAtom {
+ case a.Colgroup:
+ if p.oe.top().DataAtom != a.Html {
p.oe.pop()
p.im = inTableIM
}
return true
- case "col":
+ case a.Col:
// Ignore the token.
return true
}
}
- if p.oe.top().Data != "html" {
+ if p.oe.top().DataAtom != a.Html {
p.oe.pop()
p.im = inTableIM
return false
@@ -1243,48 +1407,42 @@ func inColumnGroupIM(p *parser) bool {
// Section 12.2.5.4.13.
func inTableBodyIM(p *parser) bool {
- var (
- add bool
- data string
- attr []Attribute
- consumed bool
- )
switch p.tok.Type {
- case ErrorToken:
- // TODO.
- case TextToken:
- // TODO.
case StartTagToken:
- switch p.tok.Data {
- case "tr":
- add = true
- data = p.tok.Data
- attr = p.tok.Attr
- consumed = true
- case "td", "th":
- add = true
- data = "tr"
- consumed = false
- case "caption", "col", "colgroup", "tbody", "tfoot", "thead":
- if !p.popUntil(tableScope, "tbody", "thead", "tfoot") {
- // Ignore the token.
- return true
- }
- p.im = inTableIM
+ switch p.tok.DataAtom {
+ case a.Tr:
+ p.clearStackToContext(tableBodyScope)
+ p.addElement()
+ p.im = inRowIM
+ return true
+ case a.Td, a.Th:
+ p.parseImpliedToken(StartTagToken, a.Tr, a.Tr.String())
return false
- default:
- // TODO.
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
+ if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
+ p.im = inTableIM
+ return false
+ }
+ // Ignore the token.
+ return true
}
case EndTagToken:
- switch p.tok.Data {
- case "table":
- if p.popUntil(tableScope, "tbody", "thead", "tfoot") {
+ switch p.tok.DataAtom {
+ case a.Tbody, a.Tfoot, a.Thead:
+ if p.elementInScope(tableScope, p.tok.DataAtom) {
+ p.clearStackToContext(tableBodyScope)
+ p.oe.pop()
+ p.im = inTableIM
+ }
+ return true
+ case a.Table:
+ if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
p.im = inTableIM
return false
}
// Ignore the token.
return true
- case "body", "caption", "col", "colgroup", "html", "td", "th", "tr":
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th, a.Tr:
// Ignore the token.
return true
}
@@ -1295,117 +1453,102 @@ func inTableBodyIM(p *parser) bool {
})
return true
}
- if add {
- // TODO: clear the stack back to a table body context.
- p.addElement(data, attr)
- p.im = inRowIM
- return consumed
- }
+
return inTableIM(p)
}
// Section 12.2.5.4.14.
func inRowIM(p *parser) bool {
switch p.tok.Type {
- case ErrorToken:
- // TODO.
- case TextToken:
- // TODO.
case StartTagToken:
- switch p.tok.Data {
- case "td", "th":
+ switch p.tok.DataAtom {
+ case a.Td, a.Th:
p.clearStackToContext(tableRowScope)
- p.addElement(p.tok.Data, p.tok.Attr)
+ p.addElement()
p.afe = append(p.afe, &scopeMarker)
p.im = inCellIM
return true
- case "caption", "col", "colgroup", "tbody", "tfoot", "thead", "tr":
- if p.popUntil(tableScope, "tr") {
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ if p.popUntil(tableScope, a.Tr) {
p.im = inTableBodyIM
return false
}
// Ignore the token.
return true
- default:
- // TODO.
}
case EndTagToken:
- switch p.tok.Data {
- case "tr":
- if p.popUntil(tableScope, "tr") {
+ switch p.tok.DataAtom {
+ case a.Tr:
+ if p.popUntil(tableScope, a.Tr) {
p.im = inTableBodyIM
return true
}
// Ignore the token.
return true
- case "table":
- if p.popUntil(tableScope, "tr") {
+ case a.Table:
+ if p.popUntil(tableScope, a.Tr) {
p.im = inTableBodyIM
return false
}
// Ignore the token.
return true
- case "tbody", "tfoot", "thead":
- // TODO.
- case "body", "caption", "col", "colgroup", "html", "td", "th":
+ case a.Tbody, a.Tfoot, a.Thead:
+ if p.elementInScope(tableScope, p.tok.DataAtom) {
+ p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th:
// Ignore the token.
return true
- default:
- // TODO.
}
- case CommentToken:
- p.addChild(&Node{
- Type: CommentNode,
- Data: p.tok.Data,
- })
- return true
}
+
return inTableIM(p)
}
// Section 12.2.5.4.15.
func inCellIM(p *parser) bool {
- var (
- closeTheCellAndReprocess bool
- )
switch p.tok.Type {
case StartTagToken:
- switch p.tok.Data {
- case "caption", "col", "colgroup", "tbody", "td", "tfoot", "th", "thead", "tr":
- // TODO: check for "td" or "th" in table scope.
- closeTheCellAndReprocess = true
- case "select":
+ switch p.tok.DataAtom {
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+ if p.popUntil(tableScope, a.Td, a.Th) {
+ // Close the cell and reprocess.
+ p.clearActiveFormattingElements()
+ p.im = inRowIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Select:
p.reconstructActiveFormattingElements()
- p.addElement(p.tok.Data, p.tok.Attr)
+ p.addElement()
p.framesetOK = false
p.im = inSelectInTableIM
return true
}
case EndTagToken:
- switch p.tok.Data {
- case "td", "th":
- if !p.popUntil(tableScope, p.tok.Data) {
+ switch p.tok.DataAtom {
+ case a.Td, a.Th:
+ if !p.popUntil(tableScope, p.tok.DataAtom) {
// Ignore the token.
return true
}
p.clearActiveFormattingElements()
p.im = inRowIM
return true
- case "body", "caption", "col", "colgroup", "html":
- // TODO.
- case "table", "tbody", "tfoot", "thead", "tr":
- // TODO: check for matching element in table scope.
- closeTheCellAndReprocess = true
- }
- case CommentToken:
- p.addChild(&Node{
- Type: CommentNode,
- Data: p.tok.Data,
- })
- return true
- }
- if closeTheCellAndReprocess {
- if p.popUntil(tableScope, "td") || p.popUntil(tableScope, "th") {
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html:
+ // Ignore the token.
+ return true
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ if !p.elementInScope(tableScope, p.tok.DataAtom) {
+ // Ignore the token.
+ return true
+ }
+ // Close the cell and reprocess.
+ p.popUntil(tableScope, a.Td, a.Th)
p.clearActiveFormattingElements()
p.im = inRowIM
return false
@@ -1416,66 +1559,73 @@ func inCellIM(p *parser) bool {
// Section 12.2.5.4.16.
func inSelectIM(p *parser) bool {
- endSelect := false
switch p.tok.Type {
case ErrorToken:
- // TODO.
+ // Stop parsing.
+ return true
case TextToken:
- p.addText(p.tok.Data)
+ p.addText(strings.Replace(p.tok.Data, "\x00", "", -1))
case StartTagToken:
- switch p.tok.Data {
- case "html":
- // TODO.
- case "option":
- if p.top().Data == "option" {
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Option:
+ if p.top().DataAtom == a.Option {
p.oe.pop()
}
- p.addElement(p.tok.Data, p.tok.Attr)
- case "optgroup":
- if p.top().Data == "option" {
+ p.addElement()
+ case a.Optgroup:
+ if p.top().DataAtom == a.Option {
p.oe.pop()
}
- if p.top().Data == "optgroup" {
+ if p.top().DataAtom == a.Optgroup {
p.oe.pop()
}
- p.addElement(p.tok.Data, p.tok.Attr)
- case "select":
- endSelect = true
- case "input", "keygen", "textarea":
- // TODO.
- case "script":
- // TODO.
- default:
+ p.addElement()
+ case a.Select:
+ p.tok.Type = EndTagToken
+ return false
+ case a.Input, a.Keygen, a.Textarea:
+ if p.elementInScope(selectScope, a.Select) {
+ p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
+ return false
+ }
+ // In order to properly ignore <textarea>, we need to change the tokenizer mode.
+ p.tokenizer.NextIsNotRawText()
// Ignore the token.
+ return true
+ case a.Script:
+ return inHeadIM(p)
}
case EndTagToken:
- switch p.tok.Data {
- case "option":
- if p.top().Data == "option" {
+ switch p.tok.DataAtom {
+ case a.Option:
+ if p.top().DataAtom == a.Option {
p.oe.pop()
}
- case "optgroup":
+ case a.Optgroup:
i := len(p.oe) - 1
- if p.oe[i].Data == "option" {
+ if p.oe[i].DataAtom == a.Option {
i--
}
- if p.oe[i].Data == "optgroup" {
+ if p.oe[i].DataAtom == a.Optgroup {
p.oe = p.oe[:i]
}
- case "select":
- endSelect = true
- default:
- // Ignore the token.
+ case a.Select:
+ if p.popUntil(selectScope, a.Select) {
+ p.resetInsertionMode()
+ }
}
case CommentToken:
- p.doc.Add(&Node{
+ p.doc.AppendChild(&Node{
Type: CommentNode,
Data: p.tok.Data,
})
+ case DoctypeToken:
+ // Ignore the token.
+ return true
}
- if endSelect {
- p.endSelect()
- }
+
return true
}
@@ -1483,10 +1633,10 @@ func inSelectIM(p *parser) bool {
func inSelectInTableIM(p *parser) bool {
switch p.tok.Type {
case StartTagToken, EndTagToken:
- switch p.tok.Data {
- case "caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th":
- if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.Data) {
- p.endSelect()
+ switch p.tok.DataAtom {
+ case a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th:
+ if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.DataAtom) {
+ p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
return false
} else {
// Ignore the token.
@@ -1497,40 +1647,35 @@ func inSelectInTableIM(p *parser) bool {
return inSelectIM(p)
}
-func (p *parser) endSelect() {
- for i := len(p.oe) - 1; i >= 0; i-- {
- switch p.oe[i].Data {
- case "option", "optgroup":
- continue
- case "select":
- p.oe = p.oe[:i]
- p.resetInsertionMode()
- }
- return
- }
-}
-
// Section 12.2.5.4.18.
func afterBodyIM(p *parser) bool {
switch p.tok.Type {
case ErrorToken:
// Stop parsing.
return true
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) == 0 {
+ // It was all whitespace.
+ return inBodyIM(p)
+ }
case StartTagToken:
- if p.tok.Data == "html" {
+ if p.tok.DataAtom == a.Html {
return inBodyIM(p)
}
case EndTagToken:
- if p.tok.Data == "html" {
- p.im = afterAfterBodyIM
+ if p.tok.DataAtom == a.Html {
+ if !p.fragment {
+ p.im = afterAfterBodyIM
+ }
return true
}
case CommentToken:
// The comment is attached to the <html> element.
- if len(p.oe) < 1 || p.oe[0].Data != "html" {
+ if len(p.oe) < 1 || p.oe[0].DataAtom != a.Html {
panic("html: bad parser state: <html> element not found, in the after-body insertion mode")
}
- p.oe[0].Add(&Node{
+ p.oe[0].AppendChild(&Node{
Type: CommentNode,
Data: p.tok.Data,
})
@@ -1561,24 +1706,24 @@ func inFramesetIM(p *parser) bool {
p.addText(s)
}
case StartTagToken:
- switch p.tok.Data {
- case "html":
+ switch p.tok.DataAtom {
+ case a.Html:
return inBodyIM(p)
- case "frameset":
- p.addElement(p.tok.Data, p.tok.Attr)
- case "frame":
- p.addElement(p.tok.Data, p.tok.Attr)
+ case a.Frameset:
+ p.addElement()
+ case a.Frame:
+ p.addElement()
p.oe.pop()
p.acknowledgeSelfClosingTag()
- case "noframes":
+ case a.Noframes:
return inHeadIM(p)
}
case EndTagToken:
- switch p.tok.Data {
- case "frameset":
- if p.oe.top().Data != "html" {
+ switch p.tok.DataAtom {
+ case a.Frameset:
+ if p.oe.top().DataAtom != a.Html {
p.oe.pop()
- if p.oe.top().Data != "frameset" {
+ if p.oe.top().DataAtom != a.Frameset {
p.im = afterFramesetIM
return true
}
@@ -1611,15 +1756,15 @@ func afterFramesetIM(p *parser) bool {
p.addText(s)
}
case StartTagToken:
- switch p.tok.Data {
- case "html":
+ switch p.tok.DataAtom {
+ case a.Html:
return inBodyIM(p)
- case "noframes":
+ case a.Noframes:
return inHeadIM(p)
}
case EndTagToken:
- switch p.tok.Data {
- case "html":
+ switch p.tok.DataAtom {
+ case a.Html:
p.im = afterAfterFramesetIM
return true
}
@@ -1636,17 +1781,23 @@ func afterAfterBodyIM(p *parser) bool {
// Stop parsing.
return true
case TextToken:
- // TODO.
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) == 0 {
+ // It was all whitespace.
+ return inBodyIM(p)
+ }
case StartTagToken:
- if p.tok.Data == "html" {
+ if p.tok.DataAtom == a.Html {
return inBodyIM(p)
}
case CommentToken:
- p.doc.Add(&Node{
+ p.doc.AppendChild(&Node{
Type: CommentNode,
Data: p.tok.Data,
})
return true
+ case DoctypeToken:
+ return inBodyIM(p)
}
p.im = inBodyIM
return false
@@ -1656,7 +1807,7 @@ func afterAfterBodyIM(p *parser) bool {
func afterAfterFramesetIM(p *parser) bool {
switch p.tok.Type {
case CommentToken:
- p.addChild(&Node{
+ p.doc.AppendChild(&Node{
Type: CommentNode,
Data: p.tok.Data,
})
@@ -1670,35 +1821,34 @@ func afterAfterFramesetIM(p *parser) bool {
return -1
}, p.tok.Data)
if s != "" {
- p.reconstructActiveFormattingElements()
- p.addText(s)
+ p.tok.Data = s
+ return inBodyIM(p)
}
case StartTagToken:
- switch p.tok.Data {
- case "html":
+ switch p.tok.DataAtom {
+ case a.Html:
return inBodyIM(p)
- case "noframes":
+ case a.Noframes:
return inHeadIM(p)
}
+ case DoctypeToken:
+ return inBodyIM(p)
default:
// Ignore the token.
}
return true
}
+const whitespaceOrNUL = whitespace + "\x00"
+
// Section 12.2.5.5.
func parseForeignContent(p *parser) bool {
switch p.tok.Type {
case TextToken:
- // TODO: HTML integration points.
- if p.top().Namespace == "" {
- inBodyIM(p)
- p.resetInsertionMode()
- return true
- }
if p.framesetOK {
- p.framesetOK = strings.TrimLeft(p.tok.Data, whitespace) == ""
+ p.framesetOK = strings.TrimLeft(p.tok.Data, whitespaceOrNUL) == ""
}
+ p.tok.Data = strings.Replace(p.tok.Data, "\x00", "\ufffd", -1)
p.addText(p.tok.Data)
case CommentToken:
p.addChild(&Node{
@@ -1706,15 +1856,21 @@ func parseForeignContent(p *parser) bool {
Data: p.tok.Data,
})
case StartTagToken:
- if htmlIntegrationPoint(p.top()) {
- inBodyIM(p)
- p.resetInsertionMode()
- return true
+ b := breakout[p.tok.Data]
+ if p.tok.DataAtom == a.Font {
+ loop:
+ for _, attr := range p.tok.Attr {
+ switch attr.Key {
+ case "color", "face", "size":
+ b = true
+ break loop
+ }
+ }
}
- if breakout[p.tok.Data] {
+ if b {
for i := len(p.oe) - 1; i >= 0; i-- {
- // TODO: MathML integration points.
- if p.oe[i].Namespace == "" || htmlIntegrationPoint(p.oe[i]) {
+ n := p.oe[i]
+ if n.Namespace == "" || htmlIntegrationPoint(n) || mathMLTextIntegrationPoint(n) {
p.oe = p.oe[:i+1]
break
}
@@ -1723,21 +1879,31 @@ func parseForeignContent(p *parser) bool {
}
switch p.top().Namespace {
case "math":
- // TODO: adjust MathML attributes.
+ adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
case "svg":
// Adjust SVG tag names. The tokenizer lower-cases tag names, but
// SVG wants e.g. "foreignObject" with a capital second "O".
if x := svgTagNameAdjustments[p.tok.Data]; x != "" {
+ p.tok.DataAtom = a.Lookup([]byte(x))
p.tok.Data = x
}
- // TODO: adjust SVG attributes.
+ adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
default:
panic("html: bad parser state: unexpected namespace")
}
adjustForeignAttributes(p.tok.Attr)
namespace := p.top().Namespace
- p.addElement(p.tok.Data, p.tok.Attr)
+ p.addElement()
p.top().Namespace = namespace
+ if namespace != "" {
+ // Don't let the tokenizer go into raw text mode in foreign content
+ // (e.g. in an SVG <title> tag).
+ p.tokenizer.NextIsNotRawText()
+ }
+ if p.hasSelfClosingToken {
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ }
case EndTagToken:
for i := len(p.oe) - 1; i >= 0; i-- {
if p.oe[i].Namespace == "" {
@@ -1764,34 +1930,80 @@ func (p *parser) inForeignContent() bool {
if n.Namespace == "" {
return false
}
- // TODO: MathML, HTML integration points.
- // TODO: MathML's annotation-xml combining with SVG's svg.
+ if mathMLTextIntegrationPoint(n) {
+ if p.tok.Type == StartTagToken && p.tok.DataAtom != a.Mglyph && p.tok.DataAtom != a.Malignmark {
+ return false
+ }
+ if p.tok.Type == TextToken {
+ return false
+ }
+ }
+ if n.Namespace == "math" && n.DataAtom == a.AnnotationXml && p.tok.Type == StartTagToken && p.tok.DataAtom == a.Svg {
+ return false
+ }
+ if htmlIntegrationPoint(n) && (p.tok.Type == StartTagToken || p.tok.Type == TextToken) {
+ return false
+ }
+ if p.tok.Type == ErrorToken {
+ return false
+ }
return true
}
-func (p *parser) parse() error {
- // Iterate until EOF. Any other error will cause an early return.
- consumed := true
- for {
- if consumed {
- if err := p.read(); err != nil {
- if err == io.EOF {
- break
- }
- return err
- }
- }
+// parseImpliedToken parses a token as though it had appeared in the parser's
+// input.
+func (p *parser) parseImpliedToken(t TokenType, dataAtom a.Atom, data string) {
+ realToken, selfClosing := p.tok, p.hasSelfClosingToken
+ p.tok = Token{
+ Type: t,
+ DataAtom: dataAtom,
+ Data: data,
+ }
+ p.hasSelfClosingToken = false
+ p.parseCurrentToken()
+ p.tok, p.hasSelfClosingToken = realToken, selfClosing
+}
+
+// parseCurrentToken runs the current token through the parsing routines
+// until it is consumed.
+func (p *parser) parseCurrentToken() {
+ if p.tok.Type == SelfClosingTagToken {
+ p.hasSelfClosingToken = true
+ p.tok.Type = StartTagToken
+ }
+
+ consumed := false
+ for !consumed {
if p.inForeignContent() {
consumed = parseForeignContent(p)
} else {
consumed = p.im(p)
}
}
- // Loop until the final token (the ErrorToken signifying EOF) is consumed.
- for {
- if consumed = p.im(p); consumed {
- break
+
+ if p.hasSelfClosingToken {
+ // This is a parse error, but ignore it.
+ p.hasSelfClosingToken = false
+ }
+}
+
+func (p *parser) parse() error {
+ // Iterate until EOF. Any other error will cause an early return.
+ var err error
+ for err != io.EOF {
+ // CDATA sections are allowed only in foreign content.
+ n := p.oe.top()
+ p.tokenizer.AllowCDATA(n != nil && n.Namespace != "")
+ // Read and parse the next token.
+ p.tokenizer.Next()
+ p.tok = p.tokenizer.Token()
+ if p.tok.Type == ErrorToken {
+ err = p.tokenizer.Err()
+ if err != nil && err != io.EOF {
+ return err
+ }
}
+ p.parseCurrentToken()
}
return nil
}
@@ -1819,32 +2031,40 @@ func Parse(r io.Reader) (*Node, error) {
// found. If the fragment is the InnerHTML for an existing element, pass that
// element in context.
func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
+ contextTag := ""
+ if context != nil {
+ if context.Type != ElementNode {
+ return nil, errors.New("html: ParseFragment of non-element Node")
+ }
+ // The next check isn't just context.DataAtom.String() == context.Data because
+ // it is valid to pass an element whose tag isn't a known atom. For example,
+ // DataAtom == 0 and Data = "tagfromthefuture" is perfectly consistent.
+ if context.DataAtom != a.Lookup([]byte(context.Data)) {
+ return nil, fmt.Errorf("html: inconsistent Node: DataAtom=%q, Data=%q", context.DataAtom, context.Data)
+ }
+ contextTag = context.DataAtom.String()
+ }
p := &parser{
- tokenizer: NewTokenizer(r),
+ tokenizer: NewTokenizerFragment(r, contextTag),
doc: &Node{
Type: DocumentNode,
},
scripting: true,
+ fragment: true,
context: context,
}
- if context != nil {
- switch context.Data {
- case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "title", "textarea", "xmp":
- p.tokenizer.rawTag = context.Data
- }
- }
-
root := &Node{
- Type: ElementNode,
- Data: "html",
+ Type: ElementNode,
+ DataAtom: a.Html,
+ Data: a.Html.String(),
}
- p.doc.Add(root)
+ p.doc.AppendChild(root)
p.oe = nodeStack{root}
p.resetInsertionMode()
for n := context; n != nil; n = n.Parent {
- if n.Type == ElementNode && n.Data == "form" {
+ if n.Type == ElementNode && n.DataAtom == a.Form {
p.form = n
break
}
@@ -1860,10 +2080,12 @@ func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
parent = root
}
- result := parent.Child
- parent.Child = nil
- for _, n := range result {
- n.Parent = nil
+ var result []*Node
+ for c := parent.FirstChild; c != nil; {
+ next := c.NextSibling
+ parent.RemoveChild(c)
+ result = append(result, c)
+ c = next
}
return result, nil
}
diff --git a/libgo/go/exp/html/parse_test.go b/libgo/go/exp/html/parse_test.go
index f3f966cf58e..7cf2ff4163e 100644
--- a/libgo/go/exp/html/parse_test.go
+++ b/libgo/go/exp/html/parse_test.go
@@ -8,9 +8,14 @@ import (
"bufio"
"bytes"
"errors"
+ "exp/html/atom"
"fmt"
"io"
+ "io/ioutil"
"os"
+ "path/filepath"
+ "runtime"
+ "sort"
"strings"
"testing"
)
@@ -37,7 +42,10 @@ func readParseTest(r *bufio.Reader) (text, want, context string, err error) {
}
b = append(b, line...)
}
- text = strings.TrimRight(string(b), "\n")
+ text = string(b)
+ if strings.HasSuffix(text, "\n") {
+ text = text[:len(text)-1]
+ }
b = b[:0]
// Skip the error list.
@@ -70,12 +78,22 @@ func readParseTest(r *bufio.Reader) (text, want, context string, err error) {
if string(line) != "#document\n" {
return "", "", "", fmt.Errorf(`got %q want "#document\n"`, line)
}
+ inQuote := false
for {
line, err = r.ReadSlice('\n')
if err != nil && err != io.EOF {
return "", "", "", err
}
- if len(line) == 0 || len(line) == 1 && line[0] == '\n' {
+ trimmed := bytes.Trim(line, "| \n")
+ if len(trimmed) > 0 {
+ if line[0] == '|' && trimmed[0] == '"' {
+ inQuote = true
+ }
+ if trimmed[len(trimmed)-1] == '"' && !(line[0] == '|' && len(trimmed) == 1) {
+ inQuote = false
+ }
+ }
+ if len(line) == 0 || len(line) == 1 && line[0] == '\n' && !inQuote {
break
}
b = append(b, line...)
@@ -90,6 +108,23 @@ func dumpIndent(w io.Writer, level int) {
}
}
+type sortedAttributes []Attribute
+
+func (a sortedAttributes) Len() int {
+ return len(a)
+}
+
+func (a sortedAttributes) Less(i, j int) bool {
+ if a[i].Namespace != a[j].Namespace {
+ return a[i].Namespace < a[j].Namespace
+ }
+ return a[i].Key < a[j].Key
+}
+
+func (a sortedAttributes) Swap(i, j int) {
+ a[i], a[j] = a[j], a[i]
+}
+
func dumpLevel(w io.Writer, n *Node, level int) error {
dumpIndent(w, level)
switch n.Type {
@@ -103,13 +138,8 @@ func dumpLevel(w io.Writer, n *Node, level int) error {
} else {
fmt.Fprintf(w, "<%s>", n.Data)
}
- attr := n.Attr
- if len(attr) == 2 && attr[0].Namespace == "xml" && attr[1].Namespace == "xlink" {
- // Some of the test cases in tests10.dat change the order of adjusted
- // foreign attributes, but that behavior is not in the spec, and could
- // simply be an implementation detail of html5lib's python map ordering.
- attr[0], attr[1] = attr[1], attr[0]
- }
+ attr := sortedAttributes(n.Attr)
+ sort.Sort(attr)
for _, a := range attr {
io.WriteString(w, "\n")
dumpIndent(w, level+1)
@@ -147,7 +177,7 @@ func dumpLevel(w io.Writer, n *Node, level int) error {
return errors.New("unknown node type")
}
io.WriteString(w, "\n")
- for _, c := range n.Child {
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
if err := dumpLevel(w, c, level+1); err != nil {
return err
}
@@ -156,106 +186,126 @@ func dumpLevel(w io.Writer, n *Node, level int) error {
}
func dump(n *Node) (string, error) {
- if n == nil || len(n.Child) == 0 {
+ if n == nil || n.FirstChild == nil {
return "", nil
}
var b bytes.Buffer
- for _, child := range n.Child {
- if err := dumpLevel(&b, child, 0); err != nil {
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if err := dumpLevel(&b, c, 0); err != nil {
return "", err
}
}
return b.String(), nil
}
+const testDataDir = "testdata/webkit/"
+
func TestParser(t *testing.T) {
- testFiles := []struct {
- filename string
- // n is the number of test cases to run from that file.
- // -1 means all test cases.
- n int
- }{
- // TODO(nigeltao): Process all the test cases from all the .dat files.
- {"adoption01.dat", -1},
- {"doctype01.dat", -1},
- {"tests1.dat", -1},
- {"tests2.dat", -1},
- {"tests3.dat", -1},
- {"tests4.dat", -1},
- {"tests5.dat", -1},
- {"tests6.dat", -1},
- {"tests10.dat", 35},
+ testFiles, err := filepath.Glob(testDataDir + "*.dat")
+ if err != nil {
+ t.Fatal(err)
}
for _, tf := range testFiles {
- f, err := os.Open("testdata/webkit/" + tf.filename)
+ f, err := os.Open(tf)
if err != nil {
t.Fatal(err)
}
defer f.Close()
r := bufio.NewReader(f)
- for i := 0; i != tf.n; i++ {
+
+ for i := 0; ; i++ {
text, want, context, err := readParseTest(r)
- if err == io.EOF && tf.n == -1 {
+ if err == io.EOF {
break
}
if err != nil {
t.Fatal(err)
}
- var doc *Node
- if context == "" {
- doc, err = Parse(strings.NewReader(text))
- if err != nil {
- t.Fatal(err)
- }
- } else {
- contextNode := &Node{
- Type: ElementNode,
- Data: context,
- }
- nodes, err := ParseFragment(strings.NewReader(text), contextNode)
- if err != nil {
- t.Fatal(err)
- }
- doc = &Node{
- Type: DocumentNode,
- }
- for _, n := range nodes {
- doc.Add(n)
- }
- }
+ err = testParseCase(text, want, context)
- got, err := dump(doc)
- if err != nil {
- t.Fatal(err)
- }
- // Compare the parsed tree to the #document section.
- if got != want {
- t.Errorf("%s test #%d %q, got vs want:\n----\n%s----\n%s----", tf.filename, i, text, got, want)
- continue
- }
- if renderTestBlacklist[text] || context != "" {
- continue
- }
- // Check that rendering and re-parsing results in an identical tree.
- pr, pw := io.Pipe()
- go func() {
- pw.CloseWithError(Render(pw, doc))
- }()
- doc1, err := Parse(pr)
if err != nil {
- t.Fatal(err)
- }
- got1, err := dump(doc1)
- if err != nil {
- t.Fatal(err)
+ t.Errorf("%s test #%d %q, %s", tf, i, text, err)
}
- if got != got1 {
- t.Errorf("%s test #%d %q, got vs got1:\n----\n%s----\n%s----", tf.filename, i, text, got, got1)
- continue
+ }
+ }
+}
+
+// testParseCase tests one test case from the test files. If the test does not
+// pass, it returns an error that explains the failure.
+// text is the HTML to be parsed, want is a dump of the correct parse tree,
+// and context is the name of the context node, if any.
+func testParseCase(text, want, context string) (err error) {
+ defer func() {
+ if x := recover(); x != nil {
+ switch e := x.(type) {
+ case error:
+ err = e
+ default:
+ err = fmt.Errorf("%v", e)
}
}
+ }()
+
+ var doc *Node
+ if context == "" {
+ doc, err = Parse(strings.NewReader(text))
+ if err != nil {
+ return err
+ }
+ } else {
+ contextNode := &Node{
+ Type: ElementNode,
+ DataAtom: atom.Lookup([]byte(context)),
+ Data: context,
+ }
+ nodes, err := ParseFragment(strings.NewReader(text), contextNode)
+ if err != nil {
+ return err
+ }
+ doc = &Node{
+ Type: DocumentNode,
+ }
+ for _, n := range nodes {
+ doc.AppendChild(n)
+ }
+ }
+
+ if err := checkTreeConsistency(doc); err != nil {
+ return err
+ }
+
+ got, err := dump(doc)
+ if err != nil {
+ return err
+ }
+ // Compare the parsed tree to the #document section.
+ if got != want {
+ return fmt.Errorf("got vs want:\n----\n%s----\n%s----", got, want)
+ }
+
+ if renderTestBlacklist[text] || context != "" {
+ return nil
}
+
+ // Check that rendering and re-parsing results in an identical tree.
+ pr, pw := io.Pipe()
+ go func() {
+ pw.CloseWithError(Render(pw, doc))
+ }()
+ doc1, err := Parse(pr)
+ if err != nil {
+ return err
+ }
+ got1, err := dump(doc1)
+ if err != nil {
+ return err
+ }
+ if got != got1 {
+ return fmt.Errorf("got vs got1:\n----\n%s----\n%s----", got, got1)
+ }
+
+ return nil
}
// Some test input result in parse trees are not 'well-formed' despite
@@ -266,11 +316,81 @@ var renderTestBlacklist = map[string]bool{
// The second <a> will be reparented to the first <table>'s parent. This
// results in an <a> whose parent is an <a>, which is not 'well-formed'.
`<a><table><td><a><table></table><a></tr><a></table><b>X</b>C<a>Y`: true,
+ // The same thing with a <p>:
+ `<p><table></p>`: true,
// More cases of <a> being reparented:
`<a href="blah">aba<table><a href="foo">br<tr><td></td></tr>x</table>aoe`: true,
`<a><table><a></table><p><a><div><a>`: true,
`<a><table><td><a><table></table><a></tr><a></table><a>`: true,
+ // A similar reparenting situation involving <nobr>:
+ `<!DOCTYPE html><body><b><nobr>1<table><nobr></b><i><nobr>2<nobr></i>3`: true,
// A <plaintext> element is reparented, putting it before a table.
// A <plaintext> element can't have anything after it in HTML.
- `<table><plaintext><td>`: true,
+ `<table><plaintext><td>`: true,
+ `<!doctype html><table><plaintext></plaintext>`: true,
+ `<!doctype html><table><tbody><plaintext></plaintext>`: true,
+ `<!doctype html><table><tbody><tr><plaintext></plaintext>`: true,
+ // A form inside a table inside a form doesn't work either.
+ `<!doctype html><form><table></form><form></table></form>`: true,
+ // A script that ends at EOF may escape its own closing tag when rendered.
+ `<!doctype html><script><!--<script `: true,
+ `<!doctype html><script><!--<script <`: true,
+ `<!doctype html><script><!--<script <a`: true,
+ `<!doctype html><script><!--<script </`: true,
+ `<!doctype html><script><!--<script </s`: true,
+ `<!doctype html><script><!--<script </script`: true,
+ `<!doctype html><script><!--<script </scripta`: true,
+ `<!doctype html><script><!--<script -`: true,
+ `<!doctype html><script><!--<script -a`: true,
+ `<!doctype html><script><!--<script -<`: true,
+ `<!doctype html><script><!--<script --`: true,
+ `<!doctype html><script><!--<script --a`: true,
+ `<!doctype html><script><!--<script --<`: true,
+ `<script><!--<script `: true,
+ `<script><!--<script <a`: true,
+ `<script><!--<script </script`: true,
+ `<script><!--<script </scripta`: true,
+ `<script><!--<script -`: true,
+ `<script><!--<script -a`: true,
+ `<script><!--<script --`: true,
+ `<script><!--<script --a`: true,
+ `<script><!--<script <`: true,
+ `<script><!--<script </`: true,
+ `<script><!--<script </s`: true,
+ // Reconstructing the active formatting elements results in a <plaintext>
+ // element that contains an <a> element.
+ `<!doctype html><p><a><plaintext>b`: true,
+}
+
+func TestNodeConsistency(t *testing.T) {
+ // inconsistentNode is a Node whose DataAtom and Data do not agree.
+ inconsistentNode := &Node{
+ Type: ElementNode,
+ DataAtom: atom.Frameset,
+ Data: "table",
+ }
+ _, err := ParseFragment(strings.NewReader("<p>hello</p>"), inconsistentNode)
+ if err == nil {
+ t.Errorf("got nil error, want non-nil")
+ }
+}
+
+func BenchmarkParser(b *testing.B) {
+ buf, err := ioutil.ReadFile("testdata/go1.html")
+ if err != nil {
+ b.Fatalf("could not read testdata/go1.html: %v", err)
+ }
+ b.SetBytes(int64(len(buf)))
+ runtime.GC()
+ var ms runtime.MemStats
+ runtime.ReadMemStats(&ms)
+ mallocs := ms.Mallocs
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse(bytes.NewBuffer(buf))
+ }
+ b.StopTimer()
+ runtime.ReadMemStats(&ms)
+ mallocs = ms.Mallocs - mallocs
+ b.Logf("%d iterations, %d mallocs per iteration\n", b.N, int(mallocs)/b.N)
}
diff --git a/libgo/go/exp/html/render.go b/libgo/go/exp/html/render.go
index 07859faa7dd..65b10046a48 100644
--- a/libgo/go/exp/html/render.go
+++ b/libgo/go/exp/html/render.go
@@ -73,7 +73,7 @@ func render1(w writer, n *Node) error {
case TextNode:
return escape(w, n.Data)
case DocumentNode:
- for _, c := range n.Child {
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
if err := render1(w, c); err != nil {
return err
}
@@ -171,7 +171,7 @@ func render1(w writer, n *Node) error {
}
}
if voidElements[n.Data] {
- if len(n.Child) != 0 {
+ if n.FirstChild != nil {
return fmt.Errorf("html: void element <%s> has child nodes", n.Data)
}
_, err := w.WriteString("/>")
@@ -182,7 +182,7 @@ func render1(w writer, n *Node) error {
}
// Add initial newline where there is danger of a newline beging ignored.
- if len(n.Child) > 0 && n.Child[0].Type == TextNode && strings.HasPrefix(n.Child[0].Data, "\n") {
+ if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
switch n.Data {
case "pre", "listing", "textarea":
if err := w.WriteByte('\n'); err != nil {
@@ -194,12 +194,15 @@ func render1(w writer, n *Node) error {
// Render any child nodes.
switch n.Data {
case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp":
- for _, c := range n.Child {
- if c.Type != TextNode {
- return fmt.Errorf("html: raw text element <%s> has non-text child node", n.Data)
- }
- if _, err := w.WriteString(c.Data); err != nil {
- return err
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if c.Type == TextNode {
+ if _, err := w.WriteString(c.Data); err != nil {
+ return err
+ }
+ } else {
+ if err := render1(w, c); err != nil {
+ return err
+ }
}
}
if n.Data == "plaintext" {
@@ -207,17 +210,8 @@ func render1(w writer, n *Node) error {
// last element in the file, with no closing tag.
return plaintextAbort
}
- case "textarea", "title":
- for _, c := range n.Child {
- if c.Type != TextNode {
- return fmt.Errorf("html: RCDATA element <%s> has non-text child node", n.Data)
- }
- if err := render1(w, c); err != nil {
- return err
- }
- }
default:
- for _, c := range n.Child {
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
if err := render1(w, c); err != nil {
return err
}
diff --git a/libgo/go/exp/html/render_test.go b/libgo/go/exp/html/render_test.go
index 0584f35abdb..11da54b313e 100644
--- a/libgo/go/exp/html/render_test.go
+++ b/libgo/go/exp/html/render_test.go
@@ -10,99 +10,144 @@ import (
)
func TestRenderer(t *testing.T) {
- n := &Node{
- Type: ElementNode,
- Data: "html",
- Child: []*Node{
- {
- Type: ElementNode,
- Data: "head",
+ nodes := [...]*Node{
+ 0: {
+ Type: ElementNode,
+ Data: "html",
+ },
+ 1: {
+ Type: ElementNode,
+ Data: "head",
+ },
+ 2: {
+ Type: ElementNode,
+ Data: "body",
+ },
+ 3: {
+ Type: TextNode,
+ Data: "0<1",
+ },
+ 4: {
+ Type: ElementNode,
+ Data: "p",
+ Attr: []Attribute{
+ {
+ Key: "id",
+ Val: "A",
+ },
+ {
+ Key: "foo",
+ Val: `abc"def`,
+ },
},
- {
- Type: ElementNode,
- Data: "body",
- Child: []*Node{
- {
- Type: TextNode,
- Data: "0<1",
- },
- {
- Type: ElementNode,
- Data: "p",
- Attr: []Attribute{
- {
- Key: "id",
- Val: "A",
- },
- {
- Key: "foo",
- Val: `abc"def`,
- },
- },
- Child: []*Node{
- {
- Type: TextNode,
- Data: "2",
- },
- {
- Type: ElementNode,
- Data: "b",
- Attr: []Attribute{
- {
- Key: "empty",
- Val: "",
- },
- },
- Child: []*Node{
- {
- Type: TextNode,
- Data: "3",
- },
- },
- },
- {
- Type: ElementNode,
- Data: "i",
- Attr: []Attribute{
- {
- Key: "backslash",
- Val: `\`,
- },
- },
- Child: []*Node{
- {
- Type: TextNode,
- Data: "&4",
- },
- },
- },
- },
- },
- {
- Type: TextNode,
- Data: "5",
- },
- {
- Type: ElementNode,
- Data: "blockquote",
- },
- {
- Type: ElementNode,
- Data: "br",
- },
- {
- Type: TextNode,
- Data: "6",
- },
+ },
+ 5: {
+ Type: TextNode,
+ Data: "2",
+ },
+ 6: {
+ Type: ElementNode,
+ Data: "b",
+ Attr: []Attribute{
+ {
+ Key: "empty",
+ Val: "",
+ },
+ },
+ },
+ 7: {
+ Type: TextNode,
+ Data: "3",
+ },
+ 8: {
+ Type: ElementNode,
+ Data: "i",
+ Attr: []Attribute{
+ {
+ Key: "backslash",
+ Val: `\`,
},
},
},
+ 9: {
+ Type: TextNode,
+ Data: "&4",
+ },
+ 10: {
+ Type: TextNode,
+ Data: "5",
+ },
+ 11: {
+ Type: ElementNode,
+ Data: "blockquote",
+ },
+ 12: {
+ Type: ElementNode,
+ Data: "br",
+ },
+ 13: {
+ Type: TextNode,
+ Data: "6",
+ },
}
- want := `<html><head></head><body>0&lt;1<p id="A" foo="abc&quot;def">` +
+
+ // Build a tree out of those nodes, based on a textual representation.
+ // Only the ".\t"s are significant. The trailing HTML-like text is
+ // just commentary. The "0:" prefixes are for easy cross-reference with
+ // the nodes array.
+ treeAsText := [...]string{
+ 0: `<html>`,
+ 1: `. <head>`,
+ 2: `. <body>`,
+ 3: `. . "0&lt;1"`,
+ 4: `. . <p id="A" foo="abc&#34;def">`,
+ 5: `. . . "2"`,
+ 6: `. . . <b empty="">`,
+ 7: `. . . . "3"`,
+ 8: `. . . <i backslash="\">`,
+ 9: `. . . . "&amp;4"`,
+ 10: `. . "5"`,
+ 11: `. . <blockquote>`,
+ 12: `. . <br>`,
+ 13: `. . "6"`,
+ }
+ if len(nodes) != len(treeAsText) {
+ t.Fatal("len(nodes) != len(treeAsText)")
+ }
+ var stack [8]*Node
+ for i, line := range treeAsText {
+ level := 0
+ for line[0] == '.' {
+ // Strip a leading ".\t".
+ line = line[2:]
+ level++
+ }
+ n := nodes[i]
+ if level == 0 {
+ if stack[0] != nil {
+ t.Fatal("multiple root nodes")
+ }
+ stack[0] = n
+ } else {
+ stack[level-1].AppendChild(n)
+ stack[level] = n
+ for i := level + 1; i < len(stack); i++ {
+ stack[i] = nil
+ }
+ }
+ // At each stage of tree construction, we check all nodes for consistency.
+ for j, m := range nodes {
+ if err := checkNodeConsistency(m); err != nil {
+ t.Fatalf("i=%d, j=%d: %v", i, j, err)
+ }
+ }
+ }
+
+ want := `<html><head></head><body>0&lt;1<p id="A" foo="abc&#34;def">` +
`2<b empty="">3</b><i backslash="\">&amp;4</i></p>` +
`5<blockquote></blockquote><br/>6</body></html>`
b := new(bytes.Buffer)
- if err := Render(b, n); err != nil {
+ if err := Render(b, nodes[0]); err != nil {
t.Fatal(err)
}
if got := b.String(); got != want {
diff --git a/libgo/go/exp/html/testdata/go1.html b/libgo/go/exp/html/testdata/go1.html
new file mode 100644
index 00000000000..a782cc71d20
--- /dev/null
+++ b/libgo/go/exp/html/testdata/go1.html
@@ -0,0 +1,2237 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ <title>Go 1 Release Notes - The Go Programming Language</title>
+
+<link type="text/css" rel="stylesheet" href="/doc/style.css">
+<script type="text/javascript" src="/doc/godocs.js"></script>
+
+<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
+
+<script type="text/javascript">
+var _gaq = _gaq || [];
+_gaq.push(["_setAccount", "UA-11222381-2"]);
+_gaq.push(["_trackPageview"]);
+</script>
+</head>
+<body>
+
+<div id="topbar"><div class="container wide">
+
+<form method="GET" action="/search">
+<div id="menu">
+<a href="/doc/">Documents</a>
+<a href="/ref/">References</a>
+<a href="/pkg/">Packages</a>
+<a href="/project/">The Project</a>
+<a href="/help/">Help</a>
+<input type="text" id="search" name="q" class="inactive" value="Search">
+</div>
+<div id="heading"><a href="/">The Go Programming Language</a></div>
+</form>
+
+</div></div>
+
+<div id="page" class="wide">
+
+
+ <div id="plusone"><g:plusone size="small" annotation="none"></g:plusone></div>
+ <h1>Go 1 Release Notes</h1>
+
+
+
+
+<div id="nav"></div>
+
+
+
+
+<h2 id="introduction">Introduction to Go 1</h2>
+
+<p>
+Go version 1, Go 1 for short, defines a language and a set of core libraries
+that provide a stable foundation for creating reliable products, projects, and
+publications.
+</p>
+
+<p>
+The driving motivation for Go 1 is stability for its users. People should be able to
+write Go programs and expect that they will continue to compile and run without
+change, on a time scale of years, including in production environments such as
+Google App Engine. Similarly, people should be able to write books about Go, be
+able to say which version of Go the book is describing, and have that version
+number still be meaningful much later.
+</p>
+
+<p>
+Code that compiles in Go 1 should, with few exceptions, continue to compile and
+run throughout the lifetime of that version, even as we issue updates and bug
+fixes such as Go version 1.1, 1.2, and so on. Other than critical fixes, changes
+made to the language and library for subsequent releases of Go 1 may
+add functionality but will not break existing Go 1 programs.
+<a href="go1compat.html">The Go 1 compatibility document</a>
+explains the compatibility guidelines in more detail.
+</p>
+
+<p>
+Go 1 is a representation of Go as it used today, not a wholesale rethinking of
+the language. We avoided designing new features and instead focused on cleaning
+up problems and inconsistencies and improving portability. There are a number
+changes to the Go language and packages that we had considered for some time and
+prototyped but not released primarily because they are significant and
+backwards-incompatible. Go 1 was an opportunity to get them out, which is
+helpful for the long term, but also means that Go 1 introduces incompatibilities
+for old programs. Fortunately, the <code>go</code> <code>fix</code> tool can
+automate much of the work needed to bring programs up to the Go 1 standard.
+</p>
+
+<p>
+This document outlines the major changes in Go 1 that will affect programmers
+updating existing code; its reference point is the prior release, r60 (tagged as
+r60.3). It also explains how to update code from r60 to run under Go 1.
+</p>
+
+<h2 id="language">Changes to the language</h2>
+
+<h3 id="append">Append</h3>
+
+<p>
+The <code>append</code> predeclared variadic function makes it easy to grow a slice
+by adding elements to the end.
+A common use is to add bytes to the end of a byte slice when generating output.
+However, <code>append</code> did not provide a way to append a string to a <code>[]byte</code>,
+which is another common case.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
+--> greeting := []byte{}
+ greeting = append(greeting, []byte(&#34;hello &#34;)...)</pre>
+
+<p>
+By analogy with the similar property of <code>copy</code>, Go 1
+permits a string to be appended (byte-wise) directly to a byte
+slice, reducing the friction between strings and byte slices.
+The conversion is no longer necessary:
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/append.*world/`}}
+--> greeting = append(greeting, &#34;world&#34;...)</pre>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="close">Close</h3>
+
+<p>
+The <code>close</code> predeclared function provides a mechanism
+for a sender to signal that no more values will be sent.
+It is important to the implementation of <code>for</code> <code>range</code>
+loops over channels and is helpful in other situations.
+Partly by design and partly because of race conditions that can occur otherwise,
+it is intended for use only by the goroutine sending on the channel,
+not by the goroutine receiving data.
+However, before Go 1 there was no compile-time checking that <code>close</code>
+was being used correctly.
+</p>
+
+<p>
+To close this gap, at least in part, Go 1 disallows <code>close</code> on receive-only channels.
+Attempting to close such a channel is a compile-time error.
+</p>
+
+<pre>
+ var c chan int
+ var csend chan&lt;- int = c
+ var crecv &lt;-chan int = c
+ close(c) // legal
+ close(csend) // legal
+ close(crecv) // illegal
+</pre>
+
+<p>
+<em>Updating</em>:
+Existing code that attempts to close a receive-only channel was
+erroneous even before Go 1 and should be fixed. The compiler will
+now reject such code.
+</p>
+
+<h3 id="literals">Composite literals</h3>
+
+<p>
+In Go 1, a composite literal of array, slice, or map type can elide the
+type specification for the elements' initializers if they are of pointer type.
+All four of the initializations in this example are legal; the last one was illegal before Go 1.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/type Date struct/` `/STOP/`}}
+--> type Date struct {
+ month string
+ day int
+ }
+ <span class="comment">// Struct values, fully qualified; always legal.</span>
+ holiday1 := []Date{
+ Date{&#34;Feb&#34;, 14},
+ Date{&#34;Nov&#34;, 11},
+ Date{&#34;Dec&#34;, 25},
+ }
+ <span class="comment">// Struct values, type name elided; always legal.</span>
+ holiday2 := []Date{
+ {&#34;Feb&#34;, 14},
+ {&#34;Nov&#34;, 11},
+ {&#34;Dec&#34;, 25},
+ }
+ <span class="comment">// Pointers, fully qualified, always legal.</span>
+ holiday3 := []*Date{
+ &amp;Date{&#34;Feb&#34;, 14},
+ &amp;Date{&#34;Nov&#34;, 11},
+ &amp;Date{&#34;Dec&#34;, 25},
+ }
+ <span class="comment">// Pointers, type name elided; legal in Go 1.</span>
+ holiday4 := []*Date{
+ {&#34;Feb&#34;, 14},
+ {&#34;Nov&#34;, 11},
+ {&#34;Dec&#34;, 25},
+ }</pre>
+
+<p>
+<em>Updating</em>:
+This change has no effect on existing code, but the command
+<code>gofmt</code> <code>-s</code> applied to existing source
+will, among other things, elide explicit element types wherever permitted.
+</p>
+
+
+<h3 id="init">Goroutines during init</h3>
+
+<p>
+The old language defined that <code>go</code> statements executed during initialization created goroutines but that they did not begin to run until initialization of the entire program was complete.
+This introduced clumsiness in many places and, in effect, limited the utility
+of the <code>init</code> construct:
+if it was possible for another package to use the library during initialization, the library
+was forced to avoid goroutines.
+This design was done for reasons of simplicity and safety but,
+as our confidence in the language grew, it seemed unnecessary.
+Running goroutines during initialization is no more complex or unsafe than running them during normal execution.
+</p>
+
+<p>
+In Go 1, code that uses goroutines can be called from
+<code>init</code> routines and global initialization expressions
+without introducing a deadlock.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/PackageGlobal/` `/^}/`}}
+-->var PackageGlobal int
+
+func init() {
+ c := make(chan int)
+ go initializationFunction(c)
+ PackageGlobal = &lt;-c
+}</pre>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes,
+although it's possible that code that depends on goroutines not starting before <code>main</code> will break.
+There was no such code in the standard repository.
+</p>
+
+<h3 id="rune">The rune type</h3>
+
+<p>
+The language spec allows the <code>int</code> type to be 32 or 64 bits wide, but current implementations set <code>int</code> to 32 bits even on 64-bit platforms.
+It would be preferable to have <code>int</code> be 64 bits on 64-bit platforms.
+(There are important consequences for indexing large slices.)
+However, this change would waste space when processing Unicode characters with
+the old language because the <code>int</code> type was also used to hold Unicode code points: each code point would waste an extra 32 bits of storage if <code>int</code> grew from 32 bits to 64.
+</p>
+
+<p>
+To make changing to 64-bit <code>int</code> feasible,
+Go 1 introduces a new basic type, <code>rune</code>, to represent
+individual Unicode code points.
+It is an alias for <code>int32</code>, analogous to <code>byte</code>
+as an alias for <code>uint8</code>.
+</p>
+
+<p>
+Character literals such as <code>'a'</code>, <code>'語'</code>, and <code>'\u0345'</code>
+now have default type <code>rune</code>,
+analogous to <code>1.0</code> having default type <code>float64</code>.
+A variable initialized to a character constant will therefore
+have type <code>rune</code> unless otherwise specified.
+</p>
+
+<p>
+Libraries have been updated to use <code>rune</code> rather than <code>int</code>
+when appropriate. For instance, the functions <code>unicode.ToLower</code> and
+relatives now take and return a <code>rune</code>.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/STARTRUNE/` `/ENDRUNE/`}}
+--> delta := &#39;δ&#39; <span class="comment">// delta has type rune.</span>
+ var DELTA rune
+ DELTA = unicode.ToUpper(delta)
+ epsilon := unicode.ToLower(DELTA + 1)
+ if epsilon != &#39;δ&#39;+1 {
+ log.Fatal(&#34;inconsistent casing for Greek&#34;)
+ }</pre>
+
+<p>
+<em>Updating</em>:
+Most source code will be unaffected by this because the type inference from
+<code>:=</code> initializers introduces the new type silently, and it propagates
+from there.
+Some code may get type errors that a trivial conversion will resolve.
+</p>
+
+<h3 id="error">The error type</h3>
+
+<p>
+Go 1 introduces a new built-in type, <code>error</code>, which has the following definition:
+</p>
+
+<pre>
+ type error interface {
+ Error() string
+ }
+</pre>
+
+<p>
+Since the consequences of this type are all in the package library,
+it is discussed <a href="#errors">below</a>.
+</p>
+
+<h3 id="delete">Deleting from maps</h3>
+
+<p>
+In the old language, to delete the entry with key <code>k</code> from map <code>m</code>, one wrote the statement,
+</p>
+
+<pre>
+ m[k] = value, false
+</pre>
+
+<p>
+This syntax was a peculiar special case, the only two-to-one assignment.
+It required passing a value (usually ignored) that is evaluated but discarded,
+plus a boolean that was nearly always the constant <code>false</code>.
+It did the job but was odd and a point of contention.
+</p>
+
+<p>
+In Go 1, that syntax has gone; instead there is a new built-in
+function, <code>delete</code>. The call
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/delete\(m, k\)/`}}
+--> delete(m, k)</pre>
+
+<p>
+will delete the map entry retrieved by the expression <code>m[k]</code>.
+There is no return value. Deleting a non-existent entry is a no-op.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will convert expressions of the form <code>m[k] = value,
+false</code> into <code>delete(m, k)</code> when it is clear that
+the ignored value can be safely discarded from the program and
+<code>false</code> refers to the predefined boolean constant.
+The fix tool
+will flag other uses of the syntax for inspection by the programmer.
+</p>
+
+<h3 id="iteration">Iterating in maps</h3>
+
+<p>
+The old language specification did not define the order of iteration for maps,
+and in practice it differed across hardware platforms.
+This caused tests that iterated over maps to be fragile and non-portable, with the
+unpleasant property that a test might always pass on one machine but break on another.
+</p>
+
+<p>
+In Go 1, the order in which elements are visited when iterating
+over a map using a <code>for</code> <code>range</code> statement
+is defined to be unpredictable, even if the same loop is run multiple
+times with the same map.
+Code should not assume that the elements are visited in any particular order.
+</p>
+
+<p>
+This change means that code that depends on iteration order is very likely to break early and be fixed long before it becomes a problem.
+Just as important, it allows the map implementation to ensure better map balancing even when programs are using range loops to select an element from a map.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/Sunday/` `/^ }/`}}
+--> m := map[string]int{&#34;Sunday&#34;: 0, &#34;Monday&#34;: 1}
+ for name, value := range m {
+ <span class="comment">// This loop should not assume Sunday will be visited first.</span>
+ f(name, value)
+ }</pre>
+
+<p>
+<em>Updating</em>:
+This is one change where tools cannot help. Most existing code
+will be unaffected, but some programs may break or misbehave; we
+recommend manual checking of all range statements over maps to
+verify they do not depend on iteration order. There were a few such
+examples in the standard repository; they have been fixed.
+Note that it was already incorrect to depend on the iteration order, which
+was unspecified. This change codifies the unpredictability.
+</p>
+
+<h3 id="multiple_assignment">Multiple assignment</h3>
+
+<p>
+The language specification has long guaranteed that in assignments
+the right-hand-side expressions are all evaluated before any left-hand-side expressions are assigned.
+To guarantee predictable behavior,
+Go 1 refines the specification further.
+</p>
+
+<p>
+If the left-hand side of the assignment
+statement contains expressions that require evaluation, such as
+function calls or array indexing operations, these will all be done
+using the usual left-to-right rule before any variables are assigned
+their value. Once everything is evaluated, the actual assignments
+proceed in left-to-right order.
+</p>
+
+<p>
+These examples illustrate the behavior.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/sa :=/` `/then sc.0. = 2/`}}
+--> sa := []int{1, 2, 3}
+ i := 0
+ i, sa[i] = 1, 2 <span class="comment">// sets i = 1, sa[0] = 2</span>
+
+ sb := []int{1, 2, 3}
+ j := 0
+ sb[j], j = 2, 1 <span class="comment">// sets sb[0] = 2, j = 1</span>
+
+ sc := []int{1, 2, 3}
+ sc[0], sc[0] = 1, 2 <span class="comment">// sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)</span></pre>
+
+<p>
+<em>Updating</em>:
+This is one change where tools cannot help, but breakage is unlikely.
+No code in the standard repository was broken by this change, and code
+that depended on the previous unspecified behavior was already incorrect.
+</p>
+
+<h3 id="shadowing">Returns and shadowed variables</h3>
+
+<p>
+A common mistake is to use <code>return</code> (without arguments) after an assignment to a variable that has the same name as a result variable but is not the same variable.
+This situation is called <em>shadowing</em>: the result variable has been shadowed by another variable with the same name declared in an inner scope.
+</p>
+
+<p>
+In functions with named return values,
+the Go 1 compilers disallow return statements without arguments if any of the named return values is shadowed at the point of the return statement.
+(It isn't part of the specification, because this is one area we are still exploring;
+the situation is analogous to the compilers rejecting functions that do not end with an explicit return statement.)
+</p>
+
+<p>
+This function implicitly returns a shadowed return value and will be rejected by the compiler:
+</p>
+
+<pre>
+ func Bug() (i, j, k int) {
+ for i = 0; i &lt; 5; i++ {
+ for j := 0; j &lt; 5; j++ { // Redeclares j.
+ k += i*j
+ if k > 100 {
+ return // Rejected: j is shadowed here.
+ }
+ }
+ }
+ return // OK: j is not shadowed here.
+ }
+</pre>
+
+<p>
+<em>Updating</em>:
+Code that shadows return values in this way will be rejected by the compiler and will need to be fixed by hand.
+The few cases that arose in the standard repository were mostly bugs.
+</p>
+
+<h3 id="unexported">Copying structs with unexported fields</h3>
+
+<p>
+The old language did not allow a package to make a copy of a struct value containing unexported fields belonging to a different package.
+There was, however, a required exception for a method receiver;
+also, the implementations of <code>copy</code> and <code>append</code> have never honored the restriction.
+</p>
+
+<p>
+Go 1 will allow packages to copy struct values containing unexported fields from other packages.
+Besides resolving the inconsistency,
+this change admits a new kind of API: a package can return an opaque value without resorting to a pointer or interface.
+The new implementations of <code>time.Time</code> and
+<code>reflect.Value</code> are examples of types taking advantage of this new property.
+</p>
+
+<p>
+As an example, if package <code>p</code> includes the definitions,
+</p>
+
+<pre>
+ type Struct struct {
+ Public int
+ secret int
+ }
+ func NewStruct(a int) Struct { // Note: not a pointer.
+ return Struct{a, f(a)}
+ }
+ func (s Struct) String() string {
+ return fmt.Sprintf("{%d (secret %d)}", s.Public, s.secret)
+ }
+</pre>
+
+<p>
+a package that imports <code>p</code> can assign and copy values of type
+<code>p.Struct</code> at will.
+Behind the scenes the unexported fields will be assigned and copied just
+as if they were exported,
+but the client code will never be aware of them. The code
+</p>
+
+<pre>
+ import "p"
+
+ myStruct := p.NewStruct(23)
+ copyOfMyStruct := myStruct
+ fmt.Println(myStruct, copyOfMyStruct)
+</pre>
+
+<p>
+will show that the secret field of the struct has been copied to the new value.
+</p>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="equality">Equality</h3>
+
+<p>
+Before Go 1, the language did not define equality on struct and array values.
+This meant,
+among other things, that structs and arrays could not be used as map keys.
+On the other hand, Go did define equality on function and map values.
+Function equality was problematic in the presence of closures
+(when are two closures equal?)
+while map equality compared pointers, not the maps' content, which was usually
+not what the user would want.
+</p>
+
+<p>
+Go 1 addressed these issues.
+First, structs and arrays can be compared for equality and inequality
+(<code>==</code> and <code>!=</code>),
+and therefore be used as map keys,
+provided they are composed from elements for which equality is also defined,
+using element-wise comparison.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/type Day struct/` `/Printf/`}}
+--> type Day struct {
+ long string
+ short string
+ }
+ Christmas := Day{&#34;Christmas&#34;, &#34;XMas&#34;}
+ Thanksgiving := Day{&#34;Thanksgiving&#34;, &#34;Turkey&#34;}
+ holiday := map[Day]bool{
+ Christmas: true,
+ Thanksgiving: true,
+ }
+ fmt.Printf(&#34;Christmas is a holiday: %t\n&#34;, holiday[Christmas])</pre>
+
+<p>
+Second, Go 1 removes the definition of equality for function values,
+except for comparison with <code>nil</code>.
+Finally, map equality is gone too, also except for comparison with <code>nil</code>.
+</p>
+
+<p>
+Note that equality is still undefined for slices, for which the
+calculation is in general infeasible. Also note that the ordered
+comparison operators (<code>&lt;</code> <code>&lt;=</code>
+<code>&gt;</code> <code>&gt;=</code>) are still undefined for
+structs and arrays.
+
+<p>
+<em>Updating</em>:
+Struct and array equality is a new feature, so existing code needs no changes.
+Existing code that depends on function or map equality will be
+rejected by the compiler and will need to be fixed by hand.
+Few programs will be affected, but the fix may require some
+redesign.
+</p>
+
+<h2 id="packages">The package hierarchy</h2>
+
+<p>
+Go 1 addresses many deficiencies in the old standard library and
+cleans up a number of packages, making them more internally consistent
+and portable.
+</p>
+
+<p>
+This section describes how the packages have been rearranged in Go 1.
+Some have moved, some have been renamed, some have been deleted.
+New packages are described in later sections.
+</p>
+
+<h3 id="hierarchy">The package hierarchy</h3>
+
+<p>
+Go 1 has a rearranged package hierarchy that groups related items
+into subdirectories. For instance, <code>utf8</code> and
+<code>utf16</code> now occupy subdirectories of <code>unicode</code>.
+Also, <a href="#subrepo">some packages</a> have moved into
+subrepositories of
+<a href="http://code.google.com/p/go"><code>code.google.com/p/go</code></a>
+while <a href="#deleted">others</a> have been deleted outright.
+</p>
+
+<table class="codetable" frame="border" summary="Moved packages">
+<colgroup align="left" width="60%"></colgroup>
+<colgroup align="left" width="40%"></colgroup>
+<tr>
+<th align="left">Old path</th>
+<th align="left">New path</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>asn1</td> <td>encoding/asn1</td></tr>
+<tr><td>csv</td> <td>encoding/csv</td></tr>
+<tr><td>gob</td> <td>encoding/gob</td></tr>
+<tr><td>json</td> <td>encoding/json</td></tr>
+<tr><td>xml</td> <td>encoding/xml</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>exp/template/html</td> <td>html/template</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>big</td> <td>math/big</td></tr>
+<tr><td>cmath</td> <td>math/cmplx</td></tr>
+<tr><td>rand</td> <td>math/rand</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>http</td> <td>net/http</td></tr>
+<tr><td>http/cgi</td> <td>net/http/cgi</td></tr>
+<tr><td>http/fcgi</td> <td>net/http/fcgi</td></tr>
+<tr><td>http/httptest</td> <td>net/http/httptest</td></tr>
+<tr><td>http/pprof</td> <td>net/http/pprof</td></tr>
+<tr><td>mail</td> <td>net/mail</td></tr>
+<tr><td>rpc</td> <td>net/rpc</td></tr>
+<tr><td>rpc/jsonrpc</td> <td>net/rpc/jsonrpc</td></tr>
+<tr><td>smtp</td> <td>net/smtp</td></tr>
+<tr><td>url</td> <td>net/url</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>exec</td> <td>os/exec</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>scanner</td> <td>text/scanner</td></tr>
+<tr><td>tabwriter</td> <td>text/tabwriter</td></tr>
+<tr><td>template</td> <td>text/template</td></tr>
+<tr><td>template/parse</td> <td>text/template/parse</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>utf8</td> <td>unicode/utf8</td></tr>
+<tr><td>utf16</td> <td>unicode/utf16</td></tr>
+</table>
+
+<p>
+Note that the package names for the old <code>cmath</code> and
+<code>exp/template/html</code> packages have changed to <code>cmplx</code>
+and <code>template</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update all imports and package renames for packages that
+remain inside the standard repository. Programs that import packages
+that are no longer in the standard repository will need to be edited
+by hand.
+</p>
+
+<h3 id="exp">The package tree exp</h3>
+
+<p>
+Because they are not standardized, the packages under the <code>exp</code> directory will not be available in the
+standard Go 1 release distributions, although they will be available in source code form
+in <a href="http://code.google.com/p/go/">the repository</a> for
+developers who wish to use them.
+</p>
+
+<p>
+Several packages have moved under <code>exp</code> at the time of Go 1's release:
+</p>
+
+<ul>
+<li><code>ebnf</code></li>
+<li><code>html</code><sup>&#8224;</sup></li>
+<li><code>go/types</code></li>
+</ul>
+
+<p>
+(<sup>&#8224;</sup>The <code>EscapeString</code> and <code>UnescapeString</code> types remain
+in package <code>html</code>.)
+</p>
+
+<p>
+All these packages are available under the same names, with the prefix <code>exp/</code>: <code>exp/ebnf</code> etc.
+</p>
+
+<p>
+Also, the <code>utf8.String</code> type has been moved to its own package, <code>exp/utf8string</code>.
+</p>
+
+<p>
+Finally, the <code>gotype</code> command now resides in <code>exp/gotype</code>, while
+<code>ebnflint</code> is now in <code>exp/ebnflint</code>.
+If they are installed, they now reside in <code>$GOROOT/bin/tool</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses packages in <code>exp</code> will need to be updated by hand,
+or else compiled from an installation that has <code>exp</code> available.
+The <code>go</code> <code>fix</code> tool or the compiler will complain about such uses.
+</p>
+
+<h3 id="old">The package tree old</h3>
+
+<p>
+Because they are deprecated, the packages under the <code>old</code> directory will not be available in the
+standard Go 1 release distributions, although they will be available in source code form for
+developers who wish to use them.
+</p>
+
+<p>
+The packages in their new locations are:
+</p>
+
+<ul>
+<li><code>old/netchan</code></li>
+<li><code>old/regexp</code></li>
+<li><code>old/template</code></li>
+</ul>
+
+<p>
+<em>Updating</em>:
+Code that uses packages now in <code>old</code> will need to be updated by hand,
+or else compiled from an installation that has <code>old</code> available.
+The <code>go</code> <code>fix</code> tool will warn about such uses.
+</p>
+
+<h3 id="deleted">Deleted packages</h3>
+
+<p>
+Go 1 deletes several packages outright:
+</p>
+
+<ul>
+<li><code>container/vector</code></li>
+<li><code>exp/datafmt</code></li>
+<li><code>go/typechecker</code></li>
+<li><code>try</code></li>
+</ul>
+
+<p>
+and also the command <code>gotry</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses <code>container/vector</code> should be updated to use
+slices directly. See
+<a href="http://code.google.com/p/go-wiki/wiki/SliceTricks">the Go
+Language Community Wiki</a> for some suggestions.
+Code that uses the other packages (there should be almost zero) will need to be rethought.
+</p>
+
+<h3 id="subrepo">Packages moving to subrepositories</h3>
+
+<p>
+Go 1 has moved a number of packages into other repositories, usually sub-repositories of
+<a href="http://code.google.com/p/go/">the main Go repository</a>.
+This table lists the old and new import paths:
+
+<table class="codetable" frame="border" summary="Sub-repositories">
+<colgroup align="left" width="40%"></colgroup>
+<colgroup align="left" width="60%"></colgroup>
+<tr>
+<th align="left">Old</th>
+<th align="left">New</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>crypto/bcrypt</td> <td>code.google.com/p/go.crypto/bcrypt</tr>
+<tr><td>crypto/blowfish</td> <td>code.google.com/p/go.crypto/blowfish</tr>
+<tr><td>crypto/cast5</td> <td>code.google.com/p/go.crypto/cast5</tr>
+<tr><td>crypto/md4</td> <td>code.google.com/p/go.crypto/md4</tr>
+<tr><td>crypto/ocsp</td> <td>code.google.com/p/go.crypto/ocsp</tr>
+<tr><td>crypto/openpgp</td> <td>code.google.com/p/go.crypto/openpgp</tr>
+<tr><td>crypto/openpgp/armor</td> <td>code.google.com/p/go.crypto/openpgp/armor</tr>
+<tr><td>crypto/openpgp/elgamal</td> <td>code.google.com/p/go.crypto/openpgp/elgamal</tr>
+<tr><td>crypto/openpgp/errors</td> <td>code.google.com/p/go.crypto/openpgp/errors</tr>
+<tr><td>crypto/openpgp/packet</td> <td>code.google.com/p/go.crypto/openpgp/packet</tr>
+<tr><td>crypto/openpgp/s2k</td> <td>code.google.com/p/go.crypto/openpgp/s2k</tr>
+<tr><td>crypto/ripemd160</td> <td>code.google.com/p/go.crypto/ripemd160</tr>
+<tr><td>crypto/twofish</td> <td>code.google.com/p/go.crypto/twofish</tr>
+<tr><td>crypto/xtea</td> <td>code.google.com/p/go.crypto/xtea</tr>
+<tr><td>exp/ssh</td> <td>code.google.com/p/go.crypto/ssh</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image/bmp</td> <td>code.google.com/p/go.image/bmp</tr>
+<tr><td>image/tiff</td> <td>code.google.com/p/go.image/tiff</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>net/dict</td> <td>code.google.com/p/go.net/dict</tr>
+<tr><td>net/websocket</td> <td>code.google.com/p/go.net/websocket</tr>
+<tr><td>exp/spdy</td> <td>code.google.com/p/go.net/spdy</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>encoding/git85</td> <td>code.google.com/p/go.codereview/git85</tr>
+<tr><td>patch</td> <td>code.google.com/p/go.codereview/patch</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>exp/wingui</td> <td>code.google.com/p/gowingui</tr>
+</table>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update imports of these packages to use the new import paths.
+Installations that depend on these packages will need to install them using
+a <code>go get</code> command.
+</p>
+
+<h2 id="major">Major changes to the library</h2>
+
+<p>
+This section describes significant changes to the core libraries, the ones that
+affect the most programs.
+</p>
+
+<h3 id="errors">The error type and errors package</h3>
+
+<p>
+The placement of <code>os.Error</code> in package <code>os</code> is mostly historical: errors first came up when implementing package <code>os</code>, and they seemed system-related at the time.
+Since then it has become clear that errors are more fundamental than the operating system. For example, it would be nice to use <code>Errors</code> in packages that <code>os</code> depends on, like <code>syscall</code>.
+Also, having <code>Error</code> in <code>os</code> introduces many dependencies on <code>os</code> that would otherwise not exist.
+</p>
+
+<p>
+Go 1 solves these problems by introducing a built-in <code>error</code> interface type and a separate <code>errors</code> package (analogous to <code>bytes</code> and <code>strings</code>) that contains utility functions.
+It replaces <code>os.NewError</code> with
+<a href="/pkg/errors/#New"><code>errors.New</code></a>,
+giving errors a more central place in the environment.
+</p>
+
+<p>
+So the widely-used <code>String</code> method does not cause accidental satisfaction
+of the <code>error</code> interface, the <code>error</code> interface uses instead
+the name <code>Error</code> for that method:
+</p>
+
+<pre>
+ type error interface {
+ Error() string
+ }
+</pre>
+
+<p>
+The <code>fmt</code> library automatically invokes <code>Error</code>, as it already
+does for <code>String</code>, for easy printing of error values.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/START ERROR EXAMPLE/` `/END ERROR EXAMPLE/`}}
+-->type SyntaxError struct {
+ File string
+ Line int
+ Message string
+}
+
+func (se *SyntaxError) Error() string {
+ return fmt.Sprintf(&#34;%s:%d: %s&#34;, se.File, se.Line, se.Message)
+}</pre>
+
+<p>
+All standard packages have been updated to use the new interface; the old <code>os.Error</code> is gone.
+</p>
+
+<p>
+A new package, <a href="/pkg/errors/"><code>errors</code></a>, contains the function
+</p>
+
+<pre>
+func New(text string) error
+</pre>
+
+<p>
+to turn a string into an error. It replaces the old <code>os.NewError</code>.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/ErrSyntax/`}}
+--> var ErrSyntax = errors.New(&#34;syntax error&#34;)</pre>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
+Code that defines error types with a <code>String</code> method will need to be updated
+by hand to rename the methods to <code>Error</code>.
+</p>
+
+<h3 id="errno">System call errors</h3>
+
+<p>
+The old <code>syscall</code> package, which predated <code>os.Error</code>
+(and just about everything else),
+returned errors as <code>int</code> values.
+In turn, the <code>os</code> package forwarded many of these errors, such
+as <code>EINVAL</code>, but using a different set of errors on each platform.
+This behavior was unpleasant and unportable.
+</p>
+
+<p>
+In Go 1, the
+<a href="/pkg/syscall/"><code>syscall</code></a>
+package instead returns an <code>error</code> for system call errors.
+On Unix, the implementation is done by a
+<a href="/pkg/syscall/#Errno"><code>syscall.Errno</code></a> type
+that satisfies <code>error</code> and replaces the old <code>os.Errno</code>.
+</p>
+
+<p>
+The changes affecting <code>os.EINVAL</code> and relatives are
+described <a href="#os">elsewhere</a>.
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
+Regardless, most code should use the <code>os</code> package
+rather than <code>syscall</code> and so will be unaffected.
+</p>
+
+<h3 id="time">Time</h3>
+
+<p>
+Time is always a challenge to support well in a programming language.
+The old Go <code>time</code> package had <code>int64</code> units, no
+real type safety,
+and no distinction between absolute times and durations.
+</p>
+
+<p>
+One of the most sweeping changes in the Go 1 library is therefore a
+complete redesign of the
+<a href="/pkg/time/"><code>time</code></a> package.
+Instead of an integer number of nanoseconds as an <code>int64</code>,
+and a separate <code>*time.Time</code> type to deal with human
+units such as hours and years,
+there are now two fundamental types:
+<a href="/pkg/time/#Time"><code>time.Time</code></a>
+(a value, so the <code>*</code> is gone), which represents a moment in time;
+and <a href="/pkg/time/#Duration"><code>time.Duration</code></a>,
+which represents an interval.
+Both have nanosecond resolution.
+A <code>Time</code> can represent any time into the ancient
+past and remote future, while a <code>Duration</code> can
+span plus or minus only about 290 years.
+There are methods on these types, plus a number of helpful
+predefined constant durations such as <code>time.Second</code>.
+</p>
+
+<p>
+Among the new methods are things like
+<a href="/pkg/time/#Time.Add"><code>Time.Add</code></a>,
+which adds a <code>Duration</code> to a <code>Time</code>, and
+<a href="/pkg/time/#Time.Sub"><code>Time.Sub</code></a>,
+which subtracts two <code>Times</code> to yield a <code>Duration</code>.
+</p>
+
+<p>
+The most important semantic change is that the Unix epoch (Jan 1, 1970) is now
+relevant only for those functions and methods that mention Unix:
+<a href="/pkg/time/#Unix"><code>time.Unix</code></a>
+and the <a href="/pkg/time/#Time.Unix"><code>Unix</code></a>
+and <a href="/pkg/time/#Time.UnixNano"><code>UnixNano</code></a> methods
+of the <code>Time</code> type.
+In particular,
+<a href="/pkg/time/#Now"><code>time.Now</code></a>
+returns a <code>time.Time</code> value rather than, in the old
+API, an integer nanosecond count since the Unix epoch.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/sleepUntil/` `/^}/`}}
+--><span class="comment">// sleepUntil sleeps until the specified time. It returns immediately if it&#39;s too late.</span>
+func sleepUntil(wakeup time.Time) {
+ now := time.Now() <span class="comment">// A Time.</span>
+ if !wakeup.After(now) {
+ return
+ }
+ delta := wakeup.Sub(now) <span class="comment">// A Duration.</span>
+ fmt.Printf(&#34;Sleeping for %.3fs\n&#34;, delta.Seconds())
+ time.Sleep(delta)
+}</pre>
+
+<p>
+The new types, methods, and constants have been propagated through
+all the standard packages that use time, such as <code>os</code> and
+its representation of file time stamps.
+</p>
+
+<p>
+<em>Updating</em>:
+The <code>go</code> <code>fix</code> tool will update many uses of the old <code>time</code> package to use the new
+types and methods, although it does not replace values such as <code>1e9</code>
+representing nanoseconds per second.
+Also, because of type changes in some of the values that arise,
+some of the expressions rewritten by the fix tool may require
+further hand editing; in such cases the rewrite will include
+the correct function or method for the old functionality, but
+may have the wrong type or require further analysis.
+</p>
+
+<h2 id="minor">Minor changes to the library</h2>
+
+<p>
+This section describes smaller changes, such as those to less commonly
+used packages or that affect
+few programs beyond the need to run <code>go</code> <code>fix</code>.
+This category includes packages that are new in Go 1.
+Collectively they improve portability, regularize behavior, and
+make the interfaces more modern and Go-like.
+</p>
+
+<h3 id="archive_zip">The archive/zip package</h3>
+
+<p>
+In Go 1, <a href="/pkg/archive/zip/#Writer"><code>*zip.Writer</code></a> no
+longer has a <code>Write</code> method. Its presence was a mistake.
+</p>
+
+<p>
+<em>Updating</em>:
+What little code is affected will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="bufio">The bufio package</h3>
+
+<p>
+In Go 1, <a href="/pkg/bufio/#NewReaderSize"><code>bufio.NewReaderSize</code></a>
+and
+<a href="/pkg/bufio/#NewWriterSize"><code>bufio.NewWriterSize</code></a>
+functions no longer return an error for invalid sizes.
+If the argument size is too small or invalid, it is adjusted.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update calls that assign the error to _.
+Calls that aren't fixed will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="compress">The compress/flate, compress/gzip and compress/zlib packages</h3>
+
+<p>
+In Go 1, the <code>NewWriterXxx</code> functions in
+<a href="/pkg/compress/flate"><code>compress/flate</code></a>,
+<a href="/pkg/compress/gzip"><code>compress/gzip</code></a> and
+<a href="/pkg/compress/zlib"><code>compress/zlib</code></a>
+all return <code>(*Writer, error)</code> if they take a compression level,
+and <code>*Writer</code> otherwise. Package <code>gzip</code>'s
+<code>Compressor</code> and <code>Decompressor</code> types have been renamed
+to <code>Writer</code> and <code>Reader</code>. Package <code>flate</code>'s
+<code>WrongValueError</code> type has been removed.
+</p>
+
+<p>
+<em>Updating</em>
+Running <code>go</code> <code>fix</code> will update old names and calls that assign the error to _.
+Calls that aren't fixed will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="crypto_aes_des">The crypto/aes and crypto/des packages</h3>
+
+<p>
+In Go 1, the <code>Reset</code> method has been removed. Go does not guarantee
+that memory is not copied and therefore this method was misleading.
+</p>
+
+<p>
+The cipher-specific types <code>*aes.Cipher</code>, <code>*des.Cipher</code>,
+and <code>*des.TripleDESCipher</code> have been removed in favor of
+<code>cipher.Block</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Remove the calls to Reset. Replace uses of the specific cipher types with
+cipher.Block.
+</p>
+
+<h3 id="crypto_elliptic">The crypto/elliptic package</h3>
+
+<p>
+In Go 1, <a href="/pkg/crypto/elliptic/#Curve"><code>elliptic.Curve</code></a>
+has been made an interface to permit alternative implementations. The curve
+parameters have been moved to the
+<a href="/pkg/crypto/elliptic/#CurveParams"><code>elliptic.CurveParams</code></a>
+structure.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing users of <code>*elliptic.Curve</code> will need to change to
+simply <code>elliptic.Curve</code>. Calls to <code>Marshal</code>,
+<code>Unmarshal</code> and <code>GenerateKey</code> are now functions
+in <code>crypto/elliptic</code> that take an <code>elliptic.Curve</code>
+as their first argument.
+</p>
+
+<h3 id="crypto_hmac">The crypto/hmac package</h3>
+
+<p>
+In Go 1, the hash-specific functions, such as <code>hmac.NewMD5</code>, have
+been removed from <code>crypto/hmac</code>. Instead, <code>hmac.New</code> takes
+a function that returns a <code>hash.Hash</code>, such as <code>md5.New</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will perform the needed changes.
+</p>
+
+<h3 id="crypto_x509">The crypto/x509 package</h3>
+
+<p>
+In Go 1, the
+<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
+and
+<a href="/pkg/crypto/x509/#CreateCRL"><code>CreateCRL</code></a>
+functions in <code>crypto/x509</code> have been altered to take an
+<code>interface{}</code> where they previously took a <code>*rsa.PublicKey</code>
+or <code>*rsa.PrivateKey</code>. This will allow other public key algorithms
+to be implemented in the future.
+</p>
+
+<p>
+<em>Updating</em>:
+No changes will be needed.
+</p>
+
+<h3 id="encoding_binary">The encoding/binary package</h3>
+
+<p>
+In Go 1, the <code>binary.TotalSize</code> function has been replaced by
+<a href="/pkg/encoding/binary/#Size"><code>Size</code></a>,
+which takes an <code>interface{}</code> argument rather than
+a <code>reflect.Value</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+What little code is affected will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="encoding_xml">The encoding/xml package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/encoding/xml/"><code>xml</code></a> package
+has been brought closer in design to the other marshaling packages such
+as <a href="/pkg/encoding/gob/"><code>encoding/gob</code></a>.
+</p>
+
+<p>
+The old <code>Parser</code> type is renamed
+<a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> and has a new
+<a href="/pkg/encoding/xml/#Decoder.Decode"><code>Decode</code></a> method. An
+<a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a> type was also introduced.
+</p>
+
+<p>
+The functions <a href="/pkg/encoding/xml/#Marshal"><code>Marshal</code></a>
+and <a href="/pkg/encoding/xml/#Unmarshal"><code>Unmarshal</code></a>
+work with <code>[]byte</code> values now. To work with streams,
+use the new <a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a>
+and <a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> types.
+</p>
+
+<p>
+When marshaling or unmarshaling values, the format of supported flags in
+field tags has changed to be closer to the
+<a href="/pkg/encoding/json"><code>json</code></a> package
+(<code>`xml:"name,flag"`</code>). The matching done between field tags, field
+names, and the XML attribute and element names is now case-sensitive.
+The <code>XMLName</code> field tag, if present, must also match the name
+of the XML element being marshaled.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update most uses of the package except for some calls to
+<code>Unmarshal</code>. Special care must be taken with field tags,
+since the fix tool will not update them and if not fixed by hand they will
+misbehave silently in some cases. For example, the old
+<code>"attr"</code> is now written <code>",attr"</code> while plain
+<code>"attr"</code> remains valid but with a different meaning.
+</p>
+
+<h3 id="expvar">The expvar package</h3>
+
+<p>
+In Go 1, the <code>RemoveAll</code> function has been removed.
+The <code>Iter</code> function and Iter method on <code>*Map</code> have
+been replaced by
+<a href="/pkg/expvar/#Do"><code>Do</code></a>
+and
+<a href="/pkg/expvar/#Map.Do"><code>(*Map).Do</code></a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Most code using <code>expvar</code> will not need changing. The rare code that used
+<code>Iter</code> can be updated to pass a closure to <code>Do</code> to achieve the same effect.
+</p>
+
+<h3 id="flag">The flag package</h3>
+
+<p>
+In Go 1, the interface <a href="/pkg/flag/#Value"><code>flag.Value</code></a> has changed slightly.
+The <code>Set</code> method now returns an <code>error</code> instead of
+a <code>bool</code> to indicate success or failure.
+</p>
+
+<p>
+There is also a new kind of flag, <code>Duration</code>, to support argument
+values specifying time intervals.
+Values for such flags must be given units, just as <code>time.Duration</code>
+formats them: <code>10s</code>, <code>1h30m</code>, etc.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/timeout/`}}
+-->var timeout = flag.Duration(&#34;timeout&#34;, 30*time.Second, &#34;how long to wait for completion&#34;)</pre>
+
+<p>
+<em>Updating</em>:
+Programs that implement their own flags will need minor manual fixes to update their
+<code>Set</code> methods.
+The <code>Duration</code> flag is new and affects no existing code.
+</p>
+
+
+<h3 id="go">The go/* packages</h3>
+
+<p>
+Several packages under <code>go</code> have slightly revised APIs.
+</p>
+
+<p>
+A concrete <code>Mode</code> type was introduced for configuration mode flags
+in the packages
+<a href="/pkg/go/scanner/"><code>go/scanner</code></a>,
+<a href="/pkg/go/parser/"><code>go/parser</code></a>,
+<a href="/pkg/go/printer/"><code>go/printer</code></a>, and
+<a href="/pkg/go/doc/"><code>go/doc</code></a>.
+</p>
+
+<p>
+The modes <code>AllowIllegalChars</code> and <code>InsertSemis</code> have been removed
+from the <a href="/pkg/go/scanner/"><code>go/scanner</code></a> package. They were mostly
+useful for scanning text other then Go source files. Instead, the
+<a href="/pkg/text/scanner/"><code>text/scanner</code></a> package should be used
+for that purpose.
+</p>
+
+<p>
+The <a href="/pkg/go/scanner/#ErrorHandler"><code>ErrorHandler</code></a> provided
+to the scanner's <a href="/pkg/go/scanner/#Scanner.Init"><code>Init</code></a> method is
+now simply a function rather than an interface. The <code>ErrorVector</code> type has
+been removed in favor of the (existing) <a href="/pkg/go/scanner/#ErrorList"><code>ErrorList</code></a>
+type, and the <code>ErrorVector</code> methods have been migrated. Instead of embedding
+an <code>ErrorVector</code> in a client of the scanner, now a client should maintain
+an <code>ErrorList</code>.
+</p>
+
+<p>
+The set of parse functions provided by the <a href="/pkg/go/parser/"><code>go/parser</code></a>
+package has been reduced to the primary parse function
+<a href="/pkg/go/parser/#ParseFile"><code>ParseFile</code></a>, and a couple of
+convenience functions <a href="/pkg/go/parser/#ParseDir"><code>ParseDir</code></a>
+and <a href="/pkg/go/parser/#ParseExpr"><code>ParseExpr</code></a>.
+</p>
+
+<p>
+The <a href="/pkg/go/printer/"><code>go/printer</code></a> package supports an additional
+configuration mode <a href="/pkg/go/printer/#Mode"><code>SourcePos</code></a>;
+if set, the printer will emit <code>//line</code> comments such that the generated
+output contains the original source code position information. The new type
+<a href="/pkg/go/printer/#CommentedNode"><code>CommentedNode</code></a> can be
+used to provide comments associated with an arbitrary
+<a href="/pkg/go/ast/#Node"><code>ast.Node</code></a> (until now only
+<a href="/pkg/go/ast/#File"><code>ast.File</code></a> carried comment information).
+</p>
+
+<p>
+The type names of the <a href="/pkg/go/doc/"><code>go/doc</code></a> package have been
+streamlined by removing the <code>Doc</code> suffix: <code>PackageDoc</code>
+is now <code>Package</code>, <code>ValueDoc</code> is <code>Value</code>, etc.
+Also, all types now consistently have a <code>Name</code> field (or <code>Names</code>,
+in the case of type <code>Value</code>) and <code>Type.Factories</code> has become
+<code>Type.Funcs</code>.
+Instead of calling <code>doc.NewPackageDoc(pkg, importpath)</code>,
+documentation for a package is created with:
+</p>
+
+<pre>
+ doc.New(pkg, importpath, mode)
+</pre>
+
+<p>
+where the new <code>mode</code> parameter specifies the operation mode:
+if set to <a href="/pkg/go/doc/#AllDecls"><code>AllDecls</code></a>, all declarations
+(not just exported ones) are considered.
+The function <code>NewFileDoc</code> was removed, and the function
+<code>CommentText</code> has become the method
+<a href="/pkg/go/ast/#Text"><code>Text</code></a> of
+<a href="/pkg/go/ast/#CommentGroup"><code>ast.CommentGroup</code></a>.
+</p>
+
+<p>
+In package <a href="/pkg/go/token/"><code>go/token</code></a>, the
+<a href="/pkg/go/token/#FileSet"><code>token.FileSet</code></a> method <code>Files</code>
+(which originally returned a channel of <code>*token.File</code>s) has been replaced
+with the iterator <a href="/pkg/go/token/#FileSet.Iterate"><code>Iterate</code></a> that
+accepts a function argument instead.
+</p>
+
+<p>
+In package <a href="/pkg/go/build/"><code>go/build</code></a>, the API
+has been nearly completely replaced.
+The package still computes Go package information
+but it does not run the build: the <code>Cmd</code> and <code>Script</code>
+types are gone.
+(To build code, use the new
+<a href="/cmd/go/"><code>go</code></a> command instead.)
+The <code>DirInfo</code> type is now named
+<a href="/pkg/go/build/#Package"><code>Package</code></a>.
+<code>FindTree</code> and <code>ScanDir</code> are replaced by
+<a href="/pkg/go/build/#Import"><code>Import</code></a>
+and
+<a href="/pkg/go/build/#ImportDir"><code>ImportDir</code></a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses packages in <code>go</code> will have to be updated by hand; the
+compiler will reject incorrect uses. Templates used in conjunction with any of the
+<code>go/doc</code> types may need manual fixes; the renamed fields will lead
+to run-time errors.
+</p>
+
+<h3 id="hash">The hash package</h3>
+
+<p>
+In Go 1, the definition of <a href="/pkg/hash/#Hash"><code>hash.Hash</code></a> includes
+a new method, <code>BlockSize</code>. This new method is used primarily in the
+cryptographic libraries.
+</p>
+
+<p>
+The <code>Sum</code> method of the
+<a href="/pkg/hash/#Hash"><code>hash.Hash</code></a> interface now takes a
+<code>[]byte</code> argument, to which the hash value will be appended.
+The previous behavior can be recreated by adding a <code>nil</code> argument to the call.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing implementations of <code>hash.Hash</code> will need to add a
+<code>BlockSize</code> method. Hashes that process the input one byte at
+a time can implement <code>BlockSize</code> to return 1.
+Running <code>go</code> <code>fix</code> will update calls to the <code>Sum</code> methods of the various
+implementations of <code>hash.Hash</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Since the package's functionality is new, no updating is necessary.
+</p>
+
+<h3 id="http">The http package</h3>
+
+<p>
+In Go 1 the <a href="/pkg/net/http/"><code>http</code></a> package is refactored,
+putting some of the utilities into a
+<a href="/pkg/net/http/httputil/"><code>httputil</code></a> subdirectory.
+These pieces are only rarely needed by HTTP clients.
+The affected items are:
+</p>
+
+<ul>
+<li>ClientConn</li>
+<li>DumpRequest</li>
+<li>DumpRequestOut</li>
+<li>DumpResponse</li>
+<li>NewChunkedReader</li>
+<li>NewChunkedWriter</li>
+<li>NewClientConn</li>
+<li>NewProxyClientConn</li>
+<li>NewServerConn</li>
+<li>NewSingleHostReverseProxy</li>
+<li>ReverseProxy</li>
+<li>ServerConn</li>
+</ul>
+
+<p>
+The <code>Request.RawURL</code> field has been removed; it was a
+historical artifact.
+</p>
+
+<p>
+The <code>Handle</code> and <code>HandleFunc</code>
+functions, and the similarly-named methods of <code>ServeMux</code>,
+now panic if an attempt is made to register the same pattern twice.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update the few programs that are affected except for
+uses of <code>RawURL</code>, which must be fixed by hand.
+</p>
+
+<h3 id="image">The image package</h3>
+
+<p>
+The <a href="/pkg/image/"><code>image</code></a> package has had a number of
+minor changes, rearrangements and renamings.
+</p>
+
+<p>
+Most of the color handling code has been moved into its own package,
+<a href="/pkg/image/color/"><code>image/color</code></a>.
+For the elements that moved, a symmetry arises; for instance,
+each pixel of an
+<a href="/pkg/image/#RGBA"><code>image.RGBA</code></a>
+is a
+<a href="/pkg/image/color/#RGBA"><code>color.RGBA</code></a>.
+</p>
+
+<p>
+The old <code>image/ycbcr</code> package has been folded, with some
+renamings, into the
+<a href="/pkg/image/"><code>image</code></a>
+and
+<a href="/pkg/image/color/"><code>image/color</code></a>
+packages.
+</p>
+
+<p>
+The old <code>image.ColorImage</code> type is still in the <code>image</code>
+package but has been renamed
+<a href="/pkg/image/#Uniform"><code>image.Uniform</code></a>,
+while <code>image.Tiled</code> has been removed.
+</p>
+
+<p>
+This table lists the renamings.
+</p>
+
+<table class="codetable" frame="border" summary="image renames">
+<colgroup align="left" width="50%"></colgroup>
+<colgroup align="left" width="50%"></colgroup>
+<tr>
+<th align="left">Old</th>
+<th align="left">New</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.Color</td> <td>color.Color</td></tr>
+<tr><td>image.ColorModel</td> <td>color.Model</td></tr>
+<tr><td>image.ColorModelFunc</td> <td>color.ModelFunc</td></tr>
+<tr><td>image.PalettedColorModel</td> <td>color.Palette</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.RGBAColor</td> <td>color.RGBA</td></tr>
+<tr><td>image.RGBA64Color</td> <td>color.RGBA64</td></tr>
+<tr><td>image.NRGBAColor</td> <td>color.NRGBA</td></tr>
+<tr><td>image.NRGBA64Color</td> <td>color.NRGBA64</td></tr>
+<tr><td>image.AlphaColor</td> <td>color.Alpha</td></tr>
+<tr><td>image.Alpha16Color</td> <td>color.Alpha16</td></tr>
+<tr><td>image.GrayColor</td> <td>color.Gray</td></tr>
+<tr><td>image.Gray16Color</td> <td>color.Gray16</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.RGBAColorModel</td> <td>color.RGBAModel</td></tr>
+<tr><td>image.RGBA64ColorModel</td> <td>color.RGBA64Model</td></tr>
+<tr><td>image.NRGBAColorModel</td> <td>color.NRGBAModel</td></tr>
+<tr><td>image.NRGBA64ColorModel</td> <td>color.NRGBA64Model</td></tr>
+<tr><td>image.AlphaColorModel</td> <td>color.AlphaModel</td></tr>
+<tr><td>image.Alpha16ColorModel</td> <td>color.Alpha16Model</td></tr>
+<tr><td>image.GrayColorModel</td> <td>color.GrayModel</td></tr>
+<tr><td>image.Gray16ColorModel</td> <td>color.Gray16Model</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>ycbcr.RGBToYCbCr</td> <td>color.RGBToYCbCr</td></tr>
+<tr><td>ycbcr.YCbCrToRGB</td> <td>color.YCbCrToRGB</td></tr>
+<tr><td>ycbcr.YCbCrColorModel</td> <td>color.YCbCrModel</td></tr>
+<tr><td>ycbcr.YCbCrColor</td> <td>color.YCbCr</td></tr>
+<tr><td>ycbcr.YCbCr</td> <td>image.YCbCr</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>ycbcr.SubsampleRatio444</td> <td>image.YCbCrSubsampleRatio444</td></tr>
+<tr><td>ycbcr.SubsampleRatio422</td> <td>image.YCbCrSubsampleRatio422</td></tr>
+<tr><td>ycbcr.SubsampleRatio420</td> <td>image.YCbCrSubsampleRatio420</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.ColorImage</td> <td>image.Uniform</td></tr>
+</table>
+
+<p>
+The image package's <code>New</code> functions
+(<a href="/pkg/image/#NewRGBA"><code>NewRGBA</code></a>,
+<a href="/pkg/image/#NewRGBA64"><code>NewRGBA64</code></a>, etc.)
+take an <a href="/pkg/image/#Rectangle"><code>image.Rectangle</code></a> as an argument
+instead of four integers.
+</p>
+
+<p>
+Finally, there are new predefined <code>color.Color</code> variables
+<a href="/pkg/image/color/#Black"><code>color.Black</code></a>,
+<a href="/pkg/image/color/#White"><code>color.White</code></a>,
+<a href="/pkg/image/color/#Opaque"><code>color.Opaque</code></a>
+and
+<a href="/pkg/image/color/#Transparent"><code>color.Transparent</code></a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
+</p>
+
+<h3 id="log_syslog">The log/syslog package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/log/syslog/#NewLogger"><code>syslog.NewLogger</code></a>
+function returns an error as well as a <code>log.Logger</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+What little code is affected will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="mime">The mime package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/mime/#FormatMediaType"><code>FormatMediaType</code></a> function
+of the <code>mime</code> package has been simplified to make it
+consistent with
+<a href="/pkg/mime/#ParseMediaType"><code>ParseMediaType</code></a>.
+It now takes <code>"text/html"</code> rather than <code>"text"</code> and <code>"html"</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+What little code is affected will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="net">The net package</h3>
+
+<p>
+In Go 1, the various <code>SetTimeout</code>,
+<code>SetReadTimeout</code>, and <code>SetWriteTimeout</code> methods
+have been replaced with
+<a href="/pkg/net/#IPConn.SetDeadline"><code>SetDeadline</code></a>,
+<a href="/pkg/net/#IPConn.SetReadDeadline"><code>SetReadDeadline</code></a>, and
+<a href="/pkg/net/#IPConn.SetWriteDeadline"><code>SetWriteDeadline</code></a>,
+respectively. Rather than taking a timeout value in nanoseconds that
+apply to any activity on the connection, the new methods set an
+absolute deadline (as a <code>time.Time</code> value) after which
+reads and writes will time out and no longer block.
+</p>
+
+<p>
+There are also new functions
+<a href="/pkg/net/#DialTimeout"><code>net.DialTimeout</code></a>
+to simplify timing out dialing a network address and
+<a href="/pkg/net/#ListenMulticastUDP"><code>net.ListenMulticastUDP</code></a>
+to allow multicast UDP to listen concurrently across multiple listeners.
+The <code>net.ListenMulticastUDP</code> function replaces the old
+<code>JoinGroup</code> and <code>LeaveGroup</code> methods.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses the old methods will fail to compile and must be updated by hand.
+The semantic change makes it difficult for the fix tool to update automatically.
+</p>
+
+<h3 id="os">The os package</h3>
+
+<p>
+The <code>Time</code> function has been removed; callers should use
+the <a href="/pkg/time/#Time"><code>Time</code></a> type from the
+<code>time</code> package.
+</p>
+
+<p>
+The <code>Exec</code> function has been removed; callers should use
+<code>Exec</code> from the <code>syscall</code> package, where available.
+</p>
+
+<p>
+The <code>ShellExpand</code> function has been renamed to <a
+href="/pkg/os/#ExpandEnv"><code>ExpandEnv</code></a>.
+</p>
+
+<p>
+The <a href="/pkg/os/#NewFile"><code>NewFile</code></a> function
+now takes a <code>uintptr</code> fd, instead of an <code>int</code>.
+The <a href="/pkg/os/#File.Fd"><code>Fd</code></a> method on files now
+also returns a <code>uintptr</code>.
+</p>
+
+<p>
+There are no longer error constants such as <code>EINVAL</code>
+in the <code>os</code> package, since the set of values varied with
+the underlying operating system. There are new portable functions like
+<a href="/pkg/os/#IsPermission"><code>IsPermission</code></a>
+to test common error properties, plus a few new error values
+with more Go-like names, such as
+<a href="/pkg/os/#ErrPermission"><code>ErrPermission</code></a>
+and
+<a href="/pkg/os/#ErrNoEnv"><code>ErrNoEnv</code></a>.
+</p>
+
+<p>
+The <code>Getenverror</code> function has been removed. To distinguish
+between a non-existent environment variable and an empty string,
+use <a href="/pkg/os/#Environ"><code>os.Environ</code></a> or
+<a href="/pkg/syscall/#Getenv"><code>syscall.Getenv</code></a>.
+</p>
+
+
+<p>
+The <a href="/pkg/os/#Process.Wait"><code>Process.Wait</code></a> method has
+dropped its option argument and the associated constants are gone
+from the package.
+Also, the function <code>Wait</code> is gone; only the method of
+the <code>Process</code> type persists.
+</p>
+
+<p>
+The <code>Waitmsg</code> type returned by
+<a href="/pkg/os/#Process.Wait"><code>Process.Wait</code></a>
+has been replaced with a more portable
+<a href="/pkg/os/#ProcessState"><code>ProcessState</code></a>
+type with accessor methods to recover information about the
+process.
+Because of changes to <code>Wait</code>, the <code>ProcessState</code>
+value always describes an exited process.
+Portability concerns simplified the interface in other ways, but the values returned by the
+<a href="/pkg/os/#ProcessState.Sys"><code>ProcessState.Sys</code></a> and
+<a href="/pkg/os/#ProcessState.SysUsage"><code>ProcessState.SysUsage</code></a>
+methods can be type-asserted to underlying system-specific data structures such as
+<a href="/pkg/syscall/#WaitStatus"><code>syscall.WaitStatus</code></a> and
+<a href="/pkg/syscall/#Rusage"><code>syscall.Rusage</code></a> on Unix.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will drop a zero argument to <code>Process.Wait</code>.
+All other changes will be caught by the compiler and must be updated by hand.
+</p>
+
+<h4 id="os_fileinfo">The os.FileInfo type</h4>
+
+<p>
+Go 1 redefines the <a href="/pkg/os/#FileInfo"><code>os.FileInfo</code></a> type,
+changing it from a struct to an interface:
+</p>
+
+<pre>
+ type FileInfo interface {
+ Name() string // base name of the file
+ Size() int64 // length in bytes
+ Mode() FileMode // file mode bits
+ ModTime() time.Time // modification time
+ IsDir() bool // abbreviation for Mode().IsDir()
+ Sys() interface{} // underlying data source (can return nil)
+ }
+</pre>
+
+<p>
+The file mode information has been moved into a subtype called
+<a href="/pkg/os/#FileMode"><code>os.FileMode</code></a>,
+a simple integer type with <code>IsDir</code>, <code>Perm</code>, and <code>String</code>
+methods.
+</p>
+
+<p>
+The system-specific details of file modes and properties such as (on Unix)
+i-number have been removed from <code>FileInfo</code> altogether.
+Instead, each operating system's <code>os</code> package provides an
+implementation of the <code>FileInfo</code> interface, which
+has a <code>Sys</code> method that returns the
+system-specific representation of file metadata.
+For instance, to discover the i-number of a file on a Unix system, unpack
+the <code>FileInfo</code> like this:
+</p>
+
+<pre>
+ fi, err := os.Stat("hello.go")
+ if err != nil {
+ log.Fatal(err)
+ }
+ // Check that it's a Unix file.
+ unixStat, ok := fi.Sys().(*syscall.Stat_t)
+ if !ok {
+ log.Fatal("hello.go: not a Unix file")
+ }
+ fmt.Printf("file i-number: %d\n", unixStat.Ino)
+</pre>
+
+<p>
+Assuming (which is unwise) that <code>"hello.go"</code> is a Unix file,
+the i-number expression could be contracted to
+</p>
+
+<pre>
+ fi.Sys().(*syscall.Stat_t).Ino
+</pre>
+
+<p>
+The vast majority of uses of <code>FileInfo</code> need only the methods
+of the standard interface.
+</p>
+
+<p>
+The <code>os</code> package no longer contains wrappers for the POSIX errors
+such as <code>ENOENT</code>.
+For the few programs that need to verify particular error conditions, there are
+now the boolean functions
+<a href="/pkg/os/#IsExist"><code>IsExist</code></a>,
+<a href="/pkg/os/#IsNotExist"><code>IsNotExist</code></a>
+and
+<a href="/pkg/os/#IsPermission"><code>IsPermission</code></a>.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/os\.Open/` `/}/`}}
+--> f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
+ if os.IsExist(err) {
+ log.Printf(&#34;%s already exists&#34;, name)
+ }</pre>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update code that uses the old equivalent of the current <code>os.FileInfo</code>
+and <code>os.FileMode</code> API.
+Code that needs system-specific file details will need to be updated by hand.
+Code that uses the old POSIX error values from the <code>os</code> package
+will fail to compile and will also need to be updated by hand.
+</p>
+
+<h3 id="os_signal">The os/signal package</h3>
+
+<p>
+The <code>os/signal</code> package in Go 1 replaces the
+<code>Incoming</code> function, which returned a channel
+that received all incoming signals,
+with the selective <code>Notify</code> function, which asks
+for delivery of specific signals on an existing channel.
+</p>
+
+<p>
+<em>Updating</em>:
+Code must be updated by hand.
+A literal translation of
+</p>
+<pre>
+c := signal.Incoming()
+</pre>
+<p>
+is
+</p>
+<pre>
+c := make(chan os.Signal)
+signal.Notify(c) // ask for all signals
+</pre>
+<p>
+but most code should list the specific signals it wants to handle instead:
+</p>
+<pre>
+c := make(chan os.Signal)
+signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT)
+</pre>
+
+<h3 id="path_filepath">The path/filepath package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/path/filepath/#Walk"><code>Walk</code></a> function of the
+<code>path/filepath</code> package
+has been changed to take a function value of type
+<a href="/pkg/path/filepath/#WalkFunc"><code>WalkFunc</code></a>
+instead of a <code>Visitor</code> interface value.
+<code>WalkFunc</code> unifies the handling of both files and directories.
+</p>
+
+<pre>
+ type WalkFunc func(path string, info os.FileInfo, err error) error
+</pre>
+
+<p>
+The <code>WalkFunc</code> function will be called even for files or directories that could not be opened;
+in such cases the error argument will describe the failure.
+If a directory's contents are to be skipped,
+the function should return the value <a href="/pkg/path/filepath/#variables"><code>filepath.SkipDir</code></a>
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/STARTWALK/` `/ENDWALK/`}}
+--> markFn := func(path string, info os.FileInfo, err error) error {
+ if path == &#34;pictures&#34; { <span class="comment">// Will skip walking of directory pictures and its contents.</span>
+ return filepath.SkipDir
+ }
+ if err != nil {
+ return err
+ }
+ log.Println(path)
+ return nil
+ }
+ err := filepath.Walk(&#34;.&#34;, markFn)
+ if err != nil {
+ log.Fatal(err)
+ }</pre>
+
+<p>
+<em>Updating</em>:
+The change simplifies most code but has subtle consequences, so affected programs
+will need to be updated by hand.
+The compiler will catch code using the old interface.
+</p>
+
+<h3 id="regexp">The regexp package</h3>
+
+<p>
+The <a href="/pkg/regexp/"><code>regexp</code></a> package has been rewritten.
+It has the same interface but the specification of the regular expressions
+it supports has changed from the old "egrep" form to that of
+<a href="http://code.google.com/p/re2/">RE2</a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses the package should have its regular expressions checked by hand.
+</p>
+
+<h3 id="runtime">The runtime package</h3>
+
+<p>
+In Go 1, much of the API exported by package
+<code>runtime</code> has been removed in favor of
+functionality provided by other packages.
+Code using the <code>runtime.Type</code> interface
+or its specific concrete type implementations should
+now use package <a href="/pkg/reflect/"><code>reflect</code></a>.
+Code using <code>runtime.Semacquire</code> or <code>runtime.Semrelease</code>
+should use channels or the abstractions in package <a href="/pkg/sync/"><code>sync</code></a>.
+The <code>runtime.Alloc</code>, <code>runtime.Free</code>,
+and <code>runtime.Lookup</code> functions, an unsafe API created for
+debugging the memory allocator, have no replacement.
+</p>
+
+<p>
+Before, <code>runtime.MemStats</code> was a global variable holding
+statistics about memory allocation, and calls to <code>runtime.UpdateMemStats</code>
+ensured that it was up to date.
+In Go 1, <code>runtime.MemStats</code> is a struct type, and code should use
+<a href="/pkg/runtime/#ReadMemStats"><code>runtime.ReadMemStats</code></a>
+to obtain the current statistics.
+</p>
+
+<p>
+The package adds a new function,
+<a href="/pkg/runtime/#NumCPU"><code>runtime.NumCPU</code></a>, that returns the number of CPUs available
+for parallel execution, as reported by the operating system kernel.
+Its value can inform the setting of <code>GOMAXPROCS</code>.
+The <code>runtime.Cgocalls</code> and <code>runtime.Goroutines</code> functions
+have been renamed to <code>runtime.NumCgoCall</code> and <code>runtime.NumGoroutine</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update code for the function renamings.
+Other code will need to be updated by hand.
+</p>
+
+<h3 id="strconv">The strconv package</h3>
+
+<p>
+In Go 1, the
+<a href="/pkg/strconv/"><code>strconv</code></a>
+package has been significantly reworked to make it more Go-like and less C-like,
+although <code>Atoi</code> lives on (it's similar to
+<code>int(ParseInt(x, 10, 0))</code>, as does
+<code>Itoa(x)</code> (<code>FormatInt(int64(x), 10)</code>).
+There are also new variants of some of the functions that append to byte slices rather than
+return strings, to allow control over allocation.
+</p>
+
+<p>
+This table summarizes the renamings; see the
+<a href="/pkg/strconv/">package documentation</a>
+for full details.
+</p>
+
+<table class="codetable" frame="border" summary="strconv renames">
+<colgroup align="left" width="50%"></colgroup>
+<colgroup align="left" width="50%"></colgroup>
+<tr>
+<th align="left">Old call</th>
+<th align="left">New call</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atob(x)</td> <td>ParseBool(x)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atof32(x)</td> <td>ParseFloat(x, 32)§</td></tr>
+<tr><td>Atof64(x)</td> <td>ParseFloat(x, 64)</td></tr>
+<tr><td>AtofN(x, n)</td> <td>ParseFloat(x, n)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atoi(x)</td> <td>Atoi(x)</td></tr>
+<tr><td>Atoi(x)</td> <td>ParseInt(x, 10, 0)§</td></tr>
+<tr><td>Atoi64(x)</td> <td>ParseInt(x, 10, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atoui(x)</td> <td>ParseUint(x, 10, 0)§</td></tr>
+<tr><td>Atoui64(x)</td> <td>ParseUint(x, 10, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Btoi64(x, b)</td> <td>ParseInt(x, b, 64)</td></tr>
+<tr><td>Btoui64(x, b)</td> <td>ParseUint(x, b, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Btoa(x)</td> <td>FormatBool(x)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Ftoa32(x, f, p)</td> <td>FormatFloat(float64(x), f, p, 32)</td></tr>
+<tr><td>Ftoa64(x, f, p)</td> <td>FormatFloat(x, f, p, 64)</td></tr>
+<tr><td>FtoaN(x, f, p, n)</td> <td>FormatFloat(x, f, p, n)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Itoa(x)</td> <td>Itoa(x)</td></tr>
+<tr><td>Itoa(x)</td> <td>FormatInt(int64(x), 10)</td></tr>
+<tr><td>Itoa64(x)</td> <td>FormatInt(x, 10)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Itob(x, b)</td> <td>FormatInt(int64(x), b)</td></tr>
+<tr><td>Itob64(x, b)</td> <td>FormatInt(x, b)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Uitoa(x)</td> <td>FormatUint(uint64(x), 10)</td></tr>
+<tr><td>Uitoa64(x)</td> <td>FormatUint(x, 10)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Uitob(x, b)</td> <td>FormatUint(uint64(x), b)</td></tr>
+<tr><td>Uitob64(x, b)</td> <td>FormatUint(x, b)</td></tr>
+</table>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
+<br>
+§ <code>Atoi</code> persists but <code>Atoui</code> and <code>Atof32</code> do not, so
+they may require
+a cast that must be added by hand; the <code>go</code> <code>fix</code> tool will warn about it.
+</p>
+
+
+<h3 id="templates">The template packages</h3>
+
+<p>
+The <code>template</code> and <code>exp/template/html</code> packages have moved to
+<a href="/pkg/text/template/"><code>text/template</code></a> and
+<a href="/pkg/html/template/"><code>html/template</code></a>.
+More significant, the interface to these packages has been simplified.
+The template language is the same, but the concept of "template set" is gone
+and the functions and methods of the packages have changed accordingly,
+often by elimination.
+</p>
+
+<p>
+Instead of sets, a <code>Template</code> object
+may contain multiple named template definitions,
+in effect constructing
+name spaces for template invocation.
+A template can invoke any other template associated with it, but only those
+templates associated with it.
+The simplest way to associate templates is to parse them together, something
+made easier with the new structure of the packages.
+</p>
+
+<p>
+<em>Updating</em>:
+The imports will be updated by fix tool.
+Single-template uses will be otherwise be largely unaffected.
+Code that uses multiple templates in concert will need to be updated by hand.
+The <a href="/pkg/text/template/#examples">examples</a> in
+the documentation for <code>text/template</code> can provide guidance.
+</p>
+
+<h3 id="testing">The testing package</h3>
+
+<p>
+The testing package has a type, <code>B</code>, passed as an argument to benchmark functions.
+In Go 1, <code>B</code> has new methods, analogous to those of <code>T</code>, enabling
+logging and failure reporting.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/func.*Benchmark/` `/^}/`}}
+-->func BenchmarkSprintf(b *testing.B) {
+ <span class="comment">// Verify correctness before running benchmark.</span>
+ b.StopTimer()
+ got := fmt.Sprintf(&#34;%x&#34;, 23)
+ const expect = &#34;17&#34;
+ if expect != got {
+ b.Fatalf(&#34;expected %q; got %q&#34;, expect, got)
+ }
+ b.StartTimer()
+ for i := 0; i &lt; b.N; i++ {
+ fmt.Sprintf(&#34;%x&#34;, 23)
+ }
+}</pre>
+
+<p>
+<em>Updating</em>:
+Existing code is unaffected, although benchmarks that use <code>println</code>
+or <code>panic</code> should be updated to use the new methods.
+</p>
+
+<h3 id="testing_script">The testing/script package</h3>
+
+<p>
+The testing/script package has been deleted. It was a dreg.
+</p>
+
+<p>
+<em>Updating</em>:
+No code is likely to be affected.
+</p>
+
+<h3 id="unsafe">The unsafe package</h3>
+
+<p>
+In Go 1, the functions
+<code>unsafe.Typeof</code>, <code>unsafe.Reflect</code>,
+<code>unsafe.Unreflect</code>, <code>unsafe.New</code>, and
+<code>unsafe.NewArray</code> have been removed;
+they duplicated safer functionality provided by
+package <a href="/pkg/reflect/"><code>reflect</code></a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code using these functions must be rewritten to use
+package <a href="/pkg/reflect/"><code>reflect</code></a>.
+The changes to <a href="http://code.google.com/p/go/source/detail?r=2646dc956207">encoding/gob</a> and the <a href="http://code.google.com/p/goprotobuf/source/detail?r=5340ad310031">protocol buffer library</a>
+may be helpful as examples.
+</p>
+
+<h3 id="url">The url package</h3>
+
+<p>
+In Go 1 several fields from the <a href="/pkg/net/url/#URL"><code>url.URL</code></a> type
+were removed or replaced.
+</p>
+
+<p>
+The <a href="/pkg/net/url/#URL.String"><code>String</code></a> method now
+predictably rebuilds an encoded URL string using all of <code>URL</code>'s
+fields as necessary. The resulting string will also no longer have
+passwords escaped.
+</p>
+
+<p>
+The <code>Raw</code> field has been removed. In most cases the <code>String</code>
+method may be used in its place.
+</p>
+
+<p>
+The old <code>RawUserinfo</code> field is replaced by the <code>User</code>
+field, of type <a href="/pkg/net/url/#Userinfo"><code>*net.Userinfo</code></a>.
+Values of this type may be created using the new <a href="/pkg/net/url/#User"><code>net.User</code></a>
+and <a href="/pkg/net/url/#UserPassword"><code>net.UserPassword</code></a>
+functions. The <code>EscapeUserinfo</code> and <code>UnescapeUserinfo</code>
+functions are also gone.
+</p>
+
+<p>
+The <code>RawAuthority</code> field has been removed. The same information is
+available in the <code>Host</code> and <code>User</code> fields.
+</p>
+
+<p>
+The <code>RawPath</code> field and the <code>EncodedPath</code> method have
+been removed. The path information in rooted URLs (with a slash following the
+schema) is now available only in decoded form in the <code>Path</code> field.
+Occasionally, the encoded data may be required to obtain information that
+was lost in the decoding process. These cases must be handled by accessing
+the data the URL was built from.
+</p>
+
+<p>
+URLs with non-rooted paths, such as <code>"mailto:dev@golang.org?subject=Hi"</code>,
+are also handled differently. The <code>OpaquePath</code> boolean field has been
+removed and a new <code>Opaque</code> string field introduced to hold the encoded
+path for such URLs. In Go 1, the cited URL parses as:
+</p>
+
+<pre>
+ URL{
+ Scheme: "mailto",
+ Opaque: "dev@golang.org",
+ RawQuery: "subject=Hi",
+ }
+</pre>
+
+<p>
+A new <a href="/pkg/net/url/#URL.RequestURI"><code>RequestURI</code></a> method was
+added to <code>URL</code>.
+</p>
+
+<p>
+The <code>ParseWithReference</code> function has been renamed to <code>ParseWithFragment</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses the old fields will fail to compile and must be updated by hand.
+The semantic changes make it difficult for the fix tool to update automatically.
+</p>
+
+<h2 id="cmd_go">The go command</h2>
+
+<p>
+Go 1 introduces the <a href="/cmd/go/">go command</a>, a tool for fetching,
+building, and installing Go packages and commands. The <code>go</code> command
+does away with makefiles, instead using Go source code to find dependencies and
+determine build conditions. Most existing Go programs will no longer require
+makefiles to be built.
+</p>
+
+<p>
+See <a href="/doc/code.html">How to Write Go Code</a> for a primer on the
+<code>go</code> command and the <a href="/cmd/go/">go command documentation</a>
+for the full details.
+</p>
+
+<p>
+<em>Updating</em>:
+Projects that depend on the Go project's old makefile-based build
+infrastructure (<code>Make.pkg</code>, <code>Make.cmd</code>, and so on) should
+switch to using the <code>go</code> command for building Go code and, if
+necessary, rewrite their makefiles to perform any auxiliary build tasks.
+</p>
+
+<h2 id="cmd_cgo">The cgo command</h2>
+
+<p>
+In Go 1, the <a href="/cmd/cgo">cgo command</a>
+uses a different <code>_cgo_export.h</code>
+file, which is generated for packages containing <code>//export</code> lines.
+The <code>_cgo_export.h</code> file now begins with the C preamble comment,
+so that exported function definitions can use types defined there.
+This has the effect of compiling the preamble multiple times, so a
+package using <code>//export</code> must not put function definitions
+or variable initializations in the C preamble.
+</p>
+
+<h2 id="releases">Packaged releases</h2>
+
+<p>
+One of the most significant changes associated with Go 1 is the availability
+of prepackaged, downloadable distributions.
+They are available for many combinations of architecture and operating system
+(including Windows) and the list will grow.
+Installation details are described on the
+<a href="/doc/install">Getting Started</a> page, while
+the distributions themselves are listed on the
+<a href="http://code.google.com/p/go/downloads/list">downloads page</a>.
+
+
+</div>
+
+<div id="footer">
+Build version go1.0.1.<br>
+Except as <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+the content of this page is licensed under the
+Creative Commons Attribution 3.0 License,
+and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
+<a href="/doc/tos.html">Terms of Service</a> |
+<a href="http://www.google.com/intl/en/privacy/privacy-policy.html">Privacy Policy</a>
+</div>
+
+<script type="text/javascript">
+(function() {
+ var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
+ ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
+ var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
+})();
+</script>
+</body>
+<script type="text/javascript">
+ (function() {
+ var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
+ po.src = 'https://apis.google.com/js/plusone.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
+ })();
+</script>
+</html>
+
diff --git a/libgo/go/exp/html/testdata/webkit/pending-spec-changes.dat b/libgo/go/exp/html/testdata/webkit/pending-spec-changes.dat
index e00ee85d3bf..5a9208465f5 100644
--- a/libgo/go/exp/html/testdata/webkit/pending-spec-changes.dat
+++ b/libgo/go/exp/html/testdata/webkit/pending-spec-changes.dat
@@ -26,3 +26,27 @@
| <svg svg>
| "foo"
| "bar"
+
+#data
+<table><tr><td><svg><desc><td></desc><circle>
+#errors
+7: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+30: A table cell was implicitly closed, but there were open elements.
+26: Unclosed element “desc”.
+20: Unclosed element “svg”.
+37: Stray end tag “desc”.
+45: End of file seen and there were open elements.
+45: Unclosed element “circle”.
+7: Unclosed element “table”.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg desc>
+| <td>
+| <circle>
diff --git a/libgo/go/exp/html/testdata/webkit/tables01.dat b/libgo/go/exp/html/testdata/webkit/tables01.dat
index 88ef1fe2ee9..c4b47e48a81 100644
--- a/libgo/go/exp/html/testdata/webkit/tables01.dat
+++ b/libgo/go/exp/html/testdata/webkit/tables01.dat
@@ -195,3 +195,18 @@
| <td>
| <button>
| <td>
+
+#data
+<table><tr><td><svg><desc><td>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg desc>
+| <td>
diff --git a/libgo/go/exp/html/testdata/webkit/tests16.dat b/libgo/go/exp/html/testdata/webkit/tests16.dat
index 937dba9f42f..c8ef66f0e6e 100644
--- a/libgo/go/exp/html/testdata/webkit/tests16.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests16.dat
@@ -1076,6 +1076,28 @@ Line: 1 Col: 64 Unexpected end tag (textarea).
| "</textarea>"
#data
+<!doctype html><textarea>&lt;</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<"
+
+#data
+<!doctype html><textarea>a&lt;b</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "a<b"
+
+#data
<!doctype html><iframe><!--<iframe></iframe>--></iframe>
#errors
Line: 1 Col: 56 Unexpected end tag (iframe).
diff --git a/libgo/go/exp/html/testdata/webkit/tests19.dat b/libgo/go/exp/html/testdata/webkit/tests19.dat
index 06222f5b9db..0d62f5a5b02 100644
--- a/libgo/go/exp/html/testdata/webkit/tests19.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests19.dat
@@ -173,7 +173,7 @@
| <ruby>
| <div>
| <span>
-| <rp>
+| <rp>
#data
<!doctype html><ruby><div><p><rp>
@@ -186,7 +186,7 @@
| <ruby>
| <div>
| <p>
-| <rp>
+| <rp>
#data
<!doctype html><ruby><p><rt>
@@ -211,7 +211,7 @@
| <ruby>
| <div>
| <span>
-| <rt>
+| <rt>
#data
<!doctype html><ruby><div><p><rt>
@@ -224,7 +224,7 @@
| <ruby>
| <div>
| <p>
-| <rt>
+| <rt>
#data
<!doctype html><math/><foo>
@@ -1218,3 +1218,20 @@
| <plaintext>
| <a>
| "b"
+
+#data
+<!DOCTYPE html><div>a<a></div>b<p>c</p>d
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| "a"
+| <a>
+| <a>
+| "b"
+| <p>
+| "c"
+| "d"
diff --git a/libgo/go/exp/html/testdata/webkit/tests26.dat b/libgo/go/exp/html/testdata/webkit/tests26.dat
index da128e7794b..fae11ffdf96 100644
--- a/libgo/go/exp/html/testdata/webkit/tests26.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests26.dat
@@ -193,3 +193,121 @@
| <i>
| <nobr>
| "2"
+
+#data
+<p><code x</code></p>
+
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <code>
+| code=""
+| x<=""
+| <code>
+| code=""
+| x<=""
+| "
+"
+
+#data
+<!DOCTYPE html><svg><foreignObject><p><i></p>a
+#errors
+45: End tag “p” seen, but there were open elements.
+41: Unclosed element “i”.
+46: End of file seen and there were open elements.
+35: Unclosed element “foreignObject”.
+20: Unclosed element “svg”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><table><tr><td><svg><foreignObject><p><i></p>a
+#errors
+56: End tag “p” seen, but there were open elements.
+52: Unclosed element “i”.
+57: End of file seen and there were open elements.
+46: Unclosed element “foreignObject”.
+31: Unclosed element “svg”.
+22: Unclosed element “table”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><math><mtext><p><i></p>a
+#errors
+38: End tag “p” seen, but there were open elements.
+34: Unclosed element “i”.
+39: End of file in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mtext>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><table><tr><td><math><mtext><p><i></p>a
+#errors
+53: End tag “p” seen, but there were open elements.
+49: Unclosed element “i”.
+54: End of file in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <math math>
+| <math mtext>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><body><div><!/div>a
+#errors
+29: Bogus comment.
+34: End of file seen and there were open elements.
+26: Unclosed element “div”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <!-- /div -->
+| "a"
diff --git a/libgo/go/exp/html/testdata/webkit/tests_innerHTML_1.dat b/libgo/go/exp/html/testdata/webkit/tests_innerHTML_1.dat
index 052fac7d554..6c78661e0cb 100644
--- a/libgo/go/exp/html/testdata/webkit/tests_innerHTML_1.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests_innerHTML_1.dat
@@ -731,3 +731,11 @@ html
frameset
#document
| <frame>
+
+#data
+#errors
+#document-fragment
+html
+#document
+| <head>
+| <body>
diff --git a/libgo/go/exp/html/testdata/webkit/webkit01.dat b/libgo/go/exp/html/testdata/webkit/webkit01.dat
index 4101b216e18..9d425e99d5f 100644
--- a/libgo/go/exp/html/testdata/webkit/webkit01.dat
+++ b/libgo/go/exp/html/testdata/webkit/webkit01.dat
@@ -289,8 +289,8 @@ console.log("FOO<span>BAR</span>BAZ");
| <body>
| <ruby>
| <div>
-| <rp>
-| "xx"
+| <rp>
+| "xx"
#data
<html><body><ruby><div><rt>xx</rt></div></ruby></body></html>
@@ -301,8 +301,8 @@ console.log("FOO<span>BAR</span>BAZ");
| <body>
| <ruby>
| <div>
-| <rt>
-| "xx"
+| <rt>
+| "xx"
#data
<html><frameset><!--1--><noframes>A</noframes><!--2--></frameset><!--3--><noframes>B</noframes><!--4--></html><!--5--><noframes>C</noframes><!--6-->
@@ -560,7 +560,8 @@ console.log("FOO<span>BAR</span>BAZ");
| <td>
| <svg svg>
| <svg desc>
-| <svg circle>
+| <td>
+| <circle>
#data
<svg><tfoot></mi><td>
diff --git a/libgo/go/exp/html/testdata/webkit/webkit02.dat b/libgo/go/exp/html/testdata/webkit/webkit02.dat
index 2218f4298c5..905783d3cdf 100644
--- a/libgo/go/exp/html/testdata/webkit/webkit02.dat
+++ b/libgo/go/exp/html/testdata/webkit/webkit02.dat
@@ -102,3 +102,58 @@
| <body>
| <legend>
| "test"
+
+#data
+<table><input>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <input>
+| <table>
+
+#data
+<b><em><dcell><postfield><postfield><postfield><postfield><missing_glyph><missing_glyph><missing_glyph><missing_glyph><hkern><aside></b></em>
+#errors
+#document-fragment
+div
+#document
+| <b>
+| <em>
+| <dcell>
+| <postfield>
+| <postfield>
+| <postfield>
+| <postfield>
+| <missing_glyph>
+| <missing_glyph>
+| <missing_glyph>
+| <missing_glyph>
+| <hkern>
+| <aside>
+| <em>
+| <b>
+
+#data
+<isindex action="x">
+#errors
+#document-fragment
+table
+#document
+| <form>
+| action="x"
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| <hr>
+
+#data
+<option><XH<optgroup></optgroup>
+#errors
+#document-fragment
+select
+#document
+| <option>
diff --git a/libgo/go/exp/html/token.go b/libgo/go/exp/html/token.go
index b5e9c2d6ea3..517bd5d3ee8 100644
--- a/libgo/go/exp/html/token.go
+++ b/libgo/go/exp/html/token.go
@@ -6,13 +6,14 @@ package html
import (
"bytes"
+ "exp/html/atom"
"io"
"strconv"
"strings"
)
// A TokenType is the type of a Token.
-type TokenType int
+type TokenType uint32
const (
// ErrorToken means that an error occurred during tokenization.
@@ -65,11 +66,13 @@ type Attribute struct {
// A Token consists of a TokenType and some Data (tag name for start and end
// tags, content for text, comments and doctypes). A tag Token may also contain
// a slice of Attributes. Data is unescaped for all Tokens (it looks like "a<b"
-// rather than "a&lt;b").
+// rather than "a&lt;b"). For tag Tokens, DataAtom is the atom for Data, or
+// zero if Data is not a known tag name.
type Token struct {
- Type TokenType
- Data string
- Attr []Attribute
+ Type TokenType
+ DataAtom atom.Atom
+ Data string
+ Attr []Attribute
}
// tagString returns a string representation of a tag Token's Data and Attr.
@@ -149,6 +152,57 @@ type Tokenizer struct {
rawTag string
// textIsRaw is whether the current text token's data is not escaped.
textIsRaw bool
+ // convertNUL is whether NUL bytes in the current token's data should
+ // be converted into \ufffd replacement characters.
+ convertNUL bool
+ // allowCDATA is whether CDATA sections are allowed in the current context.
+ allowCDATA bool
+}
+
+// AllowCDATA sets whether or not the tokenizer recognizes <![CDATA[foo]]> as
+// the text "foo". The default value is false, which means to recognize it as
+// a bogus comment "<!-- [CDATA[foo]] -->" instead.
+//
+// Strictly speaking, an HTML5 compliant tokenizer should allow CDATA if and
+// only if tokenizing foreign content, such as MathML and SVG. However,
+// tracking foreign-contentness is difficult to do purely in the tokenizer,
+// as opposed to the parser, due to HTML integration points: an <svg> element
+// can contain a <foreignObject> that is foreign-to-SVG but not foreign-to-
+// HTML. For strict compliance with the HTML5 tokenization algorithm, it is the
+// responsibility of the user of a tokenizer to call AllowCDATA as appropriate.
+// In practice, if using the tokenizer without caring whether MathML or SVG
+// CDATA is text or comments, such as tokenizing HTML to find all the anchor
+// text, it is acceptable to ignore this responsibility.
+func (z *Tokenizer) AllowCDATA(allowCDATA bool) {
+ z.allowCDATA = allowCDATA
+}
+
+// NextIsNotRawText instructs the tokenizer that the next token should not be
+// considered as 'raw text'. Some elements, such as script and title elements,
+// normally require the next token after the opening tag to be 'raw text' that
+// has no child elements. For example, tokenizing "<title>a<b>c</b>d</title>"
+// yields a start tag token for "<title>", a text token for "a<b>c</b>d", and
+// an end tag token for "</title>". There are no distinct start tag or end tag
+// tokens for the "<b>" and "</b>".
+//
+// This tokenizer implementation will generally look for raw text at the right
+// times. Strictly speaking, an HTML5 compliant tokenizer should not look for
+// raw text if in foreign content: <title> generally needs raw text, but a
+// <title> inside an <svg> does not. Another example is that a <textarea>
+// generally needs raw text, but a <textarea> is not allowed as an immediate
+// child of a <select>; in normal parsing, a <textarea> implies </select>, but
+// one cannot close the implicit element when parsing a <select>'s InnerHTML.
+// Similarly to AllowCDATA, tracking the correct moment to override raw-text-
+// ness is difficult to do purely in the tokenizer, as opposed to the parser.
+// For strict compliance with the HTML5 tokenization algorithm, it is the
+// responsibility of the user of a tokenizer to call NextIsNotRawText as
+// appropriate. In practice, like AllowCDATA, it is acceptable to ignore this
+// responsibility for basic usage.
+//
+// Note that this 'raw text' concept is different from the one offered by the
+// Tokenizer.Raw method.
+func (z *Tokenizer) NextIsNotRawText() {
+ z.rawTag = ""
}
// Err returns the error associated with the most recent ErrorToken token.
@@ -233,6 +287,12 @@ func (z *Tokenizer) skipWhiteSpace() {
// readRawOrRCDATA reads until the next "</foo>", where "foo" is z.rawTag and
// is typically something like "script" or "textarea".
func (z *Tokenizer) readRawOrRCDATA() {
+ if z.rawTag == "script" {
+ z.readScript()
+ z.textIsRaw = true
+ z.rawTag = ""
+ return
+ }
loop:
for {
c := z.readByte()
@@ -249,27 +309,8 @@ loop:
if c != '/' {
continue loop
}
- for i := 0; i < len(z.rawTag); i++ {
- c = z.readByte()
- if z.err != nil {
- break loop
- }
- if c != z.rawTag[i] && c != z.rawTag[i]-('a'-'A') {
- continue loop
- }
- }
- c = z.readByte()
- if z.err != nil {
- break loop
- }
- switch c {
- case ' ', '\n', '\r', '\t', '\f', '/', '>':
- // The 3 is 2 for the leading "</" plus 1 for the trailing character c.
- z.raw.end -= 3 + len(z.rawTag)
+ if z.readRawEndTag() || z.err != nil {
break loop
- case '<':
- // Step back one, to catch "</foo</foo>".
- z.raw.end--
}
}
z.data.end = z.raw.end
@@ -278,6 +319,242 @@ loop:
z.rawTag = ""
}
+// readRawEndTag attempts to read a tag like "</foo>", where "foo" is z.rawTag.
+// If it succeeds, it backs up the input position to reconsume the tag and
+// returns true. Otherwise it returns false. The opening "</" has already been
+// consumed.
+func (z *Tokenizer) readRawEndTag() bool {
+ for i := 0; i < len(z.rawTag); i++ {
+ c := z.readByte()
+ if z.err != nil {
+ return false
+ }
+ if c != z.rawTag[i] && c != z.rawTag[i]-('a'-'A') {
+ z.raw.end--
+ return false
+ }
+ }
+ c := z.readByte()
+ if z.err != nil {
+ return false
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f', '/', '>':
+ // The 3 is 2 for the leading "</" plus 1 for the trailing character c.
+ z.raw.end -= 3 + len(z.rawTag)
+ return true
+ }
+ z.raw.end--
+ return false
+}
+
+// readScript reads until the next </script> tag, following the byzantine
+// rules for escaping/hiding the closing tag.
+func (z *Tokenizer) readScript() {
+ defer func() {
+ z.data.end = z.raw.end
+ }()
+ var c byte
+
+scriptData:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '<' {
+ goto scriptDataLessThanSign
+ }
+ goto scriptData
+
+scriptDataLessThanSign:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '/':
+ goto scriptDataEndTagOpen
+ case '!':
+ goto scriptDataEscapeStart
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEndTagOpen:
+ if z.readRawEndTag() || z.err != nil {
+ return
+ }
+ goto scriptData
+
+scriptDataEscapeStart:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '-' {
+ goto scriptDataEscapeStartDash
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEscapeStartDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '-' {
+ goto scriptDataEscapedDashDash
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEscaped:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataEscapedDash
+ case '<':
+ goto scriptDataEscapedLessThanSign
+ }
+ goto scriptDataEscaped
+
+scriptDataEscapedDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataEscapedDashDash
+ case '<':
+ goto scriptDataEscapedLessThanSign
+ }
+ goto scriptDataEscaped
+
+scriptDataEscapedDashDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataEscapedDashDash
+ case '<':
+ goto scriptDataEscapedLessThanSign
+ case '>':
+ goto scriptData
+ }
+ goto scriptDataEscaped
+
+scriptDataEscapedLessThanSign:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '/' {
+ goto scriptDataEscapedEndTagOpen
+ }
+ if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
+ goto scriptDataDoubleEscapeStart
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEscapedEndTagOpen:
+ if z.readRawEndTag() || z.err != nil {
+ return
+ }
+ goto scriptDataEscaped
+
+scriptDataDoubleEscapeStart:
+ z.raw.end--
+ for i := 0; i < len("script"); i++ {
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c != "script"[i] && c != "SCRIPT"[i] {
+ z.raw.end--
+ goto scriptDataEscaped
+ }
+ }
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f', '/', '>':
+ goto scriptDataDoubleEscaped
+ }
+ z.raw.end--
+ goto scriptDataEscaped
+
+scriptDataDoubleEscaped:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataDoubleEscapedDash
+ case '<':
+ goto scriptDataDoubleEscapedLessThanSign
+ }
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapedDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataDoubleEscapedDashDash
+ case '<':
+ goto scriptDataDoubleEscapedLessThanSign
+ }
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapedDashDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataDoubleEscapedDashDash
+ case '<':
+ goto scriptDataDoubleEscapedLessThanSign
+ case '>':
+ goto scriptData
+ }
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapedLessThanSign:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '/' {
+ goto scriptDataDoubleEscapeEnd
+ }
+ z.raw.end--
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapeEnd:
+ if z.readRawEndTag() {
+ z.raw.end += len("</script>")
+ goto scriptDataEscaped
+ }
+ if z.err != nil {
+ return
+ }
+ goto scriptDataDoubleEscaped
+}
+
// readComment reads the next comment token starting with "<!--". The opening
// "<!--" has already been consumed.
func (z *Tokenizer) readComment() {
@@ -341,8 +618,8 @@ func (z *Tokenizer) readUntilCloseAngle() {
}
// readMarkupDeclaration reads the next token starting with "<!". It might be
-// a "<!--comment-->", a "<!DOCTYPE foo>", or "<!a bogus comment". The opening
-// "<!" has already been consumed.
+// a "<!--comment-->", a "<!DOCTYPE foo>", a "<![CDATA[section]]>" or
+// "<!a bogus comment". The opening "<!" has already been consumed.
func (z *Tokenizer) readMarkupDeclaration() TokenType {
z.data.start = z.raw.end
var c [2]byte
@@ -358,27 +635,81 @@ func (z *Tokenizer) readMarkupDeclaration() TokenType {
return CommentToken
}
z.raw.end -= 2
+ if z.readDoctype() {
+ return DoctypeToken
+ }
+ if z.allowCDATA && z.readCDATA() {
+ z.convertNUL = true
+ return TextToken
+ }
+ // It's a bogus comment.
+ z.readUntilCloseAngle()
+ return CommentToken
+}
+
+// readDoctype attempts to read a doctype declaration and returns true if
+// successful. The opening "<!" has already been consumed.
+func (z *Tokenizer) readDoctype() bool {
const s = "DOCTYPE"
for i := 0; i < len(s); i++ {
c := z.readByte()
if z.err != nil {
z.data.end = z.raw.end
- return CommentToken
+ return false
}
if c != s[i] && c != s[i]+('a'-'A') {
// Back up to read the fragment of "DOCTYPE" again.
z.raw.end = z.data.start
- z.readUntilCloseAngle()
- return CommentToken
+ return false
}
}
if z.skipWhiteSpace(); z.err != nil {
z.data.start = z.raw.end
z.data.end = z.raw.end
- return DoctypeToken
+ return true
}
z.readUntilCloseAngle()
- return DoctypeToken
+ return true
+}
+
+// readCDATA attempts to read a CDATA section and returns true if
+// successful. The opening "<!" has already been consumed.
+func (z *Tokenizer) readCDATA() bool {
+ const s = "[CDATA["
+ for i := 0; i < len(s); i++ {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return false
+ }
+ if c != s[i] {
+ // Back up to read the fragment of "[CDATA[" again.
+ z.raw.end = z.data.start
+ return false
+ }
+ }
+ z.data.start = z.raw.end
+ brackets := 0
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return true
+ }
+ switch c {
+ case ']':
+ brackets++
+ case '>':
+ if brackets >= 2 {
+ z.data.end = z.raw.end - len("]]>")
+ return true
+ }
+ brackets = 0
+ default:
+ brackets = 0
+ }
+ }
+ panic("unreachable")
}
// startTagIn returns whether the start tag in z.buf[z.data.start:z.data.end]
@@ -406,29 +737,10 @@ loop:
// readStartTag reads the next start tag token. The opening "<a" has already
// been consumed, where 'a' means anything in [A-Za-z].
func (z *Tokenizer) readStartTag() TokenType {
- z.attr = z.attr[:0]
- z.nAttrReturned = 0
- // Read the tag name and attribute key/value pairs.
- z.readTagName()
- if z.skipWhiteSpace(); z.err != nil {
+ z.readTag(true)
+ if z.err != nil {
return ErrorToken
}
- for {
- c := z.readByte()
- if z.err != nil || c == '>' {
- break
- }
- z.raw.end--
- z.readTagAttrKey()
- z.readTagAttrVal()
- // Save pendingAttr if it has a non-empty key.
- if z.pendingAttr[0].start != z.pendingAttr[0].end {
- z.attr = append(z.attr, z.pendingAttr)
- }
- if z.skipWhiteSpace(); z.err != nil {
- break
- }
- }
// Several tags flag the tokenizer's next token as raw.
c, raw := z.buf[z.data.start], false
if 'A' <= c && c <= 'Z' {
@@ -458,16 +770,32 @@ func (z *Tokenizer) readStartTag() TokenType {
return StartTagToken
}
-// readEndTag reads the next end tag token. The opening "</a" has already
-// been consumed, where 'a' means anything in [A-Za-z].
-func (z *Tokenizer) readEndTag() {
+// readTag reads the next tag token and its attributes. If saveAttr, those
+// attributes are saved in z.attr, otherwise z.attr is set to an empty slice.
+// The opening "<a" or "</a" has already been consumed, where 'a' means anything
+// in [A-Za-z].
+func (z *Tokenizer) readTag(saveAttr bool) {
z.attr = z.attr[:0]
z.nAttrReturned = 0
+ // Read the tag name and attribute key/value pairs.
z.readTagName()
+ if z.skipWhiteSpace(); z.err != nil {
+ return
+ }
for {
c := z.readByte()
if z.err != nil || c == '>' {
- return
+ break
+ }
+ z.raw.end--
+ z.readTagAttrKey()
+ z.readTagAttrVal()
+ // Save pendingAttr if saveAttr and that attribute has a non-empty key.
+ if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end {
+ z.attr = append(z.attr, z.pendingAttr)
+ }
+ if z.skipWhiteSpace(); z.err != nil {
+ break
}
}
}
@@ -594,16 +922,19 @@ func (z *Tokenizer) Next() TokenType {
for z.err == nil {
z.readByte()
}
+ z.data.end = z.raw.end
z.textIsRaw = true
} else {
z.readRawOrRCDATA()
}
if z.data.end > z.data.start {
z.tt = TextToken
+ z.convertNUL = true
return z.tt
}
}
z.textIsRaw = false
+ z.convertNUL = false
loop:
for {
@@ -662,8 +993,12 @@ loop:
continue loop
}
if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
- z.readEndTag()
- z.tt = EndTagToken
+ z.readTag(false)
+ if z.err != nil {
+ z.tt = ErrorToken
+ } else {
+ z.tt = EndTagToken
+ }
return z.tt
}
z.raw.end--
@@ -696,6 +1031,43 @@ func (z *Tokenizer) Raw() []byte {
return z.buf[z.raw.start:z.raw.end]
}
+// convertNewlines converts "\r" and "\r\n" in s to "\n".
+// The conversion happens in place, but the resulting slice may be shorter.
+func convertNewlines(s []byte) []byte {
+ for i, c := range s {
+ if c != '\r' {
+ continue
+ }
+
+ src := i + 1
+ if src >= len(s) || s[src] != '\n' {
+ s[i] = '\n'
+ continue
+ }
+
+ dst := i
+ for src < len(s) {
+ if s[src] == '\r' {
+ if src+1 < len(s) && s[src+1] == '\n' {
+ src++
+ }
+ s[dst] = '\n'
+ } else {
+ s[dst] = s[src]
+ }
+ src++
+ dst++
+ }
+ return s[:dst]
+ }
+ return s
+}
+
+var (
+ nul = []byte("\x00")
+ replacement = []byte("\ufffd")
+)
+
// Text returns the unescaped text of a text, comment or doctype token. The
// contents of the returned slice may change on the next call to Next.
func (z *Tokenizer) Text() []byte {
@@ -704,8 +1076,12 @@ func (z *Tokenizer) Text() []byte {
s := z.buf[z.data.start:z.data.end]
z.data.start = z.raw.end
z.data.end = z.raw.end
+ s = convertNewlines(s)
+ if (z.convertNUL || z.tt == CommentToken) && bytes.Contains(s, nul) {
+ s = bytes.Replace(s, nul, replacement, -1)
+ }
if !z.textIsRaw {
- s = unescape(s)
+ s = unescape(s, false)
}
return s
}
@@ -739,7 +1115,7 @@ func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
z.nAttrReturned++
key = z.buf[x[0].start:x[0].end]
val = z.buf[x[1].start:x[1].end]
- return lower(key), unescape(val), z.nAttrReturned < len(z.attr)
+ return lower(key), unescape(convertNewlines(val), true), z.nAttrReturned < len(z.attr)
}
}
return nil, nil, false
@@ -752,19 +1128,18 @@ func (z *Tokenizer) Token() Token {
switch z.tt {
case TextToken, CommentToken, DoctypeToken:
t.Data = string(z.Text())
- case StartTagToken, SelfClosingTagToken:
- var attr []Attribute
+ case StartTagToken, SelfClosingTagToken, EndTagToken:
name, moreAttr := z.TagName()
for moreAttr {
var key, val []byte
key, val, moreAttr = z.TagAttr()
- attr = append(attr, Attribute{"", string(key), string(val)})
+ t.Attr = append(t.Attr, Attribute{"", atom.String(key), string(val)})
+ }
+ if a := atom.Lookup(name); a != 0 {
+ t.DataAtom, t.Data = a, a.String()
+ } else {
+ t.DataAtom, t.Data = 0, string(name)
}
- t.Data = string(name)
- t.Attr = attr
- case EndTagToken:
- name, _ := z.TagName()
- t.Data = string(name)
}
return t
}
@@ -772,8 +1147,27 @@ func (z *Tokenizer) Token() Token {
// NewTokenizer returns a new HTML Tokenizer for the given Reader.
// The input is assumed to be UTF-8 encoded.
func NewTokenizer(r io.Reader) *Tokenizer {
- return &Tokenizer{
+ return NewTokenizerFragment(r, "")
+}
+
+// NewTokenizerFragment returns a new HTML Tokenizer for the given Reader, for
+// tokenizing an exisitng element's InnerHTML fragment. contextTag is that
+// element's tag, such as "div" or "iframe".
+//
+// For example, how the InnerHTML "a<b" is tokenized depends on whether it is
+// for a <p> tag or a <script> tag.
+//
+// The input is assumed to be UTF-8 encoded.
+func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer {
+ z := &Tokenizer{
r: r,
buf: make([]byte, 0, 4096),
}
+ if contextTag != "" {
+ switch s := strings.ToLower(contextTag); s {
+ case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "title", "textarea", "xmp":
+ z.rawTag = s
+ }
+ }
+ return z
}
diff --git a/libgo/go/exp/html/token_test.go b/libgo/go/exp/html/token_test.go
index 61d74006eab..63a8bfc4834 100644
--- a/libgo/go/exp/html/token_test.go
+++ b/libgo/go/exp/html/token_test.go
@@ -7,6 +7,8 @@ package html
import (
"bytes"
"io"
+ "io/ioutil"
+ "runtime"
"strings"
"testing"
)
@@ -126,7 +128,7 @@ var tokenTests = []tokenTest{
{
"tag name eof #4",
`<a x`,
- `<a x="">`,
+ ``,
},
// Some malformed tags that are missing a '>'.
{
@@ -142,12 +144,12 @@ var tokenTests = []tokenTest{
{
"malformed tag #2",
`<p id`,
- `<p id="">`,
+ ``,
},
{
"malformed tag #3",
`<p id=`,
- `<p id="">`,
+ ``,
},
{
"malformed tag #4",
@@ -157,7 +159,7 @@ var tokenTests = []tokenTest{
{
"malformed tag #5",
`<p id=0`,
- `<p id="0">`,
+ ``,
},
{
"malformed tag #6",
@@ -167,13 +169,18 @@ var tokenTests = []tokenTest{
{
"malformed tag #7",
`<p id="0</p>`,
- `<p id="0&lt;/p&gt;">`,
+ ``,
},
{
"malformed tag #8",
`<p id="0"</p>`,
`<p id="0" <="" p="">`,
},
+ {
+ "malformed tag #9",
+ `<p></p id`,
+ `<p>`,
+ },
// Raw text and RCDATA.
{
"basic raw text",
@@ -203,7 +210,7 @@ var tokenTests = []tokenTest{
{
"' ' completes script end tag",
"<SCRIPT>a</SCRipt ",
- "<script>$a$</script>",
+ "<script>$a",
},
{
"'>' completes script end tag",
@@ -359,7 +366,7 @@ var tokenTests = []tokenTest{
{
"tricky",
"<p \t\n iD=\"a&quot;B\" foo=\"bar\"><EM>te&lt;&amp;;xt</em></p>",
- `<p id="a&quot;B" foo="bar">$<em>$te&lt;&amp;;xt$</em>$</p>`,
+ `<p id="a&#34;B" foo="bar">$<em>$te&lt;&amp;;xt$</em>$</p>`,
},
// A nonexistent entity. Tokenizing and converting back to a string should
// escape the "&" to become "&amp;".
@@ -368,14 +375,11 @@ var tokenTests = []tokenTest{
`<a b="c&noSuchEntity;d">&lt;&alsoDoesntExist;&`,
`<a b="c&amp;noSuchEntity;d">$&lt;&amp;alsoDoesntExist;&amp;`,
},
- /*
- // TODO: re-enable this test when it works. This input/output matches html5lib's behavior.
- {
- "entity without semicolon",
- `&notit;&notin;<a b="q=z&amp=5&notice=hello&not;=world">`,
- `¬it;∉$<a b="q=z&amp;amp=5&amp;notice=hello¬=world">`,
- },
- */
+ {
+ "entity without semicolon",
+ `&notit;&notin;<a b="q=z&amp=5&notice=hello&not;=world">`,
+ `¬it;∉$<a b="q=z&amp;amp=5&amp;notice=hello¬=world">`,
+ },
{
"entity with digits",
"&frac12;",
@@ -421,7 +425,7 @@ var tokenTests = []tokenTest{
{
"Double-quoted attribute value",
`<input value="I'm an attribute" FOO="BAR">`,
- `<input value="I&apos;m an attribute" foo="BAR">`,
+ `<input value="I&#39;m an attribute" foo="BAR">`,
},
{
"Attribute name characters",
@@ -436,7 +440,7 @@ var tokenTests = []tokenTest{
{
"Attributes with a solitary single quote",
`<p id=can't><p id=won't>`,
- `<p id="can&apos;t">$<p id="won&apos;t">`,
+ `<p id="can&#39;t">$<p id="won&#39;t">`,
},
}
@@ -545,10 +549,11 @@ func TestUnescapeEscape(t *testing.T) {
`"<&>"`,
`&quot;&lt;&amp;&gt;&quot;`,
`3&5==1 && 0<1, "0&lt;1", a+acute=&aacute;`,
+ `The special characters are: <, >, &, ' and "`,
}
for _, s := range ss {
- if s != UnescapeString(EscapeString(s)) {
- t.Errorf("s != UnescapeString(EscapeString(s)), s=%q", s)
+ if got := UnescapeString(EscapeString(s)); got != s {
+ t.Errorf("got %q want %q", got, s)
}
}
}
@@ -588,3 +593,93 @@ loop:
t.Errorf("TestBufAPI: want %q got %q", u, v)
}
}
+
+func TestConvertNewlines(t *testing.T) {
+ testCases := map[string]string{
+ "Mac\rDOS\r\nUnix\n": "Mac\nDOS\nUnix\n",
+ "Unix\nMac\rDOS\r\n": "Unix\nMac\nDOS\n",
+ "DOS\r\nDOS\r\nDOS\r\n": "DOS\nDOS\nDOS\n",
+ "": "",
+ "\n": "\n",
+ "\n\r": "\n\n",
+ "\r": "\n",
+ "\r\n": "\n",
+ "\r\n\n": "\n\n",
+ "\r\n\r": "\n\n",
+ "\r\n\r\n": "\n\n",
+ "\r\r": "\n\n",
+ "\r\r\n": "\n\n",
+ "\r\r\n\n": "\n\n\n",
+ "\r\r\r\n": "\n\n\n",
+ "\r \n": "\n \n",
+ "xyz": "xyz",
+ }
+ for in, want := range testCases {
+ if got := string(convertNewlines([]byte(in))); got != want {
+ t.Errorf("input %q: got %q, want %q", in, got, want)
+ }
+ }
+}
+
+const (
+ rawLevel = iota
+ lowLevel
+ highLevel
+)
+
+func benchmarkTokenizer(b *testing.B, level int) {
+ buf, err := ioutil.ReadFile("testdata/go1.html")
+ if err != nil {
+ b.Fatalf("could not read testdata/go1.html: %v", err)
+ }
+ b.SetBytes(int64(len(buf)))
+ runtime.GC()
+ var ms runtime.MemStats
+ runtime.ReadMemStats(&ms)
+ mallocs := ms.Mallocs
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ z := NewTokenizer(bytes.NewBuffer(buf))
+ for {
+ tt := z.Next()
+ if tt == ErrorToken {
+ if err := z.Err(); err != nil && err != io.EOF {
+ b.Fatalf("tokenizer error: %v", err)
+ }
+ break
+ }
+ switch level {
+ case rawLevel:
+ // Calling z.Raw just returns the raw bytes of the token. It does
+ // not unescape &lt; to <, or lower-case tag names and attribute keys.
+ z.Raw()
+ case lowLevel:
+ // Caling z.Text, z.TagName and z.TagAttr returns []byte values
+ // whose contents may change on the next call to z.Next.
+ switch tt {
+ case TextToken, CommentToken, DoctypeToken:
+ z.Text()
+ case StartTagToken, SelfClosingTagToken:
+ _, more := z.TagName()
+ for more {
+ _, _, more = z.TagAttr()
+ }
+ case EndTagToken:
+ z.TagName()
+ }
+ case highLevel:
+ // Calling z.Token converts []byte values to strings whose validity
+ // extend beyond the next call to z.Next.
+ z.Token()
+ }
+ }
+ }
+ b.StopTimer()
+ runtime.ReadMemStats(&ms)
+ mallocs = ms.Mallocs - mallocs
+ b.Logf("%d iterations, %d mallocs per iteration\n", b.N, int(mallocs)/b.N)
+}
+
+func BenchmarkRawLevelTokenizer(b *testing.B) { benchmarkTokenizer(b, rawLevel) }
+func BenchmarkLowLevelTokenizer(b *testing.B) { benchmarkTokenizer(b, lowLevel) }
+func BenchmarkHighLevelTokenizer(b *testing.B) { benchmarkTokenizer(b, highLevel) }
diff --git a/libgo/go/exp/locale/collate/build/builder.go b/libgo/go/exp/locale/collate/build/builder.go
new file mode 100644
index 00000000000..97d5e81ddd0
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/builder.go
@@ -0,0 +1,476 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "exp/locale/collate"
+ "exp/norm"
+ "fmt"
+ "io"
+ "log"
+ "sort"
+ "strings"
+ "unicode/utf8"
+)
+
+// TODO: optimizations:
+// - expandElem is currently 20K. By putting unique colElems in a separate
+// table and having a byte array of indexes into this table, we can reduce
+// the total size to about 7K. By also factoring out the length bytes, we
+// can reduce this to about 6K.
+// - trie valueBlocks are currently 100K. There are a lot of sparse blocks
+// and many consecutive values with the same stride. This can be further
+// compacted.
+// - Compress secondary weights into 8 bits.
+// - Some LDML specs specify a context element. Currently we simply concatenate
+// those. Context can be implemented using the contraction trie. If Builder
+// could analyze and detect when using a context makes sense, there is no
+// need to expose this construct in the API.
+
+// A Builder builds a root collation table. The user must specify the
+// collation elements for each entry. A common use will be to base the weights
+// on those specified in the allkeys* file as provided by the UCA or CLDR.
+type Builder struct {
+ index *trieBuilder
+ root ordering
+ locale []*Tailoring
+ t *table
+ err error
+ built bool
+
+ minNonVar int // lowest primary recorded for a variable
+ varTop int // highest primary recorded for a non-variable
+
+ // indexes used for reusing expansions and contractions
+ expIndex map[string]int // positions of expansions keyed by their string representation
+ ctHandle map[string]ctHandle // contraction handles keyed by a concatenation of the suffixes
+ ctElem map[string]int // contraction elements keyed by their string representation
+}
+
+// A Tailoring builds a collation table based on another collation table.
+// The table is defined by specifying tailorings to the underlying table.
+// See http://unicode.org/reports/tr35/ for an overview of tailoring
+// collation tables. The CLDR contains pre-defined tailorings for a variety
+// of languages (See http://www.unicode.org/Public/cldr/2.0.1/core.zip.)
+type Tailoring struct {
+ id string
+ builder *Builder
+ index *ordering
+ // TODO: implement.
+}
+
+// NewBuilder returns a new Builder.
+func NewBuilder() *Builder {
+ return &Builder{
+ index: newTrieBuilder(),
+ root: makeRootOrdering(),
+ expIndex: make(map[string]int),
+ ctHandle: make(map[string]ctHandle),
+ ctElem: make(map[string]int),
+ }
+}
+
+// Tailoring returns a Tailoring for the given locale. One should
+// have completed all calls to Add before calling Tailoring.
+func (b *Builder) Tailoring(locale string) *Tailoring {
+ t := &Tailoring{
+ id: locale,
+ builder: b,
+ index: b.root.clone(),
+ }
+ b.locale = append(b.locale, t)
+ return t
+}
+
+// Add adds an entry to the collation element table, mapping
+// a slice of runes to a sequence of collation elements.
+// A collation element is specified as list of weights: []int{primary, secondary, ...}.
+// The entries are typically obtained from a collation element table
+// as defined in http://www.unicode.org/reports/tr10/#Data_Table_Format.
+// Note that the collation elements specified by colelems are only used
+// as a guide. The actual weights generated by Builder may differ.
+// The argument variables is a list of indices into colelems that should contain
+// a value for each colelem that is a variable. (See the reference above.)
+func (b *Builder) Add(runes []rune, colelems [][]int, variables []int) error {
+ str := string(runes)
+
+ elems := make([][]int, len(colelems))
+ for i, ce := range colelems {
+ elems[i] = append(elems[i], ce...)
+ if len(ce) == 0 {
+ elems[i] = append(elems[i], []int{0, 0, 0, 0}...)
+ break
+ }
+ if len(ce) == 1 {
+ elems[i] = append(elems[i], defaultSecondary)
+ }
+ if len(ce) <= 2 {
+ elems[i] = append(elems[i], defaultTertiary)
+ }
+ if len(ce) <= 3 {
+ elems[i] = append(elems[i], ce[0])
+ }
+ }
+ for i, ce := range elems {
+ isvar := false
+ for _, j := range variables {
+ if i == j {
+ isvar = true
+ }
+ }
+ if isvar {
+ if ce[0] >= b.minNonVar && b.minNonVar > 0 {
+ return fmt.Errorf("primary value %X of variable is larger than the smallest non-variable %X", ce[0], b.minNonVar)
+ }
+ if ce[0] > b.varTop {
+ b.varTop = ce[0]
+ }
+ } else if ce[0] > 0 {
+ if ce[0] <= b.varTop {
+ return fmt.Errorf("primary value %X of non-variable is smaller than the highest variable %X", ce[0], b.varTop)
+ }
+ if b.minNonVar == 0 || ce[0] < b.minNonVar {
+ b.minNonVar = ce[0]
+ }
+ }
+ }
+ elems, err := convertLargeWeights(elems)
+ if err != nil {
+ return err
+ }
+ b.root.newEntry(str, elems)
+ return nil
+}
+
+// SetAnchor sets the point after which elements passed in subsequent calls to
+// Insert will be inserted. It is equivalent to the reset directive in an LDML
+// specification. See Insert for an example.
+// SetAnchor supports the following logical reset positions:
+// <first_tertiary_ignorable/>, <last_teriary_ignorable/>, <first_primary_ignorable/>,
+// and <last_non_ignorable/>.
+func (t *Tailoring) SetAnchor(anchor string) error {
+ // TODO: implement.
+ return nil
+}
+
+// SetAnchorBefore is similar to SetAnchor, except that subsequent calls to
+// Insert will insert entries before the anchor.
+func (t *Tailoring) SetAnchorBefore(anchor string) error {
+ // TODO: implement.
+ return nil
+}
+
+// Insert sets the ordering of str relative to the entry set by the previous
+// call to SetAnchor or Insert. The argument extend corresponds
+// to the extend elements as defined in LDML. A non-empty value for extend
+// will cause the collation elements corresponding to extend to be appended
+// to the collation elements generated for the entry added by Insert.
+// This has the same net effect as sorting str after the string anchor+extend.
+// See http://www.unicode.org/reports/tr10/#Tailoring_Example for details
+// on parametric tailoring and http://unicode.org/reports/tr35/#Collation_Elements
+// for full details on LDML.
+//
+// Examples: create a tailoring for Swedish, where "ä" is ordered after "z"
+// at the primary sorting level:
+// t := b.Tailoring("se")
+// t.SetAnchor("z")
+// t.Insert(collate.Primary, "ä", "")
+// Order "ü" after "ue" at the secondary sorting level:
+// t.SetAnchor("ue")
+// t.Insert(collate.Secondary, "ü","")
+// or
+// t.SetAnchor("u")
+// t.Insert(collate.Secondary, "ü", "e")
+// Order "q" afer "ab" at the secondary level and "Q" after "q"
+// at the tertiary level:
+// t.SetAnchor("ab")
+// t.Insert(collate.Secondary, "q", "")
+// t.Insert(collate.Tertiary, "Q", "")
+// Order "b" before "a":
+// t.SetAnchorBefore("a")
+// t.Insert(collate.Primary, "b", "")
+// Order "0" after the last primary ignorable:
+// t.SetAnchor("<last_primary_ignorable/>")
+// t.Insert(collate.Primary, "0", "")
+func (t *Tailoring) Insert(level collate.Level, str, extend string) error {
+ // TODO: implement.
+ return nil
+}
+
+func (b *Builder) error(e error) {
+ if e != nil {
+ b.err = e
+ }
+}
+
+func (b *Builder) buildOrdering(o *ordering) {
+ o.sort()
+ simplify(o)
+ b.processExpansions(o) // requires simplify
+ b.processContractions(o) // requires simplify
+
+ t := newNode()
+ for e := o.front(); e != nil; e, _ = e.nextIndexed() {
+ if !e.skip() {
+ ce, err := e.encode()
+ b.error(err)
+ t.insert(e.runes[0], ce)
+ }
+ }
+ o.handle = b.index.addTrie(t)
+}
+
+func (b *Builder) build() (*table, error) {
+ if b.built {
+ return b.t, b.err
+ }
+ b.built = true
+ b.t = &table{
+ maxContractLen: utf8.UTFMax,
+ variableTop: uint32(b.varTop),
+ }
+
+ b.buildOrdering(&b.root)
+ b.t.root = b.root.handle
+ for _, t := range b.locale {
+ b.buildOrdering(t.index)
+ if b.err != nil {
+ break
+ }
+ }
+ i, err := b.index.generate()
+ b.t.index = *i
+ b.error(err)
+ return b.t, b.err
+}
+
+// Build builds the root Collator.
+func (b *Builder) Build() (*collate.Collator, error) {
+ t, err := b.build()
+ if err != nil {
+ return nil, err
+ }
+ return collate.Init(t), nil
+}
+
+// Build builds a Collator for Tailoring t.
+func (t *Tailoring) Build() (*collate.Collator, error) {
+ // TODO: implement.
+ return nil, nil
+}
+
+// Print prints the tables for b and all its Tailorings as a Go file
+// that can be included in the Collate package.
+func (b *Builder) Print(w io.Writer) (n int, err error) {
+ p := func(nn int, e error) {
+ n += nn
+ if err == nil {
+ err = e
+ }
+ }
+ t, err := b.build()
+ if err != nil {
+ return 0, err
+ }
+ p(fmt.Fprintf(w, "var availableLocales = []string{"))
+ for _, loc := range b.locale {
+ p(fmt.Fprintf(w, "%q, ", loc.id))
+ }
+ p(fmt.Fprintln(w, "}\n"))
+ p(fmt.Fprintln(w, "var locales = map[string]tableIndex{"))
+ for _, loc := range b.locale {
+ p(fmt.Fprintf(w, "\t%q: ", loc.id))
+ p(t.fprintIndex(w, loc.index.handle))
+ p(fmt.Fprintln(w, ","))
+ }
+ p(fmt.Fprint(w, "}\n\n"))
+ n, _, err = t.fprint(w, "main")
+ return
+}
+
+// reproducibleFromNFKD checks whether the given expansion could be generated
+// from an NFKD expansion.
+func reproducibleFromNFKD(e *entry, exp, nfkd [][]int) bool {
+ // Length must be equal.
+ if len(exp) != len(nfkd) {
+ return false
+ }
+ for i, ce := range exp {
+ // Primary and secondary values should be equal.
+ if ce[0] != nfkd[i][0] || ce[1] != nfkd[i][1] {
+ return false
+ }
+ // Tertiary values should be equal to maxTertiary for third element onwards.
+ // TODO: there seem to be a lot of cases in CLDR (e.g. ㏭ in zh.xml) that can
+ // simply be dropped. Try this out by dropping the following code.
+ if i >= 2 && ce[2] != maxTertiary {
+ return false
+ }
+ }
+ return true
+}
+
+func simplify(o *ordering) {
+ // Runes that are a starter of a contraction should not be removed.
+ // (To date, there is only Kannada character 0CCA.)
+ keep := make(map[rune]bool)
+ for e := o.front(); e != nil; e, _ = e.nextIndexed() {
+ if len(e.runes) > 1 {
+ keep[e.runes[0]] = true
+ }
+ }
+ // Remove entries for which the runes normalize (using NFD) to identical values.
+ for e := o.front(); e != nil; e, _ = e.nextIndexed() {
+ s := e.str
+ nfd := norm.NFD.String(s)
+ if len(e.runes) > 1 || keep[e.runes[0]] || nfd == s {
+ continue
+ }
+ if equalCEArrays(o.genColElems(nfd), e.elems) {
+ e.remove()
+ }
+ }
+
+ // Tag entries for which the runes NFKD decompose to identical values.
+ for e := o.front(); e != nil; e, _ = e.nextIndexed() {
+ s := e.str
+ nfkd := norm.NFKD.String(s)
+ if len(e.runes) > 1 || keep[e.runes[0]] || nfkd == s {
+ continue
+ }
+ if reproducibleFromNFKD(e, e.elems, o.genColElems(nfkd)) {
+ e.decompose = true
+ }
+ }
+}
+
+// appendExpansion converts the given collation sequence to
+// collation elements and adds them to the expansion table.
+// It returns an index to the expansion table.
+func (b *Builder) appendExpansion(e *entry) int {
+ t := b.t
+ i := len(t.expandElem)
+ ce := uint32(len(e.elems))
+ t.expandElem = append(t.expandElem, ce)
+ for _, w := range e.elems {
+ ce, err := makeCE(w)
+ if err != nil {
+ b.error(err)
+ return -1
+ }
+ t.expandElem = append(t.expandElem, ce)
+ }
+ return i
+}
+
+// processExpansions extracts data necessary to generate
+// the extraction tables.
+func (b *Builder) processExpansions(o *ordering) {
+ for e := o.front(); e != nil; e, _ = e.nextIndexed() {
+ if !e.expansion() {
+ continue
+ }
+ key := fmt.Sprintf("%v", e.elems)
+ i, ok := b.expIndex[key]
+ if !ok {
+ i = b.appendExpansion(e)
+ b.expIndex[key] = i
+ }
+ e.expansionIndex = i
+ }
+}
+
+func (b *Builder) processContractions(o *ordering) {
+ // Collate contractions per starter rune.
+ starters := []rune{}
+ cm := make(map[rune][]*entry)
+ for e := o.front(); e != nil; e, _ = e.nextIndexed() {
+ if e.contraction() {
+ if len(e.str) > b.t.maxContractLen {
+ b.t.maxContractLen = len(e.str)
+ }
+ r := e.runes[0]
+ if _, ok := cm[r]; !ok {
+ starters = append(starters, r)
+ }
+ cm[r] = append(cm[r], e)
+ }
+ }
+ // Add entries of single runes that are at a start of a contraction.
+ for e := o.front(); e != nil; e, _ = e.nextIndexed() {
+ if !e.contraction() {
+ r := e.runes[0]
+ if _, ok := cm[r]; ok {
+ cm[r] = append(cm[r], e)
+ }
+ }
+ }
+ // Build the tries for the contractions.
+ t := b.t
+ for _, r := range starters {
+ l := cm[r]
+ // Compute suffix strings. There are 31 different contraction suffix
+ // sets for 715 contractions and 82 contraction starter runes as of
+ // version 6.0.0.
+ sufx := []string{}
+ hasSingle := false
+ for _, e := range l {
+ if len(e.runes) > 1 {
+ sufx = append(sufx, string(e.runes[1:]))
+ } else {
+ hasSingle = true
+ }
+ }
+ if !hasSingle {
+ b.error(fmt.Errorf("no single entry for starter rune %U found", r))
+ continue
+ }
+ // Unique the suffix set.
+ sort.Strings(sufx)
+ key := strings.Join(sufx, "\n")
+ handle, ok := b.ctHandle[key]
+ if !ok {
+ var err error
+ handle, err = t.contractTries.appendTrie(sufx)
+ if err != nil {
+ b.error(err)
+ }
+ b.ctHandle[key] = handle
+ }
+ // Bucket sort entries in index order.
+ es := make([]*entry, len(l))
+ for _, e := range l {
+ var o, sn int
+ if len(e.runes) > 1 {
+ str := []byte(string(e.runes[1:]))
+ o, sn = t.contractTries.lookup(handle, str)
+ if sn != len(str) {
+ log.Fatalf("processContractions: unexpected length for '%X'; len=%d; want %d", e.runes, sn, len(str))
+ }
+ }
+ if es[o] != nil {
+ log.Fatalf("Multiple contractions for position %d for rune %U", o, e.runes[0])
+ }
+ es[o] = e
+ }
+ // Create collation elements for contractions.
+ elems := []uint32{}
+ for _, e := range es {
+ ce, err := e.encodeBase()
+ b.error(err)
+ elems = append(elems, ce)
+ }
+ key = fmt.Sprintf("%v", elems)
+ i, ok := b.ctElem[key]
+ if !ok {
+ i = len(t.contractElem)
+ b.ctElem[key] = i
+ t.contractElem = append(t.contractElem, elems...)
+ }
+ // Store info in entry for starter rune.
+ es[0].contractionIndex = i
+ es[0].contractionHandle = handle
+ }
+}
diff --git a/libgo/go/exp/locale/collate/build/builder_test.go b/libgo/go/exp/locale/collate/build/builder_test.go
new file mode 100644
index 00000000000..f80a2bcb5b5
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/builder_test.go
@@ -0,0 +1,269 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import "testing"
+
+// cjk returns an implicit collation element for a CJK rune.
+func cjk(r rune) [][]int {
+ // A CJK character C is represented in the DUCET as
+ // [.AAAA.0020.0002.C][.BBBB.0000.0000.C]
+ // Where AAAA is the most significant 15 bits plus a base value.
+ // Any base value will work for the test, so we pick the common value of FB40.
+ const base = 0xFB40
+ return [][]int{
+ {base + int(r>>15), defaultSecondary, defaultTertiary, int(r)},
+ {int(r&0x7FFF) | 0x8000, 0, 0, int(r)},
+ }
+}
+
+func pCE(p int) [][]int {
+ return [][]int{{p, defaultSecondary, defaultTertiary, 0}}
+}
+
+func pqCE(p, q int) [][]int {
+ return [][]int{{p, defaultSecondary, defaultTertiary, q}}
+}
+
+func ptCE(p, t int) [][]int {
+ return [][]int{{p, defaultSecondary, t, 0}}
+}
+
+func sCE(s int) [][]int {
+ return [][]int{{0, s, defaultTertiary, 0}}
+}
+
+func stCE(s, t int) [][]int {
+ return [][]int{{0, s, t, 0}}
+}
+
+// ducetElem is used to define test data that is used to generate a table.
+type ducetElem struct {
+ str string
+ ces [][]int
+}
+
+func newBuilder(t *testing.T, ducet []ducetElem) *Builder {
+ b := NewBuilder()
+ for _, e := range ducet {
+ if err := b.Add([]rune(e.str), e.ces, nil); err != nil {
+ t.Errorf(err.Error())
+ }
+ }
+ b.t = &table{}
+ b.root.sort()
+ return b
+}
+
+type convertTest struct {
+ in, out [][]int
+ err bool
+}
+
+var convLargeTests = []convertTest{
+ {pCE(0xFB39), pCE(0xFB39), false},
+ {cjk(0x2F9B2), pqCE(0x3F9B2, 0x2F9B2), false},
+ {pCE(0xFB40), pCE(0), true},
+ {append(pCE(0xFB40), pCE(0)[0]), pCE(0), true},
+ {pCE(0xFFFE), pCE(illegalOffset), false},
+ {pCE(0xFFFF), pCE(illegalOffset + 1), false},
+}
+
+func TestConvertLarge(t *testing.T) {
+ for i, tt := range convLargeTests {
+ e := &entry{elems: tt.in}
+ elems, err := convertLargeWeights(e.elems)
+ if tt.err {
+ if err == nil {
+ t.Errorf("%d: expected error; none found", i)
+ }
+ continue
+ } else if err != nil {
+ t.Errorf("%d: unexpected error: %v", i, err)
+ }
+ if !equalCEArrays(elems, tt.out) {
+ t.Errorf("%d: conversion was %x; want %x", i, elems, tt.out)
+ }
+ }
+}
+
+// Collation element table for simplify tests.
+var simplifyTest = []ducetElem{
+ {"\u0300", sCE(30)}, // grave
+ {"\u030C", sCE(40)}, // caron
+ {"A", ptCE(100, 8)},
+ {"D", ptCE(104, 8)},
+ {"E", ptCE(105, 8)},
+ {"I", ptCE(110, 8)},
+ {"z", ptCE(130, 8)},
+ {"\u05F2", append(ptCE(200, 4), ptCE(200, 4)[0])},
+ {"\u05B7", sCE(80)},
+ {"\u00C0", append(ptCE(100, 8), sCE(30)...)}, // A with grave, can be removed
+ {"\u00C8", append(ptCE(105, 8), sCE(30)...)}, // E with grave
+ {"\uFB1F", append(ptCE(200, 4), ptCE(200, 4)[0], sCE(80)[0])}, // eliminated by NFD
+ {"\u00C8\u0302", ptCE(106, 8)}, // block previous from simplifying
+ {"\u01C5", append(ptCE(104, 9), ptCE(130, 4)[0], stCE(40, maxTertiary)[0])}, // eliminated by NFKD
+ // no removal: tertiary value of third element is not maxTertiary
+ {"\u2162", append(ptCE(110, 9), ptCE(110, 4)[0], ptCE(110, 8)[0])},
+}
+
+var genColTests = []ducetElem{
+ {"\uFA70", pqCE(0x1FA70, 0xFA70)},
+ {"A\u0300", append(ptCE(100, 8), sCE(30)...)},
+ {"A\u0300\uFA70", append(ptCE(100, 8), sCE(30)[0], pqCE(0x1FA70, 0xFA70)[0])},
+ {"A\u0300A\u0300", append(ptCE(100, 8), sCE(30)[0], ptCE(100, 8)[0], sCE(30)[0])},
+}
+
+func TestGenColElems(t *testing.T) {
+ b := newBuilder(t, simplifyTest[:5])
+
+ for i, tt := range genColTests {
+ res := b.root.genColElems(tt.str)
+ if !equalCEArrays(tt.ces, res) {
+ t.Errorf("%d: result %X; want %X", i, res, tt.ces)
+ }
+ }
+}
+
+type strArray []string
+
+func (sa strArray) contains(s string) bool {
+ for _, e := range sa {
+ if e == s {
+ return true
+ }
+ }
+ return false
+}
+
+var simplifyRemoved = strArray{"\u00C0", "\uFB1F"}
+var simplifyMarked = strArray{"\u01C5"}
+
+func TestSimplify(t *testing.T) {
+ b := newBuilder(t, simplifyTest)
+ o := &b.root
+ simplify(o)
+
+ for i, tt := range simplifyTest {
+ if simplifyRemoved.contains(tt.str) {
+ continue
+ }
+ e := o.find(tt.str)
+ if e.str != tt.str || !equalCEArrays(e.elems, tt.ces) {
+ t.Errorf("%d: found element %s -> %X; want %s -> %X", i, e.str, e.elems, tt.str, tt.ces)
+ break
+ }
+ }
+ var i, k int
+ for e := o.front(); e != nil; e, _ = e.nextIndexed() {
+ gold := simplifyMarked.contains(e.str)
+ if gold {
+ k++
+ }
+ if gold != e.decompose {
+ t.Errorf("%d: %s has decompose %v; want %v", i, e.str, e.decompose, gold)
+ }
+ i++
+ }
+ if k != len(simplifyMarked) {
+ t.Errorf(" an entry that should be marked as decompose was deleted")
+ }
+}
+
+var expandTest = []ducetElem{
+ {"\u00C0", append(ptCE(100, 8), sCE(30)...)},
+ {"\u00C8", append(ptCE(105, 8), sCE(30)...)},
+ {"\u00C9", append(ptCE(105, 8), sCE(30)...)}, // identical expansion
+ {"\u05F2", append(ptCE(200, 4), ptCE(200, 4)[0], ptCE(200, 4)[0])},
+}
+
+func TestExpand(t *testing.T) {
+ const (
+ totalExpansions = 3
+ totalElements = 2 + 2 + 3 + totalExpansions
+ )
+ b := newBuilder(t, expandTest)
+ o := &b.root
+ b.processExpansions(o)
+
+ e := o.front()
+ for _, tt := range expandTest {
+ exp := b.t.expandElem[e.expansionIndex:]
+ if int(exp[0]) != len(tt.ces) {
+ t.Errorf("%U: len(expansion)==%d; want %d", []rune(tt.str)[0], exp[0], len(tt.ces))
+ }
+ exp = exp[1:]
+ for j, w := range tt.ces {
+ if ce, _ := makeCE(w); exp[j] != ce {
+ t.Errorf("%U: element %d is %X; want %X", []rune(tt.str)[0], j, exp[j], ce)
+ }
+ }
+ e, _ = e.nextIndexed()
+ }
+ // Verify uniquing.
+ if len(b.t.expandElem) != totalElements {
+ t.Errorf("len(expandElem)==%d; want %d", len(b.t.expandElem), totalElements)
+ }
+}
+
+var contractTest = []ducetElem{
+ {"abc", pCE(102)},
+ {"abd", pCE(103)},
+ {"a", pCE(100)},
+ {"ab", pCE(101)},
+ {"ac", pCE(104)},
+ {"bcd", pCE(202)},
+ {"b", pCE(200)},
+ {"bc", pCE(201)},
+ {"bd", pCE(203)},
+ // shares suffixes with a*
+ {"Ab", pCE(301)},
+ {"A", pCE(300)},
+ {"Ac", pCE(304)},
+ {"Abc", pCE(302)},
+ {"Abd", pCE(303)},
+ // starter to be ignored
+ {"z", pCE(1000)},
+}
+
+func TestContract(t *testing.T) {
+ const (
+ totalElements = 5 + 5 + 4
+ )
+ b := newBuilder(t, contractTest)
+ o := &b.root
+ b.processContractions(o)
+
+ indexMap := make(map[int]bool)
+ handleMap := make(map[rune]*entry)
+ for e := o.front(); e != nil; e, _ = e.nextIndexed() {
+ if e.contractionHandle.n > 0 {
+ handleMap[e.runes[0]] = e
+ indexMap[e.contractionHandle.index] = true
+ }
+ }
+ // Verify uniquing.
+ if len(indexMap) != 2 {
+ t.Errorf("number of tries is %d; want %d", len(indexMap), 2)
+ }
+ for _, tt := range contractTest {
+ e, ok := handleMap[[]rune(tt.str)[0]]
+ if !ok {
+ continue
+ }
+ str := tt.str[1:]
+ offset, n := b.t.contractTries.lookup(e.contractionHandle, []byte(str))
+ if len(str) != n {
+ t.Errorf("%s: bytes consumed==%d; want %d", tt.str, n, len(str))
+ }
+ ce := b.t.contractElem[offset+e.contractionIndex]
+ if want, _ := makeCE(tt.ces[0]); want != ce {
+ t.Errorf("%s: element %X; want %X", tt.str, ce, want)
+ }
+ }
+ if len(b.t.contractElem) != totalElements {
+ t.Errorf("len(expandElem)==%d; want %d", len(b.t.contractElem), totalElements)
+ }
+}
diff --git a/libgo/go/exp/locale/collate/build/colelem.go b/libgo/go/exp/locale/collate/build/colelem.go
new file mode 100644
index 00000000000..343aa740a73
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/colelem.go
@@ -0,0 +1,329 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "exp/locale/collate"
+ "fmt"
+ "unicode"
+)
+
+const (
+ defaultSecondary = 0x20
+ defaultTertiary = 0x2
+ maxTertiary = 0x1F
+)
+
+// A collation element is represented as an uint32.
+// In the typical case, a rune maps to a single collation element. If a rune
+// can be the start of a contraction or expands into multiple collation elements,
+// then the collation element that is associated with a rune will have a special
+// form to represent such m to n mappings. Such special collation elements
+// have a value >= 0x80000000.
+
+// For normal collation elements, we assume that a collation element either has
+// a primary or non-default secondary value, not both.
+// Collation elements with a primary value are of the form
+// 010ppppp pppppppp pppppppp ssssssss
+// - p* is primary collation value
+// - s* is the secondary collation value
+// or
+// 00pppppp pppppppp ppppppps sssttttt, where
+// - p* is primary collation value
+// - s* offset of secondary from default value.
+// - t* is the tertiary collation value
+// Collation elements with a secondary value are of the form
+// 10000000 0000ssss ssssssss tttttttt, where
+// - 16 BMP implicit -> weight
+// - 8 bit s
+// - default tertiary
+const (
+ maxPrimaryBits = 21
+ maxSecondaryBits = 12
+ maxSecondaryCompactBits = 8
+ maxSecondaryDiffBits = 4
+ maxTertiaryBits = 8
+ maxTertiaryCompactBits = 5
+
+ isSecondary = 0x80000000
+ isPrimary = 0x40000000
+)
+
+func makeCE(weights []int) (uint32, error) {
+ if w := weights[0]; w >= 1<<maxPrimaryBits || w < 0 {
+ return 0, fmt.Errorf("makeCE: primary weight out of bounds: %x >= %x", w, 1<<maxPrimaryBits)
+ }
+ if w := weights[1]; w >= 1<<maxSecondaryBits || w < 0 {
+ return 0, fmt.Errorf("makeCE: secondary weight out of bounds: %x >= %x", w, 1<<maxSecondaryBits)
+ }
+ if w := weights[2]; w >= 1<<maxTertiaryBits || w < 0 {
+ return 0, fmt.Errorf("makeCE: tertiary weight out of bounds: %x >= %x", w, 1<<maxTertiaryBits)
+ }
+ ce := uint32(0)
+ if weights[0] != 0 {
+ if weights[2] == defaultTertiary {
+ if weights[1] >= 1<<maxSecondaryCompactBits {
+ return 0, fmt.Errorf("makeCE: secondary weight with non-zero primary out of bounds: %x >= %x", weights[1], 1<<maxSecondaryCompactBits)
+ }
+ ce = uint32(weights[0]<<maxSecondaryCompactBits + weights[1])
+ ce |= isPrimary
+ } else {
+ d := weights[1] - defaultSecondary
+ if d >= 1<<maxSecondaryDiffBits || d < 0 {
+ return 0, fmt.Errorf("makeCE: secondary weight diff out of bounds: %x < 0 || %x > %x", d, d, 1<<maxSecondaryDiffBits)
+ }
+ if weights[2] >= 1<<maxTertiaryCompactBits {
+ return 0, fmt.Errorf("makeCE: tertiary weight with non-zero primary out of bounds: %x > %x (%X)", weights[2], 1<<maxTertiaryCompactBits, weights)
+ }
+ ce = uint32(weights[0]<<maxSecondaryDiffBits + d)
+ ce = ce<<maxTertiaryCompactBits + uint32(weights[2])
+ }
+ } else {
+ ce = uint32(weights[1]<<maxTertiaryBits + weights[2])
+ ce |= isSecondary
+ }
+ return ce, nil
+}
+
+// For contractions, collation elements are of the form
+// 110bbbbb bbbbbbbb iiiiiiii iiiinnnn, where
+// - n* is the size of the first node in the contraction trie.
+// - i* is the index of the first node in the contraction trie.
+// - b* is the offset into the contraction collation element table.
+// See contract.go for details on the contraction trie.
+const (
+ contractID = 0xC0000000
+ maxNBits = 4
+ maxTrieIndexBits = 12
+ maxContractOffsetBits = 13
+)
+
+func makeContractIndex(h ctHandle, offset int) (uint32, error) {
+ if h.n >= 1<<maxNBits {
+ return 0, fmt.Errorf("size of contraction trie node too large: %d >= %d", h.n, 1<<maxNBits)
+ }
+ if h.index >= 1<<maxTrieIndexBits {
+ return 0, fmt.Errorf("size of contraction trie offset too large: %d >= %d", h.index, 1<<maxTrieIndexBits)
+ }
+ if offset >= 1<<maxContractOffsetBits {
+ return 0, fmt.Errorf("contraction offset out of bounds: %x >= %x", offset, 1<<maxContractOffsetBits)
+ }
+ ce := uint32(contractID)
+ ce += uint32(offset << (maxNBits + maxTrieIndexBits))
+ ce += uint32(h.index << maxNBits)
+ ce += uint32(h.n)
+ return ce, nil
+}
+
+// For expansions, collation elements are of the form
+// 11100000 00000000 bbbbbbbb bbbbbbbb,
+// where b* is the index into the expansion sequence table.
+const (
+ expandID = 0xE0000000
+ maxExpandIndexBits = 16
+)
+
+func makeExpandIndex(index int) (uint32, error) {
+ if index >= 1<<maxExpandIndexBits {
+ return 0, fmt.Errorf("expansion index out of bounds: %x >= %x", index, 1<<maxExpandIndexBits)
+ }
+ return expandID + uint32(index), nil
+}
+
+// Each list of collation elements corresponding to an expansion starts with
+// a header indicating the length of the sequence.
+func makeExpansionHeader(n int) (uint32, error) {
+ return uint32(n), nil
+}
+
+// Some runes can be expanded using NFKD decomposition. Instead of storing the full
+// sequence of collation elements, we decompose the rune and lookup the collation
+// elements for each rune in the decomposition and modify the tertiary weights.
+// The collation element, in this case, is of the form
+// 11110000 00000000 wwwwwwww vvvvvvvv, where
+// - v* is the replacement tertiary weight for the first rune,
+// - w* is the replacement tertiary weight for the second rune,
+// Tertiary weights of subsequent runes should be replaced with maxTertiary.
+// See http://www.unicode.org/reports/tr10/#Compatibility_Decompositions for more details.
+const (
+ decompID = 0xF0000000
+)
+
+func makeDecompose(t1, t2 int) (uint32, error) {
+ if t1 >= 256 || t1 < 0 {
+ return 0, fmt.Errorf("first tertiary weight out of bounds: %d >= 256", t1)
+ }
+ if t2 >= 256 || t2 < 0 {
+ return 0, fmt.Errorf("second tertiary weight out of bounds: %d >= 256", t2)
+ }
+ return uint32(t2<<8+t1) + decompID, nil
+}
+
+const (
+ // These constants were taken from http://www.unicode.org/versions/Unicode6.0.0/ch12.pdf.
+ minUnified rune = 0x4E00
+ maxUnified = 0x9FFF
+ minCompatibility = 0xF900
+ maxCompatibility = 0xFAFF
+ minRare = 0x3400
+ maxRare = 0x4DBF
+)
+const (
+ commonUnifiedOffset = 0x10000
+ rareUnifiedOffset = 0x20000 // largest rune in common is U+FAFF
+ otherOffset = 0x50000 // largest rune in rare is U+2FA1D
+ illegalOffset = otherOffset + int(unicode.MaxRune)
+ maxPrimary = illegalOffset + 1
+)
+
+// implicitPrimary returns the primary weight for the a rune
+// for which there is no entry for the rune in the collation table.
+// We take a different approach from the one specified in
+// http://unicode.org/reports/tr10/#Implicit_Weights,
+// but preserve the resulting relative ordering of the runes.
+func implicitPrimary(r rune) int {
+ if unicode.Is(unicode.Ideographic, r) {
+ if r >= minUnified && r <= maxUnified {
+ // The most common case for CJK.
+ return int(r) + commonUnifiedOffset
+ }
+ if r >= minCompatibility && r <= maxCompatibility {
+ // This will typically not hit. The DUCET explicitly specifies mappings
+ // for all characters that do not decompose.
+ return int(r) + commonUnifiedOffset
+ }
+ return int(r) + rareUnifiedOffset
+ }
+ return int(r) + otherOffset
+}
+
+// convertLargeWeights converts collation elements with large
+// primaries (either double primaries or for illegal runes)
+// to our own representation.
+// A CJK character C is represented in the DUCET as
+// [.FBxx.0020.0002.C][.BBBB.0000.0000.C]
+// We will rewrite these characters to a single CE.
+// We assume the CJK values start at 0x8000.
+// See http://unicode.org/reports/tr10/#Implicit_Weights
+func convertLargeWeights(elems [][]int) (res [][]int, err error) {
+ const (
+ cjkPrimaryStart = 0xFB40
+ rarePrimaryStart = 0xFB80
+ otherPrimaryStart = 0xFBC0
+ illegalPrimary = 0xFFFE
+ highBitsMask = 0x3F
+ lowBitsMask = 0x7FFF
+ lowBitsFlag = 0x8000
+ shiftBits = 15
+ )
+ for i := 0; i < len(elems); i++ {
+ ce := elems[i]
+ p := ce[0]
+ if p < cjkPrimaryStart {
+ continue
+ }
+ if p > 0xFFFF {
+ return elems, fmt.Errorf("found primary weight %X; should be <= 0xFFFF", p)
+ }
+ if p >= illegalPrimary {
+ ce[0] = illegalOffset + p - illegalPrimary
+ } else {
+ if i+1 >= len(elems) {
+ return elems, fmt.Errorf("second part of double primary weight missing: %v", elems)
+ }
+ if elems[i+1][0]&lowBitsFlag == 0 {
+ return elems, fmt.Errorf("malformed second part of double primary weight: %v", elems)
+ }
+ np := ((p & highBitsMask) << shiftBits) + elems[i+1][0]&lowBitsMask
+ switch {
+ case p < rarePrimaryStart:
+ np += commonUnifiedOffset
+ case p < otherPrimaryStart:
+ np += rareUnifiedOffset
+ default:
+ p += otherOffset
+ }
+ ce[0] = np
+ for j := i + 1; j+1 < len(elems); j++ {
+ elems[j] = elems[j+1]
+ }
+ elems = elems[:len(elems)-1]
+ }
+ }
+ return elems, nil
+}
+
+// nextWeight computes the first possible collation weights following elems
+// for the given level.
+func nextWeight(level collate.Level, elems [][]int) [][]int {
+ nce := make([][]int, len(elems))
+ copy(nce, elems)
+
+ if level != collate.Identity {
+ nce[0] = make([]int, len(elems[0]))
+ copy(nce[0], elems[0])
+ nce[0][level]++
+ if level < collate.Secondary {
+ nce[0][collate.Secondary] = defaultSecondary
+ }
+ if level < collate.Tertiary {
+ nce[0][collate.Tertiary] = defaultTertiary
+ }
+ }
+ return nce
+}
+
+func nextVal(elems [][]int, i int, level collate.Level) (index, value int) {
+ for ; i < len(elems) && elems[i][level] == 0; i++ {
+ }
+ if i < len(elems) {
+ return i, elems[i][level]
+ }
+ return i, 0
+}
+
+// compareWeights returns -1 if a < b, 1 if a > b, or 0 otherwise.
+// It also returns the collation level at which the difference is found.
+func compareWeights(a, b [][]int) (result int, level collate.Level) {
+ for level := collate.Primary; level < collate.Identity; level++ {
+ var va, vb int
+ for ia, ib := 0, 0; ia < len(a) || ib < len(b); ia, ib = ia+1, ib+1 {
+ ia, va = nextVal(a, ia, level)
+ ib, vb = nextVal(b, ib, level)
+ if va != vb {
+ if va < vb {
+ return -1, level
+ } else {
+ return 1, level
+ }
+ }
+ }
+ }
+ return 0, collate.Identity
+}
+
+func equalCE(a, b []int) bool {
+ if len(a) != len(b) {
+ return false
+ }
+ for i := 0; i < 3; i++ {
+ if b[i] != a[i] {
+ return false
+ }
+ }
+ return true
+}
+
+func equalCEArrays(a, b [][]int) bool {
+ if len(a) != len(b) {
+ return false
+ }
+ for i := range a {
+ if !equalCE(a[i], b[i]) {
+ return false
+ }
+ }
+ return true
+}
diff --git a/libgo/go/exp/locale/collate/build/colelem_test.go b/libgo/go/exp/locale/collate/build/colelem_test.go
new file mode 100644
index 00000000000..28d7c894dc2
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/colelem_test.go
@@ -0,0 +1,197 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "exp/locale/collate"
+ "testing"
+)
+
+type ceTest struct {
+ f func(in []int) (uint32, error)
+ arg []int
+ val uint32
+}
+
+func normalCE(in []int) (ce uint32, err error) {
+ return makeCE(in)
+}
+
+func expandCE(in []int) (ce uint32, err error) {
+ return makeExpandIndex(in[0])
+}
+
+func contractCE(in []int) (ce uint32, err error) {
+ return makeContractIndex(ctHandle{in[0], in[1]}, in[2])
+}
+
+func decompCE(in []int) (ce uint32, err error) {
+ return makeDecompose(in[0], in[1])
+}
+
+var ceTests = []ceTest{
+ {normalCE, []int{0, 0, 0}, 0x80000000},
+ {normalCE, []int{0, 0x28, 3}, 0x80002803},
+ {normalCE, []int{100, defaultSecondary, 3}, 0x0000C803},
+ // non-ignorable primary with non-default secondary
+ {normalCE, []int{100, 0x28, defaultTertiary}, 0x40006428},
+ {normalCE, []int{100, defaultSecondary + 8, 3}, 0x0000C903},
+ {normalCE, []int{100, 0, 3}, 0xFFFF}, // non-ignorable primary with non-supported secondary
+ {normalCE, []int{100, 1, 3}, 0xFFFF},
+ {normalCE, []int{1 << maxPrimaryBits, defaultSecondary, 0}, 0xFFFF},
+ {normalCE, []int{0, 1 << maxSecondaryBits, 0}, 0xFFFF},
+ {normalCE, []int{100, defaultSecondary, 1 << maxTertiaryBits}, 0xFFFF},
+
+ {contractCE, []int{0, 0, 0}, 0xC0000000},
+ {contractCE, []int{1, 1, 1}, 0xC0010011},
+ {contractCE, []int{1, (1 << maxNBits) - 1, 1}, 0xC001001F},
+ {contractCE, []int{(1 << maxTrieIndexBits) - 1, 1, 1}, 0xC001FFF1},
+ {contractCE, []int{1, 1, (1 << maxContractOffsetBits) - 1}, 0xDFFF0011},
+ {contractCE, []int{1, (1 << maxNBits), 1}, 0xFFFF},
+ {contractCE, []int{(1 << maxTrieIndexBits), 1, 1}, 0xFFFF},
+ {contractCE, []int{1, (1 << maxContractOffsetBits), 1}, 0xFFFF},
+
+ {expandCE, []int{0}, 0xE0000000},
+ {expandCE, []int{5}, 0xE0000005},
+ {expandCE, []int{(1 << maxExpandIndexBits) - 1}, 0xE000FFFF},
+ {expandCE, []int{1 << maxExpandIndexBits}, 0xFFFF},
+
+ {decompCE, []int{0, 0}, 0xF0000000},
+ {decompCE, []int{1, 1}, 0xF0000101},
+ {decompCE, []int{0x1F, 0x1F}, 0xF0001F1F},
+ {decompCE, []int{256, 0x1F}, 0xFFFF},
+ {decompCE, []int{0x1F, 256}, 0xFFFF},
+}
+
+func TestColElem(t *testing.T) {
+ for i, tt := range ceTests {
+ in := make([]int, len(tt.arg))
+ copy(in, tt.arg)
+ ce, err := tt.f(in)
+ if tt.val == 0xFFFF {
+ if err == nil {
+ t.Errorf("%d: expected error for args %x", i, tt.arg)
+ }
+ continue
+ }
+ if err != nil {
+ t.Errorf("%d: unexpected error: %v", i, err.Error())
+ }
+ if ce != tt.val {
+ t.Errorf("%d: colElem=%X; want %X", i, ce, tt.val)
+ }
+ }
+}
+
+type weightsTest struct {
+ a, b [][]int
+ level collate.Level
+ result int
+}
+
+var nextWeightTests = []weightsTest{
+ {
+ a: [][]int{{100, 20, 5, 0}},
+ b: [][]int{{101, defaultSecondary, defaultTertiary, 0}},
+ level: collate.Primary,
+ },
+ {
+ a: [][]int{{100, 20, 5, 0}},
+ b: [][]int{{100, 21, defaultTertiary, 0}},
+ level: collate.Secondary,
+ },
+ {
+ a: [][]int{{100, 20, 5, 0}},
+ b: [][]int{{100, 20, 6, 0}},
+ level: collate.Tertiary,
+ },
+ {
+ a: [][]int{{100, 20, 5, 0}},
+ b: [][]int{{100, 20, 5, 0}},
+ level: collate.Identity,
+ },
+}
+
+var extra = []int{200, 32, 8, 0}
+
+func TestNextWeight(t *testing.T) {
+ for i, tt := range nextWeightTests {
+ test := func(tt weightsTest, a, gold [][]int) {
+ res := nextWeight(tt.level, a)
+ if !equalCEArrays(gold, res) {
+ t.Errorf("%d: expected weights %d; found %d", i, tt.b, res)
+ }
+ }
+ test(tt, tt.a, tt.b)
+ test(tt, append(tt.a, extra), append(tt.b, extra))
+ }
+}
+
+var compareTests = []weightsTest{
+ {
+ [][]int{{100, 20, 5, 0}},
+ [][]int{{100, 20, 5, 0}},
+ collate.Identity,
+ 0,
+ },
+ {
+ [][]int{{100, 20, 5, 0}, extra},
+ [][]int{{100, 20, 5, 1}},
+ collate.Primary,
+ 1,
+ },
+ {
+ [][]int{{100, 20, 5, 0}},
+ [][]int{{101, 20, 5, 0}},
+ collate.Primary,
+ -1,
+ },
+ {
+ [][]int{{101, 20, 5, 0}},
+ [][]int{{100, 20, 5, 0}},
+ collate.Primary,
+ 1,
+ },
+ {
+ [][]int{{100, 0, 0, 0}, {0, 20, 5, 0}},
+ [][]int{{0, 20, 5, 0}, {100, 0, 0, 0}},
+ collate.Identity,
+ 0,
+ },
+ {
+ [][]int{{100, 20, 5, 0}},
+ [][]int{{100, 21, 5, 0}},
+ collate.Secondary,
+ -1,
+ },
+ {
+ [][]int{{100, 20, 5, 0}},
+ [][]int{{100, 20, 2, 0}},
+ collate.Tertiary,
+ 1,
+ },
+ {
+ [][]int{{100, 20, 5, 1}},
+ [][]int{{100, 20, 5, 2}},
+ collate.Quaternary,
+ -1,
+ },
+}
+
+func TestCompareWeights(t *testing.T) {
+ for i, tt := range compareTests {
+ test := func(tt weightsTest, a, b [][]int) {
+ res, level := compareWeights(a, b)
+ if res != tt.result {
+ t.Errorf("%d: expected comparisson result %d; found %d", i, tt.result, res)
+ }
+ if level != tt.level {
+ t.Errorf("%d: expected level %d; found %d", i, tt.level, level)
+ }
+ }
+ test(tt, tt.a, tt.b)
+ test(tt, append(tt.a, extra), append(tt.b, extra))
+ }
+}
diff --git a/libgo/go/exp/locale/collate/build/contract.go b/libgo/go/exp/locale/collate/build/contract.go
new file mode 100644
index 00000000000..f7cf64a7309
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/contract.go
@@ -0,0 +1,307 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "fmt"
+ "io"
+ "reflect"
+ "sort"
+ "strings"
+)
+
+// This file contains code for detecting contractions and generating
+// the necessary tables.
+// Any Unicode Collation Algorithm (UCA) table entry that has more than
+// one rune one the left-hand side is called a contraction.
+// See http://www.unicode.org/reports/tr10/#Contractions for more details.
+//
+// We define the following terms:
+// initial: a rune that appears as the first rune in a contraction.
+// suffix: a sequence of runes succeeding the initial rune
+// in a given contraction.
+// non-initial: a rune that appears in a suffix.
+//
+// A rune may be both a initial and a non-initial and may be so in
+// many contractions. An initial may typically also appear by itself.
+// In case of ambiguities, the UCA requires we match the longest
+// contraction.
+//
+// Many contraction rules share the same set of possible suffixes.
+// We store sets of suffixes in a trie that associates an index with
+// each suffix in the set. This index can be used to look up a
+// collation element associated with the (starter rune, suffix) pair.
+//
+// The trie is defined on a UTF-8 byte sequence.
+// The overall trie is represented as an array of ctEntries. Each node of the trie
+// is represented as a subsequence of ctEntries, where each entry corresponds to
+// a possible match of a next character in the search string. An entry
+// also includes the length and offset to the next sequence of entries
+// to check in case of a match.
+
+const (
+ final = 0
+ noIndex = 0xFF
+)
+
+// ctEntry associates to a matching byte an offset and/or next sequence of
+// bytes to check. A ctEntry c is called final if a match means that the
+// longest suffix has been found. An entry c is final if c.n == 0.
+// A single final entry can match a range of characters to an offset.
+// A non-final entry always matches a single byte. Note that a non-final
+// entry might still resemble a completed suffix.
+// Examples:
+// The suffix strings "ab" and "ac" can be represented as:
+// []ctEntry{
+// {'a', 1, 1, noIndex}, // 'a' by itself does not match, so i is 0xFF.
+// {'b', 'c', 0, 1}, // "ab" -> 1, "ac" -> 2
+// }
+//
+// The suffix strings "ab", "abc", "abd", and "abcd" can be represented as:
+// []ctEntry{
+// {'a', 1, 1, noIndex}, // 'a' must be followed by 'b'.
+// {'b', 1, 2, 1}, // "ab" -> 1, may be followed by 'c' or 'd'.
+// {'d', 'd', final, 3}, // "abd" -> 3
+// {'c', 4, 1, 2}, // "abc" -> 2, may be followed by 'd'.
+// {'d', 'd', final, 4}, // "abcd" -> 4
+// }
+// See genStateTests in contract_test.go for more examples.
+type ctEntry struct {
+ l uint8 // non-final: byte value to match; final: lowest match in range.
+ h uint8 // non-final: relative index to next block; final: highest match in range.
+ n uint8 // non-final: length of next block; final: final
+ i uint8 // result offset. Will be noIndex if more bytes are needed to complete.
+}
+
+// contractTrieSet holds a set of contraction tries. The tries are stored
+// consecutively in the entry field.
+type contractTrieSet []struct{ l, h, n, i uint8 }
+
+// ctHandle is used to identify a trie in the trie set, consisting in an offset
+// in the array and the size of the first node.
+type ctHandle struct {
+ index, n int
+}
+
+// appendTrie adds a new trie for the given suffixes to the trie set and returns
+// a handle to it. The handle will be invalid on error.
+func (ct *contractTrieSet) appendTrie(suffixes []string) (ctHandle, error) {
+ es := make([]stridx, len(suffixes))
+ for i, s := range suffixes {
+ es[i].str = s
+ }
+ sort.Sort(offsetSort(es))
+ for i := range es {
+ es[i].index = i + 1
+ }
+ sort.Sort(genidxSort(es))
+ i := len(*ct)
+ n, err := ct.genStates(es)
+ if err != nil {
+ *ct = (*ct)[:i]
+ return ctHandle{}, err
+ }
+ return ctHandle{i, n}, nil
+}
+
+// genStates generates ctEntries for a given suffix set and returns
+// the number of entries for the first node.
+func (ct *contractTrieSet) genStates(sis []stridx) (int, error) {
+ if len(sis) == 0 {
+ return 0, fmt.Errorf("genStates: list of suffices must be non-empty")
+ }
+ start := len(*ct)
+ // create entries for differing first bytes.
+ for _, si := range sis {
+ s := si.str
+ if len(s) == 0 {
+ continue
+ }
+ added := false
+ c := s[0]
+ if len(s) > 1 {
+ for j := len(*ct) - 1; j >= start; j-- {
+ if (*ct)[j].l == c {
+ added = true
+ break
+ }
+ }
+ if !added {
+ *ct = append(*ct, ctEntry{l: c, i: noIndex})
+ }
+ } else {
+ for j := len(*ct) - 1; j >= start; j-- {
+ // Update the offset for longer suffixes with the same byte.
+ if (*ct)[j].l == c {
+ (*ct)[j].i = uint8(si.index)
+ added = true
+ }
+ // Extend range of final ctEntry, if possible.
+ if (*ct)[j].h+1 == c {
+ (*ct)[j].h = c
+ added = true
+ }
+ }
+ if !added {
+ *ct = append(*ct, ctEntry{l: c, h: c, n: final, i: uint8(si.index)})
+ }
+ }
+ }
+ n := len(*ct) - start
+ // Append nodes for the remainder of the suffixes for each ctEntry.
+ sp := 0
+ for i, end := start, len(*ct); i < end; i++ {
+ fe := (*ct)[i]
+ if fe.h == 0 { // uninitialized non-final
+ ln := len(*ct) - start - n
+ if ln > 0xFF {
+ return 0, fmt.Errorf("genStates: relative block offset too large: %d > 255", ln)
+ }
+ fe.h = uint8(ln)
+ // Find first non-final strings with same byte as current entry.
+ for ; sis[sp].str[0] != fe.l; sp++ {
+ }
+ se := sp + 1
+ for ; se < len(sis) && len(sis[se].str) > 1 && sis[se].str[0] == fe.l; se++ {
+ }
+ sl := sis[sp:se]
+ sp = se
+ for i, si := range sl {
+ sl[i].str = si.str[1:]
+ }
+ nn, err := ct.genStates(sl)
+ if err != nil {
+ return 0, err
+ }
+ fe.n = uint8(nn)
+ (*ct)[i] = fe
+ }
+ }
+ sort.Sort(entrySort((*ct)[start : start+n]))
+ return n, nil
+}
+
+// There may be both a final and non-final entry for a byte if the byte
+// is implied in a range of matches in the final entry.
+// We need to ensure that the non-final entry comes first in that case.
+type entrySort contractTrieSet
+
+func (fe entrySort) Len() int { return len(fe) }
+func (fe entrySort) Swap(i, j int) { fe[i], fe[j] = fe[j], fe[i] }
+func (fe entrySort) Less(i, j int) bool {
+ return fe[i].l > fe[j].l
+}
+
+// stridx is used for sorting suffixes and their associated offsets.
+type stridx struct {
+ str string
+ index int
+}
+
+// For computing the offsets, we first sort by size, and then by string.
+// This ensures that strings that only differ in the last byte by 1
+// are sorted consecutively in increasing order such that they can
+// be packed as a range in a final ctEntry.
+type offsetSort []stridx
+
+func (si offsetSort) Len() int { return len(si) }
+func (si offsetSort) Swap(i, j int) { si[i], si[j] = si[j], si[i] }
+func (si offsetSort) Less(i, j int) bool {
+ if len(si[i].str) != len(si[j].str) {
+ return len(si[i].str) > len(si[j].str)
+ }
+ return si[i].str < si[j].str
+}
+
+// For indexing, we want to ensure that strings are sorted in string order, where
+// for strings with the same prefix, we put longer strings before shorter ones.
+type genidxSort []stridx
+
+func (si genidxSort) Len() int { return len(si) }
+func (si genidxSort) Swap(i, j int) { si[i], si[j] = si[j], si[i] }
+func (si genidxSort) Less(i, j int) bool {
+ if strings.HasPrefix(si[j].str, si[i].str) {
+ return false
+ }
+ if strings.HasPrefix(si[i].str, si[j].str) {
+ return true
+ }
+ return si[i].str < si[j].str
+}
+
+// lookup matches the longest suffix in str and returns the associated offset
+// and the number of bytes consumed.
+func (ct *contractTrieSet) lookup(h ctHandle, str []byte) (index, ns int) {
+ states := (*ct)[h.index:]
+ p := 0
+ n := h.n
+ for i := 0; i < n && p < len(str); {
+ e := states[i]
+ c := str[p]
+ if c >= e.l {
+ if e.l == c {
+ p++
+ if e.i != noIndex {
+ index, ns = int(e.i), p
+ }
+ if e.n != final {
+ // set to new state
+ i, states, n = 0, states[int(e.h)+n:], int(e.n)
+ } else {
+ return
+ }
+ continue
+ } else if e.n == final && c <= e.h {
+ p++
+ return int(c-e.l) + int(e.i), p
+ }
+ }
+ i++
+ }
+ return
+}
+
+// print writes the contractTrieSet t as compilable Go code to w. It returns
+// the total number of bytes written and the size of the resulting data structure in bytes.
+func (t *contractTrieSet) print(w io.Writer, name string) (n, size int, err error) {
+ update3 := func(nn, sz int, e error) {
+ n += nn
+ if err == nil {
+ err = e
+ }
+ size += sz
+ }
+ update2 := func(nn int, e error) { update3(nn, 0, e) }
+
+ update3(t.printArray(w, name))
+ update2(fmt.Fprintf(w, "var %sContractTrieSet = ", name))
+ update3(t.printStruct(w, name))
+ update2(fmt.Fprintln(w))
+ return
+}
+
+func (ct contractTrieSet) printArray(w io.Writer, name string) (n, size int, err error) {
+ p := func(f string, a ...interface{}) {
+ nn, e := fmt.Fprintf(w, f, a...)
+ n += nn
+ if err == nil {
+ err = e
+ }
+ }
+ size = len(ct) * 4
+ p("// %sCTEntries: %d entries, %d bytes\n", name, len(ct), size)
+ p("var %sCTEntries = [%d]struct{l,h,n,i uint8}{\n", name, len(ct))
+ for _, fe := range ct {
+ p("\t{0x%X, 0x%X, %d, %d},\n", fe.l, fe.h, fe.n, fe.i)
+ }
+ p("}\n")
+ return
+}
+
+func (ct contractTrieSet) printStruct(w io.Writer, name string) (n, size int, err error) {
+ n, err = fmt.Fprintf(w, "contractTrieSet( %sCTEntries[:] )", name)
+ size = int(reflect.TypeOf(ct).Size())
+ return
+}
diff --git a/libgo/go/exp/locale/collate/build/contract_test.go b/libgo/go/exp/locale/collate/build/contract_test.go
new file mode 100644
index 00000000000..0fc944d34b5
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/contract_test.go
@@ -0,0 +1,264 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "bytes"
+ "sort"
+ "testing"
+)
+
+var largetosmall = []stridx{
+ {"a", 5},
+ {"ab", 4},
+ {"abc", 3},
+ {"abcd", 2},
+ {"abcde", 1},
+ {"abcdef", 0},
+}
+
+var offsetSortTests = [][]stridx{
+ {
+ {"bcde", 1},
+ {"bc", 5},
+ {"ab", 4},
+ {"bcd", 3},
+ {"abcd", 0},
+ {"abc", 2},
+ },
+ largetosmall,
+}
+
+func TestOffsetSort(t *testing.T) {
+ for i, st := range offsetSortTests {
+ sort.Sort(offsetSort(st))
+ for j, si := range st {
+ if j != si.index {
+ t.Errorf("%d: failed: %v", i, st)
+ }
+ }
+ }
+ for i, tt := range genStateTests {
+ // ensure input is well-formed
+ sort.Sort(offsetSort(tt.in))
+ for j, si := range tt.in {
+ if si.index != j+1 {
+ t.Errorf("%dth sort failed: %v", i, tt.in)
+ }
+ }
+ }
+}
+
+var genidxtest1 = []stridx{
+ {"bcde", 3},
+ {"bc", 6},
+ {"ab", 2},
+ {"bcd", 5},
+ {"abcd", 0},
+ {"abc", 1},
+ {"bcdf", 4},
+}
+
+var genidxSortTests = [][]stridx{
+ genidxtest1,
+ largetosmall,
+}
+
+func TestGenIdxSort(t *testing.T) {
+ for i, st := range genidxSortTests {
+ sort.Sort(genidxSort(st))
+ for j, si := range st {
+ if j != si.index {
+ t.Errorf("%dth sort failed %v", i, st)
+ break
+ }
+ }
+ }
+}
+
+var entrySortTests = []contractTrieSet{
+ {
+ {10, 0, 1, 3},
+ {99, 0, 1, 0},
+ {20, 50, 0, 2},
+ {30, 0, 1, 1},
+ },
+}
+
+func TestEntrySort(t *testing.T) {
+ for i, et := range entrySortTests {
+ sort.Sort(entrySort(et))
+ for j, fe := range et {
+ if j != int(fe.i) {
+ t.Errorf("%dth sort failed %v", i, et)
+ break
+ }
+ }
+ }
+}
+
+type GenStateTest struct {
+ in []stridx
+ firstBlockLen int
+ out contractTrieSet
+}
+
+var genStateTests = []GenStateTest{
+ {[]stridx{
+ {"abc", 1},
+ },
+ 1,
+ contractTrieSet{
+ {'a', 0, 1, noIndex},
+ {'b', 0, 1, noIndex},
+ {'c', 'c', final, 1},
+ },
+ },
+ {[]stridx{
+ {"abc", 1},
+ {"abd", 2},
+ {"abe", 3},
+ },
+ 1,
+ contractTrieSet{
+ {'a', 0, 1, noIndex},
+ {'b', 0, 1, noIndex},
+ {'c', 'e', final, 1},
+ },
+ },
+ {[]stridx{
+ {"abc", 1},
+ {"ab", 2},
+ {"a", 3},
+ },
+ 1,
+ contractTrieSet{
+ {'a', 0, 1, 3},
+ {'b', 0, 1, 2},
+ {'c', 'c', final, 1},
+ },
+ },
+ {[]stridx{
+ {"abc", 1},
+ {"abd", 2},
+ {"ab", 3},
+ {"ac", 4},
+ {"a", 5},
+ {"b", 6},
+ },
+ 2,
+ contractTrieSet{
+ {'b', 'b', final, 6},
+ {'a', 0, 2, 5},
+ {'c', 'c', final, 4},
+ {'b', 0, 1, 3},
+ {'c', 'd', final, 1},
+ },
+ },
+ {[]stridx{
+ {"bcde", 2},
+ {"bc", 7},
+ {"ab", 6},
+ {"bcd", 5},
+ {"abcd", 1},
+ {"abc", 4},
+ {"bcdf", 3},
+ },
+ 2,
+ contractTrieSet{
+ {'b', 3, 1, noIndex},
+ {'a', 0, 1, noIndex},
+ {'b', 0, 1, 6},
+ {'c', 0, 1, 4},
+ {'d', 'd', final, 1},
+ {'c', 0, 1, 7},
+ {'d', 0, 1, 5},
+ {'e', 'f', final, 2},
+ },
+ },
+}
+
+func TestGenStates(t *testing.T) {
+ for i, tt := range genStateTests {
+ si := []stridx{}
+ for _, e := range tt.in {
+ si = append(si, e)
+ }
+ // ensure input is well-formed
+ sort.Sort(genidxSort(si))
+ ct := contractTrieSet{}
+ n, _ := ct.genStates(si)
+ if nn := tt.firstBlockLen; nn != n {
+ t.Errorf("%d: block len %v; want %v", i, n, nn)
+ }
+ if lv, lw := len(ct), len(tt.out); lv != lw {
+ t.Errorf("%d: len %v; want %v", i, lv, lw)
+ continue
+ }
+ for j, fe := range tt.out {
+ const msg = "%d:%d: value %s=%v; want %v"
+ if fe.l != ct[j].l {
+ t.Errorf(msg, i, j, "l", ct[j].l, fe.l)
+ }
+ if fe.h != ct[j].h {
+ t.Errorf(msg, i, j, "h", ct[j].h, fe.h)
+ }
+ if fe.n != ct[j].n {
+ t.Errorf(msg, i, j, "n", ct[j].n, fe.n)
+ }
+ if fe.i != ct[j].i {
+ t.Errorf(msg, i, j, "i", ct[j].i, fe.i)
+ }
+ }
+ }
+}
+
+func TestLookupContraction(t *testing.T) {
+ for i, tt := range genStateTests {
+ input := []string{}
+ for _, e := range tt.in {
+ input = append(input, e.str)
+ }
+ cts := contractTrieSet{}
+ h, _ := cts.appendTrie(input)
+ for j, si := range tt.in {
+ str := si.str
+ for _, s := range []string{str, str + "X"} {
+ msg := "%d:%d: %s(%s) %v; want %v"
+ idx, sn := cts.lookup(h, []byte(s))
+ if idx != si.index {
+ t.Errorf(msg, i, j, "index", s, idx, si.index)
+ }
+ if sn != len(str) {
+ t.Errorf(msg, i, j, "sn", s, sn, len(str))
+ }
+ }
+ }
+ }
+}
+
+func TestPrintContractionTrieSet(t *testing.T) {
+ testdata := contractTrieSet(genStateTests[4].out)
+ buf := &bytes.Buffer{}
+ testdata.print(buf, "test")
+ if contractTrieOutput != buf.String() {
+ t.Errorf("output differs; found\n%s", buf.String())
+ println(string(buf.Bytes()))
+ }
+}
+
+const contractTrieOutput = `// testCTEntries: 8 entries, 32 bytes
+var testCTEntries = [8]struct{l,h,n,i uint8}{
+ {0x62, 0x3, 1, 255},
+ {0x61, 0x0, 1, 255},
+ {0x62, 0x0, 1, 6},
+ {0x63, 0x0, 1, 4},
+ {0x64, 0x64, 0, 1},
+ {0x63, 0x0, 1, 7},
+ {0x64, 0x0, 1, 5},
+ {0x65, 0x66, 0, 2},
+}
+var testContractTrieSet = contractTrieSet( testCTEntries[:] )
+`
diff --git a/libgo/go/exp/locale/collate/build/order.go b/libgo/go/exp/locale/collate/build/order.go
new file mode 100644
index 00000000000..7c550d59ba8
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/order.go
@@ -0,0 +1,309 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "exp/locale/collate"
+ "fmt"
+ "log"
+ "sort"
+ "strings"
+ "unicode"
+)
+
+type logicalAnchor int
+
+const (
+ firstAnchor logicalAnchor = -1
+ noAnchor = 0
+ lastAnchor = 1
+)
+
+// entry is used to keep track of a single entry in the collation element table
+// during building. Examples of entries can be found in the Default Unicode
+// Collation Element Table.
+// See http://www.unicode.org/Public/UCA/6.0.0/allkeys.txt.
+type entry struct {
+ runes []rune
+ elems [][]int // the collation elements for runes
+ str string // same as string(runes)
+
+ // prev, next, and level are used to keep track of tailorings.
+ prev, next *entry
+ level collate.Level // next differs at this level
+
+ decompose bool // can use NFKD decomposition to generate elems
+ exclude bool // do not include in table
+ logical logicalAnchor
+
+ expansionIndex int // used to store index into expansion table
+ contractionHandle ctHandle
+ contractionIndex int // index into contraction elements
+}
+
+func (e *entry) String() string {
+ return fmt.Sprintf("%X -> %X (ch:%x; ci:%d, ei:%d)",
+ e.runes, e.elems, e.contractionHandle, e.contractionIndex, e.expansionIndex)
+}
+
+func (e *entry) skip() bool {
+ return e.contraction()
+}
+
+func (e *entry) expansion() bool {
+ return !e.decompose && len(e.elems) > 1
+}
+
+func (e *entry) contraction() bool {
+ return len(e.runes) > 1
+}
+
+func (e *entry) contractionStarter() bool {
+ return e.contractionHandle.n != 0
+}
+
+// nextIndexed gets the next entry that needs to be stored in the table.
+// It returns the entry and the collation level at which the next entry differs
+// from the current entry.
+// Entries that can be explicitly derived and logical reset positions are
+// examples of entries that will not be indexed.
+func (e *entry) nextIndexed() (*entry, collate.Level) {
+ level := e.level
+ for e = e.next; e != nil && e.exclude; e = e.next {
+ if e.level < level {
+ level = e.level
+ }
+ }
+ return e, level
+}
+
+// remove unlinks entry e from the sorted chain and clears the collation
+// elements. e may not be at the front or end of the list. This should always
+// be the case, as the front and end of the list are always logical anchors,
+// which may not be removed.
+func (e *entry) remove() {
+ if e.logical != noAnchor {
+ log.Fatalf("may not remove anchor %q", e.str)
+ }
+ if e.prev != nil {
+ e.prev.next = e.next
+ }
+ if e.next != nil {
+ e.next.prev = e.prev
+ }
+ e.elems = nil
+}
+
+// insertAfter inserts t after e.
+func (e *entry) insertAfter(n *entry) {
+ if e == n {
+ panic("e == anchor")
+ }
+ if e == nil {
+ panic("unexpected nil anchor")
+ }
+ n.remove()
+ n.decompose = false // redo decomposition test
+
+ n.next = e.next
+ n.prev = e
+ e.next.prev = n
+ e.next = n
+}
+
+func (e *entry) encodeBase() (ce uint32, err error) {
+ switch {
+ case e.expansion():
+ ce, err = makeExpandIndex(e.expansionIndex)
+ default:
+ if e.decompose {
+ log.Fatal("decompose should be handled elsewhere")
+ }
+ ce, err = makeCE(e.elems[0])
+ }
+ return
+}
+
+func (e *entry) encode() (ce uint32, err error) {
+ if e.skip() {
+ log.Fatal("cannot build colElem for entry that should be skipped")
+ }
+ switch {
+ case e.decompose:
+ t1 := e.elems[0][2]
+ t2 := 0
+ if len(e.elems) > 1 {
+ t2 = e.elems[1][2]
+ }
+ ce, err = makeDecompose(t1, t2)
+ case e.contractionStarter():
+ ce, err = makeContractIndex(e.contractionHandle, e.contractionIndex)
+ default:
+ if len(e.runes) > 1 {
+ log.Fatal("colElem: contractions are handled in contraction trie")
+ }
+ ce, err = e.encodeBase()
+ }
+ return
+}
+
+// entryLess returns true if a sorts before b and false otherwise.
+func entryLess(a, b *entry) bool {
+ if res, _ := compareWeights(a.elems, b.elems); res != 0 {
+ return res == -1
+ }
+ if a.logical != noAnchor {
+ return a.logical == firstAnchor
+ }
+ if b.logical != noAnchor {
+ return b.logical == lastAnchor
+ }
+ return a.str < b.str
+}
+
+type sortedEntries []*entry
+
+func (s sortedEntries) Len() int {
+ return len(s)
+}
+
+func (s sortedEntries) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s sortedEntries) Less(i, j int) bool {
+ return entryLess(s[i], s[j])
+}
+
+type ordering struct {
+ entryMap map[string]*entry
+ ordered []*entry
+ handle *trieHandle
+}
+
+// insert inserts e into both entryMap and ordered.
+// Note that insert simply appends e to ordered. To reattain a sorted
+// order, o.sort() should be called.
+func (o *ordering) insert(e *entry) {
+ o.entryMap[e.str] = e
+ o.ordered = append(o.ordered, e)
+}
+
+// newEntry creates a new entry for the given info and inserts it into
+// the index.
+func (o *ordering) newEntry(s string, ces [][]int) *entry {
+ e := &entry{
+ runes: []rune(s),
+ elems: ces,
+ str: s,
+ }
+ o.insert(e)
+ return e
+}
+
+// find looks up and returns the entry for the given string.
+// It returns nil if str is not in the index and if an implicit value
+// cannot be derived, that is, if str represents more than one rune.
+func (o *ordering) find(str string) *entry {
+ e := o.entryMap[str]
+ if e == nil {
+ r := []rune(str)
+ if len(r) == 1 {
+ e = o.newEntry(string(r[0]), [][]int{
+ {
+ implicitPrimary(r[0]),
+ defaultSecondary,
+ defaultTertiary,
+ int(r[0]),
+ },
+ })
+ e.exclude = true // do not index implicits
+ }
+ }
+ return e
+}
+
+// makeRootOrdering returns a newly initialized ordering value and populates
+// it with a set of logical reset points that can be used as anchors.
+// The anchors first_tertiary_ignorable and __END__ will always sort at
+// the beginning and end, respectively. This means that prev and next are non-nil
+// for any indexed entry.
+func makeRootOrdering() ordering {
+ const max = unicode.MaxRune
+ o := ordering{
+ entryMap: make(map[string]*entry),
+ }
+ insert := func(typ logicalAnchor, s string, ce []int) {
+ // Use key format as used in UCA rules.
+ e := o.newEntry(fmt.Sprintf("[%s]", s), [][]int{ce})
+ // Also add index entry for XML format.
+ o.entryMap[fmt.Sprintf("<%s/>", strings.Replace(s, " ", "_", -1))] = e
+ e.runes = nil
+ e.exclude = true
+ e.logical = typ
+ }
+ insert(firstAnchor, "first tertiary ignorable", []int{0, 0, 0, 0})
+ insert(lastAnchor, "last tertiary ignorable", []int{0, 0, 0, max})
+ insert(lastAnchor, "last primary ignorable", []int{0, defaultSecondary, defaultTertiary, max})
+ insert(lastAnchor, "last non ignorable", []int{maxPrimary, defaultSecondary, defaultTertiary, max})
+ insert(lastAnchor, "__END__", []int{1 << maxPrimaryBits, defaultSecondary, defaultTertiary, max})
+ return o
+}
+
+// clone copies all ordering of es into a new ordering value.
+func (o *ordering) clone() *ordering {
+ o.sort()
+ oo := ordering{
+ entryMap: make(map[string]*entry),
+ }
+ for _, e := range o.ordered {
+ ne := &entry{
+ runes: e.runes,
+ elems: e.elems,
+ str: e.str,
+ decompose: e.decompose,
+ exclude: e.exclude,
+ logical: e.logical,
+ }
+ oo.insert(ne)
+ }
+ oo.sort() // link all ordering.
+ return &oo
+}
+
+// front returns the first entry to be indexed.
+// It assumes that sort() has been called.
+func (o *ordering) front() *entry {
+ e := o.ordered[0]
+ if e.prev != nil {
+ log.Panicf("unexpected first entry: %v", e)
+ }
+ // The first entry is always a logical position, which should not be indexed.
+ e, _ = e.nextIndexed()
+ return e
+}
+
+// sort sorts all ordering based on their collation elements and initializes
+// the prev, next, and level fields accordingly.
+func (o *ordering) sort() {
+ sort.Sort(sortedEntries(o.ordered))
+ l := o.ordered
+ for i := 1; i < len(l); i++ {
+ k := i - 1
+ l[k].next = l[i]
+ _, l[k].level = compareWeights(l[k].elems, l[i].elems)
+ l[i].prev = l[k]
+ }
+}
+
+// genColElems generates a collation element array from the runes in str. This
+// assumes that all collation elements have already been added to the Builder.
+func (o *ordering) genColElems(str string) [][]int {
+ elems := [][]int{}
+ for _, r := range []rune(str) {
+ elems = append(elems, o.find(string(r)).elems...)
+ }
+ return elems
+}
diff --git a/libgo/go/exp/locale/collate/build/order_test.go b/libgo/go/exp/locale/collate/build/order_test.go
new file mode 100644
index 00000000000..e6fdfa38443
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/order_test.go
@@ -0,0 +1,197 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "exp/locale/collate"
+ "strconv"
+ "testing"
+)
+
+type entryTest struct {
+ f func(in []int) (uint32, error)
+ arg []int
+ val uint32
+}
+
+// makeList returns a list of entries of length n+2, with n normal
+// entries plus a leading and trailing anchor.
+func makeList(n int) []*entry {
+ es := make([]*entry, n+2)
+ weights := [][]int{{100, 20, 5, 0}}
+ for i := range es {
+ runes := []rune{rune(i)}
+ es[i] = &entry{
+ runes: runes,
+ elems: weights,
+ }
+ weights = nextWeight(collate.Primary, weights)
+ }
+ for i := 1; i < len(es); i++ {
+ es[i-1].next = es[i]
+ es[i].prev = es[i-1]
+ _, es[i-1].level = compareWeights(es[i-1].elems, es[i].elems)
+ }
+ es[0].exclude = true
+ es[0].logical = firstAnchor
+ es[len(es)-1].exclude = true
+ es[len(es)-1].logical = lastAnchor
+ return es
+}
+
+func TestNextIndexed(t *testing.T) {
+ const n = 5
+ es := makeList(n)
+ for i := int64(0); i < 1<<n; i++ {
+ mask := strconv.FormatInt(i+(1<<n), 2)
+ for i, c := range mask {
+ es[i].exclude = c == '1'
+ }
+ e := es[0]
+ for i, c := range mask {
+ if c == '0' {
+ e, _ = e.nextIndexed()
+ if e != es[i] {
+ t.Errorf("%d: expected entry %d; found %d", i, es[i].elems, e.elems)
+ }
+ }
+ }
+ if e, _ = e.nextIndexed(); e != nil {
+ t.Errorf("%d: expected nil entry; found %d", i, e.elems)
+ }
+ }
+}
+
+func TestRemove(t *testing.T) {
+ const n = 5
+ for i := int64(0); i < 1<<n; i++ {
+ es := makeList(n)
+ mask := strconv.FormatInt(i+(1<<n), 2)
+ for i, c := range mask {
+ if c == '0' {
+ es[i].remove()
+ }
+ }
+ e := es[0]
+ for i, c := range mask {
+ if c == '1' {
+ if e != es[i] {
+ t.Errorf("%d: expected entry %d; found %d", i, es[i].elems, e.elems)
+ }
+ e, _ = e.nextIndexed()
+ }
+ }
+ if e != nil {
+ t.Errorf("%d: expected nil entry; found %d", i, e.elems)
+ }
+ }
+}
+
+// nextPerm generates the next permutation of the array. The starting
+// permutation is assumed to be a list of integers sorted in increasing order.
+// It returns false if there are no more permuations left.
+func nextPerm(a []int) bool {
+ i := len(a) - 2
+ for ; i >= 0; i-- {
+ if a[i] < a[i+1] {
+ break
+ }
+ }
+ if i < 0 {
+ return false
+ }
+ for j := len(a) - 1; j >= i; j-- {
+ if a[j] > a[i] {
+ a[i], a[j] = a[j], a[i]
+ break
+ }
+ }
+ for j := i + 1; j < (len(a)+i+1)/2; j++ {
+ a[j], a[len(a)+i-j] = a[len(a)+i-j], a[j]
+ }
+ return true
+}
+
+func TestInsertAfter(t *testing.T) {
+ const n = 5
+ orig := makeList(n)
+ perm := make([]int, n)
+ for i := range perm {
+ perm[i] = i + 1
+ }
+ for ok := true; ok; ok = nextPerm(perm) {
+ es := makeList(n)
+ last := es[0]
+ for _, i := range perm {
+ last.insertAfter(es[i])
+ last = es[i]
+ }
+ e := es[0]
+ for _, i := range perm {
+ e, _ = e.nextIndexed()
+ if e.runes[0] != orig[i].runes[0] {
+ t.Errorf("%d:%d: expected entry %X; found %X", perm, i, orig[i].runes, e.runes)
+ break
+ }
+ }
+ }
+}
+
+type entryLessTest struct {
+ a, b *entry
+ res bool
+}
+
+var (
+ w1 = [][]int{{100, 20, 5, 5}}
+ w2 = [][]int{{101, 20, 5, 5}}
+)
+
+var entryLessTests = []entryLessTest{
+ {&entry{str: "a", elems: w1},
+ &entry{str: "a", elems: w1},
+ false,
+ },
+ {&entry{str: "a", elems: w1},
+ &entry{str: "a", elems: w2},
+ true,
+ },
+ {&entry{str: "a", elems: w1},
+ &entry{str: "b", elems: w1},
+ true,
+ },
+ {&entry{str: "a", elems: w2},
+ &entry{str: "a", elems: w1},
+ false,
+ },
+ {&entry{str: "c", elems: w1},
+ &entry{str: "b", elems: w1},
+ false,
+ },
+ {&entry{str: "a", elems: w1, logical: firstAnchor},
+ &entry{str: "a", elems: w1},
+ true,
+ },
+ {&entry{str: "a", elems: w1},
+ &entry{str: "b", elems: w1, logical: firstAnchor},
+ false,
+ },
+ {&entry{str: "b", elems: w1},
+ &entry{str: "a", elems: w1, logical: lastAnchor},
+ true,
+ },
+ {&entry{str: "a", elems: w1, logical: lastAnchor},
+ &entry{str: "c", elems: w1},
+ false,
+ },
+}
+
+func TestEntryLess(t *testing.T) {
+ for i, tt := range entryLessTests {
+ if res := entryLess(tt.a, tt.b); res != tt.res {
+ t.Errorf("%d: was %v; want %v", i, res, tt.res)
+ }
+ }
+}
diff --git a/libgo/go/exp/locale/collate/build/table.go b/libgo/go/exp/locale/collate/build/table.go
new file mode 100644
index 00000000000..0a290cd00b5
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/table.go
@@ -0,0 +1,136 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "fmt"
+ "io"
+ "reflect"
+)
+
+// table is an intermediate structure that roughly resembles the table in collate.
+// It implements the non-exported interface collate.tableInitializer
+type table struct {
+ index trie // main trie
+ root *trieHandle
+
+ // expansion info
+ expandElem []uint32
+
+ // contraction info
+ contractTries contractTrieSet
+ contractElem []uint32
+ maxContractLen int
+ variableTop uint32
+}
+
+func (t *table) TrieIndex() []uint16 {
+ return t.index.index
+}
+
+func (t *table) TrieValues() []uint32 {
+ return t.index.values
+}
+
+func (t *table) FirstBlockOffsets() (i, v uint16) {
+ return t.root.lookupStart, t.root.valueStart
+}
+
+func (t *table) ExpandElems() []uint32 {
+ return t.expandElem
+}
+
+func (t *table) ContractTries() []struct{ l, h, n, i uint8 } {
+ return t.contractTries
+}
+
+func (t *table) ContractElems() []uint32 {
+ return t.contractElem
+}
+
+func (t *table) MaxContractLen() int {
+ return t.maxContractLen
+}
+
+func (t *table) VariableTop() uint32 {
+ return t.variableTop
+}
+
+// print writes the table as Go compilable code to w. It prefixes the
+// variable names with name. It returns the number of bytes written
+// and the size of the resulting table.
+func (t *table) fprint(w io.Writer, name string) (n, size int, err error) {
+ update := func(nn, sz int, e error) {
+ n += nn
+ if err == nil {
+ err = e
+ }
+ size += sz
+ }
+ p := func(f string, a ...interface{}) {
+ nn, e := fmt.Fprintf(w, f, a...)
+ update(nn, 0, e)
+ }
+ // Write main table.
+ size += int(reflect.TypeOf(*t).Size())
+ p("var %sTable = table{\n", name)
+ update(t.index.printStruct(w, t.root, name))
+ p(",\n")
+ p("%sExpandElem[:],\n", name)
+ update(t.contractTries.printStruct(w, name))
+ p(",\n")
+ p("%sContractElem[:],\n", name)
+ p("%d,\n", t.maxContractLen)
+ p("0x%X,\n", t.variableTop)
+ p("}\n\n")
+
+ // Write arrays needed for the structure.
+ update(printColElems(w, t.expandElem, name+"ExpandElem"))
+ update(printColElems(w, t.contractElem, name+"ContractElem"))
+ update(t.index.printArrays(w, name))
+ update(t.contractTries.printArray(w, name))
+
+ p("// Total size of %sTable is %d bytes\n", name, size)
+ return
+}
+
+func (t *table) fprintIndex(w io.Writer, h *trieHandle) (n int, err error) {
+ p := func(f string, a ...interface{}) {
+ nn, e := fmt.Fprintf(w, f, a...)
+ n += nn
+ if err == nil {
+ err = e
+ }
+ }
+ p("tableIndex{\n")
+ p("\t\tlookupOffset: 0x%x,\n", h.lookupStart)
+ p("\t\tvaluesOffset: 0x%x,\n", h.valueStart)
+ p("\t}")
+ return
+}
+
+func printColElems(w io.Writer, a []uint32, name string) (n, sz int, err error) {
+ p := func(f string, a ...interface{}) {
+ nn, e := fmt.Fprintf(w, f, a...)
+ n += nn
+ if err == nil {
+ err = e
+ }
+ }
+ sz = len(a) * int(reflect.TypeOf(uint32(0)).Size())
+ p("// %s: %d entries, %d bytes\n", name, len(a), sz)
+ p("var %s = [%d]uint32 {", name, len(a))
+ for i, c := range a {
+ switch {
+ case i%64 == 0:
+ p("\n\t// Block %d, offset 0x%x\n", i/64, i)
+ case (i%64)%6 == 0:
+ p("\n\t")
+ }
+ p("0x%.8X, ", c)
+ }
+ p("\n}\n\n")
+ return
+}
diff --git a/libgo/go/exp/locale/collate/build/trie.go b/libgo/go/exp/locale/collate/build/trie.go
new file mode 100644
index 00000000000..d251a396533
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/trie.go
@@ -0,0 +1,281 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The trie in this file is used to associate the first full character
+// in a UTF-8 string to a collation element.
+// All but the last byte in a UTF-8 byte sequence are
+// used to look up offsets in the index table to be used for the next byte.
+// The last byte is used to index into a table of collation elements.
+// This file contains the code for the generation of the trie.
+
+package build
+
+import (
+ "fmt"
+ "hash/fnv"
+ "io"
+ "reflect"
+)
+
+const (
+ blockSize = 64
+ blockOffset = 2 // Substract 2 blocks to compensate for the 0x80 added to continuation bytes.
+)
+
+type trieHandle struct {
+ lookupStart uint16 // offset in table for first byte
+ valueStart uint16 // offset in table for first byte
+}
+
+type trie struct {
+ index []uint16
+ values []uint32
+}
+
+// trieNode is the intermediate trie structure used for generating a trie.
+type trieNode struct {
+ index []*trieNode
+ value []uint32
+ b byte
+ ref uint16
+}
+
+func newNode() *trieNode {
+ return &trieNode{
+ index: make([]*trieNode, 64),
+ value: make([]uint32, 128), // root node size is 128 instead of 64
+ }
+}
+
+func (n *trieNode) isInternal() bool {
+ return n.value != nil
+}
+
+func (n *trieNode) insert(r rune, value uint32) {
+ const maskx = 0x3F // mask out two most-significant bits
+ str := string(r)
+ if len(str) == 1 {
+ n.value[str[0]] = value
+ return
+ }
+ for i := 0; i < len(str)-1; i++ {
+ b := str[i] & maskx
+ if n.index == nil {
+ n.index = make([]*trieNode, blockSize)
+ }
+ nn := n.index[b]
+ if nn == nil {
+ nn = &trieNode{}
+ nn.b = b
+ n.index[b] = nn
+ }
+ n = nn
+ }
+ if n.value == nil {
+ n.value = make([]uint32, blockSize)
+ }
+ b := str[len(str)-1] & maskx
+ n.value[b] = value
+}
+
+type trieBuilder struct {
+ t *trie
+
+ roots []*trieHandle
+
+ lookupBlocks []*trieNode
+ valueBlocks []*trieNode
+
+ lookupBlockIdx map[uint32]*trieNode
+ valueBlockIdx map[uint32]*trieNode
+}
+
+func newTrieBuilder() *trieBuilder {
+ index := &trieBuilder{}
+ index.lookupBlocks = make([]*trieNode, 0)
+ index.valueBlocks = make([]*trieNode, 0)
+ index.lookupBlockIdx = make(map[uint32]*trieNode)
+ index.valueBlockIdx = make(map[uint32]*trieNode)
+ // The third nil is the default null block. The other two blocks
+ // are used to guarantee an offset of at least 3 for each block.
+ index.lookupBlocks = append(index.lookupBlocks, nil, nil, nil)
+ index.t = &trie{}
+ return index
+}
+
+func (b *trieBuilder) computeOffsets(n *trieNode) *trieNode {
+ hasher := fnv.New32()
+ if n.index != nil {
+ for i, nn := range n.index {
+ v := uint16(0)
+ if nn != nil {
+ nn = b.computeOffsets(nn)
+ n.index[i] = nn
+ v = nn.ref
+ }
+ hasher.Write([]byte{byte(v >> 8), byte(v)})
+ }
+ h := hasher.Sum32()
+ nn, ok := b.lookupBlockIdx[h]
+ if !ok {
+ n.ref = uint16(len(b.lookupBlocks)) - blockOffset
+ b.lookupBlocks = append(b.lookupBlocks, n)
+ b.lookupBlockIdx[h] = n
+ } else {
+ n = nn
+ }
+ } else {
+ for _, v := range n.value {
+ hasher.Write([]byte{byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)})
+ }
+ h := hasher.Sum32()
+ nn, ok := b.valueBlockIdx[h]
+ if !ok {
+ n.ref = uint16(len(b.valueBlocks)) - blockOffset
+ b.valueBlocks = append(b.valueBlocks, n)
+ b.valueBlockIdx[h] = n
+ } else {
+ n = nn
+ }
+ }
+ return n
+}
+
+func (b *trieBuilder) addStartValueBlock(n *trieNode) uint16 {
+ hasher := fnv.New32()
+ for _, v := range n.value[:2*blockSize] {
+ hasher.Write([]byte{byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)})
+ }
+ h := hasher.Sum32()
+ nn, ok := b.valueBlockIdx[h]
+ if !ok {
+ n.ref = uint16(len(b.valueBlocks))
+ b.valueBlocks = append(b.valueBlocks, n)
+ // Add a dummy block to accommodate the double block size.
+ b.valueBlocks = append(b.valueBlocks, nil)
+ b.valueBlockIdx[h] = n
+ } else {
+ n = nn
+ }
+ return n.ref
+}
+
+func genValueBlock(t *trie, n *trieNode) {
+ if n != nil {
+ for _, v := range n.value {
+ t.values = append(t.values, v)
+ }
+ }
+}
+
+func genLookupBlock(t *trie, n *trieNode) {
+ for _, nn := range n.index {
+ v := uint16(0)
+ if nn != nil {
+ v = nn.ref
+ }
+ t.index = append(t.index, v)
+ }
+}
+
+func (b *trieBuilder) addTrie(n *trieNode) *trieHandle {
+ h := &trieHandle{}
+ b.roots = append(b.roots, h)
+ h.valueStart = b.addStartValueBlock(n)
+ if len(b.roots) == 1 {
+ // We insert a null block after the first start value block.
+ // This ensures that continuation bytes UTF-8 sequences of length
+ // greater than 2 will automatically hit a null block if there
+ // was an undefined entry.
+ b.valueBlocks = append(b.valueBlocks, nil)
+ }
+ n = b.computeOffsets(n)
+ // Offset by one extra block as the first byte starts at 0xC0 instead of 0x80.
+ h.lookupStart = n.ref - 1
+ return h
+}
+
+// generate generates and returns the trie for n.
+func (b *trieBuilder) generate() (t *trie, err error) {
+ t = b.t
+ if len(b.valueBlocks) >= 1<<16 {
+ return nil, fmt.Errorf("maximum number of value blocks exceeded (%d > %d)", len(b.valueBlocks), 1<<16)
+ }
+ if len(b.lookupBlocks) >= 1<<16 {
+ return nil, fmt.Errorf("maximum number of lookup blocks exceeded (%d > %d)", len(b.lookupBlocks), 1<<16)
+ }
+ genValueBlock(t, b.valueBlocks[0])
+ genValueBlock(t, &trieNode{value: make([]uint32, 64)})
+ for i := 2; i < len(b.valueBlocks); i++ {
+ genValueBlock(t, b.valueBlocks[i])
+ }
+ n := &trieNode{index: make([]*trieNode, 64)}
+ genLookupBlock(t, n)
+ genLookupBlock(t, n)
+ genLookupBlock(t, n)
+ for i := 3; i < len(b.lookupBlocks); i++ {
+ genLookupBlock(t, b.lookupBlocks[i])
+ }
+ return b.t, nil
+}
+
+func (t *trie) printArrays(w io.Writer, name string) (n, size int, err error) {
+ p := func(f string, a ...interface{}) {
+ nn, e := fmt.Fprintf(w, f, a...)
+ n += nn
+ if err == nil {
+ err = e
+ }
+ }
+ nv := len(t.values)
+ p("// %sValues: %d entries, %d bytes\n", name, nv, nv*4)
+ p("// Block 2 is the null block.\n")
+ p("var %sValues = [%d]uint32 {", name, nv)
+ var printnewline bool
+ for i, v := range t.values {
+ if i%blockSize == 0 {
+ p("\n\t// Block %#x, offset %#x", i/blockSize, i)
+ }
+ if i%4 == 0 {
+ printnewline = true
+ }
+ if v != 0 {
+ if printnewline {
+ p("\n\t")
+ printnewline = false
+ }
+ p("%#04x:%#08x, ", i, v)
+ }
+ }
+ p("\n}\n\n")
+ ni := len(t.index)
+ p("// %sLookup: %d entries, %d bytes\n", name, ni, ni*2)
+ p("// Block 0 is the null block.\n")
+ p("var %sLookup = [%d]uint16 {", name, ni)
+ printnewline = false
+ for i, v := range t.index {
+ if i%blockSize == 0 {
+ p("\n\t// Block %#x, offset %#x", i/blockSize, i)
+ }
+ if i%8 == 0 {
+ printnewline = true
+ }
+ if v != 0 {
+ if printnewline {
+ p("\n\t")
+ printnewline = false
+ }
+ p("%#03x:%#02x, ", i, v)
+ }
+ }
+ p("\n}\n\n")
+ return n, nv*4 + ni*2, err
+}
+
+func (t *trie) printStruct(w io.Writer, handle *trieHandle, name string) (n, sz int, err error) {
+ const msg = "trie{ %sLookup[%d:], %sValues[%d:], %sLookup[:], %sValues[:]}"
+ n, err = fmt.Fprintf(w, msg, name, handle.lookupStart*blockSize, name, handle.valueStart*blockSize, name, name)
+ sz += int(reflect.TypeOf(trie{}).Size())
+ return
+}
diff --git a/libgo/go/exp/locale/collate/build/trie_test.go b/libgo/go/exp/locale/collate/build/trie_test.go
new file mode 100644
index 00000000000..11da56664d0
--- /dev/null
+++ b/libgo/go/exp/locale/collate/build/trie_test.go
@@ -0,0 +1,107 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+)
+
+// We take the smallest, largest and an arbitrary value for each
+// of the UTF-8 sequence lengths.
+var testRunes = []rune{
+ 0x01, 0x0C, 0x7F, // 1-byte sequences
+ 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
+}
+
+func makeTestTrie(t *testing.T) trie {
+ n := newNode()
+ for i, r := range testRunes {
+ n.insert(r, uint32(i))
+ }
+ idx := newTrieBuilder()
+ idx.addTrie(n)
+ tr, err := idx.generate()
+ if err != nil {
+ t.Errorf(err.Error())
+ }
+ return *tr
+}
+
+func TestGenerateTrie(t *testing.T) {
+ testdata := makeTestTrie(t)
+ buf := &bytes.Buffer{}
+ testdata.printArrays(buf, "test")
+ fmt.Fprintf(buf, "var testTrie = ")
+ testdata.printStruct(buf, &trieHandle{19, 0}, "test")
+ if output != buf.String() {
+ t.Error("output differs")
+ }
+}
+
+var output = `// testValues: 832 entries, 3328 bytes
+// Block 2 is the null block.
+var testValues = [832]uint32 {
+ // Block 0x0, offset 0x0
+ 0x000c:0x00000001,
+ // Block 0x1, offset 0x40
+ 0x007f:0x00000002,
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0x00c0:0x00000003,
+ // Block 0x4, offset 0x100
+ 0x0100:0x00000004,
+ // Block 0x5, offset 0x140
+ 0x0140:0x0000000c, 0x0141:0x0000000d, 0x0142:0x0000000e,
+ 0x0150:0x0000000f,
+ 0x0155:0x00000010,
+ // Block 0x6, offset 0x180
+ 0x01bf:0x00000005,
+ // Block 0x7, offset 0x1c0
+ 0x01c0:0x00000006,
+ // Block 0x8, offset 0x200
+ 0x0219:0x00000007,
+ // Block 0x9, offset 0x240
+ 0x027f:0x00000008,
+ // Block 0xa, offset 0x280
+ 0x0280:0x00000009,
+ // Block 0xb, offset 0x2c0
+ 0x02c1:0x0000000a,
+ // Block 0xc, offset 0x300
+ 0x033f:0x0000000b,
+}
+
+// testLookup: 640 entries, 1280 bytes
+// Block 0 is the null block.
+var testLookup = [640]uint16 {
+ // Block 0x0, offset 0x0
+ // Block 0x1, offset 0x40
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0x0e0:0x05, 0x0e6:0x06,
+ // Block 0x4, offset 0x100
+ 0x13f:0x07,
+ // Block 0x5, offset 0x140
+ 0x140:0x08, 0x144:0x09,
+ // Block 0x6, offset 0x180
+ 0x190:0x03,
+ // Block 0x7, offset 0x1c0
+ 0x1ff:0x0a,
+ // Block 0x8, offset 0x200
+ 0x20f:0x05,
+ // Block 0x9, offset 0x240
+ 0x242:0x01, 0x244:0x02,
+ 0x248:0x03,
+ 0x25f:0x04,
+ 0x260:0x01,
+ 0x26f:0x02,
+ 0x270:0x04, 0x274:0x06,
+}
+
+var testTrie = trie{ testLookup[1216:], testValues[0:], testLookup[:], testValues[:]}`
diff --git a/libgo/go/exp/locale/collate/colelem.go b/libgo/go/exp/locale/collate/colelem.go
new file mode 100644
index 00000000000..4af71f02de4
--- /dev/null
+++ b/libgo/go/exp/locale/collate/colelem.go
@@ -0,0 +1,183 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package collate
+
+import (
+ "unicode"
+)
+
+// weights holds the decoded weights per collation level.
+type weights struct {
+ primary uint32
+ secondary uint16
+ tertiary uint8
+ // TODO: compute quaternary on the fly or compress this value into 8 bits
+ // such that weights fit within 64bit.
+ quaternary uint32
+}
+
+const (
+ defaultSecondary = 0x20
+ defaultTertiary = 0x2
+ maxTertiary = 0x1F
+ maxQuaternary = 0x1FFFFF // 21 bits.
+)
+
+// colElem is a representation of a collation element.
+// In the typical case, a rune maps to a single collation element. If a rune
+// can be the start of a contraction or expands into multiple collation elements,
+// then the colElem that is associated with a rune will have a special form to represent
+// such m to n mappings. Such special colElems have a value >= 0x80000000.
+type colElem uint32
+
+const (
+ maxCE colElem = 0x80FFFFFF
+ minContract = 0xC0000000
+ maxContract = 0xDFFFFFFF
+ minExpand = 0xE0000000
+ maxExpand = 0xEFFFFFFF
+ minDecomp = 0xF0000000
+)
+
+type ceType int
+
+const (
+ ceNormal ceType = iota // ceNormal includes implicits (ce == 0)
+ ceContractionIndex // rune can be a start of a contraction
+ ceExpansionIndex // rune expands into a sequence of collation elements
+ ceDecompose // rune expands using NFKC decomposition
+)
+
+func (ce colElem) ctype() ceType {
+ if ce <= maxCE {
+ return ceNormal
+ }
+ if ce <= maxContract {
+ return ceContractionIndex
+ } else {
+ if ce <= maxExpand {
+ return ceExpansionIndex
+ }
+ return ceDecompose
+ }
+ panic("should not reach here")
+ return ceType(-1)
+}
+
+// For normal collation elements, we assume that a collation element either has
+// a primary or non-default secondary value, not both.
+// Collation elements with a primary value are of the form
+// 010ppppp pppppppp pppppppp ssssssss
+// - p* is primary collation value
+// - s* is the secondary collation value
+// or
+// 00pppppp pppppppp ppppppps sssttttt, where
+// - p* is primary collation value
+// - s* offset of secondary from default value.
+// - t* is the tertiary collation value
+// Collation elements with a secondary value are of the form
+// 10000000 0000ssss ssssssss tttttttt, where
+// - 16 BMP implicit -> weight
+// - 8 bit s
+// - default tertiary
+func splitCE(ce colElem) weights {
+ const primaryMask = 0x40000000
+ const secondaryMask = 0x80000000
+ w := weights{}
+ if ce&primaryMask != 0 {
+ w.tertiary = defaultTertiary
+ w.secondary = uint16(uint8(ce))
+ w.primary = uint32((ce >> 8) & 0x1FFFFF)
+ } else if ce&secondaryMask == 0 {
+ w.tertiary = uint8(ce & 0x1F)
+ ce >>= 5
+ w.secondary = defaultSecondary + uint16(ce&0xF)
+ ce >>= 4
+ w.primary = uint32(ce)
+ } else {
+ w.tertiary = uint8(ce)
+ w.secondary = uint16(ce >> 8)
+ }
+ return w
+}
+
+// For contractions, collation elements are of the form
+// 110bbbbb bbbbbbbb iiiiiiii iiiinnnn, where
+// - n* is the size of the first node in the contraction trie.
+// - i* is the index of the first node in the contraction trie.
+// - b* is the offset into the contraction collation element table.
+// See contract.go for details on the contraction trie.
+const (
+ maxNBits = 4
+ maxTrieIndexBits = 12
+ maxContractOffsetBits = 13
+)
+
+func splitContractIndex(ce colElem) (index, n, offset int) {
+ n = int(ce & (1<<maxNBits - 1))
+ ce >>= maxNBits
+ index = int(ce & (1<<maxTrieIndexBits - 1))
+ ce >>= maxTrieIndexBits
+ offset = int(ce & (1<<maxContractOffsetBits - 1))
+ return
+}
+
+// For expansions, colElems are of the form 11100000 00000000 bbbbbbbb bbbbbbbb,
+// where b* is the index into the expansion sequence table.
+const maxExpandIndexBits = 16
+
+func splitExpandIndex(ce colElem) (index int) {
+ return int(uint16(ce))
+}
+
+// Some runes can be expanded using NFKD decomposition. Instead of storing the full
+// sequence of collation elements, we decompose the rune and lookup the collation
+// elements for each rune in the decomposition and modify the tertiary weights.
+// The colElem, in this case, is of the form 11110000 00000000 wwwwwwww vvvvvvvv, where
+// - v* is the replacement tertiary weight for the first rune,
+// - w* is the replacement tertiary weight for the second rune,
+// Tertiary weights of subsequent runes should be replaced with maxTertiary.
+// See http://www.unicode.org/reports/tr10/#Compatibility_Decompositions for more details.
+func splitDecompose(ce colElem) (t1, t2 uint8) {
+ return uint8(ce), uint8(ce >> 8)
+}
+
+const (
+ // These constants were taken from http://www.unicode.org/versions/Unicode6.0.0/ch12.pdf.
+ minUnified rune = 0x4E00
+ maxUnified = 0x9FFF
+ minCompatibility = 0xF900
+ maxCompatibility = 0xFAFF
+ minRare = 0x3400
+ maxRare = 0x4DBF
+)
+const (
+ commonUnifiedOffset = 0x10000
+ rareUnifiedOffset = 0x20000 // largest rune in common is U+FAFF
+ otherOffset = 0x50000 // largest rune in rare is U+2FA1D
+ illegalOffset = otherOffset + int(unicode.MaxRune)
+ maxPrimary = illegalOffset + 1
+)
+
+// implicitPrimary returns the primary weight for the a rune
+// for which there is no entry for the rune in the collation table.
+// We take a different approach from the one specified in
+// http://unicode.org/reports/tr10/#Implicit_Weights,
+// but preserve the resulting relative ordering of the runes.
+func implicitPrimary(r rune) int {
+ if unicode.Is(unicode.Ideographic, r) {
+ if r >= minUnified && r <= maxUnified {
+ // The most common case for CJK.
+ return int(r) + commonUnifiedOffset
+ }
+ if r >= minCompatibility && r <= maxCompatibility {
+ // This will typically not hit. The DUCET explicitly specifies mappings
+ // for all characters that do not decompose.
+ return int(r) + commonUnifiedOffset
+ }
+ return int(r) + rareUnifiedOffset
+ }
+ return int(r) + otherOffset
+}
diff --git a/libgo/go/exp/locale/collate/colelem_test.go b/libgo/go/exp/locale/collate/colelem_test.go
new file mode 100644
index 00000000000..bcb4ddb68c1
--- /dev/null
+++ b/libgo/go/exp/locale/collate/colelem_test.go
@@ -0,0 +1,169 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package collate
+
+import (
+ "testing"
+ "unicode"
+)
+
+type ceTest struct {
+ f func(inout []int) (colElem, ceType)
+ arg []int
+}
+
+// The make* funcs are simplified versions of the functions in build/colelem.go
+func makeCE(weights []int) colElem {
+ const (
+ maxPrimaryBits = 21
+ maxSecondaryBits = 12
+ maxSecondaryCompactBits = 8
+ maxSecondaryDiffBits = 4
+ maxTertiaryBits = 8
+ maxTertiaryCompactBits = 5
+ isSecondary = 0x80000000
+ isPrimary = 0x40000000
+ )
+ var ce colElem
+ if weights[0] != 0 {
+ if weights[2] == defaultTertiary {
+ ce = colElem(weights[0]<<maxSecondaryCompactBits + weights[1])
+ ce |= isPrimary
+ } else {
+ d := weights[1] - defaultSecondary
+ ce = colElem(weights[0]<<maxSecondaryDiffBits + d)
+ ce = ce<<maxTertiaryCompactBits + colElem(weights[2])
+ }
+ } else {
+ ce = colElem(weights[1]<<maxTertiaryBits + weights[2])
+ ce |= isSecondary
+ }
+ return ce
+}
+
+func makeContractIndex(index, n, offset int) colElem {
+ const (
+ contractID = 0xC0000000
+ maxNBits = 4
+ maxTrieIndexBits = 12
+ maxContractOffsetBits = 13
+ )
+ ce := colElem(contractID)
+ ce += colElem(offset << (maxNBits + maxTrieIndexBits))
+ ce += colElem(index << maxNBits)
+ ce += colElem(n)
+ return ce
+}
+
+func makeExpandIndex(index int) colElem {
+ const expandID = 0xE0000000
+ return expandID + colElem(index)
+}
+
+func makeDecompose(t1, t2 int) colElem {
+ const decompID = 0xF0000000
+ return colElem(t2<<8+t1) + decompID
+}
+
+func normalCE(inout []int) (ce colElem, t ceType) {
+ w := splitCE(makeCE(inout))
+ inout[0] = int(w.primary)
+ inout[1] = int(w.secondary)
+ inout[2] = int(w.tertiary)
+ return ce, ceNormal
+}
+
+func expandCE(inout []int) (ce colElem, t ceType) {
+ ce = makeExpandIndex(inout[0])
+ inout[0] = splitExpandIndex(ce)
+ return ce, ceExpansionIndex
+}
+
+func contractCE(inout []int) (ce colElem, t ceType) {
+ ce = makeContractIndex(inout[0], inout[1], inout[2])
+ i, n, o := splitContractIndex(ce)
+ inout[0], inout[1], inout[2] = i, n, o
+ return ce, ceContractionIndex
+}
+
+func decompCE(inout []int) (ce colElem, t ceType) {
+ ce = makeDecompose(inout[0], inout[1])
+ t1, t2 := splitDecompose(ce)
+ inout[0], inout[1] = int(t1), int(t2)
+ return ce, ceDecompose
+}
+
+const (
+ maxPrimaryBits = 21
+ maxSecondaryBits = 16
+ maxTertiaryBits = 8
+)
+
+var ceTests = []ceTest{
+ {normalCE, []int{0, 0, 0}},
+ {normalCE, []int{0, 30, 3}},
+ {normalCE, []int{100, defaultSecondary, 3}},
+
+ {contractCE, []int{0, 0, 0}},
+ {contractCE, []int{1, 1, 1}},
+ {contractCE, []int{1, (1 << maxNBits) - 1, 1}},
+ {contractCE, []int{(1 << maxTrieIndexBits) - 1, 1, 1}},
+ {contractCE, []int{1, 1, (1 << maxContractOffsetBits) - 1}},
+
+ {expandCE, []int{0}},
+ {expandCE, []int{5}},
+ {expandCE, []int{(1 << maxExpandIndexBits) - 1}},
+
+ {decompCE, []int{0, 0}},
+ {decompCE, []int{1, 1}},
+ {decompCE, []int{0x1F, 0x1F}},
+}
+
+func TestColElem(t *testing.T) {
+ for i, tt := range ceTests {
+ inout := make([]int, len(tt.arg))
+ copy(inout, tt.arg)
+ ce, typ := tt.f(inout)
+ if ce.ctype() != typ {
+ t.Errorf("%d: type is %d; want %d", i, ce.ctype(), typ)
+ }
+ for j, a := range tt.arg {
+ if inout[j] != a {
+ t.Errorf("%d: argument %d is %X; want %X", i, j, inout[j], a)
+ }
+ }
+ }
+}
+
+type implicitTest struct {
+ r rune
+ p int
+}
+
+var implicitTests = []implicitTest{
+ {0x33FF, 0x533FF},
+ {0x3400, 0x23400},
+ {0x4DC0, 0x54DC0},
+ {0x4DFF, 0x54DFF},
+ {0x4E00, 0x14E00},
+ {0x9FCB, 0x19FCB},
+ {0xA000, 0x5A000},
+ {0xF8FF, 0x5F8FF},
+ {0xF900, 0x1F900},
+ {0xFA23, 0x1FA23},
+ {0xFAD9, 0x1FAD9},
+ {0xFB00, 0x5FB00},
+ {0x20000, 0x40000},
+ {0x2B81C, 0x4B81C},
+ {unicode.MaxRune, 0x15FFFF}, // maximum primary value
+}
+
+func TestImplicit(t *testing.T) {
+ for _, tt := range implicitTests {
+ if p := implicitPrimary(tt.r); p != tt.p {
+ t.Errorf("%U: was %X; want %X", tt.r, p, tt.p)
+ }
+ }
+}
diff --git a/libgo/go/exp/locale/collate/collate.go b/libgo/go/exp/locale/collate/collate.go
new file mode 100644
index 00000000000..5853b710c33
--- /dev/null
+++ b/libgo/go/exp/locale/collate/collate.go
@@ -0,0 +1,363 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package collate contains types for comparing and sorting Unicode strings
+// according to a given collation order. Package locale provides a high-level
+// interface to collation. Users should typically use that package instead.
+package collate
+
+import (
+ "bytes"
+ "exp/norm"
+)
+
+// Level identifies the collation comparison level.
+// The primary level corresponds to the basic sorting of text.
+// The secondary level corresponds to accents and related linguistic elements.
+// The tertiary level corresponds to casing and related concepts.
+// The quaternary level is derived from the other levels by the
+// various algorithms for handling variable elements.
+type Level int
+
+const (
+ Primary Level = iota
+ Secondary
+ Tertiary
+ Quaternary
+ Identity
+)
+
+// AlternateHandling identifies the various ways in which variables are handled.
+// A rune with a primary weight lower than the variable top is considered a
+// variable.
+// See http://www.unicode.org/reports/tr10/#Variable_Weighting for details.
+type AlternateHandling int
+
+const (
+ // AltNonIgnorable turns off special handling of variables.
+ AltNonIgnorable AlternateHandling = iota
+
+ // AltBlanked sets variables and all subsequent primary ignorables to be
+ // ignorable at all levels. This is identical to removing all variables
+ // and subsequent primary ignorables from the input.
+ AltBlanked
+
+ // AltShifted sets variables to be ignorable for levels one through three and
+ // adds a fourth level based on the values of the ignored levels.
+ AltShifted
+
+ // AltShiftTrimmed is a slight variant of AltShifted that is used to
+ // emulate POSIX.
+ AltShiftTrimmed
+)
+
+// Collator provides functionality for comparing strings for a given
+// collation order.
+type Collator struct {
+ // Strength sets the maximum level to use in comparison.
+ Strength Level
+
+ // Alternate specifies an alternative handling of variables.
+ Alternate AlternateHandling
+
+ // Backwards specifies the order of sorting at the secondary level.
+ // This option exists predominantly to support reverse sorting of accents in French.
+ Backwards bool
+
+ // TODO: implement:
+ // With HiraganaQuaternary enabled, Hiragana codepoints will get lower values
+ // than all the other non-variable code points. Strength must be greater or
+ // equal to Quaternary for this to take effect.
+ HiraganaQuaternary bool
+
+ // If CaseLevel is true, a level consisting only of case characteristics will
+ // be inserted in front of the tertiary level. To ignore accents but take
+ // cases into account, set Strength to Primary and CaseLevel to true.
+ CaseLevel bool
+
+ // If Numeric is true, any sequence of decimal digits (category is Nd) is sorted
+ // at a primary level with its numeric value. For example, "A-21" < "A-123".
+ Numeric bool
+
+ f norm.Form
+
+ t *table
+}
+
+// Locales returns the list of locales for which collating differs from its parent locale.
+func Locales() []string {
+ return availableLocales
+}
+
+// New returns a new Collator initialized for the given locale.
+func New(loc string) *Collator {
+ // TODO: handle locale selection according to spec.
+ t := &mainTable
+ if loc != "" {
+ if idx, ok := locales[loc]; ok {
+ t = mainTable.indexedTable(idx)
+ }
+ }
+ return &Collator{
+ Strength: Quaternary,
+ f: norm.NFD,
+ t: t,
+ }
+}
+
+// SetVariableTop sets all runes with primary strength less than the primary
+// strength of r to be variable and thus affected by alternate handling.
+func (c *Collator) SetVariableTop(r rune) {
+ // TODO: implement
+}
+
+// Buffer holds reusable buffers that can be used during collation.
+// Reusing a Buffer for the various calls that accept it may avoid
+// unnecessary memory allocations.
+type Buffer struct {
+ // TODO: try various parameters and techniques, such as using
+ // a chan of buffers for a pool.
+ ba [4096]byte
+ wa [512]weights
+ key []byte
+ ce []weights
+}
+
+func (b *Buffer) init() {
+ if b.ce == nil {
+ b.ce = b.wa[:0]
+ b.key = b.ba[:0]
+ } else {
+ b.ce = b.ce[:0]
+ }
+}
+
+// ResetKeys clears the buffer used for generated keys. Calling ResetKeys
+// invalidates keys previously obtained from Key or KeyFromString.
+func (b *Buffer) ResetKeys() {
+ b.ce = b.ce[:0]
+ b.key = b.key[:0]
+}
+
+// Compare returns an integer comparing the two byte slices.
+// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
+// Compare calls ResetKeys, thereby invalidating keys
+// previously generated using Key or KeyFromString using buf.
+func (c *Collator) Compare(buf *Buffer, a, b []byte) int {
+ // TODO: for now we simply compute keys and compare. Once we
+ // have good benchmarks, move to an implementation that works
+ // incrementally for the majority of cases.
+ // - Benchmark with long strings that only vary in modifiers.
+ buf.ResetKeys()
+ ka := c.Key(buf, a)
+ kb := c.Key(buf, b)
+ defer buf.ResetKeys()
+ return bytes.Compare(ka, kb)
+}
+
+// CompareString returns an integer comparing the two strings.
+// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
+// CompareString calls ResetKeys, thereby invalidating keys
+// previously generated using Key or KeyFromString using buf.
+func (c *Collator) CompareString(buf *Buffer, a, b string) int {
+ buf.ResetKeys()
+ ka := c.KeyFromString(buf, a)
+ kb := c.KeyFromString(buf, b)
+ defer buf.ResetKeys()
+ return bytes.Compare(ka, kb)
+}
+
+func (c *Collator) Prefix(buf *Buffer, s, prefix []byte) int {
+ // iterate over s, track bytes consumed.
+ return 0
+}
+
+// Key returns the collation key for str.
+// Passing the buffer buf may avoid memory allocations.
+// The returned slice will point to an allocation in Buffer and will remain
+// valid until the next call to buf.ResetKeys().
+func (c *Collator) Key(buf *Buffer, str []byte) []byte {
+ // See http://www.unicode.org/reports/tr10/#Main_Algorithm for more details.
+ buf.init()
+ c.getColElems(buf, str)
+ return c.key(buf, buf.ce)
+}
+
+// KeyFromString returns the collation key for str.
+// Passing the buffer buf may avoid memory allocations.
+// The returned slice will point to an allocation in Buffer and will retain
+// valid until the next call to buf.ResetKeys().
+func (c *Collator) KeyFromString(buf *Buffer, str string) []byte {
+ // See http://www.unicode.org/reports/tr10/#Main_Algorithm for more details.
+ buf.init()
+ c.getColElemsString(buf, str)
+ return c.key(buf, buf.ce)
+}
+
+func (c *Collator) key(buf *Buffer, w []weights) []byte {
+ processWeights(c.Alternate, c.t.variableTop, w)
+ kn := len(buf.key)
+ c.keyFromElems(buf, w)
+ return buf.key[kn:]
+}
+
+func (c *Collator) getColElems(buf *Buffer, str []byte) {
+ i := c.iter()
+ i.src.SetInput(c.f, str)
+ for !i.done() {
+ buf.ce = i.next(buf.ce)
+ }
+}
+
+func (c *Collator) getColElemsString(buf *Buffer, str string) {
+ i := c.iter()
+ i.src.SetInputString(c.f, str)
+ for !i.done() {
+ buf.ce = i.next(buf.ce)
+ }
+}
+
+type iter struct {
+ src norm.Iter
+ ba [1024]byte
+ buf []byte
+ t *table
+ p int
+ minBufSize int
+ _done, eof bool
+}
+
+func (c *Collator) iter() iter {
+ i := iter{t: c.t, minBufSize: c.t.maxContractLen}
+ i.buf = i.ba[:0]
+ return i
+}
+
+func (i *iter) done() bool {
+ return i._done
+}
+
+func (i *iter) next(ce []weights) []weights {
+ if !i.eof && len(i.buf)-i.p < i.minBufSize {
+ // replenish buffer
+ n := copy(i.buf, i.buf[i.p:])
+ n += i.src.Next(i.buf[n:cap(i.buf)])
+ i.buf = i.buf[:n]
+ i.p = 0
+ i.eof = i.src.Done()
+ }
+ if i.p == len(i.buf) {
+ i._done = true
+ return ce
+ }
+ ce, sz := i.t.appendNext(ce, i.buf[i.p:])
+ i.p += sz
+ return ce
+}
+
+func appendPrimary(key []byte, p uint32) []byte {
+ // Convert to variable length encoding; supports up to 23 bits.
+ if p <= 0x7FFF {
+ key = append(key, uint8(p>>8), uint8(p))
+ } else {
+ key = append(key, uint8(p>>16)|0x80, uint8(p>>8), uint8(p))
+ }
+ return key
+}
+
+// keyFromElems converts the weights ws to a compact sequence of bytes.
+// The result will be appended to the byte buffer in buf.
+func (c *Collator) keyFromElems(buf *Buffer, ws []weights) {
+ for _, v := range ws {
+ if w := v.primary; w > 0 {
+ buf.key = appendPrimary(buf.key, w)
+ }
+ }
+ if Secondary <= c.Strength {
+ buf.key = append(buf.key, 0, 0)
+ // TODO: we can use one 0 if we can guarantee that all non-zero weights are > 0xFF.
+ if !c.Backwards {
+ for _, v := range ws {
+ if w := v.secondary; w > 0 {
+ buf.key = append(buf.key, uint8(w>>8), uint8(w))
+ }
+ }
+ } else {
+ for i := len(ws) - 1; i >= 0; i-- {
+ if w := ws[i].secondary; w > 0 {
+ buf.key = append(buf.key, uint8(w>>8), uint8(w))
+ }
+ }
+ }
+ } else if c.CaseLevel {
+ buf.key = append(buf.key, 0, 0)
+ }
+ if Tertiary <= c.Strength || c.CaseLevel {
+ buf.key = append(buf.key, 0, 0)
+ for _, v := range ws {
+ if w := v.tertiary; w > 0 {
+ buf.key = append(buf.key, w)
+ }
+ }
+ // Derive the quaternary weights from the options and other levels.
+ // Note that we represent maxQuaternary as 0xFF. The first byte of the
+ // representation of a a primary weight is always smaller than 0xFF,
+ // so using this single byte value will compare correctly.
+ if Quaternary <= c.Strength {
+ if c.Alternate == AltShiftTrimmed {
+ lastNonFFFF := len(buf.key)
+ buf.key = append(buf.key, 0)
+ for _, v := range ws {
+ if w := v.quaternary; w == maxQuaternary {
+ buf.key = append(buf.key, 0xFF)
+ } else if w > 0 {
+ buf.key = appendPrimary(buf.key, w)
+ lastNonFFFF = len(buf.key)
+ }
+ }
+ buf.key = buf.key[:lastNonFFFF]
+ } else {
+ buf.key = append(buf.key, 0)
+ for _, v := range ws {
+ if w := v.quaternary; w == maxQuaternary {
+ buf.key = append(buf.key, 0xFF)
+ } else if w > 0 {
+ buf.key = appendPrimary(buf.key, w)
+ }
+ }
+ }
+ }
+ }
+}
+
+func processWeights(vw AlternateHandling, top uint32, wa []weights) {
+ ignore := false
+ switch vw {
+ case AltShifted, AltShiftTrimmed:
+ for i := range wa {
+ if p := wa[i].primary; p <= top && p != 0 {
+ wa[i] = weights{quaternary: p}
+ ignore = true
+ } else if p == 0 {
+ if ignore {
+ wa[i] = weights{}
+ } else if wa[i].tertiary != 0 {
+ wa[i].quaternary = maxQuaternary
+ }
+ } else {
+ wa[i].quaternary = maxQuaternary
+ ignore = false
+ }
+ }
+ case AltBlanked:
+ for i := range wa {
+ if p := wa[i].primary; p <= top && (ignore || p != 0) {
+ wa[i] = weights{}
+ ignore = true
+ } else {
+ ignore = false
+ }
+ }
+ }
+}
diff --git a/libgo/go/exp/locale/collate/contract.go b/libgo/go/exp/locale/collate/contract.go
new file mode 100644
index 00000000000..0d9bc401bcf
--- /dev/null
+++ b/libgo/go/exp/locale/collate/contract.go
@@ -0,0 +1,86 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package collate
+
+import "unicode/utf8"
+
+// For a description of contractTrieSet, see exp/locale/collate/build/contract.go.
+
+type contractTrieSet []struct{ l, h, n, i uint8 }
+
+// ctScanner is used to match a trie to an input sequence.
+// A contraction may match a non-contiguous sequence of bytes in an input string.
+// For example, if there is a contraction for <a, combining_ring>, it should match
+// the sequence <a, combining_cedilla, combining_ring>, as combining_cedilla does
+// not block combining_ring.
+// ctScanner does not automatically skip over non-blocking non-starters, but rather
+// retains the state of the last match and leaves it up to the user to continue
+// the match at the appropriate points.
+type ctScanner struct {
+ states contractTrieSet
+ s []byte
+ n int
+ index int
+ pindex int
+ done bool
+}
+
+func (t contractTrieSet) scanner(index, n int, b []byte) ctScanner {
+ return ctScanner{states: t[index:], s: b, n: n}
+}
+
+// result returns the offset i and bytes consumed p so far. If no suffix
+// matched, i and p will be 0.
+func (s *ctScanner) result() (i, p int) {
+ return s.index, s.pindex
+}
+
+const (
+ final = 0
+ noIndex = 0xFF
+)
+
+// scan matches the longest suffix at the current location in the input
+// and returns the number of bytes consumed.
+func (s *ctScanner) scan(p int) int {
+ pr := p // the p at the rune start
+ str := s.s
+ states, n := s.states, s.n
+ for i := 0; i < n && p < len(str); {
+ e := states[i]
+ c := str[p]
+ // TODO: a significant number of contractions are of a form that
+ // cannot match discontiguous UTF-8 in a normalized string. We could let
+ // a negative value of e.n mean that we can set s.done = true and avoid
+ // the need for additional matches.
+ if c >= e.l {
+ if e.l == c {
+ p++
+ if e.i != noIndex {
+ s.index = int(e.i)
+ s.pindex = p
+ }
+ if e.n != final {
+ i, states, n = 0, states[int(e.h)+n:], int(e.n)
+ if p >= len(str) || utf8.RuneStart(str[p]) {
+ s.states, s.n, pr = states, n, p
+ }
+ } else {
+ s.done = true
+ return p
+ }
+ continue
+ } else if e.n == final && c <= e.h {
+ p++
+ s.done = true
+ s.index = int(c-e.l) + int(e.i)
+ s.pindex = p
+ return p
+ }
+ }
+ i++
+ }
+ return pr
+}
diff --git a/libgo/go/exp/locale/collate/contract_test.go b/libgo/go/exp/locale/collate/contract_test.go
new file mode 100644
index 00000000000..f3710a183a2
--- /dev/null
+++ b/libgo/go/exp/locale/collate/contract_test.go
@@ -0,0 +1,132 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package collate
+
+import (
+ "testing"
+)
+
+type lookupStrings struct {
+ str string
+ offset int
+ n int // bytes consumed from input
+}
+
+type LookupTest struct {
+ lookup []lookupStrings
+ n int
+ tries contractTrieSet
+}
+
+var lookupTests = []LookupTest{
+ {[]lookupStrings{
+ {"abc", 1, 3},
+ {"a", 0, 0},
+ {"b", 0, 0},
+ {"c", 0, 0},
+ {"d", 0, 0},
+ },
+ 1,
+ contractTrieSet{
+ {'a', 0, 1, 0xFF},
+ {'b', 0, 1, 0xFF},
+ {'c', 'c', 0, 1},
+ },
+ },
+ {[]lookupStrings{
+ {"abc", 1, 3},
+ {"abd", 2, 3},
+ {"abe", 3, 3},
+ {"a", 0, 0},
+ {"ab", 0, 0},
+ {"d", 0, 0},
+ {"f", 0, 0},
+ },
+ 1,
+ contractTrieSet{
+ {'a', 0, 1, 0xFF},
+ {'b', 0, 1, 0xFF},
+ {'c', 'e', 0, 1},
+ },
+ },
+ {[]lookupStrings{
+ {"abc", 1, 3},
+ {"ab", 2, 2},
+ {"a", 3, 1},
+ {"abcd", 1, 3},
+ {"abe", 2, 2},
+ },
+ 1,
+ contractTrieSet{
+ {'a', 0, 1, 3},
+ {'b', 0, 1, 2},
+ {'c', 'c', 0, 1},
+ },
+ },
+ {[]lookupStrings{
+ {"abc", 1, 3},
+ {"abd", 2, 3},
+ {"ab", 3, 2},
+ {"ac", 4, 2},
+ {"a", 5, 1},
+ {"b", 6, 1},
+ {"ba", 6, 1},
+ },
+ 2,
+ contractTrieSet{
+ {'b', 'b', 0, 6},
+ {'a', 0, 2, 5},
+ {'c', 'c', 0, 4},
+ {'b', 0, 1, 3},
+ {'c', 'd', 0, 1},
+ },
+ },
+ {[]lookupStrings{
+ {"bcde", 2, 4},
+ {"bc", 7, 2},
+ {"ab", 6, 2},
+ {"bcd", 5, 3},
+ {"abcd", 1, 4},
+ {"abc", 4, 3},
+ {"bcdf", 3, 4},
+ },
+ 2,
+ contractTrieSet{
+ {'b', 3, 1, 0xFF},
+ {'a', 0, 1, 0xFF},
+ {'b', 0, 1, 6},
+ {'c', 0, 1, 4},
+ {'d', 'd', 0, 1},
+ {'c', 0, 1, 7},
+ {'d', 0, 1, 5},
+ {'e', 'f', 0, 2},
+ },
+ },
+}
+
+func lookup(c *contractTrieSet, nnode int, s []uint8) (i, n int) {
+ scan := c.scanner(0, nnode, s)
+ scan.scan(0)
+ return scan.result()
+}
+
+func TestLookupContraction(t *testing.T) {
+ for i, tt := range lookupTests {
+ cts := contractTrieSet(tt.tries)
+ for j, lu := range tt.lookup {
+ str := lu.str
+ for _, s := range []string{str, str + "X"} {
+ const msg = `%d:%d: %s of "%s" %v; want %v`
+ offset, n := lookup(&cts, tt.n, []byte(s))
+ if offset != lu.offset {
+ t.Errorf(msg, i, j, "offset", s, offset, lu.offset)
+ }
+ if n != lu.n {
+ t.Errorf(msg, i, j, "bytes consumed", s, n, len(str))
+ }
+ }
+ }
+ }
+}
diff --git a/libgo/go/exp/locale/collate/export.go b/libgo/go/exp/locale/collate/export.go
new file mode 100644
index 00000000000..01750dd070e
--- /dev/null
+++ b/libgo/go/exp/locale/collate/export.go
@@ -0,0 +1,43 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package collate
+
+import "exp/norm"
+
+// Init is used by type Builder in exp/locale/collate/build/
+// to create Collator instances. It is for internal use only.
+func Init(data interface{}) *Collator {
+ init, ok := data.(tableInitializer)
+ if !ok {
+ return nil
+ }
+ t := &table{}
+ loff, voff := init.FirstBlockOffsets()
+ t.index.index = init.TrieIndex()
+ t.index.index0 = t.index.index[blockSize*loff:]
+ t.index.values = init.TrieValues()
+ t.index.values0 = t.index.values[blockSize*voff:]
+ t.expandElem = init.ExpandElems()
+ t.contractTries = init.ContractTries()
+ t.contractElem = init.ContractElems()
+ t.maxContractLen = init.MaxContractLen()
+ t.variableTop = init.VariableTop()
+ return &Collator{
+ Strength: Quaternary,
+ f: norm.NFD,
+ t: t,
+ }
+}
+
+type tableInitializer interface {
+ TrieIndex() []uint16
+ TrieValues() []uint32
+ FirstBlockOffsets() (lookup, value uint16)
+ ExpandElems() []uint32
+ ContractTries() []struct{ l, h, n, i uint8 }
+ ContractElems() []uint32
+ MaxContractLen() int
+ VariableTop() uint32
+}
diff --git a/libgo/go/exp/locale/collate/export_test.go b/libgo/go/exp/locale/collate/export_test.go
new file mode 100644
index 00000000000..de6e9078b5c
--- /dev/null
+++ b/libgo/go/exp/locale/collate/export_test.go
@@ -0,0 +1,87 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package collate
+
+// Export for testing.
+
+import (
+ "fmt"
+)
+
+type Weights struct {
+ Primary, Secondary, Tertiary, Quaternary int
+}
+
+func W(ce ...int) Weights {
+ w := Weights{ce[0], defaultSecondary, defaultTertiary, 0}
+ if len(ce) > 1 {
+ w.Secondary = ce[1]
+ }
+ if len(ce) > 2 {
+ w.Tertiary = ce[2]
+ }
+ if len(ce) > 3 {
+ w.Quaternary = ce[3]
+ }
+ return w
+}
+func (w Weights) String() string {
+ return fmt.Sprintf("[%d.%d.%d.%d]", w.Primary, w.Secondary, w.Tertiary, w.Quaternary)
+}
+
+type Table struct {
+ t *table
+ w []weights
+}
+
+func GetTable(c *Collator) *Table {
+ return &Table{c.t, nil}
+}
+
+func convertToWeights(ws []weights) []Weights {
+ out := make([]Weights, len(ws))
+ for i, w := range ws {
+ out[i] = Weights{int(w.primary), int(w.secondary), int(w.tertiary), int(w.quaternary)}
+ }
+ return out
+}
+
+func convertFromWeights(ws []Weights) []weights {
+ out := make([]weights, len(ws))
+ for i, w := range ws {
+ out[i] = weights{uint32(w.Primary), uint16(w.Secondary), uint8(w.Tertiary), uint32(w.Quaternary)}
+ }
+ return out
+}
+
+func (t *Table) AppendNext(s []byte) ([]Weights, int) {
+ w, n := t.t.appendNext(nil, s)
+ return convertToWeights(w), n
+}
+
+func SetTop(c *Collator, top int) {
+ if c.t == nil {
+ c.t = &table{}
+ }
+ c.t.variableTop = uint32(top)
+}
+
+func GetColElems(c *Collator, buf *Buffer, str []byte) []Weights {
+ buf.ResetKeys()
+ c.getColElems(buf, str)
+ return convertToWeights(buf.ce)
+}
+
+func ProcessWeights(h AlternateHandling, top int, w []Weights) []Weights {
+ in := convertFromWeights(w)
+ processWeights(h, uint32(top), in)
+ return convertToWeights(in)
+}
+
+func KeyFromElems(c *Collator, buf *Buffer, w []Weights) []byte {
+ k := len(buf.key)
+ c.keyFromElems(buf, convertFromWeights(w))
+ return buf.key[k:]
+}
diff --git a/libgo/go/exp/locale/collate/maketables.go b/libgo/go/exp/locale/collate/maketables.go
new file mode 100644
index 00000000000..ec03f8f8453
--- /dev/null
+++ b/libgo/go/exp/locale/collate/maketables.go
@@ -0,0 +1,722 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Collation table generator.
+// Data read from the web.
+
+package main
+
+import (
+ "archive/zip"
+ "bufio"
+ "bytes"
+ "encoding/xml"
+ "exp/locale/collate"
+ "exp/locale/collate/build"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "path"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+var (
+ root = flag.String("root",
+ "http://unicode.org/Public/UCA/"+unicode.Version+"/CollationAuxiliary.zip",
+ `URL of the Default Unicode Collation Element Table (DUCET). This can be a zip
+file containing the file allkeys_CLDR.txt or an allkeys.txt file.`)
+ cldr = flag.String("cldr",
+ "http://www.unicode.org/Public/cldr/2.0.1/core.zip",
+ "URL of CLDR archive.")
+ test = flag.Bool("test", false,
+ "test existing tables; can be used to compare web data with package data.")
+ localFiles = flag.Bool("local", false,
+ "data files have been copied to the current directory; for debugging only.")
+ short = flag.Bool("short", false, `Use "short" alternatives, when available.`)
+ draft = flag.Bool("draft", false, `Use draft versions, when available.`)
+ tags = flag.String("tags", "", "build tags to be included after +build directive")
+ pkg = flag.String("package", "collate",
+ "the name of the package in which the generated file is to be included")
+
+ tables = flagStringSetAllowAll("tables", "collate", "collate,chars",
+ "comma-spearated list of tables to generate.")
+ exclude = flagStringSet("exclude", "zh2", "",
+ "comma-separated list of languages to exclude.")
+ include = flagStringSet("include", "", "",
+ "comma-separated list of languages to include. Include trumps exclude.")
+ types = flagStringSetAllowAll("types", "", "",
+ "comma-separated list of types that should be included in addition to the standard type.")
+)
+
+// stringSet implements an ordered set based on a list. It implements flag.Value
+// to allow a set to be specified as a comma-separated list.
+type stringSet struct {
+ s []string
+ allowed *stringSet
+ dirty bool // needs compaction if true
+ all bool
+ allowAll bool
+}
+
+func flagStringSet(name, def, allowed, usage string) *stringSet {
+ ss := &stringSet{}
+ if allowed != "" {
+ usage += fmt.Sprintf(" (allowed values: any of %s)", allowed)
+ ss.allowed = &stringSet{}
+ failOnError(ss.allowed.Set(allowed))
+ }
+ ss.Set(def)
+ flag.Var(ss, name, usage)
+ return ss
+}
+
+func flagStringSetAllowAll(name, def, allowed, usage string) *stringSet {
+ ss := &stringSet{allowAll: true}
+ if allowed == "" {
+ flag.Var(ss, name, usage+fmt.Sprintf(` Use "all" to select all.`))
+ } else {
+ ss.allowed = &stringSet{}
+ failOnError(ss.allowed.Set(allowed))
+ flag.Var(ss, name, usage+fmt.Sprintf(` (allowed values: "all" or any of %s)`, allowed))
+ }
+ ss.Set(def)
+ return ss
+}
+
+func (ss stringSet) Len() int {
+ return len(ss.s)
+}
+
+func (ss stringSet) String() string {
+ return strings.Join(ss.s, ",")
+}
+
+func (ss *stringSet) Set(s string) error {
+ if ss.allowAll && s == "all" {
+ ss.s = nil
+ ss.all = true
+ return nil
+ }
+ ss.s = ss.s[:0]
+ for _, s := range strings.Split(s, ",") {
+ if s := strings.TrimSpace(s); s != "" {
+ if ss.allowed != nil && !ss.allowed.contains(s) {
+ return fmt.Errorf("unsupported value %q; must be one of %s", s, ss.allowed)
+ }
+ ss.add(s)
+ }
+ }
+ ss.compact()
+ return nil
+}
+
+func (ss *stringSet) add(s string) {
+ ss.s = append(ss.s, s)
+ ss.dirty = true
+}
+
+func (ss *stringSet) values() []string {
+ ss.compact()
+ return ss.s
+}
+
+func (ss *stringSet) contains(s string) bool {
+ if ss.all {
+ return true
+ }
+ for _, v := range ss.s {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
+
+func (ss *stringSet) compact() {
+ if !ss.dirty {
+ return
+ }
+ a := ss.s
+ sort.Strings(a)
+ k := 0
+ for i := 1; i < len(a); i++ {
+ if a[k] != a[i] {
+ a[k+1] = a[i]
+ k++
+ }
+ }
+ ss.s = a[:k+1]
+ ss.dirty = false
+}
+
+func skipLang(l string) bool {
+ if include.Len() > 0 {
+ return !include.contains(l)
+ }
+ return exclude.contains(l)
+}
+
+func skipAlt(a string) bool {
+ if *draft && a == "proposed" {
+ return false
+ }
+ if *short && a == "short" {
+ return false
+ }
+ return true
+}
+
+func failOnError(e error) {
+ if e != nil {
+ log.Fatal(e)
+ }
+}
+
+// openReader opens the URL or file given by url and returns it as an io.ReadCloser
+// or nil on error.
+func openReader(url *string) (io.ReadCloser, error) {
+ if *localFiles {
+ pwd, _ := os.Getwd()
+ *url = "file://" + path.Join(pwd, path.Base(*url))
+ }
+ t := &http.Transport{}
+ t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
+ c := &http.Client{Transport: t}
+ resp, err := c.Get(*url)
+ if err != nil {
+ return nil, err
+ }
+ if resp.StatusCode != 200 {
+ return nil, fmt.Errorf(`bad GET status for "%s": %s`, *url, resp.Status)
+ }
+ return resp.Body, nil
+}
+
+func openArchive(url *string) *zip.Reader {
+ f, err := openReader(url)
+ failOnError(err)
+ buffer, err := ioutil.ReadAll(f)
+ f.Close()
+ failOnError(err)
+ archive, err := zip.NewReader(bytes.NewReader(buffer), int64(len(buffer)))
+ failOnError(err)
+ return archive
+}
+
+// parseUCA parses a Default Unicode Collation Element Table of the format
+// specified in http://www.unicode.org/reports/tr10/#File_Format.
+// It returns the variable top.
+func parseUCA(builder *build.Builder) {
+ var r io.ReadCloser
+ var err error
+ if strings.HasSuffix(*root, ".zip") {
+ for _, f := range openArchive(root).File {
+ if strings.HasSuffix(f.Name, "allkeys_CLDR.txt") {
+ r, err = f.Open()
+ }
+ }
+ if r == nil {
+ err = fmt.Errorf("file allkeys_CLDR.txt not found in archive %q", *root)
+ }
+ } else {
+ r, err = openReader(root)
+ }
+ failOnError(err)
+ defer r.Close()
+ input := bufio.NewReader(r)
+ colelem := regexp.MustCompile(`\[([.*])([0-9A-F.]+)\]`)
+ for i := 1; err == nil; i++ {
+ l, prefix, e := input.ReadLine()
+ err = e
+ line := string(l)
+ if prefix {
+ log.Fatalf("%d: buffer overflow", i)
+ }
+ if err != nil && err != io.EOF {
+ log.Fatalf("%d: %v", i, err)
+ }
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+ if line[0] == '@' {
+ // parse properties
+ switch {
+ case strings.HasPrefix(line[1:], "version "):
+ a := strings.Split(line[1:], " ")
+ if a[1] != unicode.Version {
+ log.Fatalf("incompatible version %s; want %s", a[1], unicode.Version)
+ }
+ case strings.HasPrefix(line[1:], "backwards "):
+ log.Fatalf("%d: unsupported option backwards", i)
+ default:
+ log.Printf("%d: unknown option %s", i, line[1:])
+ }
+ } else {
+ // parse entries
+ part := strings.Split(line, " ; ")
+ if len(part) != 2 {
+ log.Fatalf("%d: production rule without ';': %v", i, line)
+ }
+ lhs := []rune{}
+ for _, v := range strings.Split(part[0], " ") {
+ if v == "" {
+ continue
+ }
+ lhs = append(lhs, rune(convHex(i, v)))
+ }
+ var n int
+ var vars []int
+ rhs := [][]int{}
+ for i, m := range colelem.FindAllStringSubmatch(part[1], -1) {
+ n += len(m[0])
+ elem := []int{}
+ for _, h := range strings.Split(m[2], ".") {
+ elem = append(elem, convHex(i, h))
+ }
+ if m[1] == "*" {
+ vars = append(vars, i)
+ }
+ rhs = append(rhs, elem)
+ }
+ if len(part[1]) < n+3 || part[1][n+1] != '#' {
+ log.Fatalf("%d: expected comment; found %s", i, part[1][n:])
+ }
+ if *test {
+ testInput.add(string(lhs))
+ }
+ failOnError(builder.Add(lhs, rhs, vars))
+ }
+ }
+}
+
+func convHex(line int, s string) int {
+ r, e := strconv.ParseInt(s, 16, 32)
+ if e != nil {
+ log.Fatalf("%d: %v", line, e)
+ }
+ return int(r)
+}
+
+var testInput = stringSet{}
+
+// LDML holds all collation information parsed from an LDML XML file.
+// The format of these files is defined in http://unicode.org/reports/tr35/.
+type LDML struct {
+ XMLName xml.Name `xml:"ldml"`
+ Language Attr `xml:"identity>language"`
+ Territory Attr `xml:"identity>territory"`
+ Chars *struct {
+ ExemplarCharacters []AttrValue `xml:"exemplarCharacters"`
+ MoreInformaton string `xml:"moreInformation,omitempty"`
+ } `xml:"characters"`
+ Default Attr `xml:"collations>default"`
+ Collations []Collation `xml:"collations>collation"`
+}
+
+type Attr struct {
+ XMLName xml.Name
+ Attr string `xml:"type,attr"`
+}
+
+func (t Attr) String() string {
+ return t.Attr
+}
+
+type AttrValue struct {
+ Type string `xml:"type,attr"`
+ Key string `xml:"key,attr,omitempty"`
+ Draft string `xml:"draft,attr,omitempty"`
+ Value string `xml:",innerxml"`
+}
+
+type Collation struct {
+ Type string `xml:"type,attr"`
+ Alt string `xml:"alt,attr"`
+ SuppressContraction string `xml:"suppress_contractions,omitempty"`
+ Settings *Settings `xml:"settings"`
+ Optimize string `xml:"optimize"`
+ Rules Rules `xml:"rules"`
+}
+
+type Optimize struct {
+ XMLName xml.Name `xml:"optimize"`
+ Data string `xml:"chardata"`
+}
+
+type Suppression struct {
+ XMLName xml.Name `xml:"suppress_contractions"`
+ Data string `xml:"chardata"`
+}
+
+type Settings struct {
+ Strength string `xml:"strenght,attr,omitempty"`
+ Backwards string `xml:"backwards,attr,omitempty"`
+ Normalization string `xml:"normalization,attr,omitempty"`
+ CaseLevel string `xml:"caseLevel,attr,omitempty"`
+ CaseFirst string `xml:"caseFirst,attr,omitempty"`
+ HiraganaQuarternary string `xml:"hiraganaQuartenary,attr,omitempty"`
+ Numeric string `xml:"numeric,attr,omitempty"`
+ VariableTop string `xml:"variableTop,attr,omitempty"`
+}
+
+type Rules struct {
+ XMLName xml.Name `xml:"rules"`
+ Any []RuleElem `xml:",any"`
+}
+
+type RuleElem struct {
+ XMLName xml.Name
+ Value string `xml:",innerxml"`
+ Before string `xml:"before,attr"`
+ Any []RuleElem `xml:",any"` // for <x> elements
+}
+
+var charRe = regexp.MustCompile(`&#x([0-9A-F]*);`)
+var tagRe = regexp.MustCompile(`<([a-z_]*) */>`)
+
+func (r *RuleElem) rewrite() {
+ // Convert hexadecimal Unicode codepoint notation to a string.
+ if m := charRe.FindAllStringSubmatch(r.Value, -1); m != nil {
+ runes := []rune{}
+ for _, sa := range m {
+ runes = append(runes, rune(convHex(-1, sa[1])))
+ }
+ r.Value = string(runes)
+ }
+ // Strip spaces from reset positions.
+ if m := tagRe.FindStringSubmatch(r.Value); m != nil {
+ r.Value = fmt.Sprintf("<%s/>", m[1])
+ }
+ for _, rr := range r.Any {
+ rr.rewrite()
+ }
+}
+
+func decodeXML(f *zip.File) *LDML {
+ r, err := f.Open()
+ failOnError(err)
+ d := xml.NewDecoder(r)
+ var x LDML
+ err = d.Decode(&x)
+ failOnError(err)
+ return &x
+}
+
+var mainLocales = []string{}
+
+// charsets holds a list of exemplar characters per category.
+type charSets map[string][]string
+
+func (p charSets) fprint(w io.Writer) {
+ fmt.Fprintln(w, "[exN]string{")
+ for i, k := range []string{"", "contractions", "punctuation", "auxiliary", "currencySymbol", "index"} {
+ if set := p[k]; len(set) != 0 {
+ fmt.Fprintf(w, "\t\t%d: %q,\n", i, strings.Join(set, " "))
+ }
+ }
+ fmt.Fprintln(w, "\t},")
+}
+
+var localeChars = make(map[string]charSets)
+
+const exemplarHeader = `
+type exemplarType int
+const (
+ exCharacters exemplarType = iota
+ exContractions
+ exPunctuation
+ exAuxiliary
+ exCurrency
+ exIndex
+ exN
+)
+`
+
+func printExemplarCharacters(w io.Writer) {
+ fmt.Fprintln(w, exemplarHeader)
+ fmt.Fprintln(w, "var exemplarCharacters = map[string][exN]string{")
+ for _, loc := range mainLocales {
+ fmt.Fprintf(w, "\t%q: ", loc)
+ localeChars[loc].fprint(w)
+ }
+ fmt.Fprintln(w, "}")
+}
+
+var mainRe = regexp.MustCompile(`.*/main/(.*)\.xml`)
+
+// parseMain parses XML files in the main directory of the CLDR core.zip file.
+func parseMain() {
+ for _, f := range openArchive(cldr).File {
+ if m := mainRe.FindStringSubmatch(f.Name); m != nil {
+ locale := m[1]
+ x := decodeXML(f)
+ if skipLang(x.Language.Attr) {
+ continue
+ }
+ if x.Chars != nil {
+ for _, ec := range x.Chars.ExemplarCharacters {
+ if ec.Draft != "" {
+ continue
+ }
+ if _, ok := localeChars[locale]; !ok {
+ mainLocales = append(mainLocales, locale)
+ localeChars[locale] = make(charSets)
+ }
+ localeChars[locale][ec.Type] = parseCharacters(ec.Value)
+ }
+ }
+ }
+ }
+}
+
+func parseCharacters(chars string) []string {
+ parseSingle := func(s string) (r rune, tail string, escaped bool) {
+ if s[0] == '\\' {
+ if s[1] == 'u' || s[1] == 'U' {
+ r, _, tail, err := strconv.UnquoteChar(s, 0)
+ failOnError(err)
+ return r, tail, false
+ } else if strings.HasPrefix(s[1:], "&amp;") {
+ return '&', s[6:], false
+ }
+ return rune(s[1]), s[2:], true
+ } else if strings.HasPrefix(s, "&quot;") {
+ return '"', s[6:], false
+ }
+ r, sz := utf8.DecodeRuneInString(s)
+ return r, s[sz:], false
+ }
+ chars = strings.Trim(chars, "[ ]")
+ list := []string{}
+ var r, last, end rune
+ for len(chars) > 0 {
+ if chars[0] == '{' { // character sequence
+ buf := []rune{}
+ for chars = chars[1:]; len(chars) > 0; {
+ r, chars, _ = parseSingle(chars)
+ if r == '}' {
+ break
+ }
+ if r == ' ' {
+ log.Fatalf("space not supported in sequence %q", chars)
+ }
+ buf = append(buf, r)
+ }
+ list = append(list, string(buf))
+ last = 0
+ } else { // single character
+ escaped := false
+ r, chars, escaped = parseSingle(chars)
+ if r != ' ' {
+ if r == '-' && !escaped {
+ if last == 0 {
+ log.Fatal("'-' should be preceded by a character")
+ }
+ end, chars, _ = parseSingle(chars)
+ for ; last <= end; last++ {
+ list = append(list, string(last))
+ }
+ last = 0
+ } else {
+ list = append(list, string(r))
+ last = r
+ }
+ }
+ }
+ }
+ return list
+}
+
+var fileRe = regexp.MustCompile(`.*/collation/(.*)\.xml`)
+
+// parseCollation parses XML files in the collation directory of the CLDR core.zip file.
+func parseCollation(b *build.Builder) {
+ for _, f := range openArchive(cldr).File {
+ if m := fileRe.FindStringSubmatch(f.Name); m != nil {
+ lang := m[1]
+ x := decodeXML(f)
+ if skipLang(x.Language.Attr) {
+ continue
+ }
+ def := "standard"
+ if x.Default.Attr != "" {
+ def = x.Default.Attr
+ }
+ todo := make(map[string]Collation)
+ for _, c := range x.Collations {
+ if c.Type != def && !types.contains(c.Type) {
+ continue
+ }
+ if c.Alt != "" && skipAlt(c.Alt) {
+ continue
+ }
+ for j := range c.Rules.Any {
+ c.Rules.Any[j].rewrite()
+ }
+ locale := lang
+ if c.Type != def {
+ locale += "_u_co_" + c.Type
+ }
+ _, exists := todo[locale]
+ if c.Alt != "" || !exists {
+ todo[locale] = c
+ }
+ }
+ for _, c := range x.Collations {
+ locale := lang
+ if c.Type != def {
+ locale += "_u_co_" + c.Type
+ }
+ if d, ok := todo[locale]; ok && d.Alt == c.Alt {
+ insertCollation(b, locale, &c)
+ }
+ }
+ }
+ }
+}
+
+var lmap = map[byte]collate.Level{
+ 'p': collate.Primary,
+ 's': collate.Secondary,
+ 't': collate.Tertiary,
+ 'i': collate.Identity,
+}
+
+// cldrIndex is a Unicode-reserved sentinel value used.
+// We ignore any rule that starts with this rune.
+// See http://unicode.org/reports/tr35/#Collation_Elements for details.
+const cldrIndex = 0xFDD0
+
+func insertTailoring(t *build.Tailoring, r RuleElem, context, extend string) {
+ switch l := r.XMLName.Local; l {
+ case "p", "s", "t", "i":
+ if []rune(r.Value)[0] != cldrIndex {
+ str := context + r.Value
+ if *test {
+ testInput.add(str)
+ }
+ err := t.Insert(lmap[l[0]], str, extend)
+ failOnError(err)
+ }
+ case "pc", "sc", "tc", "ic":
+ level := lmap[l[0]]
+ for _, s := range r.Value {
+ str := context + string(s)
+ if *test {
+ testInput.add(str)
+ }
+ err := t.Insert(level, str, extend)
+ failOnError(err)
+ }
+ default:
+ log.Fatalf("unsupported tag: %q", l)
+ }
+}
+
+func insertCollation(builder *build.Builder, locale string, c *Collation) {
+ t := builder.Tailoring(locale)
+ for _, r := range c.Rules.Any {
+ switch r.XMLName.Local {
+ case "reset":
+ if r.Before == "" {
+ failOnError(t.SetAnchor(r.Value))
+ } else {
+ failOnError(t.SetAnchorBefore(r.Value))
+ }
+ case "x":
+ var context, extend string
+ for _, r1 := range r.Any {
+ switch r1.XMLName.Local {
+ case "context":
+ context = r1.Value
+ case "extend":
+ extend = r1.Value
+ }
+ }
+ for _, r1 := range r.Any {
+ if t := r1.XMLName.Local; t == "context" || t == "extend" {
+ continue
+ }
+ insertTailoring(t, r1, context, extend)
+ }
+ default:
+ insertTailoring(t, r, "", "")
+ }
+ }
+}
+
+func testCollator(c *collate.Collator) {
+ c0 := collate.New("")
+
+ // iterator over all characters for all locales and check
+ // whether Key is equal.
+ buf := collate.Buffer{}
+
+ // Add all common and not too uncommon runes to the test set.
+ for i := rune(0); i < 0x30000; i++ {
+ testInput.add(string(i))
+ }
+ for i := rune(0xE0000); i < 0xF0000; i++ {
+ testInput.add(string(i))
+ }
+ for _, str := range testInput.values() {
+ k0 := c0.KeyFromString(&buf, str)
+ k := c.KeyFromString(&buf, str)
+ if bytes.Compare(k0, k) != 0 {
+ failOnError(fmt.Errorf("test:%U: keys differ (%x vs %x)", []rune(str), k0, k))
+ }
+ buf.ResetKeys()
+ }
+ fmt.Println("PASS")
+}
+
+func main() {
+ flag.Parse()
+ b := build.NewBuilder()
+ if *root != "" {
+ parseUCA(b)
+ }
+ if *cldr != "" {
+ if tables.contains("chars") {
+ parseMain()
+ }
+ parseCollation(b)
+ }
+
+ c, err := b.Build()
+ failOnError(err)
+
+ if *test {
+ testCollator(c)
+ } else {
+ fmt.Println("// Generated by running")
+ fmt.Printf("// maketables -root=%s -cldr=%s\n", *root, *cldr)
+ fmt.Println("// DO NOT EDIT")
+ fmt.Println("// TODO: implement more compact representation for sparse blocks.")
+ if *tags != "" {
+ fmt.Printf("// +build %s\n", *tags)
+ }
+ fmt.Println("")
+ fmt.Printf("package %s\n", *pkg)
+ if tables.contains("collate") {
+ fmt.Println("")
+ _, err = b.Print(os.Stdout)
+ failOnError(err)
+ }
+ if tables.contains("chars") {
+ printExemplarCharacters(os.Stdout)
+ }
+ }
+}
diff --git a/libgo/go/exp/locale/collate/regtest.go b/libgo/go/exp/locale/collate/regtest.go
new file mode 100644
index 00000000000..14a447c1e4e
--- /dev/null
+++ b/libgo/go/exp/locale/collate/regtest.go
@@ -0,0 +1,268 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "archive/zip"
+ "bufio"
+ "bytes"
+ "exp/locale/collate"
+ "exp/locale/collate/build"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "path"
+ "regexp"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// This regression test runs tests for the test files in CollationTest.zip
+// (taken from http://www.unicode.org/Public/UCA/<unicode.Version>/).
+//
+// The test files have the following form:
+// # header
+// 0009 0021; # ('\u0009') <CHARACTER TABULATION> [| | | 0201 025E]
+// 0009 003F; # ('\u0009') <CHARACTER TABULATION> [| | | 0201 0263]
+// 000A 0021; # ('\u000A') <LINE FEED (LF)> [| | | 0202 025E]
+// 000A 003F; # ('\u000A') <LINE FEED (LF)> [| | | 0202 0263]
+//
+// The part before the semicolon is the hex representation of a sequence
+// of runes. After the hash mark is a comment. The strings
+// represented by rune sequence are in the file in sorted order, as
+// defined by the DUCET.
+
+var testdata = flag.String("testdata",
+ "http://www.unicode.org/Public/UCA/"+unicode.Version+"/CollationTest.zip",
+ "URL of Unicode collation tests zip file")
+var ducet = flag.String("ducet",
+ "http://unicode.org/Public/UCA/"+unicode.Version+"/allkeys.txt",
+ "URL of the Default Unicode Collation Element Table (DUCET).")
+var localFiles = flag.Bool("local",
+ false,
+ "data files have been copied to the current directory; for debugging only")
+
+type Test struct {
+ name string
+ str [][]byte
+ comment []string
+}
+
+var versionRe = regexp.MustCompile(`# UCA Version: (.*)\n?$`)
+var testRe = regexp.MustCompile(`^([\dA-F ]+);.*# (.*)\n?$`)
+
+func Error(e error) {
+ if e != nil {
+ log.Fatal(e)
+ }
+}
+
+// openReader opens the url or file given by url and returns it as an io.ReadCloser
+// or nil on error.
+func openReader(url string) io.ReadCloser {
+ if *localFiles {
+ pwd, _ := os.Getwd()
+ url = "file://" + path.Join(pwd, path.Base(url))
+ }
+ t := &http.Transport{}
+ t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
+ c := &http.Client{Transport: t}
+ resp, err := c.Get(url)
+ Error(err)
+ if resp.StatusCode != 200 {
+ Error(fmt.Errorf(`bad GET status for "%s": %s`, url, resp.Status))
+ }
+ return resp.Body
+}
+
+// parseUCA parses a Default Unicode Collation Element Table of the format
+// specified in http://www.unicode.org/reports/tr10/#File_Format.
+// It returns the variable top.
+func parseUCA(builder *build.Builder) {
+ r := openReader(*ducet)
+ defer r.Close()
+ input := bufio.NewReader(r)
+ colelem := regexp.MustCompile(`\[([.*])([0-9A-F.]+)\]`)
+ for i := 1; true; i++ {
+ l, prefix, err := input.ReadLine()
+ if err == io.EOF {
+ break
+ }
+ Error(err)
+ line := string(l)
+ if prefix {
+ log.Fatalf("%d: buffer overflow", i)
+ }
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+ if line[0] == '@' {
+ if strings.HasPrefix(line[1:], "version ") {
+ if v := strings.Split(line[1:], " ")[1]; v != unicode.Version {
+ log.Fatalf("incompatible version %s; want %s", v, unicode.Version)
+ }
+ }
+ } else {
+ // parse entries
+ part := strings.Split(line, " ; ")
+ if len(part) != 2 {
+ log.Fatalf("%d: production rule without ';': %v", i, line)
+ }
+ lhs := []rune{}
+ for _, v := range strings.Split(part[0], " ") {
+ if v != "" {
+ lhs = append(lhs, rune(convHex(i, v)))
+ }
+ }
+ vars := []int{}
+ rhs := [][]int{}
+ for i, m := range colelem.FindAllStringSubmatch(part[1], -1) {
+ if m[1] == "*" {
+ vars = append(vars, i)
+ }
+ elem := []int{}
+ for _, h := range strings.Split(m[2], ".") {
+ elem = append(elem, convHex(i, h))
+ }
+ rhs = append(rhs, elem)
+ }
+ builder.Add(lhs, rhs, vars)
+ }
+ }
+}
+
+func convHex(line int, s string) int {
+ r, e := strconv.ParseInt(s, 16, 32)
+ if e != nil {
+ log.Fatalf("%d: %v", line, e)
+ }
+ return int(r)
+}
+
+func loadTestData() []Test {
+ f := openReader(*testdata)
+ buffer, err := ioutil.ReadAll(f)
+ f.Close()
+ Error(err)
+ archive, err := zip.NewReader(bytes.NewReader(buffer), int64(len(buffer)))
+ Error(err)
+ tests := []Test{}
+ for _, f := range archive.File {
+ // Skip the short versions, which are simply duplicates of the long versions.
+ if strings.Contains(f.Name, "SHORT") || f.FileInfo().IsDir() {
+ continue
+ }
+ ff, err := f.Open()
+ Error(err)
+ defer ff.Close()
+ input := bufio.NewReader(ff)
+ test := Test{name: path.Base(f.Name)}
+ for {
+ line, err := input.ReadString('\n')
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ log.Fatal(err)
+ }
+ if len(line) <= 1 || line[0] == '#' {
+ if m := versionRe.FindStringSubmatch(line); m != nil {
+ if m[1] != unicode.Version {
+ log.Printf("warning:%s: version is %s; want %s", f.Name, m[1], unicode.Version)
+ }
+ }
+ continue
+ }
+ m := testRe.FindStringSubmatch(line)
+ if m == nil || len(m) < 3 {
+ log.Fatalf(`Failed to parse: "%s" result: %#v`, line, m)
+ }
+ str := []byte{}
+ // In the regression test data (unpaired) surrogates are assigned a weight
+ // corresponding to their code point value. However, utf8.DecodeRune,
+ // which is used to compute the implicit weight, assigns FFFD to surrogates.
+ // We therefore skip tests with surrogates. This skips about 35 entries
+ // per test.
+ valid := true
+ for _, split := range strings.Split(m[1], " ") {
+ r, err := strconv.ParseUint(split, 16, 64)
+ Error(err)
+ valid = valid && utf8.ValidRune(rune(r))
+ str = append(str, string(rune(r))...)
+ }
+ if valid {
+ test.str = append(test.str, str)
+ test.comment = append(test.comment, m[2])
+ }
+ }
+ tests = append(tests, test)
+ }
+ return tests
+}
+
+var errorCount int
+
+func fail(t Test, pattern string, args ...interface{}) {
+ format := fmt.Sprintf("error:%s:%s", t.name, pattern)
+ log.Printf(format, args...)
+ errorCount++
+ if errorCount > 30 {
+ log.Fatal("too many errors")
+ }
+}
+
+func runes(b []byte) []rune {
+ return []rune(string(b))
+}
+
+func doTest(t Test) {
+ bld := build.NewBuilder()
+ parseUCA(bld)
+ c, err := bld.Build()
+ Error(err)
+ c.Strength = collate.Tertiary
+ c.Alternate = collate.AltShifted
+ b := &collate.Buffer{}
+ if strings.Contains(t.name, "NON_IGNOR") {
+ c.Alternate = collate.AltNonIgnorable
+ }
+
+ prev := t.str[0]
+ for i := 1; i < len(t.str); i++ {
+ s := t.str[i]
+ ka := c.Key(b, prev)
+ kb := c.Key(b, s)
+ if r := bytes.Compare(ka, kb); r == 1 {
+ fail(t, "%d: Key(%.4X) < Key(%.4X) (%X < %X) == %d; want -1 or 0", i, []rune(string(prev)), []rune(string(s)), ka, kb, r)
+ prev = s
+ continue
+ }
+ if r := c.Compare(b, prev, s); r == 1 {
+ fail(t, "%d: Compare(%.4X, %.4X) == %d; want -1 or 0", i, runes(prev), runes(s), r)
+ }
+ if r := c.Compare(b, s, prev); r == -1 {
+ fail(t, "%d: Compare(%.4X, %.4X) == %d; want 1 or 0", i, runes(s), runes(prev), r)
+ }
+ prev = s
+ }
+}
+
+func main() {
+ flag.Parse()
+ for _, test := range loadTestData() {
+ doTest(test)
+ }
+ if errorCount == 0 {
+ fmt.Println("PASS")
+ }
+}
diff --git a/libgo/go/exp/locale/collate/table.go b/libgo/go/exp/locale/collate/table.go
new file mode 100644
index 00000000000..c25799b98b2
--- /dev/null
+++ b/libgo/go/exp/locale/collate/table.go
@@ -0,0 +1,150 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package collate
+
+import (
+ "exp/norm"
+ "unicode/utf8"
+)
+
+// tableIndex holds information for constructing a table
+// for a certain locale based on the main table.
+type tableIndex struct {
+ lookupOffset uint32
+ valuesOffset uint32
+}
+
+// table holds all collation data for a given collation ordering.
+type table struct {
+ index trie // main trie
+
+ // expansion info
+ expandElem []uint32
+
+ // contraction info
+ contractTries contractTrieSet
+ contractElem []uint32
+ maxContractLen int
+ variableTop uint32
+}
+
+func (t *table) indexedTable(idx tableIndex) *table {
+ nt := *t
+ nt.index.index0 = t.index.index[idx.lookupOffset*blockSize:]
+ nt.index.values0 = t.index.values[idx.valuesOffset*blockSize:]
+ return &nt
+}
+
+// appendNext appends the weights corresponding to the next rune or
+// contraction in s. If a contraction is matched to a discontinuous
+// sequence of runes, the weights for the interstitial runes are
+// appended as well. It returns a new slice that includes the appended
+// weights and the number of bytes consumed from s.
+func (t *table) appendNext(w []weights, s []byte) ([]weights, int) {
+ v, sz := t.index.lookup(s)
+ ce := colElem(v)
+ tp := ce.ctype()
+ if tp == ceNormal {
+ w = append(w, getWeights(ce, s))
+ } else if tp == ceExpansionIndex {
+ w = t.appendExpansion(w, ce)
+ } else if tp == ceContractionIndex {
+ n := 0
+ w, n = t.matchContraction(w, ce, s[sz:])
+ sz += n
+ } else if tp == ceDecompose {
+ // Decompose using NFCK and replace tertiary weights.
+ t1, t2 := splitDecompose(ce)
+ i := len(w)
+ nfkd := norm.NFKD.Properties(s).Decomposition()
+ for p := 0; len(nfkd) > 0; nfkd = nfkd[p:] {
+ w, p = t.appendNext(w, nfkd)
+ }
+ w[i].tertiary = t1
+ if i++; i < len(w) {
+ w[i].tertiary = t2
+ for i++; i < len(w); i++ {
+ w[i].tertiary = maxTertiary
+ }
+ }
+ }
+ return w, sz
+}
+
+func getWeights(ce colElem, s []byte) weights {
+ if ce == 0 { // implicit
+ r, _ := utf8.DecodeRune(s)
+ return weights{
+ primary: uint32(implicitPrimary(r)),
+ secondary: defaultSecondary,
+ tertiary: defaultTertiary,
+ }
+ }
+ return splitCE(ce)
+}
+
+func (t *table) appendExpansion(w []weights, ce colElem) []weights {
+ i := splitExpandIndex(ce)
+ n := int(t.expandElem[i])
+ i++
+ for _, ce := range t.expandElem[i : i+n] {
+ w = append(w, splitCE(colElem(ce)))
+ }
+ return w
+}
+
+func (t *table) matchContraction(w []weights, ce colElem, suffix []byte) ([]weights, int) {
+ index, n, offset := splitContractIndex(ce)
+
+ scan := t.contractTries.scanner(index, n, suffix)
+ buf := [norm.MaxSegmentSize]byte{}
+ bufp := 0
+ p := scan.scan(0)
+
+ if !scan.done && p < len(suffix) && suffix[p] >= utf8.RuneSelf {
+ // By now we should have filtered most cases.
+ p0 := p
+ bufn := 0
+ rune := norm.NFC.Properties(suffix[p:])
+ p += rune.Size()
+ if prevCC := rune.TrailCCC(); prevCC != 0 {
+ // A gap may only occur in the last normalization segment.
+ // This also ensures that len(scan.s) < norm.MaxSegmentSize.
+ if end := norm.NFC.FirstBoundary(suffix[p:]); end != -1 {
+ scan.s = suffix[:p+end]
+ }
+ for p < len(suffix) && !scan.done && suffix[p] >= utf8.RuneSelf {
+ rune = norm.NFC.Properties(suffix[p:])
+ if ccc := rune.LeadCCC(); ccc == 0 || prevCC >= ccc {
+ break
+ }
+ prevCC = rune.TrailCCC()
+ if pp := scan.scan(p); pp != p {
+ // Copy the interstitial runes for later processing.
+ bufn += copy(buf[bufn:], suffix[p0:p])
+ if scan.pindex == pp {
+ bufp = bufn
+ }
+ p, p0 = pp, pp
+ } else {
+ p += rune.Size()
+ }
+ }
+ }
+ }
+ // Append weights for the matched contraction, which may be an expansion.
+ i, n := scan.result()
+ ce = colElem(t.contractElem[i+offset])
+ if ce.ctype() == ceNormal {
+ w = append(w, splitCE(ce))
+ } else {
+ w = t.appendExpansion(w, ce)
+ }
+ // Append weights for the runes in the segment not part of the contraction.
+ for b, p := buf[:bufp], 0; len(b) > 0; b = b[p:] {
+ w, p = t.appendNext(w, b)
+ }
+ return w, n
+}
diff --git a/libgo/go/exp/locale/collate/tables.go b/libgo/go/exp/locale/collate/tables.go
new file mode 100644
index 00000000000..1b36a65c50f
--- /dev/null
+++ b/libgo/go/exp/locale/collate/tables.go
@@ -0,0 +1,7578 @@
+// Generated by running
+// maketables -root=http://unicode.org/Public/UCA/6.0.0/CollationAuxiliary.zip -cldr=http://www.unicode.org/Public/cldr/2.0.1/core.zip
+// DO NOT EDIT
+// TODO: implement more compact representation for sparse blocks.
+
+package collate
+
+var availableLocales = []string{"af", "ar", "as", "az", "be", "bg", "bn", "ca", "cs", "cy", "da", "de", "dz", "el", "en_US_POSIX", "eo", "es", "et", "fa", "fi", "fil", "fo", "fr_CA", "gu", "ha", "haw", "he", "hi", "hr", "hu", "hy", "ig", "is", "ja", "kk", "kl", "km", "kn", "ko", "kok", "ln", "lt", "lv", "mk", "ml", "mr", "mt", "my", "nb", "nn", "nso", "om", "or", "pa", "pl", "ps", "ro", "root", "ru", "se", "si", "sk", "sl", "sq", "sr", "sv", "ta", "te", "th", "tn", "tr", "uk", "ur", "vi", "wae", "yo", "zh"}
+
+var locales = map[string]tableIndex{
+ "af": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ar": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "as": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "az": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "be": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "bg": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "bn": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ca": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "cs": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "cy": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "da": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "de": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "dz": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "el": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "en_US_POSIX": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "eo": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "es": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "et": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "fa": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "fi": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "fil": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "fo": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "fr_CA": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "gu": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ha": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "haw": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "he": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "hi": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "hr": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "hu": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "hy": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ig": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "is": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ja": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "kk": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "kl": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "km": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "kn": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ko": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "kok": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ln": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "lt": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "lv": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "mk": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ml": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "mr": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "mt": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "my": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "nb": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "nn": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "nso": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "om": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "or": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "pa": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "pl": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ps": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ro": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "root": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ru": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "se": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "si": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "sk": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "sl": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "sq": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "sr": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "sv": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ta": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "te": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "th": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "tn": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "tr": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "uk": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "ur": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "vi": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "wae": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "yo": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+ "zh": {
+ lookupOffset: 0x13,
+ valuesOffset: 0x0,
+ },
+}
+
+var mainTable = table{
+ trie{mainLookup[1216:], mainValues[0:], mainLookup[:], mainValues[:]},
+ mainExpandElem[:],
+ contractTrieSet(mainCTEntries[:]),
+ mainContractElem[:],
+ 9,
+ 0x2ED,
+}
+
+// mainExpandElem: 4642 entries, 18568 bytes
+var mainExpandElem = [4642]uint32{
+ // Block 0, offset 0x0
+ 0x00000002, 0x8000A31A, 0x8000AD1A, 0x00000002, 0x8000A51A, 0x8000AD1A,
+ 0x00000002, 0x8000A718, 0x8000AD18, 0x00000002, 0x8000A71A, 0x8000AD1A,
+ 0x00000002, 0x8000A918, 0x8000AD18, 0x00000002, 0x8000A91A, 0x8000AD1A,
+ 0x00000002, 0x8000AB18, 0x8000AD18, 0x00000002, 0x8000AB1A, 0x8000AD1A,
+ 0x00000002, 0x8000AD1A, 0x8000BD1A, 0x00000002, 0x40139D20, 0x80014E02,
+ 0x00000002, 0x40139E20, 0x80014E02, 0x00000002, 0x40149A20, 0x80016502,
+ 0x00000002, 0x40149A20, 0x80016602, 0x00000002, 0x40149A20, 0x80016802,
+ 0x00000002, 0x40149A20, 0x80016A02, 0x00000002, 0x40149A20, 0x80016B02,
+ 0x00000002, 0x40149A20, 0x80016C02, 0x00000002, 0x40149A20, 0x80016D02,
+ 0x00000002, 0x40149A20, 0x80016E02, 0x00000002, 0x40149A20, 0x80016F02,
+ 0x00000002, 0x40149A20, 0x80017002, 0x00000002,
+ // Block 1, offset 0x40
+ 0x40149A20, 0x80017102, 0x00000002, 0x40149A20, 0x80017102, 0x00000002,
+ 0x40149A20, 0x80017202, 0x00000002, 0x40149A20, 0x80017302, 0x00000002,
+ 0x40149A20, 0x80017402, 0x00000002, 0x40149A20, 0x80017502, 0x00000002,
+ 0x40149A20, 0x80017602, 0x00000002, 0x40149A20, 0x80017702, 0x00000002,
+ 0x40149A20, 0x80017802, 0x00000002, 0x40149A20, 0x80017902, 0x00000002,
+ 0x40149A20, 0x80017A02, 0x00000002, 0x40149A20, 0x80017B02, 0x00000002,
+ 0x40149A20, 0x80017C02, 0x00000002, 0x00293404, 0x80017C04, 0x00000002,
+ 0x40149A20, 0x80017D02, 0x00000002, 0x40149A20, 0x80017E02, 0x00000002,
+ 0x40149A20, 0x80017F02, 0x00000002, 0x40149A20, 0x80018002, 0x00000002,
+ 0x40149A20, 0x80018102, 0x00000002, 0x40149A20, 0x80018202, 0x00000002,
+ 0x40149A20, 0x80018302, 0x00000002, 0x40149A20,
+ // Block 2, offset 0x80
+ 0x80018402, 0x00000002, 0x40149A20, 0x80018502, 0x00000002, 0x40149A20,
+ 0x80018602, 0x00000002, 0x40149A20, 0x80018702, 0x00000002, 0x40149A20,
+ 0x80018802, 0x00000002, 0x40149A20, 0x80018902, 0x00000002, 0x40149A20,
+ 0x80018A02, 0x00000002, 0x40149A20, 0x80018C02, 0x00000002, 0x40149A20,
+ 0x80019602, 0x00000002, 0x40149B20, 0x80016502, 0x00000002, 0x40149B20,
+ 0x80016602, 0x00000002, 0x40149B20, 0x80016702, 0x00000002, 0x40149B20,
+ 0x80016802, 0x00000002, 0x40149B20, 0x80016902, 0x00000002, 0x40149B20,
+ 0x80016A02, 0x00000002, 0x40149B20, 0x80016B02, 0x00000002, 0x40149B20,
+ 0x80016C02, 0x00000002, 0x40149B20, 0x80016D02, 0x00000002, 0x40149B20,
+ 0x80016E02, 0x00000002, 0x40149B20, 0x80016F02, 0x00000002, 0x40149B20,
+ 0x80017002, 0x00000002, 0x40149B20, 0x80017102,
+ // Block 3, offset 0xc0
+ 0x00000002, 0x40149B20, 0x80017102, 0x00000002, 0x40149B20, 0x80017102,
+ 0x00000002, 0x40149B20, 0x80017202, 0x00000002, 0x40149B20, 0x80017302,
+ 0x00000002, 0x40149B20, 0x80017402, 0x00000002, 0x40149B20, 0x80017502,
+ 0x00000002, 0x40149B20, 0x80017602, 0x00000002, 0x40149B20, 0x80017702,
+ 0x00000002, 0x40149B20, 0x80017702, 0x00000002, 0x40149B20, 0x80017802,
+ 0x00000002, 0x40149B20, 0x80017902, 0x00000002, 0x40149B20, 0x80017A02,
+ 0x00000002, 0x40149B20, 0x80017B02, 0x00000002, 0x40149B20, 0x80017C02,
+ 0x00000002, 0x00293604, 0x80017C04, 0x00000002, 0x40149B20, 0x80017D02,
+ 0x00000002, 0x40149B20, 0x80017E02, 0x00000002, 0x40149B20, 0x80017F02,
+ 0x00000002, 0x40149B20, 0x80018002, 0x00000002, 0x40149B20, 0x80018102,
+ 0x00000002, 0x40149B20, 0x80018202, 0x00000002,
+ // Block 4, offset 0x100
+ 0x40149B20, 0x80018302, 0x00000002, 0x40149B20, 0x80018402, 0x00000002,
+ 0x40149B20, 0x80018502, 0x00000002, 0x40149B20, 0x80018602, 0x00000002,
+ 0x40149B20, 0x80018702, 0x00000002, 0x40149B20, 0x80018802, 0x00000002,
+ 0x40149B20, 0x80018902, 0x00000002, 0x40149B20, 0x80018A02, 0x00000002,
+ 0x40149B20, 0x80018B02, 0x00000002, 0x40149B20, 0x80018C02, 0x00000002,
+ 0x40149B20, 0x80018C02, 0x00000002, 0x40149B20, 0x80018C02, 0x00000002,
+ 0x40149B20, 0x80018C02, 0x00000002, 0x40149B20, 0x80018E02, 0x00000002,
+ 0x40149B20, 0x80018F02, 0x00000002, 0x40149B20, 0x80019002, 0x00000002,
+ 0x40149B20, 0x80019002, 0x00000002, 0x40149B20, 0x80019002, 0x00000002,
+ 0x40149B20, 0x80019002, 0x00000002, 0x40149B20, 0x80019002, 0x00000002,
+ 0x40149B20, 0x80019002, 0x00000002, 0x40149B20,
+ // Block 5, offset 0x140
+ 0x80019102, 0x00000002, 0x40149B20, 0x80019202, 0x00000002, 0x40149B20,
+ 0x80019302, 0x00000002, 0x40149B20, 0x80019402, 0x00000002, 0x40149B20,
+ 0x80019502, 0x00000002, 0x40149B20, 0x80019602, 0x00000002, 0x40149B20,
+ 0x80019702, 0x00000002, 0x40149B20, 0x80019802, 0x00000002, 0x40149B20,
+ 0x80019902, 0x00000002, 0x00293606, 0x00293406, 0x00000002, 0x00293606,
+ 0x00293406, 0x00000002, 0x00293606, 0x00293406, 0x00000002, 0x00293606,
+ 0x00293406, 0x00000002, 0x00293606, 0x00293406, 0x00000002, 0x00293606,
+ 0x00293606, 0x00000002, 0x00293606, 0x00293806, 0x00000002, 0x00293606,
+ 0x00293A06, 0x00000002, 0x00293606, 0x00293C06, 0x00000002, 0x00293606,
+ 0x00293E06, 0x00000002, 0x00293606, 0x00294006, 0x00000002, 0x00293606,
+ 0x00294206, 0x00000002, 0x00293606, 0x00294406,
+ // Block 6, offset 0x180
+ 0x00000002, 0x00293606, 0x00294606, 0x00000002, 0x40149C20, 0x80016502,
+ 0x00000002, 0x40149C20, 0x80016602, 0x00000002, 0x40149C20, 0x80016702,
+ 0x00000002, 0x40149C20, 0x80016802, 0x00000002, 0x40149C20, 0x80016902,
+ 0x00000002, 0x40149C20, 0x80016A02, 0x00000002, 0x40149C20, 0x80016B02,
+ 0x00000002, 0x40149C20, 0x80016C02, 0x00000002, 0x40149C20, 0x80016D02,
+ 0x00000002, 0x40149C20, 0x80016E02, 0x00000002, 0x40149C20, 0x80016F02,
+ 0x00000002, 0x40149C20, 0x80017002, 0x00000002, 0x40149C20, 0x80017102,
+ 0x00000002, 0x40149C20, 0x80017102, 0x00000002, 0x40149C20, 0x80017102,
+ 0x00000002, 0x40149C20, 0x80017202, 0x00000002, 0x40149C20, 0x80017302,
+ 0x00000002, 0x40149C20, 0x80017402, 0x00000002, 0x40149C20, 0x80017502,
+ 0x00000002, 0x40149C20, 0x80017602, 0x00000002,
+ // Block 7, offset 0x1c0
+ 0x40149C20, 0x80017702, 0x00000002, 0x40149C20, 0x80017802, 0x00000002,
+ 0x40149C20, 0x80017902, 0x00000002, 0x40149C20, 0x80017A02, 0x00000002,
+ 0x40149C20, 0x80017B02, 0x00000002, 0x40149C20, 0x80017C02, 0x00000002,
+ 0x00293804, 0x80017C04, 0x00000002, 0x40149C20, 0x80017D02, 0x00000002,
+ 0x40149C20, 0x80017E02, 0x00000002, 0x40149C20, 0x80017F02, 0x00000002,
+ 0x40149C20, 0x80018002, 0x00000002, 0x40149C20, 0x80018102, 0x00000002,
+ 0x40149C20, 0x80018202, 0x00000002, 0x40149C20, 0x80018302, 0x00000002,
+ 0x40149C20, 0x80018402, 0x00000002, 0x40149C20, 0x80018502, 0x00000002,
+ 0x40149C20, 0x80018602, 0x00000002, 0x40149C20, 0x80018702, 0x00000002,
+ 0x40149C20, 0x80018802, 0x00000002, 0x40149C20, 0x80018902, 0x00000002,
+ 0x40149C20, 0x80018A02, 0x00000002, 0x40149C20,
+ // Block 8, offset 0x200
+ 0x80018B02, 0x00000002, 0x40149C20, 0x80018C02, 0x00000002, 0x40149C20,
+ 0x80018C02, 0x00000002, 0x40149C20, 0x80018C02, 0x00000002, 0x40149C20,
+ 0x80018C02, 0x00000002, 0x40149C20, 0x80018F02, 0x00000002, 0x40149C20,
+ 0x80019002, 0x00000002, 0x40149C20, 0x80019002, 0x00000002, 0x40149C20,
+ 0x80019002, 0x00000002, 0x40149C20, 0x80019002, 0x00000002, 0x40149C20,
+ 0x80019002, 0x00000002, 0x40149C20, 0x80019002, 0x00000002, 0x40149C20,
+ 0x80019002, 0x00000002, 0x40149C20, 0x80019002, 0x00000002, 0x40149C20,
+ 0x80019002, 0x00000002, 0x40149C20, 0x80019202, 0x00000002, 0x40149C20,
+ 0x80019302, 0x00000002, 0x40149C20, 0x80019402, 0x00000002, 0x40149C20,
+ 0x80019502, 0x00000002, 0x40149C20, 0x80019602, 0x00000002, 0x40149C20,
+ 0x80019702, 0x00000002, 0x40149C20, 0x80019802,
+ // Block 9, offset 0x240
+ 0x00000002, 0x40149C20, 0x80019902, 0x00000002, 0x00293806, 0x00293406,
+ 0x00000002, 0x00293806, 0x00293406, 0x00000002, 0x40149D20, 0x80016502,
+ 0x00000002, 0x40149D20, 0x80016602, 0x00000002, 0x40149D20, 0x80016702,
+ 0x00000002, 0x40149D20, 0x80016802, 0x00000002, 0x40149D20, 0x80016902,
+ 0x00000002, 0x40149D20, 0x80016A02, 0x00000002, 0x40149D20, 0x80016B02,
+ 0x00000002, 0x40149D20, 0x80016C02, 0x00000002, 0x40149D20, 0x80016D02,
+ 0x00000002, 0x40149D20, 0x80016E02, 0x00000002, 0x40149D20, 0x80016F02,
+ 0x00000002, 0x40149D20, 0x80017002, 0x00000002, 0x40149D20, 0x80017102,
+ 0x00000002, 0x40149D20, 0x80017102, 0x00000002, 0x40149D20, 0x80017102,
+ 0x00000002, 0x40149D20, 0x80017202, 0x00000002, 0x40149D20, 0x80017302,
+ 0x00000002, 0x40149D20, 0x80017402, 0x00000002,
+ // Block 10, offset 0x280
+ 0x40149D20, 0x80017502, 0x00000002, 0x40149D20, 0x80017602, 0x00000002,
+ 0x40149D20, 0x80017702, 0x00000002, 0x40149D20, 0x80017802, 0x00000002,
+ 0x40149D20, 0x80017902, 0x00000002, 0x40149D20, 0x80017A02, 0x00000002,
+ 0x40149D20, 0x80017B02, 0x00000002, 0x40149D20, 0x80017C02, 0x00000002,
+ 0x00293A04, 0x80017C04, 0x00000002, 0x40149D20, 0x80017D02, 0x00000002,
+ 0x40149D20, 0x80017E02, 0x00000002, 0x40149D20, 0x80017F02, 0x00000002,
+ 0x40149D20, 0x80018002, 0x00000002, 0x40149D20, 0x80018102, 0x00000002,
+ 0x40149D20, 0x80018202, 0x00000002, 0x40149D20, 0x80018302, 0x00000002,
+ 0x40149D20, 0x80018402, 0x00000002, 0x40149D20, 0x80018502, 0x00000002,
+ 0x40149D20, 0x80018602, 0x00000002, 0x40149D20, 0x80018702, 0x00000002,
+ 0x40149D20, 0x80018802, 0x00000002, 0x40149D20,
+ // Block 11, offset 0x2c0
+ 0x80018902, 0x00000002, 0x40149D20, 0x80018A02, 0x00000002, 0x40149D20,
+ 0x80018B02, 0x00000002, 0x40149D20, 0x80019002, 0x00000002, 0x40149D20,
+ 0x80019002, 0x00000002, 0x40149D20, 0x80019002, 0x00000002, 0x40149D20,
+ 0x80019002, 0x00000002, 0x40149D20, 0x80019002, 0x00000002, 0x40149D20,
+ 0x80019002, 0x00000002, 0x40149D20, 0x80019002, 0x00000002, 0x40149D20,
+ 0x80019002, 0x00000002, 0x40149D20, 0x80019002, 0x00000002, 0x40149D20,
+ 0x80019002, 0x00000002, 0x40149D20, 0x80019002, 0x00000002, 0x40149D20,
+ 0x80019002, 0x00000002, 0x40149D20, 0x80019002, 0x00000002, 0x40149D20,
+ 0x80019002, 0x00000002, 0x40149D20, 0x80019202, 0x00000002, 0x40149D20,
+ 0x80019302, 0x00000002, 0x40149D20, 0x80019402, 0x00000002, 0x40149D20,
+ 0x80019502, 0x00000002, 0x40149D20, 0x80019602,
+ // Block 12, offset 0x300
+ 0x00000002, 0x40149D20, 0x80019702, 0x00000002, 0x40149D20, 0x80019802,
+ 0x00000002, 0x40149D20, 0x80019902, 0x00000002, 0x00293A06, 0x00293406,
+ 0x00000002, 0x40149E20, 0x80016502, 0x00000002, 0x40149E20, 0x80016602,
+ 0x00000002, 0x40149E20, 0x80016702, 0x00000002, 0x40149E20, 0x80016802,
+ 0x00000002, 0x40149E20, 0x80016902, 0x00000002, 0x40149E20, 0x80016A02,
+ 0x00000002, 0x40149E20, 0x80016B02, 0x00000002, 0x40149E20, 0x80016C02,
+ 0x00000002, 0x40149E20, 0x80016D02, 0x00000002, 0x40149E20, 0x80016E02,
+ 0x00000002, 0x40149E20, 0x80016F02, 0x00000002, 0x40149E20, 0x80017002,
+ 0x00000002, 0x40149E20, 0x80017102, 0x00000002, 0x40149E20, 0x80017202,
+ 0x00000002, 0x40149E20, 0x80017302, 0x00000002, 0x40149E20, 0x80017402,
+ 0x00000002, 0x40149E20, 0x80017502, 0x00000002,
+ // Block 13, offset 0x340
+ 0x40149E20, 0x80017602, 0x00000002, 0x40149E20, 0x80017702, 0x00000002,
+ 0x40149E20, 0x80017802, 0x00000002, 0x40149E20, 0x80017902, 0x00000002,
+ 0x40149E20, 0x80017A02, 0x00000002, 0x40149E20, 0x80017B02, 0x00000002,
+ 0x40149E20, 0x80017C02, 0x00000002, 0x00293C04, 0x80017C04, 0x00000002,
+ 0x40149E20, 0x80017D02, 0x00000002, 0x40149E20, 0x80017E02, 0x00000002,
+ 0x40149E20, 0x80017F02, 0x00000002, 0x40149E20, 0x80018002, 0x00000002,
+ 0x40149E20, 0x80018102, 0x00000002, 0x40149E20, 0x80018202, 0x00000002,
+ 0x40149E20, 0x80018302, 0x00000002, 0x40149E20, 0x80018402, 0x00000002,
+ 0x40149E20, 0x80018502, 0x00000002, 0x40149E20, 0x80018602, 0x00000002,
+ 0x40149E20, 0x80018702, 0x00000002, 0x40149E20, 0x80018802, 0x00000002,
+ 0x40149E20, 0x80018902, 0x00000002, 0x40149E20,
+ // Block 14, offset 0x380
+ 0x80018A02, 0x00000002, 0x40149E20, 0x80018B02, 0x00000002, 0x40149E20,
+ 0x80019002, 0x00000002, 0x40149E20, 0x80019002, 0x00000002, 0x40149E20,
+ 0x80019002, 0x00000002, 0x40149E20, 0x80019002, 0x00000002, 0x40149E20,
+ 0x80019002, 0x00000002, 0x40149E20, 0x80019002, 0x00000002, 0x40149E20,
+ 0x80019002, 0x00000002, 0x40149E20, 0x80019002, 0x00000002, 0x40149E20,
+ 0x80019002, 0x00000002, 0x40149E20, 0x80019002, 0x00000002, 0x40149E20,
+ 0x80019002, 0x00000002, 0x40149E20, 0x80019002, 0x00000002, 0x40149E20,
+ 0x80019002, 0x00000002, 0x40149E20, 0x80019002, 0x00000002, 0x40149E20,
+ 0x80019002, 0x00000002, 0x40149E20, 0x80019402, 0x00000002, 0x40149E20,
+ 0x80019502, 0x00000002, 0x40149E20, 0x80019602, 0x00000002, 0x40149E20,
+ 0x80019702, 0x00000002, 0x40149E20, 0x80019802,
+ // Block 15, offset 0x3c0
+ 0x00000002, 0x40149E20, 0x80019902, 0x00000002, 0x00293C06, 0x00293406,
+ 0x00000002, 0x40149F20, 0x80016502, 0x00000002, 0x40149F20, 0x80016602,
+ 0x00000002, 0x40149F20, 0x80016702, 0x00000002, 0x40149F20, 0x80016802,
+ 0x00000002, 0x40149F20, 0x80016902, 0x00000002, 0x40149F20, 0x80016A02,
+ 0x00000002, 0x40149F20, 0x80016B02, 0x00000002, 0x40149F20, 0x80016C02,
+ 0x00000002, 0x40149F20, 0x80016D02, 0x00000002, 0x40149F20, 0x80016E02,
+ 0x00000002, 0x40149F20, 0x80016F02, 0x00000002, 0x40149F20, 0x80017002,
+ 0x00000002, 0x40149F20, 0x80017102, 0x00000002, 0x40149F20, 0x80017202,
+ 0x00000002, 0x40149F20, 0x80017302, 0x00000002, 0x40149F20, 0x80017402,
+ 0x00000002, 0x40149F20, 0x80017502, 0x00000002, 0x40149F20, 0x80017602,
+ 0x00000002, 0x40149F20, 0x80017702, 0x00000002,
+ // Block 16, offset 0x400
+ 0x40149F20, 0x80017802, 0x00000002, 0x40149F20, 0x80017902, 0x00000002,
+ 0x40149F20, 0x80017A02, 0x00000002, 0x40149F20, 0x80017B02, 0x00000002,
+ 0x40149F20, 0x80017C02, 0x00000002, 0x00293E04, 0x80017C04, 0x00000002,
+ 0x40149F20, 0x80017D02, 0x00000002, 0x40149F20, 0x80017E02, 0x00000002,
+ 0x40149F20, 0x80017F02, 0x00000002, 0x40149F20, 0x80018002, 0x00000002,
+ 0x40149F20, 0x80018102, 0x00000002, 0x40149F20, 0x80018202, 0x00000002,
+ 0x40149F20, 0x80018302, 0x00000002, 0x40149F20, 0x80018402, 0x00000002,
+ 0x40149F20, 0x80018502, 0x00000002, 0x40149F20, 0x80018602, 0x00000002,
+ 0x40149F20, 0x80018702, 0x00000002, 0x40149F20, 0x80018802, 0x00000002,
+ 0x40149F20, 0x80018902, 0x00000002, 0x40149F20, 0x80018A02, 0x00000002,
+ 0x40149F20, 0x80018B02, 0x00000002, 0x40149F20,
+ // Block 17, offset 0x440
+ 0x80018C02, 0x00000002, 0x40149F20, 0x80018C02, 0x00000002, 0x40149F20,
+ 0x80018C02, 0x00000002, 0x40149F20, 0x80018C02, 0x00000002, 0x40149F20,
+ 0x80018C02, 0x00000002, 0x40149F20, 0x80018E02, 0x00000002, 0x40149F20,
+ 0x80019002, 0x00000002, 0x40149F20, 0x80019002, 0x00000002, 0x40149F20,
+ 0x80019002, 0x00000002, 0x40149F20, 0x80019002, 0x00000002, 0x40149F20,
+ 0x80019002, 0x00000002, 0x40149F20, 0x80019002, 0x00000002, 0x40149F20,
+ 0x80019002, 0x00000002, 0x40149F20, 0x80019002, 0x00000002, 0x40149F20,
+ 0x80019002, 0x00000002, 0x40149F20, 0x80019002, 0x00000002, 0x40149F20,
+ 0x80019002, 0x00000002, 0x40149F20, 0x80019602, 0x00000002, 0x40149F20,
+ 0x80019702, 0x00000002, 0x40149F20, 0x80019902, 0x00000002, 0x00293E06,
+ 0x00293406, 0x00000002, 0x4014A020, 0x80016502,
+ // Block 18, offset 0x480
+ 0x00000002, 0x4014A020, 0x80016602, 0x00000002, 0x4014A020, 0x80016702,
+ 0x00000002, 0x4014A020, 0x80016802, 0x00000002, 0x4014A020, 0x80016902,
+ 0x00000002, 0x4014A020, 0x80016A02, 0x00000002, 0x4014A020, 0x80016B02,
+ 0x00000002, 0x4014A020, 0x80016C02, 0x00000002, 0x4014A020, 0x80016D02,
+ 0x00000002, 0x4014A020, 0x80016E02, 0x00000002, 0x4014A020, 0x80016F02,
+ 0x00000002, 0x4014A020, 0x80017002, 0x00000002, 0x4014A020, 0x80017102,
+ 0x00000002, 0x4014A020, 0x80017202, 0x00000002, 0x4014A020, 0x80017302,
+ 0x00000002, 0x4014A020, 0x80017402, 0x00000002, 0x4014A020, 0x80017502,
+ 0x00000002, 0x4014A020, 0x80017602, 0x00000002, 0x4014A020, 0x80017702,
+ 0x00000002, 0x4014A020, 0x80017802, 0x00000002, 0x4014A020, 0x80017902,
+ 0x00000002, 0x4014A020, 0x80017A02, 0x00000002,
+ // Block 19, offset 0x4c0
+ 0x4014A020, 0x80017B02, 0x00000002, 0x4014A020, 0x80017C02, 0x00000002,
+ 0x00294004, 0x80017C04, 0x00000002, 0x4014A020, 0x80017D02, 0x00000002,
+ 0x4014A020, 0x80017E02, 0x00000002, 0x4014A020, 0x80017F02, 0x00000002,
+ 0x4014A020, 0x80018002, 0x00000002, 0x4014A020, 0x80018102, 0x00000002,
+ 0x4014A020, 0x80018202, 0x00000002, 0x4014A020, 0x80018302, 0x00000002,
+ 0x4014A020, 0x80018402, 0x00000002, 0x4014A020, 0x80018502, 0x00000002,
+ 0x4014A020, 0x80018602, 0x00000002, 0x4014A020, 0x80018702, 0x00000002,
+ 0x4014A020, 0x80018802, 0x00000002, 0x4014A020, 0x80018902, 0x00000002,
+ 0x4014A020, 0x80018A02, 0x00000002, 0x4014A020, 0x80018B02, 0x00000002,
+ 0x4014A020, 0x80018D02, 0x00000002, 0x4014A020, 0x80019002, 0x00000002,
+ 0x4014A020, 0x80019002, 0x00000002, 0x4014A020,
+ // Block 20, offset 0x500
+ 0x80019002, 0x00000002, 0x4014A020, 0x80019002, 0x00000002, 0x4014A020,
+ 0x80019002, 0x00000002, 0x4014A020, 0x80019002, 0x00000002, 0x4014A020,
+ 0x80019002, 0x00000002, 0x4014A020, 0x80019602, 0x00000002, 0x4014A020,
+ 0x80019702, 0x00000002, 0x4014A020, 0x80019902, 0x00000002, 0x00294006,
+ 0x00293406, 0x00000002, 0x4014A120, 0x80016502, 0x00000002, 0x4014A120,
+ 0x80016602, 0x00000002, 0x4014A120, 0x80016702, 0x00000002, 0x4014A120,
+ 0x80016802, 0x00000002, 0x4014A120, 0x80016902, 0x00000002, 0x4014A120,
+ 0x80016A02, 0x00000002, 0x4014A120, 0x80016B02, 0x00000002, 0x4014A120,
+ 0x80016C02, 0x00000002, 0x4014A120, 0x80016D02, 0x00000002, 0x4014A120,
+ 0x80016E02, 0x00000002, 0x4014A120, 0x80016F02, 0x00000002, 0x4014A120,
+ 0x80017002, 0x00000002, 0x4014A120, 0x80017102,
+ // Block 21, offset 0x540
+ 0x00000002, 0x4014A120, 0x80017202, 0x00000002, 0x4014A120, 0x80017302,
+ 0x00000002, 0x4014A120, 0x80017402, 0x00000002, 0x4014A120, 0x80017502,
+ 0x00000002, 0x4014A120, 0x80017602, 0x00000002, 0x4014A120, 0x80017702,
+ 0x00000002, 0x4014A120, 0x80017802, 0x00000002, 0x4014A120, 0x80017902,
+ 0x00000002, 0x4014A120, 0x80017A02, 0x00000002, 0x4014A120, 0x80017B02,
+ 0x00000002, 0x4014A120, 0x80017C02, 0x00000002, 0x00294204, 0x80017C04,
+ 0x00000002, 0x4014A120, 0x80017D02, 0x00000002, 0x4014A120, 0x80017E02,
+ 0x00000002, 0x4014A120, 0x80017F02, 0x00000002, 0x4014A120, 0x80018002,
+ 0x00000002, 0x4014A120, 0x80018102, 0x00000002, 0x4014A120, 0x80018202,
+ 0x00000002, 0x4014A120, 0x80018302, 0x00000002, 0x4014A120, 0x80018402,
+ 0x00000002, 0x4014A120, 0x80018502, 0x00000002,
+ // Block 22, offset 0x580
+ 0x4014A120, 0x80018602, 0x00000002, 0x4014A120, 0x80018702, 0x00000002,
+ 0x4014A120, 0x80018802, 0x00000002, 0x4014A120, 0x80018902, 0x00000002,
+ 0x4014A120, 0x80018A02, 0x00000002, 0x4014A120, 0x80018B02, 0x00000002,
+ 0x4014A120, 0x80019002, 0x00000002, 0x4014A120, 0x80019002, 0x00000002,
+ 0x4014A120, 0x80019002, 0x00000002, 0x4014A120, 0x80019002, 0x00000002,
+ 0x4014A120, 0x80019002, 0x00000002, 0x4014A120, 0x80019002, 0x00000002,
+ 0x4014A120, 0x80019002, 0x00000002, 0x4014A120, 0x80019002, 0x00000002,
+ 0x4014A120, 0x80019602, 0x00000002, 0x4014A120, 0x80019702, 0x00000002,
+ 0x4014A120, 0x80019902, 0x00000002, 0x00294206, 0x00293406, 0x00000002,
+ 0x4014A220, 0x80016502, 0x00000002, 0x4014A220, 0x80016602, 0x00000002,
+ 0x4014A220, 0x80016702, 0x00000002, 0x4014A220,
+ // Block 23, offset 0x5c0
+ 0x80016802, 0x00000002, 0x4014A220, 0x80016902, 0x00000002, 0x4014A220,
+ 0x80016A02, 0x00000002, 0x4014A220, 0x80016B02, 0x00000002, 0x4014A220,
+ 0x80016C02, 0x00000002, 0x4014A220, 0x80016D02, 0x00000002, 0x4014A220,
+ 0x80016E02, 0x00000002, 0x4014A220, 0x80016F02, 0x00000002, 0x4014A220,
+ 0x80017002, 0x00000002, 0x4014A220, 0x80017102, 0x00000002, 0x4014A220,
+ 0x80017202, 0x00000002, 0x4014A220, 0x80017302, 0x00000002, 0x4014A220,
+ 0x80017402, 0x00000002, 0x4014A220, 0x80017502, 0x00000002, 0x4014A220,
+ 0x80017602, 0x00000002, 0x4014A220, 0x80017702, 0x00000002, 0x4014A220,
+ 0x80017802, 0x00000002, 0x4014A220, 0x80017902, 0x00000002, 0x4014A220,
+ 0x80017A02, 0x00000002, 0x4014A220, 0x80017B02, 0x00000002, 0x4014A220,
+ 0x80017C02, 0x00000002, 0x00294404, 0x80017C04,
+ // Block 24, offset 0x600
+ 0x00000002, 0x4014A220, 0x80017D02, 0x00000002, 0x4014A220, 0x80017E02,
+ 0x00000002, 0x4014A220, 0x80017F02, 0x00000002, 0x4014A220, 0x80018002,
+ 0x00000002, 0x4014A220, 0x80018102, 0x00000002, 0x4014A220, 0x80018202,
+ 0x00000002, 0x4014A220, 0x80018302, 0x00000002, 0x4014A220, 0x80018402,
+ 0x00000002, 0x4014A220, 0x80018502, 0x00000002, 0x4014A220, 0x80018602,
+ 0x00000002, 0x4014A220, 0x80018702, 0x00000002, 0x4014A220, 0x80018802,
+ 0x00000002, 0x4014A220, 0x80018902, 0x00000002, 0x4014A220, 0x80018A02,
+ 0x00000002, 0x4014A220, 0x80018B02, 0x00000002, 0x4014A220, 0x80019002,
+ 0x00000002, 0x4014A220, 0x80019002, 0x00000002, 0x4014A220, 0x80019002,
+ 0x00000002, 0x4014A220, 0x80019002, 0x00000002, 0x4014A220, 0x80019002,
+ 0x00000002, 0x4014A220, 0x80019002, 0x00000002,
+ // Block 25, offset 0x640
+ 0x4014A220, 0x80019002, 0x00000002, 0x4014A220, 0x80019602, 0x00000002,
+ 0x4014A220, 0x80019702, 0x00000002, 0x4014A220, 0x80019902, 0x00000002,
+ 0x00294406, 0x00293406, 0x00000002, 0x4014A320, 0x80016502, 0x00000002,
+ 0x4014A320, 0x80016602, 0x00000002, 0x4014A320, 0x80016702, 0x00000002,
+ 0x4014A320, 0x80016802, 0x00000002, 0x4014A320, 0x80016902, 0x00000002,
+ 0x4014A320, 0x80016A02, 0x00000002, 0x4014A320, 0x80016B02, 0x00000002,
+ 0x4014A320, 0x80016C02, 0x00000002, 0x4014A320, 0x80016D02, 0x00000002,
+ 0x4014A320, 0x80016E02, 0x00000002, 0x4014A320, 0x80016F02, 0x00000002,
+ 0x4014A320, 0x80017002, 0x00000002, 0x4014A320, 0x80017102, 0x00000002,
+ 0x4014A320, 0x80017202, 0x00000002, 0x4014A320, 0x80017302, 0x00000002,
+ 0x4014A320, 0x80017402, 0x00000002, 0x4014A320,
+ // Block 26, offset 0x680
+ 0x80017502, 0x00000002, 0x4014A320, 0x80017602, 0x00000002, 0x4014A320,
+ 0x80017702, 0x00000002, 0x4014A320, 0x80017802, 0x00000002, 0x4014A320,
+ 0x80017902, 0x00000002, 0x4014A320, 0x80017A02, 0x00000002, 0x4014A320,
+ 0x80017B02, 0x00000002, 0x4014A320, 0x80017C02, 0x00000002, 0x00294604,
+ 0x80017C04, 0x00000002, 0x4014A320, 0x80017D02, 0x00000002, 0x4014A320,
+ 0x80017E02, 0x00000002, 0x4014A320, 0x80017F02, 0x00000002, 0x4014A320,
+ 0x80018002, 0x00000002, 0x4014A320, 0x80018102, 0x00000002, 0x4014A320,
+ 0x80018202, 0x00000002, 0x4014A320, 0x80018302, 0x00000002, 0x4014A320,
+ 0x80018402, 0x00000002, 0x4014A320, 0x80018502, 0x00000002, 0x4014A320,
+ 0x80018602, 0x00000002, 0x4014A320, 0x80018702, 0x00000002, 0x4014A320,
+ 0x80018802, 0x00000002, 0x4014A320, 0x80018902,
+ // Block 27, offset 0x6c0
+ 0x00000002, 0x4014A320, 0x80018A02, 0x00000002, 0x4014A320, 0x80018B02,
+ 0x00000002, 0x4014A320, 0x80019002, 0x00000002, 0x4014A320, 0x80019002,
+ 0x00000002, 0x4014A320, 0x80019002, 0x00000002, 0x4014A320, 0x80019002,
+ 0x00000002, 0x4014A320, 0x80019002, 0x00000002, 0x4014A320, 0x80019002,
+ 0x00000002, 0x4014A320, 0x80019002, 0x00000002, 0x4014A320, 0x80019002,
+ 0x00000002, 0x4014A320, 0x80019002, 0x00000002, 0x4014A320, 0x80019602,
+ 0x00000002, 0x4014A320, 0x80019702, 0x00000002, 0x4014A320, 0x80019902,
+ 0x00000002, 0x002B4604, 0x80015F04, 0x00000002, 0x002B4604, 0x002B4604,
+ 0x00000002, 0x002B460A, 0x002B460A, 0x00000002, 0x002B461D, 0x002B721D,
+ 0x00000003, 0x002B4604, 0x80015F04, 0x002BFE1F, 0x00000003, 0x002B4604,
+ 0x80015F04, 0x002BFE1F, 0x00000003, 0x002B460A,
+ // Block 28, offset 0x700
+ 0x80015F04, 0x002BFE1F, 0x00000002, 0x002B4604, 0x002E4804, 0x00000002,
+ 0x002B4604, 0x002E4804, 0x00000002, 0x002B460A, 0x002E480A, 0x00000002,
+ 0x002B4604, 0x002FD204, 0x00000002, 0x002B460A, 0x002FD20A, 0x00000002,
+ 0x002B4604, 0x00302404, 0x00000002, 0x002B4604, 0x00302404, 0x00000002,
+ 0x002B460A, 0x0030240A, 0x00000003, 0x002B4604, 0x80015F04, 0x0030241F,
+ 0x00000003, 0x002B460A, 0x80015F04, 0x0030241F, 0x00000002, 0x002B4604,
+ 0x00306604, 0x00000002, 0x002B460A, 0x0030660A, 0x00000002, 0x002BA204,
+ 0x80005604, 0x00000002, 0x002BA21D, 0x002D881D, 0x00000004, 0x002BA21D,
+ 0x002E481D, 0x002E481F, 0x002D881F, 0x00000002, 0x4015E420, 0x80007D02,
+ 0x00000002, 0x002BC808, 0x80007D02, 0x00000002, 0x002BC804, 0x80015F04,
+ 0x00000002, 0x002BC804, 0x80015F04, 0x00000002,
+ // Block 29, offset 0x740
+ 0x002BC80A, 0x80015F04, 0x00000002, 0x002BC804, 0x80016004, 0x00000002,
+ 0x002BC804, 0x80016004, 0x00000002, 0x002BC80A, 0x80016004, 0x00000002,
+ 0x002BC804, 0x002B7204, 0x00000002, 0x002BC804, 0x00308804, 0x00000002,
+ 0x002BC804, 0x0030AE04, 0x00000002, 0x002BC804, 0x0030C204, 0x00000002,
+ 0x002C6E04, 0x80016004, 0x00000002, 0x002C6E0A, 0x80016004, 0x00000002,
+ 0x002C6E04, 0x002E4004, 0x00000004, 0x002C6E1D, 0x002EE01D, 0x002BFE1F,
+ 0x002BFE1F, 0x00000002, 0x002C8804, 0x80006104, 0x00000002, 0x002C880A,
+ 0x80006104, 0x00000002, 0x002C8804, 0x80016004, 0x00000002, 0x002C880A,
+ 0x80016004, 0x00000002, 0x40166720, 0x80007D02, 0x00000002, 0x002CCE08,
+ 0x80007D02, 0x00000002, 0x002D001D, 0x002BA21D, 0x00000002, 0x002D001D,
+ 0x002BC81D, 0x00000002, 0x002D6404, 0x80006104,
+ // Block 30, offset 0x780
+ 0x00000002, 0x002D640A, 0x80006104, 0x00000002, 0x4016C420, 0x80007D02,
+ 0x00000002, 0x002D8808, 0x80007D02, 0x00000002, 0x4016C420, 0x80015F02,
+ 0x00000002, 0x4016C420, 0x80015F02, 0x00000002, 0x002D8808, 0x80015F02,
+ 0x00000002, 0x002D8808, 0x80015F02, 0x00000002, 0x002D8804, 0x002D8804,
+ 0x00000002, 0x002D880A, 0x002D880A, 0x00000002, 0x002D8804, 0x002F4C04,
+ 0x00000002, 0x002D8804, 0x00308804, 0x00000002, 0x002E0404, 0x80006104,
+ 0x00000002, 0x002E040A, 0x80006104, 0x00000003, 0x002E041D, 0x002BFE1D,
+ 0x0030481F, 0x00000002, 0x002E041D, 0x002C881D, 0x00000002, 0x40172420,
+ 0x80005402, 0x00000002, 0x002E4808, 0x80005402, 0x00000003, 0x002E4804,
+ 0x80015F04, 0x002BFE1F, 0x00000003, 0x002E480A, 0x80015F04, 0x002BFE1F,
+ 0x00000002, 0x002E481D, 0x002D641D, 0x00000002,
+ // Block 31, offset 0x7c0
+ 0x002E4804, 0x002E4804, 0x00000002, 0x002E480A, 0x002E480A, 0x00000002,
+ 0x002E921D, 0x002B461D, 0x00000002, 0x002EBC04, 0x002E9204, 0x00000002,
+ 0x002EE004, 0x80006104, 0x00000002, 0x002EE00A, 0x80006104, 0x00000002,
+ 0x002EE004, 0x80016004, 0x00000002, 0x002EE00A, 0x80016004, 0x00000002,
+ 0x002F4C04, 0x80006104, 0x00000002, 0x002F4C0A, 0x80006104, 0x00000002,
+ 0x002F4C04, 0x80016004, 0x00000002, 0x002F4C04, 0x80016004, 0x00000002,
+ 0x002F4C04, 0x80016004, 0x00000002, 0x002F4C0A, 0x80016004, 0x00000002,
+ 0x002F4C1D, 0x002B461D, 0x00000003, 0x002F4C1D, 0x002E481D, 0x002F4C1F,
+ 0x00000003, 0x002F4C04, 0x80015F04, 0x002F4C1F, 0x00000003, 0x002F4C0A,
+ 0x80015F04, 0x002F4C1F, 0x00000003, 0x002F4C04, 0x80016004, 0x002F921F,
+ 0x00000002, 0x002F9204, 0x80016004, 0x00000002,
+ // Block 32, offset 0x800
+ 0x002F920A, 0x80016004, 0x00000002, 0x002F9204, 0x002BBC04, 0x00000003,
+ 0x002F9204, 0x80015F04, 0x002CCE1F, 0x00000002, 0x002F9204, 0x002F4C04,
+ 0x00000002, 0x002F9204, 0x002F4C04, 0x00000002, 0x002F9204, 0x002F6E04,
+ 0x00000002, 0x002F9204, 0x00308804, 0x00000002, 0x002F920A, 0x00308804,
+ 0x00000003, 0x002FD21D, 0x002E921D, 0x0002B01F, 0x00000002, 0x0030241D,
+ 0x002F4C1D, 0x00000002, 0x00302404, 0x00306604, 0x00000002, 0x0030240A,
+ 0x0030660A, 0x00000002, 0x0030481D, 0x002BA21D, 0x00000002, 0x00308804,
+ 0x00304804, 0x00000003, 0x0031D604, 0x0031B804, 0x0031D21F, 0x00000003,
+ 0x0031D60A, 0x0031B804, 0x0031D21F, 0x00000003, 0x00322604, 0x00321004,
+ 0x0032241F, 0x00000002, 0x0032C604, 0x80016004, 0x00000002, 0x0032C60A,
+ 0x80016004, 0x00000002, 0x00349E04, 0x0034B004,
+ // Block 33, offset 0x840
+ 0x00000002, 0x0037F404, 0x0037F404, 0x00000002, 0x0037F404, 0x0037FC04,
+ 0x00000002, 0x0037FC04, 0x0037FC04, 0x00000002, 0x00387604, 0x80016004,
+ 0x00000002, 0x00388A19, 0x00388C19, 0x00000002, 0x00388A1A, 0x00388C1A,
+ 0x00000002, 0x00388A17, 0x0038B617, 0x00000002, 0x00388A1A, 0x0038B61A,
+ 0x00000002, 0x00388A17, 0x0038C217, 0x00000002, 0x00388A1A, 0x0038C21A,
+ 0x00000002, 0x00388A17, 0x0038C417, 0x00000002, 0x00388A19, 0x0038F419,
+ 0x00000002, 0x00388A19, 0x0038F619, 0x00000002, 0x00388A17, 0x00399417,
+ 0x00000002, 0x00388A18, 0x00399418, 0x00000002, 0x00388A19, 0x00399419,
+ 0x00000002, 0x00388A1A, 0x0039941A, 0x00000002, 0x00388A19, 0x00399A19,
+ 0x00000002, 0x00388A17, 0x0039AC17, 0x00000002, 0x00388A18, 0x0039AC18,
+ 0x00000002, 0x00388A19, 0x0039B619, 0x00000002,
+ // Block 34, offset 0x880
+ 0x00388A1A, 0x0039B61A, 0x00000002, 0x00388A19, 0x0039B819, 0x00000002,
+ 0x00388A1A, 0x0039B81A, 0x00000002, 0x00388A19, 0x0039BE19, 0x00000002,
+ 0x00388A1A, 0x0039BE1A, 0x00000002, 0x00388A19, 0x0039C019, 0x00000002,
+ 0x00388A1A, 0x0039C01A, 0x00000002, 0x00388A19, 0x0039C219, 0x00000002,
+ 0x00388A1A, 0x0039C21A, 0x00000002, 0x00388A17, 0x0039D017, 0x00000002,
+ 0x00388A19, 0x0039D019, 0x00000002, 0x00388A19, 0x0039D019, 0x00000002,
+ 0x00388A1A, 0x0039D01A, 0x00000002, 0x00388A1A, 0x0039D01A, 0x00000002,
+ 0x00388A19, 0x0039D219, 0x00000002, 0x00388A1A, 0x0039D21A, 0x00000002,
+ 0x00388A17, 0x0039DA17, 0x00000002, 0x00388A19, 0x0039DA19, 0x00000002,
+ 0x00388A1A, 0x0039DA1A, 0x00000002, 0x00398819, 0x00387819, 0x00000002,
+ 0x0039881A, 0x0038781A, 0x00000002, 0x00398819,
+ // Block 35, offset 0x8c0
+ 0x00387A19, 0x00000002, 0x0039881A, 0x00387A1A, 0x00000002, 0x00398819,
+ 0x00388219, 0x00000002, 0x0039881A, 0x0038821A, 0x00000002, 0x00399404,
+ 0x80016004, 0x00000002, 0x0039F404, 0x80016204, 0x00000002, 0x0039F604,
+ 0x80016004, 0x00000002, 0x0039F604, 0x80016204, 0x00000002, 0x0039FA04,
+ 0x80016204, 0x00000002, 0x003A0604, 0x80016004, 0x00000002, 0x003A1A04,
+ 0x80016004, 0x00000002, 0x003AD604, 0x80015F04, 0x00000002, 0x003AD804,
+ 0x80015F04, 0x00000002, 0x003ADC04, 0x80015F04, 0x00000002, 0x003FF004,
+ 0x00403204, 0x00000002, 0x00435C04, 0x0043CA04, 0x00000002, 0x00437804,
+ 0x0043CA04, 0x00000002, 0x00438204, 0x0043CA04, 0x00000002, 0x00439204,
+ 0x0043CA04, 0x00000002, 0x00439204, 0x0043CA04, 0x00000002, 0x00439404,
+ 0x0043CA04, 0x00000002, 0x0043A004, 0x0043CA04,
+ // Block 36, offset 0x900
+ 0x00000002, 0x40239520, 0x00479E1F, 0x00000002, 0x40239520, 0x0047A01F,
+ 0x00000002, 0x40239520, 0x0047A21F, 0x00000002, 0x40239520, 0x0047A41F,
+ 0x00000002, 0x40239520, 0x0047A61F, 0x00000002, 0x40239620, 0x00479E1F,
+ 0x00000002, 0x40239620, 0x0047A01F, 0x00000002, 0x40239620, 0x0047A21F,
+ 0x00000002, 0x40239620, 0x0047A41F, 0x00000002, 0x40239620, 0x0047A61F,
+ 0x00000002, 0x40239720, 0x00479E1F, 0x00000002, 0x40239720, 0x0047A01F,
+ 0x00000002, 0x40239720, 0x0047A21F, 0x00000002, 0x40239720, 0x0047A41F,
+ 0x00000002, 0x40239720, 0x0047A61F, 0x00000002, 0x40239820, 0x00479E1F,
+ 0x00000002, 0x40239820, 0x0047A01F, 0x00000002, 0x40239820, 0x0047A21F,
+ 0x00000002, 0x40239820, 0x0047A41F, 0x00000002, 0x40239820, 0x0047A61F,
+ 0x00000002, 0x40239920, 0x00479E1F, 0x00000002,
+ // Block 37, offset 0x940
+ 0x40239920, 0x0047A01F, 0x00000002, 0x40239920, 0x0047A21F, 0x00000002,
+ 0x40239920, 0x0047A41F, 0x00000002, 0x40239920, 0x0047A61F, 0x00000002,
+ 0x40239A20, 0x00479E1F, 0x00000002, 0x40239A20, 0x0047A01F, 0x00000002,
+ 0x40239A20, 0x0047A21F, 0x00000002, 0x40239A20, 0x0047A41F, 0x00000002,
+ 0x40239A20, 0x0047A61F, 0x00000002, 0x40239B20, 0x00479E1F, 0x00000002,
+ 0x40239B20, 0x0047A01F, 0x00000002, 0x40239B20, 0x0047A21F, 0x00000002,
+ 0x40239B20, 0x0047A41F, 0x00000002, 0x40239B20, 0x0047A61F, 0x00000002,
+ 0x40239C20, 0x00479E1F, 0x00000002, 0x40239C20, 0x0047A01F, 0x00000002,
+ 0x40239C20, 0x0047A21F, 0x00000002, 0x40239C20, 0x0047A41F, 0x00000002,
+ 0x40239C20, 0x0047A61F, 0x00000002, 0x40239D20, 0x00479E1F, 0x00000002,
+ 0x40239D20, 0x0047A01F, 0x00000002, 0x40239D20,
+ // Block 38, offset 0x980
+ 0x0047A21F, 0x00000002, 0x40239D20, 0x0047A41F, 0x00000002, 0x40239D20,
+ 0x0047A61F, 0x00000002, 0x40239E20, 0x00479E1F, 0x00000002, 0x40239E20,
+ 0x0047A01F, 0x00000002, 0x40239E20, 0x0047A21F, 0x00000002, 0x40239E20,
+ 0x0047A41F, 0x00000002, 0x40239E20, 0x0047A61F, 0x00000002, 0x40239F20,
+ 0x00479E1F, 0x00000002, 0x40239F20, 0x0047A01F, 0x00000002, 0x40239F20,
+ 0x0047A21F, 0x00000002, 0x40239F20, 0x0047A41F, 0x00000002, 0x40239F20,
+ 0x0047A61F, 0x00000002, 0x4023A020, 0x00479E1F, 0x00000002, 0x4023A020,
+ 0x0047A01F, 0x00000002, 0x4023A020, 0x0047A21F, 0x00000002, 0x4023A020,
+ 0x0047A41F, 0x00000002, 0x4023A020, 0x0047A61F, 0x00000002, 0x4023A120,
+ 0x00479E1F, 0x00000002, 0x4023A120, 0x0047A01F, 0x00000002, 0x4023A120,
+ 0x0047A21F, 0x00000002, 0x4023A120, 0x0047A41F,
+ // Block 39, offset 0x9c0
+ 0x00000002, 0x4023A120, 0x0047A61F, 0x00000002, 0x4023A220, 0x00479E1F,
+ 0x00000002, 0x4023A220, 0x0047A01F, 0x00000002, 0x4023A220, 0x0047A21F,
+ 0x00000002, 0x4023A220, 0x0047A41F, 0x00000002, 0x4023A220, 0x0047A61F,
+ 0x00000002, 0x4023A320, 0x00479E1F, 0x00000002, 0x4023A320, 0x0047A01F,
+ 0x00000002, 0x4023A320, 0x0047A21F, 0x00000002, 0x4023A320, 0x0047A41F,
+ 0x00000002, 0x4023A320, 0x0047A61F, 0x00000002, 0x4023A420, 0x00479E1F,
+ 0x00000002, 0x4023A420, 0x0047A01F, 0x00000002, 0x4023A420, 0x0047A21F,
+ 0x00000002, 0x4023A420, 0x0047A41F, 0x00000002, 0x4023A420, 0x0047A61F,
+ 0x00000002, 0x4023A520, 0x00479E1F, 0x00000002, 0x4023A520, 0x0047A01F,
+ 0x00000002, 0x4023A520, 0x0047A21F, 0x00000002, 0x4023A520, 0x0047A41F,
+ 0x00000002, 0x4023A520, 0x0047A61F, 0x00000002,
+ // Block 40, offset 0xa00
+ 0x4023A620, 0x00479E1F, 0x00000002, 0x4023A620, 0x0047A01F, 0x00000002,
+ 0x4023A620, 0x0047A21F, 0x00000002, 0x4023A620, 0x0047A41F, 0x00000002,
+ 0x4023A620, 0x0047A61F, 0x00000002, 0x4023A720, 0x00479E1F, 0x00000002,
+ 0x4023A720, 0x0047A01F, 0x00000002, 0x4023A720, 0x0047A21F, 0x00000002,
+ 0x4023A720, 0x0047A41F, 0x00000002, 0x4023A720, 0x0047A61F, 0x00000002,
+ 0x4023A820, 0x00479E1F, 0x00000002, 0x4023A820, 0x0047A01F, 0x00000002,
+ 0x4023A820, 0x0047A21F, 0x00000002, 0x4023A820, 0x0047A41F, 0x00000002,
+ 0x4023A820, 0x0047A61F, 0x00000002, 0x4023A920, 0x00479E1F, 0x00000002,
+ 0x4023A920, 0x0047A01F, 0x00000002, 0x4023A920, 0x0047A21F, 0x00000002,
+ 0x4023A920, 0x0047A41F, 0x00000002, 0x4023A920, 0x0047A61F, 0x00000002,
+ 0x4023AA20, 0x00479E1F, 0x00000002, 0x4023AA20,
+ // Block 41, offset 0xa40
+ 0x0047A01F, 0x00000002, 0x4023AA20, 0x0047A21F, 0x00000002, 0x4023AA20,
+ 0x0047A41F, 0x00000002, 0x4023AA20, 0x0047A61F, 0x00000002, 0x4023AB20,
+ 0x00479E1F, 0x00000002, 0x4023AB20, 0x0047A01F, 0x00000002, 0x4023AB20,
+ 0x0047A21F, 0x00000002, 0x4023AB20, 0x0047A41F, 0x00000002, 0x4023AB20,
+ 0x0047A61F, 0x00000002, 0x4023AC20, 0x00479E1F, 0x00000002, 0x4023AC20,
+ 0x0047A01F, 0x00000002, 0x4023AC20, 0x0047A21F, 0x00000002, 0x4023AC20,
+ 0x0047A41F, 0x00000002, 0x4023AC20, 0x0047A61F, 0x00000002, 0x4023AD20,
+ 0x00479E1F, 0x00000002, 0x4023AD20, 0x0047A01F, 0x00000002, 0x4023AD20,
+ 0x0047A21F, 0x00000002, 0x4023AD20, 0x0047A41F, 0x00000002, 0x4023AD20,
+ 0x0047A61F, 0x00000002, 0x4023AE20, 0x00479E1F, 0x00000002, 0x4023AE20,
+ 0x0047A01F, 0x00000002, 0x4023AE20, 0x0047A21F,
+ // Block 42, offset 0xa80
+ 0x00000002, 0x4023AE20, 0x0047A41F, 0x00000002, 0x4023AE20, 0x0047A61F,
+ 0x00000002, 0x4023AF20, 0x00479E1F, 0x00000002, 0x4023AF20, 0x0047A01F,
+ 0x00000002, 0x4023AF20, 0x0047A21F, 0x00000002, 0x4023AF20, 0x0047A41F,
+ 0x00000002, 0x4023AF20, 0x0047A61F, 0x00000002, 0x4023B020, 0x00479E1F,
+ 0x00000002, 0x4023B020, 0x0047A01F, 0x00000002, 0x4023B020, 0x0047A21F,
+ 0x00000002, 0x4023B020, 0x0047A41F, 0x00000002, 0x4023B020, 0x0047A61F,
+ 0x00000002, 0x4023B120, 0x00479E1F, 0x00000002, 0x4023B120, 0x0047A01F,
+ 0x00000002, 0x4023B120, 0x0047A21F, 0x00000002, 0x4023B120, 0x0047A41F,
+ 0x00000002, 0x4023B120, 0x0047A61F, 0x00000002, 0x4023B220, 0x00479E1F,
+ 0x00000002, 0x4023B220, 0x0047A01F, 0x00000002, 0x4023B220, 0x0047A21F,
+ 0x00000002, 0x4023B220, 0x0047A41F, 0x00000002,
+ // Block 43, offset 0xac0
+ 0x4023B220, 0x0047A61F, 0x00000002, 0x4023B320, 0x00479E1F, 0x00000002,
+ 0x4023B320, 0x0047A01F, 0x00000002, 0x4023B320, 0x0047A21F, 0x00000002,
+ 0x4023B320, 0x0047A41F, 0x00000002, 0x4023B320, 0x0047A61F, 0x00000002,
+ 0x4023B420, 0x00479E1F, 0x00000002, 0x4023B420, 0x0047A01F, 0x00000002,
+ 0x4023B420, 0x0047A21F, 0x00000002, 0x4023B420, 0x0047A41F, 0x00000002,
+ 0x4023B420, 0x0047A61F, 0x00000002, 0x4023B520, 0x00479E1F, 0x00000002,
+ 0x4023B520, 0x0047A01F, 0x00000002, 0x4023B520, 0x0047A21F, 0x00000002,
+ 0x4023B520, 0x0047A41F, 0x00000002, 0x4023B520, 0x0047A61F, 0x00000002,
+ 0x4023B620, 0x00479E1F, 0x00000002, 0x4023B620, 0x0047A01F, 0x00000002,
+ 0x4023B620, 0x0047A21F, 0x00000002, 0x4023B620, 0x0047A41F, 0x00000002,
+ 0x4023B620, 0x0047A61F, 0x00000002, 0x4023B720,
+ // Block 44, offset 0xb00
+ 0x00479E1F, 0x00000002, 0x4023B720, 0x0047A01F, 0x00000002, 0x4023B720,
+ 0x0047A21F, 0x00000002, 0x4023B720, 0x0047A41F, 0x00000002, 0x4023B720,
+ 0x0047A61F, 0x00000002, 0x4023B820, 0x00479E1F, 0x00000002, 0x4023B820,
+ 0x0047A01F, 0x00000002, 0x4023B820, 0x0047A21F, 0x00000002, 0x4023B820,
+ 0x0047A41F, 0x00000002, 0x4023B820, 0x0047A61F, 0x00000002, 0x4023B920,
+ 0x00479E1F, 0x00000002, 0x4023B920, 0x0047A01F, 0x00000002, 0x4023B920,
+ 0x0047A21F, 0x00000002, 0x4023B920, 0x0047A41F, 0x00000002, 0x4023B920,
+ 0x0047A61F, 0x00000002, 0x4023BA20, 0x00479E1F, 0x00000002, 0x4023BA20,
+ 0x0047A01F, 0x00000002, 0x4023BA20, 0x0047A21F, 0x00000002, 0x4023BA20,
+ 0x0047A41F, 0x00000002, 0x4023BA20, 0x0047A61F, 0x00000002, 0x4023BB20,
+ 0x00479E1F, 0x00000002, 0x4023BB20, 0x0047A01F,
+ // Block 45, offset 0xb40
+ 0x00000002, 0x4023BB20, 0x0047A21F, 0x00000002, 0x4023BB20, 0x0047A41F,
+ 0x00000002, 0x4023BB20, 0x0047A61F, 0x00000002, 0x4023BC20, 0x00479E1F,
+ 0x00000002, 0x4023BC20, 0x0047A01F, 0x00000002, 0x4023BC20, 0x0047A21F,
+ 0x00000002, 0x4023BC20, 0x0047A41F, 0x00000002, 0x4023BC20, 0x0047A61F,
+ 0x00000002, 0x4023BD20, 0x00479E1F, 0x00000002, 0x4023BD20, 0x0047A01F,
+ 0x00000002, 0x4023BD20, 0x0047A21F, 0x00000002, 0x4023BD20, 0x0047A41F,
+ 0x00000002, 0x4023BD20, 0x0047A61F, 0x00000002, 0x4023BE20, 0x00479E1F,
+ 0x00000002, 0x4023BE20, 0x0047A01F, 0x00000002, 0x4023BE20, 0x0047A21F,
+ 0x00000002, 0x4023BE20, 0x0047A41F, 0x00000002, 0x4023BE20, 0x0047A61F,
+ 0x00000002, 0x4023BF20, 0x00479E1F, 0x00000002, 0x4023BF20, 0x0047A01F,
+ 0x00000002, 0x4023BF20, 0x0047A21F, 0x00000002,
+ // Block 46, offset 0xb80
+ 0x4023BF20, 0x0047A41F, 0x00000002, 0x4023BF20, 0x0047A61F, 0x00000002,
+ 0x4023C020, 0x00479E1F, 0x00000002, 0x4023C020, 0x0047A01F, 0x00000002,
+ 0x4023C020, 0x0047A21F, 0x00000002, 0x4023C020, 0x0047A41F, 0x00000002,
+ 0x4023C020, 0x0047A61F, 0x00000002, 0x4023C120, 0x00479E1F, 0x00000002,
+ 0x4023C120, 0x0047A01F, 0x00000002, 0x4023C120, 0x0047A21F, 0x00000002,
+ 0x4023C120, 0x0047A41F, 0x00000002, 0x4023C120, 0x0047A61F, 0x00000002,
+ 0x4023C220, 0x00479E1F, 0x00000002, 0x4023C220, 0x0047A01F, 0x00000002,
+ 0x4023C220, 0x0047A21F, 0x00000002, 0x4023C220, 0x0047A41F, 0x00000002,
+ 0x4023C220, 0x0047A61F, 0x00000002, 0x4023D520, 0x0047FC1F, 0x00000002,
+ 0x4023D520, 0x0047FE1F, 0x00000002, 0x4023D520, 0x0048001F, 0x00000002,
+ 0x4023D520, 0x0048021F, 0x00000002, 0x4023D520,
+ // Block 47, offset 0xbc0
+ 0x0048041F, 0x00000002, 0x4023D620, 0x0047FC1F, 0x00000002, 0x4023D620,
+ 0x0047FE1F, 0x00000002, 0x4023D620, 0x0048001F, 0x00000002, 0x4023D620,
+ 0x0048021F, 0x00000002, 0x4023D620, 0x0048041F, 0x00000002, 0x4023D720,
+ 0x0047FC1F, 0x00000002, 0x4023D720, 0x0047FE1F, 0x00000002, 0x4023D720,
+ 0x0048001F, 0x00000002, 0x4023D720, 0x0048021F, 0x00000002, 0x4023D720,
+ 0x0048041F, 0x00000002, 0x4023D820, 0x0047FC1F, 0x00000002, 0x4023D820,
+ 0x0047FE1F, 0x00000002, 0x4023D820, 0x0048001F, 0x00000002, 0x4023D820,
+ 0x0048021F, 0x00000002, 0x4023D820, 0x0048041F, 0x00000002, 0x4023D920,
+ 0x0047FC1F, 0x00000002, 0x4023D920, 0x0047FE1F, 0x00000002, 0x4023D920,
+ 0x0048001F, 0x00000002, 0x4023D920, 0x0048021F, 0x00000002, 0x4023D920,
+ 0x0048041F, 0x00000002, 0x4023DA20, 0x0047FC1F,
+ // Block 48, offset 0xc00
+ 0x00000002, 0x4023DA20, 0x0047FE1F, 0x00000002, 0x4023DA20, 0x0048001F,
+ 0x00000002, 0x4023DA20, 0x0048021F, 0x00000002, 0x4023DA20, 0x0048041F,
+ 0x00000002, 0x4023DB20, 0x0047FC1F, 0x00000002, 0x4023DB20, 0x0047FE1F,
+ 0x00000002, 0x4023DB20, 0x0048001F, 0x00000002, 0x4023DB20, 0x0048021F,
+ 0x00000002, 0x4023DB20, 0x0048041F, 0x00000002, 0x4023DC20, 0x0047FC1F,
+ 0x00000002, 0x4023DC20, 0x0047FE1F, 0x00000002, 0x4023DC20, 0x0048001F,
+ 0x00000002, 0x4023DC20, 0x0048021F, 0x00000002, 0x4023DC20, 0x0048041F,
+ 0x00000002, 0x4023DD20, 0x0047FC1F, 0x00000002, 0x4023DD20, 0x0047FE1F,
+ 0x00000002, 0x4023DD20, 0x0048001F, 0x00000002, 0x4023DD20, 0x0048021F,
+ 0x00000002, 0x4023DD20, 0x0048041F, 0x00000002, 0x4023DE20, 0x0047FC1F,
+ 0x00000002, 0x4023DE20, 0x0047FE1F, 0x00000002,
+ // Block 49, offset 0xc40
+ 0x4023DE20, 0x0048001F, 0x00000002, 0x4023DE20, 0x0048021F, 0x00000002,
+ 0x4023DE20, 0x0048041F, 0x00000002, 0x4023DF20, 0x0047FC1F, 0x00000002,
+ 0x4023DF20, 0x0047FE1F, 0x00000002, 0x4023DF20, 0x0048001F, 0x00000002,
+ 0x4023DF20, 0x0048021F, 0x00000002, 0x4023DF20, 0x0048041F, 0x00000002,
+ 0x4023E020, 0x0047FC1F, 0x00000002, 0x4023E020, 0x0047FE1F, 0x00000002,
+ 0x4023E020, 0x0048001F, 0x00000002, 0x4023E020, 0x0048021F, 0x00000002,
+ 0x4023E020, 0x0048041F, 0x00000002, 0x4023E120, 0x0047FC1F, 0x00000002,
+ 0x4023E120, 0x0047FE1F, 0x00000002, 0x4023E120, 0x0048001F, 0x00000002,
+ 0x4023E120, 0x0048021F, 0x00000002, 0x4023E120, 0x0048041F, 0x00000002,
+ 0x4023E220, 0x0047FC1F, 0x00000002, 0x4023E220, 0x0047FE1F, 0x00000002,
+ 0x4023E220, 0x0048001F, 0x00000002, 0x4023E220,
+ // Block 50, offset 0xc80
+ 0x0048021F, 0x00000002, 0x4023E220, 0x0048041F, 0x00000002, 0x4023E320,
+ 0x0047FC1F, 0x00000002, 0x4023E320, 0x0047FE1F, 0x00000002, 0x4023E320,
+ 0x0048001F, 0x00000002, 0x4023E320, 0x0048021F, 0x00000002, 0x4023E320,
+ 0x0048041F, 0x00000002, 0x4023E420, 0x0047FC1F, 0x00000002, 0x4023E420,
+ 0x0047FE1F, 0x00000002, 0x4023E420, 0x0048001F, 0x00000002, 0x4023E420,
+ 0x0048021F, 0x00000002, 0x4023E420, 0x0048041F, 0x00000002, 0x4023E520,
+ 0x0047FC1F, 0x00000002, 0x4023E520, 0x0047FE1F, 0x00000002, 0x4023E520,
+ 0x0048001F, 0x00000002, 0x4023E520, 0x0048021F, 0x00000002, 0x4023E520,
+ 0x0048041F, 0x00000002, 0x4023E620, 0x0047FC1F, 0x00000002, 0x4023E620,
+ 0x0047FE1F, 0x00000002, 0x4023E620, 0x0048001F, 0x00000002, 0x4023E620,
+ 0x0048021F, 0x00000002, 0x4023E620, 0x0048041F,
+ // Block 51, offset 0xcc0
+ 0x00000002, 0x4023E720, 0x0047FC1F, 0x00000002, 0x4023E720, 0x0047FE1F,
+ 0x00000002, 0x4023E720, 0x0048001F, 0x00000002, 0x4023E720, 0x0048021F,
+ 0x00000002, 0x4023E720, 0x0048041F, 0x00000002, 0x4023E820, 0x0047FC1F,
+ 0x00000002, 0x4023E820, 0x0047FE1F, 0x00000002, 0x4023E820, 0x0048001F,
+ 0x00000002, 0x4023E820, 0x0048021F, 0x00000002, 0x4023E820, 0x0048041F,
+ 0x00000002, 0x4023E920, 0x0047FC1F, 0x00000002, 0x4023E920, 0x0047FE1F,
+ 0x00000002, 0x4023E920, 0x0048001F, 0x00000002, 0x4023E920, 0x0048021F,
+ 0x00000002, 0x4023E920, 0x0048041F, 0x00000002, 0x4023EA20, 0x0047FC1F,
+ 0x00000002, 0x4023EA20, 0x0047FE1F, 0x00000002, 0x4023EA20, 0x0048001F,
+ 0x00000002, 0x4023EA20, 0x0048021F, 0x00000002, 0x4023EA20, 0x0048041F,
+ 0x00000002, 0x4023EB20, 0x0047FC1F, 0x00000002,
+ // Block 52, offset 0xd00
+ 0x4023EB20, 0x0047FE1F, 0x00000002, 0x4023EB20, 0x0048001F, 0x00000002,
+ 0x4023EB20, 0x0048021F, 0x00000002, 0x4023EB20, 0x0048041F, 0x00000002,
+ 0x4023EC20, 0x0047FC1F, 0x00000002, 0x4023EC20, 0x0047FE1F, 0x00000002,
+ 0x4023EC20, 0x0048001F, 0x00000002, 0x4023EC20, 0x0048021F, 0x00000002,
+ 0x4023EC20, 0x0048041F, 0x00000003, 0x0047DA04, 0x0047C204, 0x0047FC1F,
+ 0x00000003, 0x0047DA04, 0x0047C204, 0x0047FE1F, 0x00000003, 0x0047DA04,
+ 0x0047C204, 0x0048001F, 0x00000003, 0x0047DA04, 0x0047C204, 0x0048021F,
+ 0x00000003, 0x0047DA04, 0x0047C204, 0x0048041F, 0x00000003, 0x0047DA04,
+ 0x0047D004, 0x0047FC1F, 0x00000003, 0x0047DA04, 0x0047D004, 0x0047FE1F,
+ 0x00000003, 0x0047DA04, 0x0047D004, 0x0048001F, 0x00000003, 0x0047DA04,
+ 0x0047D004, 0x0048021F, 0x00000003, 0x0047DA04,
+ // Block 53, offset 0xd40
+ 0x0047D004, 0x0048041F, 0x00000002, 0x4023ED20, 0x0047FC1F, 0x00000002,
+ 0x4023ED20, 0x0047FE1F, 0x00000002, 0x4023ED20, 0x0048001F, 0x00000002,
+ 0x4023ED20, 0x0048021F, 0x00000002, 0x4023ED20, 0x0048041F, 0x00000002,
+ 0x4023EE20, 0x0047FC1F, 0x00000002, 0x4023EE20, 0x0047FE1F, 0x00000002,
+ 0x4023EE20, 0x0048001F, 0x00000002, 0x4023EE20, 0x0048021F, 0x00000002,
+ 0x4023EE20, 0x0048041F, 0x00000002, 0x4023EF20, 0x0047FC1F, 0x00000002,
+ 0x4023EF20, 0x0047FE1F, 0x00000002, 0x4023EF20, 0x0048001F, 0x00000002,
+ 0x4023EF20, 0x0048021F, 0x00000002, 0x4023EF20, 0x0048041F, 0x00000002,
+ 0x40240320, 0x0048701F, 0x00000002, 0x40240320, 0x0048721F, 0x00000002,
+ 0x40240320, 0x0048781F, 0x00000002, 0x40240320, 0x00487C1F, 0x00000002,
+ 0x40240320, 0x00487E1F, 0x00000002, 0x40240420,
+ // Block 54, offset 0xd80
+ 0x0048701F, 0x00000002, 0x40240420, 0x0048721F, 0x00000002, 0x40240420,
+ 0x0048781F, 0x00000002, 0x40240420, 0x00487C1F, 0x00000002, 0x40240420,
+ 0x00487E1F, 0x00000002, 0x40240520, 0x0048701F, 0x00000002, 0x40240520,
+ 0x0048721F, 0x00000002, 0x40240520, 0x0048781F, 0x00000002, 0x40240520,
+ 0x00487C1F, 0x00000002, 0x40240520, 0x00487E1F, 0x00000002, 0x40240620,
+ 0x0048701F, 0x00000002, 0x40240620, 0x0048721F, 0x00000002, 0x40240620,
+ 0x0048781F, 0x00000002, 0x40240620, 0x00487C1F, 0x00000002, 0x40240620,
+ 0x00487E1F, 0x00000002, 0x40240720, 0x0048701F, 0x00000002, 0x40240720,
+ 0x0048721F, 0x00000002, 0x40240720, 0x0048781F, 0x00000002, 0x40240720,
+ 0x00487C1F, 0x00000002, 0x40240720, 0x00487E1F, 0x00000002, 0x40240820,
+ 0x0048701F, 0x00000002, 0x40240820, 0x0048721F,
+ // Block 55, offset 0xdc0
+ 0x00000002, 0x40240820, 0x0048781F, 0x00000002, 0x40240820, 0x00487C1F,
+ 0x00000002, 0x40240820, 0x00487E1F, 0x00000002, 0x40240920, 0x0048701F,
+ 0x00000002, 0x40240920, 0x0048721F, 0x00000002, 0x40240920, 0x0048781F,
+ 0x00000002, 0x40240920, 0x00487C1F, 0x00000002, 0x40240920, 0x00487E1F,
+ 0x00000002, 0x40240A20, 0x0048701F, 0x00000002, 0x40240A20, 0x0048721F,
+ 0x00000002, 0x40240A20, 0x0048781F, 0x00000002, 0x40240A20, 0x00487C1F,
+ 0x00000002, 0x40240A20, 0x00487E1F, 0x00000002, 0x40240B20, 0x0048701F,
+ 0x00000002, 0x40240B20, 0x0048721F, 0x00000002, 0x40240B20, 0x0048781F,
+ 0x00000002, 0x40240B20, 0x00487C1F, 0x00000002, 0x40240B20, 0x00487E1F,
+ 0x00000002, 0x40240C20, 0x0048701F, 0x00000002, 0x40240C20, 0x0048721F,
+ 0x00000002, 0x40240C20, 0x0048781F, 0x00000002,
+ // Block 56, offset 0xe00
+ 0x40240C20, 0x00487C1F, 0x00000002, 0x40240C20, 0x00487E1F, 0x00000002,
+ 0x40240D20, 0x0048701F, 0x00000002, 0x40240D20, 0x0048721F, 0x00000002,
+ 0x40240D20, 0x0048781F, 0x00000002, 0x40240D20, 0x00487C1F, 0x00000002,
+ 0x40240D20, 0x00487E1F, 0x00000002, 0x40240E20, 0x0048701F, 0x00000002,
+ 0x40240E20, 0x0048721F, 0x00000002, 0x40240E20, 0x0048781F, 0x00000002,
+ 0x40240E20, 0x00487C1F, 0x00000002, 0x40240E20, 0x00487E1F, 0x00000002,
+ 0x40240F20, 0x0048701F, 0x00000002, 0x40240F20, 0x0048721F, 0x00000002,
+ 0x40240F20, 0x0048781F, 0x00000002, 0x40240F20, 0x00487C1F, 0x00000002,
+ 0x40240F20, 0x00487E1F, 0x00000002, 0x40241020, 0x0048701F, 0x00000002,
+ 0x40241020, 0x0048721F, 0x00000002, 0x40241020, 0x0048781F, 0x00000002,
+ 0x40241020, 0x00487C1F, 0x00000002, 0x40241020,
+ // Block 57, offset 0xe40
+ 0x00487E1F, 0x00000002, 0x40241120, 0x0048701F, 0x00000002, 0x40241120,
+ 0x0048721F, 0x00000002, 0x40241120, 0x0048781F, 0x00000002, 0x40241120,
+ 0x00487C1F, 0x00000002, 0x40241120, 0x00487E1F, 0x00000002, 0x40241220,
+ 0x0048701F, 0x00000002, 0x40241220, 0x0048721F, 0x00000002, 0x40241220,
+ 0x0048781F, 0x00000002, 0x40241220, 0x00487C1F, 0x00000002, 0x40241220,
+ 0x00487E1F, 0x00000002, 0x40241320, 0x0048701F, 0x00000002, 0x40241320,
+ 0x0048721F, 0x00000002, 0x40241320, 0x0048781F, 0x00000002, 0x40241320,
+ 0x00487C1F, 0x00000002, 0x40241320, 0x00487E1F, 0x00000002, 0x40241420,
+ 0x0048701F, 0x00000002, 0x40241420, 0x0048721F, 0x00000002, 0x40241420,
+ 0x0048781F, 0x00000002, 0x40241420, 0x00487C1F, 0x00000002, 0x40241420,
+ 0x00487E1F, 0x00000002, 0x40241520, 0x0048701F,
+ // Block 58, offset 0xe80
+ 0x00000002, 0x40241520, 0x0048721F, 0x00000002, 0x40241520, 0x0048781F,
+ 0x00000002, 0x40241520, 0x00487C1F, 0x00000002, 0x40241520, 0x00487E1F,
+ 0x00000002, 0x40241620, 0x0048701F, 0x00000002, 0x40241620, 0x0048721F,
+ 0x00000002, 0x40241620, 0x0048781F, 0x00000002, 0x40241620, 0x00487C1F,
+ 0x00000002, 0x40241620, 0x00487E1F, 0x00000002, 0x40241720, 0x0048701F,
+ 0x00000002, 0x40241720, 0x0048721F, 0x00000002, 0x40241720, 0x0048781F,
+ 0x00000002, 0x40241720, 0x00487C1F, 0x00000002, 0x40241720, 0x00487E1F,
+ 0x00000002, 0x40241820, 0x0048701F, 0x00000002, 0x40241820, 0x0048721F,
+ 0x00000002, 0x40241820, 0x0048781F, 0x00000002, 0x40241820, 0x00487C1F,
+ 0x00000002, 0x40241820, 0x00487E1F, 0x00000002, 0x40241920, 0x0048701F,
+ 0x00000002, 0x40241920, 0x0048721F, 0x00000002,
+ // Block 59, offset 0xec0
+ 0x40241920, 0x0048781F, 0x00000002, 0x40241920, 0x00487C1F, 0x00000002,
+ 0x40241920, 0x00487E1F, 0x00000002, 0x40241A20, 0x0048701F, 0x00000002,
+ 0x40241A20, 0x0048721F, 0x00000002, 0x40241A20, 0x0048781F, 0x00000002,
+ 0x40241A20, 0x00487C1F, 0x00000002, 0x40241A20, 0x00487E1F, 0x00000002,
+ 0x40241B20, 0x0048701F, 0x00000002, 0x40241B20, 0x0048721F, 0x00000002,
+ 0x40241B20, 0x0048781F, 0x00000002, 0x40241B20, 0x00487C1F, 0x00000002,
+ 0x40241B20, 0x00487E1F, 0x00000002, 0x40241C20, 0x0048701F, 0x00000002,
+ 0x40241C20, 0x0048721F, 0x00000002, 0x40241C20, 0x0048781F, 0x00000002,
+ 0x40241C20, 0x00487C1F, 0x00000002, 0x40241C20, 0x00487E1F, 0x00000002,
+ 0x40241D20, 0x0048701F, 0x00000002, 0x40241D20, 0x0048721F, 0x00000002,
+ 0x40241D20, 0x0048781F, 0x00000002, 0x40241D20,
+ // Block 60, offset 0xf00
+ 0x00487C1F, 0x00000002, 0x40241D20, 0x00487E1F, 0x00000002, 0x40241E20,
+ 0x0048701F, 0x00000002, 0x40241E20, 0x0048721F, 0x00000002, 0x40241E20,
+ 0x0048781F, 0x00000002, 0x40241E20, 0x00487C1F, 0x00000002, 0x40241E20,
+ 0x00487E1F, 0x00000002, 0x40241F20, 0x0048701F, 0x00000002, 0x40241F20,
+ 0x0048721F, 0x00000002, 0x40241F20, 0x0048781F, 0x00000002, 0x40241F20,
+ 0x00487C1F, 0x00000002, 0x40241F20, 0x00487E1F, 0x00000002, 0x40242020,
+ 0x0048701F, 0x00000002, 0x40242020, 0x0048721F, 0x00000002, 0x40242020,
+ 0x0048781F, 0x00000002, 0x40242020, 0x00487C1F, 0x00000002, 0x40242020,
+ 0x00487E1F, 0x00000002, 0x40242120, 0x0048701F, 0x00000002, 0x40242120,
+ 0x0048721F, 0x00000002, 0x40242120, 0x0048781F, 0x00000002, 0x40242120,
+ 0x00487C1F, 0x00000002, 0x40242120, 0x00487E1F,
+ // Block 61, offset 0xf40
+ 0x00000002, 0x40242220, 0x0048701F, 0x00000002, 0x40242220, 0x0048721F,
+ 0x00000002, 0x40242220, 0x0048781F, 0x00000002, 0x40242220, 0x00487C1F,
+ 0x00000002, 0x40242220, 0x00487E1F, 0x00000002, 0x40242320, 0x0048701F,
+ 0x00000002, 0x40242320, 0x0048721F, 0x00000002, 0x40242320, 0x0048781F,
+ 0x00000002, 0x40242320, 0x00487C1F, 0x00000002, 0x40242320, 0x00487E1F,
+ 0x00000002, 0x40242420, 0x0048701F, 0x00000002, 0x40242420, 0x0048721F,
+ 0x00000002, 0x40242420, 0x0048781F, 0x00000002, 0x40242420, 0x00487C1F,
+ 0x00000002, 0x40242420, 0x00487E1F, 0x00000002, 0x40242520, 0x0048701F,
+ 0x00000002, 0x40242520, 0x0048721F, 0x00000002, 0x40242520, 0x0048781F,
+ 0x00000002, 0x40242520, 0x00487C1F, 0x00000002, 0x40242520, 0x00487E1F,
+ 0x00000002, 0x40242620, 0x0048701F, 0x00000002,
+ // Block 62, offset 0xf80
+ 0x40242620, 0x0048721F, 0x00000002, 0x40242620, 0x0048781F, 0x00000002,
+ 0x40242620, 0x00487C1F, 0x00000002, 0x40242620, 0x00487E1F, 0x00000002,
+ 0x40242720, 0x0048701F, 0x00000002, 0x40242720, 0x0048721F, 0x00000002,
+ 0x40242720, 0x0048781F, 0x00000002, 0x40242720, 0x00487C1F, 0x00000002,
+ 0x40242720, 0x00487E1F, 0x00000002, 0x40242820, 0x0048701F, 0x00000002,
+ 0x40242820, 0x0048721F, 0x00000002, 0x40242820, 0x0048781F, 0x00000002,
+ 0x40242820, 0x00487C1F, 0x00000002, 0x40242820, 0x00487E1F, 0x00000002,
+ 0x40242920, 0x0048701F, 0x00000002, 0x40242920, 0x0048721F, 0x00000002,
+ 0x40242920, 0x0048781F, 0x00000002, 0x40242920, 0x00487C1F, 0x00000002,
+ 0x40242920, 0x00487E1F, 0x00000002, 0x40242A20, 0x0048701F, 0x00000002,
+ 0x40242A20, 0x0048721F, 0x00000002, 0x40242A20,
+ // Block 63, offset 0xfc0
+ 0x0048781F, 0x00000002, 0x40242A20, 0x00487C1F, 0x00000002, 0x40242A20,
+ 0x00487E1F, 0x00000002, 0x40242B20, 0x0048701F, 0x00000002, 0x40242B20,
+ 0x0048721F, 0x00000002, 0x40242B20, 0x0048781F, 0x00000002, 0x40242B20,
+ 0x00487C1F, 0x00000002, 0x40242B20, 0x00487E1F, 0x00000002, 0x40242C20,
+ 0x0048701F, 0x00000002, 0x40242C20, 0x0048721F, 0x00000002, 0x40242C20,
+ 0x0048781F, 0x00000002, 0x40242C20, 0x00487C1F, 0x00000002, 0x40242C20,
+ 0x00487E1F, 0x00000002, 0x40242D20, 0x0048701F, 0x00000002, 0x40242D20,
+ 0x0048721F, 0x00000002, 0x40242D20, 0x0048781F, 0x00000002, 0x40242D20,
+ 0x00487C1F, 0x00000002, 0x40242D20, 0x00487E1F, 0x00000002, 0x40242E20,
+ 0x0048701F, 0x00000002, 0x40242E20, 0x0048721F, 0x00000002, 0x40242E20,
+ 0x0048781F, 0x00000002, 0x40242E20, 0x00487C1F,
+ // Block 64, offset 0x1000
+ 0x00000002, 0x40242E20, 0x00487E1F, 0x00000002, 0x40242F20, 0x0048701F,
+ 0x00000002, 0x40242F20, 0x0048721F, 0x00000002, 0x40242F20, 0x0048781F,
+ 0x00000002, 0x40242F20, 0x00487C1F, 0x00000002, 0x40242F20, 0x00487E1F,
+ 0x00000002, 0x40243020, 0x0048701F, 0x00000002, 0x40243020, 0x0048721F,
+ 0x00000002, 0x40243020, 0x0048781F, 0x00000002, 0x40243020, 0x00487C1F,
+ 0x00000002, 0x40243020, 0x00487E1F, 0x00000002, 0x40243120, 0x0048701F,
+ 0x00000002, 0x40243120, 0x0048721F, 0x00000002, 0x40243120, 0x0048781F,
+ 0x00000002, 0x40243120, 0x00487C1F, 0x00000002, 0x40243120, 0x00487E1F,
+ 0x00000002, 0x40243220, 0x0048701F, 0x00000002, 0x40243220, 0x0048721F,
+ 0x00000002, 0x40243220, 0x0048781F, 0x00000002, 0x40243220, 0x00487C1F,
+ 0x00000002, 0x40243220, 0x00487E1F, 0x00000002,
+ // Block 65, offset 0x1040
+ 0x0048EC04, 0x80016004, 0x00000002, 0x0048FC04, 0x80016004, 0x00000002,
+ 0x0048FE04, 0x80016004, 0x00000002, 0x00490004, 0x80016004, 0x00000002,
+ 0x40248020, 0x40249620, 0x00000002, 0x40248320, 0x40249620, 0x00000003,
+ 0x00491804, 0x00494604, 0x80012D1F, 0x00000003, 0x004CBC04, 0x004D2A04,
+ 0x004CBC1F, 0x00000002, 0x004E6404, 0x004E9004, 0x00000003, 0x004E6404,
+ 0x004E9004, 0x004EA61F, 0x00000003, 0x004F0404, 0x004F5004, 0x004F041F,
+ 0x00000002, 0x00589004, 0x80015F04, 0x00000002, 0x00589204, 0x80015F04,
+ 0x00000002, 0x00589204, 0x80016004, 0x00000002, 0x00589404, 0x80015F04,
+ 0x00000002, 0x00589404, 0x00589404, 0x00000002, 0x00589604, 0x80015F04,
+ 0x00000002, 0x00589604, 0x80016004, 0x00000002, 0x00589604, 0x80016204,
+ 0x00000002, 0x00589604, 0x80016304, 0x00000002,
+ // Block 66, offset 0x1080
+ 0x00589E04, 0x80015F04, 0x00000002, 0x00589E04, 0x80016004, 0x00000002,
+ 0x00589E04, 0x80016204, 0x00000002, 0x00589E04, 0x80016304, 0x00000002,
+ 0x0058A204, 0x80015F04, 0x00000002, 0x0058A404, 0x80015F04, 0x00000002,
+ 0x0058A404, 0x80016004, 0x00000002, 0x0058A404, 0x80016204, 0x00000002,
+ 0x0058A604, 0x80015F04, 0x00000002, 0x0058A604, 0x80016004, 0x00000002,
+ 0x0058A804, 0x80015F04, 0x00000002, 0x0058AA04, 0x80015F04, 0x00000002,
+ 0x0058AC04, 0x80015F04, 0x00000002, 0x0058AC04, 0x0058BE04, 0x00000002,
+ 0x0058B004, 0x80015F04, 0x00000002, 0x0058B404, 0x80015F04, 0x00000002,
+ 0x0058B404, 0x80016004, 0x00000002, 0x0058B404, 0x80016204, 0x00000002,
+ 0x0058B404, 0x80016304, 0x00000002, 0x0058B404, 0x80016404, 0x00000002,
+ 0x0058B604, 0x80015F04, 0x00000002, 0x0058B604,
+ // Block 67, offset 0x10c0
+ 0x80016004, 0x00000002, 0x0058B804, 0x80015F04, 0x00000002, 0x0058B804,
+ 0x80016004, 0x00000002, 0x0058BC04, 0x80015F04, 0x00000002, 0x0058BC04,
+ 0x80016004, 0x00000004, 0x0058BC04, 0x80015F04, 0x0058BC1F, 0x80015F1F,
+ 0x00000002, 0x0058BE04, 0x80015F04, 0x00000002, 0x0058C004, 0x80015F04,
+ 0x00000002, 0x0058DA04, 0x80015F04, 0x00000002, 0x0058DA04, 0x80016004,
+ 0x00000002, 0x0058DC04, 0x80015F04, 0x00000002, 0x0058E004, 0x80015F04,
+ 0x00000002, 0x0058E604, 0x80015F04, 0x00000002, 0x0058E804, 0x80015F04,
+ 0x00000002, 0x0058EA04, 0x80015F04, 0x00000002, 0x0058EC04, 0x80015F04,
+ 0x00000002, 0x0058EE04, 0x80015F04, 0x00000002, 0x0058F004, 0x80015F04,
+ 0x00000002, 0x0058F404, 0x80015F04, 0x00000002, 0x0058F604, 0x80015F04,
+ 0x00000002, 0x0058F804, 0x80015F04, 0x00000002,
+ // Block 68, offset 0x1100
+ 0x0058FA04, 0x80015F04, 0x00000002, 0x0058FC04, 0x80015F04, 0x00000002,
+ 0x0058FE04, 0x80015F04, 0x00000002, 0x00590804, 0x80015F04, 0x00000002,
+ 0x00590A04, 0x80015F04, 0x00000002, 0x00590C04, 0x80015F04, 0x00000002,
+ 0x00590E04, 0x80015F04, 0x00000002, 0x00591204, 0x80015F04, 0x00000002,
+ 0x00591A04, 0x80015F04, 0x00000002, 0x00591C04, 0x80015F04, 0x00000002,
+ 0x00591E04, 0x80015F04, 0x00000002, 0x00592004, 0x80015F04, 0x00000002,
+ 0x00592204, 0x80015F04, 0x00000002, 0x00592A04, 0x80015F04, 0x00000002,
+ 0x00592C04, 0x80015F04, 0x00000002, 0x00592E04, 0x80015F04, 0x00000002,
+ 0x00593004, 0x80015F04, 0x00000002, 0x00594E04, 0x005B4C04, 0x00000002,
+ 0x00597204, 0x005B4C04, 0x00000002, 0x00599C04, 0x005B4C04, 0x00000002,
+ 0x0059C404, 0x005B4E04, 0x00000002, 0x0059DA04,
+ // Block 69, offset 0x1140
+ 0x005B4C04, 0x00000002, 0x0059E604, 0x005B4E04, 0x00000002, 0x0059EA04,
+ 0x005B4E04, 0x00000002, 0x0059F604, 0x005B4C04, 0x00000002, 0x005A4004,
+ 0x005B4C04, 0x00000002, 0x005A9E04, 0x005B4C04, 0x00000002, 0x005ACC04,
+ 0x005B4C04, 0x00000002, 0x005AD804, 0x005B4E04, 0x00000002, 0x005AE604,
+ 0x005B4C04, 0x00000002, 0x00634404, 0x00637004, 0x00000002, 0x00636A04,
+ 0x00634604, 0x00000002, 0x00639004, 0x80016004, 0x00000002, 0x0063A204,
+ 0x80016004, 0x00000002, 0x0063AC04, 0x80016004, 0x00000002, 0x0063BC04,
+ 0x80016004, 0x00000002, 0x0063C804, 0x80016004, 0x00000002, 0x0063CA04,
+ 0x80016004, 0x00000002, 0x0063D204, 0x80016004, 0x00000002, 0x0063D404,
+ 0x80016004, 0x00000002, 0x0063D804, 0x80016004, 0x00000002, 0x0063EE04,
+ 0x80016004, 0x00000002, 0x0063EE16, 0x80016016,
+ // Block 70, offset 0x1180
+ 0x00000002, 0x0063F004, 0x80016004, 0x00000002, 0x0063F004, 0x80016204,
+ 0x00000002, 0x00724404, 0x80015F04, 0x00000002, 0x029C6C04, 0x80015F1F,
+ 0x00000002, 0x029CB204, 0x80015F1F, 0x00000002, 0x02A30404, 0x80015F1F,
+ 0x00000002, 0x02A3C004, 0x80015F1F, 0x00000002, 0x02A40004, 0x80015F1F,
+ 0x00000002, 0x02A6B804, 0x80015F1F, 0x00000002, 0x02A6D204, 0x80015F1F,
+ 0x00000002, 0x02A70404, 0x80015F1F, 0x00000002, 0x02B81E04, 0x80015F1F,
+ 0x00000002, 0x02B81E04, 0x8001601F, 0x00000002, 0x02B84404, 0x80015F1F,
+ 0x00000002, 0x02B84604, 0x80015F1F, 0x00000002, 0x02BEA004, 0x80015F1F,
+ 0x00000002, 0x02BF8604, 0x80015F1F, 0x00000002, 0x02CBCA04, 0x80015F1F,
+ 0x00000002, 0x02CE1004, 0x80015F1F, 0x00000002, 0x02D6F404, 0x80015F1F,
+ 0x00000002, 0x02E45604, 0x80015F1F, 0x00000002,
+ // Block 71, offset 0x11c0
+ 0x02E4B604, 0x80015F1F, 0x00000002, 0x02E71604, 0x80015F1F, 0x00000002,
+ 0x02EB1604, 0x80015F1F, 0x00000002, 0x02EDDC04, 0x80015F1F, 0x00000002,
+ 0x02F27404, 0x80015F1F, 0x00000002, 0x02F5F204, 0x80015F1F, 0x00000002,
+ 0x02FEA404, 0x80015F1F, 0x00000002, 0x02FEA604, 0x80015F1F, 0x00000002,
+ 0x02FEA604, 0x8001601F, 0x00000002, 0x02FF1404, 0x80015F1F, 0x00000002,
+ 0x02FF1404, 0x8001601F, 0x00000002, 0x0300FE04, 0x80015F1F, 0x00000002,
+ 0x03011204, 0x80015F1F, 0x00000002, 0x0303F804, 0x80015F1F, 0x00000002,
+ 0x0304F204, 0x80015F1F, 0x00000002, 0x0304F204, 0x8001601F, 0x00000002,
+ 0x0313A404, 0x80015F1F, 0x00000002, 0x031B6604, 0x80015F1F, 0x00000002,
+ 0x031F6C04, 0x80015F1F, 0x00000002, 0x031F6C04, 0x8001601F, 0x00000002,
+ 0x03212204, 0x80015F1F, 0x00000002, 0x032C3804,
+ // Block 72, offset 0x1200
+ 0x80015F1F, 0x00000002, 0x032DD004, 0x80015F1F, 0x00000002, 0x0331C004,
+ 0x80015F1F, 0x00000002, 0x03332C04, 0x80015F1F, 0x00000002, 0x03355004,
+ 0x80015F1F, 0x00000002, 0x03367804, 0x80015F1F, 0x00000002, 0x033CEA04,
+ 0x80015F1F, 0x00000002, 0x033E9404, 0x80015F1F, 0x00000002, 0x033EA404,
+ 0x80015F1F, 0x00000002, 0x033F1A04, 0x80015F1F, 0x00000002, 0x033F3804,
+ 0x80015F1F, 0x00000002, 0x033F3804, 0x8001601F,
+}
+
+// mainContractElem: 799 entries, 3196 bytes
+var mainContractElem = [799]uint32{
+ // Block 0, offset 0x0
+ 0x4016C420, 0xE0000789, 0xE0000789, 0x002D8808, 0xE000078F, 0xE000078F,
+ 0x40194320, 0x40194720, 0x40194B20, 0x00328608, 0x00328E08, 0x00329608,
+ 0x40194F20, 0x40195320, 0x00329E08, 0x0032A608, 0x40196320, 0x40198320,
+ 0x40198320, 0x0032C608, 0x00330608, 0x00330608, 0x40198B20, 0x40198F20,
+ 0x00331608, 0x00331E08, 0x40199720, 0x40199C20, 0x00332E08, 0x00333808,
+ 0x4019A420, 0x4019AB20, 0x00334808, 0x00335608, 0x4019BC20, 0x4019D120,
+ 0x4019C420, 0x00337808, 0x0033A208, 0x00338808, 0x4019C820, 0x4019CD20,
+ 0x00339008, 0x00339A08, 0x401A2920, 0x401A2D20, 0x00345208, 0x00345A08,
+ 0x401A3120, 0x401A3520, 0x00346208, 0x00346A08, 0x4019DA20, 0x401A6720,
+ 0x401A6720, 0x0033B408, 0x0034CE08, 0x0034CE08, 0x401A6B20, 0x401A6F20,
+ 0x401A7320, 0x401A7720, 0x0034D608, 0x0034DE08,
+ // Block 1, offset 0x40
+ 0x0034E608, 0x0034EE08, 0x401ABE20, 0x401AC320, 0x00357C08, 0x00358608,
+ 0x401AF120, 0x401AF520, 0x0035E208, 0x0035EA08, 0x401B0620, 0x401B0A20,
+ 0x00360C08, 0x00361408, 0x401B3C20, 0x401B4020, 0x00367808, 0x00368008,
+ 0x401C4620, 0x401C3C20, 0x401C3D20, 0x401C4120, 0x401CDC20, 0x401C4020,
+ 0x401CE920, 0x401C4520, 0x40201520, 0x40201720, 0x40201820, 0x4020D420,
+ 0x4020D620, 0x4020D520, 0x4020D720, 0x4020E520, 0x4020E720, 0x40210520,
+ 0x40210820, 0x40210A20, 0x40210620, 0x40210920, 0x40214C20, 0x40214E20,
+ 0x40218D20, 0x40218E20, 0x40219520, 0x40219920, 0x40219820, 0x40219620,
+ 0x40219720, 0x40219820, 0x40219920, 0x4021DE20, 0x4021E120, 0x4021E320,
+ 0x4021DF20, 0x4021E220, 0x40222C20, 0x40223020, 0x40222D20, 0x40222F20,
+ 0x40223120, 0x40222F20, 0x40223020, 0x4023CF20,
+ // Block 2, offset 0x80
+ 0xE0000900, 0xE000090F, 0xE000091E, 0xE000092D, 0xE000093C, 0xE000094B,
+ 0xE000095A, 0xE0000969, 0xE0000978, 0xE0000987, 0xE0000996, 0xE00009A5,
+ 0xE00009B4, 0xE00009C3, 0xE00009D2, 0xE00009E1, 0xE00009F0, 0xE00009FF,
+ 0xE0000A0E, 0xE0000A1D, 0xE0000A2C, 0xE0000A3B, 0xE0000A4A, 0xE0000A59,
+ 0xE0000A68, 0xE0000A77, 0xE0000A86, 0xE0000A95, 0xE0000AA4, 0xE0000AB3,
+ 0xE0000AC2, 0xE0000AD1, 0xE0000AE0, 0xE0000AEF, 0xE0000AFE, 0xE0000B0D,
+ 0xE0000B1C, 0xE0000B2B, 0xE0000B3A, 0xE0000B49, 0xE0000B58, 0xE0000B67,
+ 0xE0000B76, 0xE0000B85, 0xE0000B94, 0xE0000BA3, 0x4023D020, 0xE0000903,
+ 0xE0000912, 0xE0000921, 0xE0000930, 0xE000093F, 0xE000094E, 0xE000095D,
+ 0xE000096C, 0xE000097B, 0xE000098A, 0xE0000999, 0xE00009A8, 0xE00009B7,
+ 0xE00009C6, 0xE00009D5, 0xE00009E4, 0xE00009F3,
+ // Block 3, offset 0xc0
+ 0xE0000A02, 0xE0000A11, 0xE0000A20, 0xE0000A2F, 0xE0000A3E, 0xE0000A4D,
+ 0xE0000A5C, 0xE0000A6B, 0xE0000A7A, 0xE0000A89, 0xE0000A98, 0xE0000AA7,
+ 0xE0000AB6, 0xE0000AC5, 0xE0000AD4, 0xE0000AE3, 0xE0000AF2, 0xE0000B01,
+ 0xE0000B10, 0xE0000B1F, 0xE0000B2E, 0xE0000B3D, 0xE0000B4C, 0xE0000B5B,
+ 0xE0000B6A, 0xE0000B79, 0xE0000B88, 0xE0000B97, 0xE0000BA6, 0x4023D120,
+ 0xE0000906, 0xE0000915, 0xE0000924, 0xE0000933, 0xE0000942, 0xE0000951,
+ 0xE0000960, 0xE000096F, 0xE000097E, 0xE000098D, 0xE000099C, 0xE00009AB,
+ 0xE00009BA, 0xE00009C9, 0xE00009D8, 0xE00009E7, 0xE00009F6, 0xE0000A05,
+ 0xE0000A14, 0xE0000A23, 0xE0000A32, 0xE0000A41, 0xE0000A50, 0xE0000A5F,
+ 0xE0000A6E, 0xE0000A7D, 0xE0000A8C, 0xE0000A9B, 0xE0000AAA, 0xE0000AB9,
+ 0xE0000AC8, 0xE0000AD7, 0xE0000AE6, 0xE0000AF5,
+ // Block 4, offset 0x100
+ 0xE0000B04, 0xE0000B13, 0xE0000B22, 0xE0000B31, 0xE0000B40, 0xE0000B4F,
+ 0xE0000B5E, 0xE0000B6D, 0xE0000B7C, 0xE0000B8B, 0xE0000B9A, 0xE0000BA9,
+ 0x4023D220, 0xE0000909, 0xE0000918, 0xE0000927, 0xE0000936, 0xE0000945,
+ 0xE0000954, 0xE0000963, 0xE0000972, 0xE0000981, 0xE0000990, 0xE000099F,
+ 0xE00009AE, 0xE00009BD, 0xE00009CC, 0xE00009DB, 0xE00009EA, 0xE00009F9,
+ 0xE0000A08, 0xE0000A17, 0xE0000A26, 0xE0000A35, 0xE0000A44, 0xE0000A53,
+ 0xE0000A62, 0xE0000A71, 0xE0000A80, 0xE0000A8F, 0xE0000A9E, 0xE0000AAD,
+ 0xE0000ABC, 0xE0000ACB, 0xE0000ADA, 0xE0000AE9, 0xE0000AF8, 0xE0000B07,
+ 0xE0000B16, 0xE0000B25, 0xE0000B34, 0xE0000B43, 0xE0000B52, 0xE0000B61,
+ 0xE0000B70, 0xE0000B7F, 0xE0000B8E, 0xE0000B9D, 0xE0000BAC, 0x4023D320,
+ 0xE000090C, 0xE000091B, 0xE000092A, 0xE0000939,
+ // Block 5, offset 0x140
+ 0xE0000948, 0xE0000957, 0xE0000966, 0xE0000975, 0xE0000984, 0xE0000993,
+ 0xE00009A2, 0xE00009B1, 0xE00009C0, 0xE00009CF, 0xE00009DE, 0xE00009ED,
+ 0xE00009FC, 0xE0000A0B, 0xE0000A1A, 0xE0000A29, 0xE0000A38, 0xE0000A47,
+ 0xE0000A56, 0xE0000A65, 0xE0000A74, 0xE0000A83, 0xE0000A92, 0xE0000AA1,
+ 0xE0000AB0, 0xE0000ABF, 0xE0000ACE, 0xE0000ADD, 0xE0000AEC, 0xE0000AFB,
+ 0xE0000B0A, 0xE0000B19, 0xE0000B28, 0xE0000B37, 0xE0000B46, 0xE0000B55,
+ 0xE0000B64, 0xE0000B73, 0xE0000B82, 0xE0000B91, 0xE0000BA0, 0xE0000BAF,
+ 0x80012302, 0x4023C720, 0x4023FE20, 0xE0000BB2, 0xE0000BC1, 0xE0000BD0,
+ 0xE0000BDF, 0xE0000BEE, 0xE0000C0C, 0xE0000C1B, 0xE0000C2A, 0xE0000C39,
+ 0xE0000C48, 0xE0000C57, 0xE0000C66, 0xE0000C75, 0xE0000C84, 0xE0000C93,
+ 0xE0000CA2, 0xE0000CB1, 0xE0000CC0, 0xE0000CCF,
+ // Block 6, offset 0x180
+ 0xE0000CDE, 0xE0000CED, 0xE0000CFC, 0xE0000D0B, 0xE0000BFD, 0xE0000D42,
+ 0xE0000D51, 0xE0000D60, 0xE0000D1A, 0xE0000D2E, 0x4023FF20, 0xE0000BB5,
+ 0xE0000BC4, 0xE0000BD3, 0xE0000BE2, 0xE0000BF1, 0xE0000C0F, 0xE0000C1E,
+ 0xE0000C2D, 0xE0000C3C, 0xE0000C4B, 0xE0000C5A, 0xE0000C69, 0xE0000C78,
+ 0xE0000C87, 0xE0000C96, 0xE0000CA5, 0xE0000CB4, 0xE0000CC3, 0xE0000CD2,
+ 0xE0000CE1, 0xE0000CF0, 0xE0000CFF, 0xE0000D0E, 0xE0000C00, 0xE0000D45,
+ 0xE0000D54, 0xE0000D63, 0xE0000D1E, 0xE0000D32, 0x40240020, 0xE0000BB8,
+ 0xE0000BC7, 0xE0000BD6, 0xE0000BE5, 0xE0000BF4, 0xE0000C12, 0xE0000C21,
+ 0xE0000C30, 0xE0000C3F, 0xE0000C4E, 0xE0000C5D, 0xE0000C6C, 0xE0000C7B,
+ 0xE0000C8A, 0xE0000C99, 0xE0000CA8, 0xE0000CB7, 0xE0000CC6, 0xE0000CD5,
+ 0xE0000CE4, 0xE0000CF3, 0xE0000D02, 0xE0000D11,
+ // Block 7, offset 0x1c0
+ 0xE0000C03, 0xE0000D48, 0xE0000D57, 0xE0000D66, 0xE0000D22, 0xE0000D36,
+ 0x40240120, 0xE0000BBB, 0xE0000BCA, 0xE0000BD9, 0xE0000BE8, 0xE0000BF7,
+ 0xE0000C15, 0xE0000C24, 0xE0000C33, 0xE0000C42, 0xE0000C51, 0xE0000C60,
+ 0xE0000C6F, 0xE0000C7E, 0xE0000C8D, 0xE0000C9C, 0xE0000CAB, 0xE0000CBA,
+ 0xE0000CC9, 0xE0000CD8, 0xE0000CE7, 0xE0000CF6, 0xE0000D05, 0xE0000D14,
+ 0xE0000C06, 0xE0000D4B, 0xE0000D5A, 0xE0000D69, 0xE0000D26, 0xE0000D3A,
+ 0x40240220, 0xE0000BBE, 0xE0000BCD, 0xE0000BDC, 0xE0000BEB, 0xE0000BFA,
+ 0xE0000C18, 0xE0000C27, 0xE0000C36, 0xE0000C45, 0xE0000C54, 0xE0000C63,
+ 0xE0000C72, 0xE0000C81, 0xE0000C90, 0xE0000C9F, 0xE0000CAE, 0xE0000CBD,
+ 0xE0000CCC, 0xE0000CDB, 0xE0000CEA, 0xE0000CF9, 0xE0000D08, 0xE0000D17,
+ 0xE0000C09, 0xE0000D4E, 0xE0000D5D, 0xE0000D6C,
+ // Block 8, offset 0x200
+ 0xE0000D2A, 0xE0000D3E, 0x80012902, 0x4023F420, 0x40243820, 0xE0000D6F,
+ 0xE0000D7E, 0xE0000D8D, 0xE0000D9C, 0xE0000DAB, 0xE0000DBA, 0xE0000DC9,
+ 0xE0000DD8, 0xE0000DE7, 0xE0000DF6, 0xE0000E05, 0xE0000E14, 0xE0000E23,
+ 0xE0000E32, 0xE0000E41, 0xE0000E50, 0xE0000E5F, 0xE0000E6E, 0xE0000E7D,
+ 0xE0000E8C, 0xE0000E9B, 0xE0000EAA, 0xE0000EB9, 0xE0000EC8, 0xE0000ED7,
+ 0xE0000EE6, 0xE0000EF5, 0xE0000F04, 0xE0000F13, 0xE0000F22, 0xE0000F31,
+ 0xE0000F40, 0xE0000F4F, 0xE0000F5E, 0xE0000F6D, 0xE0000F7C, 0xE0000F8B,
+ 0xE0000F9A, 0xE0000FA9, 0xE0000FB8, 0xE0000FC7, 0xE0000FD6, 0xE0000FE5,
+ 0xE0000FF4, 0xE0001003, 0xE0001012, 0xE0001021, 0xE0001030, 0x40243920,
+ 0xE0000D72, 0xE0000D81, 0xE0000D90, 0xE0000D9F, 0xE0000DAE, 0xE0000DBD,
+ 0xE0000DCC, 0xE0000DDB, 0xE0000DEA, 0xE0000DF9,
+ // Block 9, offset 0x240
+ 0xE0000E08, 0xE0000E17, 0xE0000E26, 0xE0000E35, 0xE0000E44, 0xE0000E53,
+ 0xE0000E62, 0xE0000E71, 0xE0000E80, 0xE0000E8F, 0xE0000E9E, 0xE0000EAD,
+ 0xE0000EBC, 0xE0000ECB, 0xE0000EDA, 0xE0000EE9, 0xE0000EF8, 0xE0000F07,
+ 0xE0000F16, 0xE0000F25, 0xE0000F34, 0xE0000F43, 0xE0000F52, 0xE0000F61,
+ 0xE0000F70, 0xE0000F7F, 0xE0000F8E, 0xE0000F9D, 0xE0000FAC, 0xE0000FBB,
+ 0xE0000FCA, 0xE0000FD9, 0xE0000FE8, 0xE0000FF7, 0xE0001006, 0xE0001015,
+ 0xE0001024, 0xE0001033, 0x40243C20, 0xE0000D75, 0xE0000D84, 0xE0000D93,
+ 0xE0000DA2, 0xE0000DB1, 0xE0000DC0, 0xE0000DCF, 0xE0000DDE, 0xE0000DED,
+ 0xE0000DFC, 0xE0000E0B, 0xE0000E1A, 0xE0000E29, 0xE0000E38, 0xE0000E47,
+ 0xE0000E56, 0xE0000E65, 0xE0000E74, 0xE0000E83, 0xE0000E92, 0xE0000EA1,
+ 0xE0000EB0, 0xE0000EBF, 0xE0000ECE, 0xE0000EDD,
+ // Block 10, offset 0x280
+ 0xE0000EEC, 0xE0000EFB, 0xE0000F0A, 0xE0000F19, 0xE0000F28, 0xE0000F37,
+ 0xE0000F46, 0xE0000F55, 0xE0000F64, 0xE0000F73, 0xE0000F82, 0xE0000F91,
+ 0xE0000FA0, 0xE0000FAF, 0xE0000FBE, 0xE0000FCD, 0xE0000FDC, 0xE0000FEB,
+ 0xE0000FFA, 0xE0001009, 0xE0001018, 0xE0001027, 0xE0001036, 0x40243E20,
+ 0xE0000D78, 0xE0000D87, 0xE0000D96, 0xE0000DA5, 0xE0000DB4, 0xE0000DC3,
+ 0xE0000DD2, 0xE0000DE1, 0xE0000DF0, 0xE0000DFF, 0xE0000E0E, 0xE0000E1D,
+ 0xE0000E2C, 0xE0000E3B, 0xE0000E4A, 0xE0000E59, 0xE0000E68, 0xE0000E77,
+ 0xE0000E86, 0xE0000E95, 0xE0000EA4, 0xE0000EB3, 0xE0000EC2, 0xE0000ED1,
+ 0xE0000EE0, 0xE0000EEF, 0xE0000EFE, 0xE0000F0D, 0xE0000F1C, 0xE0000F2B,
+ 0xE0000F3A, 0xE0000F49, 0xE0000F58, 0xE0000F67, 0xE0000F76, 0xE0000F85,
+ 0xE0000F94, 0xE0000FA3, 0xE0000FB2, 0xE0000FC1,
+ // Block 11, offset 0x2c0
+ 0xE0000FD0, 0xE0000FDF, 0xE0000FEE, 0xE0000FFD, 0xE000100C, 0xE000101B,
+ 0xE000102A, 0xE0001039, 0x40243F20, 0xE0000D7B, 0xE0000D8A, 0xE0000D99,
+ 0xE0000DA8, 0xE0000DB7, 0xE0000DC6, 0xE0000DD5, 0xE0000DE4, 0xE0000DF3,
+ 0xE0000E02, 0xE0000E11, 0xE0000E20, 0xE0000E2F, 0xE0000E3E, 0xE0000E4D,
+ 0xE0000E5C, 0xE0000E6B, 0xE0000E7A, 0xE0000E89, 0xE0000E98, 0xE0000EA7,
+ 0xE0000EB6, 0xE0000EC5, 0xE0000ED4, 0xE0000EE3, 0xE0000EF2, 0xE0000F01,
+ 0xE0000F10, 0xE0000F1F, 0xE0000F2E, 0xE0000F3D, 0xE0000F4C, 0xE0000F5B,
+ 0xE0000F6A, 0xE0000F79, 0xE0000F88, 0xE0000F97, 0xE0000FA6, 0xE0000FB5,
+ 0xE0000FC4, 0xE0000FD3, 0xE0000FE2, 0xE0000FF1, 0xE0001000, 0xE000100F,
+ 0xE000101E, 0xE000102D, 0xE000103C, 0x40248020, 0x40249E20, 0xE000104B,
+ 0x40249D20, 0x40249E20, 0x40248320, 0x4024A020,
+ // Block 12, offset 0x300
+ 0xE000104E, 0x40249F20, 0x4024A020, 0x40249620, 0x40249820, 0x40249C20,
+ 0x40249A20, 0x40267020, 0x40267120, 0x4027EE20, 0x4027EF20, 0x4027F020,
+ 0x4027F120, 0x4027F220, 0x4027F320, 0x4027F420, 0x4027F520, 0x4027F620,
+ 0x4027F720, 0x4027FA20, 0x4027FB20, 0x40282920, 0x40282A20, 0x40282B20,
+ 0x40282C20, 0x40282D20, 0x40282F20, 0x40282E20, 0x40283020, 0x40283120,
+ 0x40283220,
+}
+
+// mainValues: 25408 entries, 101632 bytes
+// Block 2 is the null block.
+var mainValues = [25408]uint32{
+ // Block 0x0, offset 0x0
+ 0x0000: 0x80000000, 0x0001: 0x80000000, 0x0002: 0x80000000, 0x0003: 0x80000000,
+ 0x0004: 0x80000000, 0x0005: 0x80000000, 0x0006: 0x80000000, 0x0007: 0x80000000,
+ 0x0008: 0x80000000, 0x0009: 0x40010020, 0x000a: 0x40010120, 0x000b: 0x40010220,
+ 0x000c: 0x40010320, 0x000d: 0x40010420, 0x000e: 0x80000000, 0x000f: 0x80000000,
+ 0x0010: 0x80000000, 0x0011: 0x80000000, 0x0012: 0x80000000, 0x0013: 0x80000000,
+ 0x0014: 0x80000000, 0x0015: 0x80000000, 0x0016: 0x80000000, 0x0017: 0x80000000,
+ 0x0018: 0x80000000, 0x0019: 0x80000000, 0x001a: 0x80000000, 0x001b: 0x80000000,
+ 0x001c: 0x80000000, 0x001d: 0x80000000, 0x001e: 0x80000000, 0x001f: 0x80000000,
+ 0x0020: 0x40010920, 0x0021: 0x40015820, 0x0022: 0x4001df20, 0x0023: 0x40024620,
+ 0x0024: 0x4013a520, 0x0025: 0x40024720, 0x0026: 0x40024420, 0x0027: 0x4001d820,
+ 0x0028: 0x4001e920, 0x0029: 0x4001ea20, 0x002a: 0x40023d20, 0x002b: 0x40048520,
+ 0x002c: 0x40011f20, 0x002d: 0x40010e20, 0x002e: 0x40016b20, 0x002f: 0x40024220,
+ 0x0030: 0x40149a20, 0x0031: 0x40149b20, 0x0032: 0x40149c20, 0x0033: 0x40149d20,
+ 0x0034: 0x40149e20, 0x0035: 0x40149f20, 0x0036: 0x4014a020, 0x0037: 0x4014a120,
+ 0x0038: 0x4014a220, 0x0039: 0x4014a320, 0x003a: 0x40013220, 0x003b: 0x40012e20,
+ 0x003c: 0x40048920, 0x003d: 0x40048a20, 0x003e: 0x40048b20, 0x003f: 0x40015d20,
+ // Block 0x1, offset 0x40
+ 0x0040: 0x40023c20, 0x0041: 0x002b4608, 0x0042: 0x002b7208, 0x0043: 0x002ba208,
+ 0x0044: 0x002bc808, 0x0045: 0x002bfe08, 0x0046: 0x002c6e08, 0x0047: 0x002c8808,
+ 0x0048: 0x002cce08, 0x0049: 0x002d0008, 0x004a: 0x002d3208, 0x004b: 0x002d6408,
+ 0x004c: 0xc0030002, 0x004d: 0x002de808, 0x004e: 0x002e0408, 0x004f: 0x002e4808,
+ 0x0050: 0x002e9208, 0x0051: 0x002ebc08, 0x0052: 0x002ee008, 0x0053: 0x002f4c08,
+ 0x0054: 0x002f9208, 0x0055: 0x002fd208, 0x0056: 0x00302408, 0x0057: 0x00304808,
+ 0x0058: 0x00305c08, 0x0059: 0x00306608, 0x005a: 0x00308808, 0x005b: 0x4001eb20,
+ 0x005c: 0x40024320, 0x005d: 0x4001ec20, 0x005e: 0x4002f120, 0x005f: 0x40010c20,
+ 0x0060: 0x4002ee20, 0x0061: 0x4015a320, 0x0062: 0x4015b920, 0x0063: 0x4015d120,
+ 0x0064: 0x4015e420, 0x0065: 0x4015ff20, 0x0066: 0x40163720, 0x0067: 0x40164420,
+ 0x0068: 0x40166720, 0x0069: 0x40168020, 0x006a: 0x40169920, 0x006b: 0x4016b220,
+ 0x006c: 0xc0000002, 0x006d: 0x4016f420, 0x006e: 0x40170220, 0x006f: 0x40172420,
+ 0x0070: 0x40174920, 0x0071: 0x40175e20, 0x0072: 0x40177020, 0x0073: 0x4017a620,
+ 0x0074: 0x4017c920, 0x0075: 0x4017e920, 0x0076: 0x40181220, 0x0077: 0x40182420,
+ 0x0078: 0x40182e20, 0x0079: 0x40183320, 0x007a: 0x40184420, 0x007b: 0x4001ed20,
+ 0x007c: 0x40048d20, 0x007d: 0x4001ee20, 0x007e: 0x40048f20, 0x007f: 0x80000000,
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0x00c0: 0x80000000, 0x00c1: 0x80000000, 0x00c2: 0x80000000, 0x00c3: 0x80000000,
+ 0x00c4: 0x80000000, 0x00c5: 0x40010520, 0x00c6: 0x80000000, 0x00c7: 0x80000000,
+ 0x00c8: 0x80000000, 0x00c9: 0x80000000, 0x00ca: 0x80000000, 0x00cb: 0x80000000,
+ 0x00cc: 0x80000000, 0x00cd: 0x80000000, 0x00ce: 0x80000000, 0x00cf: 0x80000000,
+ 0x00d0: 0x80000000, 0x00d1: 0x80000000, 0x00d2: 0x80000000, 0x00d3: 0x80000000,
+ 0x00d4: 0x80000000, 0x00d5: 0x80000000, 0x00d6: 0x80000000, 0x00d7: 0x80000000,
+ 0x00d8: 0x80000000, 0x00d9: 0x80000000, 0x00da: 0x80000000, 0x00db: 0x80000000,
+ 0x00dc: 0x80000000, 0x00dd: 0x80000000, 0x00de: 0x80000000, 0x00df: 0x80000000,
+ 0x00e0: 0xf000001b, 0x00e1: 0x40015920, 0x00e2: 0x4013a420, 0x00e3: 0x4013a620,
+ 0x00e4: 0x4013a320, 0x00e5: 0x4013a720, 0x00e6: 0x40048e20, 0x00e7: 0x40031220,
+ 0x00e8: 0x4002f520, 0x00e9: 0x40031420, 0x00ea: 0xf0000014, 0x00eb: 0x4001e720,
+ 0x00ec: 0x40048c20, 0x00ed: 0x80000000, 0x00ee: 0x40031520, 0x00ef: 0x4002f220,
+ 0x00f0: 0x40038220, 0x00f1: 0x40048620, 0x00f2: 0xf0000014, 0x00f3: 0xf0000014,
+ 0x00f4: 0x4002ef20, 0x00f5: 0xf0000004, 0x00f6: 0x40031320, 0x00f7: 0x40017c20,
+ 0x00f8: 0x4002fa20, 0x00f9: 0xf0000014, 0x00fa: 0xf0000014, 0x00fb: 0x4001e820,
+ 0x00fc: 0xf0001e1e, 0x00fd: 0xf0001e1e, 0x00fe: 0xf0001e1e, 0x00ff: 0x40015e20,
+ // Block 0x4, offset 0x100
+ 0x0106: 0xe00006fe,
+ 0x0110: 0xe000073f,
+ 0x0117: 0x40048820,
+ 0x0118: 0xe00007b1,
+ 0x011e: 0x0030ee08, 0x011f: 0xe00007f0,
+ 0x0126: 0xe00006f6,
+ 0x0130: 0xe0000739,
+ 0x0137: 0x40048720,
+ 0x0138: 0xe00007ae,
+ 0x013e: 0x40187720,
+ // Block 0x5, offset 0x140
+ 0x0150: 0xe0000736, 0x0151: 0xe0000733,
+ 0x0166: 0xe0000774, 0x0167: 0xe0000771,
+ 0x0171: 0x40168420, 0x0172: 0xf0000a0a, 0x0173: 0xf0000404,
+ 0x0178: 0x40176c20,
+ 0x017f: 0xe0000792,
+ // Block 0x6, offset 0x180
+ 0x0180: 0xe000078c, 0x0181: 0xe0000786, 0x0182: 0xe0000783,
+ 0x0189: 0xf0000404, 0x018a: 0x002e4008, 0x018b: 0x40172020,
+ 0x0192: 0xe00007b8, 0x0193: 0xe00007b4,
+ 0x01a6: 0x002f9c08, 0x01a7: 0x4017ce20,
+ 0x01bf: 0xe00007dd,
+ // Block 0x7, offset 0x1c0
+ 0x01c0: 0x4015c120, 0x01c1: 0x002b9208, 0x01c2: 0x002b9a08, 0x01c3: 0x4015cd20,
+ 0x01c4: 0x00312a08, 0x01c5: 0x40189520, 0x01c6: 0x002e6008, 0x01c7: 0x002bb408,
+ 0x01c8: 0x4015da20, 0x01c9: 0x002bd808, 0x01ca: 0x002be008, 0x01cb: 0x002bea08,
+ 0x01cc: 0x4015f520, 0x01cd: 0xe0000828, 0x01ce: 0x002c1408, 0x01cf: 0x002c1e08,
+ 0x01d0: 0x002c2808, 0x01d1: 0x002c7c08, 0x01d2: 0x40163e20, 0x01d3: 0x002caa08,
+ 0x01d4: 0x002cbe08, 0x01d5: 0x40166f20, 0x01d6: 0x002d2808, 0x01d7: 0x002d1c08,
+ 0x01d8: 0x002d7008, 0x01d9: 0x4016b820, 0x01da: 0x4016cf20, 0x01db: 0x4016ec20,
+ 0x01dc: 0x00300608, 0x01dd: 0x002e1a08, 0x01de: 0x40171120, 0x01df: 0x002e7608,
+ 0x01e2: 0x002cc608, 0x01e3: 0x40166320,
+ 0x01e4: 0x002ea408, 0x01e5: 0x40175220, 0x01e6: 0x002ee808, 0x01e7: 0x00311a08,
+ 0x01e8: 0x40188d20, 0x01e9: 0x002f6e08, 0x01ea: 0x4017bc20, 0x01eb: 0x4017d420,
+ 0x01ec: 0x002fb008, 0x01ed: 0x4017d820, 0x01ee: 0x002fb808,
+ 0x01f1: 0x00301a08, 0x01f2: 0x00303208, 0x01f3: 0x00307e08,
+ 0x01f4: 0x40183f20, 0x01f5: 0x00309208, 0x01f6: 0x40184920, 0x01f7: 0x0030c208,
+ 0x01f8: 0x0030cc08, 0x01f9: 0x40186620, 0x01fa: 0x40186b20, 0x01fb: 0x40188620,
+ 0x01fc: 0x00312208, 0x01fd: 0x40189120, 0x01fe: 0xe0000809, 0x01ff: 0x40187d20,
+ // Block 0x8, offset 0x200
+ 0x0200: 0x4018bc20, 0x0201: 0x4018c020, 0x0202: 0x4018c420, 0x0203: 0x4018c820,
+ 0x0204: 0xf0000a0a, 0x0205: 0xf000040a, 0x0206: 0xf0000404, 0x0207: 0xf0000a0a,
+ 0x0208: 0xf000040a, 0x0209: 0xf0000404, 0x020a: 0xf0000a0a, 0x020b: 0xf000040a,
+ 0x020c: 0xf0000404,
+ 0x021d: 0x40160a20,
+ 0x0224: 0x002ca008, 0x0225: 0x40165020,
+ 0x0231: 0xf0000a0a, 0x0232: 0xf000040a, 0x0233: 0xf0000404,
+ 0x0236: 0x002cde08, 0x0237: 0x0030fa08,
+ // Block 0x9, offset 0x240
+ 0x025c: 0x0030e608, 0x025d: 0x40187320,
+ 0x0260: 0x002e2208, 0x0261: 0x4015f920, 0x0262: 0x002e8808, 0x0263: 0x40174420,
+ 0x0264: 0x00309e08, 0x0265: 0x40184f20,
+ 0x0274: 0x4016e220, 0x0275: 0x40171b20, 0x0276: 0x4017e020, 0x0277: 0x40169d20,
+ 0x0278: 0xe000074b, 0x0279: 0xe00007c8, 0x027a: 0x002b5008, 0x027b: 0x002bac08,
+ 0x027c: 0x4015d620, 0x027d: 0x002d9e08, 0x027e: 0x002fa408, 0x027f: 0x4017b120,
+ // Block 0xa, offset 0x280
+ 0x0280: 0x40185b20, 0x0281: 0x00313a08, 0x0282: 0x40189d20, 0x0283: 0x002b8208,
+ 0x0284: 0x002fe208, 0x0285: 0x00304008, 0x0286: 0x002c0808, 0x0287: 0x40160420,
+ 0x0288: 0x002d4408, 0x0289: 0x4016a220, 0x028a: 0x002ed008, 0x028b: 0x40176820,
+ 0x028c: 0x002ef408, 0x028d: 0x40177a20, 0x028e: 0x00307608, 0x028f: 0x40183b20,
+ 0x0290: 0x4015ac20, 0x0291: 0x4015b020, 0x0292: 0x4015b520, 0x0293: 0x4015c920,
+ 0x0294: 0x40173020, 0x0295: 0x4015de20, 0x0296: 0x4015ec20, 0x0297: 0x4015f020,
+ 0x0298: 0x40161920, 0x0299: 0x40160f20, 0x029a: 0x40161d20, 0x029b: 0x40161420,
+ 0x029c: 0x40162120, 0x029d: 0x40162720, 0x029e: 0x40162b20, 0x029f: 0x4016aa20,
+ 0x02a0: 0x40165520, 0x02a1: 0x40164820, 0x02a2: 0x40164c20, 0x02a3: 0x40165f20,
+ 0x02a4: 0x40163320, 0x02a5: 0x4017f720, 0x02a6: 0x40167320, 0x02a7: 0x40167a20,
+ 0x02a8: 0x40168e20, 0x02a9: 0x40169420, 0x02aa: 0x40168820, 0x02ab: 0x4016d420,
+ 0x02ac: 0x4016d820, 0x02ad: 0x4016dd20, 0x02ae: 0x4016e720, 0x02af: 0x40180320,
+ 0x02b0: 0x40180920, 0x02b1: 0x4016fb20, 0x02b2: 0x40170d20, 0x02b3: 0x40171720,
+ 0x02b4: 0x40170620, 0x02b5: 0x40173b20, 0x02b6: 0x40172a20, 0x02b7: 0x40174020,
+ 0x02b8: 0x40175920, 0x02b9: 0x40177f20, 0x02ba: 0x40178420, 0x02bb: 0x40178920,
+ 0x02bc: 0x40178e20, 0x02bd: 0x40179220, 0x02be: 0x40179620, 0x02bf: 0x40179b20,
+ // Block 0xb, offset 0x2c0
+ 0x02c0: 0x40177420, 0x02c1: 0x40179f20, 0x02c2: 0x4017ad20, 0x02c3: 0x4017b720,
+ 0x02c4: 0x4016ae20, 0x02c5: 0x4017c020, 0x02c6: 0x4017c520, 0x02c7: 0x4017e520,
+ 0x02c8: 0x4017dc20, 0x02c9: 0x4017f120, 0x02ca: 0x40180d20, 0x02cb: 0x40181920,
+ 0x02cc: 0x40182020, 0x02cd: 0x40182a20, 0x02ce: 0x4016f020, 0x02cf: 0x40183720,
+ 0x02d0: 0x40185320, 0x02d1: 0x40185720, 0x02d2: 0x40186120, 0x02d3: 0x40186f20,
+ 0x02d4: 0x40189920, 0x02d5: 0x4018a720, 0x02d6: 0x4018b820, 0x02d7: 0x4018cc20,
+ 0x02d8: 0x4018d020, 0x02d9: 0x4015bd20, 0x02da: 0x40162f20, 0x02db: 0x40165920,
+ 0x02dc: 0x40166b20, 0x02dd: 0x4016a620, 0x02de: 0x4016c020, 0x02df: 0x4016c820,
+ 0x02e0: 0x40176420, 0x02e1: 0x4018b020, 0x02e2: 0x4018b420, 0x02e3: 0xe000074e,
+ 0x02e4: 0xe0000754, 0x02e5: 0xe0000751, 0x02e6: 0xe000080c, 0x02e7: 0xe000080f,
+ 0x02e8: 0xe0000802, 0x02e9: 0xe000075d, 0x02ea: 0xe000079b, 0x02eb: 0xe000079e,
+ 0x02ec: 0x4018d420, 0x02ed: 0x4018d820, 0x02ee: 0x4017fb20, 0x02ef: 0x4017ff20,
+ 0x02f0: 0xf0000014, 0x02f1: 0xf0000014, 0x02f2: 0xf0000014, 0x02f3: 0xf0000014,
+ 0x02f4: 0xf0000014, 0x02f5: 0xf0000014, 0x02f6: 0xf0000014, 0x02f7: 0xf0000014,
+ 0x02f8: 0xf0000014, 0x02f9: 0x40032020, 0x02fa: 0x40032220, 0x02fb: 0x40167e20,
+ 0x02fc: 0x4018a220, 0x02fd: 0x40167f20, 0x02fe: 0x4018a420, 0x02ff: 0x4018ab20,
+ // Block 0xc, offset 0x300
+ 0x0300: 0x4018a120, 0x0301: 0x4018ac20, 0x0302: 0x40032320, 0x0303: 0x40032420,
+ 0x0304: 0x40032520, 0x0305: 0x40032620, 0x0306: 0x40032720, 0x0307: 0x40032820,
+ 0x0308: 0x40032920, 0x0309: 0x40032a20, 0x030a: 0x40032b20, 0x030b: 0x40032c20,
+ 0x030c: 0x40032d20, 0x030d: 0x40032e20, 0x030e: 0x40032f20, 0x030f: 0x40033020,
+ 0x0310: 0x40139220, 0x0311: 0x40139320, 0x0312: 0x40033120, 0x0313: 0x40033220,
+ 0x0314: 0x40033320, 0x0315: 0x40033420, 0x0316: 0x40033520, 0x0317: 0x40033620,
+ 0x0318: 0x4002f320, 0x0319: 0x4002f420, 0x031a: 0x4002f620, 0x031b: 0x4002fb20,
+ 0x031c: 0x4002f020, 0x031d: 0x4002f720, 0x031e: 0x40033720, 0x031f: 0x40033820,
+ 0x0320: 0xf0000014, 0x0321: 0xf0000014, 0x0322: 0xf0000014, 0x0323: 0xf0000014,
+ 0x0324: 0xf0000014, 0x0325: 0x40033920, 0x0326: 0x40033a20, 0x0327: 0x40033b20,
+ 0x0328: 0x40033c20, 0x0329: 0x40033d20, 0x032a: 0x40033e20, 0x032b: 0x40033f20,
+ 0x032c: 0x40034020, 0x032d: 0x40034120, 0x032e: 0x4018a320, 0x032f: 0x40034220,
+ 0x0330: 0x40034320, 0x0331: 0x40034420, 0x0332: 0x40034520, 0x0333: 0x40034620,
+ 0x0334: 0x40034720, 0x0335: 0x40034820, 0x0336: 0x40034920, 0x0337: 0x40034a20,
+ 0x0338: 0x40034b20, 0x0339: 0x40034c20, 0x033a: 0x40034d20, 0x033b: 0x40034e20,
+ 0x033c: 0x40034f20, 0x033d: 0x40035020, 0x033e: 0x40035120, 0x033f: 0x40035220,
+ // Block 0xd, offset 0x340
+ 0x0340: 0x80003502, 0x0341: 0x80003202, 0x0342: 0x80003c02, 0x0343: 0x80004e02,
+ 0x0344: 0x80005b02, 0x0345: 0x80006302, 0x0346: 0x80003702, 0x0347: 0x80005202,
+ 0x0348: 0x80004702, 0x0349: 0x80006402, 0x034a: 0x80004302, 0x034b: 0x80004d02,
+ 0x034c: 0x80004102, 0x034d: 0x80005f02, 0x034e: 0x80005f02, 0x034f: 0x80006502,
+ 0x0350: 0x80006602, 0x0351: 0x80006702, 0x0352: 0x80005f02, 0x0353: 0x80002202,
+ 0x0354: 0x80002a02, 0x0355: 0x80005f02, 0x0356: 0x80006002, 0x0357: 0x80006002,
+ 0x0358: 0x80006002, 0x0359: 0x80006002, 0x035a: 0x80005f02, 0x035b: 0x80006802,
+ 0x035c: 0x80006002, 0x035d: 0x80006002, 0x035e: 0x80006002, 0x035f: 0x80006002,
+ 0x0360: 0x80006002, 0x0361: 0x80006e02, 0x0362: 0x80006f02, 0x0363: 0x80007002,
+ 0x0364: 0x80007502, 0x0365: 0x80007602, 0x0366: 0x80007702, 0x0367: 0x80005602,
+ 0x0368: 0x80005902, 0x0369: 0x80006002, 0x036a: 0x80006002, 0x036b: 0x80006002,
+ 0x036c: 0x80006002, 0x036d: 0x80007802, 0x036e: 0x80007902, 0x036f: 0x80006002,
+ 0x0370: 0x80007a02, 0x0371: 0x80007b02, 0x0372: 0x80002102, 0x0373: 0x80006002,
+ 0x0374: 0x80007c02, 0x0375: 0x80007d02, 0x0376: 0x80006102, 0x0377: 0x80006102,
+ 0x0378: 0x80005402, 0x0379: 0x80007e02, 0x037a: 0x80006002, 0x037b: 0x80006002,
+ 0x037c: 0x80006002, 0x037d: 0x80005f02, 0x037e: 0x80005f02, 0x037f: 0x80005f02,
+ // Block 0xe, offset 0x380
+ 0x0382: 0x80004502,
+ 0x0385: 0x80007f02, 0x0386: 0x80005f02, 0x0387: 0x80006002,
+ 0x0388: 0x80006002, 0x0389: 0x80006002, 0x038a: 0x80005f02, 0x038b: 0x80005f02,
+ 0x038c: 0x80005f02, 0x038d: 0x80006002, 0x038e: 0x80006002, 0x038f: 0x80000000,
+ 0x0390: 0x80005f02, 0x0391: 0x80005f02, 0x0392: 0x80005f02, 0x0393: 0x80006002,
+ 0x0394: 0x80006002, 0x0395: 0x80006002, 0x0396: 0x80006002, 0x0397: 0x80005f02,
+ 0x0398: 0x80008002, 0x0399: 0x80006002, 0x039a: 0x80006002, 0x039b: 0x80005f02,
+ 0x039c: 0x80006002, 0x039d: 0x80005f02, 0x039e: 0x80005f02, 0x039f: 0x80006002,
+ 0x03a0: 0x80008102, 0x03a1: 0x80008202, 0x03a2: 0x80006002, 0x03a3: 0x002b4604,
+ 0x03a4: 0x002bfe04, 0x03a5: 0x002d0004, 0x03a6: 0x002e4804, 0x03a7: 0x002fd204,
+ 0x03a8: 0x002ba204, 0x03a9: 0x002bc804, 0x03aa: 0x002cce04, 0x03ab: 0x002de804,
+ 0x03ac: 0x002ee004, 0x03ad: 0x002f9204, 0x03ae: 0x00302404, 0x03af: 0x00305c04,
+ 0x03b0: 0x0031cc08, 0x03b1: 0x4018e620, 0x03b2: 0x00320c08, 0x03b3: 0x40190620,
+ 0x03b5: 0x40032120, 0x03b6: 0x0031c608, 0x03b7: 0x4018e320,
+ 0x03ba: 0x0031d204, 0x03bb: 0x4018fc20,
+ 0x03bc: 0x4018fb20, 0x03bd: 0x4018fd20,
+ // Block 0xf, offset 0x3c0
+ 0x03c4: 0x4002ef20,
+ 0x03d1: 0x0031b808, 0x03d2: 0x0031ba08, 0x03d3: 0x0031bc08,
+ 0x03d4: 0x0031c008, 0x03d5: 0x0031c208, 0x03d6: 0x0031ca08, 0x03d7: 0x0031ce08,
+ 0x03d8: 0x0031d008, 0x03d9: 0x0031d208, 0x03da: 0x0031d608, 0x03db: 0x0031d808,
+ 0x03dc: 0x0031dc08, 0x03dd: 0x0031de08, 0x03de: 0x0031e008, 0x03df: 0x0031e208,
+ 0x03e0: 0x0031e408, 0x03e1: 0x0031ee08, 0x03e3: 0x0031f408,
+ 0x03e4: 0x0031fc08, 0x03e5: 0x0031fe08, 0x03e6: 0x00320008, 0x03e7: 0x00320208,
+ 0x03e8: 0x00320408, 0x03e9: 0x00320808,
+ 0x03f1: 0x4018dc20, 0x03f2: 0x4018dd20, 0x03f3: 0x4018de20,
+ 0x03f4: 0x4018e020, 0x03f5: 0x4018e120, 0x03f6: 0x4018e520, 0x03f7: 0x4018e720,
+ 0x03f8: 0x4018e820, 0x03f9: 0x4018e920, 0x03fa: 0x4018eb20, 0x03fb: 0x4018ec20,
+ 0x03fc: 0x4018ee20, 0x03fd: 0x4018ef20, 0x03fe: 0x4018f020, 0x03ff: 0x4018f120,
+ // Block 0x10, offset 0x400
+ 0x0400: 0x4018f220, 0x0401: 0x4018f720, 0x0402: 0x0031f419, 0x0403: 0x4018fa20,
+ 0x0404: 0x4018fe20, 0x0405: 0x4018ff20, 0x0406: 0x40190020, 0x0407: 0x40190120,
+ 0x0408: 0x40190220, 0x0409: 0x40190420,
+ 0x040f: 0xe000082f,
+ 0x0410: 0xf0000004, 0x0411: 0xf0000004, 0x0412: 0xf000000a,
+ 0x0415: 0xf0000004, 0x0416: 0xf0000004, 0x0417: 0xe000082b,
+ 0x0418: 0x0031ec08, 0x0419: 0x4018f620, 0x041a: 0x0031c808, 0x041b: 0x4018e420,
+ 0x041c: 0x0031c408, 0x041d: 0x4018e220, 0x041e: 0x0031ea08, 0x041f: 0x4018f520,
+ 0x0420: 0x00320a08, 0x0421: 0x40190520, 0x0422: 0x00324e08, 0x0423: 0x40192720,
+ 0x0424: 0x00325808, 0x0425: 0x40192c20, 0x0426: 0x00325a08, 0x0427: 0x40192d20,
+ 0x0428: 0x00325e08, 0x0429: 0x40192f20, 0x042a: 0x00326c08, 0x042b: 0x40193620,
+ 0x042c: 0x00327208, 0x042d: 0x40193920, 0x042e: 0x00327a08, 0x042f: 0x40193d20,
+ 0x0430: 0xf0000004, 0x0431: 0xf0000004, 0x0432: 0xf0000004, 0x0433: 0x4018ea20,
+ 0x0434: 0xf000000a, 0x0435: 0xf0000004, 0x0436: 0x40048020, 0x0437: 0x00320e08,
+ 0x0438: 0x40190720, 0x0439: 0xf000000a, 0x043a: 0x0031e808, 0x043b: 0x4018f420,
+ 0x043c: 0x4018f920, 0x043d: 0x0031f808, 0x043e: 0x0031f608, 0x043f: 0x0031fa08,
+ // Block 0x11, offset 0x440
+ 0x0442: 0x0032fa08, 0x0443: 0x00330608,
+ 0x0444: 0x00332608, 0x0445: 0x00336008, 0x0446: 0xc02a0071, 0x0447: 0x00339a08,
+ 0x0448: 0x0033aa08, 0x0449: 0x0033fe08, 0x044a: 0x00344808, 0x044b: 0x0034c608,
+ 0x044c: 0x0034ce08, 0x044e: 0x0034de08, 0x044f: 0x0035b808,
+ 0x0450: 0xc0090041, 0x0451: 0x0032b608, 0x0452: 0x0032be08, 0x0453: 0xc0130092,
+ 0x0454: 0x0032ee08, 0x0455: 0xc01800d1, 0x0456: 0xc01c0071, 0x0457: 0xc0200071,
+ 0x0458: 0xc0250041, 0x0459: 0x0033a208, 0x045a: 0xc0370092, 0x045b: 0x0033e808,
+ 0x045c: 0x00340c08, 0x045d: 0x00341e08, 0x045e: 0xc02e0071, 0x045f: 0x00347208,
+ 0x0460: 0x00348c08, 0x0461: 0x00349e08, 0x0462: 0x0034b008, 0x0463: 0xc03e00f1,
+ 0x0464: 0x00351008, 0x0465: 0x00351808, 0x0466: 0x00356608, 0x0467: 0xc0440071,
+ 0x0468: 0x0035c008, 0x0469: 0x0035ca08, 0x046a: 0x0035d808, 0x046b: 0xc0480071,
+ 0x046c: 0x0035f208, 0x046d: 0xc04c0071, 0x046e: 0x00361c08, 0x046f: 0x00362808,
+ 0x0470: 0xc0060041, 0x0471: 0x40195b20, 0x0472: 0x40195f20, 0x0473: 0xc0100092,
+ 0x0474: 0x40197720, 0x0475: 0xc01600d1, 0x0476: 0xc01a0071, 0x0477: 0xc01e0071,
+ 0x0478: 0xc0220041, 0x0479: 0x4019d120, 0x047a: 0xc0340092, 0x047b: 0x4019f420,
+ 0x047c: 0x401a0620, 0x047d: 0x401a0f20, 0x047e: 0xc02c0071, 0x047f: 0x401a3920,
+ // Block 0x12, offset 0x480
+ 0x0480: 0x401a4620, 0x0481: 0x401a4f20, 0x0482: 0x401a5820, 0x0483: 0xc03a00f1,
+ 0x0484: 0x401a8820, 0x0485: 0x401a8c20, 0x0486: 0x401ab320, 0x0487: 0xc0420071,
+ 0x0488: 0x401ae020, 0x0489: 0x401ae520, 0x048a: 0x401aec20, 0x048b: 0xc0460071,
+ 0x048c: 0x401af920, 0x048d: 0xc04a0071, 0x048e: 0x401b0e20, 0x048f: 0x401b1420,
+ 0x0492: 0x40197d20, 0x0493: 0x40198320,
+ 0x0494: 0x40199320, 0x0495: 0x4019b020, 0x0496: 0xc0280071, 0x0497: 0x4019cd20,
+ 0x0498: 0x4019d520, 0x0499: 0x4019ff20, 0x049a: 0x401a2420, 0x049b: 0x401a6320,
+ 0x049c: 0x401a6720, 0x049e: 0x401a6f20, 0x049f: 0x401adc20,
+ 0x04a0: 0x00354408, 0x04a1: 0x401aa220, 0x04a2: 0x00360208, 0x04a3: 0x401b0120,
+ 0x04a4: 0x00363208, 0x04a5: 0x401b1920, 0x04a6: 0x00363a08, 0x04a7: 0x401b1d20,
+ 0x04a8: 0x00364e08, 0x04a9: 0x401b2720, 0x04aa: 0x00364408, 0x04ab: 0x401b2220,
+ 0x04ac: 0x00365808, 0x04ad: 0x401b2c20, 0x04ae: 0x00366008, 0x04af: 0x401b3020,
+ 0x04b0: 0x00366808, 0x04b1: 0x401b3420, 0x04b2: 0x00367008, 0x04b3: 0x401b3820,
+ 0x04b4: 0xc0500131, 0x04b5: 0xc04e0131, 0x04b6: 0x00368008, 0x04b7: 0x401b4020,
+ 0x04b8: 0x00350808, 0x04b9: 0x401a8420, 0x04ba: 0x00355e08, 0x04bb: 0x401aaf20,
+ 0x04bc: 0x00355608, 0x04bd: 0x401aab20, 0x04be: 0x00354c08, 0x04bf: 0x401aa620,
+ // Block 0x13, offset 0x4c0
+ 0x04c0: 0x00348408, 0x04c1: 0x401a4220, 0x04c2: 0x40038320, 0x04c3: 0x80008302,
+ 0x04c4: 0x80005f02, 0x04c5: 0x80002a02, 0x04c6: 0x80002202, 0x04c7: 0x80005f02,
+ 0x04c8: 0x80000000, 0x04c9: 0x80000000, 0x04ca: 0x00338008, 0x04cb: 0x4019c020,
+ 0x04cc: 0x0035fa08, 0x04cd: 0x401afd20, 0x04ce: 0x00349408, 0x04cf: 0x401a4a20,
+ 0x04d0: 0xe000083a, 0x04d1: 0xe0000837, 0x04d2: 0x0032ce08, 0x04d3: 0x40196720,
+ 0x04d4: 0x0032de08, 0x04d5: 0x40196f20, 0x04d6: 0x00334008, 0x04d7: 0x4019a020,
+ 0x04d8: 0x00330e08, 0x04d9: 0x40198720, 0x04da: 0x0033bc08, 0x04db: 0x4019de20,
+ 0x04dc: 0x0033dc08, 0x04dd: 0x4019ee20, 0x04de: 0x0033d408, 0x04df: 0x4019ea20,
+ 0x04e0: 0x0033cc08, 0x04e1: 0x4019e620, 0x04e2: 0x00342e08, 0x04e3: 0x401a1720,
+ 0x04e4: 0x00344008, 0x04e5: 0x401a2020, 0x04e6: 0x00347c08, 0x04e7: 0x401a3e20,
+ 0x04e8: 0x00368a08, 0x04e9: 0x401b4520, 0x04ea: 0x0034a808, 0x04eb: 0x401a5420,
+ 0x04ec: 0x0034bc08, 0x04ed: 0x401a5e20, 0x04ee: 0x0034f608, 0x04ef: 0x401a7b20,
+ 0x04f0: 0x0034fe08, 0x04f1: 0x401a7f20, 0x04f2: 0x00353008, 0x04f3: 0x401a9820,
+ 0x04f4: 0x00357208, 0x04f5: 0x401ab920, 0x04f6: 0x00358e08, 0x04f7: 0x401ac720,
+ 0x04f8: 0x00359e08, 0x04f9: 0x401acf20, 0x04fa: 0x00353808, 0x04fb: 0x401a9c20,
+ 0x04fc: 0x0035a808, 0x04fd: 0x401ad420, 0x04fe: 0x0035b008, 0x04ff: 0x401ad820,
+ // Block 0x14, offset 0x500
+ 0x0500: 0x00369408, 0x0503: 0x0033c408,
+ 0x0504: 0x4019e220, 0x0505: 0x0033f208, 0x0506: 0x4019f920, 0x0507: 0x00343608,
+ 0x0508: 0x401a1b20, 0x0509: 0x00342608, 0x050a: 0x401a1320, 0x050b: 0x00359608,
+ 0x050c: 0x401acb20, 0x050d: 0x00341408, 0x050e: 0x401a0a20, 0x050f: 0x401b4a20,
+ 0x0510: 0x00328e08, 0x0511: 0x40194720, 0x0512: 0x00329608, 0x0513: 0x40194b20,
+ 0x0514: 0x0032ae08, 0x0515: 0x40195720, 0x0516: 0x00331e08, 0x0517: 0x40198f20,
+ 0x0518: 0xc00e0071, 0x0519: 0xc00c0071, 0x051a: 0x0032a608, 0x051b: 0x40195320,
+ 0x051c: 0x00333808, 0x051d: 0x40199c20, 0x051e: 0x00335608, 0x051f: 0x4019ab20,
+ 0x0520: 0x00336a08, 0x0521: 0x4019b520,
+ 0x0524: 0x00338808, 0x0525: 0x4019c420, 0x0526: 0x00345a08, 0x0527: 0x401a2d20,
+ 0x0528: 0xc0320071, 0x0529: 0xc0300071, 0x052a: 0x00346a08, 0x052b: 0x401a3520,
+ 0x052c: 0x00361408, 0x052d: 0x401b0a20,
+ 0x0530: 0x0034e608, 0x0531: 0x401a7320, 0x0532: 0x0034ee08, 0x0533: 0x401a7720,
+ 0x0534: 0x00358608, 0x0535: 0x401ac320, 0x0536: 0x0032e608, 0x0537: 0x40197320,
+ 0x0538: 0x0035ea08, 0x0539: 0x401af520, 0x053a: 0x0032d608, 0x053b: 0x40196b20,
+ 0x053c: 0x00352008, 0x053d: 0x401a9020, 0x053e: 0x00352808, 0x053f: 0x401a9420,
+ // Block 0x15, offset 0x540
+ 0x0540: 0x0032f608, 0x0541: 0x40197b20, 0x0542: 0x00330408, 0x0543: 0x40198220,
+ 0x0544: 0x00335208, 0x0545: 0x4019a920, 0x0546: 0x00337408, 0x0547: 0x4019ba20,
+ 0x0548: 0x00340808, 0x0549: 0x401a0420, 0x054a: 0x00345008, 0x054b: 0x401a2820,
+ 0x054c: 0x0034a608, 0x054d: 0x401a5320, 0x054e: 0x0034ba08, 0x054f: 0x401a5d20,
+ 0x0550: 0x00335408, 0x0551: 0x4019aa20, 0x0552: 0x0033fa08, 0x0553: 0x4019fd20,
+ 0x0554: 0x00340a08, 0x0555: 0x401a0520, 0x0556: 0x00349c08, 0x0557: 0x401a4e20,
+ 0x0558: 0x00363008, 0x0559: 0x401b1820, 0x055a: 0x0033e608, 0x055b: 0x4019f320,
+ 0x055c: 0x00369208, 0x055d: 0x401b4920, 0x055e: 0x0033e408, 0x055f: 0x4019f220,
+ 0x0560: 0x0033fc08, 0x0561: 0x4019fe20, 0x0562: 0x00343e08, 0x0563: 0x401a1f20,
+ 0x0564: 0x00347a08, 0x0565: 0x401a3d20, 0x0566: 0x00354008, 0x0567: 0x401aa020,
+ 0x0571: 0x00379c08, 0x0572: 0x00379e08, 0x0573: 0x0037a008,
+ 0x0574: 0x0037a208, 0x0575: 0x0037a408, 0x0576: 0x0037a608, 0x0577: 0x0037a808,
+ 0x0578: 0x0037aa08, 0x0579: 0x0037ac08, 0x057a: 0x0037ae08, 0x057b: 0x0037b008,
+ 0x057c: 0x0037b208, 0x057d: 0x0037b408, 0x057e: 0x0037b608, 0x057f: 0x0037b808,
+ // Block 0x16, offset 0x580
+ 0x0580: 0x0037ba08, 0x0581: 0x0037bc08, 0x0582: 0x0037be08, 0x0583: 0x0037c008,
+ 0x0584: 0x0037c208, 0x0585: 0x0037c408, 0x0586: 0x0037c608, 0x0587: 0x0037c808,
+ 0x0588: 0x0037ca08, 0x0589: 0x0037cc08, 0x058a: 0x0037ce08, 0x058b: 0x0037d008,
+ 0x058c: 0x0037d208, 0x058d: 0x0037d408, 0x058e: 0x0037d608, 0x058f: 0x0037d808,
+ 0x0590: 0x0037da08, 0x0591: 0x0037dc08, 0x0592: 0x0037de08, 0x0593: 0x0037e008,
+ 0x0594: 0x0037e208, 0x0595: 0x0037e408, 0x0596: 0x0037e608,
+ 0x0599: 0x401bf420, 0x059a: 0x40027520, 0x059b: 0x40027620,
+ 0x059c: 0x40015a20, 0x059d: 0x40012020, 0x059e: 0x40016020, 0x059f: 0x40027720,
+ 0x05a1: 0x401bce20, 0x05a2: 0x401bcf20, 0x05a3: 0x401bd020,
+ 0x05a4: 0x401bd120, 0x05a5: 0x401bd220, 0x05a6: 0x401bd320, 0x05a7: 0x401bd420,
+ 0x05a8: 0x401bd520, 0x05a9: 0x401bd620, 0x05aa: 0x401bd720, 0x05ab: 0x401bd820,
+ 0x05ac: 0x401bd920, 0x05ad: 0x401bda20, 0x05ae: 0x401bdb20, 0x05af: 0x401bdc20,
+ 0x05b0: 0x401bdd20, 0x05b1: 0x401bde20, 0x05b2: 0x401bdf20, 0x05b3: 0x401be020,
+ 0x05b4: 0x401be120, 0x05b5: 0x401be220, 0x05b6: 0x401be320, 0x05b7: 0x401be420,
+ 0x05b8: 0x401be520, 0x05b9: 0x401be620, 0x05ba: 0x401be720, 0x05bb: 0x401be820,
+ 0x05bc: 0x401be920, 0x05bd: 0x401bea20, 0x05be: 0x401beb20, 0x05bf: 0x401bec20,
+ // Block 0x17, offset 0x5c0
+ 0x05c0: 0x401bed20, 0x05c1: 0x401bee20, 0x05c2: 0x401bef20, 0x05c3: 0x401bf020,
+ 0x05c4: 0x401bf120, 0x05c5: 0x401bf220, 0x05c6: 0x401bf320, 0x05c7: 0xf0000404,
+ 0x05c9: 0x40013320, 0x05ca: 0x40010f20,
+ 0x05d1: 0x80000000, 0x05d2: 0x80000000, 0x05d3: 0x80000000,
+ 0x05d4: 0x80000000, 0x05d5: 0x80000000, 0x05d6: 0x80000000, 0x05d7: 0x80000000,
+ 0x05d8: 0x80000000, 0x05d9: 0x80000000, 0x05da: 0x80000000, 0x05db: 0x80000000,
+ 0x05dc: 0x80000000, 0x05dd: 0x80000000, 0x05de: 0x80000000, 0x05df: 0x80000000,
+ 0x05e0: 0x80000000, 0x05e1: 0x80000000, 0x05e2: 0x80000000, 0x05e3: 0x80000000,
+ 0x05e4: 0x80000000, 0x05e5: 0x80000000, 0x05e6: 0x80000000, 0x05e7: 0x80000000,
+ 0x05e8: 0x80000000, 0x05e9: 0x80000000, 0x05ea: 0x80000000, 0x05eb: 0x80000000,
+ 0x05ec: 0x80000000, 0x05ed: 0x80000000, 0x05ee: 0x80000000, 0x05ef: 0x80000000,
+ 0x05f0: 0x80008502, 0x05f1: 0x80008602, 0x05f2: 0x80008702, 0x05f3: 0x80008802,
+ 0x05f4: 0x80008902, 0x05f5: 0x80008a02, 0x05f6: 0x80008b02, 0x05f7: 0x80008c02,
+ 0x05f8: 0x80008d02, 0x05f9: 0x80008e02, 0x05fa: 0x80008e02, 0x05fb: 0x80008f02,
+ 0x05fc: 0x80009202, 0x05fd: 0x80000000, 0x05fe: 0x40027820, 0x05ff: 0x80009502,
+ // Block 0x18, offset 0x600
+ 0x0600: 0x40027920, 0x0601: 0x80009102, 0x0602: 0x80009002, 0x0603: 0x40027a20,
+ 0x0604: 0x80000000, 0x0605: 0x80000000, 0x0606: 0x40027b20, 0x0607: 0x80008d02,
+ 0x0610: 0x401bf520, 0x0611: 0x401bf620, 0x0612: 0x401bf720, 0x0613: 0x401bf820,
+ 0x0614: 0x401bf920, 0x0615: 0x401bfa20, 0x0616: 0x401bfb20, 0x0617: 0x401bfc20,
+ 0x0618: 0x401bfd20, 0x0619: 0x401bfe20, 0x061a: 0x0037fe19, 0x061b: 0x401bff20,
+ 0x061c: 0x401c0020, 0x061d: 0x00380219, 0x061e: 0x401c0120, 0x061f: 0x00380419,
+ 0x0620: 0x401c0220, 0x0621: 0x401c0320, 0x0622: 0x401c0420, 0x0623: 0x00380a19,
+ 0x0624: 0x401c0520, 0x0625: 0x00380c19, 0x0626: 0x401c0620, 0x0627: 0x401c0720,
+ 0x0628: 0x401c0820, 0x0629: 0x401c0920, 0x062a: 0x401c0a20,
+ 0x0630: 0xe0000840, 0x0631: 0xe0000843, 0x0632: 0xe0000846, 0x0633: 0x40027c20,
+ 0x0634: 0x40027d20,
+ // Block 0x19, offset 0x640
+ 0x0640: 0x80000000, 0x0641: 0x80000000, 0x0642: 0x80000000, 0x0643: 0x80000000,
+ 0x0646: 0x40049a20, 0x0647: 0x40049c20,
+ 0x0648: 0x40038420, 0x0649: 0x40024a20, 0x064a: 0x40024c20, 0x064b: 0x4013a820,
+ 0x064c: 0x40012120, 0x064d: 0x40012220, 0x064e: 0x40038520, 0x064f: 0x40038620,
+ 0x0650: 0x80000000, 0x0651: 0x80000000, 0x0652: 0x80000000, 0x0653: 0x80000000,
+ 0x0654: 0x80000000, 0x0655: 0x80000000, 0x0656: 0x80000000, 0x0657: 0x80000000,
+ 0x0658: 0x80000000, 0x0659: 0x80000000, 0x065a: 0x80000000, 0x065b: 0x40012f20,
+ 0x065e: 0x40013420, 0x065f: 0x40016120,
+ 0x0660: 0x401cf220, 0x0661: 0x401c3b20, 0x0662: 0x401c3c20, 0x0663: 0x401c3d20,
+ 0x0664: 0x401c4020, 0x0665: 0x401c4120, 0x0666: 0x401c4520, 0x0667: 0xc0520151,
+ 0x0668: 0x401c4820, 0x0669: 0x401c5320, 0x066a: 0x401c5420, 0x066b: 0x401c5520,
+ 0x066c: 0x401c5b20, 0x066d: 0x401c6120, 0x066e: 0x401c6220, 0x066f: 0x401c6c20,
+ 0x0670: 0x401c6d20, 0x0671: 0x401c7a20, 0x0672: 0x401c7b20, 0x0673: 0x401c8a20,
+ 0x0674: 0x401c8b20, 0x0675: 0x401c9520, 0x0676: 0x401c9620, 0x0677: 0x401c9a20,
+ 0x0678: 0x401c9b20, 0x0679: 0x401c9d20, 0x067a: 0x401c9e20, 0x067b: 0x401cc020,
+ 0x067c: 0x401cc120, 0x067d: 0x401cef20, 0x067e: 0x401cf020, 0x067f: 0x401cf120,
+ // Block 0x1a, offset 0x680
+ 0x0680: 0x80000000, 0x0681: 0x401ca420, 0x0682: 0x401cae20, 0x0683: 0x401cb120,
+ 0x0684: 0x401cc420, 0x0685: 0x401cca20, 0x0686: 0x401ccd20, 0x0687: 0x401cd620,
+ 0x0688: 0xc0560171, 0x0689: 0x401ce820, 0x068a: 0xc0580171, 0x068b: 0x8000a202,
+ 0x068c: 0x8000a302, 0x068d: 0x8000a502, 0x068e: 0x8000a702, 0x068f: 0x8000a902,
+ 0x0690: 0x8000ab02, 0x0691: 0x8000ad02, 0x0692: 0x8000af02, 0x0693: 0x8000b002,
+ 0x0694: 0x8000b102, 0x0695: 0x8000b202, 0x0696: 0x8000b402, 0x0697: 0x8000b502,
+ 0x0698: 0x8000b602, 0x0699: 0x8000b702, 0x069a: 0x8000b802, 0x069b: 0x8000b902,
+ 0x069c: 0x8000ba02, 0x069d: 0x8000bb02, 0x069e: 0x8000bc02, 0x069f: 0x8000b302,
+ 0x06a0: 0xe0000021, 0x06a1: 0xe0000099, 0x06a2: 0xe0000183, 0x06a3: 0xe0000249,
+ 0x06a4: 0xe000030c, 0x06a5: 0xe00003c6, 0x06a6: 0xe000047d, 0x06a7: 0xe0000519,
+ 0x06a8: 0xe00005b5, 0x06a9: 0xe000064e, 0x06aa: 0x40024820, 0x06ab: 0x40012320,
+ 0x06ac: 0x40012420, 0x06ad: 0x40024020, 0x06ae: 0x401c4720, 0x06af: 0x401cad20,
+ 0x06b0: 0x8000bd02, 0x06b1: 0x401c3f20, 0x06b2: 0x401c3e20, 0x06b3: 0x401c4220,
+ 0x06b4: 0x00387604, 0x06b5: 0xf0000404, 0x06b6: 0xf0000404, 0x06b7: 0xf0000404,
+ 0x06b8: 0xf0000404, 0x06b9: 0x401c5620, 0x06ba: 0x401c5720, 0x06bb: 0x401c4920,
+ 0x06bc: 0x401c5820, 0x06bd: 0x401c5920, 0x06be: 0x401c4a20, 0x06bf: 0x401c5a20,
+ // Block 0x1b, offset 0x6c0
+ 0x06c0: 0x401c4b20, 0x06c1: 0x401c6320, 0x06c2: 0x401c6420, 0x06c3: 0x401c5c20,
+ 0x06c4: 0x401c5d20, 0x06c5: 0x401c6520, 0x06c6: 0x401c5e20, 0x06c7: 0x401c6020,
+ 0x06c8: 0x401c6e20, 0x06c9: 0x401c6f20, 0x06ca: 0x401c7020, 0x06cb: 0x401c7120,
+ 0x06cc: 0x401c7220, 0x06cd: 0x401c7320, 0x06ce: 0x401c7420, 0x06cf: 0x401c7520,
+ 0x06d0: 0x401c7620, 0x06d1: 0x401c7c20, 0x06d2: 0x401c7d20, 0x06d3: 0x401c7e20,
+ 0x06d4: 0x401c7f20, 0x06d5: 0x401c8020, 0x06d6: 0x401c8120, 0x06d7: 0x401c8220,
+ 0x06d8: 0x401c8320, 0x06d9: 0x401c8420, 0x06da: 0x401c8c20, 0x06db: 0x401c8d20,
+ 0x06dc: 0x401c8e20, 0x06dd: 0x401c9720, 0x06de: 0x401c9820, 0x06df: 0x401c9c20,
+ 0x06e0: 0x401c9f20, 0x06e1: 0x401ca520, 0x06e2: 0x401ca620, 0x06e3: 0x401ca720,
+ 0x06e4: 0x401ca820, 0x06e5: 0x401ca920, 0x06e6: 0x401caa20, 0x06e7: 0x401caf20,
+ 0x06e8: 0x401cb020, 0x06e9: 0x401cb220, 0x06ea: 0x401cb320, 0x06eb: 0x401cb420,
+ 0x06ec: 0x401cb520, 0x06ed: 0x401cb720, 0x06ee: 0x401cb820, 0x06ef: 0x401cb920,
+ 0x06f0: 0x401cba20, 0x06f1: 0x401cbb20, 0x06f2: 0x401cbc20, 0x06f3: 0x401cbd20,
+ 0x06f4: 0x401cbe20, 0x06f5: 0x401cc520, 0x06f6: 0x401cc620, 0x06f7: 0x401cc720,
+ 0x06f8: 0x401cc820, 0x06f9: 0x401cd220, 0x06fa: 0x401cce20, 0x06fb: 0x401ccf20,
+ 0x06fc: 0x401cd020, 0x06fd: 0x401cd120, 0x06fe: 0x401cd720, 0x06ff: 0x401c5f20,
+ // Block 0x1c, offset 0x700
+ 0x0701: 0x401cd820, 0x0703: 0x401cd920,
+ 0x0704: 0x401cdd20, 0x0705: 0x401cde20, 0x0706: 0x401cdf20, 0x0707: 0x401ce020,
+ 0x0708: 0x401ce120, 0x0709: 0x401ce220, 0x070a: 0x401ce320, 0x070b: 0x401ce420,
+ 0x070c: 0x401cea20, 0x070d: 0x401ceb20, 0x070e: 0x401cec20, 0x070f: 0x401ce520,
+ 0x0710: 0x401ced20, 0x0711: 0x401cee20, 0x0712: 0x401cf620,
+ 0x0714: 0x40016d20, 0x0715: 0x401cdb20, 0x0716: 0x80000000, 0x0717: 0x80000000,
+ 0x0718: 0x80000000, 0x0719: 0x80000000, 0x071a: 0x80000000, 0x071b: 0x80000000,
+ 0x071c: 0x80000000, 0x071d: 0x80000000, 0x071e: 0x40038720, 0x071f: 0x80000000,
+ 0x0720: 0x80000000, 0x0721: 0x80000000, 0x0722: 0x80000000, 0x0723: 0x80000000,
+ 0x0724: 0x80000000, 0x0725: 0x0039b804, 0x0726: 0x0039d204, 0x0727: 0x80000000,
+ 0x0728: 0x80000000, 0x0729: 0x40038820, 0x072a: 0x80000000, 0x072b: 0x80000000,
+ 0x072c: 0x80000000, 0x072d: 0x80000000, 0x072e: 0x401c7720, 0x072f: 0x401c8520,
+ 0x0730: 0xe0000024, 0x0731: 0xe000009c, 0x0732: 0xe0000186, 0x0733: 0xe000024c,
+ 0x0734: 0xe000030f, 0x0735: 0xe00003c9, 0x0736: 0xe0000480, 0x0737: 0xe000051c,
+ 0x0738: 0xe00005b8, 0x0739: 0xe0000651, 0x073a: 0x401c8f20, 0x073b: 0x401c9920,
+ 0x073c: 0x401ca020, 0x073d: 0xe0000849, 0x073e: 0xe00008ca, 0x073f: 0x401cda20,
+ // Block 0x1d, offset 0x740
+ 0x0740: 0x4001a120, 0x0741: 0x40016e20, 0x0742: 0x40016f20, 0x0743: 0x40013520,
+ 0x0744: 0x40013620, 0x0745: 0x40013720, 0x0746: 0x40013820, 0x0747: 0x40013920,
+ 0x0748: 0x40013a20, 0x0749: 0x40016220, 0x074a: 0x40027e20, 0x074b: 0x40027f20,
+ 0x074c: 0x40028020, 0x074d: 0x40028120, 0x074f: 0x80000000,
+ 0x0750: 0x401cf920, 0x0751: 0x8000be02, 0x0752: 0x401cfa20, 0x0753: 0x401cfb20,
+ 0x0754: 0xe00008d0, 0x0755: 0x401cfd20, 0x0756: 0x401cfc20, 0x0757: 0x401cfe20,
+ 0x0758: 0x401cff20, 0x0759: 0x401d0020, 0x075a: 0x401d0220, 0x075b: 0x401d0320,
+ 0x075c: 0xe00008d9, 0x075d: 0x401d0420, 0x075e: 0x401d0520, 0x075f: 0x401d0620,
+ 0x0760: 0x401d0820, 0x0761: 0x401d0920, 0x0762: 0x401d0a20, 0x0763: 0x401d0b20,
+ 0x0764: 0x003a1619, 0x0765: 0x401d0c20, 0x0766: 0x401d0d20, 0x0767: 0xe00008dc,
+ 0x0768: 0x401d0f20, 0x0769: 0x401d1020, 0x076a: 0x401d1120, 0x076b: 0x401d1220,
+ 0x076c: 0x401d1320, 0x076d: 0xe00008cd, 0x076e: 0xe00008d3, 0x076f: 0xe00008d6,
+ 0x0770: 0x8000bf02, 0x0771: 0x8000c002, 0x0772: 0x8000c102, 0x0773: 0x8000c202,
+ 0x0774: 0x8000c302, 0x0775: 0x8000c402, 0x0776: 0x8000c502, 0x0777: 0x8000c602,
+ 0x0778: 0x8000c702, 0x0779: 0x8000c802, 0x077a: 0x8000c902, 0x077b: 0x8000ca02,
+ 0x077c: 0x8000cb02, 0x077d: 0x8000cc02, 0x077e: 0x8000cd02, 0x077f: 0x8000ce02,
+ // Block 0x1e, offset 0x780
+ 0x0780: 0x80000000, 0x0781: 0x80005f02, 0x0782: 0x80006002, 0x0783: 0x80000000,
+ 0x0784: 0x80000000, 0x0785: 0x80005f02, 0x0786: 0x80006002, 0x0787: 0x80000000,
+ 0x0788: 0x80000000, 0x0789: 0x80000000, 0x078a: 0x80000000,
+ 0x078d: 0x401d0120, 0x078e: 0x401d0720, 0x078f: 0x401d0e20,
+ 0x0790: 0x401c4c20, 0x0791: 0x401c4d20, 0x0792: 0x401c4e20, 0x0793: 0x401c4f20,
+ 0x0794: 0x401c5020, 0x0795: 0x401c5120, 0x0796: 0x401c5220, 0x0797: 0x401c6620,
+ 0x0798: 0x401c6720, 0x0799: 0x401c7820, 0x079a: 0x401c7920, 0x079b: 0x401c8620,
+ 0x079c: 0x401c9020, 0x079d: 0x401ca120, 0x079e: 0x401ca220, 0x079f: 0x401ca320,
+ 0x07a0: 0x401cab20, 0x07a1: 0x401cac20, 0x07a2: 0x401cbf20, 0x07a3: 0x401cc220,
+ 0x07a4: 0x401cc320, 0x07a5: 0x401ccb20, 0x07a6: 0x401ccc20, 0x07a7: 0x401cd320,
+ 0x07a8: 0x401cd420, 0x07a9: 0x401cd520, 0x07aa: 0x401cc920, 0x07ab: 0x401c8720,
+ 0x07ac: 0x401c8820, 0x07ad: 0x401c9120, 0x07ae: 0x401c6820, 0x07af: 0x401c6920,
+ 0x07b0: 0x401c9220, 0x07b1: 0x401c8920, 0x07b2: 0x401c6a20, 0x07b3: 0x401c4320,
+ 0x07b4: 0x401c4420, 0x07b5: 0x401cf320, 0x07b6: 0x401cf420, 0x07b7: 0x401cf520,
+ 0x07b8: 0x401ce620, 0x07b9: 0x401ce720, 0x07ba: 0x401cf720, 0x07bb: 0x401cf820,
+ 0x07bc: 0x401c6b20, 0x07bd: 0x401c9320, 0x07be: 0x401c9420, 0x07bf: 0x401cb620,
+ // Block 0x1f, offset 0x7c0
+ 0x07c0: 0x401d2d20, 0x07c1: 0x401d3020, 0x07c2: 0x401d3120, 0x07c3: 0x401d3220,
+ 0x07c4: 0x401d3420, 0x07c5: 0x401d3520, 0x07c6: 0x401d3620, 0x07c7: 0x401d3720,
+ 0x07c8: 0x401d3a20, 0x07c9: 0x401d3c20, 0x07ca: 0x401d3d20, 0x07cb: 0x401d3e20,
+ 0x07cc: 0x401d4020, 0x07cd: 0x401d4420, 0x07ce: 0x401d4520, 0x07cf: 0x401d4720,
+ 0x07d0: 0x401d4820, 0x07d1: 0x401d4c20, 0x07d2: 0x401d4d20, 0x07d3: 0x401d4e20,
+ 0x07d4: 0x401d4f20, 0x07d5: 0x401d5020, 0x07d6: 0x401d5120, 0x07d7: 0x401d5220,
+ 0x07d8: 0x401d4120, 0x07d9: 0x401d2e20, 0x07da: 0x401d2f20, 0x07db: 0x401d3f20,
+ 0x07dc: 0x401d3320, 0x07dd: 0x401d4920, 0x07de: 0x401d4a20, 0x07df: 0x401d4b20,
+ 0x07e0: 0x401d4220, 0x07e1: 0x401d4320, 0x07e2: 0x401d3820, 0x07e3: 0x401d3920,
+ 0x07e4: 0x401d4620, 0x07e5: 0x401d3b20, 0x07e6: 0x401d5420, 0x07e7: 0x401d5520,
+ 0x07e8: 0x401d5620, 0x07e9: 0x401d5720, 0x07ea: 0x401d5820, 0x07eb: 0x401d5920,
+ 0x07ec: 0x401d5a20, 0x07ed: 0x401d5b20, 0x07ee: 0x401d5c20, 0x07ef: 0x401d5d20,
+ 0x07f0: 0x401d5e20, 0x07f1: 0x401d5320,
+ // Block 0x20, offset 0x800
+ 0x0800: 0xe0000027, 0x0801: 0xe00000a2, 0x0802: 0xe000018c, 0x0803: 0xe0000252,
+ 0x0804: 0xe0000315, 0x0805: 0xe00003cf, 0x0806: 0xe0000486, 0x0807: 0xe0000522,
+ 0x0808: 0xe00005be, 0x0809: 0xe0000657, 0x080a: 0x401d5f20, 0x080b: 0x401d6020,
+ 0x080c: 0x401d6120, 0x080d: 0x401d6220, 0x080e: 0x401d6320, 0x080f: 0x401d6420,
+ 0x0810: 0x401d6520, 0x0811: 0x401d6620, 0x0812: 0x401d6720, 0x0813: 0x401d6820,
+ 0x0814: 0x401d6920, 0x0815: 0x401d6a20, 0x0816: 0x401d6b20, 0x0817: 0x401d6c20,
+ 0x0818: 0x401d6d20, 0x0819: 0x401d6e20, 0x081a: 0x401d6f20, 0x081b: 0x401d7020,
+ 0x081c: 0x401d7120, 0x081d: 0x401d7220, 0x081e: 0x401d7320, 0x081f: 0x401d7420,
+ 0x0820: 0x401d7520, 0x0821: 0x401d7620, 0x0822: 0x401d7720, 0x0823: 0x401d7820,
+ 0x0824: 0x401d7920, 0x0825: 0x401d7a20, 0x0826: 0x401d7b20, 0x0827: 0x401d7c20,
+ 0x0828: 0xe00008df, 0x0829: 0xe00008e2, 0x082a: 0xe00008e5, 0x082b: 0x8000cf02,
+ 0x082c: 0x8000d002, 0x082d: 0x8000d102, 0x082e: 0x8000d202, 0x082f: 0x8000d302,
+ 0x0830: 0x8000d402, 0x0831: 0x8000d502, 0x0832: 0x8000d602, 0x0833: 0x8000d702,
+ 0x0834: 0x401d7d20, 0x0835: 0x401d7e20, 0x0836: 0x40038a20, 0x0837: 0x4001a220,
+ 0x0838: 0x40012520, 0x0839: 0x40015b20, 0x083a: 0x80000000,
+ // Block 0x21, offset 0x840
+ 0x0840: 0x401c2120, 0x0841: 0x401c2220, 0x0842: 0x401c2320, 0x0843: 0x401c2420,
+ 0x0844: 0x401c2520, 0x0845: 0x401c2620, 0x0846: 0x401c2720, 0x0847: 0x401c2820,
+ 0x0848: 0x401c2920, 0x0849: 0x401c2a20, 0x084a: 0x401c2b20, 0x084b: 0x401c2c20,
+ 0x084c: 0x401c2d20, 0x084d: 0x401c2e20, 0x084e: 0x401c2f20, 0x084f: 0x401c3020,
+ 0x0850: 0x401c3120, 0x0851: 0x401c3220, 0x0852: 0x401c3320, 0x0853: 0x401c3420,
+ 0x0854: 0x401c3520, 0x0855: 0x401c3620, 0x0856: 0x401c3720, 0x0857: 0x401c3820,
+ 0x0858: 0x80009f02, 0x0859: 0x8000a002, 0x085a: 0x401c3920, 0x085b: 0x401c3a20,
+ 0x085c: 0x80009702, 0x085d: 0x80009702, 0x085e: 0x80009802, 0x085f: 0x80009802,
+ 0x0860: 0x80009802, 0x0861: 0x80009902, 0x0862: 0x80009902, 0x0863: 0x80009902,
+ 0x0864: 0x80009a02, 0x0865: 0x80009a02, 0x0866: 0x80009b02, 0x0867: 0x80009b02,
+ 0x0868: 0x80009c02, 0x0869: 0x80009c02, 0x086a: 0x80009c02, 0x086b: 0x80009d02,
+ 0x086c: 0x80009e02, 0x086d: 0x8000a102,
+ 0x0870: 0x40013b20, 0x0871: 0x40013c20, 0x0872: 0x40013d20, 0x0873: 0x40013e20,
+ 0x0874: 0x40013f20, 0x0875: 0x40014020, 0x0876: 0x40014120, 0x0877: 0x40014220,
+ 0x0878: 0x40014320, 0x0879: 0x40014420, 0x087a: 0x40014520, 0x087b: 0x40014620,
+ 0x087c: 0x40014720, 0x087d: 0x40014820, 0x087e: 0x40014920,
+ // Block 0x22, offset 0x880
+ 0x0880: 0x401d1420, 0x0881: 0x401d1520, 0x0882: 0x401d1620, 0x0883: 0x401d1720,
+ 0x0884: 0x401d1820, 0x0885: 0x401d1920, 0x0886: 0x401d1a20, 0x0887: 0x401d1b20,
+ 0x0888: 0x401d1c20, 0x0889: 0x401d1d20, 0x088a: 0x401d1e20, 0x088b: 0x401d1f20,
+ 0x088c: 0x401d2020, 0x088d: 0x401d2120, 0x088e: 0x401d2220, 0x088f: 0x401d2320,
+ 0x0890: 0x401d2420, 0x0891: 0x401d2520, 0x0892: 0x401d2620, 0x0893: 0x401d2720,
+ 0x0894: 0x401d2820, 0x0895: 0x401d2920, 0x0896: 0x401d2a20, 0x0897: 0x401d2b20,
+ 0x0898: 0x401d2c20, 0x0899: 0x80006002, 0x089a: 0x80006002, 0x089b: 0x80006002,
+ 0x089e: 0x40028220,
+ // Block 0x23, offset 0x8c0
+ 0x08c0: 0x8000de02, 0x08c1: 0x8000de02, 0x08c2: 0x8000df02, 0x08c3: 0x8000e002,
+ 0x08c4: 0x401f7d20, 0x08c5: 0x401f7e20, 0x08c6: 0x401f7f20, 0x08c7: 0x401f8520,
+ 0x08c8: 0x401f8620, 0x08c9: 0x401f8720, 0x08ca: 0x401f8820, 0x08cb: 0x401f8920,
+ 0x08cc: 0x401f8b20, 0x08cd: 0x401f8d20, 0x08ce: 0x401f8e20, 0x08cf: 0x401f8f20,
+ 0x08d0: 0x401f9020, 0x08d1: 0x401f9120, 0x08d2: 0x401f9220, 0x08d3: 0x401f9320,
+ 0x08d4: 0x401f9420, 0x08d5: 0x401f9520, 0x08d6: 0x401f9620, 0x08d7: 0x401f9720,
+ 0x08d8: 0x401f9920, 0x08d9: 0x401f9a20, 0x08da: 0x401f9b20, 0x08db: 0x401f9c20,
+ 0x08dc: 0x401f9d20, 0x08dd: 0x401fa020, 0x08de: 0x401fa120, 0x08df: 0x401fa220,
+ 0x08e0: 0x401fa320, 0x08e1: 0x401fa420, 0x08e2: 0x401fa620, 0x08e3: 0x401fa720,
+ 0x08e4: 0x401fa820, 0x08e5: 0x401fa920, 0x08e6: 0x401faa20, 0x08e7: 0x401fab20,
+ 0x08e8: 0x401fac20, 0x08ea: 0x401fad20, 0x08eb: 0x401fae20,
+ 0x08ec: 0x401faf20, 0x08ed: 0x401fb120, 0x08ee: 0x401fb220, 0x08ef: 0x401fb320,
+ 0x08f0: 0x401fb520, 0x08f2: 0x401fb620, 0x08f3: 0x401fb720,
+ 0x08f5: 0x401fb820, 0x08f6: 0x401fb920, 0x08f7: 0x401fba20,
+ 0x08f8: 0x401fbb20, 0x08f9: 0x401fbc20, 0x08fa: 0x401fc320, 0x08fb: 0x401fc420,
+ 0x08fc: 0x8000dd02, 0x08fd: 0x401fbd20, 0x08fe: 0x401fc220, 0x08ff: 0x401fc820,
+ // Block 0x24, offset 0x900
+ 0x0900: 0x401fc920, 0x0901: 0x401fca20, 0x0902: 0x401fcb20, 0x0903: 0x401fcc20,
+ 0x0904: 0x401fcd20, 0x0905: 0x401fd020, 0x0906: 0x401fd220, 0x0907: 0x401fd320,
+ 0x0908: 0x401fd520, 0x0909: 0x401fd620, 0x090a: 0x401fd720, 0x090b: 0x401fd820,
+ 0x090c: 0x401fd920, 0x090d: 0x401fda20, 0x090e: 0x401fd420, 0x090f: 0x401fc520,
+ 0x0910: 0x401f7b20, 0x0911: 0x80000000, 0x0912: 0x80000000, 0x0913: 0x80003502,
+ 0x0914: 0x80003202, 0x0915: 0x401fd120, 0x0916: 0x401fc620, 0x0917: 0x401fc720,
+ 0x0920: 0x401f8a20, 0x0921: 0x401f8c20, 0x0922: 0x401fce20, 0x0923: 0x401fcf20,
+ 0x0924: 0x40017e20, 0x0925: 0x40017f20, 0x0926: 0xe000002d, 0x0927: 0xe00000ab,
+ 0x0928: 0xe0000195, 0x0929: 0xe000025b, 0x092a: 0xe000031e, 0x092b: 0xe00003d8,
+ 0x092c: 0xe000048f, 0x092d: 0xe000052b, 0x092e: 0xe00005c7, 0x092f: 0xe0000660,
+ 0x0930: 0x40028420, 0x0931: 0x40139420, 0x0932: 0x401f7c20, 0x0933: 0x401f8020,
+ 0x0934: 0x401f8120, 0x0935: 0x401f8220, 0x0936: 0x401f8320, 0x0937: 0x401f8420,
+ 0x0939: 0x401f9e20, 0x093a: 0x401fb420, 0x093b: 0x401f9820,
+ 0x093c: 0x401f9f20, 0x093d: 0x401fbe20, 0x093e: 0x401fa520, 0x093f: 0x401fb020,
+ // Block 0x25, offset 0x940
+ 0x0941: 0x8000e202, 0x0942: 0x8000e302, 0x0943: 0x8000e402,
+ 0x0945: 0x401fdb20, 0x0946: 0x401fdc20, 0x0947: 0x401fdd20,
+ 0x0948: 0x401fde20, 0x0949: 0x401fdf20, 0x094a: 0x401fe020, 0x094b: 0x401fe120,
+ 0x094c: 0x401fe320, 0x094f: 0x401fe520,
+ 0x0950: 0x401fe620, 0x0953: 0x401fe720,
+ 0x0954: 0x401fe820, 0x0955: 0x401fe920, 0x0956: 0x401fea20, 0x0957: 0x401feb20,
+ 0x0958: 0x401fec20, 0x0959: 0x401fed20, 0x095a: 0x401fee20, 0x095b: 0x401fef20,
+ 0x095c: 0x401ff020, 0x095d: 0x401ff120, 0x095e: 0x401ff220, 0x095f: 0x401ff320,
+ 0x0960: 0x401ff420, 0x0961: 0x401ff520, 0x0962: 0x401ff620, 0x0963: 0x401ff720,
+ 0x0964: 0x401ff820, 0x0965: 0x401ff920, 0x0966: 0x401ffa20, 0x0967: 0x401ffb20,
+ 0x0968: 0x401ffc20, 0x096a: 0x401ffd20, 0x096b: 0x401ffe20,
+ 0x096c: 0x401fff20, 0x096d: 0x40200020, 0x096e: 0x40200120, 0x096f: 0x40200220,
+ 0x0970: 0x40200320, 0x0972: 0x40200520,
+ 0x0976: 0x40200720, 0x0977: 0x40200820,
+ 0x0978: 0x40200920, 0x0979: 0x40200a20,
+ 0x097c: 0x8000e102, 0x097d: 0x40200b20, 0x097e: 0x40200c20, 0x097f: 0x40200d20,
+ // Block 0x26, offset 0x980
+ 0x0980: 0x40200e20, 0x0981: 0x40200f20, 0x0982: 0x40201020, 0x0983: 0x40201120,
+ 0x0984: 0x40201220, 0x0987: 0xc05a0191,
+ 0x0988: 0x40201620, 0x098b: 0x40201720,
+ 0x098c: 0x40201820, 0x098d: 0x40201920, 0x098e: 0xe00008e8,
+ 0x0997: 0x40201a20,
+ 0x09a0: 0x401fe220, 0x09a1: 0x401fe420, 0x09a2: 0x40201320, 0x09a3: 0x40201420,
+ 0x09a6: 0xe0000030, 0x09a7: 0xe00000ae,
+ 0x09a8: 0xe0000198, 0x09a9: 0xe000025e, 0x09aa: 0xe0000321, 0x09ab: 0xe00003db,
+ 0x09ac: 0xe0000492, 0x09ad: 0xe000052e, 0x09ae: 0xe00005ca, 0x09af: 0xe0000663,
+ 0x09b0: 0x40200420, 0x09b1: 0x40200620, 0x09b2: 0x4013a920, 0x09b3: 0x4013aa20,
+ 0x09b4: 0x4013cc20, 0x09b5: 0x4013cd20, 0x09b6: 0x4013ce20, 0x09b7: 0x4013cf20,
+ 0x09b8: 0x4013d020, 0x09b9: 0x4013d120, 0x09ba: 0x40038b20, 0x09bb: 0x4013ab20,
+ // Block 0x27, offset 0x9c0
+ 0x09c1: 0x8000e602, 0x09c2: 0x8000e702, 0x09c3: 0x8000e802,
+ 0x09c5: 0x40202020, 0x09c6: 0x40202120, 0x09c7: 0x40202520,
+ 0x09c8: 0x40202620, 0x09c9: 0x40201d20, 0x09ca: 0x40201e20,
+ 0x09cf: 0x40202720,
+ 0x09d0: 0x40202220, 0x09d3: 0x40201f20,
+ 0x09d4: 0x40202320, 0x09d5: 0x40202b20, 0x09d6: 0x40202c20, 0x09d7: 0x40202d20,
+ 0x09d8: 0x40202e20, 0x09d9: 0x40202f20, 0x09da: 0x40203020, 0x09db: 0x40203120,
+ 0x09dc: 0x40203220, 0x09dd: 0x40203320, 0x09de: 0x40203420, 0x09df: 0x40203520,
+ 0x09e0: 0x40203620, 0x09e1: 0x40203720, 0x09e2: 0x40203820, 0x09e3: 0x40203920,
+ 0x09e4: 0x40203a20, 0x09e5: 0x40203b20, 0x09e6: 0x40203c20, 0x09e7: 0x40203d20,
+ 0x09e8: 0x40203e20, 0x09ea: 0x40203f20, 0x09eb: 0x40204020,
+ 0x09ec: 0x40204120, 0x09ed: 0x40204220, 0x09ee: 0x40204320, 0x09ef: 0x40204420,
+ 0x09f0: 0x40204620, 0x09f2: 0x40204720,
+ 0x09f5: 0x40204820,
+ 0x09f8: 0x40202820, 0x09f9: 0x40202920,
+ 0x09fc: 0x8000e502, 0x09fe: 0x40204a20, 0x09ff: 0x40204b20,
+ // Block 0x28, offset 0xa00
+ 0x0a00: 0x40204c20, 0x0a01: 0x40204d20, 0x0a02: 0x40204e20,
+ 0x0a07: 0x40204f20,
+ 0x0a08: 0x40205020, 0x0a0b: 0x40205120,
+ 0x0a0c: 0x40205220, 0x0a0d: 0x40205320,
+ 0x0a11: 0x40202a20,
+ 0x0a1c: 0x40204920,
+ 0x0a26: 0xe0000033, 0x0a27: 0xe00000b1,
+ 0x0a28: 0xe000019b, 0x0a29: 0xe0000261, 0x0a2a: 0xe0000324, 0x0a2b: 0xe00003de,
+ 0x0a2c: 0xe0000495, 0x0a2d: 0xe0000531, 0x0a2e: 0xe00005cd, 0x0a2f: 0xe0000666,
+ 0x0a30: 0x8000e902, 0x0a31: 0x8000ea02, 0x0a32: 0x40202420, 0x0a33: 0x40201c20,
+ 0x0a34: 0x40201b20, 0x0a35: 0x40204520,
+ // Block 0x29, offset 0xa40
+ 0x0a41: 0x8000ec02, 0x0a42: 0x8000ed02, 0x0a43: 0x8000ee02,
+ 0x0a45: 0x40205520, 0x0a46: 0x40205620, 0x0a47: 0x40205720,
+ 0x0a48: 0x40205820, 0x0a49: 0x40205920, 0x0a4a: 0x40205a20, 0x0a4b: 0x40205b20,
+ 0x0a4c: 0x40205d20, 0x0a4d: 0x40205f20, 0x0a4f: 0x40206020,
+ 0x0a50: 0x40206120, 0x0a51: 0x40206220, 0x0a53: 0x40206320,
+ 0x0a54: 0x40206420, 0x0a55: 0x40206520, 0x0a56: 0x40206620, 0x0a57: 0x40206720,
+ 0x0a58: 0x40206820, 0x0a59: 0x40206920, 0x0a5a: 0x40206a20, 0x0a5b: 0x40206b20,
+ 0x0a5c: 0x40206c20, 0x0a5d: 0x40206d20, 0x0a5e: 0x40206e20, 0x0a5f: 0x40206f20,
+ 0x0a60: 0x40207020, 0x0a61: 0x40207120, 0x0a62: 0x40207220, 0x0a63: 0x40207320,
+ 0x0a64: 0x40207420, 0x0a65: 0x40207520, 0x0a66: 0x40207620, 0x0a67: 0x40207720,
+ 0x0a68: 0x40207820, 0x0a6a: 0x40207920, 0x0a6b: 0x40207a20,
+ 0x0a6c: 0x40207b20, 0x0a6d: 0x40207c20, 0x0a6e: 0x40207d20, 0x0a6f: 0x40207e20,
+ 0x0a70: 0x40207f20, 0x0a72: 0x40208020, 0x0a73: 0x40208620,
+ 0x0a75: 0x40208120, 0x0a76: 0x40208220, 0x0a77: 0x40208320,
+ 0x0a78: 0x40208420, 0x0a79: 0x40208520,
+ 0x0a7c: 0x8000eb02, 0x0a7d: 0x40208720, 0x0a7e: 0x40208820, 0x0a7f: 0x40208920,
+ // Block 0x2a, offset 0xa80
+ 0x0a80: 0x40208a20, 0x0a81: 0x40208b20, 0x0a82: 0x40208c20, 0x0a83: 0x40208d20,
+ 0x0a84: 0x40208e20, 0x0a85: 0x40209120, 0x0a87: 0x40209220,
+ 0x0a88: 0x40209320, 0x0a89: 0x40209420, 0x0a8b: 0x40209520,
+ 0x0a8c: 0x40209620, 0x0a8d: 0x40209720,
+ 0x0a90: 0x40205420,
+ 0x0aa0: 0x40205c20, 0x0aa1: 0x40205e20, 0x0aa2: 0x40208f20, 0x0aa3: 0x40209020,
+ 0x0aa6: 0xe0000036, 0x0aa7: 0xe00000b4,
+ 0x0aa8: 0xe000019e, 0x0aa9: 0xe0000264, 0x0aaa: 0xe0000327, 0x0aab: 0xe00003e1,
+ 0x0aac: 0xe0000498, 0x0aad: 0xe0000534, 0x0aae: 0xe00005d0, 0x0aaf: 0xe0000669,
+ 0x0ab1: 0x4013ac20,
+ // Block 0x2b, offset 0xac0
+ 0x0ac1: 0x8000f002, 0x0ac2: 0x8000f102, 0x0ac3: 0x8000f202,
+ 0x0ac5: 0x40209820, 0x0ac6: 0x40209920, 0x0ac7: 0x40209a20,
+ 0x0ac8: 0x40209b20, 0x0ac9: 0x40209c20, 0x0aca: 0x40209d20, 0x0acb: 0x40209e20,
+ 0x0acc: 0x4020a020, 0x0acf: 0x4020a220,
+ 0x0ad0: 0x4020a320, 0x0ad3: 0x4020a420,
+ 0x0ad4: 0x4020a520, 0x0ad5: 0x4020a620, 0x0ad6: 0x4020a720, 0x0ad7: 0x4020a820,
+ 0x0ad8: 0x4020a920, 0x0ad9: 0x4020aa20, 0x0ada: 0x4020ab20, 0x0adb: 0x4020ac20,
+ 0x0adc: 0x4020ad20, 0x0add: 0x4020ae20, 0x0ade: 0x4020af20, 0x0adf: 0x4020b020,
+ 0x0ae0: 0x4020b120, 0x0ae1: 0x4020b220, 0x0ae2: 0x4020b320, 0x0ae3: 0x4020b420,
+ 0x0ae4: 0x4020b520, 0x0ae5: 0x4020b620, 0x0ae6: 0x4020b720, 0x0ae7: 0x4020b820,
+ 0x0ae8: 0x4020b920, 0x0aea: 0x4020ba20, 0x0aeb: 0x4020bb20,
+ 0x0aec: 0x4020bc20, 0x0aed: 0x4020bd20, 0x0aee: 0x4020be20, 0x0aef: 0x4020bf20,
+ 0x0af0: 0x4020c120, 0x0af2: 0x4020c220, 0x0af3: 0x4020c320,
+ 0x0af5: 0x4020c420, 0x0af6: 0x4020c620, 0x0af7: 0x4020c720,
+ 0x0af8: 0x4020c820, 0x0af9: 0x4020c920,
+ 0x0afc: 0x8000ef02, 0x0afd: 0x4020ca20, 0x0afe: 0x4020cb20, 0x0aff: 0x4020cc20,
+ // Block 0x2c, offset 0xb00
+ 0x0b00: 0x4020cd20, 0x0b01: 0x4020ce20, 0x0b02: 0x4020cf20, 0x0b03: 0x4020d020,
+ 0x0b04: 0x4020d120, 0x0b07: 0xc05d01e1,
+ 0x0b08: 0x4020d520, 0x0b0b: 0x4020d620,
+ 0x0b0c: 0x4020d720, 0x0b0d: 0x4020d820,
+ 0x0b16: 0x4020d920, 0x0b17: 0x4020da20,
+ 0x0b1f: 0x4020c020,
+ 0x0b20: 0x40209f20, 0x0b21: 0x4020a120, 0x0b22: 0x4020d220, 0x0b23: 0x4020d320,
+ 0x0b26: 0xe0000039, 0x0b27: 0xe00000b7,
+ 0x0b28: 0xe00001a1, 0x0b29: 0xe0000267, 0x0b2a: 0xe000032a, 0x0b2b: 0xe00003e4,
+ 0x0b2c: 0xe000049b, 0x0b2d: 0xe0000537, 0x0b2e: 0xe00005d3, 0x0b2f: 0xe000066c,
+ 0x0b30: 0x40038c20, 0x0b31: 0x4020c520, 0x0b32: 0x4013d220, 0x0b33: 0x4013d320,
+ 0x0b34: 0x4013d420, 0x0b35: 0x4013d520, 0x0b36: 0x4013d620, 0x0b37: 0x4013d720,
+ // Block 0x2d, offset 0xb40
+ 0x0b42: 0x8000f302, 0x0b43: 0x4020e820,
+ 0x0b45: 0x4020dc20, 0x0b46: 0x4020dd20, 0x0b47: 0x4020de20,
+ 0x0b48: 0x4020df20, 0x0b49: 0x4020e020, 0x0b4a: 0x4020e120,
+ 0x0b4e: 0x4020e220, 0x0b4f: 0x4020e320,
+ 0x0b50: 0x4020e420, 0x0b52: 0xc0610231, 0x0b53: 0x4020e620,
+ 0x0b54: 0x4020e720, 0x0b55: 0x4020e920,
+ 0x0b59: 0x4020ea20, 0x0b5a: 0x4020eb20,
+ 0x0b5c: 0x4020fb20, 0x0b5e: 0x4020ec20, 0x0b5f: 0x4020ed20,
+ 0x0b63: 0x4020ee20,
+ 0x0b64: 0x4020ef20,
+ 0x0b68: 0x4020f020, 0x0b69: 0x4020fa20, 0x0b6a: 0x4020f120,
+ 0x0b6e: 0x4020f220, 0x0b6f: 0x4020f320,
+ 0x0b70: 0x4020f420, 0x0b71: 0x4020f920, 0x0b72: 0x4020f520, 0x0b73: 0x4020f820,
+ 0x0b74: 0x4020f720, 0x0b75: 0x4020f620, 0x0b76: 0x4020fc20, 0x0b77: 0x4020fd20,
+ 0x0b78: 0x4020fe20, 0x0b79: 0x4020ff20,
+ 0x0b7e: 0x40210020, 0x0b7f: 0x40210120,
+ // Block 0x2e, offset 0xb80
+ 0x0b80: 0x40210220, 0x0b81: 0x40210320, 0x0b82: 0x40210420,
+ 0x0b86: 0xc0630261, 0x0b87: 0xc06602b1,
+ 0x0b88: 0x40210720, 0x0b8a: 0x40210820, 0x0b8b: 0x40210920,
+ 0x0b8c: 0x40210a20, 0x0b8d: 0x40210b20,
+ 0x0b90: 0x4020db20,
+ 0x0b97: 0x40210c20,
+ 0x0ba6: 0xe000003c, 0x0ba7: 0xe00000ba,
+ 0x0ba8: 0xe00001a4, 0x0ba9: 0xe000026a, 0x0baa: 0xe000032d, 0x0bab: 0xe00003e7,
+ 0x0bac: 0xe000049e, 0x0bad: 0xe000053a, 0x0bae: 0xe00005d6, 0x0baf: 0xe000066f,
+ 0x0bb0: 0x4013de20, 0x0bb1: 0x4013df20, 0x0bb2: 0x4013e020, 0x0bb3: 0x40038d20,
+ 0x0bb4: 0x40038e20, 0x0bb5: 0x40038f20, 0x0bb6: 0x40039020, 0x0bb7: 0x40039120,
+ 0x0bb8: 0x40039220, 0x0bb9: 0x4013ae20, 0x0bba: 0x40039320,
+ // Block 0x2f, offset 0xbc0
+ 0x0bc1: 0x8000f402, 0x0bc2: 0x8000f502, 0x0bc3: 0x8000f602,
+ 0x0bc5: 0x40210d20, 0x0bc6: 0x40210e20, 0x0bc7: 0x40210f20,
+ 0x0bc8: 0x40211020, 0x0bc9: 0x40211120, 0x0bca: 0x40211220, 0x0bcb: 0x40211320,
+ 0x0bcc: 0x40211520, 0x0bce: 0x40211720, 0x0bcf: 0x40211820,
+ 0x0bd0: 0x40211920, 0x0bd2: 0x40211a20, 0x0bd3: 0x40211b20,
+ 0x0bd4: 0x40211c20, 0x0bd5: 0x40211d20, 0x0bd6: 0x40211e20, 0x0bd7: 0x40211f20,
+ 0x0bd8: 0x40212020, 0x0bd9: 0x40212120, 0x0bda: 0x40212220, 0x0bdb: 0x40212420,
+ 0x0bdc: 0x40212520, 0x0bdd: 0x40212720, 0x0bde: 0x40212820, 0x0bdf: 0x40212920,
+ 0x0be0: 0x40212a20, 0x0be1: 0x40212b20, 0x0be2: 0x40212c20, 0x0be3: 0x40212d20,
+ 0x0be4: 0x40212e20, 0x0be5: 0x40212f20, 0x0be6: 0x40213020, 0x0be7: 0x40213120,
+ 0x0be8: 0x40213220, 0x0bea: 0x40213320, 0x0beb: 0x40213420,
+ 0x0bec: 0x40213520, 0x0bed: 0x40213620, 0x0bee: 0x40213720, 0x0bef: 0x40213820,
+ 0x0bf0: 0x40213920, 0x0bf1: 0x40213a20, 0x0bf2: 0x40213b20, 0x0bf3: 0x40214120,
+ 0x0bf5: 0x40213c20, 0x0bf6: 0x40213d20, 0x0bf7: 0x40213e20,
+ 0x0bf8: 0x40213f20, 0x0bf9: 0x40214020,
+ 0x0bfd: 0x40214220, 0x0bfe: 0x40214320, 0x0bff: 0x40214420,
+ // Block 0x30, offset 0xc00
+ 0x0c00: 0x40214520, 0x0c01: 0x40214620, 0x0c02: 0x40214720, 0x0c03: 0x40214820,
+ 0x0c04: 0x40214920, 0x0c06: 0xc06802e1, 0x0c07: 0x40214d20,
+ 0x0c08: 0x40214e20, 0x0c0a: 0x40214f20, 0x0c0b: 0x40215020,
+ 0x0c0c: 0x40215120, 0x0c0d: 0x40215220,
+ 0x0c15: 0x40215320, 0x0c16: 0x40215420,
+ 0x0c18: 0x40212320, 0x0c19: 0x40212620,
+ 0x0c20: 0x40211420, 0x0c21: 0x40211620, 0x0c22: 0x40214a20, 0x0c23: 0x40214b20,
+ 0x0c26: 0xe000003f, 0x0c27: 0xe00000bd,
+ 0x0c28: 0xe00001a7, 0x0c29: 0xe000026d, 0x0c2a: 0xe0000330, 0x0c2b: 0xe00003ea,
+ 0x0c2c: 0xe00004a1, 0x0c2d: 0xe000053d, 0x0c2e: 0xe00005d9, 0x0c2f: 0xe0000672,
+ 0x0c38: 0xe0000042, 0x0c39: 0xe00000c0, 0x0c3a: 0xe00001aa, 0x0c3b: 0xe0000270,
+ 0x0c3c: 0xe00000c3, 0x0c3d: 0xe00001ad, 0x0c3e: 0xe0000273, 0x0c3f: 0x40039420,
+ // Block 0x31, offset 0xc40
+ 0x0c42: 0x8000f802, 0x0c43: 0x8000f902,
+ 0x0c45: 0x40215520, 0x0c46: 0x40215620, 0x0c47: 0x40215720,
+ 0x0c48: 0x40215820, 0x0c49: 0x40215920, 0x0c4a: 0x40215a20, 0x0c4b: 0x40215b20,
+ 0x0c4c: 0x40215d20, 0x0c4e: 0x40215f20, 0x0c4f: 0x40216020,
+ 0x0c50: 0x40216120, 0x0c52: 0x40216220, 0x0c53: 0x40216320,
+ 0x0c54: 0x40216420, 0x0c55: 0x40216520, 0x0c56: 0x40216620, 0x0c57: 0x40216720,
+ 0x0c58: 0x40216820, 0x0c59: 0x40216920, 0x0c5a: 0x40216a20, 0x0c5b: 0x40216b20,
+ 0x0c5c: 0x40216c20, 0x0c5d: 0x40216d20, 0x0c5e: 0x40216e20, 0x0c5f: 0x40216f20,
+ 0x0c60: 0x40217020, 0x0c61: 0x40217120, 0x0c62: 0x40217220, 0x0c63: 0x40217320,
+ 0x0c64: 0x40217420, 0x0c65: 0x40217520, 0x0c66: 0x40217620, 0x0c67: 0x40217720,
+ 0x0c68: 0x40217820, 0x0c6a: 0x40217920, 0x0c6b: 0x40217a20,
+ 0x0c6c: 0x40217b20, 0x0c6d: 0x40217c20, 0x0c6e: 0x40217d20, 0x0c6f: 0x40217e20,
+ 0x0c70: 0x40217f20, 0x0c71: 0x40218020, 0x0c72: 0x40218120, 0x0c73: 0x40218720,
+ 0x0c75: 0x40218220, 0x0c76: 0x40218320, 0x0c77: 0x40218420,
+ 0x0c78: 0x40218520, 0x0c79: 0x40218620,
+ 0x0c7c: 0x8000f702, 0x0c7d: 0x40218920, 0x0c7e: 0x40218c20, 0x0c7f: 0xc06a0311,
+ // Block 0x32, offset 0xc80
+ 0x0c80: 0x40218e20, 0x0c81: 0x40218f20, 0x0c82: 0x40219020, 0x0c83: 0x40219120,
+ 0x0c84: 0x40219220, 0x0c86: 0xc06c0341, 0x0c87: 0x40219620,
+ 0x0c88: 0x40219720, 0x0c8a: 0xc0710311, 0x0c8b: 0x40219920,
+ 0x0c8c: 0x40219a20, 0x0c8d: 0x40219b20,
+ 0x0c95: 0x40219c20, 0x0c96: 0x40219d20,
+ 0x0c9e: 0x40218820,
+ 0x0ca0: 0x40215c20, 0x0ca1: 0x40215e20, 0x0ca2: 0x40219320, 0x0ca3: 0x40219420,
+ 0x0ca6: 0xe0000045, 0x0ca7: 0xe00000c6,
+ 0x0ca8: 0xe00001b0, 0x0ca9: 0xe0000276, 0x0caa: 0xe0000333, 0x0cab: 0xe00003ed,
+ 0x0cac: 0xe00004a4, 0x0cad: 0xe0000540, 0x0cae: 0xe00005dc, 0x0caf: 0xe0000675,
+ 0x0cb1: 0x40218a20, 0x0cb2: 0x40218b20,
+ // Block 0x33, offset 0xcc0
+ 0x0cc2: 0x8000fa02, 0x0cc3: 0x8000fb02,
+ 0x0cc5: 0x40219e20, 0x0cc6: 0x40219f20, 0x0cc7: 0x4021a020,
+ 0x0cc8: 0x4021a120, 0x0cc9: 0x4021a220, 0x0cca: 0x4021a320, 0x0ccb: 0x4021a420,
+ 0x0ccc: 0x4021a620, 0x0cce: 0x4021a820, 0x0ccf: 0x4021a920,
+ 0x0cd0: 0x4021aa20, 0x0cd2: 0x4021ab20, 0x0cd3: 0x4021ac20,
+ 0x0cd4: 0x4021ad20, 0x0cd5: 0x4021ae20, 0x0cd6: 0x4021af20, 0x0cd7: 0x4021b020,
+ 0x0cd8: 0x4021b120, 0x0cd9: 0x4021b220, 0x0cda: 0x4021b320, 0x0cdb: 0x4021b420,
+ 0x0cdc: 0x4021b520, 0x0cdd: 0x4021b620, 0x0cde: 0x4021b720, 0x0cdf: 0x4021b820,
+ 0x0ce0: 0x4021b920, 0x0ce1: 0x4021ba20, 0x0ce2: 0x4021bb20, 0x0ce3: 0x4021bc20,
+ 0x0ce4: 0x4021bd20, 0x0ce5: 0x4021be20, 0x0ce6: 0x4021bf20, 0x0ce7: 0x4021c020,
+ 0x0ce8: 0x4021c120, 0x0ce9: 0x4021c220, 0x0cea: 0x4021c320, 0x0ceb: 0x4021c420,
+ 0x0cec: 0x4021c520, 0x0ced: 0x4021c620, 0x0cee: 0x4021c720, 0x0cef: 0x4021c820,
+ 0x0cf0: 0x4021c920, 0x0cf1: 0x4021d220, 0x0cf2: 0x4021ca20, 0x0cf3: 0x4021d020,
+ 0x0cf4: 0x4021d120, 0x0cf5: 0x4021cb20, 0x0cf6: 0x4021cc20, 0x0cf7: 0x4021cd20,
+ 0x0cf8: 0x4021ce20, 0x0cf9: 0x4021cf20, 0x0cfa: 0x4021d320,
+ 0x0cfd: 0x4021d420, 0x0cfe: 0x4021d520, 0x0cff: 0x4021d620,
+ // Block 0x34, offset 0xd00
+ 0x0d00: 0x4021d720, 0x0d01: 0x4021d820, 0x0d02: 0x4021d920, 0x0d03: 0x4021da20,
+ 0x0d04: 0x4021db20, 0x0d06: 0xc07303b1, 0x0d07: 0xc0760401,
+ 0x0d08: 0x4021e020, 0x0d0a: 0x4021e120, 0x0d0b: 0x4021e220,
+ 0x0d0c: 0x4021e320, 0x0d0d: 0x4021e520, 0x0d0e: 0xe00008f4,
+ 0x0d17: 0x4021e420,
+ 0x0d20: 0x4021a520, 0x0d21: 0x4021a720, 0x0d22: 0x4021dc20, 0x0d23: 0x4021dd20,
+ 0x0d26: 0xe0000048, 0x0d27: 0xe00000c9,
+ 0x0d28: 0xe00001b3, 0x0d29: 0xe0000279, 0x0d2a: 0xe0000336, 0x0d2b: 0xe00003f0,
+ 0x0d2c: 0xe00004a7, 0x0d2d: 0xe0000543, 0x0d2e: 0xe00005df, 0x0d2f: 0xe0000678,
+ 0x0d30: 0x4013e120, 0x0d31: 0x4013e220, 0x0d32: 0x4013e320, 0x0d33: 0x4013e420,
+ 0x0d34: 0x4013e520, 0x0d35: 0x4013e620,
+ 0x0d39: 0x40039520, 0x0d3a: 0xe00008ee, 0x0d3b: 0xe00008f1,
+ 0x0d3c: 0xe00008f7, 0x0d3d: 0xe00008fa, 0x0d3e: 0xe00008fd, 0x0d3f: 0xe00008eb,
+ // Block 0x35, offset 0xd40
+ 0x0d42: 0x8000fc02, 0x0d43: 0x8000fd02,
+ 0x0d45: 0x4021e620, 0x0d46: 0x4021e720, 0x0d47: 0x4021e820,
+ 0x0d48: 0x4021e920, 0x0d49: 0x4021ea20, 0x0d4a: 0x4021eb20, 0x0d4b: 0x4021ec20,
+ 0x0d4c: 0x4021ed20, 0x0d4d: 0x4021ee20, 0x0d4e: 0x4021ef20, 0x0d4f: 0x4021f020,
+ 0x0d50: 0x4021f120, 0x0d51: 0x4021f220, 0x0d52: 0x4021f320, 0x0d53: 0x4021f420,
+ 0x0d54: 0x4021f520, 0x0d55: 0x4021f620, 0x0d56: 0x4021f720,
+ 0x0d5a: 0x4021f820, 0x0d5b: 0x4021f920,
+ 0x0d5c: 0x4021fa20, 0x0d5d: 0x4021fb20, 0x0d5e: 0x4021fc20, 0x0d5f: 0x4021fd20,
+ 0x0d60: 0x4021fe20, 0x0d61: 0x4021ff20, 0x0d62: 0x40220020, 0x0d63: 0x40220120,
+ 0x0d64: 0x40220220, 0x0d65: 0x40220320, 0x0d66: 0x40220420, 0x0d67: 0x40220520,
+ 0x0d68: 0x40220620, 0x0d69: 0x40220720, 0x0d6a: 0x40220820, 0x0d6b: 0x40220920,
+ 0x0d6c: 0x40220a20, 0x0d6d: 0x40220b20, 0x0d6e: 0x40220c20, 0x0d6f: 0x40220d20,
+ 0x0d70: 0x40220e20, 0x0d71: 0x40220f20, 0x0d73: 0x40221020,
+ 0x0d74: 0x40221120, 0x0d75: 0x40221220, 0x0d76: 0x40221320, 0x0d77: 0x40221420,
+ 0x0d78: 0x40221520, 0x0d79: 0x40221620, 0x0d7a: 0x40221720, 0x0d7b: 0x40221820,
+ 0x0d7d: 0x40221920,
+ // Block 0x36, offset 0xd80
+ 0x0d80: 0x40221a20, 0x0d81: 0x40221b20, 0x0d82: 0x40221c20, 0x0d83: 0x40221d20,
+ 0x0d84: 0x40221e20, 0x0d85: 0x40221f20, 0x0d86: 0x40222020,
+ 0x0d8a: 0x40223220,
+ 0x0d8f: 0x40222120,
+ 0x0d90: 0x40222220, 0x0d91: 0x40222320, 0x0d92: 0x40222420, 0x0d93: 0x40222520,
+ 0x0d94: 0x40222620, 0x0d96: 0x40222720,
+ 0x0d98: 0x40222820, 0x0d99: 0xc0780431, 0x0d9a: 0x40222d20, 0x0d9b: 0x40222e20,
+ 0x0d9c: 0xc07d04b1, 0x0d9d: 0x40223020, 0x0d9e: 0x40223120, 0x0d9f: 0x40222a20,
+ 0x0db2: 0x40222920, 0x0db3: 0x40222b20,
+ 0x0db4: 0x40028820,
+ // Block 0x37, offset 0xdc0
+ 0x0dc1: 0x40239520, 0x0dc2: 0x40239620, 0x0dc3: 0x40239720,
+ 0x0dc4: 0x40239820, 0x0dc5: 0x40239920, 0x0dc6: 0x40239a20, 0x0dc7: 0x40239b20,
+ 0x0dc8: 0x40239c20, 0x0dc9: 0x40239d20, 0x0dca: 0x40239e20, 0x0dcb: 0x40239f20,
+ 0x0dcc: 0x4023a020, 0x0dcd: 0x4023a120, 0x0dce: 0x4023a220, 0x0dcf: 0x4023a320,
+ 0x0dd0: 0x4023a420, 0x0dd1: 0x4023a520, 0x0dd2: 0x4023a620, 0x0dd3: 0x4023a720,
+ 0x0dd4: 0x4023a820, 0x0dd5: 0x4023a920, 0x0dd6: 0x4023aa20, 0x0dd7: 0x4023ab20,
+ 0x0dd8: 0x4023ac20, 0x0dd9: 0x4023ad20, 0x0dda: 0x4023ae20, 0x0ddb: 0x4023af20,
+ 0x0ddc: 0x4023b020, 0x0ddd: 0x4023b120, 0x0dde: 0x4023b220, 0x0ddf: 0x4023b320,
+ 0x0de0: 0x4023b420, 0x0de1: 0x4023b520, 0x0de2: 0x4023b620, 0x0de3: 0x4023b720,
+ 0x0de4: 0x4023b820, 0x0de5: 0x4023b920, 0x0de6: 0x4023ba20, 0x0de7: 0x4023bb20,
+ 0x0de8: 0x4023bc20, 0x0de9: 0x4023bd20, 0x0dea: 0x4023be20, 0x0deb: 0x4023bf20,
+ 0x0dec: 0x4023c020, 0x0ded: 0x4023c120, 0x0dee: 0x4023c220, 0x0def: 0x4023c320,
+ 0x0df0: 0x4023c420, 0x0df1: 0x4023c520, 0x0df2: 0x4023c620, 0x0df3: 0x4023c720,
+ 0x0df4: 0x4023c820, 0x0df5: 0x4023c920, 0x0df6: 0x4023ca20, 0x0df7: 0x4023cb20,
+ 0x0df8: 0x4023cc20, 0x0df9: 0x4023cd20, 0x0dfa: 0x4023ce20,
+ 0x0dff: 0x4013af20,
+ // Block 0x38, offset 0xe00
+ 0x0e00: 0xc07f04e1, 0x0e01: 0xc0ae04e1, 0x0e02: 0xc0dd04e1, 0x0e03: 0xc10c04e1,
+ 0x0e04: 0xc13b04e1, 0x0e05: 0x4023d420, 0x0e06: 0x40139520, 0x0e07: 0x80011d02,
+ 0x0e08: 0x80011e02, 0x0e09: 0x80011f02, 0x0e0a: 0x80012002, 0x0e0b: 0x80012102,
+ 0x0e0c: 0x80012202, 0x0e0d: 0xc16a0511, 0x0e0e: 0x80011c02, 0x0e0f: 0x4002d120,
+ 0x0e10: 0xe000005d, 0x0e11: 0xe00000e1, 0x0e12: 0xe00001c8, 0x0e13: 0xe000028e,
+ 0x0e14: 0xe000034b, 0x0e15: 0xe0000405, 0x0e16: 0xe00004bc, 0x0e17: 0xe0000558,
+ 0x0e18: 0xe00005f4, 0x0e19: 0xe000068d, 0x0e1a: 0x40028920, 0x0e1b: 0x40028a20,
+ // Block 0x39, offset 0xe40
+ 0x0e41: 0x4023d520, 0x0e42: 0x4023d620,
+ 0x0e44: 0x4023d720, 0x0e47: 0x4023d820,
+ 0x0e48: 0x4023d920, 0x0e4a: 0x4023db20,
+ 0x0e4d: 0x4023dc20,
+ 0x0e54: 0x4023dd20, 0x0e55: 0x4023de20, 0x0e56: 0x4023df20, 0x0e57: 0x4023e020,
+ 0x0e59: 0x4023e120, 0x0e5a: 0x4023e220, 0x0e5b: 0x4023e320,
+ 0x0e5c: 0x4023e420, 0x0e5d: 0x4023e520, 0x0e5e: 0x4023e620, 0x0e5f: 0x4023e720,
+ 0x0e61: 0x4023e820, 0x0e62: 0x4023e920, 0x0e63: 0x4023ea20,
+ 0x0e65: 0x4023eb20, 0x0e67: 0x4023ec20,
+ 0x0e6a: 0x4023da20, 0x0e6b: 0x4023ed20,
+ 0x0e6d: 0x4023ee20, 0x0e6e: 0x4023ef20, 0x0e6f: 0x4023f020,
+ 0x0e70: 0x4023f120, 0x0e71: 0x4023f220, 0x0e72: 0x4023f320, 0x0e73: 0x4023f420,
+ 0x0e74: 0x4023f520, 0x0e75: 0x4023f620, 0x0e76: 0x4023f720, 0x0e77: 0x4023f820,
+ 0x0e78: 0x4023f920, 0x0e79: 0x4023fa20, 0x0e7b: 0x4023fb20,
+ 0x0e7c: 0x4023fc20, 0x0e7d: 0x4023fd20,
+ // Block 0x3a, offset 0xe80
+ 0x0e80: 0xc16c0541, 0x0e81: 0xc18a0541, 0x0e82: 0xc1a80541, 0x0e83: 0xc1c60541,
+ 0x0e84: 0xc1e40541, 0x0e86: 0x40139620,
+ 0x0e88: 0x80012402, 0x0e89: 0x80012502, 0x0e8a: 0x80012602, 0x0e8b: 0x80012702,
+ 0x0e8c: 0x80012802, 0x0e8d: 0xc2020641,
+ 0x0e90: 0xe0000060, 0x0e91: 0xe00000e4, 0x0e92: 0xe00001cb, 0x0e93: 0xe0000291,
+ 0x0e94: 0xe000034e, 0x0e95: 0xe0000408, 0x0e96: 0xe00004bf, 0x0e97: 0xe000055b,
+ 0x0e98: 0xe00005f7, 0x0e99: 0xe0000690,
+ 0x0e9c: 0xf0000404, 0x0e9d: 0xf0000404,
+ // Block 0x3b, offset 0xec0
+ 0x0ec0: 0xe0001051, 0x0ec1: 0x40039d20, 0x0ec2: 0x40039e20, 0x0ec3: 0x40039f20,
+ 0x0ec4: 0x40028d20, 0x0ec5: 0x40028e20, 0x0ec6: 0x40028f20, 0x0ec7: 0x40029020,
+ 0x0ec8: 0x40029120, 0x0ec9: 0x40029220, 0x0eca: 0x40029320, 0x0ecb: 0x40029620,
+ 0x0ecc: 0xf000001b, 0x0ecd: 0x40029720, 0x0ece: 0x40029820, 0x0ecf: 0x40029920,
+ 0x0ed0: 0x40029a20, 0x0ed1: 0x40029b20, 0x0ed2: 0x40029c20, 0x0ed3: 0x4003a020,
+ 0x0ed4: 0x40030f20, 0x0ed5: 0x4003a120, 0x0ed6: 0x4003a220, 0x0ed7: 0x4003a320,
+ 0x0ed8: 0x80000000, 0x0ed9: 0x80000000, 0x0eda: 0x4003a420, 0x0edb: 0x4003a520,
+ 0x0edc: 0x4003a620, 0x0edd: 0x4003a720, 0x0ede: 0x4003a820, 0x0edf: 0x4003a920,
+ 0x0ee0: 0xe0000063, 0x0ee1: 0xe00000e7, 0x0ee2: 0xe00001ce, 0x0ee3: 0xe0000294,
+ 0x0ee4: 0xe0000351, 0x0ee5: 0xe000040b, 0x0ee6: 0xe00004c2, 0x0ee7: 0xe000055e,
+ 0x0ee8: 0xe00005fa, 0x0ee9: 0xe0000693, 0x0eea: 0xe00000ea, 0x0eeb: 0xe00001d1,
+ 0x0eec: 0xe0000297, 0x0eed: 0xe0000354, 0x0eee: 0xe000040e, 0x0eef: 0xe00004c5,
+ 0x0ef0: 0xe0000561, 0x0ef1: 0xe00005fd, 0x0ef2: 0xe0000696, 0x0ef3: 0xe0000066,
+ 0x0ef4: 0x4003aa20, 0x0ef5: 0x80000000, 0x0ef6: 0x4003ab20, 0x0ef7: 0x80000000,
+ 0x0ef8: 0x4003ac20, 0x0ef9: 0x80012c02, 0x0efa: 0x4001ef20, 0x0efb: 0x4001f020,
+ 0x0efc: 0x4001f120, 0x0efd: 0x4001f220, 0x0efe: 0x4003ad20, 0x0eff: 0x4003ae20,
+ // Block 0x3c, offset 0xf00
+ 0x0f00: 0x40244620, 0x0f01: 0x40244920, 0x0f02: 0x40244b20,
+ 0x0f04: 0x40244d20, 0x0f05: 0x40244f20, 0x0f06: 0x40245120, 0x0f07: 0x40245320,
+ 0x0f09: 0x40245520, 0x0f0a: 0x40245720, 0x0f0b: 0x40245920,
+ 0x0f0c: 0x40245b20, 0x0f0e: 0x40245d20, 0x0f0f: 0x40245f20,
+ 0x0f10: 0x40246120, 0x0f11: 0x40246320, 0x0f13: 0x40246520,
+ 0x0f14: 0x40246720, 0x0f15: 0x40246920, 0x0f16: 0x40246b20,
+ 0x0f18: 0x40246d20, 0x0f19: 0x40246f20, 0x0f1a: 0x40247120, 0x0f1b: 0x40247320,
+ 0x0f1d: 0x40247520, 0x0f1e: 0x40247720, 0x0f1f: 0x40247920,
+ 0x0f20: 0x40247b20, 0x0f21: 0x40247d20, 0x0f22: 0x40247f20, 0x0f23: 0x40248220,
+ 0x0f24: 0x40248420, 0x0f25: 0x40248620, 0x0f26: 0x40248820, 0x0f27: 0x40248a20,
+ 0x0f28: 0x40248c20, 0x0f2a: 0xe0001045, 0x0f2b: 0x40244820,
+ 0x0f2c: 0x40248120,
+ 0x0f31: 0xc3030721, 0x0f32: 0x40249720, 0x0f33: 0x40249820,
+ 0x0f34: 0x40249b20, 0x0f35: 0x40249c20, 0x0f36: 0x40249d20, 0x0f37: 0x40249e20,
+ 0x0f38: 0x40249f20, 0x0f39: 0x4024a020, 0x0f3a: 0x4024a120, 0x0f3b: 0x4024a220,
+ 0x0f3c: 0x4024a320, 0x0f3d: 0x4024a420, 0x0f3e: 0x80012d02, 0x0f3f: 0x80012e02,
+ // Block 0x3d, offset 0xf40
+ 0x0f40: 0x40249920, 0x0f41: 0x40249a20, 0x0f42: 0x80000000, 0x0f43: 0x80000000,
+ 0x0f44: 0x4024a520, 0x0f45: 0x40029d20, 0x0f46: 0x80000000, 0x0f47: 0x80000000,
+ 0x0f48: 0x40248e20, 0x0f49: 0x40249020, 0x0f4a: 0x40249420, 0x0f4b: 0x40249520,
+ 0x0f4c: 0x40249220, 0x0f4d: 0x40248f20, 0x0f4e: 0x40249120, 0x0f4f: 0x40249320,
+ 0x0f50: 0x40244720, 0x0f51: 0x40244a20, 0x0f52: 0x40244c20,
+ 0x0f54: 0x40244e20, 0x0f55: 0x40245020, 0x0f56: 0x40245220, 0x0f57: 0x40245420,
+ 0x0f59: 0x40245620, 0x0f5a: 0x40245820, 0x0f5b: 0x40245a20,
+ 0x0f5c: 0x40245c20, 0x0f5e: 0x40245e20, 0x0f5f: 0x40246020,
+ 0x0f60: 0x40246220, 0x0f61: 0x40246420, 0x0f63: 0x40246620,
+ 0x0f64: 0x40246820, 0x0f65: 0x40246a20, 0x0f66: 0x40246c20,
+ 0x0f68: 0x40246e20, 0x0f69: 0x40247020, 0x0f6a: 0x40247220, 0x0f6b: 0x40247420,
+ 0x0f6d: 0x40247620, 0x0f6e: 0x40247820, 0x0f6f: 0x40247a20,
+ 0x0f70: 0x40247c20, 0x0f71: 0x40247e20, 0x0f72: 0xc2f906a1, 0x0f73: 0xc2fe06a1,
+ 0x0f74: 0x40248520, 0x0f75: 0x40248720, 0x0f76: 0x40248920, 0x0f77: 0x40248b20,
+ 0x0f78: 0x40248d20, 0x0f7a: 0xe000103f, 0x0f7b: 0xe0001042,
+ 0x0f7c: 0xe0001048, 0x0f7e: 0x4003af20, 0x0f7f: 0x4003b020,
+ // Block 0x3e, offset 0xf80
+ 0x0f80: 0x4003b120, 0x0f81: 0x4003b220, 0x0f82: 0x4003b320, 0x0f83: 0x4003b420,
+ 0x0f84: 0x4003b520, 0x0f85: 0x4003b620, 0x0f86: 0x80000000, 0x0f87: 0x4003b720,
+ 0x0f88: 0x4003b820, 0x0f89: 0x4003b920, 0x0f8a: 0x4003ba20, 0x0f8b: 0x4003bb20,
+ 0x0f8c: 0x4003bc20, 0x0f8e: 0x4003bd20, 0x0f8f: 0x4003be20,
+ 0x0f90: 0x40029420, 0x0f91: 0x40029520, 0x0f92: 0x40029e20, 0x0f93: 0x40029f20,
+ 0x0f94: 0x4002a020, 0x0f95: 0x4003bf20, 0x0f96: 0x4003c020, 0x0f97: 0x4003c120,
+ 0x0f98: 0x4003c220, 0x0f99: 0x4002a120, 0x0f9a: 0x4002a220,
+ // Block 0x3f, offset 0xfc0
+ 0x0fc0: 0x40261520, 0x0fc1: 0x40261720, 0x0fc2: 0x40261920, 0x0fc3: 0x40261c20,
+ 0x0fc4: 0x40261d20, 0x0fc5: 0x40261f20, 0x0fc6: 0x40262220, 0x0fc7: 0x40262420,
+ 0x0fc8: 0x40262820, 0x0fc9: 0x40262c20, 0x0fca: 0x40262f20, 0x0fcb: 0x40263020,
+ 0x0fcc: 0x40263220, 0x0fcd: 0x40263420, 0x0fce: 0x40263620, 0x0fcf: 0x40263820,
+ 0x0fd0: 0x40263a20, 0x0fd1: 0x40263b20, 0x0fd2: 0x40263c20, 0x0fd3: 0x40263e20,
+ 0x0fd4: 0x40264020, 0x0fd5: 0x40264420, 0x0fd6: 0x40264520, 0x0fd7: 0x40264a20,
+ 0x0fd8: 0x40264c20, 0x0fd9: 0x40264d20, 0x0fda: 0x40264f20, 0x0fdb: 0x40265120,
+ 0x0fdc: 0x40265520, 0x0fdd: 0x40265720, 0x0fde: 0x40265e20, 0x0fdf: 0x40266020,
+ 0x0fe0: 0x40266620, 0x0fe1: 0x40266c20, 0x0fe2: 0x40266d20, 0x0fe3: 0x40266e20,
+ 0x0fe4: 0x40266f20, 0x0fe5: 0xc3070781, 0x0fe6: 0x40267120, 0x0fe7: 0x40267620,
+ 0x0fe8: 0x40267720, 0x0fe9: 0x40267820, 0x0fea: 0x40267920, 0x0feb: 0x004cf404,
+ 0x0fec: 0x40267a20, 0x0fed: 0x40267e20, 0x0fee: 0x40268020, 0x0fef: 0x40268220,
+ 0x0ff0: 0x40268520, 0x0ff1: 0x40268a20, 0x0ff2: 0x40268e20, 0x0ff3: 0x40268120,
+ 0x0ff4: 0x40269020, 0x0ff5: 0x40268c20, 0x0ff6: 0x80013302, 0x0ff7: 0x80013402,
+ 0x0ff8: 0x80013502, 0x0ff9: 0x40269520, 0x0ffa: 0x40269620, 0x0ffb: 0x40265020,
+ 0x0ffc: 0x40265420, 0x0ffd: 0x40265820, 0x0ffe: 0x40266320, 0x0fff: 0xe0001055,
+ // Block 0x40, offset 0x1000
+ 0x1000: 0xe000006f, 0x1001: 0xe00000f3, 0x1002: 0xe00001da, 0x1003: 0xe00002a0,
+ 0x1004: 0xe000035d, 0x1005: 0xe0000417, 0x1006: 0xe00004ce, 0x1007: 0xe000056a,
+ 0x1008: 0xe0000606, 0x1009: 0xe000069f, 0x100a: 0x40018920, 0x100b: 0x40018a20,
+ 0x100c: 0x4002a620, 0x100d: 0x4002a720, 0x100e: 0x4002a820, 0x100f: 0x4002a920,
+ 0x1010: 0x40265b20, 0x1011: 0x40265c20, 0x1012: 0x40267220, 0x1013: 0x40267320,
+ 0x1014: 0x40267420, 0x1015: 0x40267520, 0x1016: 0x40268620, 0x1017: 0x40268720,
+ 0x1018: 0x40268820, 0x1019: 0x40268920, 0x101a: 0x40261e20, 0x101b: 0x40262920,
+ 0x101c: 0x40266720, 0x101d: 0x40266820, 0x101e: 0x40264320, 0x101f: 0x40264e20,
+ 0x1020: 0x40265620, 0x1021: 0x40262b20, 0x1022: 0x40269120, 0x1023: 0x40269720,
+ 0x1024: 0x40269820, 0x1025: 0x40265d20, 0x1026: 0x40266b20, 0x1027: 0x40269220,
+ 0x1028: 0x40269320, 0x1029: 0x40269920, 0x102a: 0x40269a20, 0x102b: 0x40269b20,
+ 0x102c: 0x40269c20, 0x102d: 0x40269d20, 0x102e: 0x40263920, 0x102f: 0x40266920,
+ 0x1030: 0x40266a20, 0x1031: 0x40267f20, 0x1032: 0x40267c20, 0x1033: 0x40268320,
+ 0x1034: 0x40268420, 0x1035: 0x40261620, 0x1036: 0x40261820, 0x1037: 0x40261a20,
+ 0x1038: 0x40262020, 0x1039: 0x40262620, 0x103a: 0x40262d20, 0x103b: 0x40263d20,
+ 0x103c: 0x40264120, 0x103d: 0x40264620, 0x103e: 0x40264720, 0x103f: 0x40264b20,
+ // Block 0x41, offset 0x1040
+ 0x1040: 0x40265a20, 0x1041: 0x40266120, 0x1042: 0x40265920, 0x1043: 0x40267b20,
+ 0x1044: 0x40268b20, 0x1045: 0x40268d20, 0x1046: 0x40269420, 0x1047: 0x40269e20,
+ 0x1048: 0x4026a020, 0x1049: 0x4026a220, 0x104a: 0x4026a320, 0x104b: 0x40269f20,
+ 0x104c: 0x4026a120, 0x104d: 0x80013602, 0x104e: 0x40264920, 0x104f: 0x4026a420,
+ 0x1050: 0xe0000072, 0x1051: 0xe00000f6, 0x1052: 0xe00001dd, 0x1053: 0xe00002a3,
+ 0x1054: 0xe0000360, 0x1055: 0xe000041a, 0x1056: 0xe00004d1, 0x1057: 0xe000056d,
+ 0x1058: 0xe0000609, 0x1059: 0xe00006a2, 0x105a: 0x4026a520, 0x105b: 0x4026a620,
+ 0x105c: 0x40267d20, 0x105d: 0x40268f20, 0x105e: 0x40031a20, 0x105f: 0x40031b20,
+ 0x1060: 0x0036fc08, 0x1061: 0x00370008, 0x1062: 0x00370408, 0x1063: 0x00370808,
+ 0x1064: 0x00370c08, 0x1065: 0x00371008, 0x1066: 0x00371408, 0x1067: 0x00371c08,
+ 0x1068: 0x00372008, 0x1069: 0x00372408, 0x106a: 0x00372808, 0x106b: 0x00372c08,
+ 0x106c: 0x00373008, 0x106d: 0x00373808, 0x106e: 0x00373c08, 0x106f: 0x00374008,
+ 0x1070: 0x00374408, 0x1071: 0x00374808, 0x1072: 0x00374c08, 0x1073: 0x00375408,
+ 0x1074: 0x00375808, 0x1075: 0x00375c08, 0x1076: 0x00376008, 0x1077: 0x00376408,
+ 0x1078: 0x00376808, 0x1079: 0x00376c08, 0x107a: 0x00377008, 0x107b: 0x00377408,
+ 0x107c: 0x00377808, 0x107d: 0x00377c08, 0x107e: 0x00378008, 0x107f: 0x00378808,
+ // Block 0x42, offset 0x1080
+ 0x1080: 0x00378c08, 0x1081: 0x00371808, 0x1082: 0x00373408, 0x1083: 0x00375008,
+ 0x1084: 0x00378408, 0x1085: 0x00379008,
+ 0x1090: 0x401b7d20, 0x1091: 0x401b7f20, 0x1092: 0x401b8120, 0x1093: 0x401b8320,
+ 0x1094: 0x401b8520, 0x1095: 0x401b8720, 0x1096: 0x401b8920, 0x1097: 0x401b8d20,
+ 0x1098: 0x401b8f20, 0x1099: 0x401b9120, 0x109a: 0x401b9320, 0x109b: 0x401b9520,
+ 0x109c: 0x401b9720, 0x109d: 0x401b9b20, 0x109e: 0x401b9d20, 0x109f: 0x401b9f20,
+ 0x10a0: 0x401ba120, 0x10a1: 0x401ba320, 0x10a2: 0x401ba520, 0x10a3: 0x401ba920,
+ 0x10a4: 0x401bab20, 0x10a5: 0x401bad20, 0x10a6: 0x401baf20, 0x10a7: 0x401bb120,
+ 0x10a8: 0x401bb320, 0x10a9: 0x401bb520, 0x10aa: 0x401bb720, 0x10ab: 0x401bb920,
+ 0x10ac: 0x401bbb20, 0x10ad: 0x401bbd20, 0x10ae: 0x401bbf20, 0x10af: 0x401bc320,
+ 0x10b0: 0x401bc520, 0x10b1: 0x401b8b20, 0x10b2: 0x401b9920, 0x10b3: 0x401ba720,
+ 0x10b4: 0x401bc120, 0x10b5: 0x401bc720, 0x10b6: 0x401bc920, 0x10b7: 0x401bca20,
+ 0x10b8: 0x401bcb20, 0x10b9: 0x401bcc20, 0x10ba: 0x401bcd20, 0x10bb: 0x4001a320,
+ 0x10bc: 0xf0000014,
+ // Block 0x43, offset 0x10c0
+ 0x10c0: 0x40303120, 0x10c1: 0x40303220, 0x10c2: 0x40303320, 0x10c3: 0x40303420,
+ 0x10c4: 0x40303520, 0x10c5: 0x40303620, 0x10c6: 0x40303720, 0x10c7: 0x40303820,
+ 0x10c8: 0x40303920, 0x10c9: 0x40303a20, 0x10ca: 0x40303b20, 0x10cb: 0x40303c20,
+ 0x10cc: 0x40303d20, 0x10cd: 0x40303e20, 0x10ce: 0x40303f20, 0x10cf: 0x40304020,
+ 0x10d0: 0x40304120, 0x10d1: 0x40304220, 0x10d2: 0x40304320, 0x10d3: 0x40304420,
+ 0x10d4: 0x40304520, 0x10d5: 0x40304620, 0x10d6: 0x40304720, 0x10d7: 0x40304820,
+ 0x10d8: 0x40304920, 0x10d9: 0x40304a20, 0x10da: 0x40304b20, 0x10db: 0x40304c20,
+ 0x10dc: 0x40304d20, 0x10dd: 0x40304e20, 0x10de: 0x40304f20, 0x10df: 0x40305020,
+ 0x10e0: 0x40305120, 0x10e1: 0x40305220, 0x10e2: 0x40305320, 0x10e3: 0x40305420,
+ 0x10e4: 0x40305520, 0x10e5: 0x40305620, 0x10e6: 0x40305720, 0x10e7: 0x40305820,
+ 0x10e8: 0x40305920, 0x10e9: 0x40305a20, 0x10ea: 0x40305b20, 0x10eb: 0x40305c20,
+ 0x10ec: 0x40305d20, 0x10ed: 0x40305e20, 0x10ee: 0x40305f20, 0x10ef: 0x40306020,
+ 0x10f0: 0x40306120, 0x10f1: 0x40306220, 0x10f2: 0x40306320, 0x10f3: 0x40306420,
+ 0x10f4: 0x40306520, 0x10f5: 0x40306620, 0x10f6: 0x40306720, 0x10f7: 0x40306820,
+ 0x10f8: 0x40306920, 0x10f9: 0x40306a20, 0x10fa: 0x40306b20, 0x10fb: 0x40306c20,
+ 0x10fc: 0x40306d20, 0x10fd: 0x40306e20, 0x10fe: 0x40306f20, 0x10ff: 0x40307020,
+ // Block 0x44, offset 0x1100
+ 0x1100: 0x40307120, 0x1101: 0x40307220, 0x1102: 0x40307320, 0x1103: 0x40307420,
+ 0x1104: 0x40307520, 0x1105: 0x40307620, 0x1106: 0x40307720, 0x1107: 0x40307820,
+ 0x1108: 0x40307920, 0x1109: 0x40307a20, 0x110a: 0x40307b20, 0x110b: 0x40307c20,
+ 0x110c: 0x40307d20, 0x110d: 0x40307e20, 0x110e: 0x40307f20, 0x110f: 0x40308020,
+ 0x1110: 0x40308120, 0x1111: 0x40308220, 0x1112: 0x40308320, 0x1113: 0x40308420,
+ 0x1114: 0x40308520, 0x1115: 0x40308620, 0x1116: 0x40308720, 0x1117: 0x40308820,
+ 0x1118: 0x40308920, 0x1119: 0x40308a20, 0x111a: 0x40308b20, 0x111b: 0x40308c20,
+ 0x111c: 0x40308d20, 0x111d: 0x40308e20, 0x111e: 0x40308f20, 0x111f: 0x4030ad20,
+ 0x1120: 0x4030ae20, 0x1121: 0x4030af20, 0x1122: 0x4030b020, 0x1123: 0x4030b120,
+ 0x1124: 0x4030b220, 0x1125: 0x4030b320, 0x1126: 0x4030b420, 0x1127: 0x4030b520,
+ 0x1128: 0x4030b620, 0x1129: 0x4030b720, 0x112a: 0x4030b820, 0x112b: 0x4030b920,
+ 0x112c: 0x4030ba20, 0x112d: 0x4030bb20, 0x112e: 0x4030bc20, 0x112f: 0x4030bd20,
+ 0x1130: 0x4030be20, 0x1131: 0x4030bf20, 0x1132: 0x4030c020, 0x1133: 0x4030c120,
+ 0x1134: 0x4030c220, 0x1135: 0x4030c320, 0x1136: 0x4030c420, 0x1137: 0x4030c520,
+ 0x1138: 0x4030c620, 0x1139: 0x4030c720, 0x113a: 0x4030c820, 0x113b: 0x4030c920,
+ 0x113c: 0x4030ca20, 0x113d: 0x4030cb20, 0x113e: 0x4030cc20, 0x113f: 0x4030cd20,
+ // Block 0x45, offset 0x1140
+ 0x1140: 0x4030ce20, 0x1141: 0x4030cf20, 0x1142: 0x4030d020, 0x1143: 0x4030d120,
+ 0x1144: 0x4030d220, 0x1145: 0x4030d320, 0x1146: 0x4030d420, 0x1147: 0x4030d520,
+ 0x1148: 0x4030d620, 0x1149: 0x4030d720, 0x114a: 0x4030d820, 0x114b: 0x4030d920,
+ 0x114c: 0x4030da20, 0x114d: 0x4030db20, 0x114e: 0x4030dc20, 0x114f: 0x4030dd20,
+ 0x1150: 0x4030de20, 0x1151: 0x4030df20, 0x1152: 0x4030e020, 0x1153: 0x4030e120,
+ 0x1154: 0x4030e220, 0x1155: 0x4030e320, 0x1156: 0x4030e420, 0x1157: 0x4030e520,
+ 0x1158: 0x4030e620, 0x1159: 0x4030e720, 0x115a: 0x4030e820, 0x115b: 0x4030e920,
+ 0x115c: 0x4030ea20, 0x115d: 0x4030eb20, 0x115e: 0x4030ec20, 0x115f: 0x4030ed20,
+ 0x1160: 0x4030ee20, 0x1161: 0x4030ef20, 0x1162: 0x4030f020, 0x1163: 0x4030f120,
+ 0x1164: 0x4030f220, 0x1165: 0x4030f320, 0x1166: 0x4030f420, 0x1167: 0x4030f520,
+ 0x1168: 0x40310d20, 0x1169: 0x40310e20, 0x116a: 0x40310f20, 0x116b: 0x40311020,
+ 0x116c: 0x40311120, 0x116d: 0x40311220, 0x116e: 0x40311320, 0x116f: 0x40311420,
+ 0x1170: 0x40311520, 0x1171: 0x40311620, 0x1172: 0x40311720, 0x1173: 0x40311820,
+ 0x1174: 0x40311920, 0x1175: 0x40311a20, 0x1176: 0x40311b20, 0x1177: 0x40311c20,
+ 0x1178: 0x40311d20, 0x1179: 0x40311e20, 0x117a: 0x40311f20, 0x117b: 0x40312020,
+ 0x117c: 0x40312120, 0x117d: 0x40312220, 0x117e: 0x40312320, 0x117f: 0x40312420,
+ // Block 0x46, offset 0x1180
+ 0x1180: 0x40312520, 0x1181: 0x40312620, 0x1182: 0x40312720, 0x1183: 0x40312820,
+ 0x1184: 0x40312920, 0x1185: 0x40312a20, 0x1186: 0x40312b20, 0x1187: 0x40312c20,
+ 0x1188: 0x40312d20, 0x1189: 0x40312e20, 0x118a: 0x40312f20, 0x118b: 0x40313020,
+ 0x118c: 0x40313120, 0x118d: 0x40313220, 0x118e: 0x40313320, 0x118f: 0x40313420,
+ 0x1190: 0x40313520, 0x1191: 0x40313620, 0x1192: 0x40313720, 0x1193: 0x40313820,
+ 0x1194: 0x40313920, 0x1195: 0x40313a20, 0x1196: 0x40313b20, 0x1197: 0x40313c20,
+ 0x1198: 0x40313d20, 0x1199: 0x40313e20, 0x119a: 0x40313f20, 0x119b: 0x40314020,
+ 0x119c: 0x40314120, 0x119d: 0x40314220, 0x119e: 0x40314320, 0x119f: 0x40314420,
+ 0x11a0: 0x40314520, 0x11a1: 0x40314620, 0x11a2: 0x40314720, 0x11a3: 0x40314820,
+ 0x11a4: 0x40314920, 0x11a5: 0x40314a20, 0x11a6: 0x40314b20, 0x11a7: 0x40314c20,
+ 0x11a8: 0x40314d20, 0x11a9: 0x40314e20, 0x11aa: 0x40314f20, 0x11ab: 0x40315020,
+ 0x11ac: 0x40315120, 0x11ad: 0x40315220, 0x11ae: 0x40315320, 0x11af: 0x40315420,
+ 0x11b0: 0x40315520, 0x11b1: 0x40315620, 0x11b2: 0x40315720, 0x11b3: 0x40315820,
+ 0x11b4: 0x40315920, 0x11b5: 0x40315a20, 0x11b6: 0x40315b20, 0x11b7: 0x40315c20,
+ 0x11b8: 0x40315d20, 0x11b9: 0x40315e20, 0x11ba: 0x40315f20, 0x11bb: 0x40316020,
+ 0x11bc: 0x40316120, 0x11bd: 0x40316220, 0x11be: 0x40316320, 0x11bf: 0x40316420,
+ // Block 0x47, offset 0x11c0
+ 0x11c0: 0x401db620, 0x11c1: 0x401db720, 0x11c2: 0x401db820, 0x11c3: 0x401db920,
+ 0x11c4: 0x401dba20, 0x11c5: 0x401dbb20, 0x11c6: 0x401dbc20, 0x11c7: 0x401dbd20,
+ 0x11c8: 0x401dbe20, 0x11c9: 0x401dbf20, 0x11ca: 0x401dc020, 0x11cb: 0x401dc120,
+ 0x11cc: 0x401dc220, 0x11cd: 0x401dc320, 0x11ce: 0x401dc420, 0x11cf: 0x401dc520,
+ 0x11d0: 0x401dc720, 0x11d1: 0x401dc820, 0x11d2: 0x401dc920, 0x11d3: 0x401dca20,
+ 0x11d4: 0x401dcb20, 0x11d5: 0x401dcc20, 0x11d6: 0x401dcd20, 0x11d7: 0x401dce20,
+ 0x11d8: 0x401dcf20, 0x11d9: 0x401dd020, 0x11da: 0x401dd120, 0x11db: 0x401dd220,
+ 0x11dc: 0x401dd320, 0x11dd: 0x401dd420, 0x11de: 0x401dd520, 0x11df: 0x401dd620,
+ 0x11e0: 0x401ddc20, 0x11e1: 0x401ddd20, 0x11e2: 0x401dde20, 0x11e3: 0x401ddf20,
+ 0x11e4: 0x401de020, 0x11e5: 0x401de120, 0x11e6: 0x401de220, 0x11e7: 0x401de320,
+ 0x11e8: 0x401de420, 0x11e9: 0x401de520, 0x11ea: 0x401de620, 0x11eb: 0x401de720,
+ 0x11ec: 0x401de820, 0x11ed: 0x401de920, 0x11ee: 0x401dea20, 0x11ef: 0x401deb20,
+ 0x11f0: 0x401ded20, 0x11f1: 0x401dee20, 0x11f2: 0x401def20, 0x11f3: 0x401df020,
+ 0x11f4: 0x401df120, 0x11f5: 0x401df220, 0x11f6: 0x401df320, 0x11f7: 0x401df420,
+ 0x11f8: 0x401dfc20, 0x11f9: 0x401dfd20, 0x11fa: 0x401dfe20, 0x11fb: 0x401dff20,
+ 0x11fc: 0x401e0020, 0x11fd: 0x401e0120, 0x11fe: 0x401e0220, 0x11ff: 0x401e0320,
+ // Block 0x48, offset 0x1200
+ 0x1200: 0x401e0520, 0x1201: 0x401e0620, 0x1202: 0x401e0720, 0x1203: 0x401e0820,
+ 0x1204: 0x401e0920, 0x1205: 0x401e0a20, 0x1206: 0x401e0b20, 0x1207: 0x401e0c20,
+ 0x1208: 0x401e0d20, 0x120a: 0x401e0e20, 0x120b: 0x401e0f20,
+ 0x120c: 0x401e1020, 0x120d: 0x401e1120,
+ 0x1210: 0x401e1220, 0x1211: 0x401e1320, 0x1212: 0x401e1420, 0x1213: 0x401e1520,
+ 0x1214: 0x401e1620, 0x1215: 0x401e1720, 0x1216: 0x401e1820,
+ 0x1218: 0x401e1920, 0x121a: 0x401e1a20, 0x121b: 0x401e1b20,
+ 0x121c: 0x401e1c20, 0x121d: 0x401e1d20,
+ 0x1220: 0x401e1e20, 0x1221: 0x401e1f20, 0x1222: 0x401e2020, 0x1223: 0x401e2120,
+ 0x1224: 0x401e2220, 0x1225: 0x401e2320, 0x1226: 0x401e2420, 0x1227: 0x401e2520,
+ 0x1228: 0x401e2b20, 0x1229: 0x401e2c20, 0x122a: 0x401e2d20, 0x122b: 0x401e2e20,
+ 0x122c: 0x401e2f20, 0x122d: 0x401e3020, 0x122e: 0x401e3120, 0x122f: 0x401e3220,
+ 0x1230: 0x401e3320, 0x1231: 0x401e3420, 0x1232: 0x401e3520, 0x1233: 0x401e3620,
+ 0x1234: 0x401e3720, 0x1235: 0x401e3820, 0x1236: 0x401e3920, 0x1237: 0x401e3a20,
+ 0x1238: 0x401e3c20, 0x1239: 0x401e3d20, 0x123a: 0x401e3e20, 0x123b: 0x401e3f20,
+ 0x123c: 0x401e4020, 0x123d: 0x401e4120, 0x123e: 0x401e4220, 0x123f: 0x401e4320,
+ // Block 0x49, offset 0x1240
+ 0x1240: 0x401e4520, 0x1241: 0x401e4620, 0x1242: 0x401e4720, 0x1243: 0x401e4820,
+ 0x1244: 0x401e4920, 0x1245: 0x401e4a20, 0x1246: 0x401e4b20, 0x1247: 0x401e4c20,
+ 0x1248: 0x401e4d20, 0x124a: 0x401e4e20, 0x124b: 0x401e4f20,
+ 0x124c: 0x401e5020, 0x124d: 0x401e5120,
+ 0x1250: 0x401e5220, 0x1251: 0x401e5320, 0x1252: 0x401e5420, 0x1253: 0x401e5520,
+ 0x1254: 0x401e5620, 0x1255: 0x401e5720, 0x1256: 0x401e5820, 0x1257: 0x401e5920,
+ 0x1258: 0x401e5b20, 0x1259: 0x401e5c20, 0x125a: 0x401e5d20, 0x125b: 0x401e5e20,
+ 0x125c: 0x401e5f20, 0x125d: 0x401e6020, 0x125e: 0x401e6120, 0x125f: 0x401e6220,
+ 0x1260: 0x401e6420, 0x1261: 0x401e6520, 0x1262: 0x401e6620, 0x1263: 0x401e6720,
+ 0x1264: 0x401e6820, 0x1265: 0x401e6920, 0x1266: 0x401e6a20, 0x1267: 0x401e6b20,
+ 0x1268: 0x401e6d20, 0x1269: 0x401e6e20, 0x126a: 0x401e6f20, 0x126b: 0x401e7020,
+ 0x126c: 0x401e7120, 0x126d: 0x401e7220, 0x126e: 0x401e7320, 0x126f: 0x401e7420,
+ 0x1270: 0x401e7520, 0x1272: 0x401e7620, 0x1273: 0x401e7720,
+ 0x1274: 0x401e7820, 0x1275: 0x401e7920,
+ 0x1278: 0x401e7a20, 0x1279: 0x401e7b20, 0x127a: 0x401e7c20, 0x127b: 0x401e7d20,
+ 0x127c: 0x401e7e20, 0x127d: 0x401e7f20, 0x127e: 0x401e8020,
+ // Block 0x4a, offset 0x1280
+ 0x1280: 0x401e8120, 0x1282: 0x401e8220, 0x1283: 0x401e8320,
+ 0x1284: 0x401e8420, 0x1285: 0x401e8520,
+ 0x1288: 0x401e8620, 0x1289: 0x401e8720, 0x128a: 0x401e8820, 0x128b: 0x401e8920,
+ 0x128c: 0x401e8a20, 0x128d: 0x401e8b20, 0x128e: 0x401e8c20, 0x128f: 0x401e8d20,
+ 0x1290: 0x401e8e20, 0x1291: 0x401e8f20, 0x1292: 0x401e9020, 0x1293: 0x401e9120,
+ 0x1294: 0x401e9220, 0x1295: 0x401e9320, 0x1296: 0x401e9420,
+ 0x1298: 0x401e9520, 0x1299: 0x401e9620, 0x129a: 0x401e9720, 0x129b: 0x401e9820,
+ 0x129c: 0x401e9920, 0x129d: 0x401e9a20, 0x129e: 0x401e9b20, 0x129f: 0x401e9c20,
+ 0x12a0: 0x401ea420, 0x12a1: 0x401ea520, 0x12a2: 0x401ea620, 0x12a3: 0x401ea720,
+ 0x12a4: 0x401ea820, 0x12a5: 0x401ea920, 0x12a6: 0x401eaa20, 0x12a7: 0x401eab20,
+ 0x12a8: 0x401eac20, 0x12a9: 0x401ead20, 0x12aa: 0x401eae20, 0x12ab: 0x401eaf20,
+ 0x12ac: 0x401eb020, 0x12ad: 0x401eb120, 0x12ae: 0x401eb220, 0x12af: 0x401eb320,
+ 0x12b0: 0x401eb420, 0x12b1: 0x401eb520, 0x12b2: 0x401eb620, 0x12b3: 0x401eb720,
+ 0x12b4: 0x401eb820, 0x12b5: 0x401eb920, 0x12b6: 0x401eba20, 0x12b7: 0x401ebb20,
+ 0x12b8: 0x401ec320, 0x12b9: 0x401ec420, 0x12ba: 0x401ec520, 0x12bb: 0x401ec620,
+ 0x12bc: 0x401ec720, 0x12bd: 0x401ec820, 0x12be: 0x401ec920, 0x12bf: 0x401eca20,
+ // Block 0x4b, offset 0x12c0
+ 0x12c0: 0x401ecc20, 0x12c1: 0x401ecd20, 0x12c2: 0x401ece20, 0x12c3: 0x401ecf20,
+ 0x12c4: 0x401ed020, 0x12c5: 0x401ed120, 0x12c6: 0x401ed220, 0x12c7: 0x401ed320,
+ 0x12c8: 0x401ed520, 0x12c9: 0x401ed620, 0x12ca: 0x401ed720, 0x12cb: 0x401ed820,
+ 0x12cc: 0x401ed920, 0x12cd: 0x401eda20, 0x12ce: 0x401edb20, 0x12cf: 0x401edc20,
+ 0x12d0: 0x401edd20, 0x12d2: 0x401ede20, 0x12d3: 0x401edf20,
+ 0x12d4: 0x401ee020, 0x12d5: 0x401ee120,
+ 0x12d8: 0x401ee220, 0x12d9: 0x401ee320, 0x12da: 0x401ee420, 0x12db: 0x401ee520,
+ 0x12dc: 0x401ee620, 0x12dd: 0x401ee720, 0x12de: 0x401ee820, 0x12df: 0x401ee920,
+ 0x12e0: 0x401eee20, 0x12e1: 0x401eef20, 0x12e2: 0x401ef020, 0x12e3: 0x401ef120,
+ 0x12e4: 0x401ef220, 0x12e5: 0x401ef320, 0x12e6: 0x401ef420, 0x12e7: 0x401ef520,
+ 0x12e8: 0x401ef720, 0x12e9: 0x401ef820, 0x12ea: 0x401ef920, 0x12eb: 0x401efa20,
+ 0x12ec: 0x401efb20, 0x12ed: 0x401efc20, 0x12ee: 0x401efd20, 0x12ef: 0x401efe20,
+ 0x12f0: 0x401f0720, 0x12f1: 0x401f0820, 0x12f2: 0x401f0920, 0x12f3: 0x401f0a20,
+ 0x12f4: 0x401f0b20, 0x12f5: 0x401f0c20, 0x12f6: 0x401f0d20, 0x12f7: 0x401f0e20,
+ 0x12f8: 0x401f1020, 0x12f9: 0x401f1120, 0x12fa: 0x401f1220, 0x12fb: 0x401f1320,
+ 0x12fc: 0x401f1420, 0x12fd: 0x401f1520, 0x12fe: 0x401f1620, 0x12ff: 0x401f1720,
+ // Block 0x4c, offset 0x1300
+ 0x1300: 0x401f1f20, 0x1301: 0x401f2020, 0x1302: 0x401f2120, 0x1303: 0x401f2220,
+ 0x1304: 0x401f2320, 0x1305: 0x401f2420, 0x1306: 0x401f2520, 0x1307: 0x401f2620,
+ 0x1308: 0x401f2720, 0x1309: 0x401f2820, 0x130a: 0x401f2920, 0x130b: 0x401f2a20,
+ 0x130c: 0x401f2b20, 0x130d: 0x401f2c20, 0x130e: 0x401f2d20, 0x130f: 0x401f2e20,
+ 0x1310: 0x401f3320, 0x1311: 0x401f3420, 0x1312: 0x401f3520, 0x1313: 0x401f3620,
+ 0x1314: 0x401f3720, 0x1315: 0x401f3820, 0x1316: 0x401f3920, 0x1317: 0x401f3a20,
+ 0x1318: 0x401f4020, 0x1319: 0x401f4120, 0x131a: 0x401f4220,
+ 0x131d: 0x8000da02, 0x131e: 0x8000d902, 0x131f: 0x8000d802,
+ 0x1320: 0x40031020, 0x1321: 0x40014a20, 0x1322: 0x40017020, 0x1323: 0x40014b20,
+ 0x1324: 0x40014c20, 0x1325: 0x40014d20, 0x1326: 0x40014e20, 0x1327: 0x40016320,
+ 0x1328: 0x4001a420, 0x1329: 0xe00000a5, 0x132a: 0xe000018f, 0x132b: 0xe0000255,
+ 0x132c: 0xe0000318, 0x132d: 0xe00003d2, 0x132e: 0xe0000489, 0x132f: 0xe0000525,
+ 0x1330: 0xe00005c1, 0x1331: 0xe000065a, 0x1332: 0x4013e720, 0x1333: 0x4013e820,
+ 0x1334: 0x4013e920, 0x1335: 0x4013ea20, 0x1336: 0x4013eb20, 0x1337: 0x4013ec20,
+ 0x1338: 0x4013ed20, 0x1339: 0x4013ee20, 0x133a: 0x4013ef20, 0x133b: 0x4013f020,
+ 0x133c: 0x4013f120,
+ // Block 0x4d, offset 0x1340
+ 0x1340: 0x401dd720, 0x1341: 0x401dd820, 0x1342: 0x401dd920, 0x1343: 0x401dda20,
+ 0x1344: 0x401e2620, 0x1345: 0x401e2720, 0x1346: 0x401e2820, 0x1347: 0x401e2920,
+ 0x1348: 0x401f2f20, 0x1349: 0x401f3020, 0x134a: 0x401f3120, 0x134b: 0x401f3220,
+ 0x134c: 0x401f3b20, 0x134d: 0x401f3c20, 0x134e: 0x401f3d20, 0x134f: 0x401f3e20,
+ 0x1350: 0x40035320, 0x1351: 0x40035420, 0x1352: 0x40035520, 0x1353: 0x40035620,
+ 0x1354: 0x40035720, 0x1355: 0x40035820, 0x1356: 0x40035920, 0x1357: 0x40035a20,
+ 0x1358: 0x40035b20, 0x1359: 0x40035c20,
+ 0x1360: 0x40291620, 0x1361: 0x40291720, 0x1362: 0x40291820, 0x1363: 0x40291920,
+ 0x1364: 0x40291a20, 0x1365: 0x40291b20, 0x1366: 0x40291c20, 0x1367: 0x40291d20,
+ 0x1368: 0x40291e20, 0x1369: 0x40291f20, 0x136a: 0x40292020, 0x136b: 0x40292120,
+ 0x136c: 0x40292220, 0x136d: 0x40292320, 0x136e: 0x40292420, 0x136f: 0x40292520,
+ 0x1370: 0x40292620, 0x1371: 0x40292720, 0x1372: 0x40292820, 0x1373: 0x40292920,
+ 0x1374: 0x40292a20, 0x1375: 0x40292b20, 0x1376: 0x40292c20, 0x1377: 0x40292d20,
+ 0x1378: 0x40292e20, 0x1379: 0x40292f20, 0x137a: 0x40293020, 0x137b: 0x40293120,
+ 0x137c: 0x40293220, 0x137d: 0x40293320, 0x137e: 0x40293420, 0x137f: 0x40293520,
+ // Block 0x4e, offset 0x1380
+ 0x1380: 0x40293620, 0x1381: 0x40293720, 0x1382: 0x40293820, 0x1383: 0x40293920,
+ 0x1384: 0x40293a20, 0x1385: 0x40293b20, 0x1386: 0x40293c20, 0x1387: 0x40293d20,
+ 0x1388: 0x40293e20, 0x1389: 0x40293f20, 0x138a: 0x40294020, 0x138b: 0x40294120,
+ 0x138c: 0x40294220, 0x138d: 0x40294320, 0x138e: 0x40294420, 0x138f: 0x40294520,
+ 0x1390: 0x40294620, 0x1391: 0x40294720, 0x1392: 0x40294820, 0x1393: 0x40294920,
+ 0x1394: 0x40294a20, 0x1395: 0x40294b20, 0x1396: 0x40294c20, 0x1397: 0x40294d20,
+ 0x1398: 0x40294e20, 0x1399: 0x40294f20, 0x139a: 0x40295020, 0x139b: 0x40295120,
+ 0x139c: 0x40295220, 0x139d: 0x40295320, 0x139e: 0x40295420, 0x139f: 0x40295520,
+ 0x13a0: 0x40295620, 0x13a1: 0x40295720, 0x13a2: 0x40295820, 0x13a3: 0x40295920,
+ 0x13a4: 0x40295a20, 0x13a5: 0x40295b20, 0x13a6: 0x40295c20, 0x13a7: 0x40295d20,
+ 0x13a8: 0x40295e20, 0x13a9: 0x40295f20, 0x13aa: 0x40296020, 0x13ab: 0x40296120,
+ 0x13ac: 0x40296220, 0x13ad: 0x40296320, 0x13ae: 0x40296420, 0x13af: 0x40296520,
+ 0x13b0: 0x40296620, 0x13b1: 0x40296720, 0x13b2: 0x40296820, 0x13b3: 0x40296920,
+ 0x13b4: 0x40296a20,
+ // Block 0x4f, offset 0x13c0
+ 0x13c0: 0x40011020, 0x13c1: 0x40296b20, 0x13c2: 0x40296c20, 0x13c3: 0x40296d20,
+ 0x13c4: 0x40296e20, 0x13c5: 0x40296f20, 0x13c6: 0x40297020, 0x13c7: 0x40297120,
+ 0x13c8: 0x40297220, 0x13c9: 0x40297320, 0x13ca: 0x40297420, 0x13cb: 0x40297520,
+ 0x13cc: 0x40297620, 0x13cd: 0x40297720, 0x13ce: 0x40297820, 0x13cf: 0x40297920,
+ 0x13d0: 0x40297a20, 0x13d1: 0x40297b20, 0x13d2: 0x40297c20, 0x13d3: 0x40297d20,
+ 0x13d4: 0x40297e20, 0x13d5: 0x40297f20, 0x13d6: 0x40298020, 0x13d7: 0x40298120,
+ 0x13d8: 0x40298220, 0x13d9: 0x40298320, 0x13da: 0x40298420, 0x13db: 0x40298520,
+ 0x13dc: 0x40298620, 0x13dd: 0x40298720, 0x13de: 0x40298820, 0x13df: 0x40298920,
+ 0x13e0: 0x40298a20, 0x13e1: 0x40298b20, 0x13e2: 0x40298c20, 0x13e3: 0x40298d20,
+ 0x13e4: 0x40298e20, 0x13e5: 0x40298f20, 0x13e6: 0x40299020, 0x13e7: 0x40299120,
+ 0x13e8: 0x40299220, 0x13e9: 0x40299320, 0x13ea: 0x40299420, 0x13eb: 0x40299520,
+ 0x13ec: 0x40299620, 0x13ed: 0x40299720, 0x13ee: 0x40299820, 0x13ef: 0x40299920,
+ 0x13f0: 0x40299a20, 0x13f1: 0x40299b20, 0x13f2: 0x40299c20, 0x13f3: 0x40299d20,
+ 0x13f4: 0x40299e20, 0x13f5: 0x40299f20, 0x13f6: 0x4029a020, 0x13f7: 0x4029a120,
+ 0x13f8: 0x4029a220, 0x13f9: 0x4029a320, 0x13fa: 0x4029a420, 0x13fb: 0x4029a520,
+ 0x13fc: 0x4029a620, 0x13fd: 0x4029a720, 0x13fe: 0x4029a820, 0x13ff: 0x4029a920,
+ // Block 0x50, offset 0x1400
+ 0x1400: 0x4029aa20, 0x1401: 0x4029ab20, 0x1402: 0x4029ac20, 0x1403: 0x4029ad20,
+ 0x1404: 0x4029ae20, 0x1405: 0x4029af20, 0x1406: 0x4029b020, 0x1407: 0x4029b120,
+ 0x1408: 0x4029b220, 0x1409: 0x4029b320, 0x140a: 0x4029b420, 0x140b: 0x4029b520,
+ 0x140c: 0x4029b620, 0x140d: 0x4029b720, 0x140e: 0x4029b820, 0x140f: 0x4029b920,
+ 0x1410: 0x4029ba20, 0x1411: 0x4029bb20, 0x1412: 0x4029bc20, 0x1413: 0x4029bd20,
+ 0x1414: 0x4029be20, 0x1415: 0x4029bf20, 0x1416: 0x4029c020, 0x1417: 0x4029c120,
+ 0x1418: 0x4029c220, 0x1419: 0x4029c320, 0x141a: 0x4029c420, 0x141b: 0x4029c520,
+ 0x141c: 0x4029c620, 0x141d: 0x4029c720, 0x141e: 0x4029c820, 0x141f: 0x4029c920,
+ 0x1420: 0x4029ca20, 0x1421: 0x4029cb20, 0x1422: 0x4029cc20, 0x1423: 0x4029cd20,
+ 0x1424: 0x4029ce20, 0x1425: 0x4029cf20, 0x1426: 0x4029d020, 0x1427: 0x4029d120,
+ 0x1428: 0x4029d220, 0x1429: 0x4029d320, 0x142a: 0x4029d420, 0x142b: 0x4029d520,
+ 0x142c: 0x4029d620, 0x142d: 0x4029d720, 0x142e: 0x4029d820, 0x142f: 0x4029d920,
+ 0x1430: 0x4029da20, 0x1431: 0x4029db20, 0x1432: 0x4029dc20, 0x1433: 0x4029dd20,
+ 0x1434: 0x4029de20, 0x1435: 0x4029df20, 0x1436: 0x4029e020, 0x1437: 0x4029e120,
+ 0x1438: 0x4029e220, 0x1439: 0x4029e320, 0x143a: 0x4029e420, 0x143b: 0x4029e520,
+ 0x143c: 0x4029e620, 0x143d: 0x4029e720, 0x143e: 0x4029e820, 0x143f: 0x4029e920,
+ // Block 0x51, offset 0x1440
+ 0x1440: 0x4029ea20, 0x1441: 0x4029eb20, 0x1442: 0x4029ec20, 0x1443: 0x4029ed20,
+ 0x1444: 0x4029ee20, 0x1445: 0x4029ef20, 0x1446: 0x4029f020, 0x1447: 0x4029f120,
+ 0x1448: 0x4029f220, 0x1449: 0x4029f320, 0x144a: 0x4029f420, 0x144b: 0x4029f520,
+ 0x144c: 0x4029f620, 0x144d: 0x4029f720, 0x144e: 0x4029f820, 0x144f: 0x4029f920,
+ 0x1450: 0x4029fa20, 0x1451: 0x4029fb20, 0x1452: 0x4029fc20, 0x1453: 0x4029fd20,
+ 0x1454: 0x4029fe20, 0x1455: 0x4029ff20, 0x1456: 0x402a0020, 0x1457: 0x402a0120,
+ 0x1458: 0x402a0220, 0x1459: 0x402a0320, 0x145a: 0x402a0420, 0x145b: 0x402a0520,
+ 0x145c: 0x402a0620, 0x145d: 0x402a0720, 0x145e: 0x402a0820, 0x145f: 0x402a0920,
+ 0x1460: 0x402a0a20, 0x1461: 0x402a0b20, 0x1462: 0x402a0c20, 0x1463: 0x402a0d20,
+ 0x1464: 0x402a0e20, 0x1465: 0x402a0f20, 0x1466: 0x402a1020, 0x1467: 0x402a1120,
+ 0x1468: 0x402a1220, 0x1469: 0x402a1320, 0x146a: 0x402a1420, 0x146b: 0x402a1520,
+ 0x146c: 0x402a1620, 0x146d: 0x402a1720, 0x146e: 0x402a1820, 0x146f: 0x402a1920,
+ 0x1470: 0x402a1a20, 0x1471: 0x402a1b20, 0x1472: 0x402a1c20, 0x1473: 0x402a1d20,
+ 0x1474: 0x402a1e20, 0x1475: 0x402a1f20, 0x1476: 0x402a2020, 0x1477: 0x402a2120,
+ 0x1478: 0x402a2220, 0x1479: 0x402a2320, 0x147a: 0x402a2420, 0x147b: 0x402a2520,
+ 0x147c: 0x402a2620, 0x147d: 0x402a2720, 0x147e: 0x402a2820, 0x147f: 0x402a2920,
+ // Block 0x52, offset 0x1480
+ 0x1480: 0x402a2a20, 0x1481: 0x402a2b20, 0x1482: 0x402a2c20, 0x1483: 0x402a2d20,
+ 0x1484: 0x402a2e20, 0x1485: 0x402a2f20, 0x1486: 0x402a3020, 0x1487: 0x402a3120,
+ 0x1488: 0x402a3220, 0x1489: 0x402a3320, 0x148a: 0x402a3420, 0x148b: 0x402a3520,
+ 0x148c: 0x402a3620, 0x148d: 0x402a3720, 0x148e: 0x402a3820, 0x148f: 0x402a3920,
+ 0x1490: 0x402a3a20, 0x1491: 0x402a3b20, 0x1492: 0x402a3c20, 0x1493: 0x402a3d20,
+ 0x1494: 0x402a3e20, 0x1495: 0x402a3f20, 0x1496: 0x402a4020, 0x1497: 0x402a4120,
+ 0x1498: 0x402a4220, 0x1499: 0x402a4320, 0x149a: 0x402a4420, 0x149b: 0x402a4520,
+ 0x149c: 0x402a4620, 0x149d: 0x402a4720, 0x149e: 0x402a4820, 0x149f: 0x402a4920,
+ 0x14a0: 0x402a4a20, 0x14a1: 0x402a4b20, 0x14a2: 0x402a4c20, 0x14a3: 0x402a4d20,
+ 0x14a4: 0x402a4e20, 0x14a5: 0x402a4f20, 0x14a6: 0x402a5020, 0x14a7: 0x402a5120,
+ 0x14a8: 0x402a5220, 0x14a9: 0x402a5320, 0x14aa: 0x402a5420, 0x14ab: 0x402a5520,
+ 0x14ac: 0x402a5620, 0x14ad: 0x402a5720, 0x14ae: 0x402a5820, 0x14af: 0x402a5920,
+ 0x14b0: 0x402a5a20, 0x14b1: 0x402a5b20, 0x14b2: 0x402a5c20, 0x14b3: 0x402a5d20,
+ 0x14b4: 0x402a5e20, 0x14b5: 0x402a5f20, 0x14b6: 0x402a6020, 0x14b7: 0x402a6120,
+ 0x14b8: 0x402a6220, 0x14b9: 0x402a6320, 0x14ba: 0x402a6420, 0x14bb: 0x402a6520,
+ 0x14bc: 0x402a6620, 0x14bd: 0x402a6720, 0x14be: 0x402a6820, 0x14bf: 0x402a6920,
+ // Block 0x53, offset 0x14c0
+ 0x14c0: 0x402a6a20, 0x14c1: 0x402a6b20, 0x14c2: 0x402a6c20, 0x14c3: 0x402a6d20,
+ 0x14c4: 0x402a6e20, 0x14c5: 0x402a6f20, 0x14c6: 0x402a7020, 0x14c7: 0x402a7120,
+ 0x14c8: 0x402a7220, 0x14c9: 0x402a7320, 0x14ca: 0x402a7420, 0x14cb: 0x402a7520,
+ 0x14cc: 0x402a7620, 0x14cd: 0x402a7720, 0x14ce: 0x402a7820, 0x14cf: 0x402a7920,
+ 0x14d0: 0x402a7a20, 0x14d1: 0x402a7b20, 0x14d2: 0x402a7c20, 0x14d3: 0x402a7d20,
+ 0x14d4: 0x402a7e20, 0x14d5: 0x402a7f20, 0x14d6: 0x402a8020, 0x14d7: 0x402a8120,
+ 0x14d8: 0x402a8220, 0x14d9: 0x402a8320, 0x14da: 0x402a8420, 0x14db: 0x402a8520,
+ 0x14dc: 0x402a8620, 0x14dd: 0x402a8720, 0x14de: 0x402a8820, 0x14df: 0x402a8920,
+ 0x14e0: 0x402a8a20, 0x14e1: 0x402a8b20, 0x14e2: 0x402a8c20, 0x14e3: 0x402a8d20,
+ 0x14e4: 0x402a8e20, 0x14e5: 0x402a8f20, 0x14e6: 0x402a9020, 0x14e7: 0x402a9120,
+ 0x14e8: 0x402a9220, 0x14e9: 0x402a9320, 0x14ea: 0x402a9420, 0x14eb: 0x402a9520,
+ 0x14ec: 0x402a9620, 0x14ed: 0x402a9720, 0x14ee: 0x402a9820, 0x14ef: 0x402a9920,
+ 0x14f0: 0x402a9a20, 0x14f1: 0x402a9b20, 0x14f2: 0x402a9c20, 0x14f3: 0x402a9d20,
+ 0x14f4: 0x402a9e20, 0x14f5: 0x402a9f20, 0x14f6: 0x402aa020, 0x14f7: 0x402aa120,
+ 0x14f8: 0x402aa220, 0x14f9: 0x402aa320, 0x14fa: 0x402aa420, 0x14fb: 0x402aa520,
+ 0x14fc: 0x402aa620, 0x14fd: 0x402aa720, 0x14fe: 0x402aa820, 0x14ff: 0x402aa920,
+ // Block 0x54, offset 0x1500
+ 0x1500: 0x402aaa20, 0x1501: 0x402aab20, 0x1502: 0x402aac20, 0x1503: 0x402aad20,
+ 0x1504: 0x402aae20, 0x1505: 0x402aaf20, 0x1506: 0x402ab020, 0x1507: 0x402ab120,
+ 0x1508: 0x402ab220, 0x1509: 0x402ab320, 0x150a: 0x402ab420, 0x150b: 0x402ab520,
+ 0x150c: 0x402ab620, 0x150d: 0x402ab720, 0x150e: 0x402ab820, 0x150f: 0x402ab920,
+ 0x1510: 0x402aba20, 0x1511: 0x402abb20, 0x1512: 0x402abc20, 0x1513: 0x402abd20,
+ 0x1514: 0x402abe20, 0x1515: 0x402abf20, 0x1516: 0x402ac020, 0x1517: 0x402ac120,
+ 0x1518: 0x402ac220, 0x1519: 0x402ac320, 0x151a: 0x402ac420, 0x151b: 0x402ac520,
+ 0x151c: 0x402ac620, 0x151d: 0x402ac720, 0x151e: 0x402ac820, 0x151f: 0x402ac920,
+ 0x1520: 0x402aca20, 0x1521: 0x402acb20, 0x1522: 0x402acc20, 0x1523: 0x402acd20,
+ 0x1524: 0x402ace20, 0x1525: 0x402acf20, 0x1526: 0x402ad020, 0x1527: 0x402ad120,
+ 0x1528: 0x402ad220, 0x1529: 0x402ad320, 0x152a: 0x402ad420, 0x152b: 0x402ad520,
+ 0x152c: 0x402ad620, 0x152d: 0x402ad720, 0x152e: 0x402ad820, 0x152f: 0x402ad920,
+ 0x1530: 0x402ada20, 0x1531: 0x402adb20, 0x1532: 0x402adc20, 0x1533: 0x402add20,
+ 0x1534: 0x402ade20, 0x1535: 0x402adf20, 0x1536: 0x402ae020, 0x1537: 0x402ae120,
+ 0x1538: 0x402ae220, 0x1539: 0x402ae320, 0x153a: 0x402ae420, 0x153b: 0x402ae520,
+ 0x153c: 0x402b1820, 0x153d: 0x402ae620, 0x153e: 0x402ae820, 0x153f: 0x402ae920,
+ // Block 0x55, offset 0x1540
+ 0x1540: 0x402aea20, 0x1541: 0x402aeb20, 0x1542: 0x402aec20, 0x1543: 0x402aed20,
+ 0x1544: 0x402aee20, 0x1545: 0x402aef20, 0x1546: 0x402af020, 0x1547: 0x402af120,
+ 0x1548: 0x402af220, 0x1549: 0x402af320, 0x154a: 0x402af420, 0x154b: 0x402af520,
+ 0x154c: 0x402af620, 0x154d: 0x402af720, 0x154e: 0x402af920, 0x154f: 0x402afa20,
+ 0x1550: 0x402afb20, 0x1551: 0x402afc20, 0x1552: 0x402afd20, 0x1553: 0x402afe20,
+ 0x1554: 0x402aff20, 0x1555: 0x402b0020, 0x1556: 0x402b0720, 0x1557: 0x402b0820,
+ 0x1558: 0x402b0920, 0x1559: 0x402b0a20, 0x155a: 0x402b0b20, 0x155b: 0x402b0c20,
+ 0x155c: 0x402b0d20, 0x155d: 0x402b0e20, 0x155e: 0x402b0f20, 0x155f: 0x402b1020,
+ 0x1560: 0x402b1120, 0x1561: 0x402b1220, 0x1562: 0x402b1320, 0x1563: 0x402b1420,
+ 0x1564: 0x402b1520, 0x1565: 0x402b1620, 0x1566: 0x402b1720, 0x1567: 0x402b1920,
+ 0x1568: 0x402b1a20, 0x1569: 0x402b1b20, 0x156a: 0x402b1c20, 0x156b: 0x402b1d20,
+ 0x156c: 0x402b1e20, 0x156d: 0x402b1f20, 0x156e: 0x402b2020, 0x156f: 0x402b2120,
+ 0x1570: 0x402b2220, 0x1571: 0x402b2320, 0x1572: 0x402b2420, 0x1573: 0x402b2520,
+ 0x1574: 0x402b2620, 0x1575: 0x402b2720, 0x1576: 0x402b2820, 0x1577: 0x402b2920,
+ 0x1578: 0x402b2a20, 0x1579: 0x402b2b20, 0x157a: 0x402b2c20, 0x157b: 0x402b2d20,
+ 0x157c: 0x402b2e20, 0x157d: 0x402b2f20, 0x157e: 0x402b3020, 0x157f: 0x402b3120,
+ // Block 0x56, offset 0x1580
+ 0x1580: 0x402b3220, 0x1581: 0x402b3320, 0x1582: 0x402b3420, 0x1583: 0x402b3520,
+ 0x1584: 0x402b3620, 0x1585: 0x402b3720, 0x1586: 0x402b3820, 0x1587: 0x402b3920,
+ 0x1588: 0x402b3a20, 0x1589: 0x402b3b20, 0x158a: 0x402b3c20, 0x158b: 0x402b3d20,
+ 0x158c: 0x402b3e20, 0x158d: 0x402b3f20, 0x158e: 0x402b4020, 0x158f: 0x402b4120,
+ 0x1590: 0x402b4220, 0x1591: 0x402b4320, 0x1592: 0x402b4420, 0x1593: 0x402b4520,
+ 0x1594: 0x402b4620, 0x1595: 0x402b4720, 0x1596: 0x402b4820, 0x1597: 0x402b4920,
+ 0x1598: 0x402b4a20, 0x1599: 0x402b4b20, 0x159a: 0x402b4c20, 0x159b: 0x402b4d20,
+ 0x159c: 0x402b4e20, 0x159d: 0x402b4f20, 0x159e: 0x402b5020, 0x159f: 0x402b5120,
+ 0x15a0: 0x402b5220, 0x15a1: 0x402b5320, 0x15a2: 0x402b5420, 0x15a3: 0x402b5520,
+ 0x15a4: 0x402b5620, 0x15a5: 0x402b5720, 0x15a6: 0x402b5820, 0x15a7: 0x402b5920,
+ 0x15a8: 0x402b5a20, 0x15a9: 0x402b5b20, 0x15aa: 0x402b5c20, 0x15ab: 0x402b5d20,
+ 0x15ac: 0x402b5e20, 0x15ad: 0x402b5f20, 0x15ae: 0x402b6020, 0x15af: 0x402b6120,
+ 0x15b0: 0x402b6220, 0x15b1: 0x402b6320, 0x15b2: 0x402b6420, 0x15b3: 0x402b6520,
+ 0x15b4: 0x402b6620, 0x15b5: 0x402b6720, 0x15b6: 0x402b6820, 0x15b7: 0x402b6920,
+ 0x15b8: 0x402b6a20, 0x15b9: 0x402b6b20, 0x15ba: 0x402b6c20, 0x15bb: 0x402b6d20,
+ 0x15bc: 0x402b6e20, 0x15bd: 0x402b6f20, 0x15be: 0x402b7020, 0x15bf: 0x402b7120,
+ // Block 0x57, offset 0x15c0
+ 0x15c0: 0x402b7220, 0x15c1: 0x402b7320, 0x15c2: 0x402b7420, 0x15c3: 0x402b7520,
+ 0x15c4: 0x402b7620, 0x15c5: 0x402b7720, 0x15c6: 0x402b7820, 0x15c7: 0x402b7920,
+ 0x15c8: 0x402b7a20, 0x15c9: 0x402b7b20, 0x15ca: 0x402b7c20, 0x15cb: 0x402b7d20,
+ 0x15cc: 0x402b7e20, 0x15cd: 0x402b7f20, 0x15ce: 0x402b8020, 0x15cf: 0x402b8120,
+ 0x15d0: 0x402b8220, 0x15d1: 0x402b8320, 0x15d2: 0x402b8420, 0x15d3: 0x402b8520,
+ 0x15d4: 0x402b8620, 0x15d5: 0x402b8720, 0x15d6: 0x402b8820, 0x15d7: 0x402b8920,
+ 0x15d8: 0x402b8a20, 0x15d9: 0x402b8b20, 0x15da: 0x402b8c20, 0x15db: 0x402b8d20,
+ 0x15dc: 0x402b8e20, 0x15dd: 0x402b8f20, 0x15de: 0x402b9020, 0x15df: 0x402b9120,
+ 0x15e0: 0x402b9220, 0x15e1: 0x402b9320, 0x15e2: 0x402b9420, 0x15e3: 0x402b9520,
+ 0x15e4: 0x402b9620, 0x15e5: 0x402b9720, 0x15e6: 0x402b9820, 0x15e7: 0x402b9920,
+ 0x15e8: 0x402b9a20, 0x15e9: 0x402b9b20, 0x15ea: 0x402b9c20, 0x15eb: 0x402b9d20,
+ 0x15ec: 0x402b9e20, 0x15ed: 0x402b9f20, 0x15ee: 0x402ba020, 0x15ef: 0x402ba120,
+ 0x15f0: 0x402ba220, 0x15f1: 0x402ba320, 0x15f2: 0x402ba420, 0x15f3: 0x402ba520,
+ 0x15f4: 0x402ba620, 0x15f5: 0x402ba720, 0x15f6: 0x402ba820, 0x15f7: 0x402ba920,
+ 0x15f8: 0x402baa20, 0x15f9: 0x402bab20, 0x15fa: 0x402bac20, 0x15fb: 0x402bad20,
+ 0x15fc: 0x402bae20, 0x15fd: 0x402baf20, 0x15fe: 0x402bb020, 0x15ff: 0x402bb120,
+ // Block 0x58, offset 0x1600
+ 0x1600: 0x402bb220, 0x1601: 0x402bb320, 0x1602: 0x402bb420, 0x1603: 0x402bb520,
+ 0x1604: 0x402bb620, 0x1605: 0x402bb720, 0x1606: 0x402bb820, 0x1607: 0x402bb920,
+ 0x1608: 0x402bba20, 0x1609: 0x402bbb20, 0x160a: 0x402bbc20, 0x160b: 0x402bbd20,
+ 0x160c: 0x402bbe20, 0x160d: 0x402bbf20, 0x160e: 0x402bc020, 0x160f: 0x402bc120,
+ 0x1610: 0x402bc220, 0x1611: 0x402bc320, 0x1612: 0x402bc420, 0x1613: 0x402bc520,
+ 0x1614: 0x402bc620, 0x1615: 0x402bc720, 0x1616: 0x402bc820, 0x1617: 0x402bc920,
+ 0x1618: 0x402bca20, 0x1619: 0x402bcb20, 0x161a: 0x402bcc20, 0x161b: 0x402bcd20,
+ 0x161c: 0x402bce20, 0x161d: 0x402bcf20, 0x161e: 0x402bd020, 0x161f: 0x402bd120,
+ 0x1620: 0x402bd220, 0x1621: 0x402bd320, 0x1622: 0x402bd420, 0x1623: 0x402bd520,
+ 0x1624: 0x402bd620, 0x1625: 0x402bd720, 0x1626: 0x402bd820, 0x1627: 0x402bd920,
+ 0x1628: 0x402bda20, 0x1629: 0x402bdb20, 0x162a: 0x402bdc20, 0x162b: 0x402bdd20,
+ 0x162c: 0x402bde20, 0x162d: 0x4002b620, 0x162e: 0x40017320, 0x162f: 0x402ae720,
+ 0x1630: 0x402af820, 0x1631: 0x402b0120, 0x1632: 0x402b0220, 0x1633: 0x402b0320,
+ 0x1634: 0x402b0420, 0x1635: 0x402b0520, 0x1636: 0x402b0620, 0x1637: 0x402bdf20,
+ 0x1638: 0x402be020, 0x1639: 0x402be120, 0x163a: 0x402be220, 0x163b: 0x402be320,
+ 0x163c: 0x402be420, 0x163d: 0x402be520, 0x163e: 0x402be620, 0x163f: 0x402be720,
+ // Block 0x59, offset 0x1640
+ 0x1640: 0x40010a20, 0x1641: 0x402c2e20, 0x1642: 0x402c2f20, 0x1643: 0x402c3020,
+ 0x1644: 0x402c3120, 0x1645: 0x402c3220, 0x1646: 0x402c3320, 0x1647: 0x402c3420,
+ 0x1648: 0x402c3520, 0x1649: 0x402c3620, 0x164a: 0x402c3720, 0x164b: 0x402c3820,
+ 0x164c: 0x402c3920, 0x164d: 0x402c3a20, 0x164e: 0x402c3b20, 0x164f: 0x402c3c20,
+ 0x1650: 0x402c3d20, 0x1651: 0x402c3e20, 0x1652: 0x402c3f20, 0x1653: 0x402c4020,
+ 0x1654: 0x402c4120, 0x1655: 0x402c4220, 0x1656: 0x402c4320, 0x1657: 0x402c4420,
+ 0x1658: 0x402c4520, 0x1659: 0x402c4620, 0x165a: 0x402c4720, 0x165b: 0x4001f320,
+ 0x165c: 0x4001f420,
+ 0x1660: 0x402c4820, 0x1661: 0xe0001064, 0x1662: 0x402c4920, 0x1663: 0x402c6520,
+ 0x1664: 0xe0001067, 0x1665: 0xe000106a, 0x1666: 0x402c4a20, 0x1667: 0xe000106d,
+ 0x1668: 0x402c4b20, 0x1669: 0xe0001073, 0x166a: 0x402c6320, 0x166b: 0x402c6420,
+ 0x166c: 0xe0001076, 0x166d: 0xe0001079, 0x166e: 0xe000107c, 0x166f: 0x402c4c20,
+ 0x1670: 0x402c4d20, 0x1671: 0x402c4e20, 0x1672: 0x402c4f20, 0x1673: 0xe000107f,
+ 0x1674: 0xe0001082, 0x1675: 0xe0001085, 0x1676: 0xe0001088, 0x1677: 0x402c5020,
+ 0x1678: 0x402c6820, 0x1679: 0x402c5120, 0x167a: 0x402c5220, 0x167b: 0xe000108e,
+ 0x167c: 0xe0001091, 0x167d: 0xe0001094, 0x167e: 0x402c5320, 0x167f: 0xe0001097,
+ // Block 0x5a, offset 0x1680
+ 0x1680: 0xe000109a, 0x1681: 0x402c5420, 0x1682: 0xe000109d, 0x1683: 0x402c5520,
+ 0x1684: 0xe00010a0, 0x1685: 0x402c5620, 0x1686: 0xe00010a3, 0x1687: 0x402c5720,
+ 0x1688: 0x402c5820, 0x1689: 0x402c5920, 0x168a: 0x402c5a20, 0x168b: 0xe00010ac,
+ 0x168c: 0xe00010b2, 0x168d: 0xe00010b5, 0x168e: 0xe00010b8, 0x168f: 0x402c5b20,
+ 0x1690: 0xe00010bb, 0x1691: 0xe00010be, 0x1692: 0x402c5c20, 0x1693: 0xe00010c1,
+ 0x1694: 0xe00010c4, 0x1695: 0xe00010a9, 0x1696: 0x402c5d20, 0x1697: 0x402c5e20,
+ 0x1698: 0xe00010c7, 0x1699: 0xe00010ca, 0x169a: 0x402c5f20, 0x169b: 0xe00010d2,
+ 0x169c: 0x402c6020, 0x169d: 0xe00010d5, 0x169e: 0x402c6120, 0x169f: 0x402c6220,
+ 0x16a0: 0x402c6620, 0x16a1: 0x402c6a20, 0x16a2: 0x402c6b20, 0x16a3: 0x402c6720,
+ 0x16a4: 0x402c6920, 0x16a5: 0x402c6c20, 0x16a6: 0x402c6d20, 0x16a7: 0xe00010d8,
+ 0x16a8: 0xe00010db, 0x16a9: 0xe000108b, 0x16aa: 0xe00010af, 0x16ab: 0x40015420,
+ 0x16ac: 0x40015520, 0x16ad: 0x40015620, 0x16ae: 0xe00010a6, 0x16af: 0xe00010cd,
+ 0x16b0: 0xe0001070,
+ // Block 0x5b, offset 0x16c0
+ 0x16c0: 0x40254620, 0x16c1: 0x40254720, 0x16c2: 0x40254820, 0x16c3: 0x40254920,
+ 0x16c4: 0x40254a20, 0x16c5: 0x40254b20, 0x16c6: 0x40254c20, 0x16c7: 0x40254d20,
+ 0x16c8: 0x40254e20, 0x16c9: 0x40254f20, 0x16ca: 0x40255020, 0x16cb: 0x40255120,
+ 0x16cc: 0x40255220, 0x16ce: 0x40255320, 0x16cf: 0x40255420,
+ 0x16d0: 0x40255520, 0x16d1: 0x40255620, 0x16d2: 0x40255720, 0x16d3: 0x40255820,
+ 0x16d4: 0x40255920,
+ 0x16e0: 0x40255a20, 0x16e1: 0x40255b20, 0x16e2: 0x40255c20, 0x16e3: 0x40255d20,
+ 0x16e4: 0x40255e20, 0x16e5: 0x40255f20, 0x16e6: 0x40256020, 0x16e7: 0x40256120,
+ 0x16e8: 0x40256220, 0x16e9: 0x40256320, 0x16ea: 0x40256420, 0x16eb: 0x40256520,
+ 0x16ec: 0x40256620, 0x16ed: 0x40256720, 0x16ee: 0x40256820, 0x16ef: 0x40256920,
+ 0x16f0: 0x40256a20, 0x16f1: 0x40256b20, 0x16f2: 0x40256c20, 0x16f3: 0x40256d20,
+ 0x16f4: 0x40256e20, 0x16f5: 0x40018620, 0x16f6: 0x40018720,
+ // Block 0x5c, offset 0x1700
+ 0x1700: 0x40256f20, 0x1701: 0x40257020, 0x1702: 0x40257120, 0x1703: 0x40257220,
+ 0x1704: 0x40257320, 0x1705: 0x40257420, 0x1706: 0x40257520, 0x1707: 0x40257620,
+ 0x1708: 0x40257720, 0x1709: 0x40257820, 0x170a: 0x40257920, 0x170b: 0x40257a20,
+ 0x170c: 0x40257b20, 0x170d: 0x40257c20, 0x170e: 0x40257d20, 0x170f: 0x40257e20,
+ 0x1710: 0x40257f20, 0x1711: 0x40258020, 0x1712: 0x40258120, 0x1713: 0x40258220,
+ 0x1720: 0x40258320, 0x1721: 0x40258420, 0x1722: 0x40258520, 0x1723: 0x40258620,
+ 0x1724: 0x40258720, 0x1725: 0x40258820, 0x1726: 0x40258920, 0x1727: 0x40258a20,
+ 0x1728: 0x40258b20, 0x1729: 0x40258c20, 0x172a: 0x40258d20, 0x172b: 0x40258e20,
+ 0x172c: 0x40258f20, 0x172e: 0x40259020, 0x172f: 0x40259120,
+ 0x1730: 0x40259220, 0x1732: 0x40259320, 0x1733: 0x40259420,
+ // Block 0x5d, offset 0x1740
+ 0x1740: 0x4026ab20, 0x1741: 0x4026ac20, 0x1742: 0x4026ad20, 0x1743: 0x4026ae20,
+ 0x1744: 0x4026af20, 0x1745: 0x4026b020, 0x1746: 0x4026b120, 0x1747: 0x4026b220,
+ 0x1748: 0x4026b320, 0x1749: 0x4026b420, 0x174a: 0x4026b520, 0x174b: 0x4026b620,
+ 0x174c: 0x4026b720, 0x174d: 0x4026b820, 0x174e: 0x4026b920, 0x174f: 0x4026ba20,
+ 0x1750: 0x4026bb20, 0x1751: 0x4026bc20, 0x1752: 0x4026bd20, 0x1753: 0x4026be20,
+ 0x1754: 0x4026bf20, 0x1755: 0x4026c020, 0x1756: 0x4026c120, 0x1757: 0x4026c220,
+ 0x1758: 0x4026c320, 0x1759: 0x4026c420, 0x175a: 0x4026c520, 0x175b: 0x4026c620,
+ 0x175c: 0x4026c720, 0x175d: 0x4026c820, 0x175e: 0x4026c920, 0x175f: 0x4026ca20,
+ 0x1760: 0x4026cb20, 0x1761: 0x4026cc20, 0x1762: 0x4026cd20, 0x1763: 0x4026cf20,
+ 0x1764: 0x4026d020, 0x1765: 0x4026d120, 0x1766: 0x4026d220, 0x1767: 0x4026d320,
+ 0x1768: 0x4026d420, 0x1769: 0x4026d520, 0x176a: 0x4026d620, 0x176b: 0x4026d720,
+ 0x176c: 0x4026d820, 0x176d: 0x4026d920, 0x176e: 0x4026da20, 0x176f: 0x4026db20,
+ 0x1770: 0x4026dc20, 0x1771: 0x4026dd20, 0x1772: 0x4026de20, 0x1773: 0x4026df20,
+ 0x1774: 0x4026e020, 0x1775: 0x4026e120, 0x1776: 0x4026e220, 0x1777: 0x4026e320,
+ 0x1778: 0x4026e420, 0x1779: 0x4026e520, 0x177a: 0x4026e620, 0x177b: 0x4026e720,
+ 0x177c: 0x4026e820, 0x177d: 0x4026e920, 0x177e: 0x4026ea20, 0x177f: 0x4026eb20,
+ // Block 0x5e, offset 0x1780
+ 0x1780: 0x4026ec20, 0x1781: 0x4026ed20, 0x1782: 0x4026ee20, 0x1783: 0x4026ef20,
+ 0x1784: 0x4026f020, 0x1785: 0x4026f120, 0x1786: 0x80013702, 0x1787: 0x80013802,
+ 0x1788: 0x80013902, 0x1789: 0x80013a02, 0x178a: 0x80013b02, 0x178b: 0x80005f02,
+ 0x178c: 0x80005f02, 0x178d: 0x80005f02, 0x178e: 0x80005f02, 0x178f: 0x80005f02,
+ 0x1790: 0x80005f02, 0x1791: 0x80005f02, 0x1792: 0x4026f220, 0x1793: 0x80000000,
+ 0x1794: 0x40018b20, 0x1795: 0x40018c20, 0x1796: 0x40015120, 0x1797: 0x40031f20,
+ 0x1798: 0x4002aa20, 0x1799: 0x4002ab20, 0x179a: 0x4002ac20, 0x179b: 0x4013b020,
+ 0x179c: 0x4026ce20, 0x179d: 0x80005f02,
+ 0x17a0: 0xe0000075, 0x17a1: 0xe00000f9, 0x17a2: 0xe00001e0, 0x17a3: 0xe00002a6,
+ 0x17a4: 0xe0000363, 0x17a5: 0xe000041d, 0x17a6: 0xe00004d4, 0x17a7: 0xe0000570,
+ 0x17a8: 0xe000060c, 0x17a9: 0xe00006a5,
+ 0x17b0: 0xe0000078, 0x17b1: 0xe00000fc, 0x17b2: 0xe00001e3, 0x17b3: 0xe00002a9,
+ 0x17b4: 0xe0000366, 0x17b5: 0xe0000420, 0x17b6: 0xe00004d7, 0x17b7: 0xe0000573,
+ 0x17b8: 0xe000060f, 0x17b9: 0xe00006a8,
+ // Block 0x5f, offset 0x17c0
+ 0x17c0: 0x40028320, 0x17c1: 0x40016c20, 0x17c2: 0x40012620, 0x17c3: 0x40017120,
+ 0x17c4: 0x40014f20, 0x17c5: 0x40015020, 0x17c6: 0x40011220, 0x17c7: 0x40011320,
+ 0x17c8: 0x40012720, 0x17c9: 0x40017220, 0x17ca: 0x80000000, 0x17cb: 0x80000000,
+ 0x17cc: 0x80000000, 0x17cd: 0x80000000, 0x17ce: 0x40010620,
+ 0x17d0: 0xe0000087, 0x17d1: 0xe000010b, 0x17d2: 0xe00001f2, 0x17d3: 0xe00002b8,
+ 0x17d4: 0xe0000375, 0x17d5: 0xe000042f, 0x17d6: 0xe00004e6, 0x17d7: 0xe0000582,
+ 0x17d8: 0xe000061e, 0x17d9: 0xe00006b7,
+ 0x17e0: 0x40287720, 0x17e1: 0x40287920, 0x17e2: 0x40287c20, 0x17e3: 0x40288220,
+ 0x17e4: 0x40288420, 0x17e5: 0x40288720, 0x17e6: 0x40288920, 0x17e7: 0x40288c20,
+ 0x17e8: 0x40288d20, 0x17e9: 0x40288e20, 0x17ea: 0x40289320, 0x17eb: 0x40289520,
+ 0x17ec: 0x40289820, 0x17ed: 0x40289a20, 0x17ee: 0x40289f20, 0x17ef: 0x4028a120,
+ 0x17f0: 0x4028a220, 0x17f1: 0x4028a320, 0x17f2: 0x4028aa20, 0x17f3: 0x4028ad20,
+ 0x17f4: 0x4028b020, 0x17f5: 0x4028b520, 0x17f6: 0x4028b920, 0x17f7: 0x4028bc20,
+ 0x17f8: 0x4028be20, 0x17f9: 0x4028c020, 0x17fa: 0x4028c320, 0x17fb: 0x4028c820,
+ 0x17fc: 0x4028c920, 0x17fd: 0x4028cc20, 0x17fe: 0x4028d020, 0x17ff: 0x4028d320,
+ // Block 0x60, offset 0x1800
+ 0x1800: 0x4028d420, 0x1801: 0x4028d520, 0x1802: 0x4028d620, 0x1803: 0x40287620,
+ 0x1804: 0x40287a20, 0x1805: 0x40287d20, 0x1806: 0x40288320, 0x1807: 0x40288520,
+ 0x1808: 0x40288820, 0x1809: 0x40288a20, 0x180a: 0x40288f20, 0x180b: 0x40289420,
+ 0x180c: 0x40289620, 0x180d: 0x40289920, 0x180e: 0x40289b20, 0x180f: 0x4028a020,
+ 0x1810: 0x4028ab20, 0x1811: 0x4028ae20, 0x1812: 0x4028b120, 0x1813: 0x4028b620,
+ 0x1814: 0x4028ca20, 0x1815: 0x4028ba20, 0x1816: 0x4028bf20, 0x1817: 0x4028c420,
+ 0x1818: 0x4028ce20, 0x1819: 0x4028d120, 0x181a: 0x4028d720, 0x181b: 0x4028d820,
+ 0x181c: 0x4028b320, 0x181d: 0x40287b20, 0x181e: 0x40287e20, 0x181f: 0x40288120,
+ 0x1820: 0x40288b20, 0x1821: 0x40288620, 0x1822: 0x40289020, 0x1823: 0x4028c520,
+ 0x1824: 0x40289c20, 0x1825: 0x40289e20, 0x1826: 0x40289720, 0x1827: 0x4028a420,
+ 0x1828: 0x4028ac20, 0x1829: 0x4028af20, 0x182a: 0x4028b720, 0x182b: 0x4028c120,
+ 0x182c: 0x4028cf20, 0x182d: 0x4028d220, 0x182e: 0x4028cb20, 0x182f: 0x4028cd20,
+ 0x1830: 0x4028d920, 0x1831: 0x4028b220, 0x1832: 0x4028bb20, 0x1833: 0x40287f20,
+ 0x1834: 0x4028c620, 0x1835: 0x4028bd20, 0x1836: 0x4028c220, 0x1837: 0x4028b820,
+ // Block 0x61, offset 0x1840
+ 0x1840: 0x40286f20, 0x1841: 0x40287020, 0x1842: 0x40287120, 0x1843: 0x40287220,
+ 0x1844: 0x40287320, 0x1845: 0x40287420, 0x1846: 0x40287520, 0x1847: 0x40287820,
+ 0x1848: 0x40288020, 0x1849: 0x4028c720, 0x184a: 0x40289120, 0x184b: 0x4028b420,
+ 0x184c: 0x4028da20, 0x184d: 0x4028dc20, 0x184e: 0x4028dd20, 0x184f: 0x4028df20,
+ 0x1850: 0x4028e020, 0x1851: 0x4028e320, 0x1852: 0x4028e520, 0x1853: 0x4028e620,
+ 0x1854: 0x4028e820, 0x1855: 0x4028ea20, 0x1856: 0x4028ec20, 0x1857: 0x4028ed20,
+ 0x1858: 0x4028e120, 0x1859: 0x4028eb20, 0x185a: 0x40289d20, 0x185b: 0x40289220,
+ 0x185c: 0x4028a520, 0x185d: 0x4028a620, 0x185e: 0x4028db20, 0x185f: 0x4028de20,
+ 0x1860: 0x4028e220, 0x1861: 0x4028e420, 0x1862: 0x4028a720, 0x1863: 0x4028e920,
+ 0x1864: 0x4028a820, 0x1865: 0x4028a920, 0x1866: 0x4028ee20, 0x1867: 0x4028ef20,
+ 0x1868: 0x4028e720, 0x1869: 0x4028f120, 0x186a: 0x4028f020,
+ 0x1870: 0x402be820, 0x1871: 0x402be920, 0x1872: 0x402bea20, 0x1873: 0x402beb20,
+ 0x1874: 0x402bec20, 0x1875: 0x402bed20, 0x1876: 0x402bee20, 0x1877: 0x402bef20,
+ 0x1878: 0x402bf020, 0x1879: 0x402bf120, 0x187a: 0x402bf220, 0x187b: 0x402bf320,
+ 0x187c: 0x402bf420, 0x187d: 0x402bf520, 0x187e: 0x402bf620, 0x187f: 0x402bf720,
+ // Block 0x62, offset 0x1880
+ 0x1880: 0x402bf820, 0x1881: 0x402bf920, 0x1882: 0x402bfa20, 0x1883: 0x402bfb20,
+ 0x1884: 0x402bfc20, 0x1885: 0x402bfd20, 0x1886: 0x402bfe20, 0x1887: 0x402bff20,
+ 0x1888: 0x402c0020, 0x1889: 0x402c0120, 0x188a: 0x402c0220, 0x188b: 0x402c0320,
+ 0x188c: 0x402c0420, 0x188d: 0x402c0520, 0x188e: 0x402c0620, 0x188f: 0x402c0720,
+ 0x1890: 0x402c0820, 0x1891: 0x402c0920, 0x1892: 0x402c0a20, 0x1893: 0x402c0b20,
+ 0x1894: 0x402c0c20, 0x1895: 0x402c0d20, 0x1896: 0x402c0e20, 0x1897: 0x402c0f20,
+ 0x1898: 0x402c1020, 0x1899: 0x402c1120, 0x189a: 0x402c1220, 0x189b: 0x402c1320,
+ 0x189c: 0x402c1420, 0x189d: 0x402c1520, 0x189e: 0x402c1620, 0x189f: 0x402c1720,
+ 0x18a0: 0x402c1820, 0x18a1: 0x402c1920, 0x18a2: 0x402c1a20, 0x18a3: 0x402c1b20,
+ 0x18a4: 0x402c1c20, 0x18a5: 0x402c1d20, 0x18a6: 0x402c1e20, 0x18a7: 0x402c1f20,
+ 0x18a8: 0x402c2020, 0x18a9: 0x402c2120, 0x18aa: 0x402c2220, 0x18ab: 0x402c2320,
+ 0x18ac: 0x402c2420, 0x18ad: 0x402c2520, 0x18ae: 0x402c2620, 0x18af: 0x402c2720,
+ 0x18b0: 0x402c2820, 0x18b1: 0x402c2920, 0x18b2: 0x402c2a20, 0x18b3: 0x402c2b20,
+ 0x18b4: 0x402c2c20, 0x18b5: 0x402c2d20,
+ // Block 0x63, offset 0x18c0
+ 0x18c0: 0x40251420, 0x18c1: 0x40251520, 0x18c2: 0x40251620, 0x18c3: 0x40251720,
+ 0x18c4: 0x40251820, 0x18c5: 0x40251920, 0x18c6: 0x40251a20, 0x18c7: 0x40251b20,
+ 0x18c8: 0x40251c20, 0x18c9: 0x40251d20, 0x18ca: 0x40251e20, 0x18cb: 0x40251f20,
+ 0x18cc: 0x40252020, 0x18cd: 0x40252120, 0x18ce: 0x40252220, 0x18cf: 0x40252320,
+ 0x18d0: 0x40252420, 0x18d1: 0x40252520, 0x18d2: 0x40252620, 0x18d3: 0x40252720,
+ 0x18d4: 0x40252820, 0x18d5: 0x40252920, 0x18d6: 0x40252a20, 0x18d7: 0x40252b20,
+ 0x18d8: 0x40252c20, 0x18d9: 0x40252d20, 0x18da: 0x40252e20, 0x18db: 0x40252f20,
+ 0x18dc: 0x40253020,
+ 0x18e0: 0x40253120, 0x18e1: 0x40253220, 0x18e2: 0x40253320, 0x18e3: 0x40253420,
+ 0x18e4: 0x40253520, 0x18e5: 0x40253620, 0x18e6: 0x40253720, 0x18e7: 0x40253820,
+ 0x18e8: 0x40253920, 0x18e9: 0x40253a20, 0x18ea: 0x40253b20, 0x18eb: 0x40253c20,
+ 0x18f0: 0x40253d20, 0x18f1: 0x40253e20, 0x18f2: 0x40253f20, 0x18f3: 0x40254020,
+ 0x18f4: 0x40254120, 0x18f5: 0x40254220, 0x18f6: 0x40254320, 0x18f7: 0x40254420,
+ 0x18f8: 0x40254520, 0x18f9: 0x80014502, 0x18fa: 0x80014602, 0x18fb: 0x80014702,
+ // Block 0x64, offset 0x1900
+ 0x1900: 0x40031920,
+ 0x1904: 0x40015c20, 0x1905: 0x40016420, 0x1906: 0xe0000051, 0x1907: 0xe00000d2,
+ 0x1908: 0xe00001bc, 0x1909: 0xe0000282, 0x190a: 0xe000033f, 0x190b: 0xe00003f9,
+ 0x190c: 0xe00004b0, 0x190d: 0xe000054c, 0x190e: 0xe00005e8, 0x190f: 0xe0000681,
+ 0x1910: 0x4026f320, 0x1911: 0x4026f420, 0x1912: 0x4026f520, 0x1913: 0x4026f620,
+ 0x1914: 0x4026f720, 0x1915: 0x4026f820, 0x1916: 0x4026f920, 0x1917: 0x4026fa20,
+ 0x1918: 0x4026fb20, 0x1919: 0x4026fc20, 0x191a: 0x4026fd20, 0x191b: 0x4026fe20,
+ 0x191c: 0x4026ff20, 0x191d: 0x40270020, 0x191e: 0x40270120, 0x191f: 0x40270220,
+ 0x1920: 0x40270320, 0x1921: 0x40270420, 0x1922: 0x40270520, 0x1923: 0x40270620,
+ 0x1924: 0x40270720, 0x1925: 0x40270820, 0x1926: 0x40270920, 0x1927: 0x40270a20,
+ 0x1928: 0x40270b20, 0x1929: 0x40270c20, 0x192a: 0x40270d20, 0x192b: 0x40270e20,
+ 0x192c: 0x40270f20, 0x192d: 0x40271020,
+ 0x1930: 0x40271120, 0x1931: 0x40271220, 0x1932: 0x40271320, 0x1933: 0x40271420,
+ 0x1934: 0x40271520,
+ // Block 0x65, offset 0x1940
+ 0x1940: 0x40271620, 0x1941: 0x40271720, 0x1942: 0x40271820, 0x1943: 0x40271920,
+ 0x1944: 0x40271a20, 0x1945: 0x40271b20, 0x1946: 0x40271c20, 0x1947: 0x40271d20,
+ 0x1948: 0x40271e20, 0x1949: 0x40271f20, 0x194a: 0x40272020, 0x194b: 0x40272120,
+ 0x194c: 0x40272220, 0x194d: 0x40272320, 0x194e: 0x40272420, 0x194f: 0x40272520,
+ 0x1950: 0x40272620, 0x1951: 0x40272720, 0x1952: 0x40272820, 0x1953: 0x40272920,
+ 0x1954: 0x40272a20, 0x1955: 0x40272b20, 0x1956: 0x40272c20, 0x1957: 0x40272d20,
+ 0x1958: 0x40272e20, 0x1959: 0x40272f20, 0x195a: 0x40273020, 0x195b: 0x40273120,
+ 0x195c: 0x40273220, 0x195d: 0x40273320, 0x195e: 0x40273420, 0x195f: 0x40273520,
+ 0x1960: 0x40273620, 0x1961: 0x40273720, 0x1962: 0x40273820, 0x1963: 0x40273920,
+ 0x1964: 0x40273a20, 0x1965: 0x40273b20, 0x1966: 0x40273c20, 0x1967: 0x40273d20,
+ 0x1968: 0x40273e20, 0x1969: 0x40273f20, 0x196a: 0x40274020, 0x196b: 0x40274120,
+ 0x1970: 0x40274220, 0x1971: 0x40274320, 0x1972: 0x40274420, 0x1973: 0x40274520,
+ 0x1974: 0x40274620, 0x1975: 0x40274720, 0x1976: 0x40274820, 0x1977: 0x40274920,
+ 0x1978: 0x40274a20, 0x1979: 0x40274b20, 0x197a: 0x40274c20, 0x197b: 0x40274d20,
+ 0x197c: 0x40274e20, 0x197d: 0x40274f20, 0x197e: 0x40275020, 0x197f: 0x40275120,
+ // Block 0x66, offset 0x1980
+ 0x1980: 0x40275220, 0x1981: 0x40275320, 0x1982: 0x40275420, 0x1983: 0x40275520,
+ 0x1984: 0x40275620, 0x1985: 0x40275720, 0x1986: 0x40275820, 0x1987: 0x40275920,
+ 0x1988: 0x40275a20, 0x1989: 0x40275b20,
+ 0x1990: 0xe0000054, 0x1991: 0xe00000d5, 0x1992: 0xe00001bf, 0x1993: 0xe0000285,
+ 0x1994: 0xe0000342, 0x1995: 0xe00003fc, 0x1996: 0xe00004b3, 0x1997: 0xe000054f,
+ 0x1998: 0xe00005eb, 0x1999: 0xe0000684, 0x199a: 0xe00000d8,
+ 0x199e: 0xe0001059, 0x199f: 0xe000105c,
+ 0x19a0: 0x4003c320, 0x19a1: 0x4003c420, 0x19a2: 0x4003c520, 0x19a3: 0x4003c620,
+ 0x19a4: 0x4003c720, 0x19a5: 0x4003c820, 0x19a6: 0x4003c920, 0x19a7: 0x4003ca20,
+ 0x19a8: 0x4003cb20, 0x19a9: 0x4003cc20, 0x19aa: 0x4003cd20, 0x19ab: 0x4003ce20,
+ 0x19ac: 0x4003cf20, 0x19ad: 0x4003d020, 0x19ae: 0x4003d120, 0x19af: 0x4003d220,
+ 0x19b0: 0x4003d320, 0x19b1: 0x4003d420, 0x19b2: 0x4003d520, 0x19b3: 0x4003d620,
+ 0x19b4: 0x4003d720, 0x19b5: 0x4003d820, 0x19b6: 0x4003d920, 0x19b7: 0x4003da20,
+ 0x19b8: 0x4003db20, 0x19b9: 0x4003dc20, 0x19ba: 0x4003dd20, 0x19bb: 0x4003de20,
+ 0x19bc: 0x4003df20, 0x19bd: 0x4003e020, 0x19be: 0x4003e120, 0x19bf: 0x4003e220,
+ // Block 0x67, offset 0x19c0
+ 0x19c0: 0x40259520, 0x19c1: 0x40259620, 0x19c2: 0x40259720, 0x19c3: 0x40259820,
+ 0x19c4: 0x40259920, 0x19c5: 0x40259a20, 0x19c6: 0x40259b20, 0x19c7: 0x40259c20,
+ 0x19c8: 0x40259d20, 0x19c9: 0x40259e20, 0x19ca: 0x40259f20, 0x19cb: 0x4025a020,
+ 0x19cc: 0x4025a120, 0x19cd: 0x4025a220, 0x19ce: 0x4025a320, 0x19cf: 0x4025a420,
+ 0x19d0: 0x4025a520, 0x19d1: 0x4025a620, 0x19d2: 0x4025a720, 0x19d3: 0x4025a820,
+ 0x19d4: 0x4025a920, 0x19d5: 0x4025aa20, 0x19d6: 0x4025ab20, 0x19d7: 0x4025ac20,
+ 0x19d8: 0x4025ad20, 0x19d9: 0x4025ae20, 0x19da: 0x4025af20, 0x19db: 0x4025b020,
+ 0x19de: 0x4001a520, 0x19df: 0x4001a620,
+ 0x19e0: 0x40275c20, 0x19e1: 0x40275d20, 0x19e2: 0x40275e20, 0x19e3: 0x40275f20,
+ 0x19e4: 0x40276020, 0x19e5: 0x40276120, 0x19e6: 0x40276220, 0x19e7: 0x40276320,
+ 0x19e8: 0x40276420, 0x19e9: 0x40276520, 0x19ea: 0x40276620, 0x19eb: 0x40276720,
+ 0x19ec: 0x40276820, 0x19ed: 0x40276920, 0x19ee: 0x40276a20, 0x19ef: 0x40276b20,
+ 0x19f0: 0x40276c20, 0x19f1: 0x40276d20, 0x19f2: 0x40276e20, 0x19f3: 0x40276f20,
+ 0x19f4: 0x40277020, 0x19f5: 0x40277120, 0x19f6: 0x40277220, 0x19f7: 0x40277320,
+ 0x19f8: 0x40277420, 0x19f9: 0x40277520, 0x19fa: 0x40277620, 0x19fb: 0x40277720,
+ 0x19fc: 0x40277820, 0x19fd: 0x40277920, 0x19fe: 0x40277a20, 0x19ff: 0x40277b20,
+ // Block 0x68, offset 0x1a00
+ 0x1a00: 0x40277c20, 0x1a01: 0x40277d20, 0x1a02: 0x40277e20, 0x1a03: 0x40277f20,
+ 0x1a04: 0x40278020, 0x1a05: 0x40278120, 0x1a06: 0x40278220, 0x1a07: 0x40278320,
+ 0x1a08: 0x40278420, 0x1a09: 0x40278520, 0x1a0a: 0x40278620, 0x1a0b: 0x40278720,
+ 0x1a0c: 0x40278820, 0x1a0d: 0x40279120, 0x1a0e: 0x40279220, 0x1a0f: 0x40279320,
+ 0x1a10: 0x40279420, 0x1a11: 0x40279520, 0x1a12: 0x40279620, 0x1a13: 0x40278920,
+ 0x1a14: 0xe0001060, 0x1a15: 0x40278b20, 0x1a16: 0x40278c20, 0x1a17: 0x40278d20,
+ 0x1a18: 0x004ec404, 0x1a19: 0x004ec404, 0x1a1a: 0x004eee04, 0x1a1b: 0x004eee04,
+ 0x1a1c: 0x40278e20, 0x1a1d: 0x40278f20, 0x1a1e: 0x40279020,
+ 0x1a20: 0x4027a820, 0x1a21: 0x40279720, 0x1a22: 0x40279920, 0x1a23: 0x40279a20,
+ 0x1a24: 0x004f3404, 0x1a25: 0x40279b20, 0x1a26: 0x40279c20, 0x1a27: 0x40279d20,
+ 0x1a28: 0x40279e20, 0x1a29: 0x40279f20, 0x1a2a: 0x4027a020, 0x1a2b: 0x40278a20,
+ 0x1a2c: 0x40279820, 0x1a2d: 0x4027a720, 0x1a2e: 0x4027a120, 0x1a2f: 0x4027a220,
+ 0x1a30: 0x4027a420, 0x1a31: 0x4027a520, 0x1a32: 0x4027a620, 0x1a33: 0x4027a320,
+ 0x1a34: 0x80013c02, 0x1a35: 0x80013d02, 0x1a36: 0x80013e02, 0x1a37: 0x80013f02,
+ 0x1a38: 0x80014002, 0x1a39: 0x80014102, 0x1a3a: 0x80014202, 0x1a3b: 0x80014302,
+ 0x1a3c: 0x80014402, 0x1a3f: 0x80000000,
+ // Block 0x69, offset 0x1a40
+ 0x1a40: 0xe0000057, 0x1a41: 0xe00000db, 0x1a42: 0xe00001c2, 0x1a43: 0xe0000288,
+ 0x1a44: 0xe0000345, 0x1a45: 0xe00003ff, 0x1a46: 0xe00004b6, 0x1a47: 0xe0000552,
+ 0x1a48: 0xe00005ee, 0x1a49: 0xe0000687,
+ 0x1a50: 0xe000005a, 0x1a51: 0xe00000de, 0x1a52: 0xe00001c5, 0x1a53: 0xe000028b,
+ 0x1a54: 0xe0000348, 0x1a55: 0xe0000402, 0x1a56: 0xe00004b9, 0x1a57: 0xe0000555,
+ 0x1a58: 0xe00005f1, 0x1a59: 0xe000068a,
+ 0x1a60: 0x4002ad20, 0x1a61: 0x4002ae20, 0x1a62: 0x4002af20, 0x1a63: 0x4002b020,
+ 0x1a64: 0x4002b120, 0x1a65: 0x4002b220, 0x1a66: 0x4002b320, 0x1a67: 0x40139720,
+ 0x1a68: 0x40018d20, 0x1a69: 0x40018e20, 0x1a6a: 0x40018f20, 0x1a6b: 0x40019020,
+ 0x1a6c: 0x4002b420, 0x1a6d: 0x4002b520,
+ // Block 0x6a, offset 0x1a80
+ 0x1a80: 0x8000ff02, 0x1a81: 0x80010002, 0x1a82: 0x80010102, 0x1a83: 0x80010202,
+ 0x1a84: 0x80010302, 0x1a85: 0xc30907b1, 0x1a86: 0x4027ef20, 0x1a87: 0xc30b07b1,
+ 0x1a88: 0x4027f120, 0x1a89: 0xc30d07b1, 0x1a8a: 0x4027f320, 0x1a8b: 0xc30f07b1,
+ 0x1a8c: 0x4027f520, 0x1a8d: 0xc31107b1, 0x1a8e: 0x4027f720, 0x1a8f: 0x4027f820,
+ 0x1a90: 0x4027f920, 0x1a91: 0xc31307b1, 0x1a92: 0x4027fb20, 0x1a93: 0x4027fc20,
+ 0x1a94: 0x4027ff20, 0x1a95: 0x40280020, 0x1a96: 0x40280120, 0x1a97: 0x40280220,
+ 0x1a98: 0x40280320, 0x1a99: 0x40280420, 0x1a9a: 0x40280520, 0x1a9b: 0x40280620,
+ 0x1a9c: 0x40280720, 0x1a9d: 0x40280820, 0x1a9e: 0x40280920, 0x1a9f: 0x40280a20,
+ 0x1aa0: 0x40280b20, 0x1aa1: 0x40280c20, 0x1aa2: 0x40280d20, 0x1aa3: 0x40280f20,
+ 0x1aa4: 0x40281020, 0x1aa5: 0x40281120, 0x1aa6: 0x40281220, 0x1aa7: 0x40281320,
+ 0x1aa8: 0x40281520, 0x1aa9: 0x40281620, 0x1aaa: 0x40281720, 0x1aab: 0x40281820,
+ 0x1aac: 0x40281920, 0x1aad: 0x40281a20, 0x1aae: 0x40281b20, 0x1aaf: 0x40281c20,
+ 0x1ab0: 0x40281e20, 0x1ab1: 0x40281f20, 0x1ab2: 0x40282020, 0x1ab3: 0x40282320,
+ 0x1ab4: 0x8000fe02, 0x1ab5: 0x40282420, 0x1ab6: 0x40282520, 0x1ab7: 0x40282620,
+ 0x1ab8: 0x40282720, 0x1ab9: 0x40282820, 0x1aba: 0xc31507b1, 0x1abb: 0x40282a20,
+ 0x1abc: 0xc31707b1, 0x1abd: 0x40282c20, 0x1abe: 0xc31907b1, 0x1abf: 0xc31b07b1,
+ // Block 0x6b, offset 0x1ac0
+ 0x1ac0: 0x40282f20, 0x1ac1: 0x40283020, 0x1ac2: 0xc31d07b1, 0x1ac3: 0x40283220,
+ 0x1ac4: 0x40283320, 0x1ac5: 0x4027fd20, 0x1ac6: 0x4027fe20, 0x1ac7: 0x40280e20,
+ 0x1ac8: 0x40281420, 0x1ac9: 0x40281d20, 0x1aca: 0x40282120, 0x1acb: 0x40282220,
+ 0x1ad0: 0xe000007e, 0x1ad1: 0xe0000102, 0x1ad2: 0xe00001e9, 0x1ad3: 0xe00002af,
+ 0x1ad4: 0xe000036c, 0x1ad5: 0xe0000426, 0x1ad6: 0xe00004dd, 0x1ad7: 0xe0000579,
+ 0x1ad8: 0xe0000615, 0x1ad9: 0xe00006ae, 0x1ada: 0x4001a720, 0x1adb: 0x4001a820,
+ 0x1adc: 0x40017420, 0x1add: 0x40015220, 0x1ade: 0x40019120, 0x1adf: 0x40019220,
+ 0x1ae0: 0x40011120, 0x1ae1: 0x4003e320, 0x1ae2: 0x4003e420, 0x1ae3: 0x4003e520,
+ 0x1ae4: 0x4003e620, 0x1ae5: 0x4003e720, 0x1ae6: 0x4003e820, 0x1ae7: 0x4003e920,
+ 0x1ae8: 0x4003ea20, 0x1ae9: 0x4003eb20, 0x1aea: 0x4003ec20, 0x1aeb: 0x80000000,
+ 0x1aec: 0x80000000, 0x1aed: 0x80000000, 0x1aee: 0x80000000, 0x1aef: 0x80000000,
+ 0x1af0: 0x80000000, 0x1af1: 0x80000000, 0x1af2: 0x80000000, 0x1af3: 0x80000000,
+ 0x1af4: 0x4003ed20, 0x1af5: 0x4003ee20, 0x1af6: 0x4003ef20, 0x1af7: 0x4003f020,
+ 0x1af8: 0x4003f120, 0x1af9: 0x4003f220, 0x1afa: 0x4003f320, 0x1afb: 0x4003f420,
+ 0x1afc: 0x4003f520,
+ // Block 0x6c, offset 0x1b00
+ 0x1b00: 0x80010902, 0x1b01: 0x80010a02, 0x1b02: 0x80010b02, 0x1b03: 0x4022fd20,
+ 0x1b04: 0x4022fe20, 0x1b05: 0x4022ff20, 0x1b06: 0x40230020, 0x1b07: 0x40230120,
+ 0x1b08: 0x40230220, 0x1b09: 0x40230320, 0x1b0a: 0x40230420, 0x1b0b: 0x40230620,
+ 0x1b0c: 0x40230720, 0x1b0d: 0x40230820, 0x1b0e: 0x40230920, 0x1b0f: 0x40230a20,
+ 0x1b10: 0x40230b20, 0x1b11: 0x40230c20, 0x1b12: 0x40230d20, 0x1b13: 0x40230e20,
+ 0x1b14: 0x40230f20, 0x1b15: 0x40231020, 0x1b16: 0x40231120, 0x1b17: 0x40231220,
+ 0x1b18: 0x40231320, 0x1b19: 0x40231420, 0x1b1a: 0x40231520, 0x1b1b: 0x40231720,
+ 0x1b1c: 0x40231920, 0x1b1d: 0x40231b20, 0x1b1e: 0x40231c20, 0x1b1f: 0x40231d20,
+ 0x1b20: 0x40231f20, 0x1b21: 0x40231620, 0x1b22: 0x40231820, 0x1b23: 0x40231a20,
+ 0x1b24: 0x40232020, 0x1b25: 0x40232120, 0x1b26: 0x40232220, 0x1b27: 0x40232320,
+ 0x1b28: 0x40232420, 0x1b29: 0x40232520, 0x1b2a: 0x40232620,
+ 0x1b2e: 0x40230520, 0x1b2f: 0x40231e20,
+ 0x1b30: 0xe0000084, 0x1b31: 0xe0000108, 0x1b32: 0xe00001ef, 0x1b33: 0xe00002b5,
+ 0x1b34: 0xe0000372, 0x1b35: 0xe000042c, 0x1b36: 0xe00004e3, 0x1b37: 0xe000057f,
+ 0x1b38: 0xe000061b, 0x1b39: 0xe00006b4,
+ // Block 0x6d, offset 0x1b40
+ 0x1b40: 0x4025b120, 0x1b41: 0x004b6204, 0x1b42: 0x4025b220, 0x1b43: 0x004b6404,
+ 0x1b44: 0x004b6404, 0x1b45: 0x4025b320, 0x1b46: 0x004b6604, 0x1b47: 0x4025b420,
+ 0x1b48: 0x004b6804, 0x1b49: 0x4025b520, 0x1b4a: 0x004b6a04, 0x1b4b: 0x4025b620,
+ 0x1b4c: 0x004b6c04, 0x1b4d: 0x004b6c04, 0x1b4e: 0x4025b720, 0x1b4f: 0x004b6e04,
+ 0x1b50: 0x4025b820, 0x1b51: 0x4025b920, 0x1b52: 0x4025ba20, 0x1b53: 0x004b7404,
+ 0x1b54: 0x4025bb20, 0x1b55: 0x004b7604, 0x1b56: 0x4025bc20, 0x1b57: 0x004b7804,
+ 0x1b58: 0x4025bd20, 0x1b59: 0x004b7a04, 0x1b5a: 0x004b7a04, 0x1b5b: 0x4025be20,
+ 0x1b5c: 0x004b7c04, 0x1b5d: 0x4025bf20, 0x1b5e: 0x4025c020, 0x1b5f: 0x004b8004,
+ 0x1b60: 0x4025c120, 0x1b61: 0x4025c220, 0x1b62: 0x4025c320, 0x1b63: 0x4025c420,
+ 0x1b64: 0x4025c520, 0x1b65: 0x4025c620, 0x1b66: 0x80005f02, 0x1b67: 0x4025c720,
+ 0x1b68: 0x004b8e04, 0x1b69: 0x4025c820, 0x1b6a: 0x4025c920, 0x1b6b: 0x004b9204,
+ 0x1b6c: 0x4025ca20, 0x1b6d: 0x004b9404, 0x1b6e: 0x4025cb20, 0x1b6f: 0x004b9604,
+ 0x1b70: 0x4025cc20, 0x1b71: 0x4025cd20, 0x1b72: 0x4025ce20, 0x1b73: 0x4025cf20,
+ 0x1b7c: 0x4002ba20, 0x1b7d: 0x4002bb20, 0x1b7e: 0x4002bc20, 0x1b7f: 0x4002bd20,
+ // Block 0x6e, offset 0x1b80
+ 0x1b80: 0x4024a620, 0x1b81: 0x4024a720, 0x1b82: 0x4024a820, 0x1b83: 0x4024a920,
+ 0x1b84: 0x4024aa20, 0x1b85: 0x4024ab20, 0x1b86: 0x4024ac20, 0x1b87: 0x4024ad20,
+ 0x1b88: 0x4024ae20, 0x1b89: 0x4024af20, 0x1b8a: 0x4024b320, 0x1b8b: 0x4024b420,
+ 0x1b8c: 0x4024b520, 0x1b8d: 0x4024b620, 0x1b8e: 0x4024b720, 0x1b8f: 0x4024b820,
+ 0x1b90: 0x4024b920, 0x1b91: 0x4024ba20, 0x1b92: 0x4024bb20, 0x1b93: 0x4024bc20,
+ 0x1b94: 0x4024bd20, 0x1b95: 0x4024be20, 0x1b96: 0x4024bf20, 0x1b97: 0x4024c020,
+ 0x1b98: 0x4024c120, 0x1b99: 0x4024c220, 0x1b9a: 0x4024c320, 0x1b9b: 0x4024c520,
+ 0x1b9c: 0x4024c720, 0x1b9d: 0x4024c820, 0x1b9e: 0x4024c920, 0x1b9f: 0x4024ca20,
+ 0x1ba0: 0x4024cb20, 0x1ba1: 0x4024cc20, 0x1ba2: 0x4024cd20, 0x1ba3: 0x4024ce20,
+ 0x1ba4: 0x4024c420, 0x1ba5: 0x4024c620, 0x1ba6: 0x4024d020, 0x1ba7: 0x4024d120,
+ 0x1ba8: 0x4024d220, 0x1ba9: 0x4024d320, 0x1baa: 0x4024d420, 0x1bab: 0x4024d520,
+ 0x1bac: 0x4024d620, 0x1bad: 0x4024d720, 0x1bae: 0x4024d820, 0x1baf: 0x4024d920,
+ 0x1bb0: 0x4024da20, 0x1bb1: 0x4024db20, 0x1bb2: 0x4024dc20, 0x1bb3: 0x4024dd20,
+ 0x1bb4: 0x4024de20, 0x1bb5: 0x4024df20, 0x1bb6: 0x4024cf20, 0x1bb7: 0x80012f02,
+ 0x1bbb: 0x40018220,
+ 0x1bbc: 0x40018320, 0x1bbd: 0x4002a320, 0x1bbe: 0x4002a420, 0x1bbf: 0x4002a520,
+ // Block 0x6f, offset 0x1bc0
+ 0x1bc0: 0xe0000069, 0x1bc1: 0xe00000ed, 0x1bc2: 0xe00001d4, 0x1bc3: 0xe000029a,
+ 0x1bc4: 0xe0000357, 0x1bc5: 0xe0000411, 0x1bc6: 0xe00004c8, 0x1bc7: 0xe0000564,
+ 0x1bc8: 0xe0000600, 0x1bc9: 0xe0000699,
+ 0x1bcd: 0x4024b020, 0x1bce: 0x4024b120, 0x1bcf: 0x4024b220,
+ 0x1bd0: 0xe000008a, 0x1bd1: 0xe000010e, 0x1bd2: 0xe00001f5, 0x1bd3: 0xe00002bb,
+ 0x1bd4: 0xe0000378, 0x1bd5: 0xe0000432, 0x1bd6: 0xe00004e9, 0x1bd7: 0xe0000585,
+ 0x1bd8: 0xe0000621, 0x1bd9: 0xe00006ba, 0x1bda: 0x4028f220, 0x1bdb: 0x4028f320,
+ 0x1bdc: 0x4028f420, 0x1bdd: 0x4028f520, 0x1bde: 0x4028f620, 0x1bdf: 0x4028f720,
+ 0x1be0: 0x4028f820, 0x1be1: 0x4028f920, 0x1be2: 0x4028fa20, 0x1be3: 0x4028fb20,
+ 0x1be4: 0x4028fc20, 0x1be5: 0x4028fd20, 0x1be6: 0x4028fe20, 0x1be7: 0x4028ff20,
+ 0x1be8: 0x40290020, 0x1be9: 0x40290120, 0x1bea: 0x40290220, 0x1beb: 0x40290320,
+ 0x1bec: 0x40290420, 0x1bed: 0x40290520, 0x1bee: 0x40290620, 0x1bef: 0x40290720,
+ 0x1bf0: 0x40290820, 0x1bf1: 0x40290920, 0x1bf2: 0x40290a20, 0x1bf3: 0x40290b20,
+ 0x1bf4: 0x40290c20, 0x1bf5: 0x40290d20, 0x1bf6: 0x40290e20, 0x1bf7: 0x40290f20,
+ 0x1bf8: 0x40291020, 0x1bf9: 0x40291120, 0x1bfa: 0x40291220, 0x1bfb: 0x40291320,
+ 0x1bfc: 0x40291420, 0x1bfd: 0x40291520, 0x1bfe: 0x40019f20, 0x1bff: 0x4001a020,
+ // Block 0x70, offset 0x1c00
+ 0x1c10: 0x80000000, 0x1c11: 0x80000000, 0x1c12: 0x80000000, 0x1c13: 0x80000000,
+ 0x1c14: 0x80000000, 0x1c15: 0x80000000, 0x1c16: 0x80000000, 0x1c17: 0x80000000,
+ 0x1c18: 0x80000000, 0x1c19: 0x80000000, 0x1c1a: 0x80000000, 0x1c1b: 0x80000000,
+ 0x1c1c: 0x80000000, 0x1c1d: 0x80000000, 0x1c1e: 0x80000000, 0x1c1f: 0x80000000,
+ 0x1c20: 0x80000000, 0x1c21: 0x80000000, 0x1c22: 0x80000000, 0x1c23: 0x80000000,
+ 0x1c24: 0x80000000, 0x1c25: 0x80000000, 0x1c26: 0x80000000, 0x1c27: 0x80000000,
+ 0x1c28: 0x80000000, 0x1c29: 0x401fbf20, 0x1c2a: 0x003f7e04, 0x1c2b: 0x003f7e04,
+ 0x1c2c: 0x003f7e04, 0x1c2d: 0x8000df02, 0x1c2e: 0x003f7e04, 0x1c2f: 0x003f7e04,
+ 0x1c30: 0x003f7e04, 0x1c31: 0x003f7e04, 0x1c32: 0x8000e002,
+ // Block 0x71, offset 0x1c40
+ 0x1c40: 0x4015a720, 0x1c41: 0x4015aa20, 0x1c42: 0x4015ab20, 0x1c43: 0x4015c620,
+ 0x1c44: 0x4015d520, 0x1c45: 0x4015e820, 0x1c46: 0x4015e920, 0x1c47: 0x40160320,
+ 0x1c48: 0x40162620, 0x1c49: 0x40168d20, 0x1c4a: 0x4016a120, 0x1c4b: 0x4016b620,
+ 0x1c4c: 0x4016cd20, 0x1c4d: 0x4016f820, 0x1c4e: 0x40170b20, 0x1c4f: 0x40172820,
+ 0x1c50: 0x40173420, 0x1c51: 0x40172920, 0x1c52: 0x40173520, 0x1c53: 0x40172f20,
+ 0x1c54: 0x40172e20, 0x1c55: 0x40174820, 0x1c56: 0x40173820, 0x1c57: 0x40173920,
+ 0x1c58: 0x40174d20, 0x1c59: 0x40177920, 0x1c5a: 0x40178320, 0x1c5b: 0x4017cd20,
+ 0x1c5c: 0x4017ed20, 0x1c5d: 0x4017ee20, 0x1c5e: 0x4017ef20, 0x1c5f: 0x40180820,
+ 0x1c60: 0x40181620, 0x1c61: 0x40182820, 0x1c62: 0x40184820, 0x1c63: 0x40186520,
+ 0x1c64: 0x4018ad20, 0x1c65: 0x4018ae20, 0x1c66: 0x4018df20, 0x1c67: 0x4018ed20,
+ 0x1c68: 0x4018f320, 0x1c69: 0x4018f820, 0x1c6a: 0x40190320, 0x1c6b: 0x4019f820,
+ 0x1c6c: 0xf000001d, 0x1c6d: 0xf0001414, 0x1c6e: 0xf000001d, 0x1c6f: 0x4015c520,
+ 0x1c70: 0xf000001d, 0x1c71: 0xf000001d, 0x1c72: 0xf000001d, 0x1c73: 0xf000001d,
+ 0x1c74: 0xf000001d, 0x1c75: 0xf000001d, 0x1c76: 0xf000001d, 0x1c77: 0xf000001d,
+ 0x1c78: 0xf000001d, 0x1c79: 0xf000001d, 0x1c7a: 0xf000001d, 0x1c7b: 0x40170a20,
+ 0x1c7c: 0xf000001d, 0x1c7d: 0xf000001d, 0x1c7e: 0xf000001d, 0x1c7f: 0xf000001d,
+ // Block 0x72, offset 0x1c80
+ 0x1c80: 0xf000001d, 0x1c81: 0xf000001d, 0x1c82: 0xf000001d, 0x1c83: 0xf0000014,
+ 0x1c84: 0xf0000014, 0x1c85: 0xf0000014, 0x1c86: 0xf0000014, 0x1c87: 0xf0000014,
+ 0x1c88: 0xf0000014, 0x1c89: 0xf0000014, 0x1c8a: 0xf0000014, 0x1c8b: 0xf0000014,
+ 0x1c8c: 0x002c4c14, 0x1c8d: 0xf0000014, 0x1c8e: 0x002d1a14, 0x1c8f: 0xf0000014,
+ 0x1c90: 0xf0000014, 0x1c91: 0xf0000014, 0x1c92: 0xf0000014, 0x1c93: 0xf0000014,
+ 0x1c94: 0xf0000014, 0x1c95: 0xf0000014, 0x1c96: 0xf0000014, 0x1c97: 0xf0000014,
+ 0x1c98: 0xf0000014, 0x1c99: 0xf0000014, 0x1c9a: 0xf0000014, 0x1c9b: 0xf0000014,
+ 0x1c9c: 0xf0000014, 0x1c9d: 0xf0000014, 0x1c9e: 0xf0000014, 0x1c9f: 0xf0000014,
+ 0x1ca0: 0xf0000014, 0x1ca1: 0xf0000014, 0x1ca2: 0xf0000015, 0x1ca3: 0xf0000015,
+ 0x1ca4: 0xf0000015, 0x1ca5: 0xf0000015, 0x1ca6: 0xf0000015, 0x1ca7: 0xf0000015,
+ 0x1ca8: 0xf0000015, 0x1ca9: 0xf0000015, 0x1caa: 0xf0000015, 0x1cab: 0x4017f020,
+ 0x1cac: 0x4015c720, 0x1cad: 0x4015ea20, 0x1cae: 0x40163c20, 0x1caf: 0x4016f920,
+ 0x1cb0: 0x40170c20, 0x1cb1: 0x40175020, 0x1cb2: 0x40177e20, 0x1cb3: 0x40179a20,
+ 0x1cb4: 0x4017ab20, 0x1cb5: 0x4017d320, 0x1cb6: 0x40184d20, 0x1cb7: 0x40165d20,
+ 0x1cb8: 0xf0000014, 0x1cb9: 0xe000076b, 0x1cba: 0xe0000805, 0x1cbb: 0x40169220,
+ 0x1cbc: 0x40169820, 0x1cbd: 0x40174e20, 0x1cbe: 0x4017f520, 0x1cbf: 0x40181120,
+ // Block 0x73, offset 0x1cc0
+ 0x1cc0: 0x4015c820, 0x1cc1: 0x4015eb20, 0x1cc2: 0x40163d20, 0x1cc3: 0x40165420,
+ 0x1cc4: 0x4016b720, 0x1cc5: 0x4016dc20, 0x1cc6: 0x4016fa20, 0x1cc7: 0x40171620,
+ 0x1cc8: 0x40175120, 0x1cc9: 0x40178820, 0x1cca: 0x4017ac20, 0x1ccb: 0x4017bb20,
+ 0x1ccc: 0x40181820, 0x1ccd: 0x40183220, 0x1cce: 0x40184e20, 0x1ccf: 0x4015a920,
+ 0x1cd0: 0x4015b420, 0x1cd1: 0x4015f420, 0x1cd2: 0x40160820, 0x1cd3: 0x40161820,
+ 0x1cd4: 0x40162520, 0x1cd5: 0x40161320, 0x1cd6: 0x40169320, 0x1cd7: 0x40173620,
+ 0x1cd8: 0x4017c420, 0x1cd9: 0x4017f620, 0x1cda: 0x40186a20, 0x1cdb: 0xf0000014,
+ 0x1cdc: 0xf0000014, 0x1cdd: 0xf0000014, 0x1cde: 0xf0001414, 0x1cdf: 0xf0000014,
+ 0x1ce0: 0xf0000014, 0x1ce1: 0xf0000014, 0x1ce2: 0xf0000014, 0x1ce3: 0xf0000014,
+ 0x1ce4: 0xf0000014, 0x1ce5: 0xf0000014, 0x1ce6: 0xf0000014, 0x1ce7: 0xf0000014,
+ 0x1ce8: 0xf0000014, 0x1ce9: 0xf0000014, 0x1cea: 0xf0000014, 0x1ceb: 0xf0000014,
+ 0x1cec: 0xf0000014, 0x1ced: 0xf0000014, 0x1cee: 0xf0000014, 0x1cef: 0xf0000014,
+ 0x1cf0: 0xf0000014, 0x1cf1: 0xf0000014, 0x1cf2: 0xf0000014, 0x1cf3: 0xf0000014,
+ 0x1cf4: 0xf0000014, 0x1cf5: 0xf0000014, 0x1cf6: 0xf0000014, 0x1cf7: 0xf0000014,
+ 0x1cf8: 0xf0000014, 0x1cf9: 0xf0000014, 0x1cfa: 0xf0000014, 0x1cfb: 0xf0000014,
+ 0x1cfc: 0xf0000014, 0x1cfd: 0xf0000014, 0x1cfe: 0xf0000014, 0x1cff: 0xf0000014,
+ // Block 0x74, offset 0x1d00
+ 0x1d00: 0x80005f02, 0x1d01: 0x80005f02, 0x1d02: 0x80006002, 0x1d03: 0x80005f02,
+ 0x1d04: 0x80005f02, 0x1d05: 0x80005f02, 0x1d06: 0x80005f02, 0x1d07: 0x80005f02,
+ 0x1d08: 0x80005f02, 0x1d09: 0x80005f02, 0x1d0a: 0x002ee004, 0x1d0b: 0x80005f02,
+ 0x1d0c: 0x80005f02, 0x1d0d: 0x80005f02, 0x1d0e: 0x80005f02, 0x1d0f: 0x80006002,
+ 0x1d10: 0x80006002, 0x1d11: 0x80005f02, 0x1d12: 0x00310804, 0x1d13: 0xe00006ea,
+ 0x1d14: 0xe00006fa, 0x1d15: 0xe0000702, 0x1d16: 0xe0000711, 0x1d17: 0xe0000728,
+ 0x1d18: 0xe0000742, 0x1d19: 0xe000073c, 0x1d1a: 0x002c8804, 0x1d1b: 0x002c9804,
+ 0x1d1c: 0x002d6404, 0x1d1d: 0x002d8804, 0x1d1e: 0x002d9004, 0x1d1f: 0x002df004,
+ 0x1d20: 0x002e0404, 0x1d21: 0x002e0c04, 0x1d22: 0x002ee804, 0x1d23: 0x002ef004,
+ 0x1d24: 0x002f4c04, 0x1d25: 0xe00007e0, 0x1d26: 0x00308804,
+ 0x1d3c: 0x80006002, 0x1d3d: 0x80006002, 0x1d3e: 0x80005f02, 0x1d3f: 0x80006002,
+ // Block 0x75, offset 0x1d40
+ 0x1d5a: 0xf0000404,
+ 0x1d5c: 0x4017b520, 0x1d5d: 0x4017b620, 0x1d5e: 0xe00007f4, 0x1d5f: 0x4015fe20,
+ // Block 0x76, offset 0x1d80
+ 0x1dba: 0xe0000798, 0x1dbb: 0xe0000795,
+ 0x1dbc: 0x00303e08, 0x1dbd: 0x40181f20, 0x1dbe: 0x00308608, 0x1dbf: 0x40184320,
+ // Block 0x77, offset 0x1dc0
+ 0x1dfd: 0x4002f820, 0x1dff: 0x4002f820,
+ // Block 0x78, offset 0x1e00
+ 0x1e00: 0x4002fc20,
+ 0x1e3e: 0x4002f920,
+ // Block 0x79, offset 0x1e40
+ 0x1e42: 0xf0000004, 0x1e43: 0xf0000004,
+ 0x1e44: 0xf0000004, 0x1e45: 0xf0000004, 0x1e46: 0xf0000004, 0x1e47: 0xf000001b,
+ 0x1e48: 0xf0000004, 0x1e49: 0xf0000004, 0x1e4a: 0xf0000004, 0x1e4b: 0x80000000,
+ 0x1e4c: 0x80000000, 0x1e4d: 0x80000000, 0x1e4e: 0x80000000, 0x1e4f: 0x80000000,
+ 0x1e50: 0x40011420, 0x1e51: 0xf000001b, 0x1e52: 0x40011520, 0x1e53: 0x40011620,
+ 0x1e54: 0x40011720, 0x1e55: 0x40011820, 0x1e56: 0x4002d220, 0x1e57: 0x40010d20,
+ 0x1e58: 0x4001d920, 0x1e59: 0x4001da20, 0x1e5a: 0x4001db20, 0x1e5b: 0x4001dc20,
+ 0x1e5c: 0x4001e020, 0x1e5d: 0x4001e120, 0x1e5e: 0x4001e220, 0x1e5f: 0x4001e320,
+ 0x1e60: 0x40024d20, 0x1e61: 0x40024e20, 0x1e62: 0x40024f20, 0x1e63: 0x40025020,
+ 0x1e64: 0xf0000004, 0x1e65: 0xf0000404, 0x1e66: 0xf0000404, 0x1e67: 0x40025120,
+ 0x1e68: 0x40010720, 0x1e69: 0x40010820, 0x1e6a: 0x80000000, 0x1e6b: 0x80000000,
+ 0x1e6c: 0x80000000, 0x1e6d: 0x80000000, 0x1e6e: 0x80000000, 0x1e6f: 0xf000001b,
+ 0x1e70: 0x40024920, 0x1e71: 0x40024b20, 0x1e72: 0x40025520, 0x1e73: 0xf0000404,
+ 0x1e74: 0xf0000404, 0x1e75: 0x40025620, 0x1e76: 0xf0000404, 0x1e77: 0xf0000404,
+ 0x1e78: 0x40025920, 0x1e79: 0x4001dd20, 0x1e7a: 0x4001de20, 0x1e7b: 0x40025a20,
+ 0x1e7c: 0xf0000404, 0x1e7d: 0x40016920, 0x1e7e: 0x40010b20, 0x1e7f: 0x40025b20,
+ // Block 0x7a, offset 0x1e80
+ 0x1e80: 0x40025d20, 0x1e81: 0x40025f20, 0x1e82: 0x40026020, 0x1e83: 0x40025220,
+ 0x1e84: 0x40031620, 0x1e85: 0x4001f520, 0x1e86: 0x4001f620, 0x1e87: 0xf0000404,
+ 0x1e88: 0xf0000404, 0x1e89: 0xf0000404, 0x1e8a: 0x40024520, 0x1e8b: 0x40023b20,
+ 0x1e8c: 0x40025320, 0x1e8d: 0x40025420, 0x1e8e: 0x40023e20, 0x1e8f: 0x40013020,
+ 0x1e90: 0x40025e20, 0x1e91: 0x40023f20, 0x1e92: 0x40031820, 0x1e93: 0x40011920,
+ 0x1e94: 0x40025c20, 0x1e95: 0x4001be20, 0x1e96: 0x4001bf20, 0x1e97: 0xf0000404,
+ 0x1e98: 0x4001c020, 0x1e99: 0x4001c120, 0x1e9a: 0x4001c220, 0x1e9b: 0x4001c320,
+ 0x1e9c: 0x4001c420, 0x1e9d: 0x4001c520, 0x1e9e: 0x4001c620, 0x1e9f: 0xf0000004,
+ 0x1ea0: 0x80000000, 0x1ea1: 0x80000000, 0x1ea2: 0x80000000, 0x1ea3: 0x80000000,
+ 0x1ea4: 0x80000000,
+ 0x1eaa: 0x80000000, 0x1eab: 0x80000000,
+ 0x1eac: 0x80000000, 0x1ead: 0x80000000, 0x1eae: 0x80000000, 0x1eaf: 0x80000000,
+ 0x1eb0: 0xf0000014, 0x1eb1: 0xf0000014,
+ 0x1eb4: 0xf0000014, 0x1eb5: 0xf0000014, 0x1eb6: 0xf0000014, 0x1eb7: 0xf0000014,
+ 0x1eb8: 0xf0000014, 0x1eb9: 0xf0000014, 0x1eba: 0xf0000014, 0x1ebb: 0xf0000014,
+ 0x1ebc: 0xf0000014, 0x1ebd: 0xf0000014, 0x1ebe: 0xf0000014, 0x1ebf: 0xf0000014,
+ // Block 0x7b, offset 0x1ec0
+ 0x1ec0: 0xf0000015, 0x1ec1: 0xf0000015, 0x1ec2: 0xf0000015, 0x1ec3: 0xf0000015,
+ 0x1ec4: 0xf0000015, 0x1ec5: 0xf0000015, 0x1ec6: 0xf0000015, 0x1ec7: 0xf0000015,
+ 0x1ec8: 0xf0000015, 0x1ec9: 0xf0000015, 0x1eca: 0xf0000015, 0x1ecb: 0xf0000015,
+ 0x1ecc: 0xf0000015, 0x1ecd: 0xf0000015, 0x1ece: 0xf0000015,
+ 0x1ed0: 0xf0000015, 0x1ed1: 0xf0000015, 0x1ed2: 0xf0000015, 0x1ed3: 0xf0000015,
+ 0x1ed4: 0xf0000015, 0x1ed5: 0xf0000015, 0x1ed6: 0xf0000015, 0x1ed7: 0xf0000015,
+ 0x1ed8: 0xf0000015, 0x1ed9: 0xf0000015, 0x1eda: 0xf0000015, 0x1edb: 0xf0000015,
+ 0x1edc: 0xf0000015,
+ 0x1ee0: 0x4013b120, 0x1ee1: 0x4013b220, 0x1ee2: 0x4013b320, 0x1ee3: 0x4013b420,
+ 0x1ee4: 0x4013b520, 0x1ee5: 0x4013b620, 0x1ee6: 0x4013b720, 0x1ee7: 0x4013b820,
+ 0x1ee8: 0x4013ca20, 0x1ee9: 0x4013b920, 0x1eea: 0x4013ba20, 0x1eeb: 0x4013bb20,
+ 0x1eec: 0x4013bc20, 0x1eed: 0x4013bd20, 0x1eee: 0x4013be20, 0x1eef: 0x4013bf20,
+ 0x1ef0: 0x4013c020, 0x1ef1: 0x4013c120, 0x1ef2: 0x4013c220, 0x1ef3: 0x4013c320,
+ 0x1ef4: 0x4013c420, 0x1ef5: 0x4013c520, 0x1ef6: 0x4013c620, 0x1ef7: 0x4013c720,
+ 0x1ef8: 0x4013c820, 0x1ef9: 0x4013c920,
+ // Block 0x7c, offset 0x1f00
+ 0x1f10: 0x80015002, 0x1f11: 0x80015102, 0x1f12: 0x80015202, 0x1f13: 0x80015202,
+ 0x1f14: 0x80015302, 0x1f15: 0x80015402, 0x1f16: 0x80015502, 0x1f17: 0x80015602,
+ 0x1f18: 0x80006102, 0x1f19: 0x80006102, 0x1f1a: 0x80006102, 0x1f1b: 0x80015702,
+ 0x1f1c: 0x80015802, 0x1f1d: 0x80006202, 0x1f1e: 0x80006202, 0x1f1f: 0x80006202,
+ 0x1f20: 0x80006202, 0x1f21: 0x80015902, 0x1f22: 0x80006202, 0x1f23: 0x80006202,
+ 0x1f24: 0x80006202, 0x1f25: 0x80006102, 0x1f26: 0x80015a02, 0x1f27: 0x80015b02,
+ 0x1f28: 0x80015c02, 0x1f29: 0x80015d02, 0x1f2a: 0x80006102, 0x1f2b: 0x80006102,
+ 0x1f2c: 0x80006002, 0x1f2d: 0x80006002, 0x1f2e: 0x80006002, 0x1f2f: 0x80006002,
+ 0x1f30: 0x80005f02,
+ // Block 0x7d, offset 0x1f40
+ 0x1f40: 0xf0000404, 0x1f41: 0xf0000404, 0x1f42: 0xf000000b, 0x1f43: 0xf0000a04,
+ 0x1f44: 0x4003f620, 0x1f45: 0xf0000404, 0x1f46: 0xf0000404, 0x1f47: 0xf000000a,
+ 0x1f48: 0x4003f720, 0x1f49: 0xf0000a04, 0x1f4a: 0xf0000005, 0x1f4b: 0xf000000b,
+ 0x1f4c: 0xf000000b, 0x1f4d: 0xf000000b, 0x1f4e: 0xf0000005, 0x1f4f: 0xf0000202,
+ 0x1f50: 0xf000000b, 0x1f51: 0xf000000b, 0x1f52: 0xf000000b, 0x1f53: 0xf0000005,
+ 0x1f54: 0x4003f820, 0x1f55: 0xf000000b, 0x1f56: 0xf000040a, 0x1f57: 0x4003f920,
+ 0x1f58: 0x4003fa20, 0x1f59: 0xf000000b, 0x1f5a: 0xf000000b, 0x1f5b: 0xf000000b,
+ 0x1f5c: 0xf000000b, 0x1f5d: 0xf000000b, 0x1f5e: 0x4003fb20, 0x1f5f: 0x4003fc20,
+ 0x1f60: 0xf0001414, 0x1f61: 0xf0000a0a, 0x1f62: 0xf0001414, 0x1f63: 0x4003fd20,
+ 0x1f64: 0xf000000b, 0x1f65: 0x4003fe20, 0x1f67: 0x4003ff20,
+ 0x1f68: 0xf000000b, 0x1f69: 0x40040020,
+ 0x1f6c: 0xf000000b, 0x1f6d: 0xf000000b, 0x1f6e: 0x40040120, 0x1f6f: 0xf0000005,
+ 0x1f70: 0xf000000b, 0x1f71: 0xf000000b, 0x1f72: 0x002c8408, 0x1f73: 0xf000000b,
+ 0x1f74: 0xf0000005, 0x1f75: 0xf0000004, 0x1f76: 0xf0000004, 0x1f77: 0xf0000004,
+ 0x1f78: 0xf0000004, 0x1f79: 0xf0000005, 0x1f7a: 0x40040220, 0x1f7b: 0xf0000a0a,
+ 0x1f7c: 0xf0000005, 0x1f7d: 0xf0000005, 0x1f7e: 0xf000000b, 0x1f7f: 0xf000000b,
+ // Block 0x7e, offset 0x1f80
+ 0x1f80: 0xf0000005, 0x1f81: 0x40040320, 0x1f82: 0x40040420, 0x1f83: 0x40040520,
+ 0x1f84: 0x40040620, 0x1f85: 0xf000000b, 0x1f86: 0xf0000005, 0x1f87: 0xf0000005,
+ 0x1f88: 0xf0000005, 0x1f89: 0xf0000005, 0x1f8a: 0x40040720, 0x1f8b: 0x40031720,
+ 0x1f8c: 0x40040820, 0x1f8d: 0x40040920, 0x1f8e: 0x40164220, 0x1f8f: 0x40040a20,
+ 0x1f90: 0xf0001e1e, 0x1f91: 0xf0001e1e, 0x1f92: 0xf0001e1e, 0x1f93: 0xf0001e1e,
+ 0x1f94: 0xf0001e1e, 0x1f95: 0xf0001e1e, 0x1f96: 0xf0001e1e, 0x1f97: 0xf0001e1e,
+ 0x1f98: 0xf0001e1e, 0x1f99: 0xf0001e1e, 0x1f9a: 0xf0001e1e, 0x1f9b: 0xf0001e1e,
+ 0x1f9c: 0xf0001e1e, 0x1f9d: 0xf0001e1e, 0x1f9e: 0xf0001e1e, 0x1f9f: 0xf0001e1e,
+ 0x1fa0: 0xf000000a, 0x1fa1: 0xf0000a0a, 0x1fa2: 0xf0000a0a, 0x1fa3: 0xf0000a0a,
+ 0x1fa4: 0xf000000a, 0x1fa5: 0xf0000a0a, 0x1fa6: 0xf0000a0a, 0x1fa7: 0xf0000a0a,
+ 0x1fa8: 0xf0000a0a, 0x1fa9: 0xf000000a, 0x1faa: 0xf0000a0a, 0x1fab: 0xf0000a0a,
+ 0x1fac: 0xf000000a, 0x1fad: 0xf000000a, 0x1fae: 0xf000000a, 0x1faf: 0xf000000a,
+ 0x1fb0: 0xf0000004, 0x1fb1: 0xf0000404, 0x1fb2: 0xf0000404, 0x1fb3: 0xf0000404,
+ 0x1fb4: 0xf0000004, 0x1fb5: 0xf0000404, 0x1fb6: 0xf0000404, 0x1fb7: 0xf0000404,
+ 0x1fb8: 0xf0000404, 0x1fb9: 0xf0000004, 0x1fba: 0xf0000404, 0x1fbb: 0xf0000404,
+ 0x1fbc: 0xf0000004, 0x1fbd: 0xf0000004, 0x1fbe: 0xf0000004, 0x1fbf: 0xf0000004,
+ // Block 0x7f, offset 0x1fc0
+ 0x1fc0: 0x4013f220, 0x1fc1: 0x4013f320, 0x1fc2: 0x4013f420, 0x1fc3: 0x002bc408,
+ 0x1fc4: 0x4015e220, 0x1fc5: 0xe00004f5, 0x1fc6: 0x4013f520, 0x1fc7: 0x4013f620,
+ 0x1fc8: 0x4013f720, 0x1fc9: 0xf0001e1e,
+ 0x1fd0: 0x40040b20, 0x1fd1: 0x40040d20, 0x1fd2: 0x40040c20, 0x1fd3: 0x40040e20,
+ 0x1fd4: 0x40040f20, 0x1fd5: 0x40041020, 0x1fd6: 0x40041120, 0x1fd7: 0x40041220,
+ 0x1fd8: 0x40041320, 0x1fd9: 0x40041420,
+ 0x1fdc: 0x40041520, 0x1fdd: 0x40041620, 0x1fde: 0x40041720, 0x1fdf: 0x40041820,
+ 0x1fe0: 0x40041920, 0x1fe1: 0x40041a20, 0x1fe2: 0x40041b20, 0x1fe3: 0x40041c20,
+ 0x1fe4: 0x40041d20, 0x1fe5: 0x40041e20, 0x1fe6: 0x40041f20, 0x1fe7: 0x40042020,
+ 0x1fe8: 0x40042120, 0x1fe9: 0x40042220, 0x1fea: 0x40042320, 0x1feb: 0x40042420,
+ 0x1fec: 0x40042520, 0x1fed: 0x40042620, 0x1fef: 0x40042720,
+ 0x1ff0: 0x40042820, 0x1ff1: 0x40042920, 0x1ff2: 0x40042a20, 0x1ff3: 0x40042b20,
+ 0x1ff4: 0x40042c20, 0x1ff5: 0x40042d20, 0x1ff6: 0x40042e20, 0x1ff7: 0x40042f20,
+ 0x1ff8: 0x40043020, 0x1ff9: 0x40043120, 0x1ffa: 0x40043220, 0x1ffb: 0x40043320,
+ 0x1ffc: 0x40043420, 0x1ffd: 0x40043520, 0x1ffe: 0x40043620, 0x1fff: 0x40043720,
+ // Block 0x80, offset 0x2000
+ 0x2000: 0x40043820, 0x2001: 0x40043920, 0x2002: 0x40043a20, 0x2003: 0x40043b20,
+ 0x2004: 0x40043c20, 0x2005: 0x40043d20, 0x2006: 0x40043e20, 0x2007: 0x40043f20,
+ 0x2008: 0x40044020, 0x2009: 0x40044120, 0x200a: 0x40044220, 0x200b: 0x40044320,
+ 0x200c: 0x40044420,
+ 0x2010: 0x40044520, 0x2011: 0x40044620, 0x2012: 0x40044720, 0x2013: 0x40044820,
+ 0x2014: 0x40044920, 0x2015: 0x40044a20, 0x2016: 0x40044b20, 0x2017: 0x40044c20,
+ 0x2018: 0x40044d20, 0x2019: 0x40044e20, 0x201a: 0x40044f20, 0x201b: 0x40045020,
+ 0x201c: 0x40045120, 0x201d: 0x40045220, 0x201e: 0x40045320, 0x201f: 0x40045420,
+ 0x2020: 0x40045520, 0x2021: 0x40045620, 0x2022: 0x40045720, 0x2023: 0x40045820,
+ 0x2024: 0x40045920, 0x2025: 0x40045a20, 0x2026: 0x40045b20, 0x2027: 0x40045c20,
+ 0x2028: 0x40045d20, 0x2029: 0x40045e20, 0x202a: 0x40045f20, 0x202b: 0x40046020,
+ 0x202c: 0x40046120, 0x202d: 0x40046220, 0x202e: 0x40046320, 0x202f: 0x40046420,
+ 0x2030: 0x40046520, 0x2031: 0x40046620, 0x2032: 0x40046720, 0x2033: 0x40046820,
+ 0x2034: 0x40046920, 0x2035: 0x40046a20, 0x2036: 0x40046b20, 0x2037: 0x40046c20,
+ 0x2038: 0x40046d20, 0x2039: 0x40046e20, 0x203a: 0x40046f20, 0x203b: 0x40047020,
+ 0x203c: 0x40047120, 0x203d: 0x40047220, 0x203e: 0x40047320, 0x203f: 0x40047420,
+ // Block 0x81, offset 0x2040
+ 0x2040: 0x40047520, 0x2041: 0x40047620, 0x2042: 0x40047720, 0x2043: 0x40047820,
+ 0x2045: 0x40047920, 0x2046: 0x40047a20, 0x2047: 0x40047b20,
+ 0x2048: 0x40047c20, 0x204a: 0x40047d20, 0x204b: 0x40047e20,
+ 0x204d: 0x40047f20, 0x204e: 0x40048120, 0x204f: 0x40048220,
+ 0x2050: 0x40048320, 0x2051: 0x40048420, 0x2052: 0x40049020, 0x2053: 0x40049120,
+ 0x2054: 0x40049220, 0x2055: 0x40049320, 0x2056: 0x40049420, 0x2057: 0x40049520,
+ 0x2058: 0x40049620, 0x2059: 0x40049720, 0x205a: 0x40049820, 0x205b: 0x40049920,
+ 0x205c: 0x40049b20, 0x205d: 0x40049d20, 0x205e: 0x40049e20, 0x205f: 0x40049f20,
+ 0x2060: 0x4004a020, 0x2061: 0x4004a120, 0x2062: 0x4004a220, 0x2063: 0x4004a320,
+ 0x2065: 0x4004a420, 0x2067: 0x4004a520,
+ 0x2068: 0x4004a620, 0x2069: 0x4004a720, 0x206a: 0x4004a820, 0x206b: 0x4004a920,
+ 0x206c: 0xf0000404, 0x206d: 0xf0000404, 0x206e: 0x4004aa20, 0x206f: 0xf0000404,
+ 0x2070: 0xf0000404, 0x2071: 0x4004ab20, 0x2072: 0x4004ac20, 0x2073: 0x4004ad20,
+ 0x2074: 0x4004ae20, 0x2075: 0x4004af20, 0x2076: 0x4004b020, 0x2077: 0x4004b120,
+ 0x2078: 0x4004b220, 0x2079: 0x4004b320, 0x207a: 0x4004b420, 0x207b: 0x4004b520,
+ 0x207c: 0x4004b620, 0x207d: 0x4004b720, 0x207e: 0x4004b820, 0x207f: 0x4004b920,
+ // Block 0x82, offset 0x2080
+ 0x2080: 0x4004ba20, 0x2082: 0x4004bb20, 0x2083: 0x4004bc20,
+ 0x2085: 0x4004bd20, 0x2086: 0x4004be20,
+ 0x2088: 0x4004bf20, 0x208a: 0x4004c020, 0x208b: 0x4004c120,
+ 0x208c: 0x4004c220, 0x208d: 0x4004c320, 0x208e: 0x4004c420, 0x208f: 0x4004c520,
+ 0x2090: 0x4004c620, 0x2091: 0x4004c720, 0x2092: 0x4004c820, 0x2093: 0x4004c920,
+ 0x2094: 0x4004ca20, 0x2095: 0x4004cb20, 0x2096: 0x4004cc20, 0x2097: 0x4004cd20,
+ 0x2098: 0x4004ce20, 0x2099: 0x4004cf20, 0x209a: 0x4004d020, 0x209b: 0x4004d120,
+ 0x209c: 0x4004d220, 0x209d: 0x4004d320, 0x209e: 0x4004d420, 0x209f: 0x4004d520,
+ 0x20a1: 0x4004d620, 0x20a3: 0x4004d720,
+ 0x20a4: 0x4004d820, 0x20a5: 0x4004d920, 0x20a6: 0x4004da20, 0x20a7: 0x4004db20,
+ 0x20a8: 0x4004dc20, 0x20a9: 0x4004dd20, 0x20aa: 0x4004de20, 0x20ab: 0x4004df20,
+ 0x20ac: 0x4004e020,
+ 0x20b2: 0x4004e120, 0x20b3: 0x4004e220,
+ 0x20b6: 0x4004e320, 0x20b7: 0x4004e420,
+ 0x20ba: 0x4004e520, 0x20bb: 0x4004e620,
+ 0x20bc: 0x4004e720, 0x20bd: 0x4004e820, 0x20be: 0x4004e920, 0x20bf: 0x4004ea20,
+ // Block 0x83, offset 0x20c0
+ 0x20c2: 0x4004eb20, 0x20c3: 0x4004ec20,
+ 0x20c6: 0x4004ed20, 0x20c7: 0x4004ee20,
+ 0x20ca: 0x4004ef20, 0x20cb: 0x4004f020,
+ 0x20cc: 0x4004f120, 0x20cd: 0x4004f220, 0x20ce: 0x4004f320, 0x20cf: 0x4004f420,
+ 0x20d0: 0x4004f520, 0x20d1: 0x4004f620, 0x20d2: 0x4004f720, 0x20d3: 0x4004f820,
+ 0x20d4: 0x4004f920, 0x20d5: 0x4004fa20, 0x20d6: 0x4004fb20, 0x20d7: 0x4004fc20,
+ 0x20d8: 0x4004fd20, 0x20d9: 0x4004fe20, 0x20da: 0x4004ff20, 0x20db: 0x40050020,
+ 0x20dc: 0x40050120, 0x20dd: 0x40050220, 0x20de: 0x40050320, 0x20df: 0x40050420,
+ 0x20e0: 0x40050520, 0x20e1: 0x40050620, 0x20e2: 0x40050720, 0x20e3: 0x40050820,
+ 0x20e4: 0x40050920, 0x20e5: 0x40050a20, 0x20e6: 0x40050b20, 0x20e7: 0x40050c20,
+ 0x20e8: 0x40050d20, 0x20e9: 0x40050e20, 0x20ea: 0x40050f20, 0x20eb: 0x40051020,
+ 0x20f0: 0x40051120, 0x20f1: 0x40051220, 0x20f2: 0x40051320, 0x20f3: 0x40051420,
+ 0x20f4: 0x40051520, 0x20f5: 0x40051620, 0x20f6: 0x40051720, 0x20f7: 0x40051820,
+ 0x20f8: 0x40051920, 0x20f9: 0x40051a20, 0x20fa: 0x40051b20, 0x20fb: 0x40051c20,
+ 0x20fc: 0x40051d20, 0x20fd: 0x40051e20, 0x20fe: 0x40051f20, 0x20ff: 0x40052020,
+ // Block 0x84, offset 0x2100
+ 0x2100: 0x40052120, 0x2101: 0x40052220, 0x2102: 0x40052320, 0x2103: 0x40052420,
+ 0x2104: 0x40052520, 0x2105: 0x40052620, 0x2106: 0x40052720, 0x2107: 0x40052820,
+ 0x2108: 0x40052920, 0x2109: 0x40052a20, 0x210a: 0x40052b20, 0x210b: 0x40052c20,
+ 0x210c: 0x40052d20, 0x210d: 0x40052e20, 0x210e: 0x40052f20, 0x210f: 0x40053020,
+ 0x2110: 0x40053120, 0x2111: 0x40053220, 0x2112: 0x40053320, 0x2113: 0x40053420,
+ 0x2114: 0x40053520, 0x2115: 0x40053620, 0x2116: 0x40053720, 0x2117: 0x40053820,
+ 0x2118: 0x40053920, 0x2119: 0x40053a20, 0x211a: 0x40053b20, 0x211b: 0x40053c20,
+ 0x211c: 0x40053d20, 0x211d: 0x40053e20, 0x211e: 0x40053f20, 0x211f: 0x40054020,
+ 0x2124: 0x40054120, 0x2125: 0x40054220, 0x2126: 0x40054320, 0x2127: 0x40054420,
+ 0x2128: 0x40054520, 0x2129: 0x40054620,
+ 0x212e: 0x40054720, 0x212f: 0x40054820,
+ 0x2130: 0x40054920, 0x2131: 0x40054a20, 0x2132: 0x40054b20, 0x2133: 0x40054c20,
+ 0x2134: 0x40054d20, 0x2135: 0x40054e20, 0x2136: 0x40054f20, 0x2137: 0x40055020,
+ 0x2138: 0x40055120, 0x2139: 0x40055220, 0x213a: 0x40055320, 0x213b: 0x40055420,
+ 0x213c: 0x40055520, 0x213d: 0x40055620, 0x213e: 0x40055720, 0x213f: 0x40055820,
+ // Block 0x85, offset 0x2140
+ 0x2140: 0x40055920, 0x2141: 0x40055a20, 0x2142: 0x40055b20, 0x2143: 0x40055c20,
+ 0x2144: 0x40055d20, 0x2145: 0x40055e20, 0x2146: 0x40055f20, 0x2147: 0x40056020,
+ 0x2148: 0x40056120, 0x2149: 0x40056220, 0x214a: 0x40056320, 0x214b: 0x40056420,
+ 0x214c: 0x40056520, 0x214d: 0x40056620, 0x214e: 0x40056720, 0x214f: 0x40056820,
+ 0x2150: 0x40056920, 0x2151: 0x40056a20, 0x2152: 0x40056b20, 0x2153: 0x40056c20,
+ 0x2154: 0x40056d20, 0x2155: 0x40056e20, 0x2156: 0x40056f20, 0x2157: 0x40057020,
+ 0x2158: 0x40057120, 0x2159: 0x40057220, 0x215a: 0x40057320, 0x215b: 0x40057420,
+ 0x215c: 0x40057520, 0x215d: 0x40057620, 0x215e: 0x40057720, 0x215f: 0x40057820,
+ 0x2160: 0x40057920, 0x2161: 0x40057a20, 0x2162: 0x40057b20, 0x2163: 0x40057c20,
+ 0x2164: 0x40057d20, 0x2165: 0x40057e20, 0x2166: 0x40057f20, 0x2167: 0x40058020,
+ 0x2168: 0x40058120, 0x216b: 0x40058220,
+ 0x216c: 0x40058320, 0x216d: 0x40058420, 0x216e: 0x40058520, 0x216f: 0x40058620,
+ 0x2170: 0x40058720, 0x2171: 0x40058820, 0x2172: 0x40058920, 0x2173: 0x40058a20,
+ 0x2174: 0x40058b20, 0x2175: 0x40058c20, 0x2176: 0x40058d20, 0x2177: 0x40058e20,
+ 0x2178: 0x40058f20, 0x2179: 0x40059020, 0x217a: 0x40059120, 0x217b: 0x40059220,
+ 0x217c: 0x40059320, 0x217d: 0x40059420, 0x217e: 0x40059520, 0x217f: 0x40059620,
+ // Block 0x86, offset 0x2180
+ 0x2180: 0x40059720, 0x2181: 0x40059820, 0x2182: 0x40059920, 0x2183: 0x40059a20,
+ 0x2184: 0x40059b20, 0x2185: 0x40059c20, 0x2186: 0x40059d20, 0x2187: 0x40059e20,
+ 0x2188: 0x40059f20, 0x2189: 0x4005a020, 0x218a: 0x4005a120, 0x218b: 0x4005a220,
+ 0x218c: 0x4005a320, 0x218d: 0x4005a420, 0x218e: 0x4005a520, 0x218f: 0x4005a620,
+ 0x2190: 0x4005a720, 0x2191: 0x4005a820, 0x2192: 0x4005a920, 0x2193: 0x4005aa20,
+ 0x2194: 0x4005ab20, 0x2195: 0x4005ac20, 0x2196: 0x4005ad20, 0x2197: 0x4005ae20,
+ 0x2198: 0x4005af20, 0x2199: 0x4005b020, 0x219a: 0x4005b120, 0x219b: 0x4005b220,
+ 0x219c: 0x4005b320, 0x219d: 0x4005b420, 0x219e: 0x4005b520, 0x219f: 0x4005b620,
+ 0x21a0: 0x4005b720, 0x21a1: 0x4005b820, 0x21a2: 0x4005b920, 0x21a3: 0x4005ba20,
+ 0x21a4: 0x4005bb20, 0x21a5: 0x4005bc20, 0x21a6: 0x4005bd20, 0x21a7: 0x4005be20,
+ 0x21a8: 0x4005bf20, 0x21a9: 0x4005c020, 0x21aa: 0x4005c120, 0x21ab: 0x4005c220,
+ 0x21ac: 0x4005c320, 0x21ad: 0x4005c420, 0x21ae: 0x4005c520, 0x21af: 0x4005c620,
+ 0x21b0: 0x4005c720, 0x21b1: 0x4005c820, 0x21b2: 0x4005c920, 0x21b3: 0x4005ca20,
+ 0x21b4: 0x4005cb20, 0x21b5: 0x4005cc20, 0x21b6: 0x4005cd20, 0x21b7: 0x4005ce20,
+ 0x21b8: 0x4005cf20, 0x21b9: 0x4005d020, 0x21ba: 0x4005d120, 0x21bb: 0x4005d220,
+ 0x21bc: 0x4005d320, 0x21bd: 0x4005d420, 0x21be: 0x4005d520, 0x21bf: 0x4005d620,
+ // Block 0x87, offset 0x21c0
+ 0x21c0: 0x4005d720, 0x21c1: 0x4005d820, 0x21c2: 0x4005d920, 0x21c3: 0x4005da20,
+ 0x21c4: 0x4005db20, 0x21c5: 0x4005dc20, 0x21c6: 0x4005dd20, 0x21c7: 0x4005de20,
+ 0x21c8: 0x4005df20, 0x21c9: 0x4005e020, 0x21ca: 0x4005e120, 0x21cb: 0x4005e220,
+ 0x21cc: 0x4005e320, 0x21cd: 0x4005e420, 0x21ce: 0x4005e520, 0x21cf: 0x4005e620,
+ 0x21d0: 0x4005e720, 0x21d1: 0x4005e820, 0x21d2: 0x4005e920, 0x21d3: 0x4005ea20,
+ 0x21d4: 0x4005eb20, 0x21d5: 0x4005ec20, 0x21d6: 0x4005ed20, 0x21d7: 0x4005ee20,
+ 0x21d8: 0x4005ef20, 0x21d9: 0x4005f020, 0x21da: 0x4005f120, 0x21db: 0x4005f220,
+ 0x21dc: 0x4005f320, 0x21dd: 0x4005f420, 0x21de: 0x4005f520, 0x21df: 0x4005f620,
+ 0x21e0: 0x4005f720, 0x21e1: 0x4005f820, 0x21e2: 0x4005f920, 0x21e3: 0x4005fa20,
+ 0x21e4: 0x4005fb20, 0x21e5: 0x4005fc20, 0x21e6: 0x4005fd20, 0x21e7: 0x4005fe20,
+ 0x21e8: 0x4005ff20, 0x21e9: 0x40060020, 0x21ea: 0x40060120, 0x21eb: 0x40060220,
+ 0x21ec: 0x40060320, 0x21ed: 0x40060420, 0x21ee: 0x40060520, 0x21ef: 0x40060620,
+ 0x21f0: 0x40060720, 0x21f1: 0x40060820, 0x21f2: 0x40060920, 0x21f3: 0x40060a20,
+ 0x21f4: 0x40060b20, 0x21f5: 0x40060c20, 0x21f6: 0x40060d20, 0x21f7: 0x40060e20,
+ 0x21f8: 0x40060f20, 0x21f9: 0x40061020, 0x21fa: 0x40061120, 0x21fb: 0x40061220,
+ 0x21fc: 0x40061320, 0x21fd: 0x40061420, 0x21fe: 0x40061520, 0x21ff: 0x40061620,
+ // Block 0x88, offset 0x2200
+ 0x2200: 0x40061720, 0x2201: 0x40061820, 0x2202: 0x40061920, 0x2203: 0x40061a20,
+ 0x2204: 0x40061b20, 0x2205: 0x40061c20, 0x2206: 0x40061d20, 0x2207: 0x40061e20,
+ 0x2208: 0x40061f20, 0x2209: 0x40062020, 0x220a: 0x40062120, 0x220b: 0x40062220,
+ 0x220c: 0x40062320, 0x220d: 0x40062420, 0x220e: 0x40062520, 0x220f: 0x40062620,
+ 0x2210: 0x40062720, 0x2211: 0x40062820, 0x2212: 0x40062920, 0x2213: 0x40062a20,
+ 0x2214: 0x40062b20, 0x2215: 0x40062c20, 0x2216: 0x40062d20, 0x2217: 0x40062e20,
+ 0x2218: 0x40062f20, 0x2219: 0x40063020, 0x221a: 0x40063120, 0x221b: 0x40063220,
+ 0x221c: 0x40063320, 0x221d: 0x40063420, 0x221e: 0x40063520, 0x221f: 0x40063620,
+ 0x2220: 0x40063720, 0x2221: 0x40063820, 0x2222: 0x40063920, 0x2223: 0x40063a20,
+ 0x2224: 0x40063b20, 0x2225: 0x40063c20, 0x2226: 0x40063d20, 0x2227: 0x40063e20,
+ 0x2228: 0x40063f20, 0x2229: 0x40064020, 0x222a: 0x40064120, 0x222b: 0x40064220,
+ 0x222c: 0x40064320, 0x222d: 0x40064420, 0x222e: 0x40064520, 0x222f: 0x40064620,
+ 0x2230: 0x40064720, 0x2231: 0x40064820, 0x2232: 0x40064920, 0x2233: 0x40064a20,
+ // Block 0x89, offset 0x2240
+ 0x2240: 0x40064b20, 0x2241: 0x40064c20, 0x2242: 0x40064d20, 0x2243: 0x40064e20,
+ 0x2244: 0x40064f20, 0x2245: 0x40065020, 0x2246: 0x40065120, 0x2247: 0x40065220,
+ 0x2248: 0x40065320, 0x2249: 0x40065420, 0x224a: 0x40065520, 0x224b: 0x40065620,
+ 0x224c: 0x40065720, 0x224d: 0x40065820, 0x224e: 0x40065920, 0x224f: 0x40065a20,
+ 0x2250: 0x40065b20, 0x2251: 0x40065c20, 0x2252: 0x40065d20, 0x2253: 0x40065e20,
+ 0x2254: 0x40065f20, 0x2255: 0x40066020, 0x2256: 0x40066120, 0x2257: 0x40066220,
+ 0x2258: 0x40066320, 0x2259: 0x40066420, 0x225a: 0x40066520, 0x225b: 0x40066620,
+ 0x225c: 0x40066720, 0x225d: 0x40066820, 0x225e: 0x40066920, 0x225f: 0x40066a20,
+ 0x2260: 0x40066b20, 0x2261: 0x40066c20, 0x2262: 0x40066d20, 0x2263: 0x40066e20,
+ 0x2264: 0x40066f20, 0x2265: 0x40067020, 0x2266: 0x40067120,
+ // Block 0x8a, offset 0x2280
+ 0x2280: 0x40067220, 0x2281: 0x40067320, 0x2282: 0x40067420, 0x2283: 0x40067520,
+ 0x2284: 0x40067620, 0x2285: 0x40067720, 0x2286: 0x40067820, 0x2287: 0x40067920,
+ 0x2288: 0x40067a20, 0x2289: 0x40067b20, 0x228a: 0x40067c20,
+ 0x22a0: 0xf0000006, 0x22a1: 0xf0000006, 0x22a2: 0xf0000006, 0x22a3: 0xf0000006,
+ 0x22a4: 0xf0000006, 0x22a5: 0xf0000006, 0x22a6: 0xf0000006, 0x22a7: 0xf0000006,
+ 0x22a8: 0xf0000006, 0x22a9: 0xf0000606, 0x22aa: 0xf0000606, 0x22ab: 0xf0000606,
+ 0x22ac: 0xf0000606, 0x22ad: 0xf0000606, 0x22ae: 0xf0000606, 0x22af: 0xf0000606,
+ 0x22b0: 0xf0000606, 0x22b1: 0xf0000606, 0x22b2: 0xf0000606, 0x22b3: 0xf0000606,
+ 0x22b4: 0xf0000404, 0x22b5: 0xf0000404, 0x22b6: 0xf0000404, 0x22b7: 0xf0000404,
+ 0x22b8: 0xf0000404, 0x22b9: 0xf0000404, 0x22ba: 0xf0000404, 0x22bb: 0xf0000404,
+ 0x22bc: 0xf0000404, 0x22bd: 0xf0000404, 0x22be: 0xf0000404, 0x22bf: 0xf0000404,
+ // Block 0x8b, offset 0x22c0
+ 0x22c0: 0xf0000404, 0x22c1: 0xf0000404, 0x22c2: 0xf0000404, 0x22c3: 0xf0000404,
+ 0x22c4: 0xf0000404, 0x22c5: 0xf0000404, 0x22c6: 0xf0000404, 0x22c7: 0xf0000404,
+ 0x22c8: 0xf0000404, 0x22c9: 0xf0000404, 0x22ca: 0xf0000404, 0x22cb: 0xf0000404,
+ 0x22cc: 0xf0000404, 0x22cd: 0xf0000404, 0x22ce: 0xf0000404, 0x22cf: 0xf0000404,
+ 0x22d0: 0xf0000404, 0x22d1: 0xf0000404, 0x22d2: 0xf0000404, 0x22d3: 0xf0000404,
+ 0x22d4: 0xf0000404, 0x22d5: 0xf0000404, 0x22d6: 0xf0000404, 0x22d7: 0xf0000404,
+ 0x22d8: 0xf0000404, 0x22d9: 0xf0000404, 0x22da: 0xf0000404, 0x22db: 0xf0000404,
+ 0x22dc: 0xf0000404, 0x22dd: 0xf0000404, 0x22de: 0xf0000404, 0x22df: 0xf0000404,
+ 0x22e0: 0xf0000404, 0x22e1: 0xf0000404, 0x22e2: 0xf0000404, 0x22e3: 0xf0000404,
+ 0x22e4: 0xf0000404, 0x22e5: 0xf0000404, 0x22e6: 0xf0000404, 0x22e7: 0xf0000404,
+ 0x22e8: 0xf0000404, 0x22e9: 0xf0000404, 0x22ea: 0xf0000404, 0x22eb: 0xf0000404,
+ 0x22ec: 0xf0000404, 0x22ed: 0xf0000404, 0x22ee: 0xf0000404, 0x22ef: 0xf0000404,
+ 0x22f0: 0xf0000404, 0x22f1: 0xf0000404, 0x22f2: 0xf0000404, 0x22f3: 0xf0000404,
+ 0x22f4: 0xf0000404, 0x22f5: 0xf0000404, 0x22f6: 0xf000000c, 0x22f7: 0xf000000c,
+ 0x22f8: 0xf000000c, 0x22f9: 0xf000000c, 0x22fa: 0xf000000c, 0x22fb: 0xf000000c,
+ 0x22fc: 0xf000000c, 0x22fd: 0xf000000c, 0x22fe: 0xf000000c, 0x22ff: 0xf000000c,
+ // Block 0x8c, offset 0x2300
+ 0x2300: 0xf000000c, 0x2301: 0xf000000c, 0x2302: 0xf000000c, 0x2303: 0xf000000c,
+ 0x2304: 0xf000000c, 0x2305: 0xf000000c, 0x2306: 0xf000000c, 0x2307: 0xf000000c,
+ 0x2308: 0xf000000c, 0x2309: 0xf000000c, 0x230a: 0xf000000c, 0x230b: 0xf000000c,
+ 0x230c: 0xf000000c, 0x230d: 0xf000000c, 0x230e: 0xf000000c, 0x230f: 0xf000000c,
+ 0x2310: 0xf0000006, 0x2311: 0xf0000006, 0x2312: 0xf0000006, 0x2313: 0xf0000006,
+ 0x2314: 0xf0000006, 0x2315: 0xf0000006, 0x2316: 0xf0000006, 0x2317: 0xf0000006,
+ 0x2318: 0xf0000006, 0x2319: 0xf0000006, 0x231a: 0xf0000006, 0x231b: 0xf0000006,
+ 0x231c: 0xf0000006, 0x231d: 0xf0000006, 0x231e: 0xf0000006, 0x231f: 0xf0000006,
+ 0x2320: 0xf0000006, 0x2321: 0xf0000006, 0x2322: 0xf0000006, 0x2323: 0xf0000006,
+ 0x2324: 0xf0000006, 0x2325: 0xf0000006, 0x2326: 0xf0000006, 0x2327: 0xf0000006,
+ 0x2328: 0xf0000006, 0x2329: 0xf0000006, 0x232a: 0xf0000006, 0x232b: 0xe0000168,
+ 0x232c: 0xe000016b, 0x232d: 0xe000016e, 0x232e: 0xe0000171, 0x232f: 0xe0000174,
+ 0x2330: 0xe0000177, 0x2331: 0xe000017a, 0x2332: 0xe000017d, 0x2333: 0xe0000180,
+ 0x2334: 0xe0000243, 0x2335: 0x00293606, 0x2336: 0x00293806, 0x2337: 0x00293a06,
+ 0x2338: 0x00293c06, 0x2339: 0x00293e06, 0x233a: 0x00294006, 0x233b: 0x00294206,
+ 0x233c: 0x00294406, 0x233d: 0x00294606, 0x233e: 0xe0000159, 0x233f: 0x00293406,
+ // Block 0x8d, offset 0x2340
+ 0x2340: 0x40067d20, 0x2341: 0x40067e20, 0x2342: 0x40067f20, 0x2343: 0x40068020,
+ 0x2344: 0x40068120, 0x2345: 0x40068220, 0x2346: 0x40068320, 0x2347: 0x40068420,
+ 0x2348: 0x40068520, 0x2349: 0x40068620, 0x234a: 0x40068720, 0x234b: 0x40068820,
+ 0x234c: 0x40068920, 0x234d: 0x40068a20, 0x234e: 0x40068b20, 0x234f: 0x40068c20,
+ 0x2350: 0x40068d20, 0x2351: 0x40068e20, 0x2352: 0x40068f20, 0x2353: 0x40069020,
+ 0x2354: 0x40069120, 0x2355: 0x40069220, 0x2356: 0x40069320, 0x2357: 0x40069420,
+ 0x2358: 0x40069520, 0x2359: 0x40069620, 0x235a: 0x40069720, 0x235b: 0x40069820,
+ 0x235c: 0x40069920, 0x235d: 0x40069a20, 0x235e: 0x40069b20, 0x235f: 0x40069c20,
+ 0x2360: 0x40069d20, 0x2361: 0x40069e20, 0x2362: 0x40069f20, 0x2363: 0x4006a020,
+ 0x2364: 0x4006a120, 0x2365: 0x4006a220, 0x2366: 0x4006a320, 0x2367: 0x4006a420,
+ 0x2368: 0x4006a520, 0x2369: 0x4006a620, 0x236a: 0x4006a720, 0x236b: 0x4006a820,
+ 0x236c: 0x4006a920, 0x236d: 0x4006aa20, 0x236e: 0x4006ab20, 0x236f: 0x4006ac20,
+ 0x2370: 0x4006ad20, 0x2371: 0x4006ae20, 0x2372: 0x4006af20, 0x2373: 0x4006b020,
+ 0x2374: 0x4006b120, 0x2375: 0x4006b220, 0x2376: 0x4006b320, 0x2377: 0x4006b420,
+ 0x2378: 0x4006b520, 0x2379: 0x4006b620, 0x237a: 0x4006b720, 0x237b: 0x4006b820,
+ 0x237c: 0x4006b920, 0x237d: 0x4006ba20, 0x237e: 0x4006bb20, 0x237f: 0x4006bc20,
+ // Block 0x8e, offset 0x2380
+ 0x2380: 0x4006bd20, 0x2381: 0x4006be20, 0x2382: 0x4006bf20, 0x2383: 0x4006c020,
+ 0x2384: 0x4006c120, 0x2385: 0x4006c220, 0x2386: 0x4006c320, 0x2387: 0x4006c420,
+ 0x2388: 0x4006c520, 0x2389: 0x4006c620, 0x238a: 0x4006c720, 0x238b: 0x4006c820,
+ 0x238c: 0x4006c920, 0x238d: 0x4006ca20, 0x238e: 0x4006cb20, 0x238f: 0x4006cc20,
+ 0x2390: 0x4006cd20, 0x2391: 0x4006ce20, 0x2392: 0x4006cf20, 0x2393: 0x4006d020,
+ 0x2394: 0x4006d120, 0x2395: 0x4006d220, 0x2396: 0x4006d320, 0x2397: 0x4006d420,
+ 0x2398: 0x4006d520, 0x2399: 0x4006d620, 0x239a: 0x4006d720, 0x239b: 0x4006d820,
+ 0x239c: 0x4006d920, 0x239d: 0x4006da20, 0x239e: 0x4006db20, 0x239f: 0x4006dc20,
+ 0x23a0: 0x4006dd20, 0x23a1: 0x4006de20, 0x23a2: 0x4006df20, 0x23a3: 0x4006e020,
+ 0x23a4: 0x4006e120, 0x23a5: 0x4006e220, 0x23a6: 0x4006e320, 0x23a7: 0x4006e420,
+ 0x23a8: 0x4006e520, 0x23a9: 0x4006e620, 0x23aa: 0x4006e720, 0x23ab: 0x4006e820,
+ 0x23ac: 0x4006e920, 0x23ad: 0x4006ea20, 0x23ae: 0x4006eb20, 0x23af: 0x4006ec20,
+ 0x23b0: 0x4006ed20, 0x23b1: 0x4006ee20, 0x23b2: 0x4006ef20, 0x23b3: 0x4006f020,
+ 0x23b4: 0x4006f120, 0x23b5: 0x4006f220, 0x23b6: 0x4006f320, 0x23b7: 0x4006f420,
+ 0x23b8: 0x4006f520, 0x23b9: 0x4006f620, 0x23ba: 0x4006f720, 0x23bb: 0x4006f820,
+ 0x23bc: 0x4006f920, 0x23bd: 0x4006fa20, 0x23be: 0x4006fb20, 0x23bf: 0x4006fc20,
+ // Block 0x8f, offset 0x23c0
+ 0x23c0: 0x4006fd20, 0x23c1: 0x4006fe20, 0x23c2: 0x4006ff20, 0x23c3: 0x40070020,
+ 0x23c4: 0x40070120, 0x23c5: 0x40070220, 0x23c6: 0x40070320, 0x23c7: 0x40070420,
+ 0x23c8: 0x40070520, 0x23c9: 0x40070620, 0x23ca: 0x40070720, 0x23cb: 0x40070820,
+ 0x23cc: 0x40070920, 0x23cd: 0x40070a20, 0x23ce: 0x40070b20, 0x23cf: 0x40070c20,
+ 0x23d0: 0x40070d20, 0x23d1: 0x40070e20, 0x23d2: 0x40070f20, 0x23d3: 0x40071020,
+ 0x23d4: 0x40071120, 0x23d5: 0x40071220, 0x23d6: 0x40071320, 0x23d7: 0x40071420,
+ 0x23d8: 0x40071520, 0x23d9: 0x40071620, 0x23da: 0x40071720, 0x23db: 0x40071820,
+ 0x23dc: 0x40071920, 0x23dd: 0x40071a20, 0x23de: 0x40071b20, 0x23df: 0x40071c20,
+ 0x23e0: 0x40071d20, 0x23e1: 0x40071e20, 0x23e2: 0x40071f20, 0x23e3: 0x40072020,
+ 0x23e4: 0x40072120, 0x23e5: 0x40072220, 0x23e6: 0x40072320, 0x23e7: 0x40072420,
+ 0x23e8: 0x40072520, 0x23e9: 0x40072620, 0x23ea: 0x40072720, 0x23eb: 0x40072820,
+ 0x23ec: 0x40072920, 0x23ed: 0x40072a20, 0x23ee: 0x40072b20, 0x23ef: 0x40072c20,
+ 0x23f0: 0x40072d20, 0x23f1: 0x40072e20, 0x23f2: 0x40072f20, 0x23f3: 0x40073020,
+ 0x23f4: 0x40073120, 0x23f5: 0x40073220, 0x23f6: 0x40073320, 0x23f7: 0x40073420,
+ 0x23f8: 0x40073520, 0x23f9: 0x40073620, 0x23fa: 0x40073720, 0x23fb: 0x40073820,
+ 0x23fc: 0x40073920, 0x23fd: 0x40073a20, 0x23fe: 0x40073b20, 0x23ff: 0x40073c20,
+ // Block 0x90, offset 0x2400
+ 0x2400: 0x40073d20, 0x2401: 0x40073e20, 0x2402: 0x40073f20, 0x2403: 0x40074020,
+ 0x2404: 0x40074120, 0x2405: 0x40074220, 0x2406: 0x40074320, 0x2407: 0x40074420,
+ 0x2408: 0x40074520, 0x2409: 0x40074620, 0x240a: 0x40074720, 0x240b: 0x40074820,
+ 0x240c: 0x40074920, 0x240d: 0x40074a20, 0x240e: 0x40074b20, 0x240f: 0x40074c20,
+ 0x2410: 0x40074d20, 0x2411: 0x40074e20, 0x2412: 0x40074f20, 0x2413: 0x40075020,
+ 0x2414: 0x40075120, 0x2415: 0x40075220, 0x2416: 0x40075320, 0x2417: 0x40075420,
+ 0x2418: 0x40075520, 0x2419: 0x40075620, 0x241a: 0x40075720, 0x241b: 0x40075820,
+ 0x241c: 0x40075920, 0x241d: 0x40075a20, 0x241e: 0x40075b20, 0x241f: 0x40075c20,
+ 0x2420: 0x40075d20, 0x2421: 0x40075e20, 0x2422: 0x40075f20, 0x2423: 0x40076020,
+ 0x2424: 0x40076120, 0x2425: 0x40076220, 0x2426: 0x40076320, 0x2427: 0x40076420,
+ 0x2428: 0x40076520, 0x2429: 0x40076620, 0x242a: 0x40076720, 0x242b: 0x40076820,
+ 0x242c: 0x40076920, 0x242d: 0x40076a20, 0x242e: 0x40076b20, 0x242f: 0x40076c20,
+ 0x2430: 0x40076d20, 0x2431: 0x40076e20, 0x2432: 0x40076f20, 0x2433: 0x40077020,
+ 0x2434: 0x40077120, 0x2435: 0x40077220, 0x2436: 0x40077320, 0x2437: 0x40077420,
+ 0x2438: 0x40077520, 0x2439: 0x40077620, 0x243a: 0x40077720, 0x243b: 0x40077820,
+ 0x243c: 0x40077920, 0x243d: 0x40077a20, 0x243e: 0x40077b20, 0x243f: 0x40077c20,
+ // Block 0x91, offset 0x2440
+ 0x2440: 0x40077d20, 0x2441: 0x40077e20, 0x2442: 0x40077f20, 0x2443: 0x40078020,
+ 0x2444: 0x40078120, 0x2445: 0x40078220, 0x2446: 0x40078320, 0x2447: 0x40078420,
+ 0x2448: 0x40078520, 0x2449: 0x40078620, 0x244a: 0x40078720, 0x244b: 0x40078820,
+ 0x244c: 0x40078920, 0x244d: 0x40078a20, 0x244e: 0x40078b20, 0x244f: 0x40078c20,
+ 0x2450: 0x40078d20, 0x2451: 0x40078e20, 0x2452: 0x40078f20, 0x2453: 0x40079020,
+ 0x2454: 0x40079120, 0x2455: 0x40079220, 0x2456: 0x40079320, 0x2457: 0x40079420,
+ 0x2458: 0x40079520, 0x2459: 0x40079620, 0x245a: 0x40079720, 0x245b: 0x40079820,
+ 0x245c: 0x40079920, 0x245d: 0x40079a20, 0x245e: 0x40079b20, 0x245f: 0x40079c20,
+ 0x2460: 0x40079d20, 0x2461: 0x40079e20, 0x2462: 0x40079f20, 0x2463: 0x4007a020,
+ 0x2464: 0x4007a120, 0x2465: 0x4007a220, 0x2466: 0x4007a320, 0x2467: 0x4007a420,
+ 0x2468: 0x4007a520, 0x2469: 0x4007a620, 0x246a: 0x4007a720, 0x246b: 0x4007a820,
+ 0x246c: 0x4007a920, 0x246d: 0x4007aa20, 0x246e: 0x4007ab20, 0x246f: 0x4007ac20,
+ 0x2470: 0x400c7320, 0x2471: 0x400c7420, 0x2472: 0x400c7520, 0x2473: 0x400c7620,
+ 0x2474: 0x400c7720, 0x2475: 0x400c7820, 0x2476: 0x400c7920, 0x2477: 0x400c7a20,
+ 0x2478: 0x4007ad20, 0x2479: 0x4007ae20, 0x247a: 0x4007af20, 0x247b: 0x4007b020,
+ 0x247c: 0x4007b120, 0x247d: 0x4007b220, 0x247e: 0x4007b320, 0x247f: 0x4007b420,
+ // Block 0x92, offset 0x2480
+ 0x2480: 0x4007b520, 0x2481: 0x4007b620, 0x2482: 0x4007b720, 0x2483: 0x4007b820,
+ 0x2484: 0x4007b920, 0x2485: 0x4007ba20, 0x2486: 0x4007bb20, 0x2487: 0x4007bc20,
+ 0x2488: 0x4007bd20, 0x2489: 0x4007be20, 0x248a: 0x4007bf20, 0x248b: 0x4007c020,
+ 0x248c: 0x4007c120, 0x248d: 0x4007c220, 0x248e: 0x4007c320, 0x248f: 0x4007c420,
+ 0x2490: 0x4007c520, 0x2491: 0x4007c620, 0x2492: 0x4007c720, 0x2493: 0x4007c820,
+ 0x2494: 0x4007c920, 0x2495: 0x4007ca20, 0x2496: 0x4007cb20, 0x2497: 0x4007cc20,
+ 0x2498: 0x4007cd20, 0x2499: 0x4007ce20, 0x249a: 0x4007cf20, 0x249b: 0x4007d020,
+ 0x249c: 0x4007d120, 0x249d: 0x4007d220, 0x249e: 0x4007d320, 0x249f: 0x4007d420,
+ 0x24a0: 0x4007d520, 0x24a1: 0x4007d620, 0x24a2: 0x4007d720, 0x24a3: 0x4007d820,
+ 0x24a4: 0x4007d920, 0x24a5: 0x4007da20, 0x24a6: 0x4007db20, 0x24a7: 0x4007dc20,
+ 0x24a8: 0x4007dd20, 0x24a9: 0x4007de20, 0x24aa: 0x4007df20, 0x24ab: 0x4007e020,
+ 0x24ac: 0x4007e120, 0x24ad: 0x400eb920, 0x24ae: 0x400eba20, 0x24af: 0x400ebb20,
+ 0x24b0: 0x4007e220, 0x24b1: 0x4007e320, 0x24b2: 0x4007e420, 0x24b3: 0x4007e520,
+ 0x24b4: 0x4007e620, 0x24b5: 0x4007e720, 0x24b6: 0x4007e820, 0x24b7: 0x4007e920,
+ 0x24b8: 0x4007ea20, 0x24b9: 0x4007eb20, 0x24ba: 0x4007ec20, 0x24bb: 0x4007ed20,
+ 0x24bc: 0x4007ee20, 0x24bd: 0x4007ef20, 0x24be: 0x4007f020, 0x24bf: 0x4007f120,
+ // Block 0x93, offset 0x24c0
+ 0x24c0: 0x4007f220, 0x24c1: 0x4007f320, 0x24c2: 0x4007f420, 0x24c3: 0x4007f520,
+ 0x24c4: 0x4007f620, 0x24c5: 0x4007f720, 0x24c6: 0x4007f820, 0x24c7: 0x4007f920,
+ 0x24c8: 0x4007fa20, 0x24c9: 0x4007fb20, 0x24ca: 0x400c6d20, 0x24cb: 0x400c6e20,
+ 0x24cc: 0x400c6f20, 0x24cd: 0x400c7020, 0x24ce: 0x400c7120, 0x24cf: 0x400c7220,
+ 0x24d0: 0x4007fc20, 0x24d1: 0x4007fd20, 0x24d2: 0x4007fe20, 0x24d3: 0x4007ff20,
+ 0x24d4: 0x40080020, 0x24d5: 0x40080120, 0x24d6: 0x40080220, 0x24d7: 0x40080320,
+ 0x24d8: 0x40080420, 0x24d9: 0x40080520, 0x24da: 0x40080620, 0x24db: 0x40080720,
+ 0x24dc: 0x40080820, 0x24dd: 0x40080920, 0x24de: 0x40080a20, 0x24df: 0x40080b20,
+ 0x24e0: 0x40080c20, 0x24e1: 0x40080d20, 0x24e2: 0x40080e20, 0x24e3: 0x40080f20,
+ 0x24e4: 0x40081020, 0x24e5: 0x40081120, 0x24e6: 0x40081220, 0x24e7: 0x40081320,
+ 0x24e8: 0x40081420, 0x24e9: 0x40081520, 0x24ea: 0x40081620, 0x24eb: 0x40081720,
+ 0x24ec: 0x40081820, 0x24ed: 0x40081920, 0x24ee: 0x40081a20, 0x24ef: 0x40081b20,
+ 0x24f0: 0x40081c20, 0x24f1: 0x40081d20, 0x24f2: 0x40081e20, 0x24f3: 0x40081f20,
+ 0x24f4: 0x40082020, 0x24f5: 0x40082120, 0x24f6: 0x40082220, 0x24f7: 0x40082320,
+ 0x24f8: 0x40082420, 0x24f9: 0x40082520, 0x24fa: 0x40082620, 0x24fb: 0x40082720,
+ 0x24fc: 0x40082820, 0x24fd: 0x40082920, 0x24fe: 0x40082a20, 0x24ff: 0x40082b20,
+ // Block 0x94, offset 0x2500
+ 0x2500: 0x40082c20, 0x2501: 0x40082d20, 0x2502: 0x40082e20, 0x2503: 0x40082f20,
+ 0x2504: 0x40083020, 0x2505: 0x40083120, 0x2506: 0x40083220, 0x2507: 0x40083320,
+ 0x2508: 0x40083420, 0x2509: 0x40083520, 0x250a: 0x40083620, 0x250b: 0x40083720,
+ 0x250c: 0x40083820, 0x250d: 0x40083920, 0x250e: 0x40083a20, 0x250f: 0x40083b20,
+ 0x2510: 0x40083c20, 0x2511: 0x40083d20, 0x2512: 0x40083e20, 0x2513: 0x40083f20,
+ 0x2514: 0x40084020, 0x2515: 0x40084120, 0x2516: 0x40084220, 0x2517: 0x40084320,
+ 0x2518: 0x40084420, 0x2519: 0x40084520, 0x251a: 0x40084620, 0x251b: 0x40084720,
+ 0x251c: 0x40084820, 0x251d: 0x40084920, 0x251e: 0x40084a20, 0x251f: 0x40084b20,
+ 0x2520: 0x40084c20, 0x2521: 0x40084d20, 0x2522: 0x40084e20, 0x2523: 0x40084f20,
+ 0x2524: 0x40085020, 0x2525: 0x40085120, 0x2526: 0x40085220, 0x2527: 0x40085320,
+ 0x2528: 0x40085420, 0x2529: 0x40085520, 0x252a: 0x40085620, 0x252b: 0x40085720,
+ 0x252c: 0x40085820, 0x252d: 0x40085920, 0x252e: 0x40085a20, 0x252f: 0x40085b20,
+ 0x2530: 0x40085c20, 0x2531: 0x40085d20, 0x2532: 0x40085e20, 0x2533: 0x40085f20,
+ 0x2534: 0x40086020, 0x2535: 0x40086120, 0x2536: 0x40086220, 0x2537: 0x40086320,
+ 0x2538: 0x40086420, 0x2539: 0x40086520, 0x253a: 0x40086620, 0x253b: 0x40086720,
+ 0x253c: 0x40086820, 0x253d: 0x40086920, 0x253e: 0x40086a20, 0x253f: 0x40086b20,
+ // Block 0x95, offset 0x2540
+ 0x2541: 0x40086c20, 0x2542: 0x40086d20, 0x2543: 0x40086e20,
+ 0x2544: 0x40086f20, 0x2545: 0x40087020, 0x2546: 0x40087120, 0x2547: 0x40087220,
+ 0x2548: 0x40087320, 0x2549: 0x40087420, 0x254a: 0x40087520, 0x254b: 0x40087620,
+ 0x254c: 0x40087720, 0x254d: 0x40087820, 0x254e: 0x40087920, 0x254f: 0x40087a20,
+ 0x2550: 0x40087b20, 0x2551: 0x40087c20, 0x2552: 0x40087d20, 0x2553: 0x40087e20,
+ 0x2554: 0x40087f20, 0x2555: 0x40088020, 0x2556: 0x40088120, 0x2557: 0x40088220,
+ 0x2558: 0x40088320, 0x2559: 0x40088420, 0x255a: 0x40088520, 0x255b: 0x40088620,
+ 0x255c: 0x40088720, 0x255d: 0x40088820, 0x255e: 0x40088920, 0x255f: 0x40088a20,
+ 0x2560: 0x40088b20, 0x2561: 0x40088c20, 0x2562: 0x40088d20, 0x2563: 0x40088e20,
+ 0x2564: 0x40088f20, 0x2565: 0x40089020, 0x2566: 0x40089120, 0x2567: 0x40089220,
+ 0x2568: 0x40089320, 0x2569: 0x40089420, 0x256a: 0x40089520, 0x256b: 0x40089620,
+ 0x256c: 0x40089720, 0x256d: 0x40089820, 0x256e: 0x40089920, 0x256f: 0x40089a20,
+ 0x2570: 0x40089b20, 0x2571: 0x40089c20, 0x2572: 0x40089d20, 0x2573: 0x40089e20,
+ 0x2574: 0x40089f20, 0x2575: 0x4008a020, 0x2576: 0x4008a120, 0x2577: 0x4008a220,
+ 0x2578: 0x4008a320, 0x2579: 0x4008a420, 0x257a: 0x4008a520, 0x257b: 0x4008a620,
+ 0x257c: 0x4008a720, 0x257d: 0x4008a820, 0x257e: 0x4008a920, 0x257f: 0x4008aa20,
+ // Block 0x96, offset 0x2580
+ 0x2580: 0x4008ab20, 0x2581: 0x4008ac20, 0x2582: 0x4008ad20, 0x2583: 0x4008ae20,
+ 0x2584: 0x4008af20, 0x2585: 0x4008b020, 0x2586: 0x4008b120, 0x2587: 0x4008b220,
+ 0x2588: 0x4008b320, 0x2589: 0x4008b420, 0x258a: 0x4008b520, 0x258b: 0x4008b620,
+ 0x258c: 0x4008b720, 0x258d: 0x4008b820, 0x258e: 0x4008b920, 0x258f: 0x4008ba20,
+ 0x2590: 0x4008bb20, 0x2591: 0x4008bc20, 0x2592: 0x4008bd20, 0x2593: 0x4008be20,
+ 0x2594: 0x4008bf20, 0x2595: 0x4008c020, 0x2596: 0x4008c120, 0x2597: 0x4008c220,
+ 0x2598: 0x4008c320, 0x2599: 0x4008c420, 0x259a: 0x4008c520, 0x259b: 0x4008c620,
+ 0x259c: 0x4008c720, 0x259d: 0x4008c820, 0x259e: 0x4008c920, 0x259f: 0x4008ca20,
+ 0x25a0: 0x4008cb20, 0x25a1: 0x4008cc20, 0x25a2: 0x4008cd20, 0x25a3: 0x4008ce20,
+ 0x25a4: 0x4008cf20, 0x25a5: 0x4008d020, 0x25a6: 0x4008d120, 0x25a7: 0x4008d220,
+ 0x25a8: 0x4002d320, 0x25a9: 0x4002d420, 0x25aa: 0x4002d520, 0x25ab: 0x4002d620,
+ 0x25ac: 0x4002d720, 0x25ad: 0x4002d820, 0x25ae: 0x4002d920, 0x25af: 0x4002da20,
+ 0x25b0: 0x4002db20, 0x25b1: 0x4002dc20, 0x25b2: 0x4002dd20, 0x25b3: 0x4002de20,
+ 0x25b4: 0x4002df20, 0x25b5: 0x4002e020, 0x25b6: 0x00293606, 0x25b7: 0x00293806,
+ 0x25b8: 0x00293a06, 0x25b9: 0x00293c06, 0x25ba: 0x00293e06, 0x25bb: 0x00294006,
+ 0x25bc: 0x00294206, 0x25bd: 0x00294406, 0x25be: 0x00294606, 0x25bf: 0xe000015c,
+ // Block 0x97, offset 0x25c0
+ 0x25c0: 0x00293606, 0x25c1: 0x00293806, 0x25c2: 0x00293a06, 0x25c3: 0x00293c06,
+ 0x25c4: 0x00293e06, 0x25c5: 0x00294006, 0x25c6: 0x00294206, 0x25c7: 0x00294406,
+ 0x25c8: 0x00294606, 0x25c9: 0xe000015f, 0x25ca: 0x00293606, 0x25cb: 0x00293806,
+ 0x25cc: 0x00293a06, 0x25cd: 0x00293c06, 0x25ce: 0x00293e06, 0x25cf: 0x00294006,
+ 0x25d0: 0x00294206, 0x25d1: 0x00294406, 0x25d2: 0x00294606, 0x25d3: 0xe0000162,
+ 0x25d4: 0x4008d320, 0x25d5: 0x4008d420, 0x25d6: 0x4008d520, 0x25d7: 0x4008d620,
+ 0x25d8: 0x4008d720, 0x25d9: 0x4008d820, 0x25da: 0x4008d920, 0x25db: 0x4008da20,
+ 0x25dc: 0x4008db20, 0x25dd: 0x4008dc20, 0x25de: 0x4008dd20, 0x25df: 0x4008de20,
+ 0x25e0: 0x4008df20, 0x25e1: 0x4008e020, 0x25e2: 0x4008e120, 0x25e3: 0x4008e220,
+ 0x25e4: 0x4008e320, 0x25e5: 0x4008e420, 0x25e6: 0x4008e520, 0x25e7: 0x4008e620,
+ 0x25e8: 0x4008e720, 0x25e9: 0x4008e820, 0x25ea: 0x4008e920, 0x25eb: 0x4008ea20,
+ 0x25ec: 0x4008eb20, 0x25ed: 0x4008ec20, 0x25ee: 0x4008ed20, 0x25ef: 0x4008ee20,
+ 0x25f0: 0x4008ef20, 0x25f1: 0x4008f020, 0x25f2: 0x4008f120, 0x25f3: 0x4008f220,
+ 0x25f4: 0x4008f320, 0x25f5: 0x4008f420, 0x25f6: 0x4008f520, 0x25f7: 0x4008f620,
+ 0x25f8: 0x4008f720, 0x25f9: 0x4008f820, 0x25fa: 0x4008f920, 0x25fb: 0x4008fa20,
+ 0x25fc: 0x4008fb20, 0x25fd: 0x4008fc20, 0x25fe: 0x4008fd20, 0x25ff: 0x4008fe20,
+ // Block 0x98, offset 0x2600
+ 0x2600: 0x4008ff20, 0x2601: 0x40090020, 0x2602: 0x40090120, 0x2603: 0x40090220,
+ 0x2604: 0x40090320, 0x2605: 0x4002e120, 0x2606: 0x4002e220, 0x2607: 0x40090420,
+ 0x2608: 0x40090520, 0x2609: 0x40090620, 0x260a: 0x40090720,
+ 0x260c: 0x40090820, 0x260e: 0x40090920, 0x260f: 0x40090a20,
+ 0x2610: 0x40090b20, 0x2611: 0x40090c20, 0x2612: 0x40090d20, 0x2613: 0x40090e20,
+ 0x2614: 0x40090f20, 0x2615: 0x40091020, 0x2616: 0x40091120, 0x2617: 0x40091220,
+ 0x2618: 0x40091320, 0x2619: 0x40091420, 0x261a: 0x40091520, 0x261b: 0x40091620,
+ 0x261c: 0x40091720, 0x261d: 0x40091820, 0x261e: 0x40091920, 0x261f: 0x40091a20,
+ 0x2620: 0x40091b20, 0x2621: 0x40091c20, 0x2622: 0x40091d20, 0x2623: 0x40091e20,
+ 0x2624: 0x40091f20, 0x2625: 0x40092020, 0x2626: 0x4002e320, 0x2627: 0x4002e420,
+ 0x2628: 0x4002e520, 0x2629: 0x4002e620, 0x262a: 0x4002e720, 0x262b: 0x4002e820,
+ 0x262c: 0x40020f20, 0x262d: 0x40021020, 0x262e: 0x40021120, 0x262f: 0x40021220,
+ 0x2630: 0x40092120, 0x2631: 0x40092220, 0x2632: 0x40092320, 0x2633: 0x40092420,
+ 0x2634: 0x40092520, 0x2635: 0x40092620, 0x2636: 0x40092720, 0x2637: 0x40092820,
+ 0x2638: 0x40092920, 0x2639: 0x40092a20, 0x263a: 0x40092b20, 0x263b: 0x40092c20,
+ 0x263c: 0x40092d20, 0x263d: 0x40092e20, 0x263e: 0x40092f20, 0x263f: 0x40093020,
+ // Block 0x99, offset 0x2640
+ 0x2640: 0x400b6d20, 0x2641: 0x400b6e20, 0x2642: 0x400b6f20, 0x2643: 0x400b7020,
+ 0x2644: 0x400b7120, 0x2645: 0x400b7220, 0x2646: 0x400b7320, 0x2647: 0x400b7420,
+ 0x2648: 0x400b7520, 0x2649: 0x400b7620, 0x264a: 0x400b7720, 0x264b: 0x400b7820,
+ 0x264c: 0x400b7920, 0x264d: 0x400b7a20, 0x264e: 0x400b7b20, 0x264f: 0x400b7c20,
+ 0x2650: 0x400b7d20, 0x2651: 0x400b7e20, 0x2652: 0x400b7f20, 0x2653: 0x400b8020,
+ 0x2654: 0x400b8120, 0x2655: 0x400b8220, 0x2656: 0x400b8320, 0x2657: 0x400b8420,
+ 0x2658: 0x400b8520, 0x2659: 0x400b8620, 0x265a: 0x400b8720, 0x265b: 0x400b8820,
+ 0x265c: 0x400b8920, 0x265d: 0x400b8a20, 0x265e: 0x400b8b20, 0x265f: 0x400b8c20,
+ 0x2660: 0x400b8d20, 0x2661: 0x400b8e20, 0x2662: 0x400b8f20, 0x2663: 0x400b9020,
+ 0x2664: 0x400b9120, 0x2665: 0x400b9220, 0x2666: 0x400b9320, 0x2667: 0x400b9420,
+ 0x2668: 0x400b9520, 0x2669: 0x400b9620, 0x266a: 0x400b9720, 0x266b: 0x400b9820,
+ 0x266c: 0x400b9920, 0x266d: 0x400b9a20, 0x266e: 0x400b9b20, 0x266f: 0x400b9c20,
+ 0x2670: 0x400b9d20, 0x2671: 0x400b9e20, 0x2672: 0x400b9f20, 0x2673: 0x400ba020,
+ 0x2674: 0x400ba120, 0x2675: 0x400ba220, 0x2676: 0x400ba320, 0x2677: 0x400ba420,
+ 0x2678: 0x400ba520, 0x2679: 0x400ba620, 0x267a: 0x400ba720, 0x267b: 0x400ba820,
+ 0x267c: 0x400ba920, 0x267d: 0x400baa20, 0x267e: 0x400bab20, 0x267f: 0x400bac20,
+ // Block 0x9a, offset 0x2680
+ 0x2680: 0x400bad20, 0x2681: 0x400bae20, 0x2682: 0x400baf20, 0x2683: 0x400bb020,
+ 0x2684: 0x400bb120, 0x2685: 0x400bb220, 0x2686: 0x400bb320, 0x2687: 0x400bb420,
+ 0x2688: 0x400bb520, 0x2689: 0x400bb620, 0x268a: 0x400bb720, 0x268b: 0x400bb820,
+ 0x268c: 0x400bb920, 0x268d: 0x400bba20, 0x268e: 0x400bbb20, 0x268f: 0x400bbc20,
+ 0x2690: 0x400bbd20, 0x2691: 0x400bbe20, 0x2692: 0x400bbf20, 0x2693: 0x400bc020,
+ 0x2694: 0x400bc120, 0x2695: 0x400bc220, 0x2696: 0x400bc320, 0x2697: 0x400bc420,
+ 0x2698: 0x400bc520, 0x2699: 0x400bc620, 0x269a: 0x400bc720, 0x269b: 0x400bc820,
+ 0x269c: 0x400bc920, 0x269d: 0x400bca20, 0x269e: 0x400bcb20, 0x269f: 0x400bcc20,
+ 0x26a0: 0x400bcd20, 0x26a1: 0x400bce20, 0x26a2: 0x400bcf20, 0x26a3: 0x400bd020,
+ 0x26a4: 0x400bd120, 0x26a5: 0x400bd220, 0x26a6: 0x400bd320, 0x26a7: 0x400bd420,
+ 0x26a8: 0x400bd520, 0x26a9: 0x400bd620, 0x26aa: 0x400bd720, 0x26ab: 0x400bd820,
+ 0x26ac: 0x400bd920, 0x26ad: 0x400bda20, 0x26ae: 0x400bdb20, 0x26af: 0x400bdc20,
+ 0x26b0: 0x400bdd20, 0x26b1: 0x400bde20, 0x26b2: 0x400bdf20, 0x26b3: 0x400be020,
+ 0x26b4: 0x400be120, 0x26b5: 0x400be220, 0x26b6: 0x400be320, 0x26b7: 0x400be420,
+ 0x26b8: 0x400be520, 0x26b9: 0x400be620, 0x26ba: 0x400be720, 0x26bb: 0x400be820,
+ 0x26bc: 0x400be920, 0x26bd: 0x400bea20, 0x26be: 0x400beb20, 0x26bf: 0x400bec20,
+ // Block 0x9b, offset 0x26c0
+ 0x26c0: 0x400bed20, 0x26c1: 0x400bee20, 0x26c2: 0x400bef20, 0x26c3: 0x400bf020,
+ 0x26c4: 0x400bf120, 0x26c5: 0x400bf220, 0x26c6: 0x400bf320, 0x26c7: 0x400bf420,
+ 0x26c8: 0x400bf520, 0x26c9: 0x400bf620, 0x26ca: 0x400bf720, 0x26cb: 0x400bf820,
+ 0x26cc: 0x400bf920, 0x26cd: 0x400bfa20, 0x26ce: 0x400bfb20, 0x26cf: 0x400bfc20,
+ 0x26d0: 0x400bfd20, 0x26d1: 0x400bfe20, 0x26d2: 0x400bff20, 0x26d3: 0x400c0020,
+ 0x26d4: 0x400c0120, 0x26d5: 0x400c0220, 0x26d6: 0x400c0320, 0x26d7: 0x400c0420,
+ 0x26d8: 0x400c0520, 0x26d9: 0x400c0620, 0x26da: 0x400c0720, 0x26db: 0x400c0820,
+ 0x26dc: 0x400c0920, 0x26dd: 0x400c0a20, 0x26de: 0x400c0b20, 0x26df: 0x400c0c20,
+ 0x26e0: 0x400c0d20, 0x26e1: 0x400c0e20, 0x26e2: 0x400c0f20, 0x26e3: 0x400c1020,
+ 0x26e4: 0x400c1120, 0x26e5: 0x400c1220, 0x26e6: 0x400c1320, 0x26e7: 0x400c1420,
+ 0x26e8: 0x400c1520, 0x26e9: 0x400c1620, 0x26ea: 0x400c1720, 0x26eb: 0x400c1820,
+ 0x26ec: 0x400c1920, 0x26ed: 0x400c1a20, 0x26ee: 0x400c1b20, 0x26ef: 0x400c1c20,
+ 0x26f0: 0x400c1d20, 0x26f1: 0x400c1e20, 0x26f2: 0x400c1f20, 0x26f3: 0x400c2020,
+ 0x26f4: 0x400c2120, 0x26f5: 0x400c2220, 0x26f6: 0x400c2320, 0x26f7: 0x400c2420,
+ 0x26f8: 0x400c2520, 0x26f9: 0x400c2620, 0x26fa: 0x400c2720, 0x26fb: 0x400c2820,
+ 0x26fc: 0x400c2920, 0x26fd: 0x400c2a20, 0x26fe: 0x400c2b20, 0x26ff: 0x400c2c20,
+ // Block 0x9c, offset 0x2700
+ 0x2700: 0x400c2d20, 0x2701: 0x400c2e20, 0x2702: 0x400c2f20, 0x2703: 0x400c3020,
+ 0x2704: 0x400c3120, 0x2705: 0x400c3220, 0x2706: 0x400c3320, 0x2707: 0x400c3420,
+ 0x2708: 0x400c3520, 0x2709: 0x400c3620, 0x270a: 0x400c3720, 0x270b: 0x400c3820,
+ 0x270c: 0x400c3920, 0x270d: 0x400c3a20, 0x270e: 0x400c3b20, 0x270f: 0x400c3c20,
+ 0x2710: 0x400c3d20, 0x2711: 0x400c3e20, 0x2712: 0x400c3f20, 0x2713: 0x400c4020,
+ 0x2714: 0x400c4120, 0x2715: 0x400c4220, 0x2716: 0x400c4320, 0x2717: 0x400c4420,
+ 0x2718: 0x400c4520, 0x2719: 0x400c4620, 0x271a: 0x400c4720, 0x271b: 0x400c4820,
+ 0x271c: 0x400c4920, 0x271d: 0x400c4a20, 0x271e: 0x400c4b20, 0x271f: 0x400c4c20,
+ 0x2720: 0x400c4d20, 0x2721: 0x400c4e20, 0x2722: 0x400c4f20, 0x2723: 0x400c5020,
+ 0x2724: 0x400c5120, 0x2725: 0x400c5220, 0x2726: 0x400c5320, 0x2727: 0x400c5420,
+ 0x2728: 0x400c5520, 0x2729: 0x400c5620, 0x272a: 0x400c5720, 0x272b: 0x400c5820,
+ 0x272c: 0x400c5920, 0x272d: 0x400c5a20, 0x272e: 0x400c5b20, 0x272f: 0x400c5c20,
+ 0x2730: 0x400c5d20, 0x2731: 0x400c5e20, 0x2732: 0x400c5f20, 0x2733: 0x400c6020,
+ 0x2734: 0x400c6120, 0x2735: 0x400c6220, 0x2736: 0x400c6320, 0x2737: 0x400c6420,
+ 0x2738: 0x400c6520, 0x2739: 0x400c6620, 0x273a: 0x400c6720, 0x273b: 0x400c6820,
+ 0x273c: 0x400c6920, 0x273d: 0x400c6a20, 0x273e: 0x400c6b20, 0x273f: 0x400c6c20,
+ // Block 0x9d, offset 0x2740
+ 0x2740: 0x40093120, 0x2741: 0x40093220, 0x2742: 0x40093320, 0x2743: 0x40093420,
+ 0x2744: 0x40093520, 0x2745: 0x40093620, 0x2746: 0x40093720, 0x2747: 0x40093820,
+ 0x2748: 0x40093920, 0x2749: 0x40093a20, 0x274a: 0x40093b20, 0x274b: 0x40093c20,
+ 0x274c: 0x40093d20, 0x274d: 0x40093e20, 0x274e: 0x40093f20, 0x274f: 0x40094020,
+ 0x2750: 0x40094120, 0x2751: 0x40094220, 0x2752: 0x40094320, 0x2753: 0x40094420,
+ 0x2754: 0x40094520, 0x2755: 0x40094620, 0x2756: 0x40094720, 0x2757: 0x40094820,
+ 0x2758: 0x40094920, 0x2759: 0x40094a20, 0x275a: 0x40094b20, 0x275b: 0x40094c20,
+ 0x275c: 0x40094d20, 0x275d: 0x40094e20, 0x275e: 0x40094f20, 0x275f: 0x40095020,
+ 0x2760: 0x40095120, 0x2761: 0x40095220, 0x2762: 0x40095320, 0x2763: 0x40095420,
+ 0x2764: 0x40095520, 0x2765: 0x40095620, 0x2766: 0x40095720, 0x2767: 0x40095820,
+ 0x2768: 0x40095920, 0x2769: 0x40095a20, 0x276a: 0x40095b20, 0x276b: 0x40095c20,
+ 0x276c: 0x40095d20, 0x276d: 0x40095e20, 0x276e: 0x40095f20, 0x276f: 0x40096020,
+ 0x2770: 0x40096120, 0x2771: 0x40096220, 0x2772: 0x40096320, 0x2773: 0x40096420,
+ 0x2774: 0x40096520, 0x2775: 0x40096620, 0x2776: 0x40096720, 0x2777: 0x40096820,
+ 0x2778: 0x40096920, 0x2779: 0x40096a20, 0x277a: 0x40096b20, 0x277b: 0x40096c20,
+ 0x277c: 0x40096d20, 0x277d: 0x40096e20, 0x277e: 0x40096f20, 0x277f: 0x40097020,
+ // Block 0x9e, offset 0x2780
+ 0x2780: 0x40097120, 0x2781: 0x40097220, 0x2782: 0x40097320, 0x2783: 0x40097420,
+ 0x2784: 0x40097520, 0x2785: 0x40097620, 0x2786: 0x40097720, 0x2787: 0x40097820,
+ 0x2788: 0x40097920, 0x2789: 0x40097a20, 0x278a: 0x40097b20, 0x278b: 0x40097c20,
+ 0x278c: 0x40097d20, 0x278d: 0x40097e20, 0x278e: 0x40097f20, 0x278f: 0x40098020,
+ 0x2790: 0x40098120, 0x2791: 0x40098220, 0x2792: 0x40098320, 0x2793: 0x40098420,
+ 0x2794: 0x40098520, 0x2795: 0x40098620, 0x2796: 0x40098720, 0x2797: 0x40098820,
+ 0x2798: 0x40098920, 0x2799: 0x40098a20, 0x279a: 0x40098b20, 0x279b: 0x40098c20,
+ 0x279c: 0x40098d20, 0x279d: 0x40098e20, 0x279e: 0x40098f20, 0x279f: 0x40099020,
+ 0x27a0: 0x40099120, 0x27a1: 0x40099220, 0x27a2: 0x40099320, 0x27a3: 0x40099420,
+ 0x27a4: 0x40099520, 0x27a5: 0x40099620, 0x27a6: 0x40099720, 0x27a7: 0x40099820,
+ 0x27a8: 0x40099920, 0x27a9: 0x40099a20, 0x27aa: 0x40099b20, 0x27ab: 0x40099c20,
+ 0x27ac: 0x40099d20, 0x27ad: 0x40099e20, 0x27ae: 0x40099f20, 0x27af: 0x4009a020,
+ 0x27b0: 0x4009a120, 0x27b1: 0x4009a220, 0x27b2: 0x4009a320, 0x27b3: 0x4009a420,
+ 0x27b4: 0x4009a520, 0x27b5: 0x4009a620, 0x27b6: 0x4009a720, 0x27b7: 0x4009a820,
+ 0x27b8: 0x4009a920, 0x27b9: 0x4009aa20, 0x27ba: 0x4009ab20, 0x27bb: 0x4009ac20,
+ 0x27bc: 0x4009ad20, 0x27bd: 0x4009ae20, 0x27be: 0x4009af20, 0x27bf: 0x4009b020,
+ // Block 0x9f, offset 0x27c0
+ 0x27c0: 0x4009b120, 0x27c1: 0x4009b220, 0x27c2: 0x4009b320, 0x27c3: 0x4001f920,
+ 0x27c4: 0x4001fa20, 0x27c5: 0x4001fb20, 0x27c6: 0x4001fc20, 0x27c7: 0x4001fd20,
+ 0x27c8: 0x4001fe20, 0x27c9: 0x4001ff20, 0x27ca: 0x40020020, 0x27cb: 0x40020120,
+ 0x27cc: 0x40020220, 0x27cd: 0x40020320, 0x27ce: 0x40020420, 0x27cf: 0x40020520,
+ 0x27d0: 0x40020620, 0x27d1: 0x40020720, 0x27d2: 0x40020820, 0x27d3: 0x40020920,
+ 0x27d4: 0x40020a20, 0x27d5: 0x40020b20, 0x27d6: 0x40020c20, 0x27d7: 0x40020d20,
+ 0x27d8: 0x40020e20, 0x27d9: 0x4009b420, 0x27da: 0x4009b520, 0x27db: 0x4009b620,
+ 0x27dc: 0x4009b720, 0x27dd: 0x4009b820, 0x27de: 0x4009b920, 0x27df: 0x4009ba20,
+ 0x27e0: 0x4009bb20, 0x27e1: 0x4009bc20, 0x27e2: 0x4009bd20, 0x27e3: 0x4009be20,
+ 0x27e4: 0x4009bf20, 0x27e5: 0x4009c020, 0x27e6: 0x4009c120, 0x27e7: 0x4009c220,
+ 0x27e8: 0x4009c320, 0x27e9: 0x4009c420, 0x27ea: 0x4009c520, 0x27eb: 0x4009c620,
+ 0x27ec: 0x4009c720, 0x27ed: 0x4009c820, 0x27ee: 0x4009c920, 0x27ef: 0x4009ca20,
+ 0x27f0: 0x4009cb20, 0x27f1: 0x4009cc20, 0x27f2: 0x4009cd20, 0x27f3: 0x4009ce20,
+ 0x27f4: 0x4009cf20, 0x27f5: 0x4009d020, 0x27f6: 0x4009d120, 0x27f7: 0x4009d220,
+ 0x27f8: 0x4009d320, 0x27f9: 0x4009d420, 0x27fa: 0x4009d520, 0x27fb: 0x4009d620,
+ 0x27fc: 0x4009d720, 0x27fd: 0x4009d820, 0x27fe: 0x4009d920, 0x27ff: 0x4009da20,
+ // Block 0xa0, offset 0x2800
+ 0x2800: 0x4009db20, 0x2801: 0x4009dc20, 0x2802: 0x4009dd20, 0x2803: 0x4009de20,
+ 0x2804: 0x4009df20, 0x2805: 0x4009e020, 0x2806: 0x4009e120, 0x2807: 0x4009e220,
+ 0x2808: 0x4009e320, 0x2809: 0x4009e420, 0x280a: 0x4009e520, 0x280b: 0x4009e620,
+ 0x280c: 0x4009e720, 0x280d: 0x4009e820, 0x280e: 0x4009e920, 0x280f: 0x4009ea20,
+ 0x2810: 0x4009eb20, 0x2811: 0x4009ec20, 0x2812: 0x4009ed20, 0x2813: 0x4009ee20,
+ 0x2814: 0x4009ef20, 0x2815: 0x4009f020, 0x2816: 0x4009f120, 0x2817: 0x4009f220,
+ 0x2818: 0x4002e920, 0x2819: 0x4002ea20, 0x281a: 0x4002eb20, 0x281b: 0x4002ec20,
+ 0x281c: 0x4009f320, 0x281d: 0x4009f420, 0x281e: 0x4009f520, 0x281f: 0x4009f620,
+ 0x2820: 0x4009f720, 0x2821: 0x4009f820, 0x2822: 0x4009f920, 0x2823: 0x4009fa20,
+ 0x2824: 0x4009fb20, 0x2825: 0x4009fc20, 0x2826: 0x4009fd20, 0x2827: 0x4009fe20,
+ 0x2828: 0x4009ff20, 0x2829: 0x400a0020, 0x282a: 0x400a0120, 0x282b: 0x400a0220,
+ 0x282c: 0x400a0320, 0x282d: 0x400a0420, 0x282e: 0x400a0520, 0x282f: 0x400a0620,
+ 0x2830: 0x400a0720, 0x2831: 0x400a0820, 0x2832: 0x400a0920, 0x2833: 0x400a0a20,
+ 0x2834: 0x400a0b20, 0x2835: 0x400a0c20, 0x2836: 0x400a0d20, 0x2837: 0x400a0e20,
+ 0x2838: 0x400a0f20, 0x2839: 0x400a1020, 0x283a: 0x400a1120, 0x283b: 0x400a1220,
+ 0x283c: 0x4001f720, 0x283d: 0x4001f820, 0x283e: 0x400a1320, 0x283f: 0x400a1420,
+ // Block 0xa1, offset 0x2840
+ 0x2840: 0x400a1520, 0x2841: 0x400a1620, 0x2842: 0x400a1720, 0x2843: 0x400a1820,
+ 0x2844: 0x400a1920, 0x2845: 0x400a1a20, 0x2846: 0x400a1b20, 0x2847: 0x400a1c20,
+ 0x2848: 0x400a1d20, 0x2849: 0x400a1e20, 0x284a: 0x400a1f20, 0x284b: 0x400a2020,
+ 0x284c: 0xf0000404, 0x284d: 0x400a2120, 0x284e: 0x400a2220, 0x284f: 0x400a2320,
+ 0x2850: 0x400a2420, 0x2851: 0x400a2520, 0x2852: 0x400a2620, 0x2853: 0x400a2720,
+ 0x2854: 0x400a2820, 0x2855: 0x400a2920, 0x2856: 0x400a2a20, 0x2857: 0x400a2b20,
+ 0x2858: 0x400a2c20, 0x2859: 0x400a2d20, 0x285a: 0x400a2e20, 0x285b: 0x400a2f20,
+ 0x285c: 0x400a3020, 0x285d: 0x400a3120, 0x285e: 0x400a3220, 0x285f: 0x400a3320,
+ 0x2860: 0x400a3420, 0x2861: 0x400a3520, 0x2862: 0x400a3620, 0x2863: 0x400a3720,
+ 0x2864: 0x400a3820, 0x2865: 0x400a3920, 0x2866: 0x400a3a20, 0x2867: 0x400a3b20,
+ 0x2868: 0x400a3c20, 0x2869: 0x400a3d20, 0x286a: 0x400a3e20, 0x286b: 0x400a3f20,
+ 0x286c: 0x400a4020, 0x286d: 0x400a4120, 0x286e: 0x400a4220, 0x286f: 0x400a4320,
+ 0x2870: 0x400a4420, 0x2871: 0x400a4520, 0x2872: 0x400a4620, 0x2873: 0x400a4720,
+ 0x2874: 0x400a4820, 0x2875: 0x400a4920, 0x2876: 0x400a4a20, 0x2877: 0x400a4b20,
+ 0x2878: 0x400a4c20, 0x2879: 0x400a4d20, 0x287a: 0x400a4e20, 0x287b: 0x400a4f20,
+ 0x287c: 0x400a5020, 0x287d: 0x400a5120, 0x287e: 0x400a5220, 0x287f: 0x400a5320,
+ // Block 0xa2, offset 0x2880
+ 0x2880: 0x400a5420, 0x2881: 0x400a5520, 0x2882: 0x400a5620, 0x2883: 0x400a5720,
+ 0x2884: 0x400a5820, 0x2885: 0x400a5920, 0x2886: 0x400a5a20, 0x2887: 0x400a5b20,
+ 0x2888: 0x400a5c20, 0x2889: 0x400a5d20, 0x288a: 0x400a5e20, 0x288b: 0x400a5f20,
+ 0x288c: 0x400a6020, 0x288d: 0x400a6120, 0x288e: 0x400a6220, 0x288f: 0x400a6320,
+ 0x2890: 0x400a6420, 0x2891: 0x400a6520, 0x2892: 0x400a6620, 0x2893: 0x400a6720,
+ 0x2894: 0x400a6820, 0x2895: 0x400a6920, 0x2896: 0x400a6a20, 0x2897: 0x400a6b20,
+ 0x2898: 0x400a6c20, 0x2899: 0x400a6d20, 0x289a: 0x400a6e20, 0x289b: 0x400a6f20,
+ 0x289c: 0x400a7020, 0x289d: 0x400a7120, 0x289e: 0x400a7220, 0x289f: 0x400a7320,
+ 0x28a0: 0x400a7420, 0x28a1: 0x400a7520, 0x28a2: 0x400a7620, 0x28a3: 0x400a7720,
+ 0x28a4: 0x400a7820, 0x28a5: 0x400a7920, 0x28a6: 0x400a7a20, 0x28a7: 0x400a7b20,
+ 0x28a8: 0x400a7c20, 0x28a9: 0x400a7d20, 0x28aa: 0x400a7e20, 0x28ab: 0x400a7f20,
+ 0x28ac: 0x400a8020, 0x28ad: 0x400a8120, 0x28ae: 0x400a8220, 0x28af: 0x400a8320,
+ 0x28b0: 0x400a8420, 0x28b1: 0x400a8520, 0x28b2: 0x400a8620, 0x28b3: 0x400a8720,
+ 0x28b4: 0xf0000404, 0x28b5: 0xf0000404, 0x28b6: 0xf0000404, 0x28b7: 0x400a8820,
+ 0x28b8: 0x400a8920, 0x28b9: 0x400a8a20, 0x28ba: 0x400a8b20, 0x28bb: 0x400a8c20,
+ 0x28bc: 0x400a8d20, 0x28bd: 0x400a8e20, 0x28be: 0x400a8f20, 0x28bf: 0x400a9020,
+ // Block 0xa3, offset 0x28c0
+ 0x28c0: 0x400a9120, 0x28c1: 0x400a9220, 0x28c2: 0x400a9320, 0x28c3: 0x400a9420,
+ 0x28c4: 0x400a9520, 0x28c5: 0x400a9620, 0x28c6: 0x400a9720, 0x28c7: 0x400a9820,
+ 0x28c8: 0x400a9920, 0x28c9: 0x400a9a20, 0x28ca: 0x400a9b20, 0x28cb: 0x400a9c20,
+ 0x28cc: 0x400a9d20, 0x28cd: 0x400a9e20, 0x28ce: 0x400a9f20, 0x28cf: 0x400aa020,
+ 0x28d0: 0x400aa120, 0x28d1: 0x400aa220, 0x28d2: 0x400aa320, 0x28d3: 0x400aa420,
+ 0x28d4: 0x400aa520, 0x28d5: 0x400aa620, 0x28d6: 0x400aa720, 0x28d7: 0x400aa820,
+ 0x28d8: 0x400aa920, 0x28d9: 0x400aaa20, 0x28da: 0x400aab20, 0x28db: 0x400aac20,
+ 0x28dc: 0x400aad20, 0x28dd: 0x400aae20, 0x28de: 0x400aaf20, 0x28df: 0x400ab020,
+ 0x28e0: 0x400ab120, 0x28e1: 0x400ab220, 0x28e2: 0x400ab320, 0x28e3: 0x400ab420,
+ 0x28e4: 0x400ab520, 0x28e5: 0x400ab620, 0x28e6: 0x400ab720, 0x28e7: 0x400ab820,
+ 0x28e8: 0x400ab920, 0x28e9: 0x400aba20, 0x28ea: 0x400abb20, 0x28eb: 0x400abc20,
+ 0x28ec: 0x400abd20, 0x28ed: 0x400abe20, 0x28ee: 0x400abf20, 0x28ef: 0x400ac020,
+ 0x28f0: 0x400ac120, 0x28f1: 0x400ac220, 0x28f2: 0x400ac320, 0x28f3: 0x400ac420,
+ 0x28f4: 0x400ac520, 0x28f5: 0x400ac620, 0x28f6: 0x400ac720, 0x28f7: 0x400ac820,
+ 0x28f8: 0x400ac920, 0x28f9: 0x400aca20, 0x28fa: 0x400acb20, 0x28fb: 0x400acc20,
+ 0x28fc: 0x400acd20, 0x28fd: 0x400ace20, 0x28fe: 0x400acf20, 0x28ff: 0x400ad020,
+ // Block 0xa4, offset 0x2900
+ 0x2900: 0x400ad120, 0x2901: 0x400ad220, 0x2902: 0x400ad320, 0x2903: 0x400ad420,
+ 0x2904: 0x400ad520, 0x2905: 0x400ad620, 0x2906: 0x400ad720, 0x2907: 0x400ad820,
+ 0x2908: 0x400ad920, 0x2909: 0x400ada20, 0x290a: 0x400adb20, 0x290b: 0x400adc20,
+ 0x290c: 0x400add20, 0x290d: 0x400ade20, 0x290e: 0x400adf20, 0x290f: 0x400ae020,
+ 0x2910: 0x400ae120, 0x2911: 0x400ae220, 0x2912: 0x400ae320, 0x2913: 0x400ae420,
+ 0x2914: 0x400ae520, 0x2915: 0x400ae620, 0x2916: 0x400ae720, 0x2917: 0x400ae820,
+ 0x2918: 0x400ae920, 0x2919: 0x400aea20, 0x291a: 0x400aeb20, 0x291b: 0x400aec20,
+ 0x291d: 0x400aed20, 0x291e: 0x400aee20, 0x291f: 0x400aef20,
+ 0x2920: 0x400af020, 0x2921: 0x400af120, 0x2922: 0x400af220, 0x2923: 0x400af320,
+ 0x2924: 0x400af420, 0x2925: 0x400af520, 0x2926: 0x400af620, 0x2927: 0x400af720,
+ 0x2928: 0x400af820, 0x2929: 0x400af920, 0x292a: 0x400afa20, 0x292b: 0x400afb20,
+ 0x292c: 0x400afc20, 0x292d: 0x400afd20, 0x292e: 0x400afe20, 0x292f: 0x400aff20,
+ 0x2930: 0x400b0020, 0x2931: 0x400b0120, 0x2932: 0x400b0220, 0x2933: 0x400b0320,
+ 0x2934: 0x400b0420, 0x2935: 0x400b0520, 0x2936: 0x400b0620, 0x2937: 0x400b0720,
+ 0x2938: 0x400b0820, 0x2939: 0x400b0920, 0x293a: 0x400b0a20, 0x293b: 0x400b0b20,
+ 0x293c: 0x400b0c20, 0x293d: 0x400b0d20, 0x293e: 0x400b0e20, 0x293f: 0x400b0f20,
+ // Block 0xa5, offset 0x2940
+ 0x2940: 0x400b1020, 0x2941: 0x400b1120, 0x2942: 0x400b1220, 0x2943: 0x400b1320,
+ 0x2944: 0x400b1420, 0x2945: 0x400b1520, 0x2946: 0x400b1620, 0x2947: 0x400b1720,
+ 0x2948: 0x400b1820, 0x2949: 0x400b1920, 0x294a: 0x400b1a20, 0x294b: 0x400b1b20,
+ 0x294c: 0x400b1c20, 0x294d: 0x400b1d20, 0x294e: 0x400b1e20, 0x294f: 0x400b1f20,
+ 0x2950: 0x400b2020, 0x2951: 0x400b2120, 0x2952: 0x400b2220, 0x2953: 0x400b2320,
+ 0x2954: 0x400b2420, 0x2955: 0x400b2520, 0x2956: 0x400b2620, 0x2957: 0x400b2720,
+ 0x2958: 0x400b2820, 0x2959: 0x400b2920, 0x295a: 0x400b2a20, 0x295b: 0x400b2b20,
+ 0x295c: 0x400b2c20, 0x295d: 0x400b2d20, 0x295e: 0x400b2e20, 0x295f: 0x400b2f20,
+ 0x2960: 0x400b3020, 0x2961: 0x400b3120, 0x2962: 0x400b3220, 0x2963: 0x400b3320,
+ 0x2964: 0x400b3420, 0x2965: 0x400b3520, 0x2966: 0x400b3620, 0x2967: 0x400b3720,
+ 0x2968: 0x400b3820, 0x2969: 0x400b3920, 0x296a: 0x400b3a20, 0x296b: 0x400b3b20,
+ 0x296c: 0x400b3c20, 0x296d: 0x400b3d20, 0x296e: 0x400b3e20, 0x296f: 0x400b3f20,
+ 0x2970: 0x400b4020, 0x2971: 0x400b4120, 0x2972: 0x400b4220, 0x2973: 0x400b4320,
+ 0x2974: 0x400b4420, 0x2975: 0x400b4520, 0x2976: 0x400b4620, 0x2977: 0x400b4720,
+ 0x2978: 0x400b4820, 0x2979: 0x400b4920, 0x297a: 0x400b4a20, 0x297b: 0x400b4b20,
+ 0x297c: 0x400b4c20, 0x297d: 0x400b4d20, 0x297e: 0x400b4e20, 0x297f: 0x400b4f20,
+ // Block 0xa6, offset 0x2980
+ 0x2980: 0x400b5020, 0x2981: 0x400b5120, 0x2982: 0x400b5220, 0x2983: 0x400b5320,
+ 0x2984: 0x400b5420, 0x2985: 0x400b5520, 0x2986: 0x400b5620, 0x2987: 0x400b5720,
+ 0x2988: 0x400b5820, 0x2989: 0x400b5920, 0x298a: 0x400b5a20, 0x298b: 0x400b5b20,
+ 0x298c: 0x400b5c20,
+ 0x2990: 0x400b5d20, 0x2991: 0x400b5e20, 0x2992: 0x400b5f20, 0x2993: 0x400b6020,
+ 0x2994: 0x400b6120, 0x2995: 0x400b6220, 0x2996: 0x400b6320, 0x2997: 0x400b6420,
+ 0x2998: 0x400b6520, 0x2999: 0x400b6620,
+ // Block 0xa7, offset 0x29c0
+ 0x29c0: 0x00369c08, 0x29c1: 0x00369e08, 0x29c2: 0x0036a008, 0x29c3: 0x0036a208,
+ 0x29c4: 0x0036a408, 0x29c5: 0x0036a608, 0x29c6: 0x0036a808, 0x29c7: 0x0036aa08,
+ 0x29c8: 0x0036ac08, 0x29c9: 0x0036ae08, 0x29ca: 0x0036b008, 0x29cb: 0x0036b208,
+ 0x29cc: 0x0036b408, 0x29cd: 0x0036b608, 0x29ce: 0x0036b808, 0x29cf: 0x0036ba08,
+ 0x29d0: 0x0036bc08, 0x29d1: 0x0036be08, 0x29d2: 0x0036c008, 0x29d3: 0x0036c208,
+ 0x29d4: 0x0036c408, 0x29d5: 0x0036c608, 0x29d6: 0x0036c808, 0x29d7: 0x0036ca08,
+ 0x29d8: 0x0036cc08, 0x29d9: 0x0036ce08, 0x29da: 0x0036d008, 0x29db: 0x0036d208,
+ 0x29dc: 0x0036d408, 0x29dd: 0x0036d608, 0x29de: 0x0036d808, 0x29df: 0x0036da08,
+ 0x29e0: 0x0036dc08, 0x29e1: 0x0036de08, 0x29e2: 0x0036e008, 0x29e3: 0x0036e208,
+ 0x29e4: 0x0036e408, 0x29e5: 0x0036e608, 0x29e6: 0x0036e808, 0x29e7: 0x0036ea08,
+ 0x29e8: 0x0036ec08, 0x29e9: 0x0036ee08, 0x29ea: 0x0036f008, 0x29eb: 0x0036f208,
+ 0x29ec: 0x0036f408, 0x29ed: 0x0036f608, 0x29ee: 0x0036f808,
+ 0x29f0: 0x401b4e20, 0x29f1: 0x401b4f20, 0x29f2: 0x401b5020, 0x29f3: 0x401b5120,
+ 0x29f4: 0x401b5220, 0x29f5: 0x401b5320, 0x29f6: 0x401b5420, 0x29f7: 0x401b5520,
+ 0x29f8: 0x401b5620, 0x29f9: 0x401b5720, 0x29fa: 0x401b5820, 0x29fb: 0x401b5920,
+ 0x29fc: 0x401b5a20, 0x29fd: 0x401b5b20, 0x29fe: 0x401b5c20, 0x29ff: 0x401b5d20,
+ // Block 0xa8, offset 0x2a00
+ 0x2a00: 0x401b5e20, 0x2a01: 0x401b5f20, 0x2a02: 0x401b6020, 0x2a03: 0x401b6120,
+ 0x2a04: 0x401b6220, 0x2a05: 0x401b6320, 0x2a06: 0x401b6420, 0x2a07: 0x401b6520,
+ 0x2a08: 0x401b6620, 0x2a09: 0x401b6720, 0x2a0a: 0x401b6820, 0x2a0b: 0x401b6920,
+ 0x2a0c: 0x401b6a20, 0x2a0d: 0x401b6b20, 0x2a0e: 0x401b6c20, 0x2a0f: 0x401b6d20,
+ 0x2a10: 0x401b6e20, 0x2a11: 0x401b6f20, 0x2a12: 0x401b7020, 0x2a13: 0x401b7120,
+ 0x2a14: 0x401b7220, 0x2a15: 0x401b7320, 0x2a16: 0x401b7420, 0x2a17: 0x401b7520,
+ 0x2a18: 0x401b7620, 0x2a19: 0x401b7720, 0x2a1a: 0x401b7820, 0x2a1b: 0x401b7920,
+ 0x2a1c: 0x401b7a20, 0x2a1d: 0x401b7b20, 0x2a1e: 0x401b7c20,
+ 0x2a20: 0x002da608, 0x2a21: 0x4016d320, 0x2a22: 0x002da808, 0x2a23: 0x002e9c08,
+ 0x2a24: 0x002f2408, 0x2a25: 0x4015a820, 0x2a26: 0x4017d220, 0x2a27: 0x002cee08,
+ 0x2a28: 0x40167720, 0x2a29: 0x002d7808, 0x2a2a: 0x4016bc20, 0x2a2b: 0x0030be08,
+ 0x2a2c: 0x40185f20, 0x2a2d: 0x002b6008, 0x2a2e: 0x002df608, 0x2a2f: 0x002b5808,
+ 0x2a30: 0x002b6a08, 0x2a31: 0x40181d20, 0x2a32: 0x00305208, 0x2a33: 0x40182920,
+ 0x2a34: 0x40181e20, 0x2a35: 0x002cf008, 0x2a36: 0x40167820, 0x2a37: 0x40175d20,
+ 0x2a38: 0x40160920, 0x2a39: 0x40178d20, 0x2a3a: 0x40173a20, 0x2a3b: 0x40160e20,
+ 0x2a3c: 0xf0000015, 0x2a3d: 0xf000001d, 0x2a3e: 0x002f6208, 0x2a3f: 0x0030b608,
+ // Block 0xa9, offset 0x2a40
+ 0x2a40: 0x00321008, 0x2a41: 0x40190820, 0x2a42: 0x00321208, 0x2a43: 0x40190920,
+ 0x2a44: 0x00321408, 0x2a45: 0x40190a20, 0x2a46: 0x00321608, 0x2a47: 0x40190b20,
+ 0x2a48: 0x00321808, 0x2a49: 0x40190c20, 0x2a4a: 0x00321c08, 0x2a4b: 0x40190e20,
+ 0x2a4c: 0x00321e08, 0x2a4d: 0x40190f20, 0x2a4e: 0x00322008, 0x2a4f: 0x40191020,
+ 0x2a50: 0x00322208, 0x2a51: 0x40191120, 0x2a52: 0x00322408, 0x2a53: 0x40191220,
+ 0x2a54: 0x00322608, 0x2a55: 0x40191320, 0x2a56: 0x00322a08, 0x2a57: 0x40191520,
+ 0x2a58: 0x00322c08, 0x2a59: 0x40191620, 0x2a5a: 0x00322e08, 0x2a5b: 0x40191720,
+ 0x2a5c: 0x00323408, 0x2a5d: 0x40191a20, 0x2a5e: 0x00323608, 0x2a5f: 0x40191b20,
+ 0x2a60: 0x00323808, 0x2a61: 0x40191c20, 0x2a62: 0x00323a08, 0x2a63: 0x40191d20,
+ 0x2a64: 0x00323c08, 0x2a65: 0x40191e20, 0x2a66: 0x00323e08, 0x2a67: 0x40191f20,
+ 0x2a68: 0x00324008, 0x2a69: 0x40192020, 0x2a6a: 0x00324208, 0x2a6b: 0x40192120,
+ 0x2a6c: 0x00324408, 0x2a6d: 0x40192220, 0x2a6e: 0x00324608, 0x2a6f: 0x40192320,
+ 0x2a70: 0x00324808, 0x2a71: 0x40192420, 0x2a72: 0x00327c08, 0x2a73: 0x40193e20,
+ 0x2a74: 0x00327e08, 0x2a75: 0x40193f20, 0x2a76: 0x00321a08, 0x2a77: 0x40190d20,
+ 0x2a78: 0x00322808, 0x2a79: 0x40191420, 0x2a7a: 0x00323008, 0x2a7b: 0x40191820,
+ 0x2a7c: 0x00323208, 0x2a7d: 0x40191920, 0x2a7e: 0x00324a08, 0x2a7f: 0x40192520,
+ // Block 0xaa, offset 0x2a80
+ 0x2a80: 0x00324c08, 0x2a81: 0x40192620, 0x2a82: 0x00325208, 0x2a83: 0x40192920,
+ 0x2a84: 0x00325408, 0x2a85: 0x40192a20, 0x2a86: 0x00325608, 0x2a87: 0x40192b20,
+ 0x2a88: 0x00325c08, 0x2a89: 0x40192e20, 0x2a8a: 0x00326008, 0x2a8b: 0x40193020,
+ 0x2a8c: 0x00326208, 0x2a8d: 0x40193120, 0x2a8e: 0x00326408, 0x2a8f: 0x40193220,
+ 0x2a90: 0x00326608, 0x2a91: 0x40193320, 0x2a92: 0x00326808, 0x2a93: 0x40193420,
+ 0x2a94: 0x00326a08, 0x2a95: 0x40193520, 0x2a96: 0x00327008, 0x2a97: 0x40193820,
+ 0x2a98: 0x00327408, 0x2a99: 0x40193a20, 0x2a9a: 0x00327608, 0x2a9b: 0x40193b20,
+ 0x2a9c: 0x00327808, 0x2a9d: 0x40193c20, 0x2a9e: 0x00328008, 0x2a9f: 0x40194020,
+ 0x2aa0: 0x00328208, 0x2aa1: 0x40194120, 0x2aa2: 0x00328408, 0x2aa3: 0x40194220,
+ 0x2aa4: 0xe0000833, 0x2aa5: 0x400b6720, 0x2aa6: 0x400b6820, 0x2aa7: 0x400b6920,
+ 0x2aa8: 0x400b6a20, 0x2aa9: 0x400b6b20, 0x2aaa: 0x400b6c20, 0x2aab: 0x00325008,
+ 0x2aac: 0x40192820, 0x2aad: 0x00326e08, 0x2aae: 0x40193720, 0x2aaf: 0x80005f02,
+ 0x2ab0: 0x80002a02, 0x2ab1: 0x80002202,
+ 0x2ab9: 0x40017520, 0x2aba: 0x40016520, 0x2abb: 0x40016620,
+ 0x2abc: 0x4001cb20, 0x2abd: 0x40140e20, 0x2abe: 0x40017620, 0x2abf: 0x4001cc20,
+ // Block 0xab, offset 0x2ac0
+ 0x2ac0: 0x401b7e20, 0x2ac1: 0x401b8020, 0x2ac2: 0x401b8220, 0x2ac3: 0x401b8420,
+ 0x2ac4: 0x401b8620, 0x2ac5: 0x401b8820, 0x2ac6: 0x401b8a20, 0x2ac7: 0x401b8e20,
+ 0x2ac8: 0x401b9020, 0x2ac9: 0x401b9220, 0x2aca: 0x401b9420, 0x2acb: 0x401b9620,
+ 0x2acc: 0x401b9820, 0x2acd: 0x401b9c20, 0x2ace: 0x401b9e20, 0x2acf: 0x401ba020,
+ 0x2ad0: 0x401ba220, 0x2ad1: 0x401ba420, 0x2ad2: 0x401ba620, 0x2ad3: 0x401baa20,
+ 0x2ad4: 0x401bac20, 0x2ad5: 0x401bae20, 0x2ad6: 0x401bb020, 0x2ad7: 0x401bb220,
+ 0x2ad8: 0x401bb420, 0x2ad9: 0x401bb620, 0x2ada: 0x401bb820, 0x2adb: 0x401bba20,
+ 0x2adc: 0x401bbc20, 0x2add: 0x401bbe20, 0x2ade: 0x401bc020, 0x2adf: 0x401bc420,
+ 0x2ae0: 0x401bc620, 0x2ae1: 0x401b8c20, 0x2ae2: 0x401b9a20, 0x2ae3: 0x401ba820,
+ 0x2ae4: 0x401bc220, 0x2ae5: 0x401bc820,
+ 0x2af0: 0x401d7f20, 0x2af1: 0x401d8020, 0x2af2: 0x401d8120, 0x2af3: 0x401d8220,
+ 0x2af4: 0x401d8320, 0x2af5: 0x401d8420, 0x2af6: 0x401d8520, 0x2af7: 0x401d8620,
+ 0x2af8: 0x401d8720, 0x2af9: 0x401d8820, 0x2afa: 0x401d8920, 0x2afb: 0x401d8a20,
+ 0x2afc: 0x401d8b20, 0x2afd: 0x401d8c20, 0x2afe: 0x401d8d20, 0x2aff: 0x401d8e20,
+ // Block 0xac, offset 0x2b00
+ 0x2b00: 0x401d8f20, 0x2b01: 0x401d9020, 0x2b02: 0x401d9120, 0x2b03: 0x401d9220,
+ 0x2b04: 0x401d9320, 0x2b05: 0x401d9420, 0x2b06: 0x401d9520, 0x2b07: 0x401d9620,
+ 0x2b08: 0x401d9720, 0x2b09: 0x401d9820, 0x2b0a: 0x401d9920, 0x2b0b: 0x401d9a20,
+ 0x2b0c: 0x401d9b20, 0x2b0d: 0x401d9c20, 0x2b0e: 0x401d9d20, 0x2b0f: 0x401d9e20,
+ 0x2b10: 0x401d9f20, 0x2b11: 0x401da020, 0x2b12: 0x401da120, 0x2b13: 0x401da220,
+ 0x2b14: 0x401da320, 0x2b15: 0x401da420, 0x2b16: 0x401da520, 0x2b17: 0x401da620,
+ 0x2b18: 0x401da720, 0x2b19: 0x401da820, 0x2b1a: 0x401da920, 0x2b1b: 0x401daa20,
+ 0x2b1c: 0x401dab20, 0x2b1d: 0x401dac20, 0x2b1e: 0x401dad20, 0x2b1f: 0x401dae20,
+ 0x2b20: 0x401daf20, 0x2b21: 0x401db020, 0x2b22: 0x401db120, 0x2b23: 0x401db220,
+ 0x2b24: 0x401db320, 0x2b25: 0x401db420,
+ 0x2b2f: 0x401db520,
+ 0x2b30: 0x4002b720,
+ 0x2b3f: 0x80000000,
+ // Block 0xad, offset 0x2b40
+ 0x2b40: 0x401dc620, 0x2b41: 0x401ddb20, 0x2b42: 0x401dec20, 0x2b43: 0x401df520,
+ 0x2b44: 0x401e0420, 0x2b45: 0x401e2a20, 0x2b46: 0x401e3b20, 0x2b47: 0x401e4420,
+ 0x2b48: 0x401e5a20, 0x2b49: 0x401e6320, 0x2b4a: 0x401e6c20, 0x2b4b: 0x401e9d20,
+ 0x2b4c: 0x401ebc20, 0x2b4d: 0x401ecb20, 0x2b4e: 0x401ed420, 0x2b4f: 0x401ef620,
+ 0x2b50: 0x401eff20, 0x2b51: 0x401f0f20, 0x2b52: 0x401f3f20, 0x2b53: 0x401eea20,
+ 0x2b54: 0x401eeb20, 0x2b55: 0x401eec20, 0x2b56: 0x401eed20,
+ 0x2b60: 0x401f4320, 0x2b61: 0x401f4420, 0x2b62: 0x401f4520, 0x2b63: 0x401f4620,
+ 0x2b64: 0x401f4720, 0x2b65: 0x401f4820, 0x2b66: 0x401f4920,
+ 0x2b68: 0x401f4a20, 0x2b69: 0x401f4b20, 0x2b6a: 0x401f4c20, 0x2b6b: 0x401f4d20,
+ 0x2b6c: 0x401f4e20, 0x2b6d: 0x401f4f20, 0x2b6e: 0x401f5020,
+ 0x2b70: 0x401f5120, 0x2b71: 0x401f5220, 0x2b72: 0x401f5320, 0x2b73: 0x401f5420,
+ 0x2b74: 0x401f5520, 0x2b75: 0x401f5620, 0x2b76: 0x401f5720,
+ 0x2b78: 0x401f5820, 0x2b79: 0x401f5920, 0x2b7a: 0x401f5a20, 0x2b7b: 0x401f5b20,
+ 0x2b7c: 0x401f5c20, 0x2b7d: 0x401f5d20, 0x2b7e: 0x401f5e20,
+ // Block 0xae, offset 0x2b80
+ 0x2b80: 0x401f5f20, 0x2b81: 0x401f6020, 0x2b82: 0x401f6120, 0x2b83: 0x401f6220,
+ 0x2b84: 0x401f6320, 0x2b85: 0x401f6420, 0x2b86: 0x401f6520,
+ 0x2b88: 0x401f6620, 0x2b89: 0x401f6720, 0x2b8a: 0x401f6820, 0x2b8b: 0x401f6920,
+ 0x2b8c: 0x401f6a20, 0x2b8d: 0x401f6b20, 0x2b8e: 0x401f6c20,
+ 0x2b90: 0x401f6d20, 0x2b91: 0x401f6e20, 0x2b92: 0x401f6f20, 0x2b93: 0x401f7020,
+ 0x2b94: 0x401f7120, 0x2b95: 0x401f7220, 0x2b96: 0x401f7320,
+ 0x2b98: 0x401f7420, 0x2b99: 0x401f7520, 0x2b9a: 0x401f7620, 0x2b9b: 0x401f7720,
+ 0x2b9c: 0x401f7820, 0x2b9d: 0x401f7920, 0x2b9e: 0x401f7a20,
+ 0x2ba0: 0x0032b604, 0x2ba1: 0x0032be04, 0x2ba2: 0x0032c604, 0x2ba3: 0x0032ee04,
+ 0x2ba4: 0x00332e04, 0x2ba5: 0x00334804, 0x2ba6: 0x0033b404, 0x2ba7: 0x0033e804,
+ 0x2ba8: 0x00340c04, 0x2ba9: 0x00341e04, 0x2baa: 0x00345204, 0x2bab: 0x00347204,
+ 0x2bac: 0x00348c04, 0x2bad: 0x00349e04, 0x2bae: 0x0034b004, 0x2baf: 0x00351804,
+ 0x2bb0: 0x00356604, 0x2bb1: 0x00357c04, 0x2bb2: 0x0035c004, 0x2bb3: 0x0035ca04,
+ 0x2bb4: 0x00367004, 0x2bb5: 0xe000083d, 0x2bb6: 0x00328604, 0x2bb7: 0x00331604,
+ 0x2bb8: 0x0033b204, 0x2bb9: 0x00350604, 0x2bba: 0x00360204, 0x2bbb: 0x00361c04,
+ 0x2bbc: 0x00362604, 0x2bbd: 0x00363a04, 0x2bbe: 0x00364404, 0x2bbf: 0x00365804,
+ // Block 0xaf, offset 0x2bc0
+ 0x2bc0: 0x40026120, 0x2bc1: 0x40026220, 0x2bc2: 0x40021320, 0x2bc3: 0x40021420,
+ 0x2bc4: 0x40021520, 0x2bc5: 0x40021620, 0x2bc6: 0x40026320, 0x2bc7: 0x40026420,
+ 0x2bc8: 0x40026520, 0x2bc9: 0x40021720, 0x2bca: 0x40021820, 0x2bcb: 0x40026620,
+ 0x2bcc: 0x40021920, 0x2bcd: 0x40021a20, 0x2bce: 0x40026720, 0x2bcf: 0x40026820,
+ 0x2bd0: 0x40026920, 0x2bd1: 0x40026a20, 0x2bd2: 0x40026b20, 0x2bd3: 0x40026c20,
+ 0x2bd4: 0x40026d20, 0x2bd5: 0x40026e20, 0x2bd6: 0x40026f20, 0x2bd7: 0x40011a20,
+ 0x2bd8: 0x40016a20, 0x2bd9: 0x4001cd20, 0x2bda: 0x40027020, 0x2bdb: 0x40027120,
+ 0x2bdc: 0x40021b20, 0x2bdd: 0x40021c20, 0x2bde: 0x40027220, 0x2bdf: 0x40027320,
+ 0x2be0: 0x40021d20, 0x2be1: 0x40021e20, 0x2be2: 0x40021f20, 0x2be3: 0x40022020,
+ 0x2be4: 0x40022120, 0x2be5: 0x40022220, 0x2be6: 0x40022320, 0x2be7: 0x40022420,
+ 0x2be8: 0x40022520, 0x2be9: 0x40022620, 0x2bea: 0x4001c720, 0x2beb: 0x4001c820,
+ 0x2bec: 0x4001c920, 0x2bed: 0x4001ca20, 0x2bee: 0x40015f20, 0x2bef: 0x401aea20,
+ 0x2bf0: 0x40017720, 0x2bf1: 0x40017d20,
+ // Block 0xb0, offset 0x2c00
+ 0x2c00: 0xe0001189, 0x2c01: 0xe000119e, 0x2c02: 0x029cb604, 0x2c03: 0x029cb404,
+ 0x2c04: 0xe000118c, 0x2c05: 0x029d7604, 0x2c06: 0xe000118f, 0x2c07: 0xe0001192,
+ 0x2c08: 0xe0001195, 0x2c09: 0x02a40404, 0x2c0a: 0xe0001198, 0x2c0b: 0xe000119b,
+ 0x2c0c: 0xe00011a1, 0x2c0d: 0xe00011a4, 0x2c0e: 0xe00011a7, 0x2c0f: 0x02b84604,
+ 0x2c10: 0x02b84404, 0x2c11: 0xe00011aa, 0x2c12: 0x02bbe604, 0x2c13: 0x02bcf404,
+ 0x2c14: 0x02bea204, 0x2c15: 0xe00011ad, 0x2c16: 0x02bf8804, 0x2c17: 0xe00011b0,
+ 0x2c18: 0x02c49804, 0x2c19: 0x02ca6a04, 0x2c1b: 0x02cbc204,
+ 0x2c1c: 0xe00011b3, 0x2c1d: 0xe00011b6, 0x2c1e: 0xe00011b9, 0x2c1f: 0xf0000004,
+ 0x2c20: 0x02d82204, 0x2c21: 0x02d86a04, 0x2c22: 0x02d87404, 0x2c23: 0x02e0d804,
+ 0x2c24: 0x02e45604, 0x2c25: 0xe00011bc, 0x2c26: 0x029c5804, 0x2c27: 0xe00011bf,
+ 0x2c28: 0x02e55a04, 0x2c29: 0xe00011c2, 0x2c2a: 0xe00011c5, 0x2c2b: 0xe00011c8,
+ 0x2c2c: 0xe00011cb, 0x2c2d: 0x02f27604, 0x2c2e: 0xe00011ce, 0x2c2f: 0x02f9f204,
+ 0x2c30: 0x02fd3e04, 0x2c31: 0x02fea604, 0x2c32: 0x02fea404, 0x2c33: 0xe00011d4,
+ 0x2c34: 0xe00011d7, 0x2c35: 0xe00011d1, 0x2c36: 0xe00011da, 0x2c37: 0xe00011dd,
+ 0x2c38: 0x02ff1604, 0x2c39: 0x03000404, 0x2c3a: 0x03010004, 0x2c3b: 0xe00011e0,
+ 0x2c3c: 0xe00011e3, 0x2c3d: 0xe00011e6, 0x2c3e: 0x0304f204, 0x2c3f: 0xe00011e9,
+ // Block 0xb1, offset 0x2c40
+ 0x2c40: 0xe00011ec, 0x2c41: 0x030c9c04, 0x2c42: 0x0310c804, 0x2c43: 0x03130004,
+ 0x2c44: 0x0312fe04, 0x2c45: 0x03138204, 0x2c46: 0x0313a404, 0x2c47: 0xe00011ef,
+ 0x2c48: 0x03174004, 0x2c49: 0x031a3a04, 0x2c4a: 0xe00011f2, 0x2c4b: 0x031ecc04,
+ 0x2c4c: 0x031f6c04, 0x2c4d: 0xe00011f5, 0x2c4e: 0xe00011f8, 0x2c4f: 0xe00011fb,
+ 0x2c50: 0x03290a04, 0x2c51: 0x032aee04, 0x2c52: 0x032af004, 0x2c53: 0x032afe04,
+ 0x2c54: 0x032bd004, 0x2c55: 0xe00011fe, 0x2c56: 0x032c3a04, 0x2c57: 0xe0001201,
+ 0x2c58: 0x032ea404, 0x2c59: 0x032fcc04, 0x2c5a: 0x0330ea04, 0x2c5b: 0x03319c04,
+ 0x2c5c: 0x0331bc04, 0x2c5d: 0x0331be04, 0x2c5e: 0xe0001204, 0x2c5f: 0x0331c004,
+ 0x2c60: 0x0332c604, 0x2c61: 0xe0001207, 0x2c62: 0x0334d804, 0x2c63: 0xe000120a,
+ 0x2c64: 0xe000120d, 0x2c65: 0x0338f804, 0x2c66: 0x033c3e04, 0x2c67: 0xe0001210,
+ 0x2c68: 0x033d4c04, 0x2c69: 0x033d8804, 0x2c6a: 0x033dfc04, 0x2c6b: 0xe0001213,
+ 0x2c6c: 0x033ea004, 0x2c6d: 0xe0001216, 0x2c6e: 0x033efe04, 0x2c6f: 0xe0001219,
+ 0x2c70: 0x033f3204, 0x2c71: 0xe000121c, 0x2c72: 0xe000121f, 0x2c73: 0xf0000004,
+ // Block 0xb2, offset 0x2c80
+ 0x2c80: 0xf0000004, 0x2c81: 0xf0000004, 0x2c82: 0xf0000004, 0x2c83: 0xf0000004,
+ 0x2c84: 0xf0000004, 0x2c85: 0xf0000004, 0x2c86: 0xf0000004, 0x2c87: 0xf0000004,
+ 0x2c88: 0xf0000004, 0x2c89: 0xf0000004, 0x2c8a: 0xf0000004, 0x2c8b: 0xf0000004,
+ 0x2c8c: 0xf0000004, 0x2c8d: 0xf0000004, 0x2c8e: 0xf0000004, 0x2c8f: 0xf0000004,
+ 0x2c90: 0xf0000004, 0x2c91: 0xf0000004, 0x2c92: 0xf0000004, 0x2c93: 0xf0000004,
+ 0x2c94: 0xf0000004, 0x2c95: 0xf0000004, 0x2c96: 0xf0000004, 0x2c97: 0xf0000004,
+ 0x2c98: 0xf0000004, 0x2c99: 0xf0000004, 0x2c9a: 0xf0000004, 0x2c9b: 0xf0000004,
+ 0x2c9c: 0xf0000004, 0x2c9d: 0xf0000004, 0x2c9e: 0xf0000004, 0x2c9f: 0xf0000004,
+ 0x2ca0: 0xf0000004, 0x2ca1: 0xf0000004, 0x2ca2: 0xf0000004, 0x2ca3: 0xf0000004,
+ 0x2ca4: 0xf0000004, 0x2ca5: 0xf0000004, 0x2ca6: 0xf0000004, 0x2ca7: 0xf0000004,
+ 0x2ca8: 0xf0000004, 0x2ca9: 0xf0000004, 0x2caa: 0xf0000004, 0x2cab: 0xf0000004,
+ 0x2cac: 0xf0000004, 0x2cad: 0xf0000004, 0x2cae: 0xf0000004, 0x2caf: 0xf0000004,
+ 0x2cb0: 0xf0000004, 0x2cb1: 0xf0000004, 0x2cb2: 0xf0000004, 0x2cb3: 0xf0000004,
+ 0x2cb4: 0xf0000004, 0x2cb5: 0xf0000004, 0x2cb6: 0xf0000004, 0x2cb7: 0xf0000004,
+ 0x2cb8: 0xf0000004, 0x2cb9: 0xf0000004, 0x2cba: 0xf0000004, 0x2cbb: 0xf0000004,
+ 0x2cbc: 0xf0000004, 0x2cbd: 0xf0000004, 0x2cbe: 0xf0000004, 0x2cbf: 0xf0000004,
+ // Block 0xb3, offset 0x2cc0
+ 0x2cc0: 0xf0000004, 0x2cc1: 0xf0000004, 0x2cc2: 0xf0000004, 0x2cc3: 0xf0000004,
+ 0x2cc4: 0xf0000004, 0x2cc5: 0xf0000004, 0x2cc6: 0xf0000004, 0x2cc7: 0xf0000004,
+ 0x2cc8: 0xf0000004, 0x2cc9: 0xf0000004, 0x2cca: 0xf0000004, 0x2ccb: 0xf0000004,
+ 0x2ccc: 0xf0000004, 0x2ccd: 0xf0000004, 0x2cce: 0xf0000004, 0x2ccf: 0xf0000004,
+ 0x2cd0: 0xf0000004, 0x2cd1: 0xf0000004, 0x2cd2: 0xf0000004, 0x2cd3: 0xf0000004,
+ 0x2cd4: 0xf0000004, 0x2cd5: 0xf0000004,
+ 0x2cf0: 0x40135620, 0x2cf1: 0x40135720, 0x2cf2: 0x40135820, 0x2cf3: 0x40135920,
+ 0x2cf4: 0x40135a20, 0x2cf5: 0x40135b20, 0x2cf6: 0x40135c20, 0x2cf7: 0x40135d20,
+ 0x2cf8: 0x40135e20, 0x2cf9: 0x40135f20, 0x2cfa: 0x40136020, 0x2cfb: 0x40136120,
+ // Block 0xb4, offset 0x2d00
+ 0x2d00: 0xf0000003, 0x2d01: 0x40012b20, 0x2d02: 0x40017b20, 0x2d03: 0x40025720,
+ 0x2d04: 0x40138620, 0x2d05: 0x40139b20, 0x2d06: 0xe0001159, 0x2d07: 0xe0000090,
+ 0x2d08: 0x40022720, 0x2d09: 0x40022820, 0x2d0a: 0x40022920, 0x2d0b: 0x40022a20,
+ 0x2d0c: 0x40022b20, 0x2d0d: 0x40022c20, 0x2d0e: 0x40022d20, 0x2d0f: 0x40022e20,
+ 0x2d10: 0x40022f20, 0x2d11: 0x40023020, 0x2d12: 0x40138720, 0x2d13: 0x40138820,
+ 0x2d14: 0x40023120, 0x2d15: 0x40023220, 0x2d16: 0x40023320, 0x2d17: 0x40023420,
+ 0x2d18: 0x40023520, 0x2d19: 0x40023620, 0x2d1a: 0x40023720, 0x2d1b: 0x40023820,
+ 0x2d1c: 0x40011b20, 0x2d1d: 0x4001e420, 0x2d1e: 0x4001e520, 0x2d1f: 0x4001e620,
+ 0x2d20: 0x40138920, 0x2d21: 0xe0000114, 0x2d22: 0xe00001fb, 0x2d23: 0xe00002c1,
+ 0x2d24: 0xe000037e, 0x2d25: 0xe0000438, 0x2d26: 0xe00004ef, 0x2d27: 0xe000058b,
+ 0x2d28: 0xe0000627, 0x2d29: 0xe00006c0, 0x2d2a: 0x80014802, 0x2d2b: 0x80014902,
+ 0x2d2c: 0x80014a02, 0x2d2d: 0x80014b02, 0x2d2e: 0x80014c02, 0x2d2f: 0x80014d02,
+ 0x2d30: 0x40011c20, 0x2d31: 0x40139d20, 0x2d32: 0xe000001b, 0x2d33: 0x40139e20,
+ 0x2d34: 0xe000001e, 0x2d35: 0x40139f20, 0x2d36: 0xf0000004, 0x2d37: 0x40138a20,
+ 0x2d38: 0xf0000004, 0x2d39: 0xf0000004, 0x2d3a: 0xf0000004, 0x2d3b: 0x40139c20,
+ 0x2d3c: 0xe000115c, 0x2d3d: 0x40025820, 0x2d3e: 0x40138b20, 0x2d3f: 0x40138c20,
+ // Block 0xb5, offset 0x2d40
+ 0x2d41: 0x00632c0d, 0x2d42: 0x00632c0e, 0x2d43: 0x00632e0d,
+ 0x2d44: 0x00632e0e, 0x2d45: 0x0063300d, 0x2d46: 0x0063300e, 0x2d47: 0x0063340d,
+ 0x2d48: 0x0063340e, 0x2d49: 0x0063360d, 0x2d4a: 0x0063360e, 0x2d4b: 0x0063380e,
+ 0x2d4d: 0x00633a0e, 0x2d4f: 0x00633c0e,
+ 0x2d51: 0x00633e0e, 0x2d53: 0x0063400e,
+ 0x2d55: 0x0063420e, 0x2d57: 0x0063440e,
+ 0x2d59: 0x0063460e, 0x2d5b: 0x0063480e,
+ 0x2d5d: 0x00634a0e, 0x2d5f: 0x00634c0e,
+ 0x2d61: 0x00634e0e, 0x2d63: 0x0063500d,
+ 0x2d64: 0x0063500e, 0x2d66: 0x0063520e,
+ 0x2d68: 0x0063540e, 0x2d6a: 0x0063560e, 0x2d6b: 0x0063580e,
+ 0x2d6c: 0x00635a0e, 0x2d6d: 0x00635c0e, 0x2d6e: 0x00635e0e, 0x2d6f: 0x0063600e,
+ 0x2d72: 0x0063620e,
+ 0x2d75: 0x0063640e,
+ 0x2d78: 0x0063660e, 0x2d7b: 0x0063680e,
+ 0x2d7e: 0x00636a0e, 0x2d7f: 0x00636c0e,
+ // Block 0xb6, offset 0x2d80
+ 0x2d80: 0x00636e0e, 0x2d81: 0x0063700e, 0x2d82: 0x0063720e, 0x2d83: 0x0063740d,
+ 0x2d84: 0x0063740e, 0x2d85: 0x0063760d, 0x2d86: 0x0063760e, 0x2d87: 0x00637a0d,
+ 0x2d88: 0x00637a0e, 0x2d89: 0x00637c0e, 0x2d8a: 0x00637e0e, 0x2d8b: 0x0063800e,
+ 0x2d8c: 0x0063820e, 0x2d8d: 0x0063840e, 0x2d8e: 0x0063860d, 0x2d8f: 0x0063860e,
+ 0x2d90: 0x0063880e, 0x2d91: 0x00638a0e, 0x2d92: 0x00638c0e, 0x2d93: 0x00638e0e,
+ 0x2d95: 0x0063380d, 0x2d96: 0x00633e0d,
+ 0x2d99: 0x80014e02, 0x2d9a: 0x80014f02, 0x2d9b: 0x40030d20,
+ 0x2d9c: 0x40030e20, 0x2d9d: 0x4013a020, 0x2d9f: 0xf0001616,
+ 0x2da0: 0x40011d20, 0x2da1: 0x00632c0f, 0x2da2: 0x00632c11, 0x2da3: 0x00632e0f,
+ 0x2da4: 0x00632e11, 0x2da5: 0x0063300f, 0x2da6: 0x00633011, 0x2da7: 0x0063340f,
+ 0x2da8: 0x00633411, 0x2da9: 0x0063360f, 0x2daa: 0x00633611, 0x2dab: 0x00633811,
+ 0x2dad: 0x00633a11, 0x2daf: 0x00633c11,
+ 0x2db1: 0x00633e11, 0x2db3: 0x00634011,
+ 0x2db5: 0x00634211, 0x2db7: 0x00634411,
+ 0x2db9: 0x00634611, 0x2dbb: 0x00634811,
+ 0x2dbd: 0x00634a11, 0x2dbf: 0x00634c11,
+ // Block 0xb7, offset 0x2dc0
+ 0x2dc1: 0x00634e11, 0x2dc3: 0x0063500f,
+ 0x2dc4: 0x00635011, 0x2dc6: 0x00635211,
+ 0x2dc8: 0x00635411, 0x2dca: 0x00635611, 0x2dcb: 0x00635811,
+ 0x2dcc: 0x00635a11, 0x2dcd: 0x00635c11, 0x2dce: 0x00635e11, 0x2dcf: 0x00636011,
+ 0x2dd2: 0x00636211,
+ 0x2dd5: 0x00636411,
+ 0x2dd8: 0x00636611, 0x2ddb: 0x00636811,
+ 0x2dde: 0x00636a11, 0x2ddf: 0x00636c11,
+ 0x2de0: 0x00636e11, 0x2de1: 0x00637011, 0x2de2: 0x00637211, 0x2de3: 0x0063740f,
+ 0x2de4: 0x00637411, 0x2de5: 0x0063760f, 0x2de6: 0x00637611, 0x2de7: 0x00637a0f,
+ 0x2de8: 0x00637a11, 0x2de9: 0x00637c11, 0x2dea: 0x00637e11, 0x2deb: 0x00638011,
+ 0x2dec: 0x00638211, 0x2ded: 0x00638411, 0x2dee: 0x0063860f, 0x2def: 0x00638611,
+ 0x2df0: 0x00638811, 0x2df1: 0x00638a11, 0x2df2: 0x00638c11, 0x2df3: 0x00638e11,
+ 0x2df5: 0x0063380f, 0x2df6: 0x00633e0f,
+ 0x2dfb: 0x40011e20,
+ 0x2dfc: 0x4013a120, 0x2dfd: 0x4013a220, 0x2dff: 0xf0001616,
+ // Block 0xb8, offset 0x2e00
+ 0x2e05: 0x4031c820, 0x2e06: 0x4031c920, 0x2e07: 0x4031ca20,
+ 0x2e08: 0x4031cb20, 0x2e09: 0x4031cd20, 0x2e0a: 0x4031ce20, 0x2e0b: 0x4031cf20,
+ 0x2e0c: 0x4031d020, 0x2e0d: 0x4031d120, 0x2e0e: 0x4031d220, 0x2e0f: 0x4031d520,
+ 0x2e10: 0x4031d620, 0x2e11: 0x4031d720, 0x2e12: 0x4031d820, 0x2e13: 0x4031da20,
+ 0x2e14: 0x4031db20, 0x2e15: 0x4031dc20, 0x2e16: 0x4031dd20, 0x2e17: 0x4031de20,
+ 0x2e18: 0x4031df20, 0x2e19: 0x4031e020, 0x2e1a: 0x4031e420, 0x2e1b: 0x4031e520,
+ 0x2e1c: 0x4031e720, 0x2e1d: 0x4031e820, 0x2e1e: 0x4031ea20, 0x2e1f: 0x4031eb20,
+ 0x2e20: 0x4031ec20, 0x2e21: 0x4031ed20, 0x2e22: 0x4031ee20, 0x2e23: 0x4031ef20,
+ 0x2e24: 0x4031f020, 0x2e25: 0x4031f220, 0x2e26: 0x4031f620, 0x2e27: 0x4031f720,
+ 0x2e28: 0x4031f820, 0x2e29: 0x4031f920, 0x2e2a: 0x4031cc20, 0x2e2b: 0x4031d320,
+ 0x2e2c: 0x4031d920, 0x2e2d: 0x4031fa20,
+ 0x2e31: 0xf0000004, 0x2e32: 0xf0000004, 0x2e33: 0xf0000004,
+ 0x2e34: 0xf0000004, 0x2e35: 0xf0000004, 0x2e36: 0xf0000004, 0x2e37: 0xf0000004,
+ 0x2e38: 0xf0000004, 0x2e39: 0xf0000004, 0x2e3a: 0xf0000004, 0x2e3b: 0xf0000004,
+ 0x2e3c: 0xf0000004, 0x2e3d: 0xf0000004, 0x2e3e: 0xf0000004, 0x2e3f: 0xf0000004,
+ // Block 0xb9, offset 0x2e40
+ 0x2e40: 0xf0000004, 0x2e41: 0xf0000004, 0x2e42: 0xf0000004, 0x2e43: 0xf0000004,
+ 0x2e44: 0xf0000004, 0x2e45: 0xf0000004, 0x2e46: 0xf0000004, 0x2e47: 0xf0000004,
+ 0x2e48: 0xf0000004, 0x2e49: 0xf0000004, 0x2e4a: 0xf0000004, 0x2e4b: 0xf0000004,
+ 0x2e4c: 0xf0000004, 0x2e4d: 0xf0000004, 0x2e4e: 0xf0000004,
+ 0x2e50: 0x40138d20, 0x2e51: 0x40138e20, 0x2e52: 0xf0000014, 0x2e53: 0xf0000014,
+ 0x2e54: 0xf0000014, 0x2e55: 0xf0000014, 0x2e56: 0xf0000014, 0x2e57: 0xf0000014,
+ 0x2e58: 0xf0000014, 0x2e59: 0xf0000014, 0x2e5a: 0xf0000014, 0x2e5b: 0xf0000014,
+ 0x2e5c: 0xf0000014, 0x2e5d: 0xf0000014, 0x2e5e: 0xf0000014, 0x2e5f: 0xf0000014,
+ 0x2e60: 0xe000115f, 0x2e61: 0xe0001168, 0x2e62: 0xe0001165, 0x2e63: 0xe0001162,
+ 0x2e64: 0x4031e920, 0x2e65: 0xe0001171, 0x2e66: 0x4031e620, 0x2e67: 0xe000116e,
+ 0x2e68: 0xe0001183, 0x2e69: 0xe000116b, 0x2e6a: 0xe000117a, 0x2e6b: 0xe0001180,
+ 0x2e6c: 0x4031f520, 0x2e6d: 0x4031d420, 0x2e6e: 0xe0001174, 0x2e6f: 0xe0001177,
+ 0x2e70: 0x4031f320, 0x2e71: 0x4031f420, 0x2e72: 0x4031f120, 0x2e73: 0xe000117d,
+ 0x2e74: 0x00639219, 0x2e75: 0x00639c19, 0x2e76: 0x0063a419, 0x2e77: 0x0063aa19,
+ 0x2e78: 0x4031e120, 0x2e79: 0x4031e220, 0x2e7a: 0x4031e320,
+ // Block 0xba, offset 0x2e80
+ 0x2e80: 0x40136220, 0x2e81: 0x40136320, 0x2e82: 0x40136420, 0x2e83: 0x40136520,
+ 0x2e84: 0x40136620, 0x2e85: 0x40136720, 0x2e86: 0x40136820, 0x2e87: 0x40136920,
+ 0x2e88: 0x40136a20, 0x2e89: 0x40136b20, 0x2e8a: 0x40136c20, 0x2e8b: 0x40136d20,
+ 0x2e8c: 0x40136e20, 0x2e8d: 0x40136f20, 0x2e8e: 0x40137020, 0x2e8f: 0x40137120,
+ 0x2e90: 0x40137220, 0x2e91: 0x40137320, 0x2e92: 0x40137420, 0x2e93: 0x40137520,
+ 0x2e94: 0x40137620, 0x2e95: 0x40137720, 0x2e96: 0x40137820, 0x2e97: 0x40137920,
+ 0x2e98: 0x40137a20, 0x2e99: 0x40137b20, 0x2e9a: 0x40137c20, 0x2e9b: 0x40137d20,
+ 0x2e9c: 0x40137e20, 0x2e9d: 0x40137f20, 0x2e9e: 0x40138020, 0x2e9f: 0x40138120,
+ 0x2ea0: 0x40138220, 0x2ea1: 0x40138320, 0x2ea2: 0x40138420, 0x2ea3: 0x40138520,
+ 0x2eb0: 0x00633c0f, 0x2eb1: 0x0063440f, 0x2eb2: 0x0063460f, 0x2eb3: 0x0063540f,
+ 0x2eb4: 0x00635a0f, 0x2eb5: 0x0063600f, 0x2eb6: 0x0063620f, 0x2eb7: 0x0063640f,
+ 0x2eb8: 0x0063660f, 0x2eb9: 0x0063680f, 0x2eba: 0x00636e0f, 0x2ebb: 0x00637c0f,
+ 0x2ebc: 0x00637e0f, 0x2ebd: 0x0063800f, 0x2ebe: 0x0063820f, 0x2ebf: 0x0063840f,
+ // Block 0xbb, offset 0x2ec0
+ 0x2ec0: 0xf0000404, 0x2ec1: 0xf0000404, 0x2ec2: 0xf0000404, 0x2ec3: 0xf0000404,
+ 0x2ec4: 0xf0000404, 0x2ec5: 0xf0000404, 0x2ec6: 0xf0000404, 0x2ec7: 0xf0000404,
+ 0x2ec8: 0xf0000404, 0x2ec9: 0xf0000404, 0x2eca: 0xf0000404, 0x2ecb: 0xf0000404,
+ 0x2ecc: 0xf0000404, 0x2ecd: 0xf0000404, 0x2ece: 0xf0000404, 0x2ecf: 0xf0000404,
+ 0x2ed0: 0xf0000404, 0x2ed1: 0xf0000404, 0x2ed2: 0xf0000404, 0x2ed3: 0xf0000404,
+ 0x2ed4: 0xf0000404, 0x2ed5: 0xf0000404, 0x2ed6: 0xf0000404, 0x2ed7: 0xf0000404,
+ 0x2ed8: 0xf0000404, 0x2ed9: 0xf0000404, 0x2eda: 0xf0000404, 0x2edb: 0xf0000404,
+ 0x2edc: 0xf0000404, 0x2edd: 0xf0000404, 0x2ede: 0xf0000404,
+ 0x2ee0: 0xf0000404, 0x2ee1: 0xf0000404, 0x2ee2: 0xf0000404, 0x2ee3: 0xf0000404,
+ 0x2ee4: 0xf0000404, 0x2ee5: 0xf0000404, 0x2ee6: 0xf0000404, 0x2ee7: 0xf0000404,
+ 0x2ee8: 0xf0000404, 0x2ee9: 0xf0000404, 0x2eea: 0xf0000404, 0x2eeb: 0xf0000404,
+ 0x2eec: 0xf0000404, 0x2eed: 0xf0000404, 0x2eee: 0xf0000404, 0x2eef: 0xf0000404,
+ 0x2ef0: 0xf0000404, 0x2ef1: 0xf0000404, 0x2ef2: 0xf0000404, 0x2ef3: 0xf0000404,
+ 0x2ef4: 0xf0000404, 0x2ef5: 0xf0000404, 0x2ef6: 0xf0000404, 0x2ef7: 0xf0000404,
+ 0x2ef8: 0xf0000404, 0x2ef9: 0xf0000404, 0x2efa: 0xf0000404, 0x2efb: 0xf0000404,
+ 0x2efc: 0xf0000404, 0x2efd: 0xf0000404, 0x2efe: 0xf0000404, 0x2eff: 0xf0000404,
+ // Block 0xbc, offset 0x2f00
+ 0x2f00: 0xf0000404, 0x2f01: 0xf0000404, 0x2f02: 0xf0000404, 0x2f03: 0xf0000404,
+ 0x2f04: 0xf0000006, 0x2f05: 0xf0000006, 0x2f06: 0xf0000006, 0x2f07: 0xf0000006,
+ 0x2f08: 0xe0000165, 0x2f09: 0xe0000246, 0x2f0a: 0xe0000309, 0x2f0b: 0xe00003c3,
+ 0x2f0c: 0xe000047a, 0x2f0d: 0xe0000516, 0x2f0e: 0xe00005b2, 0x2f0f: 0xe000064b,
+ 0x2f10: 0xf0001d1d, 0x2f11: 0xf0000606, 0x2f12: 0xf0000606, 0x2f13: 0xf0000606,
+ 0x2f14: 0xf0000606, 0x2f15: 0xf0000606, 0x2f16: 0xf0000606, 0x2f17: 0xf0000606,
+ 0x2f18: 0xf0000606, 0x2f19: 0xf0000606, 0x2f1a: 0xf0000606, 0x2f1b: 0xf0000606,
+ 0x2f1c: 0xf0000606, 0x2f1d: 0xf0000606, 0x2f1e: 0xf0000606, 0x2f1f: 0xf0000606,
+ 0x2f20: 0xf0000006, 0x2f21: 0xf0000006, 0x2f22: 0xf0000006, 0x2f23: 0xf0000006,
+ 0x2f24: 0xf0000006, 0x2f25: 0xf0000006, 0x2f26: 0xf0000006, 0x2f27: 0xf0000006,
+ 0x2f28: 0xf0000006, 0x2f29: 0xf0000006, 0x2f2a: 0xf0000006, 0x2f2b: 0xf0000006,
+ 0x2f2c: 0xf0000006, 0x2f2d: 0xf0000006, 0x2f2e: 0xf0000606, 0x2f2f: 0xf0000606,
+ 0x2f30: 0xf0000606, 0x2f31: 0xf0000606, 0x2f32: 0xf0000606, 0x2f33: 0xf0000606,
+ 0x2f34: 0xf0000606, 0x2f35: 0xf0000606, 0x2f36: 0xf0000606, 0x2f37: 0xf0000606,
+ 0x2f38: 0xf0000606, 0x2f39: 0xf0000606, 0x2f3a: 0xf0000606, 0x2f3b: 0xf0000606,
+ 0x2f3c: 0xf0000606, 0x2f3d: 0xf0000606, 0x2f3e: 0xf0000606, 0x2f3f: 0x40138f20,
+ // Block 0xbd, offset 0x2f40
+ 0x2f40: 0xf0000006, 0x2f41: 0xf0000006, 0x2f42: 0xf0000006, 0x2f43: 0xf0000006,
+ 0x2f44: 0xf0000006, 0x2f45: 0xf0000006, 0x2f46: 0xf0000006, 0x2f47: 0xf0000006,
+ 0x2f48: 0xf0000006, 0x2f49: 0xf0000006, 0x2f4a: 0xf0000006, 0x2f4b: 0xf0000006,
+ 0x2f4c: 0xf0000006, 0x2f4d: 0xf0000006, 0x2f4e: 0xf0000006, 0x2f4f: 0xf0000006,
+ 0x2f50: 0xf0000006, 0x2f51: 0xf0000006, 0x2f52: 0xf0000006, 0x2f53: 0xf0000006,
+ 0x2f54: 0xf0000006, 0x2f55: 0xf0000006, 0x2f56: 0xf0000006, 0x2f57: 0xf0000006,
+ 0x2f58: 0xf0000006, 0x2f59: 0xf0000006, 0x2f5a: 0xf0000006, 0x2f5b: 0xf0000006,
+ 0x2f5c: 0xf0000006, 0x2f5d: 0xf0000006, 0x2f5e: 0xf0000006, 0x2f5f: 0xf0000006,
+ 0x2f60: 0xf0000006, 0x2f61: 0xf0000006, 0x2f62: 0xf0000006, 0x2f63: 0xf0000006,
+ 0x2f64: 0xf0000006, 0x2f65: 0xf0000006, 0x2f66: 0xf0000006, 0x2f67: 0xf0000006,
+ 0x2f68: 0xf0000006, 0x2f69: 0xf0000006, 0x2f6a: 0xf0000006, 0x2f6b: 0xf0000006,
+ 0x2f6c: 0xf0000006, 0x2f6d: 0xf0000006, 0x2f6e: 0xf0000006, 0x2f6f: 0xf0000006,
+ 0x2f70: 0xf0000006, 0x2f71: 0xf0000606, 0x2f72: 0xf0000606, 0x2f73: 0xf0000606,
+ 0x2f74: 0xf0000606, 0x2f75: 0xf0000606, 0x2f76: 0xf0000606, 0x2f77: 0xf0000606,
+ 0x2f78: 0xf0000606, 0x2f79: 0xf0000606, 0x2f7a: 0xf0000606, 0x2f7b: 0xf0000606,
+ 0x2f7c: 0xf0000606, 0x2f7d: 0xf0000606, 0x2f7e: 0xf0000606, 0x2f7f: 0xf0000606,
+ // Block 0xbe, offset 0x2f80
+ 0x2f80: 0xf0000404, 0x2f81: 0xf0000404, 0x2f82: 0xf0000404, 0x2f83: 0xf0000404,
+ 0x2f84: 0xf0000404, 0x2f85: 0xf0000404, 0x2f86: 0xf0000404, 0x2f87: 0xf0000404,
+ 0x2f88: 0xf0000404, 0x2f89: 0xf0000404, 0x2f8a: 0xf0000404, 0x2f8b: 0xf0000404,
+ 0x2f8c: 0xf0001c1d, 0x2f8d: 0xf0001c1c, 0x2f8e: 0xf0001d1c, 0x2f8f: 0xf0001d1d,
+ 0x2f90: 0xf0000013, 0x2f91: 0xf0000013, 0x2f92: 0xf0000013, 0x2f93: 0xf0000013,
+ 0x2f94: 0xf0000013, 0x2f95: 0xf0000013, 0x2f96: 0xf0000013, 0x2f97: 0xf0000013,
+ 0x2f98: 0xf0000013, 0x2f99: 0xf0000013, 0x2f9a: 0xf0000013, 0x2f9b: 0xf0000013,
+ 0x2f9c: 0xf0000013, 0x2f9d: 0xf0000013, 0x2f9e: 0xf0000013, 0x2f9f: 0xf0000013,
+ 0x2fa0: 0xf0000013, 0x2fa1: 0xf0000013, 0x2fa2: 0xf0000013, 0x2fa3: 0xf0000013,
+ 0x2fa4: 0xf0000013, 0x2fa5: 0xf0000013, 0x2fa6: 0xf0000013, 0x2fa7: 0xf0000013,
+ 0x2fa8: 0xf0000013, 0x2fa9: 0xf0000013, 0x2faa: 0xf0000013, 0x2fab: 0xf0000013,
+ 0x2fac: 0xf0000013, 0x2fad: 0xf0000013, 0x2fae: 0xf0000013, 0x2faf: 0xf0000013,
+ 0x2fb0: 0xf0000013, 0x2fb1: 0xf0000013, 0x2fb2: 0xf0000013, 0x2fb3: 0xf0000013,
+ 0x2fb4: 0xf0000013, 0x2fb5: 0xf0000013, 0x2fb6: 0xf0000013, 0x2fb7: 0xf0000013,
+ 0x2fb8: 0xf0000013, 0x2fb9: 0xf0000013, 0x2fba: 0xf0000013, 0x2fbb: 0xf0000013,
+ 0x2fbc: 0xf0000013, 0x2fbd: 0xf0000013, 0x2fbe: 0xf0000013,
+ // Block 0xbf, offset 0x2fc0
+ 0x2fc0: 0xf0001c1c, 0x2fc1: 0xf0001c1c, 0x2fc2: 0xf0001c1c, 0x2fc3: 0xf0001c1c,
+ 0x2fc4: 0xf0001c1c, 0x2fc5: 0xf0001c1c, 0x2fc6: 0xf0001c1c, 0x2fc7: 0xf0001c1c,
+ 0x2fc8: 0xf0001c1c, 0x2fc9: 0xf0001c1c, 0x2fca: 0xf0001c1c, 0x2fcb: 0xf0001c1c,
+ 0x2fcc: 0xf0001c1c, 0x2fcd: 0xf0001c1c, 0x2fce: 0xf0001c1c, 0x2fcf: 0xf0001c1c,
+ 0x2fd0: 0xf0001c1c, 0x2fd1: 0xf0001c1c, 0x2fd2: 0xf0001c1c, 0x2fd3: 0xf0001c1c,
+ 0x2fd4: 0xf0001c1c, 0x2fd5: 0xf0001c1c, 0x2fd6: 0xf0001c1c, 0x2fd7: 0xf0001c1c,
+ 0x2fd8: 0xf0001c1c, 0x2fd9: 0xf0001c1c, 0x2fda: 0xf0001c1c, 0x2fdb: 0xf0001c1c,
+ 0x2fdc: 0xf0001c1c, 0x2fdd: 0xf0001c1c, 0x2fde: 0xf0001c1c, 0x2fdf: 0xf0001c1c,
+ 0x2fe0: 0xf0001c1c, 0x2fe1: 0xf0001c1c, 0x2fe2: 0xf0001c1c, 0x2fe3: 0xf0001c1c,
+ 0x2fe4: 0xf0001c1c, 0x2fe5: 0xf0001c1c, 0x2fe6: 0xf0001c1c, 0x2fe7: 0xf0001c1c,
+ 0x2fe8: 0xf0001c1c, 0x2fe9: 0xf0001c1c, 0x2fea: 0xf0001c1c, 0x2feb: 0xf0001c1c,
+ 0x2fec: 0xf0001c1c, 0x2fed: 0xf0001c1c, 0x2fee: 0xf0001c1c, 0x2fef: 0xf0001c1c,
+ 0x2ff0: 0xf0001c1c, 0x2ff1: 0xf0001c1c, 0x2ff2: 0xf0001c1c, 0x2ff3: 0xf0001c1c,
+ 0x2ff4: 0xf0001c1c, 0x2ff5: 0xf0001c1c, 0x2ff6: 0xf0001c1c, 0x2ff7: 0xf0001c1c,
+ 0x2ff8: 0xf0001c1c, 0x2ff9: 0xf0001c1c, 0x2ffa: 0xf0001c1c, 0x2ffb: 0xf0001c1c,
+ 0x2ffc: 0xf0001c1c, 0x2ffd: 0xf0001c1c, 0x2ffe: 0xf0001c1c, 0x2fff: 0xf0001c1c,
+ // Block 0xc0, offset 0x3000
+ 0x3000: 0xf0001c1c, 0x3001: 0xf0001c1c, 0x3002: 0xf0001c1c, 0x3003: 0xf0001c1c,
+ 0x3004: 0xf0001c1c, 0x3005: 0xf0001c1c, 0x3006: 0xf0001c1c, 0x3007: 0xf0001c1c,
+ 0x3008: 0xf0001c1c, 0x3009: 0xf0001c1c, 0x300a: 0xf0001c1c, 0x300b: 0xf0001c1c,
+ 0x300c: 0xf0001c1c, 0x300d: 0xf0001c1c, 0x300e: 0xf0001c1c, 0x300f: 0xf0001c1c,
+ 0x3010: 0xf0001c1c, 0x3011: 0xf0001c1c, 0x3012: 0xf0001c1c, 0x3013: 0xf0001c1c,
+ 0x3014: 0xf0001c1c, 0x3015: 0xf0001c1c, 0x3016: 0xf0001c1c, 0x3017: 0xf0001c1c,
+ 0x3018: 0xf0000404, 0x3019: 0xf0000404, 0x301a: 0xf0000404, 0x301b: 0xf0000404,
+ 0x301c: 0xf0000404, 0x301d: 0xf0000404, 0x301e: 0xf0000404, 0x301f: 0xf0000404,
+ 0x3020: 0xf0000404, 0x3021: 0xf0000404, 0x3022: 0xf0000404, 0x3023: 0xf0000404,
+ 0x3024: 0xf0000404, 0x3025: 0xf0000404, 0x3026: 0xf0000404, 0x3027: 0xf0000404,
+ 0x3028: 0xf0000404, 0x3029: 0xf0000404, 0x302a: 0xf0000404, 0x302b: 0xf0000404,
+ 0x302c: 0xf0000404, 0x302d: 0xf0000404, 0x302e: 0xf0000404, 0x302f: 0xf0000404,
+ 0x3030: 0xf0000404, 0x3031: 0xf0001d1c, 0x3032: 0xf0001c1c, 0x3033: 0xf0001d1d,
+ 0x3034: 0xf0001c1c, 0x3035: 0xf0001d1c, 0x3036: 0xf0001c1c, 0x3037: 0xf0001c1c,
+ 0x3038: 0xf0001c1c, 0x3039: 0xf0001c1c, 0x303a: 0xf0001d1d, 0x303b: 0xf0001f1c,
+ 0x303c: 0xf0001f1c, 0x303d: 0xf0001f1c, 0x303e: 0xf0001f1c, 0x303f: 0xf0001f1c,
+ // Block 0xc1, offset 0x3040
+ 0x3040: 0xf0001d1c, 0x3041: 0xf0001d1c, 0x3042: 0xf0001d1c, 0x3043: 0xf0001d1c,
+ 0x3044: 0xf0001d1c, 0x3045: 0xf0001d1d, 0x3046: 0xf0001d1d, 0x3047: 0xf0001d1d,
+ 0x3048: 0xf0001c1c, 0x3049: 0xf0001c1c, 0x304a: 0xf0001d1c, 0x304b: 0xf0001d1c,
+ 0x304c: 0xf0001d1c, 0x304d: 0xf0001c1c, 0x304e: 0xf0001c1c, 0x304f: 0xf0001c1c,
+ 0x3050: 0xf0001c1d, 0x3051: 0xf0001d1c, 0x3052: 0xf0001d1d, 0x3053: 0xf0001d1d,
+ 0x3054: 0xf0001d1d, 0x3055: 0xf0001c1c, 0x3056: 0xf0001c1c, 0x3057: 0xf0001c1c,
+ 0x3058: 0xf0001c1c, 0x3059: 0xf0001c1c, 0x305a: 0xf0001c1c, 0x305b: 0xf0001c1c,
+ 0x305c: 0xf0001c1c, 0x305d: 0xf0001c1c, 0x305e: 0xf0001c1c, 0x305f: 0xf0001c1c,
+ 0x3060: 0xf0001c1c, 0x3061: 0xf0001c1c, 0x3062: 0xf0001c1c, 0x3063: 0xf0001c1c,
+ 0x3064: 0xf0001c1c, 0x3065: 0xf0001c1c, 0x3066: 0xf0001c1c, 0x3067: 0xf0001c1c,
+ 0x3068: 0xf0001c1c, 0x3069: 0xf0001c1d, 0x306a: 0xf0001d1c, 0x306b: 0xf0001d1d,
+ 0x306c: 0xf0001d1d, 0x306d: 0xf0001c1c, 0x306e: 0xf0001c1c, 0x306f: 0xf0001c1c,
+ 0x3070: 0xf0001c1c, 0x3071: 0xf0001c1c, 0x3072: 0xf0001c1c, 0x3073: 0xf0001c1c,
+ 0x3074: 0xf0001d1c, 0x3075: 0xf0001d1c, 0x3076: 0xf0001d1c, 0x3077: 0xf0001d1c,
+ 0x3078: 0xf0001d1c, 0x3079: 0xf0001d1d, 0x307a: 0xf0001d1c, 0x307b: 0xf0001d1c,
+ 0x307c: 0xf0001d1c, 0x307d: 0xf0001d1c, 0x307e: 0xf0001d1c, 0x307f: 0xf0001d1d,
+ // Block 0xc2, offset 0x3080
+ 0x3080: 0xf0001d1c, 0x3081: 0xf0001d1d, 0x3082: 0xf0001c1c, 0x3083: 0xf0001c1d,
+ 0x3084: 0xf0001c1c, 0x3085: 0xf0001c1c, 0x3086: 0xf0001c1d, 0x3087: 0xf0001c1d,
+ 0x3088: 0xf0001d1c, 0x3089: 0xf0001c1d, 0x308a: 0xf0001c1c, 0x308b: 0xf0001d1d,
+ 0x308c: 0xf0001c1c, 0x308d: 0xf0001d1d, 0x308e: 0xf0001d1d, 0x308f: 0xf0001c1c,
+ 0x3090: 0xf0001c1c, 0x3091: 0xf0001c1c, 0x3092: 0xf0001c1c, 0x3093: 0xf0001c1c,
+ 0x3094: 0xf0001c1c, 0x3095: 0xf0001c1c, 0x3096: 0xf0001c1c, 0x3097: 0xf0001d1d,
+ 0x3098: 0xf0001c1c, 0x3099: 0xf0001d1d, 0x309a: 0xf0001d1d, 0x309b: 0xf0001c1c,
+ 0x309c: 0xf0001c1d, 0x309d: 0xf0001c1d, 0x309e: 0xf0001c1d, 0x309f: 0xf0001c1d,
+ 0x30a0: 0xf0000404, 0x30a1: 0xf0000404, 0x30a2: 0xf0000404, 0x30a3: 0xf0000404,
+ 0x30a4: 0xf0000404, 0x30a5: 0xf0000404, 0x30a6: 0xf0000404, 0x30a7: 0xf0000404,
+ 0x30a8: 0xf0000404, 0x30a9: 0xf0000404, 0x30aa: 0xf0000404, 0x30ab: 0xf0000404,
+ 0x30ac: 0xf0000404, 0x30ad: 0xf0000404, 0x30ae: 0xf0000404, 0x30af: 0xf0000404,
+ 0x30b0: 0xf0000404, 0x30b1: 0xf0000404, 0x30b2: 0xf0000404, 0x30b3: 0xf0000404,
+ 0x30b4: 0xf0000404, 0x30b5: 0xf0000404, 0x30b6: 0xf0000404, 0x30b7: 0xf0000404,
+ 0x30b8: 0xf0000404, 0x30b9: 0xf0000404, 0x30ba: 0xf0000404, 0x30bb: 0xf0000404,
+ 0x30bc: 0xf0000404, 0x30bd: 0xf0000404, 0x30be: 0xf0000404, 0x30bf: 0xf0001c1c,
+ // Block 0xc3, offset 0x30c0
+ 0x30c0: 0x400c7b20, 0x30c1: 0x400c7c20, 0x30c2: 0x400c7d20, 0x30c3: 0x400c7e20,
+ 0x30c4: 0x400c7f20, 0x30c5: 0x400c8020, 0x30c6: 0x400c8120, 0x30c7: 0x400c8220,
+ 0x30c8: 0x400c8320, 0x30c9: 0x400c8420, 0x30ca: 0x400c8520, 0x30cb: 0x400c8620,
+ 0x30cc: 0x400c8720, 0x30cd: 0x400c8820, 0x30ce: 0x400c8920, 0x30cf: 0x400c8a20,
+ 0x30d0: 0x400c8b20, 0x30d1: 0x400c8c20, 0x30d2: 0x400c8d20, 0x30d3: 0x400c8e20,
+ 0x30d4: 0x400c8f20, 0x30d5: 0x400c9020, 0x30d6: 0x400c9120, 0x30d7: 0x400c9220,
+ 0x30d8: 0x400c9320, 0x30d9: 0x400c9420, 0x30da: 0x400c9520, 0x30db: 0x400c9620,
+ 0x30dc: 0x400c9720, 0x30dd: 0x400c9820, 0x30de: 0x400c9920, 0x30df: 0x400c9a20,
+ 0x30e0: 0x400c9b20, 0x30e1: 0x400c9c20, 0x30e2: 0x400c9d20, 0x30e3: 0x400c9e20,
+ 0x30e4: 0x400c9f20, 0x30e5: 0x400ca020, 0x30e6: 0x400ca120, 0x30e7: 0x400ca220,
+ 0x30e8: 0x400ca320, 0x30e9: 0x400ca420, 0x30ea: 0x400ca520, 0x30eb: 0x400ca620,
+ 0x30ec: 0x400ca720, 0x30ed: 0x400ca820, 0x30ee: 0x400ca920, 0x30ef: 0x400caa20,
+ 0x30f0: 0x400cab20, 0x30f1: 0x400cac20, 0x30f2: 0x400cad20, 0x30f3: 0x400cae20,
+ 0x30f4: 0x400caf20, 0x30f5: 0x400cb020, 0x30f6: 0x400cb120, 0x30f7: 0x400cb220,
+ 0x30f8: 0x400cb320, 0x30f9: 0x400cb420, 0x30fa: 0x400cb520, 0x30fb: 0x400cb620,
+ 0x30fc: 0x400cb720, 0x30fd: 0x400cb820, 0x30fe: 0x400cb920, 0x30ff: 0x400cba20,
+ // Block 0xc4, offset 0x3100
+ 0x3100: 0x4031fb20, 0x3101: 0x4031fc20, 0x3102: 0x4031fd20, 0x3103: 0x4031fe20,
+ 0x3104: 0x4031ff20, 0x3105: 0x40320020, 0x3106: 0x40320120, 0x3107: 0x40320220,
+ 0x3108: 0x40320320, 0x3109: 0x40320420, 0x310a: 0x40320520, 0x310b: 0x40320620,
+ 0x310c: 0x40320720, 0x310d: 0x40320820, 0x310e: 0x40320920, 0x310f: 0x40320a20,
+ 0x3110: 0x40320b20, 0x3111: 0x40320c20, 0x3112: 0x40320d20, 0x3113: 0x40320e20,
+ 0x3114: 0x40320f20, 0x3115: 0x40321020, 0x3116: 0x40321120, 0x3117: 0x40321220,
+ 0x3118: 0x40321320, 0x3119: 0x40321420, 0x311a: 0x40321520, 0x311b: 0x40321620,
+ 0x311c: 0x40321720, 0x311d: 0x40321820, 0x311e: 0x40321920, 0x311f: 0x40321a20,
+ 0x3120: 0x40321b20, 0x3121: 0x40321c20, 0x3122: 0x40321d20, 0x3123: 0x40321e20,
+ 0x3124: 0x40321f20, 0x3125: 0x40322020, 0x3126: 0x40322120, 0x3127: 0x40322220,
+ 0x3128: 0x40322320, 0x3129: 0x40322420, 0x312a: 0x40322520, 0x312b: 0x40322620,
+ 0x312c: 0x40322720, 0x312d: 0x40322820, 0x312e: 0x40322920, 0x312f: 0x40322a20,
+ 0x3130: 0x40322b20, 0x3131: 0x40322c20, 0x3132: 0x40322d20, 0x3133: 0x40322e20,
+ 0x3134: 0x40322f20, 0x3135: 0x40323020, 0x3136: 0x40323120, 0x3137: 0x40323220,
+ 0x3138: 0x40323320, 0x3139: 0x40323420, 0x313a: 0x40323520, 0x313b: 0x40323620,
+ 0x313c: 0x40323720, 0x313d: 0x40323820, 0x313e: 0x40323920, 0x313f: 0x40323a20,
+ // Block 0xc5, offset 0x3140
+ 0x3140: 0x40323b20, 0x3141: 0x40323c20, 0x3142: 0x40323d20, 0x3143: 0x40323e20,
+ 0x3144: 0x40323f20, 0x3145: 0x40324020, 0x3146: 0x40324120, 0x3147: 0x40324220,
+ 0x3148: 0x40324320, 0x3149: 0x40324420, 0x314a: 0x40324520, 0x314b: 0x40324620,
+ 0x314c: 0x40324720, 0x314d: 0x40324820, 0x314e: 0x40324920, 0x314f: 0x40324a20,
+ 0x3150: 0x40324b20, 0x3151: 0x40324c20, 0x3152: 0x40324d20, 0x3153: 0x40324e20,
+ 0x3154: 0x40324f20, 0x3155: 0x40325020, 0x3156: 0x40325120, 0x3157: 0x40325220,
+ 0x3158: 0x40325320, 0x3159: 0x40325420, 0x315a: 0x40325520, 0x315b: 0x40325620,
+ 0x315c: 0x40325720, 0x315d: 0x40325820, 0x315e: 0x40325920, 0x315f: 0x40325a20,
+ 0x3160: 0x40325b20, 0x3161: 0x40325c20, 0x3162: 0x40325d20, 0x3163: 0x40325e20,
+ 0x3164: 0x40325f20, 0x3165: 0x40326020, 0x3166: 0x40326120, 0x3167: 0x40326220,
+ 0x3168: 0x40326320, 0x3169: 0x40326420, 0x316a: 0x40326520, 0x316b: 0x40326620,
+ 0x316c: 0x40326720, 0x316d: 0x40326820, 0x316e: 0x40326920, 0x316f: 0x40326a20,
+ 0x3170: 0x40326b20, 0x3171: 0x40326c20, 0x3172: 0x40326d20, 0x3173: 0x40326e20,
+ 0x3174: 0x40326f20, 0x3175: 0x40327020, 0x3176: 0x40327120, 0x3177: 0x40327220,
+ 0x3178: 0x40327320, 0x3179: 0x40327420, 0x317a: 0x40327520, 0x317b: 0x40327620,
+ 0x317c: 0x40327720, 0x317d: 0x40327820, 0x317e: 0x40327920, 0x317f: 0x40327a20,
+ // Block 0xc6, offset 0x3180
+ 0x3180: 0x40327b20, 0x3181: 0x40327c20, 0x3182: 0x40327d20, 0x3183: 0x40327e20,
+ 0x3184: 0x40327f20, 0x3185: 0x40328020, 0x3186: 0x40328120, 0x3187: 0x40328220,
+ 0x3188: 0x40328320, 0x3189: 0x40328420, 0x318a: 0x40328520, 0x318b: 0x40328620,
+ 0x318c: 0x40328720, 0x318d: 0x40328820, 0x318e: 0x40328920, 0x318f: 0x40328a20,
+ 0x3190: 0x40328b20, 0x3191: 0x40328c20, 0x3192: 0x40328d20, 0x3193: 0x40328e20,
+ 0x3194: 0x40328f20, 0x3195: 0x40329020, 0x3196: 0x40329120, 0x3197: 0x40329220,
+ 0x3198: 0x40329320, 0x3199: 0x40329420, 0x319a: 0x40329520, 0x319b: 0x40329620,
+ 0x319c: 0x40329720, 0x319d: 0x40329820, 0x319e: 0x40329920, 0x319f: 0x40329a20,
+ 0x31a0: 0x40329b20, 0x31a1: 0x40329c20, 0x31a2: 0x40329d20, 0x31a3: 0x40329e20,
+ 0x31a4: 0x40329f20, 0x31a5: 0x4032a020, 0x31a6: 0x4032a120, 0x31a7: 0x4032a220,
+ 0x31a8: 0x4032a320, 0x31a9: 0x4032a420, 0x31aa: 0x4032a520, 0x31ab: 0x4032a620,
+ 0x31ac: 0x4032a720, 0x31ad: 0x4032a820, 0x31ae: 0x4032a920, 0x31af: 0x4032aa20,
+ 0x31b0: 0x4032ab20, 0x31b1: 0x4032ac20, 0x31b2: 0x4032ad20, 0x31b3: 0x4032ae20,
+ 0x31b4: 0x4032af20, 0x31b5: 0x4032b020, 0x31b6: 0x4032b120, 0x31b7: 0x4032b220,
+ 0x31b8: 0x4032b320, 0x31b9: 0x4032b420, 0x31ba: 0x4032b520, 0x31bb: 0x4032b620,
+ 0x31bc: 0x4032b720, 0x31bd: 0x4032b820, 0x31be: 0x4032b920, 0x31bf: 0x4032ba20,
+ // Block 0xc7, offset 0x31c0
+ 0x31c0: 0x4032bb20, 0x31c1: 0x4032bc20, 0x31c2: 0x4032bd20, 0x31c3: 0x4032be20,
+ 0x31c4: 0x4032bf20, 0x31c5: 0x4032c020, 0x31c6: 0x4032c120, 0x31c7: 0x4032c220,
+ 0x31c8: 0x4032c320, 0x31c9: 0x4032c420, 0x31ca: 0x4032c520, 0x31cb: 0x4032c620,
+ 0x31cc: 0x4032c720, 0x31cd: 0x4032c820, 0x31ce: 0x4032c920, 0x31cf: 0x4032ca20,
+ 0x31d0: 0x4032cb20, 0x31d1: 0x4032cc20, 0x31d2: 0x4032cd20, 0x31d3: 0x4032ce20,
+ 0x31d4: 0x4032cf20, 0x31d5: 0x4032d020, 0x31d6: 0x4032d120, 0x31d7: 0x4032d220,
+ 0x31d8: 0x4032d320, 0x31d9: 0x4032d420, 0x31da: 0x4032d520, 0x31db: 0x4032d620,
+ 0x31dc: 0x4032d720, 0x31dd: 0x4032d820, 0x31de: 0x4032d920, 0x31df: 0x4032da20,
+ 0x31e0: 0x4032db20, 0x31e1: 0x4032dc20, 0x31e2: 0x4032dd20, 0x31e3: 0x4032de20,
+ 0x31e4: 0x4032df20, 0x31e5: 0x4032e020, 0x31e6: 0x4032e120, 0x31e7: 0x4032e220,
+ 0x31e8: 0x4032e320, 0x31e9: 0x4032e420, 0x31ea: 0x4032e520, 0x31eb: 0x4032e620,
+ 0x31ec: 0x4032e720, 0x31ed: 0x4032e820, 0x31ee: 0x4032e920, 0x31ef: 0x4032ea20,
+ 0x31f0: 0x4032eb20, 0x31f1: 0x4032ec20, 0x31f2: 0x4032ed20, 0x31f3: 0x4032ee20,
+ 0x31f4: 0x4032ef20, 0x31f5: 0x4032f020, 0x31f6: 0x4032f120, 0x31f7: 0x4032f220,
+ 0x31f8: 0x4032f320, 0x31f9: 0x4032f420, 0x31fa: 0x4032f520, 0x31fb: 0x4032f620,
+ 0x31fc: 0x4032f720, 0x31fd: 0x4032f820, 0x31fe: 0x4032f920, 0x31ff: 0x4032fa20,
+ // Block 0xc8, offset 0x3200
+ 0x3200: 0x4032fb20, 0x3201: 0x4032fc20, 0x3202: 0x4032fd20, 0x3203: 0x4032fe20,
+ 0x3204: 0x4032ff20, 0x3205: 0x40330020, 0x3206: 0x40330120, 0x3207: 0x40330220,
+ 0x3208: 0x40330320, 0x3209: 0x40330420, 0x320a: 0x40330520, 0x320b: 0x40330620,
+ 0x320c: 0x40330720, 0x320d: 0x40330820, 0x320e: 0x40330920, 0x320f: 0x40330a20,
+ 0x3210: 0x40330b20, 0x3211: 0x40330c20, 0x3212: 0x40330d20, 0x3213: 0x40330e20,
+ 0x3214: 0x40330f20, 0x3215: 0x40331020, 0x3216: 0x40331120, 0x3217: 0x40331220,
+ 0x3218: 0x40331320, 0x3219: 0x40331420, 0x321a: 0x40331520, 0x321b: 0x40331620,
+ 0x321c: 0x40331720, 0x321d: 0x40331820, 0x321e: 0x40331920, 0x321f: 0x40331a20,
+ 0x3220: 0x40331b20, 0x3221: 0x40331c20, 0x3222: 0x40331d20, 0x3223: 0x40331e20,
+ 0x3224: 0x40331f20, 0x3225: 0x40332020, 0x3226: 0x40332120, 0x3227: 0x40332220,
+ 0x3228: 0x40332320, 0x3229: 0x40332420, 0x322a: 0x40332520, 0x322b: 0x40332620,
+ 0x322c: 0x40332720, 0x322d: 0x40332820, 0x322e: 0x40332920, 0x322f: 0x40332a20,
+ 0x3230: 0x40332b20, 0x3231: 0x40332c20, 0x3232: 0x40332d20, 0x3233: 0x40332e20,
+ 0x3234: 0x40332f20, 0x3235: 0x40333020, 0x3236: 0x40333120, 0x3237: 0x40333220,
+ 0x3238: 0x40333320, 0x3239: 0x40333420, 0x323a: 0x40333520, 0x323b: 0x40333620,
+ 0x323c: 0x40333720, 0x323d: 0x40333820, 0x323e: 0x40333920, 0x323f: 0x40333a20,
+ // Block 0xc9, offset 0x3240
+ 0x3240: 0x40333b20, 0x3241: 0x40333c20, 0x3242: 0x40333d20, 0x3243: 0x40333e20,
+ 0x3244: 0x40333f20, 0x3245: 0x40334020, 0x3246: 0x40334120, 0x3247: 0x40334220,
+ 0x3248: 0x40334320, 0x3249: 0x40334420, 0x324a: 0x40334520, 0x324b: 0x40334620,
+ 0x324c: 0x40334720, 0x324d: 0x40334820, 0x324e: 0x40334920, 0x324f: 0x40334a20,
+ 0x3250: 0x40334b20, 0x3251: 0x40334c20, 0x3252: 0x40334d20, 0x3253: 0x40334e20,
+ 0x3254: 0x40334f20, 0x3255: 0x40335020, 0x3256: 0x40335120, 0x3257: 0x40335220,
+ 0x3258: 0x40335320, 0x3259: 0x40335420, 0x325a: 0x40335520, 0x325b: 0x40335620,
+ 0x325c: 0x40335720, 0x325d: 0x40335820, 0x325e: 0x40335920, 0x325f: 0x40335a20,
+ 0x3260: 0x40335b20, 0x3261: 0x40335c20, 0x3262: 0x40335d20, 0x3263: 0x40335e20,
+ 0x3264: 0x40335f20, 0x3265: 0x40336020, 0x3266: 0x40336120, 0x3267: 0x40336220,
+ 0x3268: 0x40336320, 0x3269: 0x40336420, 0x326a: 0x40336520, 0x326b: 0x40336620,
+ 0x326c: 0x40336720, 0x326d: 0x40336820, 0x326e: 0x40336920, 0x326f: 0x40336a20,
+ 0x3270: 0x40336b20, 0x3271: 0x40336c20, 0x3272: 0x40336d20, 0x3273: 0x40336e20,
+ 0x3274: 0x40336f20, 0x3275: 0x40337020, 0x3276: 0x40337120, 0x3277: 0x40337220,
+ 0x3278: 0x40337320, 0x3279: 0x40337420, 0x327a: 0x40337520, 0x327b: 0x40337620,
+ 0x327c: 0x40337720, 0x327d: 0x40337820, 0x327e: 0x40337920, 0x327f: 0x40337a20,
+ // Block 0xca, offset 0x3280
+ 0x3280: 0x40337b20, 0x3281: 0x40337c20, 0x3282: 0x40337d20, 0x3283: 0x40337e20,
+ 0x3284: 0x40337f20, 0x3285: 0x40338020, 0x3286: 0x40338120, 0x3287: 0x40338220,
+ 0x3288: 0x40338320, 0x3289: 0x40338420, 0x328a: 0x40338520, 0x328b: 0x40338620,
+ 0x328c: 0x40338720, 0x328d: 0x40338820, 0x328e: 0x40338920, 0x328f: 0x40338a20,
+ 0x3290: 0x40338b20, 0x3291: 0x40338c20, 0x3292: 0x40338d20, 0x3293: 0x40338e20,
+ 0x3294: 0x40338f20, 0x3295: 0x40339020, 0x3296: 0x40339120, 0x3297: 0x40339220,
+ 0x3298: 0x40339320, 0x3299: 0x40339420, 0x329a: 0x40339520, 0x329b: 0x40339620,
+ 0x329c: 0x40339720, 0x329d: 0x40339820, 0x329e: 0x40339920, 0x329f: 0x40339a20,
+ 0x32a0: 0x40339b20, 0x32a1: 0x40339c20, 0x32a2: 0x40339d20, 0x32a3: 0x40339e20,
+ 0x32a4: 0x40339f20, 0x32a5: 0x4033a020, 0x32a6: 0x4033a120, 0x32a7: 0x4033a220,
+ 0x32a8: 0x4033a320, 0x32a9: 0x4033a420, 0x32aa: 0x4033a520, 0x32ab: 0x4033a620,
+ 0x32ac: 0x4033a720, 0x32ad: 0x4033a820, 0x32ae: 0x4033a920, 0x32af: 0x4033aa20,
+ 0x32b0: 0x4033ab20, 0x32b1: 0x4033ac20, 0x32b2: 0x4033ad20, 0x32b3: 0x4033ae20,
+ 0x32b4: 0x4033af20, 0x32b5: 0x4033b020, 0x32b6: 0x4033b120, 0x32b7: 0x4033b220,
+ 0x32b8: 0x4033b320, 0x32b9: 0x4033b420, 0x32ba: 0x4033b520, 0x32bb: 0x4033b620,
+ 0x32bc: 0x4033b720, 0x32bd: 0x4033b820, 0x32be: 0x4033b920, 0x32bf: 0x4033ba20,
+ // Block 0xcb, offset 0x32c0
+ 0x32c0: 0x4033bb20, 0x32c1: 0x4033bc20, 0x32c2: 0x4033bd20, 0x32c3: 0x4033be20,
+ 0x32c4: 0x4033bf20, 0x32c5: 0x4033c020, 0x32c6: 0x4033c120, 0x32c7: 0x4033c220,
+ 0x32c8: 0x4033c320, 0x32c9: 0x4033c420, 0x32ca: 0x4033c520, 0x32cb: 0x4033c620,
+ 0x32cc: 0x4033c720, 0x32cd: 0x4033c820, 0x32ce: 0x4033c920, 0x32cf: 0x4033ca20,
+ 0x32d0: 0x4033cb20, 0x32d1: 0x4033cc20, 0x32d2: 0x4033cd20, 0x32d3: 0x4033ce20,
+ 0x32d4: 0x4033cf20, 0x32d5: 0x4033d020, 0x32d6: 0x4033d120, 0x32d7: 0x4033d220,
+ 0x32d8: 0x4033d320, 0x32d9: 0x4033d420, 0x32da: 0x4033d520, 0x32db: 0x4033d620,
+ 0x32dc: 0x4033d720, 0x32dd: 0x4033d820, 0x32de: 0x4033d920, 0x32df: 0x4033da20,
+ 0x32e0: 0x4033db20, 0x32e1: 0x4033dc20, 0x32e2: 0x4033dd20, 0x32e3: 0x4033de20,
+ 0x32e4: 0x4033df20, 0x32e5: 0x4033e020, 0x32e6: 0x4033e120, 0x32e7: 0x4033e220,
+ 0x32e8: 0x4033e320, 0x32e9: 0x4033e420, 0x32ea: 0x4033e520, 0x32eb: 0x4033e620,
+ 0x32ec: 0x4033e720, 0x32ed: 0x4033e820, 0x32ee: 0x4033e920, 0x32ef: 0x4033ea20,
+ 0x32f0: 0x4033eb20, 0x32f1: 0x4033ec20, 0x32f2: 0x4033ed20, 0x32f3: 0x4033ee20,
+ 0x32f4: 0x4033ef20, 0x32f5: 0x4033f020, 0x32f6: 0x4033f120, 0x32f7: 0x4033f220,
+ 0x32f8: 0x4033f320, 0x32f9: 0x4033f420, 0x32fa: 0x4033f520, 0x32fb: 0x4033f620,
+ 0x32fc: 0x4033f720, 0x32fd: 0x4033f820, 0x32fe: 0x4033f920, 0x32ff: 0x4033fa20,
+ // Block 0xcc, offset 0x3300
+ 0x3300: 0x4033fb20, 0x3301: 0x4033fc20, 0x3302: 0x4033fd20, 0x3303: 0x4033fe20,
+ 0x3304: 0x4033ff20, 0x3305: 0x40340020, 0x3306: 0x40340120, 0x3307: 0x40340220,
+ 0x3308: 0x40340320, 0x3309: 0x40340420, 0x330a: 0x40340520, 0x330b: 0x40340620,
+ 0x330c: 0x40340720, 0x330d: 0x40340820, 0x330e: 0x40340920, 0x330f: 0x40340a20,
+ 0x3310: 0x40340b20, 0x3311: 0x40340c20, 0x3312: 0x40340d20, 0x3313: 0x40340e20,
+ 0x3314: 0x40340f20, 0x3315: 0x40341020, 0x3316: 0x40341120, 0x3317: 0x40341220,
+ 0x3318: 0x40341320, 0x3319: 0x40341420, 0x331a: 0x40341520, 0x331b: 0x40341620,
+ 0x331c: 0x40341720, 0x331d: 0x40341820, 0x331e: 0x40341920, 0x331f: 0x40341a20,
+ 0x3320: 0x40341b20, 0x3321: 0x40341c20, 0x3322: 0x40341d20, 0x3323: 0x40341e20,
+ 0x3324: 0x40341f20, 0x3325: 0x40342020, 0x3326: 0x40342120, 0x3327: 0x40342220,
+ 0x3328: 0x40342320, 0x3329: 0x40342420, 0x332a: 0x40342520, 0x332b: 0x40342620,
+ 0x332c: 0x40342720, 0x332d: 0x40342820, 0x332e: 0x40342920, 0x332f: 0x40342a20,
+ 0x3330: 0x40342b20, 0x3331: 0x40342c20, 0x3332: 0x40342d20, 0x3333: 0x40342e20,
+ 0x3334: 0x40342f20, 0x3335: 0x40343020, 0x3336: 0x40343120, 0x3337: 0x40343220,
+ 0x3338: 0x40343320, 0x3339: 0x40343420, 0x333a: 0x40343520, 0x333b: 0x40343620,
+ 0x333c: 0x40343720, 0x333d: 0x40343820, 0x333e: 0x40343920, 0x333f: 0x40343a20,
+ // Block 0xcd, offset 0x3340
+ 0x3340: 0x40343b20, 0x3341: 0x40343c20, 0x3342: 0x40343d20, 0x3343: 0x40343e20,
+ 0x3344: 0x40343f20, 0x3345: 0x40344020, 0x3346: 0x40344120, 0x3347: 0x40344220,
+ 0x3348: 0x40344320, 0x3349: 0x40344420, 0x334a: 0x40344520, 0x334b: 0x40344620,
+ 0x334c: 0x40344720, 0x334d: 0x40344820, 0x334e: 0x40344920, 0x334f: 0x40344a20,
+ 0x3350: 0x40344b20, 0x3351: 0x40344c20, 0x3352: 0x40344d20, 0x3353: 0x40344e20,
+ 0x3354: 0x40344f20, 0x3355: 0x40345020, 0x3356: 0x40345120, 0x3357: 0x40345220,
+ 0x3358: 0x40345320, 0x3359: 0x40345420, 0x335a: 0x40345520, 0x335b: 0x40345620,
+ 0x335c: 0x40345720, 0x335d: 0x40345820, 0x335e: 0x40345920, 0x335f: 0x40345a20,
+ 0x3360: 0x40345b20, 0x3361: 0x40345c20, 0x3362: 0x40345d20, 0x3363: 0x40345e20,
+ 0x3364: 0x40345f20, 0x3365: 0x40346020, 0x3366: 0x40346120, 0x3367: 0x40346220,
+ 0x3368: 0x40346320, 0x3369: 0x40346420, 0x336a: 0x40346520, 0x336b: 0x40346620,
+ 0x336c: 0x40346720, 0x336d: 0x40346820, 0x336e: 0x40346920, 0x336f: 0x40346a20,
+ 0x3370: 0x40346b20, 0x3371: 0x40346c20, 0x3372: 0x40346d20, 0x3373: 0x40346e20,
+ 0x3374: 0x40346f20, 0x3375: 0x40347020, 0x3376: 0x40347120, 0x3377: 0x40347220,
+ 0x3378: 0x40347320, 0x3379: 0x40347420, 0x337a: 0x40347520, 0x337b: 0x40347620,
+ 0x337c: 0x40347720, 0x337d: 0x40347820, 0x337e: 0x40347920, 0x337f: 0x40347a20,
+ // Block 0xce, offset 0x3380
+ 0x3380: 0x40347b20, 0x3381: 0x40347c20, 0x3382: 0x40347d20, 0x3383: 0x40347e20,
+ 0x3384: 0x40347f20, 0x3385: 0x40348020, 0x3386: 0x40348120, 0x3387: 0x40348220,
+ 0x3388: 0x40348320, 0x3389: 0x40348420, 0x338a: 0x40348520, 0x338b: 0x40348620,
+ 0x338c: 0x40348720, 0x338d: 0x40348820, 0x338e: 0x40348920, 0x338f: 0x40348a20,
+ 0x3390: 0x40348b20, 0x3391: 0x40348c20, 0x3392: 0x40348d20, 0x3393: 0x40348e20,
+ 0x3394: 0x40348f20, 0x3395: 0x40349020, 0x3396: 0x40349120, 0x3397: 0x40349220,
+ 0x3398: 0x40349320, 0x3399: 0x40349420, 0x339a: 0x40349520, 0x339b: 0x40349620,
+ 0x339c: 0x40349720, 0x339d: 0x40349820, 0x339e: 0x40349920, 0x339f: 0x40349a20,
+ 0x33a0: 0x40349b20, 0x33a1: 0x40349c20, 0x33a2: 0x40349d20, 0x33a3: 0x40349e20,
+ 0x33a4: 0x40349f20, 0x33a5: 0x4034a020, 0x33a6: 0x4034a120, 0x33a7: 0x4034a220,
+ 0x33a8: 0x4034a320, 0x33a9: 0x4034a420, 0x33aa: 0x4034a520, 0x33ab: 0x4034a620,
+ 0x33ac: 0x4034a720, 0x33ad: 0x4034a820, 0x33ae: 0x4034a920, 0x33af: 0x4034aa20,
+ 0x33b0: 0x4034ab20, 0x33b1: 0x4034ac20, 0x33b2: 0x4034ad20, 0x33b3: 0x4034ae20,
+ 0x33b4: 0x4034af20, 0x33b5: 0x4034b020, 0x33b6: 0x4034b120, 0x33b7: 0x4034b220,
+ 0x33b8: 0x4034b320, 0x33b9: 0x4034b420, 0x33ba: 0x4034b520, 0x33bb: 0x4034b620,
+ 0x33bc: 0x4034b720, 0x33bd: 0x4034b820, 0x33be: 0x4034b920, 0x33bf: 0x4034ba20,
+ // Block 0xcf, offset 0x33c0
+ 0x33c0: 0x4034bb20, 0x33c1: 0x4034bc20, 0x33c2: 0x4034bd20, 0x33c3: 0x4034be20,
+ 0x33c4: 0x4034bf20, 0x33c5: 0x4034c020, 0x33c6: 0x4034c120, 0x33c7: 0x4034c220,
+ 0x33c8: 0x4034c320, 0x33c9: 0x4034c420, 0x33ca: 0x4034c520, 0x33cb: 0x4034c620,
+ 0x33cc: 0x4034c720, 0x33cd: 0x4034c820, 0x33ce: 0x4034c920, 0x33cf: 0x4034ca20,
+ 0x33d0: 0x4034cb20, 0x33d1: 0x4034cc20, 0x33d2: 0x4034cd20, 0x33d3: 0x4034ce20,
+ 0x33d4: 0x4034cf20, 0x33d5: 0x4034d020, 0x33d6: 0x4034d120, 0x33d7: 0x4034d220,
+ 0x33d8: 0x4034d320, 0x33d9: 0x4034d420, 0x33da: 0x4034d520, 0x33db: 0x4034d620,
+ 0x33dc: 0x4034d720, 0x33dd: 0x4034d820, 0x33de: 0x4034d920, 0x33df: 0x4034da20,
+ 0x33e0: 0x4034db20, 0x33e1: 0x4034dc20, 0x33e2: 0x4034dd20, 0x33e3: 0x4034de20,
+ 0x33e4: 0x4034df20, 0x33e5: 0x4034e020, 0x33e6: 0x4034e120, 0x33e7: 0x4034e220,
+ 0x33e8: 0x4034e320, 0x33e9: 0x4034e420, 0x33ea: 0x4034e520, 0x33eb: 0x4034e620,
+ 0x33ec: 0x4034e720, 0x33ed: 0x4034e820, 0x33ee: 0x4034e920, 0x33ef: 0x4034ea20,
+ 0x33f0: 0x4034eb20, 0x33f1: 0x4034ec20, 0x33f2: 0x4034ed20, 0x33f3: 0x4034ee20,
+ 0x33f4: 0x4034ef20, 0x33f5: 0x4034f020, 0x33f6: 0x4034f120, 0x33f7: 0x4034f220,
+ 0x33f8: 0x4034f320, 0x33f9: 0x4034f420, 0x33fa: 0x4034f520, 0x33fb: 0x4034f620,
+ 0x33fc: 0x4034f720, 0x33fd: 0x4034f820, 0x33fe: 0x4034f920, 0x33ff: 0x4034fa20,
+ // Block 0xd0, offset 0x3400
+ 0x3400: 0x4034fb20, 0x3401: 0x4034fc20, 0x3402: 0x4034fd20, 0x3403: 0x4034fe20,
+ 0x3404: 0x4034ff20, 0x3405: 0x40350020, 0x3406: 0x40350120, 0x3407: 0x40350220,
+ 0x3408: 0x40350320, 0x3409: 0x40350420, 0x340a: 0x40350520, 0x340b: 0x40350620,
+ 0x340c: 0x40350720, 0x340d: 0x40350820, 0x340e: 0x40350920, 0x340f: 0x40350a20,
+ 0x3410: 0x40350b20, 0x3411: 0x40350c20, 0x3412: 0x40350d20, 0x3413: 0x40350e20,
+ 0x3414: 0x40350f20, 0x3415: 0x40351020, 0x3416: 0x40351120, 0x3417: 0x40351220,
+ 0x3418: 0x40351320, 0x3419: 0x40351420, 0x341a: 0x40351520, 0x341b: 0x40351620,
+ 0x341c: 0x40351720, 0x341d: 0x40351820, 0x341e: 0x40351920, 0x341f: 0x40351a20,
+ 0x3420: 0x40351b20, 0x3421: 0x40351c20, 0x3422: 0x40351d20, 0x3423: 0x40351e20,
+ 0x3424: 0x40351f20, 0x3425: 0x40352020, 0x3426: 0x40352120, 0x3427: 0x40352220,
+ 0x3428: 0x40352320, 0x3429: 0x40352420, 0x342a: 0x40352520, 0x342b: 0x40352620,
+ 0x342c: 0x40352720, 0x342d: 0x40352820, 0x342e: 0x40352920, 0x342f: 0x40352a20,
+ 0x3430: 0x40352b20, 0x3431: 0x40352c20, 0x3432: 0x40352d20, 0x3433: 0x40352e20,
+ 0x3434: 0x40352f20, 0x3435: 0x40353020, 0x3436: 0x40353120, 0x3437: 0x40353220,
+ 0x3438: 0x40353320, 0x3439: 0x40353420, 0x343a: 0x40353520, 0x343b: 0x40353620,
+ 0x343c: 0x40353720, 0x343d: 0x40353820, 0x343e: 0x40353920, 0x343f: 0x40353a20,
+ // Block 0xd1, offset 0x3440
+ 0x3440: 0x40353b20, 0x3441: 0x40353c20, 0x3442: 0x40353d20, 0x3443: 0x40353e20,
+ 0x3444: 0x40353f20, 0x3445: 0x40354020, 0x3446: 0x40354120, 0x3447: 0x40354220,
+ 0x3448: 0x40354320, 0x3449: 0x40354420, 0x344a: 0x40354520, 0x344b: 0x40354620,
+ 0x344c: 0x40354720, 0x344d: 0x40354820, 0x344e: 0x40354920, 0x344f: 0x40354a20,
+ 0x3450: 0x40354b20, 0x3451: 0x40354c20, 0x3452: 0x40354d20, 0x3453: 0x40354e20,
+ 0x3454: 0x40354f20, 0x3455: 0x40355020, 0x3456: 0x40355120, 0x3457: 0x40355220,
+ 0x3458: 0x40355320, 0x3459: 0x40355420, 0x345a: 0x40355520, 0x345b: 0x40355620,
+ 0x345c: 0x40355720, 0x345d: 0x40355820, 0x345e: 0x40355920, 0x345f: 0x40355a20,
+ 0x3460: 0x40355b20, 0x3461: 0x40355c20, 0x3462: 0x40355d20, 0x3463: 0x40355e20,
+ 0x3464: 0x40355f20, 0x3465: 0x40356020, 0x3466: 0x40356120, 0x3467: 0x40356220,
+ 0x3468: 0x40356320, 0x3469: 0x40356420, 0x346a: 0x40356520, 0x346b: 0x40356620,
+ 0x346c: 0x40356720, 0x346d: 0x40356820, 0x346e: 0x40356920, 0x346f: 0x40356a20,
+ 0x3470: 0x40356b20, 0x3471: 0x40356c20, 0x3472: 0x40356d20, 0x3473: 0x40356e20,
+ 0x3474: 0x40356f20, 0x3475: 0x40357020, 0x3476: 0x40357120, 0x3477: 0x40357220,
+ 0x3478: 0x40357320, 0x3479: 0x40357420, 0x347a: 0x40357520, 0x347b: 0x40357620,
+ 0x347c: 0x40357720, 0x347d: 0x40357820, 0x347e: 0x40357920, 0x347f: 0x40357a20,
+ // Block 0xd2, offset 0x3480
+ 0x3480: 0x40357b20, 0x3481: 0x40357c20, 0x3482: 0x40357d20, 0x3483: 0x40357e20,
+ 0x3484: 0x40357f20, 0x3485: 0x40358020, 0x3486: 0x40358120, 0x3487: 0x40358220,
+ 0x3488: 0x40358320, 0x3489: 0x40358420, 0x348a: 0x40358520, 0x348b: 0x40358620,
+ 0x348c: 0x40358720, 0x348d: 0x40358820, 0x348e: 0x40358920, 0x348f: 0x40358a20,
+ 0x3490: 0x40358b20, 0x3491: 0x40358c20, 0x3492: 0x40358d20, 0x3493: 0x40358e20,
+ 0x3494: 0x40358f20, 0x3495: 0x40359020, 0x3496: 0x40359120, 0x3497: 0x40359220,
+ 0x3498: 0x40359320, 0x3499: 0x40359420, 0x349a: 0x40359520, 0x349b: 0x40359620,
+ 0x349c: 0x40359720, 0x349d: 0x40359820, 0x349e: 0x40359920, 0x349f: 0x40359a20,
+ 0x34a0: 0x40359b20, 0x34a1: 0x40359c20, 0x34a2: 0x40359d20, 0x34a3: 0x40359e20,
+ 0x34a4: 0x40359f20, 0x34a5: 0x4035a020, 0x34a6: 0x4035a120, 0x34a7: 0x4035a220,
+ 0x34a8: 0x4035a320, 0x34a9: 0x4035a420, 0x34aa: 0x4035a520, 0x34ab: 0x4035a620,
+ 0x34ac: 0x4035a720, 0x34ad: 0x4035a820, 0x34ae: 0x4035a920, 0x34af: 0x4035aa20,
+ 0x34b0: 0x4035ab20, 0x34b1: 0x4035ac20, 0x34b2: 0x4035ad20, 0x34b3: 0x4035ae20,
+ 0x34b4: 0x4035af20, 0x34b5: 0x4035b020, 0x34b6: 0x4035b120, 0x34b7: 0x4035b220,
+ 0x34b8: 0x4035b320, 0x34b9: 0x4035b420, 0x34ba: 0x4035b520, 0x34bb: 0x4035b620,
+ 0x34bc: 0x4035b720, 0x34bd: 0x4035b820, 0x34be: 0x4035b920, 0x34bf: 0x4035ba20,
+ // Block 0xd3, offset 0x34c0
+ 0x34c0: 0x4035bb20, 0x34c1: 0x4035bc20, 0x34c2: 0x4035bd20, 0x34c3: 0x4035be20,
+ 0x34c4: 0x4035bf20, 0x34c5: 0x4035c020, 0x34c6: 0x4035c120, 0x34c7: 0x4035c220,
+ 0x34c8: 0x4035c320, 0x34c9: 0x4035c420, 0x34ca: 0x4035c520, 0x34cb: 0x4035c620,
+ 0x34cc: 0x4035c720, 0x34cd: 0x4035c820, 0x34ce: 0x4035c920, 0x34cf: 0x4035ca20,
+ 0x34d0: 0x4035cb20, 0x34d1: 0x4035cc20, 0x34d2: 0x4035cd20, 0x34d3: 0x4035ce20,
+ 0x34d4: 0x4035cf20, 0x34d5: 0x4035d020, 0x34d6: 0x4035d120, 0x34d7: 0x4035d220,
+ 0x34d8: 0x4035d320, 0x34d9: 0x4035d420, 0x34da: 0x4035d520, 0x34db: 0x4035d620,
+ 0x34dc: 0x4035d720, 0x34dd: 0x4035d820, 0x34de: 0x4035d920, 0x34df: 0x4035da20,
+ 0x34e0: 0x4035db20, 0x34e1: 0x4035dc20, 0x34e2: 0x4035dd20, 0x34e3: 0x4035de20,
+ 0x34e4: 0x4035df20, 0x34e5: 0x4035e020, 0x34e6: 0x4035e120, 0x34e7: 0x4035e220,
+ 0x34e8: 0x4035e320, 0x34e9: 0x4035e420, 0x34ea: 0x4035e520, 0x34eb: 0x4035e620,
+ 0x34ec: 0x4035e720, 0x34ed: 0x4035e820, 0x34ee: 0x4035e920, 0x34ef: 0x4035ea20,
+ 0x34f0: 0x4035eb20, 0x34f1: 0x4035ec20, 0x34f2: 0x4035ed20, 0x34f3: 0x4035ee20,
+ 0x34f4: 0x4035ef20, 0x34f5: 0x4035f020, 0x34f6: 0x4035f120, 0x34f7: 0x4035f220,
+ 0x34f8: 0x4035f320, 0x34f9: 0x4035f420, 0x34fa: 0x4035f520, 0x34fb: 0x4035f620,
+ 0x34fc: 0x4035f720, 0x34fd: 0x4035f820, 0x34fe: 0x4035f920, 0x34ff: 0x4035fa20,
+ // Block 0xd4, offset 0x3500
+ 0x3500: 0x4035fb20, 0x3501: 0x4035fc20, 0x3502: 0x4035fd20, 0x3503: 0x4035fe20,
+ 0x3504: 0x4035ff20, 0x3505: 0x40360020, 0x3506: 0x40360120, 0x3507: 0x40360220,
+ 0x3508: 0x40360320, 0x3509: 0x40360420, 0x350a: 0x40360520, 0x350b: 0x40360620,
+ 0x350c: 0x40360720, 0x350d: 0x40360820, 0x350e: 0x40360920, 0x350f: 0x40360a20,
+ 0x3510: 0x40360b20, 0x3511: 0x40360c20, 0x3512: 0x40360d20, 0x3513: 0x40360e20,
+ 0x3514: 0x40360f20, 0x3515: 0x40361020, 0x3516: 0x40361120, 0x3517: 0x40361220,
+ 0x3518: 0x40361320, 0x3519: 0x40361420, 0x351a: 0x40361520, 0x351b: 0x40361620,
+ 0x351c: 0x40361720, 0x351d: 0x40361820, 0x351e: 0x40361920, 0x351f: 0x40361a20,
+ 0x3520: 0x40361b20, 0x3521: 0x40361c20, 0x3522: 0x40361d20, 0x3523: 0x40361e20,
+ 0x3524: 0x40361f20, 0x3525: 0x40362020, 0x3526: 0x40362120, 0x3527: 0x40362220,
+ 0x3528: 0x40362320, 0x3529: 0x40362420, 0x352a: 0x40362520, 0x352b: 0x40362620,
+ 0x352c: 0x40362720, 0x352d: 0x40362820, 0x352e: 0x40362920, 0x352f: 0x40362a20,
+ 0x3530: 0x40362b20, 0x3531: 0x40362c20, 0x3532: 0x40362d20, 0x3533: 0x40362e20,
+ 0x3534: 0x40362f20, 0x3535: 0x40363020, 0x3536: 0x40363120, 0x3537: 0x40363220,
+ 0x3538: 0x40363320, 0x3539: 0x40363420, 0x353a: 0x40363520, 0x353b: 0x40363620,
+ 0x353c: 0x40363720, 0x353d: 0x40363820, 0x353e: 0x40363920, 0x353f: 0x40363a20,
+ // Block 0xd5, offset 0x3540
+ 0x3540: 0x40363b20, 0x3541: 0x40363c20, 0x3542: 0x40363d20, 0x3543: 0x40363e20,
+ 0x3544: 0x40363f20, 0x3545: 0x40364020, 0x3546: 0x40364120, 0x3547: 0x40364220,
+ 0x3548: 0x40364320, 0x3549: 0x40364420, 0x354a: 0x40364520, 0x354b: 0x40364620,
+ 0x354c: 0x40364720, 0x354d: 0x40364820, 0x354e: 0x40364920, 0x354f: 0x40364a20,
+ 0x3550: 0x40364b20, 0x3551: 0x40364c20, 0x3552: 0x40364d20, 0x3553: 0x40364e20,
+ 0x3554: 0x40364f20, 0x3555: 0x40365020, 0x3556: 0x40365120, 0x3557: 0x40365220,
+ 0x3558: 0x40365320, 0x3559: 0x40365420, 0x355a: 0x40365520, 0x355b: 0x40365620,
+ 0x355c: 0x40365720, 0x355d: 0x40365820, 0x355e: 0x40365920, 0x355f: 0x40365a20,
+ 0x3560: 0x40365b20, 0x3561: 0x40365c20, 0x3562: 0x40365d20, 0x3563: 0x40365e20,
+ 0x3564: 0x40365f20, 0x3565: 0x40366020, 0x3566: 0x40366120, 0x3567: 0x40366220,
+ 0x3568: 0x40366320, 0x3569: 0x40366420, 0x356a: 0x40366520, 0x356b: 0x40366620,
+ 0x356c: 0x40366720, 0x356d: 0x40366820, 0x356e: 0x40366920, 0x356f: 0x40366a20,
+ 0x3570: 0x40366b20, 0x3571: 0x40366c20, 0x3572: 0x40366d20, 0x3573: 0x40366e20,
+ 0x3574: 0x40366f20, 0x3575: 0x40367020, 0x3576: 0x40367120, 0x3577: 0x40367220,
+ 0x3578: 0x40367320, 0x3579: 0x40367420, 0x357a: 0x40367520, 0x357b: 0x40367620,
+ 0x357c: 0x40367720, 0x357d: 0x40367820, 0x357e: 0x40367920, 0x357f: 0x40367a20,
+ // Block 0xd6, offset 0x3580
+ 0x3580: 0x40367b20, 0x3581: 0x40367c20, 0x3582: 0x40367d20, 0x3583: 0x40367e20,
+ 0x3584: 0x40367f20, 0x3585: 0x40368020, 0x3586: 0x40368120, 0x3587: 0x40368220,
+ 0x3588: 0x40368320, 0x3589: 0x40368420, 0x358a: 0x40368520, 0x358b: 0x40368620,
+ 0x358c: 0x40368720,
+ 0x3590: 0x400d1220, 0x3591: 0x400d1320, 0x3592: 0x400d1420, 0x3593: 0x400d1520,
+ 0x3594: 0x400d1620, 0x3595: 0x400d1720, 0x3596: 0x400d1820, 0x3597: 0x400d1920,
+ 0x3598: 0x400d1a20, 0x3599: 0x400d1b20, 0x359a: 0x400d1c20, 0x359b: 0x400d1d20,
+ 0x359c: 0x400d1e20, 0x359d: 0x400d1f20, 0x359e: 0x400d2020, 0x359f: 0x400d2120,
+ 0x35a0: 0x400d2220, 0x35a1: 0x400d2320, 0x35a2: 0x400d2420, 0x35a3: 0x400d2520,
+ 0x35a4: 0x400d2620, 0x35a5: 0x400d2720, 0x35a6: 0x400d2820, 0x35a7: 0x400d2920,
+ 0x35a8: 0x400d2a20, 0x35a9: 0x400d2b20, 0x35aa: 0x400d2c20, 0x35ab: 0x400d2d20,
+ 0x35ac: 0x400d2e20, 0x35ad: 0x400d2f20, 0x35ae: 0x400d3020, 0x35af: 0x400d3120,
+ 0x35b0: 0x400d3220, 0x35b1: 0x400d3320, 0x35b2: 0x400d3420, 0x35b3: 0x400d3520,
+ 0x35b4: 0x400d3620, 0x35b5: 0x400d3720, 0x35b6: 0x400d3820, 0x35b7: 0x400d3920,
+ 0x35b8: 0x400d3a20, 0x35b9: 0x400d3b20, 0x35ba: 0x400d3c20, 0x35bb: 0x400d3d20,
+ 0x35bc: 0x400d3e20, 0x35bd: 0x400d3f20, 0x35be: 0x400d4020, 0x35bf: 0x400d4120,
+ // Block 0xd7, offset 0x35c0
+ 0x35c0: 0x400d4220, 0x35c1: 0x400d4320, 0x35c2: 0x400d4420, 0x35c3: 0x400d4520,
+ 0x35c4: 0x400d4620, 0x35c5: 0x400d4720, 0x35c6: 0x400d4820,
+ 0x35d0: 0x40368e20, 0x35d1: 0x40368f20, 0x35d2: 0x40369020, 0x35d3: 0x40369120,
+ 0x35d4: 0x40369220, 0x35d5: 0x40369320, 0x35d6: 0x40369420, 0x35d7: 0x40369520,
+ 0x35d8: 0x40369620, 0x35d9: 0x40369720, 0x35da: 0x40369820, 0x35db: 0x40369920,
+ 0x35dc: 0x40369a20, 0x35dd: 0x40369b20, 0x35de: 0x40369c20, 0x35df: 0x40369d20,
+ 0x35e0: 0x40369e20, 0x35e1: 0x40369f20, 0x35e2: 0x4036a020, 0x35e3: 0x4036a120,
+ 0x35e4: 0x4036a220, 0x35e5: 0x4036a320, 0x35e6: 0x4036a420, 0x35e7: 0x4036a520,
+ 0x35e8: 0x4036a620, 0x35e9: 0x4036a720, 0x35ea: 0x4036aa20, 0x35eb: 0x4036a820,
+ 0x35ec: 0x4036ab20, 0x35ed: 0x4036a920, 0x35ee: 0x4036ac20, 0x35ef: 0x4036ad20,
+ 0x35f0: 0x4036ae20, 0x35f1: 0x4036af20, 0x35f2: 0x4036b020, 0x35f3: 0x4036b120,
+ 0x35f4: 0x4036b220, 0x35f5: 0x4036b320, 0x35f6: 0x4036b420, 0x35f7: 0x4036b520,
+ 0x35f8: 0x40368820, 0x35f9: 0x40368920, 0x35fa: 0x40368a20, 0x35fb: 0x40368b20,
+ 0x35fc: 0x40368d20, 0x35fd: 0x40368c20, 0x35fe: 0x40012820, 0x35ff: 0x40017820,
+ // Block 0xd8, offset 0x3600
+ 0x3600: 0x402c9b20, 0x3601: 0x402c9c20, 0x3602: 0x402c9d20, 0x3603: 0x402c9e20,
+ 0x3604: 0x402c9f20, 0x3605: 0x402ca020, 0x3606: 0x402ca120, 0x3607: 0x402ca220,
+ 0x3608: 0x402ca320, 0x3609: 0x402ca420, 0x360a: 0x402ca520, 0x360b: 0x402ca620,
+ 0x360c: 0x402ca720, 0x360d: 0x402ca820, 0x360e: 0x402ca920, 0x360f: 0x402caa20,
+ 0x3610: 0x402cab20, 0x3611: 0x402cac20, 0x3612: 0x402cad20, 0x3613: 0x402cae20,
+ 0x3614: 0x402caf20, 0x3615: 0x402cb020, 0x3616: 0x402cb120, 0x3617: 0x402cb220,
+ 0x3618: 0x402cb320, 0x3619: 0x402cb420, 0x361a: 0x402cb520, 0x361b: 0x402cb620,
+ 0x361c: 0x402cb720, 0x361d: 0x402cb820, 0x361e: 0x402cb920, 0x361f: 0x402cba20,
+ 0x3620: 0x402cbb20, 0x3621: 0x402cbc20, 0x3622: 0x402cbd20, 0x3623: 0x402cbe20,
+ 0x3624: 0x402cbf20, 0x3625: 0x402cc020, 0x3626: 0x402cc120, 0x3627: 0x402cc220,
+ 0x3628: 0x402cc320, 0x3629: 0x402cc420, 0x362a: 0x402cc520, 0x362b: 0x402cc620,
+ 0x362c: 0x402cc720, 0x362d: 0x402cc820, 0x362e: 0x402cc920, 0x362f: 0x402cca20,
+ 0x3630: 0x402ccb20, 0x3631: 0x402ccc20, 0x3632: 0x402ccd20, 0x3633: 0x402cce20,
+ 0x3634: 0x402ccf20, 0x3635: 0x402cd020, 0x3636: 0x402cd120, 0x3637: 0x402cd220,
+ 0x3638: 0x402cd320, 0x3639: 0x402cd420, 0x363a: 0x402cd520, 0x363b: 0x402cd620,
+ 0x363c: 0x402cd720, 0x363d: 0x402cd820, 0x363e: 0x402cd920, 0x363f: 0x402cda20,
+ // Block 0xd9, offset 0x3640
+ 0x3640: 0x402cdb20, 0x3641: 0x402cdc20, 0x3642: 0x402cdd20, 0x3643: 0x402cde20,
+ 0x3644: 0x402cdf20, 0x3645: 0x402ce020, 0x3646: 0x402ce120, 0x3647: 0x402ce220,
+ 0x3648: 0x402ce320, 0x3649: 0x402ce420, 0x364a: 0x402ce520, 0x364b: 0x402ce620,
+ 0x364c: 0x402ce720, 0x364d: 0x402ce820, 0x364e: 0x402ce920, 0x364f: 0x402cea20,
+ 0x3650: 0x402ceb20, 0x3651: 0x402cec20, 0x3652: 0x402ced20, 0x3653: 0x402cee20,
+ 0x3654: 0x402cef20, 0x3655: 0x402cf020, 0x3656: 0x402cf120, 0x3657: 0x402cf220,
+ 0x3658: 0x402cf320, 0x3659: 0x402cf420, 0x365a: 0x402cf520, 0x365b: 0x402cf620,
+ 0x365c: 0x402cf720, 0x365d: 0x402cf820, 0x365e: 0x402cf920, 0x365f: 0x402cfa20,
+ 0x3660: 0x402cfb20, 0x3661: 0x402cfc20, 0x3662: 0x402cfd20, 0x3663: 0x402cfe20,
+ 0x3664: 0x402cff20, 0x3665: 0x402d0020, 0x3666: 0x402d0120, 0x3667: 0x402d0220,
+ 0x3668: 0x402d0320, 0x3669: 0x402d0420, 0x366a: 0x402d0520, 0x366b: 0x402d0620,
+ 0x366c: 0x402d0720, 0x366d: 0x402d0820, 0x366e: 0x402d0920, 0x366f: 0x402d0a20,
+ 0x3670: 0x402d0b20, 0x3671: 0x402d0c20, 0x3672: 0x402d0d20, 0x3673: 0x402d0e20,
+ 0x3674: 0x402d0f20, 0x3675: 0x402d1020, 0x3676: 0x402d1120, 0x3677: 0x402d1220,
+ 0x3678: 0x402d1320, 0x3679: 0x402d1420, 0x367a: 0x402d1520, 0x367b: 0x402d1620,
+ 0x367c: 0x402d1720, 0x367d: 0x402d1820, 0x367e: 0x402d1920, 0x367f: 0x402d1a20,
+ // Block 0xda, offset 0x3680
+ 0x3680: 0x402d1b20, 0x3681: 0x402d1c20, 0x3682: 0x402d1d20, 0x3683: 0x402d1e20,
+ 0x3684: 0x402d1f20, 0x3685: 0x402d2020, 0x3686: 0x402d2120, 0x3687: 0x402d2220,
+ 0x3688: 0x402d2320, 0x3689: 0x402d2420, 0x368a: 0x402d2520, 0x368b: 0x402d2620,
+ 0x368c: 0x402d2720, 0x368d: 0x402d2820, 0x368e: 0x402d2920, 0x368f: 0x402d2a20,
+ 0x3690: 0x402d2b20, 0x3691: 0x402d2c20, 0x3692: 0x402d2d20, 0x3693: 0x402d2e20,
+ 0x3694: 0x402d2f20, 0x3695: 0x402d3020, 0x3696: 0x402d3120, 0x3697: 0x402d3220,
+ 0x3698: 0x402d3320, 0x3699: 0x402d3420, 0x369a: 0x402d3520, 0x369b: 0x402d3620,
+ 0x369c: 0x402d3720, 0x369d: 0x402d3820, 0x369e: 0x402d3920, 0x369f: 0x402d3a20,
+ 0x36a0: 0x402d3b20, 0x36a1: 0x402d3c20, 0x36a2: 0x402d3d20, 0x36a3: 0x402d3e20,
+ 0x36a4: 0x402d3f20, 0x36a5: 0x402d4020, 0x36a6: 0x402d4120, 0x36a7: 0x402d4220,
+ 0x36a8: 0x402d4320, 0x36a9: 0x402d4420, 0x36aa: 0x402d4520, 0x36ab: 0x402d4620,
+ 0x36ac: 0x402d4720, 0x36ad: 0x402d4820, 0x36ae: 0x402d4920, 0x36af: 0x402d4a20,
+ 0x36b0: 0x402d4b20, 0x36b1: 0x402d4c20, 0x36b2: 0x402d4d20, 0x36b3: 0x402d4e20,
+ 0x36b4: 0x402d4f20, 0x36b5: 0x402d5020, 0x36b6: 0x402d5120, 0x36b7: 0x402d5220,
+ 0x36b8: 0x402d5320, 0x36b9: 0x402d5420, 0x36ba: 0x402d5520, 0x36bb: 0x402d5620,
+ 0x36bc: 0x402d5720, 0x36bd: 0x402d5820, 0x36be: 0x402d5920, 0x36bf: 0x402d5a20,
+ // Block 0xdb, offset 0x36c0
+ 0x36c0: 0x402d5b20, 0x36c1: 0x402d5c20, 0x36c2: 0x402d5d20, 0x36c3: 0x402d5e20,
+ 0x36c4: 0x402d5f20, 0x36c5: 0x402d6020, 0x36c6: 0x402d6120, 0x36c7: 0x402d6220,
+ 0x36c8: 0x402d6320, 0x36c9: 0x402d6420, 0x36ca: 0x402d6520, 0x36cb: 0x402d6620,
+ 0x36cc: 0x402d6720, 0x36cd: 0x402d6820, 0x36ce: 0x402d6920, 0x36cf: 0x402d6a20,
+ 0x36d0: 0x402d6b20, 0x36d1: 0x402d6c20, 0x36d2: 0x402d6d20, 0x36d3: 0x402d6e20,
+ 0x36d4: 0x402d6f20, 0x36d5: 0x402d7020, 0x36d6: 0x402d7120, 0x36d7: 0x402d7220,
+ 0x36d8: 0x402d7320, 0x36d9: 0x402d7420, 0x36da: 0x402d7520, 0x36db: 0x402d7620,
+ 0x36dc: 0x402d7720, 0x36dd: 0x402d7820, 0x36de: 0x402d7920, 0x36df: 0x402d7a20,
+ 0x36e0: 0x402d7b20, 0x36e1: 0x402d7c20, 0x36e2: 0x402d7d20, 0x36e3: 0x402d7e20,
+ 0x36e4: 0x402d7f20, 0x36e5: 0x402d8020, 0x36e6: 0x402d8120, 0x36e7: 0x402d8220,
+ 0x36e8: 0x402d8320, 0x36e9: 0x402d8420, 0x36ea: 0x402d8520, 0x36eb: 0x402d8620,
+ 0x36ec: 0x402d8720, 0x36ed: 0x402d8820, 0x36ee: 0x402d8920, 0x36ef: 0x402d8a20,
+ 0x36f0: 0x402d8b20, 0x36f1: 0x402d8c20, 0x36f2: 0x402d8d20, 0x36f3: 0x402d8e20,
+ 0x36f4: 0x402d8f20, 0x36f5: 0x402d9020, 0x36f6: 0x402d9120, 0x36f7: 0x402d9220,
+ 0x36f8: 0x402d9320, 0x36f9: 0x402d9420, 0x36fa: 0x402d9520, 0x36fb: 0x402d9620,
+ 0x36fc: 0x402d9720, 0x36fd: 0x402d9820, 0x36fe: 0x402d9920, 0x36ff: 0x402d9a20,
+ // Block 0xdc, offset 0x3700
+ 0x3700: 0x402d9b20, 0x3701: 0x402d9c20, 0x3702: 0x402d9d20, 0x3703: 0x402d9e20,
+ 0x3704: 0x402d9f20, 0x3705: 0x402da020, 0x3706: 0x402da120, 0x3707: 0x402da220,
+ 0x3708: 0x402da320, 0x3709: 0x402da420, 0x370a: 0x402da520, 0x370b: 0x402da620,
+ 0x370c: 0x402da720, 0x370d: 0x40012920, 0x370e: 0x40017920, 0x370f: 0x40016720,
+ 0x3710: 0x0059e604, 0x3711: 0x005a0a04, 0x3712: 0x005a4404, 0x3713: 0xe0001132,
+ 0x3714: 0xe0001135, 0x3715: 0xe0001138, 0x3716: 0xe000113b, 0x3717: 0xe000113e,
+ 0x3718: 0xe0001141, 0x3719: 0xe0001144, 0x371a: 0xe0001147, 0x371b: 0xe000114a,
+ 0x371c: 0xe000114d, 0x371d: 0xe0001150, 0x371e: 0xe0001153, 0x371f: 0xe0001156,
+ 0x3720: 0xe000008d, 0x3721: 0xe0000111, 0x3722: 0xe00001f8, 0x3723: 0xe00002be,
+ 0x3724: 0xe000037b, 0x3725: 0xe0000435, 0x3726: 0xe00004ec, 0x3727: 0xe0000588,
+ 0x3728: 0xe0000624, 0x3729: 0xe00006bd, 0x372a: 0x005a1204, 0x372b: 0x005ad804,
+ // Block 0xdd, offset 0x3740
+ 0x3740: 0x00335008, 0x3741: 0x4019a820, 0x3742: 0x00335e08, 0x3743: 0x4019af20,
+ 0x3744: 0x00336808, 0x3745: 0x4019b420, 0x3746: 0x00339808, 0x3747: 0x4019cc20,
+ 0x3748: 0x0033b208, 0x3749: 0x4019d920, 0x374a: 0x00350608, 0x374b: 0x401a8320,
+ 0x374c: 0x00355408, 0x374d: 0x401aaa20, 0x374e: 0x0035d208, 0x374f: 0x401ae920,
+ 0x3750: 0x0035e008, 0x3751: 0x401af020, 0x3752: 0x00360a08, 0x3753: 0x401b0520,
+ 0x3754: 0x00362408, 0x3755: 0x401b1220, 0x3756: 0x00362608, 0x3757: 0x401b1320,
+ 0x3758: 0x00364208, 0x3759: 0x401b2120, 0x375a: 0x00364c08, 0x375b: 0x401b2620,
+ 0x375c: 0x00365608, 0x375d: 0x401b2b20, 0x375e: 0x00368808, 0x375f: 0x401b4420,
+ 0x3760: 0x00356e08, 0x3761: 0x401ab720, 0x3762: 0x00330208, 0x3763: 0x40198120,
+ 0x3764: 0x00340608, 0x3765: 0x401a0320, 0x3766: 0x00341c08, 0x3767: 0x401a0e20,
+ 0x3768: 0x0034520a, 0x3769: 0x00345204, 0x376a: 0x0034520a, 0x376b: 0x00345204,
+ 0x376c: 0x0034520a, 0x376d: 0x00345204, 0x376e: 0x00345204, 0x376f: 0x80008402,
+ 0x3770: 0x80000000, 0x3771: 0x80000000, 0x3772: 0x80000000, 0x3773: 0x40024120,
+ 0x377c: 0x80005f02, 0x377d: 0x80005f02, 0x377e: 0x40027420, 0x377f: 0x401aeb20,
+ // Block 0xde, offset 0x3780
+ 0x3780: 0x0032f808, 0x3781: 0x40197c20, 0x3782: 0x00337608, 0x3783: 0x4019bb20,
+ 0x3784: 0x00333608, 0x3785: 0x40199b20, 0x3786: 0x0035a608, 0x3787: 0x401ad320,
+ 0x3788: 0x00337208, 0x3789: 0x4019b920, 0x378a: 0x0034c408, 0x378b: 0x401a6220,
+ 0x378c: 0x0034b808, 0x378d: 0x401a5c20, 0x378e: 0x00357008, 0x378f: 0x401ab820,
+ 0x3790: 0x00357a08, 0x3791: 0x401abd20, 0x3792: 0x00358408, 0x3793: 0x401ac220,
+ 0x3794: 0x00354208, 0x3795: 0x401aa120, 0x3796: 0x0035c808, 0x3797: 0x401ae420,
+ 0x37a0: 0x402da820, 0x37a1: 0x402da920, 0x37a2: 0x402daa20, 0x37a3: 0x402dab20,
+ 0x37a4: 0x402dac20, 0x37a5: 0x402dad20, 0x37a6: 0x402dae20, 0x37a7: 0x402daf20,
+ 0x37a8: 0x402db020, 0x37a9: 0x402db120, 0x37aa: 0x402db220, 0x37ab: 0x402db320,
+ 0x37ac: 0x402db420, 0x37ad: 0x402db520, 0x37ae: 0x402db620, 0x37af: 0x402db720,
+ 0x37b0: 0x402db820, 0x37b1: 0x402db920, 0x37b2: 0x402dba20, 0x37b3: 0x402dbb20,
+ 0x37b4: 0x402dbc20, 0x37b5: 0x402dbd20, 0x37b6: 0x402dbe20, 0x37b7: 0x402dbf20,
+ 0x37b8: 0x402dc020, 0x37b9: 0x402dc120, 0x37ba: 0x402dc220, 0x37bb: 0x402dc320,
+ 0x37bc: 0x402dc420, 0x37bd: 0x402dc520, 0x37be: 0x402dc620, 0x37bf: 0x402dc720,
+ // Block 0xdf, offset 0x37c0
+ 0x37c0: 0x402dc820, 0x37c1: 0x402dc920, 0x37c2: 0x402dca20, 0x37c3: 0x402dcb20,
+ 0x37c4: 0x402dcc20, 0x37c5: 0x402dcd20, 0x37c6: 0x402dce20, 0x37c7: 0x402dcf20,
+ 0x37c8: 0x402dd020, 0x37c9: 0x402dd120, 0x37ca: 0x402dd220, 0x37cb: 0x402dd320,
+ 0x37cc: 0x402dd420, 0x37cd: 0x402dd520, 0x37ce: 0x402dd620, 0x37cf: 0x402dd720,
+ 0x37d0: 0x402dd820, 0x37d1: 0x402dd920, 0x37d2: 0x402dda20, 0x37d3: 0x402ddb20,
+ 0x37d4: 0x402ddc20, 0x37d5: 0x402ddd20, 0x37d6: 0x402dde20, 0x37d7: 0x402ddf20,
+ 0x37d8: 0x402de020, 0x37d9: 0x402de120, 0x37da: 0x402de220, 0x37db: 0x402de320,
+ 0x37dc: 0x402de420, 0x37dd: 0x402de520, 0x37de: 0x402de620, 0x37df: 0x402de720,
+ 0x37e0: 0x402de820, 0x37e1: 0x402de920, 0x37e2: 0x402dea20, 0x37e3: 0x402deb20,
+ 0x37e4: 0x402dec20, 0x37e5: 0x402ded20, 0x37e6: 0x402dee20, 0x37e7: 0x402def20,
+ 0x37e8: 0x402df020, 0x37e9: 0x402df120, 0x37ea: 0x402df220, 0x37eb: 0x402df320,
+ 0x37ec: 0x402df420, 0x37ed: 0x402df520, 0x37ee: 0x402df620, 0x37ef: 0x402df720,
+ 0x37f0: 0x8000db02, 0x37f1: 0x8000dc02, 0x37f2: 0x4001b320, 0x37f3: 0x40017a20,
+ 0x37f4: 0x40015720, 0x37f5: 0x40012a20, 0x37f6: 0x40013120, 0x37f7: 0x40016820,
+ // Block 0xe0, offset 0x3800
+ 0x3800: 0x40035d20, 0x3801: 0x40035e20, 0x3802: 0x40035f20, 0x3803: 0x40036020,
+ 0x3804: 0x40036120, 0x3805: 0x40036220, 0x3806: 0x40036320, 0x3807: 0x40036420,
+ 0x3808: 0x40036520, 0x3809: 0x40036620, 0x380a: 0x40036720, 0x380b: 0x40036820,
+ 0x380c: 0x40036920, 0x380d: 0x40036a20, 0x380e: 0x40036b20, 0x380f: 0x40036c20,
+ 0x3810: 0x40036d20, 0x3811: 0x40036e20, 0x3812: 0x40036f20, 0x3813: 0x40037020,
+ 0x3814: 0x40037120, 0x3815: 0x40037220, 0x3816: 0x40037320, 0x3817: 0x40037420,
+ 0x3818: 0x40037520, 0x3819: 0x40037620, 0x381a: 0x40037720, 0x381b: 0x40037820,
+ 0x381c: 0x40037920, 0x381d: 0x40037a20, 0x381e: 0x40037b20, 0x381f: 0x40037c20,
+ 0x3820: 0x40037d20, 0x3821: 0x40037e20, 0x3822: 0x00314a08, 0x3823: 0x4018a520,
+ 0x3824: 0x00315e08, 0x3825: 0x4018af20, 0x3826: 0x002cf208, 0x3827: 0x40167920,
+ 0x3828: 0xe0000815, 0x3829: 0xe0000812, 0x382a: 0x00311408, 0x382b: 0x40188a20,
+ 0x382c: 0x00311608, 0x382d: 0x40188b20, 0x382e: 0x00311808, 0x382f: 0x40188c20,
+ 0x3830: 0x40163b20, 0x3831: 0x4017aa20, 0x3832: 0xe00006f0, 0x3833: 0xe00006ed,
+ 0x3834: 0xe0000708, 0x3835: 0xe0000705, 0x3836: 0xe000070e, 0x3837: 0xe000070b,
+ 0x3838: 0xe0000717, 0x3839: 0xe0000714, 0x383a: 0xe000071e, 0x383b: 0xe000071a,
+ 0x383c: 0xe0000725, 0x383d: 0xe0000722, 0x383e: 0x002bc608, 0x383f: 0x4015e320,
+ // Block 0xe1, offset 0x3840
+ 0x3840: 0x002d7a08, 0x3841: 0x4016bd20, 0x3842: 0x002d7c08, 0x3843: 0x4016be20,
+ 0x3844: 0x002d7e08, 0x3845: 0x4016bf20, 0x3846: 0x002d9808, 0x3847: 0x4016cc20,
+ 0x3848: 0x002d9c08, 0x3849: 0x4016ce20, 0x384a: 0x002e7e08, 0x384b: 0x40173f20,
+ 0x384c: 0x002e6e08, 0x384d: 0x40173720, 0x384e: 0xe00007c2, 0x384f: 0xe00007bf,
+ 0x3850: 0x002e9e08, 0x3851: 0x40174f20, 0x3852: 0x002eac08, 0x3853: 0x40175620,
+ 0x3854: 0x002eae08, 0x3855: 0x40175720, 0x3856: 0x002ec408, 0x3857: 0x40176220,
+ 0x3858: 0x002ec608, 0x3859: 0x40176320, 0x385a: 0x002ef008, 0x385b: 0x40177820,
+ 0x385c: 0x002f4a08, 0x385d: 0x4017a520, 0x385e: 0x00302e08, 0x385f: 0x40181720,
+ 0x3860: 0xe0000822, 0x3861: 0xe000081f, 0x3862: 0x0030c008, 0x3863: 0x40186020,
+ 0x3864: 0x0030f608, 0x3865: 0x40187b20, 0x3866: 0x0030f808, 0x3867: 0x40187c20,
+ 0x3868: 0x00310208, 0x3869: 0x40188120, 0x386a: 0x00310408, 0x386b: 0x40188220,
+ 0x386c: 0x00310608, 0x386d: 0x40188320, 0x386e: 0x00310808, 0x386f: 0x40188420,
+ 0x3870: 0xf0000014, 0x3871: 0x4015fd20, 0x3872: 0x4016e620, 0x3873: 0x40170120,
+ 0x3874: 0x40171f20, 0x3875: 0x4017a320, 0x3876: 0x4017a420, 0x3877: 0x4017e420,
+ 0x3878: 0x40188520, 0x3879: 0xe0000748, 0x387a: 0xe0000745, 0x387b: 0xe000075a,
+ 0x387c: 0xe0000757, 0x387d: 0xe000076e, 0x387e: 0x002cbc08, 0x387f: 0x40165e20,
+ // Block 0xe2, offset 0x3880
+ 0x3880: 0x002dd608, 0x3881: 0x4016eb20, 0x3882: 0xe00007d4, 0x3883: 0xe00007d1,
+ 0x3884: 0xe00007e6, 0x3885: 0xe00007e3, 0x3886: 0xe00007ff, 0x3887: 0xe00007fc,
+ 0x3888: 0x40037f20, 0x3889: 0x40038020, 0x388a: 0x40038120, 0x388b: 0x00314c08,
+ 0x388c: 0x4018a620, 0x388d: 0x002fee08, 0x388e: 0x4016e120,
+ 0x3890: 0x002e2a08, 0x3891: 0x40171520,
+ 0x38a0: 0xe0000768, 0x38a1: 0xe0000765, 0x38a2: 0xe0000780, 0x38a3: 0xe000077d,
+ 0x38a4: 0xe00007a4, 0x38a5: 0xe00007a1, 0x38a6: 0xe00007ce, 0x38a7: 0xe00007cb,
+ 0x38a8: 0xe00007da, 0x38a9: 0xe00007d7,
+ // Block 0xe3, offset 0x38c0
+ 0x38fa: 0x40180720, 0x38fb: 0x40164320,
+ 0x38fc: 0x40175820, 0x38fd: 0x4016ff20, 0x38fe: 0x40168c20, 0x38ff: 0x40170020,
+ // Block 0xe4, offset 0x3900
+ 0x3900: 0x40225f20, 0x3901: 0x40226020, 0x3902: 0x40226120, 0x3903: 0x40226220,
+ 0x3904: 0x40226320, 0x3905: 0x40226420, 0x3906: 0x40226520, 0x3907: 0x40226620,
+ 0x3908: 0x40226720, 0x3909: 0x40226820, 0x390a: 0x40226920, 0x390b: 0x80010d02,
+ 0x390c: 0x40226a20, 0x390d: 0x40226b20, 0x390e: 0x40226c20, 0x390f: 0x40226d20,
+ 0x3910: 0x40226e20, 0x3911: 0x40226f20, 0x3912: 0x40227020, 0x3913: 0x40227120,
+ 0x3914: 0x40227220, 0x3915: 0x40227320, 0x3916: 0x40227420, 0x3917: 0x40227520,
+ 0x3918: 0x40227620, 0x3919: 0x40227720, 0x391a: 0x40227820, 0x391b: 0x40227920,
+ 0x391c: 0x40227a20, 0x391d: 0x40227b20, 0x391e: 0x40227c20, 0x391f: 0x40227d20,
+ 0x3920: 0x40227e20, 0x3921: 0x40227f20, 0x3922: 0x40228020, 0x3923: 0x40228120,
+ 0x3924: 0x40228220, 0x3925: 0x40228320, 0x3926: 0x40228420, 0x3927: 0x40228520,
+ 0x3928: 0x40039620, 0x3929: 0x40039720, 0x392a: 0x40039820, 0x392b: 0x40039920,
+ 0x3930: 0x4013d820, 0x3931: 0x4013d920, 0x3932: 0x4013da20, 0x3933: 0x4013db20,
+ 0x3934: 0x4013dc20, 0x3935: 0x4013dd20, 0x3936: 0x40039a20, 0x3937: 0x40039b20,
+ 0x3938: 0x4013ad20, 0x3939: 0x40039c20,
+ // Block 0xe5, offset 0x3940
+ 0x3940: 0x4024e020, 0x3941: 0x4024e120, 0x3942: 0x4024e220, 0x3943: 0x4024e320,
+ 0x3944: 0x4024e420, 0x3945: 0x4024e520, 0x3946: 0x4024e620, 0x3947: 0x4024e720,
+ 0x3948: 0x4024ec20, 0x3949: 0x4024ed20, 0x394a: 0x4024ee20, 0x394b: 0x4024ef20,
+ 0x394c: 0x4024f020, 0x394d: 0x4024f120, 0x394e: 0x4024f220, 0x394f: 0x4024f320,
+ 0x3950: 0x4024f420, 0x3951: 0x4024f520, 0x3952: 0x4024f620, 0x3953: 0x4024f720,
+ 0x3954: 0x4024f920, 0x3955: 0x4024fa20, 0x3956: 0x4024fb20, 0x3957: 0x4024fc20,
+ 0x3958: 0x4024ff20, 0x3959: 0x40250220, 0x395a: 0x40250320, 0x395b: 0x40250520,
+ 0x395c: 0x40250620, 0x395d: 0x40250920, 0x395e: 0x40250e20, 0x395f: 0x40250f20,
+ 0x3960: 0x40251020, 0x3961: 0x40251120, 0x3962: 0x40250a20, 0x3963: 0x40250b20,
+ 0x3964: 0x40250c20, 0x3965: 0x40250d20, 0x3966: 0x40251220, 0x3967: 0x4024f820,
+ 0x3968: 0x4024fd20, 0x3969: 0x4024e820, 0x396a: 0x4024e920, 0x396b: 0x4024ea20,
+ 0x396c: 0x4024eb20, 0x396d: 0x4024fe20, 0x396e: 0x40250420, 0x396f: 0x40250720,
+ 0x3970: 0x40250820, 0x3971: 0x40250020, 0x3972: 0x40250120, 0x3973: 0x40251320,
+ 0x3974: 0x4002b820, 0x3975: 0x4002b920, 0x3976: 0x40018420, 0x3977: 0x40018520,
+ // Block 0xe6, offset 0x3980
+ 0x3980: 0x80010e02, 0x3981: 0x80010f02, 0x3982: 0x40228620, 0x3983: 0x40228720,
+ 0x3984: 0x40228820, 0x3985: 0x40228920, 0x3986: 0x40228a20, 0x3987: 0x40228b20,
+ 0x3988: 0x40228c20, 0x3989: 0x40228d20, 0x398a: 0x40228e20, 0x398b: 0x40228f20,
+ 0x398c: 0x40229020, 0x398d: 0x40229120, 0x398e: 0x40229220, 0x398f: 0x40229320,
+ 0x3990: 0x40229420, 0x3991: 0x40229520, 0x3992: 0x40229620, 0x3993: 0x40229720,
+ 0x3994: 0x40229820, 0x3995: 0x40229920, 0x3996: 0x40229a20, 0x3997: 0x40229b20,
+ 0x3998: 0x40229c20, 0x3999: 0x40229d20, 0x399a: 0x40229e20, 0x399b: 0x40229f20,
+ 0x399c: 0x4022a020, 0x399d: 0x4022a120, 0x399e: 0x4022a220, 0x399f: 0x4022a320,
+ 0x39a0: 0x4022a420, 0x39a1: 0x4022a520, 0x39a2: 0x4022a620, 0x39a3: 0x4022a720,
+ 0x39a4: 0x4022a820, 0x39a5: 0x4022a920, 0x39a6: 0x4022aa20, 0x39a7: 0x4022ab20,
+ 0x39a8: 0x4022ac20, 0x39a9: 0x4022ad20, 0x39aa: 0x4022ae20, 0x39ab: 0x4022af20,
+ 0x39ac: 0x4022b020, 0x39ad: 0x4022b120, 0x39ae: 0x4022b220, 0x39af: 0x4022b320,
+ 0x39b0: 0x4022b420, 0x39b1: 0x4022b520, 0x39b2: 0x4022b620, 0x39b3: 0x4022b720,
+ 0x39b4: 0x4022b820, 0x39b5: 0x4022b920, 0x39b6: 0x4022ba20, 0x39b7: 0x4022bb20,
+ 0x39b8: 0x4022bc20, 0x39b9: 0x4022bd20, 0x39ba: 0x4022be20, 0x39bb: 0x4022bf20,
+ 0x39bc: 0x4022c020, 0x39bd: 0x4022c120, 0x39be: 0x4022c220, 0x39bf: 0x4022c320,
+ // Block 0xe7, offset 0x39c0
+ 0x39c0: 0x4022c420, 0x39c1: 0x4022c520, 0x39c2: 0x4022c620, 0x39c3: 0x4022c720,
+ 0x39c4: 0x4022c820,
+ 0x39ce: 0x40018020, 0x39cf: 0x40018120,
+ 0x39d0: 0xe000004e, 0x39d1: 0xe00000cf, 0x39d2: 0xe00001b9, 0x39d3: 0xe000027f,
+ 0x39d4: 0xe000033c, 0x39d5: 0xe00003f6, 0x39d6: 0xe00004ad, 0x39d7: 0xe0000549,
+ 0x39d8: 0xe00005e5, 0x39d9: 0xe000067e,
+ 0x39e0: 0x80000000, 0x39e1: 0x80000000, 0x39e2: 0x80000000, 0x39e3: 0x80000000,
+ 0x39e4: 0x80000000, 0x39e5: 0x80000000, 0x39e6: 0x80000000, 0x39e7: 0x80000000,
+ 0x39e8: 0x80000000, 0x39e9: 0x80000000, 0x39ea: 0x80000000, 0x39eb: 0x80000000,
+ 0x39ec: 0x80000000, 0x39ed: 0x80000000, 0x39ee: 0x80000000, 0x39ef: 0x80000000,
+ 0x39f0: 0x80000000, 0x39f1: 0x80000000, 0x39f2: 0x401fc020, 0x39f3: 0x003f8004,
+ 0x39f4: 0x003f8004, 0x39f5: 0x003f8004, 0x39f6: 0x003f8004, 0x39f7: 0x003f8004,
+ 0x39f8: 0x40028520, 0x39f9: 0x40028620, 0x39fa: 0x40028720, 0x39fb: 0x401fc120,
+ // Block 0xe8, offset 0x3a00
+ 0x3a00: 0xe000006c, 0x3a01: 0xe00000f0, 0x3a02: 0xe00001d7, 0x3a03: 0xe000029d,
+ 0x3a04: 0xe000035a, 0x3a05: 0xe0000414, 0x3a06: 0xe00004cb, 0x3a07: 0xe0000567,
+ 0x3a08: 0xe0000603, 0x3a09: 0xe000069c, 0x3a0a: 0x4025f420, 0x3a0b: 0x4025f520,
+ 0x3a0c: 0x4025f620, 0x3a0d: 0x4025f720, 0x3a0e: 0x4025f820, 0x3a0f: 0x4025f920,
+ 0x3a10: 0x4025fa20, 0x3a11: 0x4025fb20, 0x3a12: 0x4025fc20, 0x3a13: 0x4025fd20,
+ 0x3a14: 0x4025fe20, 0x3a15: 0x4025ff20, 0x3a16: 0x40260020, 0x3a17: 0x40260120,
+ 0x3a18: 0x40260220, 0x3a19: 0x40260320, 0x3a1a: 0x40260420, 0x3a1b: 0x40260520,
+ 0x3a1c: 0x40260620, 0x3a1d: 0x40260720, 0x3a1e: 0x40260820, 0x3a1f: 0x40260920,
+ 0x3a20: 0x40260a20, 0x3a21: 0x40260b20, 0x3a22: 0x40260c20, 0x3a23: 0x40260d20,
+ 0x3a24: 0x40260e20, 0x3a25: 0x40260f20, 0x3a26: 0x40261020, 0x3a27: 0x40261120,
+ 0x3a28: 0x40261220, 0x3a29: 0x40261320, 0x3a2a: 0x40261420, 0x3a2b: 0x80013002,
+ 0x3a2c: 0x80013102, 0x3a2d: 0x80013202, 0x3a2e: 0x4002be20, 0x3a2f: 0x40018820,
+ 0x3a30: 0x4025d020, 0x3a31: 0x4025d120, 0x3a32: 0x4025d220, 0x3a33: 0x4025d320,
+ 0x3a34: 0x4025d420, 0x3a35: 0x4025d520, 0x3a36: 0x4025d620, 0x3a37: 0x4025d720,
+ 0x3a38: 0x4025d820, 0x3a39: 0x4025d920, 0x3a3a: 0x4025da20, 0x3a3b: 0x4025db20,
+ 0x3a3c: 0x4025dc20, 0x3a3d: 0x4025dd20, 0x3a3e: 0x4025de20, 0x3a3f: 0x4025df20,
+ // Block 0xe9, offset 0x3a40
+ 0x3a40: 0x4025e020, 0x3a41: 0x4025e120, 0x3a42: 0x4025e220, 0x3a43: 0x4025e320,
+ 0x3a44: 0x4025e420, 0x3a45: 0x4025e520, 0x3a46: 0x4025e620, 0x3a47: 0x4025e720,
+ 0x3a48: 0x4025e820, 0x3a49: 0x4025e920, 0x3a4a: 0x4025ea20, 0x3a4b: 0x4025eb20,
+ 0x3a4c: 0x4025ec20, 0x3a4d: 0x4025ed20, 0x3a4e: 0x4025ee20, 0x3a4f: 0x4025ef20,
+ 0x3a50: 0x4025f020, 0x3a51: 0x4025f120, 0x3a52: 0x4025f220, 0x3a53: 0x4025f320,
+ 0x3a5f: 0x4001b420,
+ 0x3a60: 0x40309020, 0x3a61: 0x40309120, 0x3a62: 0x40309220, 0x3a63: 0x40309320,
+ 0x3a64: 0x40309420, 0x3a65: 0x40309520, 0x3a66: 0x40309620, 0x3a67: 0x40309720,
+ 0x3a68: 0x40309820, 0x3a69: 0x40309920, 0x3a6a: 0x40309a20, 0x3a6b: 0x40309b20,
+ 0x3a6c: 0x40309c20, 0x3a6d: 0x40309d20, 0x3a6e: 0x40309e20, 0x3a6f: 0x40309f20,
+ 0x3a70: 0x4030a020, 0x3a71: 0x4030a120, 0x3a72: 0x4030a220, 0x3a73: 0x4030a320,
+ 0x3a74: 0x4030a420, 0x3a75: 0x4030a520, 0x3a76: 0x4030a620, 0x3a77: 0x4030a720,
+ 0x3a78: 0x4030a820, 0x3a79: 0x4030a920, 0x3a7a: 0x4030aa20, 0x3a7b: 0x4030ab20,
+ 0x3a7c: 0x4030ac20,
+ // Block 0xea, offset 0x3a80
+ 0x3a80: 0x80010502, 0x3a81: 0x80010602, 0x3a82: 0x80010702, 0x3a83: 0x80010802,
+ 0x3a84: 0x40283420, 0x3a85: 0x40283520, 0x3a86: 0x40283620, 0x3a87: 0x40283720,
+ 0x3a88: 0x40283820, 0x3a89: 0x40283920, 0x3a8a: 0x40283a20, 0x3a8b: 0x40283b20,
+ 0x3a8c: 0x40283c20, 0x3a8d: 0x40283d20, 0x3a8e: 0x40283e20, 0x3a8f: 0x40283f20,
+ 0x3a90: 0x40284020, 0x3a91: 0x40284120, 0x3a92: 0x40284220, 0x3a93: 0x40284320,
+ 0x3a94: 0x40284420, 0x3a95: 0x40284520, 0x3a96: 0x40284620, 0x3a97: 0x40284720,
+ 0x3a98: 0x40284820, 0x3a99: 0x40284920, 0x3a9a: 0x40284a20, 0x3a9b: 0x40284b20,
+ 0x3a9c: 0x40284c20, 0x3a9d: 0x40284d20, 0x3a9e: 0x40284e20, 0x3a9f: 0x40284f20,
+ 0x3aa0: 0x40285020, 0x3aa1: 0x40285120, 0x3aa2: 0x40285220, 0x3aa3: 0x40285320,
+ 0x3aa4: 0x40285420, 0x3aa5: 0x40285520, 0x3aa6: 0x40285620, 0x3aa7: 0x40285720,
+ 0x3aa8: 0x40285820, 0x3aa9: 0x40285920, 0x3aaa: 0x40285a20, 0x3aab: 0x40285c20,
+ 0x3aac: 0x0050b804, 0x3aad: 0x40285e20, 0x3aae: 0x40285f20, 0x3aaf: 0x40286020,
+ 0x3ab0: 0x40286120, 0x3ab1: 0x40286220, 0x3ab2: 0x40286320, 0x3ab3: 0x80010402,
+ 0x3ab4: 0x40286420, 0x3ab5: 0x40286d20, 0x3ab6: 0x40286620, 0x3ab7: 0x40286720,
+ 0x3ab8: 0x40286820, 0x3ab9: 0x40286920, 0x3aba: 0x40286b20, 0x3abb: 0x40286c20,
+ 0x3abc: 0x40286520, 0x3abd: 0x40286a20, 0x3abe: 0x40285b20, 0x3abf: 0x40285d20,
+ // Block 0xeb, offset 0x3ac0
+ 0x3ac0: 0x40286e20, 0x3ac1: 0x4001a920, 0x3ac2: 0x4001aa20, 0x3ac3: 0x4001ab20,
+ 0x3ac4: 0x4001ac20, 0x3ac5: 0x4001ad20, 0x3ac6: 0x4001ae20, 0x3ac7: 0x40015320,
+ 0x3ac8: 0x40019320, 0x3ac9: 0x40019420, 0x3aca: 0x4001af20, 0x3acb: 0x4001b020,
+ 0x3acc: 0x4001b120, 0x3acd: 0x4001b220, 0x3acf: 0x40139820,
+ 0x3ad0: 0xe0000081, 0x3ad1: 0xe0000105, 0x3ad2: 0xe00001ec, 0x3ad3: 0xe00002b2,
+ 0x3ad4: 0xe000036f, 0x3ad5: 0xe0000429, 0x3ad6: 0xe00004e0, 0x3ad7: 0xe000057c,
+ 0x3ad8: 0xe0000618, 0x3ad9: 0xe00006b1,
+ 0x3ade: 0x4002bf20, 0x3adf: 0x4002c020,
+ // Block 0xec, offset 0x3b00
+ 0x3b00: 0x4027a920, 0x3b01: 0x4027aa20, 0x3b02: 0x4027ab20, 0x3b03: 0x4027ac20,
+ 0x3b04: 0x4027ad20, 0x3b05: 0x4027ae20, 0x3b06: 0x4027af20, 0x3b07: 0x4027b020,
+ 0x3b08: 0x4027b120, 0x3b09: 0x4027b220, 0x3b0a: 0x4027b320, 0x3b0b: 0x4027b420,
+ 0x3b0c: 0x4027b520, 0x3b0d: 0x4027b620, 0x3b0e: 0x4027b720, 0x3b0f: 0x4027b820,
+ 0x3b10: 0x4027b920, 0x3b11: 0x4027ba20, 0x3b12: 0x4027bb20, 0x3b13: 0x4027bc20,
+ 0x3b14: 0x4027bd20, 0x3b15: 0x4027be20, 0x3b16: 0x4027bf20, 0x3b17: 0x4027c020,
+ 0x3b18: 0x4027c120, 0x3b19: 0x4027c220, 0x3b1a: 0x4027c320, 0x3b1b: 0x4027c420,
+ 0x3b1c: 0x4027c520, 0x3b1d: 0x4027c620, 0x3b1e: 0x4027c720, 0x3b1f: 0x4027c820,
+ 0x3b20: 0x4027c920, 0x3b21: 0x4027ca20, 0x3b22: 0x4027cb20, 0x3b23: 0x4027cc20,
+ 0x3b24: 0x4027cd20, 0x3b25: 0x4027ce20, 0x3b26: 0x4027cf20, 0x3b27: 0x4027d020,
+ 0x3b28: 0x4027d120, 0x3b29: 0x4027d620, 0x3b2a: 0x4027d720, 0x3b2b: 0x4027d820,
+ 0x3b2c: 0x4027d920, 0x3b2d: 0x4027da20, 0x3b2e: 0x4027db20, 0x3b2f: 0x4027dc20,
+ 0x3b30: 0x4027dd20, 0x3b31: 0x4027de20, 0x3b32: 0x4027df20, 0x3b33: 0x4027d220,
+ 0x3b34: 0x4027d320, 0x3b35: 0x4027d420, 0x3b36: 0x4027d520,
+ // Block 0xed, offset 0x3b40
+ 0x3b40: 0x4027e020, 0x3b41: 0x4027e120, 0x3b42: 0x4027e220, 0x3b43: 0x4027e320,
+ 0x3b44: 0x4027e420, 0x3b45: 0x4027e520, 0x3b46: 0x4027e620, 0x3b47: 0x4027e720,
+ 0x3b48: 0x4027e820, 0x3b49: 0x4027e920, 0x3b4a: 0x4027ea20, 0x3b4b: 0x4027eb20,
+ 0x3b4c: 0x4027ec20, 0x3b4d: 0x4027ed20,
+ 0x3b50: 0xe000007b, 0x3b51: 0xe00000ff, 0x3b52: 0xe00001e6, 0x3b53: 0xe00002ac,
+ 0x3b54: 0xe0000369, 0x3b55: 0xe0000423, 0x3b56: 0xe00004da, 0x3b57: 0xe0000576,
+ 0x3b58: 0xe0000612, 0x3b59: 0xe00006ab,
+ 0x3b5c: 0x4002c120, 0x3b5d: 0x40019520, 0x3b5e: 0x40019620, 0x3b5f: 0x40019720,
+ 0x3b60: 0x40261b20, 0x3b61: 0x40262120, 0x3b62: 0x40262320, 0x3b63: 0x40262520,
+ 0x3b64: 0x40262a20, 0x3b65: 0x40262e20, 0x3b66: 0x40263120, 0x3b67: 0x40263320,
+ 0x3b68: 0x40263520, 0x3b69: 0x40263720, 0x3b6a: 0x40263f20, 0x3b6b: 0x40264220,
+ 0x3b6c: 0x40265f20, 0x3b6d: 0x40266220, 0x3b6e: 0x40266420, 0x3b6f: 0x40264820,
+ 0x3b70: 0x40139920, 0x3b71: 0x40266520, 0x3b72: 0x40262720, 0x3b73: 0x40265220,
+ 0x3b74: 0x4026a820, 0x3b75: 0x4026a920, 0x3b76: 0x4026aa20, 0x3b77: 0x40031c20,
+ 0x3b78: 0x40031d20, 0x3b79: 0x40031e20, 0x3b7a: 0x40265320, 0x3b7b: 0x4026a720,
+ // Block 0xee, offset 0x3b80
+ 0x3b80: 0x40240320, 0x3b81: 0x40240420, 0x3b82: 0x40240520, 0x3b83: 0x40240620,
+ 0x3b84: 0x40240720, 0x3b85: 0x40240820, 0x3b86: 0x40240920, 0x3b87: 0x40240a20,
+ 0x3b88: 0x40240b20, 0x3b89: 0x40240c20, 0x3b8a: 0x40240d20, 0x3b8b: 0x40240e20,
+ 0x3b8c: 0x40240f20, 0x3b8d: 0x40241020, 0x3b8e: 0x40241120, 0x3b8f: 0x40241220,
+ 0x3b90: 0x40241320, 0x3b91: 0x40241420, 0x3b92: 0x40241520, 0x3b93: 0x40241620,
+ 0x3b94: 0x40241720, 0x3b95: 0x40241820, 0x3b96: 0x40241920, 0x3b97: 0x40241a20,
+ 0x3b98: 0x40241b20, 0x3b99: 0x40241c20, 0x3b9a: 0x40241d20, 0x3b9b: 0x40241e20,
+ 0x3b9c: 0x40241f20, 0x3b9d: 0x40242020, 0x3b9e: 0x40242120, 0x3b9f: 0x40242220,
+ 0x3ba0: 0x40242320, 0x3ba1: 0x40242420, 0x3ba2: 0x40242520, 0x3ba3: 0x40242620,
+ 0x3ba4: 0x40242720, 0x3ba5: 0x40242820, 0x3ba6: 0x40242920, 0x3ba7: 0x40242a20,
+ 0x3ba8: 0x40242b20, 0x3ba9: 0x40242c20, 0x3baa: 0x40242d20, 0x3bab: 0x40242e20,
+ 0x3bac: 0x40242f20, 0x3bad: 0x40243020, 0x3bae: 0x40243120, 0x3baf: 0x40243220,
+ 0x3bb0: 0x40243320, 0x3bb1: 0x40243420, 0x3bb2: 0x40243520, 0x3bb3: 0x40243620,
+ 0x3bb4: 0x40243720, 0x3bb5: 0xc2040671, 0x3bb6: 0xc2350671, 0x3bb7: 0x40243a20,
+ 0x3bb8: 0x40243b20, 0x3bb9: 0xc2660671, 0x3bba: 0x40243d20, 0x3bbb: 0xc2970671,
+ 0x3bbc: 0xc2c80671, 0x3bbd: 0x40244020, 0x3bbe: 0x40244120, 0x3bbf: 0x80012a02,
+ // Block 0xef, offset 0x3bc0
+ 0x3bc0: 0x40244220, 0x3bc1: 0x80012b02, 0x3bc2: 0x40244320,
+ 0x3bdb: 0x40244420,
+ 0x3bdc: 0x40244520, 0x3bdd: 0x40139a20, 0x3bde: 0x40028b20, 0x3bdf: 0x40028c20,
+ // Block 0xf0, offset 0x3c00
+ 0x3c01: 0x401df620, 0x3c02: 0x401df720, 0x3c03: 0x401df820,
+ 0x3c04: 0x401df920, 0x3c05: 0x401dfa20, 0x3c06: 0x401dfb20,
+ 0x3c09: 0x401ebd20, 0x3c0a: 0x401ebe20, 0x3c0b: 0x401ebf20,
+ 0x3c0c: 0x401ec020, 0x3c0d: 0x401ec120, 0x3c0e: 0x401ec220,
+ 0x3c11: 0x401e9e20, 0x3c12: 0x401e9f20, 0x3c13: 0x401ea020,
+ 0x3c14: 0x401ea120, 0x3c15: 0x401ea220, 0x3c16: 0x401ea320,
+ 0x3c20: 0x401f0020, 0x3c21: 0x401f0120, 0x3c22: 0x401f0220, 0x3c23: 0x401f0320,
+ 0x3c24: 0x401f0420, 0x3c25: 0x401f0520, 0x3c26: 0x401f0620,
+ 0x3c28: 0x401f1820, 0x3c29: 0x401f1920, 0x3c2a: 0x401f1a20, 0x3c2b: 0x401f1b20,
+ 0x3c2c: 0x401f1c20, 0x3c2d: 0x401f1d20, 0x3c2e: 0x401f1e20,
+ // Block 0xf1, offset 0x3c40
+ 0x3c40: 0x40223320, 0x3c41: 0x40223420, 0x3c42: 0x40223520, 0x3c43: 0x40223620,
+ 0x3c44: 0x40223720, 0x3c45: 0x40223820, 0x3c46: 0x40223920, 0x3c47: 0x40223a20,
+ 0x3c48: 0x40223b20, 0x3c49: 0x40223c20, 0x3c4a: 0x40223d20, 0x3c4b: 0x40223e20,
+ 0x3c4c: 0x40223f20, 0x3c4d: 0x40224020, 0x3c4e: 0x40224120, 0x3c4f: 0x40224220,
+ 0x3c50: 0x40224320, 0x3c51: 0x40224420, 0x3c52: 0x40224520, 0x3c53: 0x40224620,
+ 0x3c54: 0x40224720, 0x3c55: 0x40224820, 0x3c56: 0x40224920, 0x3c57: 0x40224a20,
+ 0x3c58: 0x40224b20, 0x3c59: 0x40224c20, 0x3c5a: 0x40224d20, 0x3c5b: 0x40225620,
+ 0x3c5c: 0x40225720, 0x3c5d: 0x40225820, 0x3c5e: 0x40225920, 0x3c5f: 0x40225a20,
+ 0x3c60: 0x40225b20, 0x3c61: 0x40225c20, 0x3c62: 0x40225d20, 0x3c63: 0x40224e20,
+ 0x3c64: 0x40224f20, 0x3c65: 0x40225020, 0x3c66: 0x40225120, 0x3c67: 0x40225220,
+ 0x3c68: 0x40225320, 0x3c69: 0x40225420, 0x3c6a: 0x40225520, 0x3c6b: 0x40019820,
+ 0x3c6c: 0x80010c02, 0x3c6d: 0x40225e20,
+ 0x3c70: 0xe000004b, 0x3c71: 0xe00000cc, 0x3c72: 0xe00001b6, 0x3c73: 0xe000027c,
+ 0x3c74: 0xe0000339, 0x3c75: 0xe00003f3, 0x3c76: 0xe00004aa, 0x3c77: 0xe0000546,
+ 0x3c78: 0xe00005e2, 0x3c79: 0xe000067b,
+ // Block 0xf2, offset 0x3c80
+ 0x3cb0: 0x4030f620, 0x3cb1: 0x4030f720, 0x3cb2: 0x4030f820, 0x3cb3: 0x4030f920,
+ 0x3cb4: 0x4030fa20, 0x3cb5: 0x4030fb20, 0x3cb6: 0x4030fc20, 0x3cb7: 0x4030fd20,
+ 0x3cb8: 0x4030fe20, 0x3cb9: 0x4030ff20, 0x3cba: 0x40310020, 0x3cbb: 0x40310120,
+ 0x3cbc: 0x40310220, 0x3cbd: 0x40310320, 0x3cbe: 0x40310420, 0x3cbf: 0x40310520,
+ // Block 0xf3, offset 0x3cc0
+ 0x3cc0: 0x40310620, 0x3cc1: 0x40310720, 0x3cc2: 0x40310820, 0x3cc3: 0x40310920,
+ 0x3cc4: 0x40310a20, 0x3cc5: 0x40310b20, 0x3cc6: 0x40310c20,
+ 0x3ccb: 0x40316520,
+ 0x3ccc: 0x40316620, 0x3ccd: 0x40316720, 0x3cce: 0x40316820, 0x3ccf: 0x40316920,
+ 0x3cd0: 0x40316a20, 0x3cd1: 0x40316b20, 0x3cd2: 0x40316c20, 0x3cd3: 0x40316d20,
+ 0x3cd4: 0x40316e20, 0x3cd5: 0x40316f20, 0x3cd6: 0x40317020, 0x3cd7: 0x40317120,
+ 0x3cd8: 0x40317220, 0x3cd9: 0x40317320, 0x3cda: 0x40317420, 0x3cdb: 0x40317520,
+ 0x3cdc: 0x40317620, 0x3cdd: 0x40317720, 0x3cde: 0x40317820, 0x3cdf: 0x40317920,
+ 0x3ce0: 0x40317a20, 0x3ce1: 0x40317b20, 0x3ce2: 0x40317c20, 0x3ce3: 0x40317d20,
+ 0x3ce4: 0x40317e20, 0x3ce5: 0x40317f20, 0x3ce6: 0x40318020, 0x3ce7: 0x40318120,
+ 0x3ce8: 0x40318220, 0x3ce9: 0x40318320, 0x3cea: 0x40318420, 0x3ceb: 0x40318520,
+ 0x3cec: 0x40318620, 0x3ced: 0x40318720, 0x3cee: 0x40318820, 0x3cef: 0x40318920,
+ 0x3cf0: 0x40318a20, 0x3cf1: 0x40318b20, 0x3cf2: 0x40318c20, 0x3cf3: 0x40318d20,
+ 0x3cf4: 0x40318e20, 0x3cf5: 0x40318f20, 0x3cf6: 0x40319020, 0x3cf7: 0x40319120,
+ 0x3cf8: 0x40319220, 0x3cf9: 0x40319320, 0x3cfa: 0x40319420, 0x3cfb: 0x40319520,
+ // Block 0xf4, offset 0x3d00
+ 0x3d0e: 0x41fa0e20, 0x3d0f: 0x41fa0f20,
+ 0x3d11: 0x41fa1120, 0x3d13: 0x41fa1320,
+ 0x3d14: 0x41fa1420,
+ 0x3d1f: 0x41fa1f20,
+ 0x3d21: 0x41fa2120, 0x3d23: 0x41fa2320,
+ 0x3d24: 0x41fa2420, 0x3d27: 0x41fa2720,
+ 0x3d28: 0x41fa2820, 0x3d29: 0x41fa2920,
+ // Block 0xf5, offset 0x3d40
+ 0x3d40: 0xf0000404, 0x3d41: 0xf0000404, 0x3d42: 0xf0000404, 0x3d43: 0xf0000404,
+ 0x3d44: 0xf0000404, 0x3d45: 0xe00007f8, 0x3d46: 0xf0000404,
+ 0x3d53: 0xf0000404,
+ 0x3d54: 0xf0000404, 0x3d55: 0xf0000404, 0x3d56: 0xf0000404, 0x3d57: 0xf0000404,
+ 0x3d5e: 0x80009602,
+ 0x3d60: 0xf0000005, 0x3d61: 0xf0000005, 0x3d62: 0xf0000005, 0x3d63: 0xf0000005,
+ 0x3d64: 0xf0000005, 0x3d65: 0xf0000005, 0x3d66: 0xf0000005, 0x3d67: 0xf0000005,
+ 0x3d68: 0xf0000005, 0x3d69: 0xf0000005,
+ // Block 0xf6, offset 0x3d80
+ 0x3d8f: 0xf0000404,
+ 0x3d90: 0xf000001a, 0x3d91: 0xf0000019, 0x3d92: 0xf000001a, 0x3d93: 0xf0000019,
+ 0x3d94: 0xf0000017, 0x3d95: 0xf0000018, 0x3d96: 0xf000001a, 0x3d97: 0xf0000019,
+ 0x3d98: 0xf0000017, 0x3d99: 0xf0000018, 0x3d9a: 0xf000001a, 0x3d9b: 0xf0000019,
+ 0x3d9c: 0xf0000017, 0x3d9d: 0xf0000018, 0x3d9e: 0xf000001a, 0x3d9f: 0xf0000019,
+ 0x3da0: 0xf0000017, 0x3da1: 0xf0000018, 0x3da2: 0xf000001a, 0x3da3: 0xf0000019,
+ 0x3da4: 0xf0000017, 0x3da5: 0xf0000018, 0x3da6: 0xf000001a, 0x3da7: 0xf0000019,
+ 0x3da8: 0xf0000017, 0x3da9: 0xf0000018, 0x3daa: 0xf000001a, 0x3dab: 0xf0000019,
+ 0x3dac: 0xf0000017, 0x3dad: 0xf0000018, 0x3dae: 0xf000001a, 0x3daf: 0xf0000019,
+ 0x3db0: 0xf0000017, 0x3db1: 0xf0000018, 0x3db2: 0xf000001a, 0x3db3: 0xf0000019,
+ 0x3db4: 0xf0000017, 0x3db5: 0xf0000018, 0x3db6: 0xf000001a, 0x3db7: 0xf0000019,
+ 0x3db8: 0xf0000017, 0x3db9: 0xf0000018, 0x3dba: 0xf000001a, 0x3dbb: 0xf0000019,
+ 0x3dbc: 0xf0000017, 0x3dbd: 0xf0000018, 0x3dbe: 0xf000001a, 0x3dbf: 0xf0000019,
+ // Block 0xf7, offset 0x3dc0
+ 0x3dc0: 0xf0000017, 0x3dc1: 0xf0000018, 0x3dc2: 0xf000001a, 0x3dc3: 0xf0000019,
+ 0x3dc4: 0xf000001a, 0x3dc5: 0xf0000019, 0x3dc6: 0xf000001a, 0x3dc7: 0xf0000019,
+ 0x3dc8: 0xf000001a, 0x3dc9: 0xf0000019, 0x3dca: 0xf000001a, 0x3dcb: 0xf0000019,
+ 0x3dcc: 0xf000001a, 0x3dcd: 0xf0000019, 0x3dce: 0xf000001a, 0x3dcf: 0xf0000019,
+ 0x3dd0: 0xf0000017, 0x3dd1: 0xf0000018, 0x3dd2: 0xf000001a, 0x3dd3: 0xf0000019,
+ 0x3dd4: 0xf0000017, 0x3dd5: 0xf0000018, 0x3dd6: 0xf000001a, 0x3dd7: 0xf0000019,
+ 0x3dd8: 0xf0000017, 0x3dd9: 0xf0000018, 0x3dda: 0xf000001a, 0x3ddb: 0xf0000019,
+ 0x3ddc: 0xf0000017, 0x3ddd: 0xf0000018, 0x3dde: 0xf000001a, 0x3ddf: 0xf0000019,
+ 0x3de0: 0xf000001a, 0x3de1: 0xf0000019, 0x3de2: 0xf0000017, 0x3de3: 0xf0000018,
+ 0x3de4: 0xf0001a1a, 0x3de5: 0xf0001919, 0x3de6: 0xf000001a, 0x3de7: 0xf0000019,
+ 0x3de8: 0xf0000017, 0x3de9: 0xf0000018, 0x3dea: 0xf000001a, 0x3deb: 0xf0000019,
+ 0x3dec: 0xf0000017, 0x3ded: 0xf0000018, 0x3dee: 0xf000001a, 0x3def: 0xf0000019,
+ 0x3df0: 0xf0001a1a, 0x3df1: 0xf0001919, 0x3df2: 0x4002fd20, 0x3df3: 0x4002fe20,
+ 0x3df4: 0x4002ff20, 0x3df5: 0x40030020, 0x3df6: 0x40030120, 0x3df7: 0x40030220,
+ 0x3df8: 0x40030320, 0x3df9: 0x40030420, 0x3dfa: 0x40030520, 0x3dfb: 0x40030620,
+ 0x3dfc: 0x40030720, 0x3dfd: 0x40030820, 0x3dfe: 0x40030920, 0x3dff: 0x40030a20,
+ // Block 0xf8, offset 0x3e00
+ 0x3e00: 0x40030b20, 0x3e01: 0x40030c20,
+ 0x3e13: 0xf000001a,
+ 0x3e14: 0xf0000019, 0x3e15: 0xf0000017, 0x3e16: 0xf0000018, 0x3e17: 0xf000001a,
+ 0x3e18: 0xf0000019, 0x3e19: 0xf000001a, 0x3e1a: 0xf0000019, 0x3e1b: 0xf000001a,
+ 0x3e1c: 0xf0000019, 0x3e1d: 0xf0001a1a, 0x3e1e: 0xf000001a, 0x3e1f: 0xf0000019,
+ 0x3e20: 0xf000001a, 0x3e21: 0xf0000019, 0x3e22: 0xf000001a, 0x3e23: 0xf0000019,
+ 0x3e24: 0xf000001a, 0x3e25: 0xf0000019, 0x3e26: 0xf0000017, 0x3e27: 0xf0000018,
+ 0x3e28: 0xf0000017, 0x3e29: 0xf0000018, 0x3e2a: 0xe000084f, 0x3e2b: 0xe000084c,
+ 0x3e2c: 0xe000087f, 0x3e2d: 0xe000087c, 0x3e2e: 0xe0000885, 0x3e2f: 0xe0000882,
+ 0x3e30: 0xe0000891, 0x3e31: 0xe000088e, 0x3e32: 0xe000088b, 0x3e33: 0xe0000888,
+ 0x3e34: 0xe0000897, 0x3e35: 0xe0000894, 0x3e36: 0xe00008b5, 0x3e37: 0xe00008b2,
+ 0x3e38: 0xe00008af, 0x3e39: 0xe00008a3, 0x3e3a: 0xe000089d, 0x3e3b: 0xe000089a,
+ 0x3e3c: 0xf000001a, 0x3e3d: 0xf0000019, 0x3e3e: 0xf0000017, 0x3e3f: 0xf0000018,
+ // Block 0xf9, offset 0x3e40
+ 0x3e40: 0xe0000855, 0x3e41: 0xe000085b, 0x3e42: 0xe0000870, 0x3e43: 0xe00008a6,
+ 0x3e44: 0xe00008ac, 0x3e45: 0xf0001a1a, 0x3e46: 0xf0001a1a, 0x3e47: 0xf0001a1a,
+ 0x3e48: 0xf0001a1a, 0x3e49: 0xf0001a1a, 0x3e4a: 0xf0001a1a, 0x3e4b: 0xf0001a1a,
+ 0x3e4c: 0xf0001a1a, 0x3e4d: 0xf0001a1a, 0x3e4e: 0xf0001a1a, 0x3e4f: 0xf0001a1a,
+ 0x3e50: 0xf0001a1a, 0x3e51: 0xf0001a1a, 0x3e52: 0xf0001a1a, 0x3e53: 0xf0001a1a,
+ 0x3e54: 0xf0001a1a, 0x3e55: 0xf0001a1a, 0x3e56: 0xf0001a1a, 0x3e57: 0xf0001a1a,
+ 0x3e58: 0xf0001a1a, 0x3e59: 0xf0001a1a, 0x3e5a: 0xf0001a1a, 0x3e5b: 0xf0001a1a,
+ 0x3e5c: 0xf0001a1a, 0x3e5d: 0xf0001a1a, 0x3e5e: 0xf0001a1a, 0x3e5f: 0xf0001a1a,
+ 0x3e60: 0xf0001a1a, 0x3e61: 0xf0001a1a, 0x3e62: 0xf0001a1a, 0x3e63: 0xf0001a1a,
+ 0x3e64: 0xf0001a1a, 0x3e65: 0xf0001a1a, 0x3e66: 0xf0001a1a, 0x3e67: 0xf0001a1a,
+ 0x3e68: 0xf0001a1a, 0x3e69: 0xf0001a1a, 0x3e6a: 0xf0001a1a, 0x3e6b: 0xf0001a1a,
+ 0x3e6c: 0xf0001a1a, 0x3e6d: 0xf0001a1a, 0x3e6e: 0xf0001a1a, 0x3e6f: 0xf0001a1a,
+ 0x3e70: 0xf0001a1a, 0x3e71: 0xf0001a1a, 0x3e72: 0xf0001a1a, 0x3e73: 0xf0001a1a,
+ 0x3e74: 0xf0001a1a, 0x3e75: 0xf0001a1a, 0x3e76: 0xf0001a1a, 0x3e77: 0xf0001a1a,
+ 0x3e78: 0xf0001a1a, 0x3e79: 0xf0001a1a, 0x3e7a: 0xf0001a1a, 0x3e7b: 0xf0001a1a,
+ 0x3e7c: 0xf0001a1a, 0x3e7d: 0xf0001a1a, 0x3e7e: 0xf0001a1a, 0x3e7f: 0xf0001a1a,
+ // Block 0xfa, offset 0x3e80
+ 0x3e80: 0xf0001a1a, 0x3e81: 0xf0001a1a, 0x3e82: 0xf0001a1a, 0x3e83: 0xf0001a1a,
+ 0x3e84: 0xf0001a1a, 0x3e85: 0xf0001a1a, 0x3e86: 0xf0001a1a, 0x3e87: 0xf0001a1a,
+ 0x3e88: 0xf0001a1a, 0x3e89: 0xf0001a1a, 0x3e8a: 0xf0001a1a, 0x3e8b: 0xf0001a1a,
+ 0x3e8c: 0xf0001a1a, 0x3e8d: 0xf0001a1a, 0x3e8e: 0xf0001a1a, 0x3e8f: 0xf0001a1a,
+ 0x3e90: 0xf0001a1a, 0x3e91: 0xf0001a1a, 0x3e92: 0xf0001a1a, 0x3e93: 0xf0001a1a,
+ 0x3e94: 0xf0001a1a, 0x3e95: 0xf0001a1a, 0x3e96: 0xf0001a1a, 0x3e97: 0xf0001a1a,
+ 0x3e98: 0xf0001a1a, 0x3e99: 0xf0001a1a, 0x3e9a: 0xf0001a1a, 0x3e9b: 0xf0001a1a,
+ 0x3e9c: 0xf0001a1a, 0x3e9d: 0xf0001a1a, 0x3e9e: 0xe0000000, 0x3e9f: 0xe0000003,
+ 0x3ea0: 0xe0000009, 0x3ea1: 0xe000000f, 0x3ea2: 0xe0000015, 0x3ea3: 0xe0000018,
+ 0x3ea4: 0xe0000861, 0x3ea5: 0xe0000864, 0x3ea6: 0xe000086d, 0x3ea7: 0xe0000873,
+ 0x3ea8: 0xe00008a0, 0x3ea9: 0xe00008a9, 0x3eaa: 0xf0001919, 0x3eab: 0xf0001919,
+ 0x3eac: 0xf0001919, 0x3ead: 0xf0001919, 0x3eae: 0xf0001919, 0x3eaf: 0xf0001919,
+ 0x3eb0: 0xf0001919, 0x3eb1: 0xf0001919, 0x3eb2: 0xf0001919, 0x3eb3: 0xf0001919,
+ 0x3eb4: 0xf0001919, 0x3eb5: 0xf0001919, 0x3eb6: 0xf0001919, 0x3eb7: 0xf0001919,
+ 0x3eb8: 0xf0001919, 0x3eb9: 0xf0001919, 0x3eba: 0xf0001919, 0x3ebb: 0xf0001919,
+ 0x3ebc: 0xf0001919, 0x3ebd: 0xf0001919, 0x3ebe: 0xf0001919, 0x3ebf: 0xf0001919,
+ // Block 0xfb, offset 0x3ec0
+ 0x3ec0: 0xf0001919, 0x3ec1: 0xf0001919, 0x3ec2: 0xf0001919, 0x3ec3: 0xf0001919,
+ 0x3ec4: 0xf0001919, 0x3ec5: 0xf0001919, 0x3ec6: 0xf0001919, 0x3ec7: 0xf0001919,
+ 0x3ec8: 0xf0001919, 0x3ec9: 0xf0001919, 0x3eca: 0xf0001919, 0x3ecb: 0xf0001919,
+ 0x3ecc: 0xf0001919, 0x3ecd: 0xf0001919, 0x3ece: 0xf0001919, 0x3ecf: 0xf0001919,
+ 0x3ed0: 0xf0001919, 0x3ed1: 0xf0001919, 0x3ed2: 0xf0001919, 0x3ed3: 0xf0001919,
+ 0x3ed4: 0xf0001919, 0x3ed5: 0xf0001919, 0x3ed6: 0xf0001919, 0x3ed7: 0xe0000852,
+ 0x3ed8: 0xe0000858, 0x3ed9: 0xe000085e, 0x3eda: 0xe0000867, 0x3edb: 0xe0000876,
+ 0x3edc: 0xf0001717, 0x3edd: 0xf0001717, 0x3ede: 0xf0001717, 0x3edf: 0xf0001717,
+ 0x3ee0: 0xf0001717, 0x3ee1: 0xf0001717, 0x3ee2: 0xf0001717, 0x3ee3: 0xf0001717,
+ 0x3ee4: 0xf0001717, 0x3ee5: 0xf0001717, 0x3ee6: 0xf0001717, 0x3ee7: 0xf0001717,
+ 0x3ee8: 0xf0001717, 0x3ee9: 0xf0001717, 0x3eea: 0xf0001717, 0x3eeb: 0xf0001717,
+ 0x3eec: 0xf0001717, 0x3eed: 0xf0001717, 0x3eee: 0xf0001717, 0x3eef: 0xf0001717,
+ 0x3ef0: 0xf0001717, 0x3ef1: 0xf0001717, 0x3ef2: 0xf0001717, 0x3ef3: 0xf0001717,
+ 0x3ef4: 0xf0001717, 0x3ef5: 0xf0001717, 0x3ef6: 0xf0001717, 0x3ef7: 0xf0001717,
+ 0x3ef8: 0xf0001717, 0x3ef9: 0xf0001717, 0x3efa: 0xf0001717, 0x3efb: 0xf0001717,
+ 0x3efc: 0xf0001717, 0x3efd: 0xf0001717, 0x3efe: 0xf0001717, 0x3eff: 0xf0001717,
+ // Block 0xfc, offset 0x3f00
+ 0x3f00: 0xf0001717, 0x3f01: 0xf0001717, 0x3f02: 0xf0001717, 0x3f03: 0xf0001717,
+ 0x3f04: 0xf0001717, 0x3f05: 0xf0001717, 0x3f06: 0xf0001717, 0x3f07: 0xf0001717,
+ 0x3f08: 0xf0001717, 0x3f09: 0xf0001717, 0x3f0a: 0xf0001717, 0x3f0b: 0xf0001717,
+ 0x3f0c: 0xf0001717, 0x3f0d: 0xf0001717, 0x3f0e: 0xf0001717, 0x3f0f: 0xf0001717,
+ 0x3f10: 0xf0001717, 0x3f11: 0xf0001717, 0x3f12: 0xf0001717, 0x3f13: 0xf0001717,
+ 0x3f14: 0xf0001717, 0x3f15: 0xf0001717, 0x3f16: 0xf0001717, 0x3f17: 0xf0001717,
+ 0x3f18: 0xf0001717, 0x3f19: 0xf0001717, 0x3f1a: 0xf0001717, 0x3f1b: 0xf0001717,
+ 0x3f1c: 0xf0001717, 0x3f1d: 0xf0001717, 0x3f1e: 0xf0001717, 0x3f1f: 0xe000086a,
+ 0x3f20: 0xe0000879, 0x3f21: 0xf0001818, 0x3f22: 0xf0001818, 0x3f23: 0xf0001818,
+ 0x3f24: 0xf0001818, 0x3f25: 0xf0001818, 0x3f26: 0xf0001818, 0x3f27: 0xf0001818,
+ 0x3f28: 0xf0001818, 0x3f29: 0xf0001818, 0x3f2a: 0xf0001818, 0x3f2b: 0xf0001818,
+ 0x3f2c: 0xf0001818, 0x3f2d: 0xf0001818, 0x3f2e: 0xf0001818, 0x3f2f: 0xf0001818,
+ 0x3f30: 0xf0001818, 0x3f31: 0xf0001818, 0x3f32: 0xe0000006, 0x3f33: 0xe000000c,
+ 0x3f34: 0xe0000012, 0x3f35: 0xf0001a1a, 0x3f36: 0xf0001a1a, 0x3f37: 0xf0001a1a,
+ 0x3f38: 0xf0001a1a, 0x3f39: 0xf0001a1a, 0x3f3a: 0xf0001a1a, 0x3f3b: 0xf0001a1a,
+ 0x3f3c: 0xf0001a1a, 0x3f3d: 0xf0001a1a, 0x3f3e: 0xf0001a1a, 0x3f3f: 0xf0001a1a,
+ // Block 0xfd, offset 0x3f40
+ 0x3f40: 0xf0001a1a, 0x3f41: 0xf0001a1a, 0x3f42: 0xf0001a1a, 0x3f43: 0xf0001a1a,
+ 0x3f44: 0xf0001a1a, 0x3f45: 0xf0001a1a, 0x3f46: 0xf0001a1a, 0x3f47: 0xf0001a1a,
+ 0x3f48: 0xf0001a1a, 0x3f49: 0xf0001a1a, 0x3f4a: 0xf0001a1a, 0x3f4b: 0xf0001a1a,
+ 0x3f4c: 0xf0001a1a, 0x3f4d: 0xf0001a1a, 0x3f4e: 0xf0001a1a, 0x3f4f: 0xf0001a1a,
+ 0x3f50: 0xf0001a1a, 0x3f51: 0xf0001919, 0x3f52: 0xf0001919, 0x3f53: 0xf0001919,
+ 0x3f54: 0xf0001919, 0x3f55: 0xf0001919, 0x3f56: 0xf0001919, 0x3f57: 0xf0001919,
+ 0x3f58: 0xf0001919, 0x3f59: 0xf0001919, 0x3f5a: 0xf0001919, 0x3f5b: 0xf0001919,
+ 0x3f5c: 0xf0001919, 0x3f5d: 0xf0001919, 0x3f5e: 0xf0001919, 0x3f5f: 0xf0001919,
+ 0x3f60: 0xf0001919, 0x3f61: 0xf0001919, 0x3f62: 0xf0001919, 0x3f63: 0xf0001919,
+ 0x3f64: 0xf0001919, 0x3f65: 0xf0001919, 0x3f66: 0xf0001919, 0x3f67: 0xf0001919,
+ 0x3f68: 0xf0001919, 0x3f69: 0xf0001919, 0x3f6a: 0xf0001919, 0x3f6b: 0xf0001919,
+ 0x3f6c: 0xf0001919, 0x3f6d: 0xf0001717, 0x3f6e: 0xf0001717, 0x3f6f: 0xf0001717,
+ 0x3f70: 0xf0001717, 0x3f71: 0xf0001717, 0x3f72: 0xf0001717, 0x3f73: 0xf0001717,
+ 0x3f74: 0xf0001818, 0x3f75: 0xf0001818, 0x3f76: 0xf0001818, 0x3f77: 0xf0001818,
+ 0x3f78: 0xf0001818, 0x3f79: 0xf0001818, 0x3f7a: 0xf0001818, 0x3f7b: 0xf0001818,
+ 0x3f7c: 0xf0001919, 0x3f7d: 0xf0001a1a, 0x3f7e: 0x40023920, 0x3f7f: 0x40023a20,
+ // Block 0xfe, offset 0x3f80
+ 0x3f90: 0xf0001717, 0x3f91: 0xf0001919, 0x3f92: 0xf0001717, 0x3f93: 0xf0001717,
+ 0x3f94: 0xf0001717, 0x3f95: 0xf0001717, 0x3f96: 0xf0001717, 0x3f97: 0xf0001717,
+ 0x3f98: 0xf0001919, 0x3f99: 0xf0001717, 0x3f9a: 0xf0001919, 0x3f9b: 0xf0001919,
+ 0x3f9c: 0xf0001717, 0x3f9d: 0xf0001717, 0x3f9e: 0xf0001919, 0x3f9f: 0xf0001919,
+ 0x3fa0: 0xf0001717, 0x3fa1: 0xf0001717, 0x3fa2: 0xf0001919, 0x3fa3: 0xf0001717,
+ 0x3fa4: 0xf0001919, 0x3fa5: 0xf0001717, 0x3fa6: 0xf0001919, 0x3fa7: 0xf0001919,
+ 0x3fa8: 0xf0001717, 0x3fa9: 0xf0001919, 0x3faa: 0xf0001919, 0x3fab: 0xf0001717,
+ 0x3fac: 0xf0001919, 0x3fad: 0xf0001717, 0x3fae: 0xf0001919, 0x3faf: 0xf0001919,
+ 0x3fb0: 0xf0001717, 0x3fb1: 0xf0001919, 0x3fb2: 0xf0001717, 0x3fb3: 0xf0001717,
+ 0x3fb4: 0xf0001919, 0x3fb5: 0xf0001919, 0x3fb6: 0xf0001919, 0x3fb7: 0xf0001717,
+ 0x3fb8: 0xf0001919, 0x3fb9: 0xf0001919, 0x3fba: 0xf0001919, 0x3fbb: 0xf0001919,
+ 0x3fbc: 0xf0001919, 0x3fbd: 0xf0001717, 0x3fbe: 0xf0001919, 0x3fbf: 0xf0001919,
+ // Block 0xff, offset 0x3fc0
+ 0x3fc0: 0xf0001919, 0x3fc1: 0xf0001919, 0x3fc2: 0xf0001919, 0x3fc3: 0xf0001717,
+ 0x3fc4: 0xf0001919, 0x3fc5: 0xf0001919, 0x3fc6: 0xf0001717, 0x3fc7: 0xf0001919,
+ 0x3fc8: 0xf0001717, 0x3fc9: 0xf0001717, 0x3fca: 0xf0001717, 0x3fcb: 0xf0001919,
+ 0x3fcc: 0xf0001717, 0x3fcd: 0xf0001717, 0x3fce: 0xf0001717, 0x3fcf: 0xf0001717,
+ 0x3fd2: 0xf0001717, 0x3fd3: 0xf0001717,
+ 0x3fd4: 0xf0001717, 0x3fd5: 0xf0001717, 0x3fd6: 0xf0001919, 0x3fd7: 0xf0001919,
+ 0x3fd8: 0xf0001717, 0x3fd9: 0xf0001919, 0x3fda: 0xf0001919, 0x3fdb: 0xf0001919,
+ 0x3fdc: 0xf0001919, 0x3fdd: 0xf0001717, 0x3fde: 0xf0001919, 0x3fdf: 0xf0001919,
+ 0x3fe0: 0xf0001919, 0x3fe1: 0xf0001919, 0x3fe2: 0xf0001919, 0x3fe3: 0xf0001919,
+ 0x3fe4: 0xf0001919, 0x3fe5: 0xf0001919, 0x3fe6: 0xf0001919, 0x3fe7: 0xf0001919,
+ 0x3fe8: 0xf0001919, 0x3fe9: 0xf0001919, 0x3fea: 0xf0001919, 0x3feb: 0xf0001919,
+ 0x3fec: 0xf0001919, 0x3fed: 0xf0001919, 0x3fee: 0xf0001919, 0x3fef: 0xf0001919,
+ 0x3ff0: 0xf0001919, 0x3ff1: 0xf0001919, 0x3ff2: 0xf0001919, 0x3ff3: 0xf0001919,
+ 0x3ff4: 0xf0001717, 0x3ff5: 0xf0001717, 0x3ff6: 0xf0001919, 0x3ff7: 0xf0001919,
+ 0x3ff8: 0xf0001717, 0x3ff9: 0xf0001919, 0x3ffa: 0xf0001717, 0x3ffb: 0xf0001919,
+ 0x3ffc: 0xf0001919, 0x3ffd: 0xf0001919, 0x3ffe: 0xf0001919, 0x3fff: 0xf0001919,
+ // Block 0x100, offset 0x4000
+ 0x4000: 0xf0001919, 0x4001: 0xf0001919, 0x4002: 0xf0001919, 0x4003: 0xf0001717,
+ 0x4004: 0xf0001717, 0x4005: 0xf0001717, 0x4006: 0xf0001919, 0x4007: 0xf0001919,
+ 0x4030: 0xf0001a1a, 0x4031: 0xf0001a1a, 0x4032: 0xf0001a1a, 0x4033: 0xf0001a1a,
+ 0x4034: 0xf0001a1a, 0x4035: 0xf0001a1a, 0x4036: 0xf0001a1a, 0x4037: 0xf0001a1a,
+ 0x4038: 0xf0001a1a, 0x4039: 0xf0001a1a, 0x403a: 0xf0001a1a, 0x403b: 0xf0001a1a,
+ 0x403c: 0x4013cb20, 0x403d: 0x40038920,
+ // Block 0x101, offset 0x4040
+ 0x4040: 0x80000000, 0x4041: 0x80000000, 0x4042: 0x80000000, 0x4043: 0x80000000,
+ 0x4044: 0x80000000, 0x4045: 0x80000000, 0x4046: 0x80000000, 0x4047: 0x80000000,
+ 0x4048: 0x80000000, 0x4049: 0x80000000, 0x404a: 0x80000000, 0x404b: 0x80000000,
+ 0x404c: 0x80000000, 0x404d: 0x80000000, 0x404e: 0x80000000, 0x404f: 0x80000000,
+ 0x4050: 0xf0000016, 0x4051: 0xf0000016, 0x4052: 0xf0000016, 0x4053: 0xf0000016,
+ 0x4054: 0xf0000016, 0x4055: 0xf0000016, 0x4056: 0xf0000016, 0x4057: 0xf0000016,
+ 0x4058: 0xf0000016, 0x4059: 0xf0001616,
+ 0x4060: 0x80008202, 0x4061: 0x80000000, 0x4062: 0x80008102, 0x4063: 0x80000000,
+ 0x4064: 0x80000000, 0x4065: 0x80000000, 0x4066: 0x80000000,
+ 0x4070: 0xf0001616, 0x4071: 0xf0000016, 0x4072: 0xf0000016, 0x4073: 0xf0000016,
+ 0x4074: 0xf0000016, 0x4075: 0xf0000016, 0x4076: 0xf0000016, 0x4077: 0xf0000016,
+ 0x4078: 0xf0000016, 0x4079: 0xf0000016, 0x407a: 0xf0000016, 0x407b: 0xf0000016,
+ 0x407c: 0xf0000016, 0x407d: 0xf0000016, 0x407e: 0xf0000016, 0x407f: 0xf0000016,
+ // Block 0x102, offset 0x4080
+ 0x4080: 0xf0000016, 0x4081: 0xf0000016, 0x4082: 0xf0000016, 0x4083: 0xf0000016,
+ 0x4084: 0xf0000016, 0x4085: 0x40012c20, 0x4086: 0x40012d20, 0x4087: 0xf0000016,
+ 0x4088: 0xf0000016, 0x4089: 0x00021604, 0x408a: 0x00021604, 0x408b: 0x00021604,
+ 0x408c: 0x00021604, 0x408d: 0xf0000004, 0x408e: 0xf0000004, 0x408f: 0xf0000004,
+ 0x4090: 0xf000000f, 0x4091: 0xf000000f, 0x4092: 0xf000000f,
+ 0x4094: 0xf000000f, 0x4095: 0xf000000f, 0x4096: 0xf000000f, 0x4097: 0xf000000f,
+ 0x4098: 0xf000000f, 0x4099: 0xf000000f, 0x409a: 0xf000000f, 0x409b: 0xf000000f,
+ 0x409c: 0xf000000f, 0x409d: 0xf000000f, 0x409e: 0xf000000f, 0x409f: 0xf000000f,
+ 0x40a0: 0xf000000f, 0x40a1: 0xf000000f, 0x40a2: 0xf000000f, 0x40a3: 0xf000000f,
+ 0x40a4: 0xf000000f, 0x40a5: 0xf000000f, 0x40a6: 0xf000000f,
+ 0x40a8: 0xf000000f, 0x40a9: 0xf000000f, 0x40aa: 0xf000000f, 0x40ab: 0xf000000f,
+ 0x40b0: 0x8000a21a, 0x40b1: 0x8000a218, 0x40b2: 0x8000a31a, 0x40b3: 0x80000000,
+ 0x40b4: 0x8000a51a, 0x40b6: 0x8000a71a, 0x40b7: 0x8000a718,
+ 0x40b8: 0x8000a91a, 0x40b9: 0x8000a918, 0x40ba: 0x8000ab1a, 0x40bb: 0x8000ab18,
+ 0x40bc: 0x8000ad1a, 0x40bd: 0x8000ad18, 0x40be: 0x8000af1a, 0x40bf: 0x8000af18,
+ // Block 0x103, offset 0x40c0
+ 0x40c0: 0xf000001a, 0x40c1: 0x0038781a, 0x40c2: 0x00387819, 0x40c3: 0x00387a1a,
+ 0x40c4: 0x00387a19, 0x40c5: 0x0038801a, 0x40c6: 0x00388019, 0x40c7: 0x0038821a,
+ 0x40c8: 0x00388219, 0x40c9: 0x00388a1a, 0x40ca: 0x00388a19, 0x40cb: 0x00388a17,
+ 0x40cc: 0x00388a18, 0x40cd: 0xf000001a, 0x40ce: 0xf0000019, 0x40cf: 0xf000001a,
+ 0x40d0: 0xf0000019, 0x40d1: 0xf0000017, 0x40d2: 0xf0000018, 0x40d3: 0xf000001a,
+ 0x40d4: 0xf0000019, 0x40d5: 0xf000001a, 0x40d6: 0xf0000019, 0x40d7: 0xf0000017,
+ 0x40d8: 0xf0000018, 0x40d9: 0xf000001a, 0x40da: 0xf0000019, 0x40db: 0xf0000017,
+ 0x40dc: 0xf0000018, 0x40dd: 0xf000001a, 0x40de: 0xf0000019, 0x40df: 0xf0000017,
+ 0x40e0: 0xf0000018, 0x40e1: 0xf000001a, 0x40e2: 0xf0000019, 0x40e3: 0xf0000017,
+ 0x40e4: 0xf0000018, 0x40e5: 0xf000001a, 0x40e6: 0xf0000019, 0x40e7: 0xf0000017,
+ 0x40e8: 0xf0000018, 0x40e9: 0xf000001a, 0x40ea: 0xf0000019, 0x40eb: 0xf000001a,
+ 0x40ec: 0xf0000019, 0x40ed: 0xf000001a, 0x40ee: 0xf0000019, 0x40ef: 0xf000001a,
+ 0x40f0: 0xf0000019, 0x40f1: 0xf000001a, 0x40f2: 0xf0000019, 0x40f3: 0xf0000017,
+ 0x40f4: 0xf0000018, 0x40f5: 0xf000001a, 0x40f6: 0xf0000019, 0x40f7: 0xf0000017,
+ 0x40f8: 0xf0000018, 0x40f9: 0xf000001a, 0x40fa: 0xf0000019, 0x40fb: 0xf0000017,
+ 0x40fc: 0xf0000018, 0x40fd: 0xf000001a, 0x40fe: 0xf0000019, 0x40ff: 0xf0000017,
+ // Block 0x104, offset 0x4100
+ 0x4100: 0xf0000018, 0x4101: 0xf000001a, 0x4102: 0xf0000019, 0x4103: 0xf0000017,
+ 0x4104: 0xf0000018, 0x4105: 0xf000001a, 0x4106: 0xf0000019, 0x4107: 0xf0000017,
+ 0x4108: 0xf0000018, 0x4109: 0xf000001a, 0x410a: 0xf0000019, 0x410b: 0xf0000017,
+ 0x410c: 0xf0000018, 0x410d: 0xf000001a, 0x410e: 0xf0000019, 0x410f: 0xf0000017,
+ 0x4110: 0xf0000018, 0x4111: 0xf000001a, 0x4112: 0xf0000019, 0x4113: 0xf0000017,
+ 0x4114: 0xf0000018, 0x4115: 0xf000001a, 0x4116: 0xf0000019, 0x4117: 0xf0000017,
+ 0x4118: 0xf0000018, 0x4119: 0xf000001a, 0x411a: 0xf0000019, 0x411b: 0xf0000017,
+ 0x411c: 0xf0000018, 0x411d: 0xf000001a, 0x411e: 0xf0000019, 0x411f: 0xf0000017,
+ 0x4120: 0xf0000018, 0x4121: 0xf000001a, 0x4122: 0xf0000019, 0x4123: 0xf0000017,
+ 0x4124: 0xf0000018, 0x4125: 0xf000001a, 0x4126: 0xf0000019, 0x4127: 0xf0000017,
+ 0x4128: 0xf0000018, 0x4129: 0xf000001a, 0x412a: 0xf0000019, 0x412b: 0xf0000017,
+ 0x412c: 0xf0000018, 0x412d: 0xf000001a, 0x412e: 0xf0000019, 0x412f: 0xf000001a,
+ 0x4130: 0xf0000019, 0x4131: 0xf000001a, 0x4132: 0xf0000019, 0x4133: 0xf0000017,
+ 0x4134: 0xf0000018, 0x4135: 0xe00008bb, 0x4136: 0xe00008b8, 0x4137: 0xe00008c1,
+ 0x4138: 0xe00008be, 0x4139: 0xe00008c7, 0x413a: 0xe00008c4, 0x413b: 0xf0001a1a,
+ 0x413c: 0xf0001919, 0x413f: 0x80000000,
+ // Block 0x105, offset 0x4140
+ 0x4141: 0xf0000003, 0x4142: 0xf0000003, 0x4143: 0xf0000003,
+ 0x4144: 0xf0000003, 0x4145: 0xf0000003, 0x4146: 0xf0000003, 0x4147: 0xf0000003,
+ 0x4148: 0xf0000003, 0x4149: 0xf0000003, 0x414a: 0xf0000003, 0x414b: 0xf0000003,
+ 0x414c: 0xf0000003, 0x414d: 0xf0000003, 0x414e: 0xf0000003, 0x414f: 0xf0000003,
+ 0x4150: 0xf0000003, 0x4151: 0xf0000003, 0x4152: 0xf0000003, 0x4153: 0xf0000003,
+ 0x4154: 0xf0000003, 0x4155: 0xf0000003, 0x4156: 0xf0000003, 0x4157: 0xf0000003,
+ 0x4158: 0xf0000003, 0x4159: 0xf0000003, 0x415a: 0xf0000003, 0x415b: 0xf0000003,
+ 0x415c: 0xf0000003, 0x415d: 0xf0000003, 0x415e: 0xf0000003, 0x415f: 0xf0000003,
+ 0x4160: 0xf0000003, 0x4161: 0xf0000009, 0x4162: 0xf0000009, 0x4163: 0xf0000009,
+ 0x4164: 0xf0000009, 0x4165: 0xf0000009, 0x4166: 0xf0000009, 0x4167: 0xf0000009,
+ 0x4168: 0xf0000009, 0x4169: 0xf0000009, 0x416a: 0xf0000009, 0x416b: 0xf0000009,
+ 0x416c: 0xf0000009, 0x416d: 0xf0000009, 0x416e: 0xf0000009, 0x416f: 0xf0000009,
+ 0x4170: 0xf0000009, 0x4171: 0xf0000009, 0x4172: 0xf0000009, 0x4173: 0xf0000009,
+ 0x4174: 0xf0000009, 0x4175: 0xf0000009, 0x4176: 0xf0000009, 0x4177: 0xf0000009,
+ 0x4178: 0xf0000009, 0x4179: 0xf0000009, 0x417a: 0xf0000009, 0x417b: 0xf0000003,
+ 0x417c: 0xf0000003, 0x417d: 0xf0000003, 0x417e: 0xf0000003, 0x417f: 0xf0000003,
+ // Block 0x106, offset 0x4180
+ 0x4180: 0xf0000003, 0x4181: 0xf0000003, 0x4182: 0xf0000003, 0x4183: 0xf0000003,
+ 0x4184: 0xf0000003, 0x4185: 0xf0000003, 0x4186: 0xf0000003, 0x4187: 0xf0000003,
+ 0x4188: 0xf0000003, 0x4189: 0xf0000003, 0x418a: 0xf0000003, 0x418b: 0xf0000003,
+ 0x418c: 0xf0000003, 0x418d: 0xf0000003, 0x418e: 0xf0000003, 0x418f: 0xf0000003,
+ 0x4190: 0xf0000003, 0x4191: 0xf0000003, 0x4192: 0xf0000003, 0x4193: 0xf0000003,
+ 0x4194: 0xf0000003, 0x4195: 0xf0000003, 0x4196: 0xf0000003, 0x4197: 0xf0000003,
+ 0x4198: 0xf0000003, 0x4199: 0xf0000003, 0x419a: 0xf0000003, 0x419b: 0xf0000003,
+ 0x419c: 0xf0000003, 0x419d: 0xf0000003, 0x419e: 0xf0000003, 0x419f: 0xf0000003,
+ 0x41a0: 0xf0000003, 0x41a1: 0xf0000012, 0x41a2: 0xf0000012, 0x41a3: 0xf0000012,
+ 0x41a4: 0xf0000012, 0x41a5: 0xf0000012, 0x41a6: 0xf0000012, 0x41a7: 0xf0000010,
+ 0x41a8: 0xf0000010, 0x41a9: 0xf0000010, 0x41aa: 0xf0000010, 0x41ab: 0xf0000010,
+ 0x41ac: 0xf0000010, 0x41ad: 0xf0000010, 0x41ae: 0xf0000010, 0x41af: 0xf0000010,
+ 0x41b0: 0xf0000012, 0x41b1: 0xf0000012, 0x41b2: 0xf0000012, 0x41b3: 0xf0000012,
+ 0x41b4: 0xf0000012, 0x41b5: 0xf0000012, 0x41b6: 0xf0000012, 0x41b7: 0xf0000012,
+ 0x41b8: 0xf0000012, 0x41b9: 0xf0000012, 0x41ba: 0xf0000012, 0x41bb: 0xf0000012,
+ 0x41bc: 0xf0000012, 0x41bd: 0xf0000012, 0x41be: 0xf0000012, 0x41bf: 0xf0000012,
+ // Block 0x107, offset 0x41c0
+ 0x41c0: 0xf0000012, 0x41c1: 0xf0000012, 0x41c2: 0xf0000012, 0x41c3: 0xf0000012,
+ 0x41c4: 0xf0000012, 0x41c5: 0xf0000012, 0x41c6: 0xf0000012, 0x41c7: 0xf0000012,
+ 0x41c8: 0xf0000012, 0x41c9: 0xf0000012, 0x41ca: 0xf0000012, 0x41cb: 0xf0000012,
+ 0x41cc: 0xf0000012, 0x41cd: 0xf0000012, 0x41ce: 0xf0000012, 0x41cf: 0xf0000012,
+ 0x41d0: 0xf0000012, 0x41d1: 0xf0000012, 0x41d2: 0xf0000012, 0x41d3: 0xf0000012,
+ 0x41d4: 0xf0000012, 0x41d5: 0xf0000012, 0x41d6: 0xf0000012, 0x41d7: 0xf0000012,
+ 0x41d8: 0xf0000012, 0x41d9: 0xf0000012, 0x41da: 0xf0000012, 0x41db: 0xf0000012,
+ 0x41dc: 0xf0000012, 0x41dd: 0xf0000012, 0x41de: 0xf0000012, 0x41df: 0xf0000012,
+ 0x41e0: 0xf0000012, 0x41e1: 0xf0000012, 0x41e2: 0xf0000012, 0x41e3: 0xf0000012,
+ 0x41e4: 0xf0000012, 0x41e5: 0xf0000012, 0x41e6: 0xf0000012, 0x41e7: 0xf0000012,
+ 0x41e8: 0xf0000012, 0x41e9: 0xf0000012, 0x41ea: 0xf0000012, 0x41eb: 0xf0000012,
+ 0x41ec: 0xf0000012, 0x41ed: 0xf0000012, 0x41ee: 0xf0000012, 0x41ef: 0xf0000012,
+ 0x41f0: 0xf0000012, 0x41f1: 0xf0000012, 0x41f2: 0xf0000012, 0x41f3: 0xf0000012,
+ 0x41f4: 0xf0000012, 0x41f5: 0xf0000012, 0x41f6: 0xf0000012, 0x41f7: 0xf0000012,
+ 0x41f8: 0xf0000012, 0x41f9: 0xf0000012, 0x41fa: 0xf0000012, 0x41fb: 0xf0000012,
+ 0x41fc: 0xf0000012, 0x41fd: 0xf0000012, 0x41fe: 0xf0000012,
+ // Block 0x108, offset 0x4200
+ 0x4202: 0xf0000012, 0x4203: 0xf0000012,
+ 0x4204: 0xf0000012, 0x4205: 0xf0000012, 0x4206: 0xf0000012, 0x4207: 0xf0000012,
+ 0x420a: 0xf0000012, 0x420b: 0xf0000012,
+ 0x420c: 0xf0000012, 0x420d: 0xf0000012, 0x420e: 0xf0000012, 0x420f: 0xf0000012,
+ 0x4212: 0xf0000012, 0x4213: 0xf0000012,
+ 0x4214: 0xf0000012, 0x4215: 0xf0000012, 0x4216: 0xf0000012, 0x4217: 0xf0000012,
+ 0x421a: 0xf0000012, 0x421b: 0xf0000012,
+ 0x421c: 0xf0000012,
+ 0x4220: 0xf0000003, 0x4221: 0xf0000003, 0x4222: 0xf0000003, 0x4223: 0x0005e403,
+ 0x4224: 0xf0000003, 0x4225: 0xf0000003, 0x4226: 0xf0000003,
+ 0x4228: 0xf0000012, 0x4229: 0xf0000012, 0x422a: 0xf0000012, 0x422b: 0xf0000012,
+ 0x422c: 0xf0000012, 0x422d: 0xf0000012, 0x422e: 0xf0000012,
+ 0x4239: 0x80000000, 0x423a: 0x80000000, 0x423b: 0x80000000,
+ 0x423c: 0x40139020, 0x423d: 0x40139120, 0x423e: 0x00000205, 0x423f: 0x2bfffe05,
+ // Block 0x109, offset 0x4240
+ 0x4240: 0x4037ce20, 0x4241: 0x4037cf20, 0x4242: 0x4037d020, 0x4243: 0x4037d120,
+ 0x4244: 0x4037d220, 0x4245: 0x4037d320, 0x4246: 0x4037d420, 0x4247: 0x4037d520,
+ 0x4248: 0x4037d620, 0x4249: 0x4037d720, 0x424a: 0x4037d820, 0x424b: 0x4037d920,
+ 0x424d: 0x4037da20, 0x424e: 0x4037db20, 0x424f: 0x4037dc20,
+ 0x4250: 0x4037dd20, 0x4251: 0x4037de20, 0x4252: 0x4037df20, 0x4253: 0x4037e020,
+ 0x4254: 0x4037e120, 0x4255: 0x4037e220, 0x4256: 0x4037e320, 0x4257: 0x4037e420,
+ 0x4258: 0x4037e520, 0x4259: 0x4037e620, 0x425a: 0x4037e720, 0x425b: 0x4037e820,
+ 0x425c: 0x4037e920, 0x425d: 0x4037ea20, 0x425e: 0x4037eb20, 0x425f: 0x4037ec20,
+ 0x4260: 0x4037ed20, 0x4261: 0x4037ee20, 0x4262: 0x4037ef20, 0x4263: 0x4037f020,
+ 0x4264: 0x4037f120, 0x4265: 0x4037f220, 0x4266: 0x4037f320,
+ 0x4268: 0x4037f420, 0x4269: 0x4037f520, 0x426a: 0x4037f620, 0x426b: 0x4037f720,
+ 0x426c: 0x4037f820, 0x426d: 0x4037f920, 0x426e: 0x4037fa20, 0x426f: 0x4037fb20,
+ 0x4270: 0x4037fc20, 0x4271: 0x4037fd20, 0x4272: 0x4037fe20, 0x4273: 0x4037ff20,
+ 0x4274: 0x40380020, 0x4275: 0x40380120, 0x4276: 0x40380220, 0x4277: 0x40380320,
+ 0x4278: 0x40380420, 0x4279: 0x40380520, 0x427a: 0x40380620,
+ 0x427c: 0x40380720, 0x427d: 0x40380820, 0x427f: 0x40380920,
+ // Block 0x10a, offset 0x4280
+ 0x4280: 0x40380a20, 0x4281: 0x40380b20, 0x4282: 0x40380c20, 0x4283: 0x40380d20,
+ 0x4284: 0x40380e20, 0x4285: 0x40380f20, 0x4286: 0x40381020, 0x4287: 0x40381120,
+ 0x4288: 0x40381220, 0x4289: 0x40381320, 0x428a: 0x40381420, 0x428b: 0x40381520,
+ 0x428c: 0x40381620, 0x428d: 0x40381720,
+ 0x4290: 0x40381820, 0x4291: 0x40381920, 0x4292: 0x40381a20, 0x4293: 0x40381b20,
+ 0x4294: 0x40381c20, 0x4295: 0x40381d20, 0x4296: 0x40381e20, 0x4297: 0x40381f20,
+ 0x4298: 0x40382020, 0x4299: 0x40382120, 0x429a: 0x40382220, 0x429b: 0x40382320,
+ 0x429c: 0x40382420, 0x429d: 0x40382520,
+ // Block 0x10b, offset 0x42c0
+ 0x42c0: 0x40382620, 0x42c1: 0x40382720, 0x42c2: 0x40382820, 0x42c3: 0x40382920,
+ 0x42c4: 0x40382a20, 0x42c5: 0x40382b20, 0x42c6: 0x40382c20, 0x42c7: 0x40382d20,
+ 0x42c8: 0x40382e20, 0x42c9: 0x40382f20, 0x42ca: 0x40383020, 0x42cb: 0x40383120,
+ 0x42cc: 0x40383220, 0x42cd: 0x40383320, 0x42ce: 0x40383420, 0x42cf: 0x40383520,
+ 0x42d0: 0x40383620, 0x42d1: 0x40383720, 0x42d2: 0x40383820, 0x42d3: 0x40383920,
+ 0x42d4: 0x40383a20, 0x42d5: 0x40383b20, 0x42d6: 0x40383c20, 0x42d7: 0x40383d20,
+ 0x42d8: 0x40383e20, 0x42d9: 0x40383f20, 0x42da: 0x40384020, 0x42db: 0x40384120,
+ 0x42dc: 0x40384220, 0x42dd: 0x40384320, 0x42de: 0x40384420, 0x42df: 0x40384520,
+ 0x42e0: 0x40384620, 0x42e1: 0x40384720, 0x42e2: 0x40384820, 0x42e3: 0x40384920,
+ 0x42e4: 0x40384a20, 0x42e5: 0x40384b20, 0x42e6: 0x40384c20, 0x42e7: 0x40384d20,
+ 0x42e8: 0x40384e20, 0x42e9: 0x40384f20, 0x42ea: 0x40385020, 0x42eb: 0x40385120,
+ 0x42ec: 0x40385220, 0x42ed: 0x40385320, 0x42ee: 0x40385420, 0x42ef: 0x40385520,
+ 0x42f0: 0x40385620, 0x42f1: 0x40385720, 0x42f2: 0x40385820, 0x42f3: 0x40385920,
+ 0x42f4: 0x40385a20, 0x42f5: 0x40385b20, 0x42f6: 0x40385c20, 0x42f7: 0x40385d20,
+ 0x42f8: 0x40385e20, 0x42f9: 0x40385f20, 0x42fa: 0x40386020, 0x42fb: 0x40386120,
+ 0x42fc: 0x40386220, 0x42fd: 0x40386320, 0x42fe: 0x40386420, 0x42ff: 0x40386520,
+ // Block 0x10c, offset 0x4300
+ 0x4300: 0x40386620, 0x4301: 0x40386720, 0x4302: 0x40386820, 0x4303: 0x40386920,
+ 0x4304: 0x40386a20, 0x4305: 0x40386b20, 0x4306: 0x40386c20, 0x4307: 0x40386d20,
+ 0x4308: 0x40386e20, 0x4309: 0x40386f20, 0x430a: 0x40387020, 0x430b: 0x40387120,
+ 0x430c: 0x40387220, 0x430d: 0x40387320, 0x430e: 0x40387420, 0x430f: 0x40387520,
+ 0x4310: 0x40387620, 0x4311: 0x40387720, 0x4312: 0x40387820, 0x4313: 0x40387920,
+ 0x4314: 0x40387a20, 0x4315: 0x40387b20, 0x4316: 0x40387c20, 0x4317: 0x40387d20,
+ 0x4318: 0x40387e20, 0x4319: 0x40387f20, 0x431a: 0x40388020, 0x431b: 0x40388120,
+ 0x431c: 0x40388220, 0x431d: 0x40388320, 0x431e: 0x40388420, 0x431f: 0x40388520,
+ 0x4320: 0x40388620, 0x4321: 0x40388720, 0x4322: 0x40388820, 0x4323: 0x40388920,
+ 0x4324: 0x40388a20, 0x4325: 0x40388b20, 0x4326: 0x40388c20, 0x4327: 0x40388d20,
+ 0x4328: 0x40388e20, 0x4329: 0x40388f20, 0x432a: 0x40389020, 0x432b: 0x40389120,
+ 0x432c: 0x40389220, 0x432d: 0x40389320, 0x432e: 0x40389420, 0x432f: 0x40389520,
+ 0x4330: 0x40389620, 0x4331: 0x40389720, 0x4332: 0x40389820, 0x4333: 0x40389920,
+ 0x4334: 0x40389a20, 0x4335: 0x40389b20, 0x4336: 0x40389c20, 0x4337: 0x40389d20,
+ 0x4338: 0x40389e20, 0x4339: 0x40389f20, 0x433a: 0x4038a020,
+ // Block 0x10d, offset 0x4340
+ 0x4340: 0x4001cf20, 0x4341: 0x4001d020, 0x4342: 0x40031120,
+ 0x4347: 0xe0000117,
+ 0x4348: 0xe00001fe, 0x4349: 0xe00002c4, 0x434a: 0xe0000381, 0x434b: 0xe000043b,
+ 0x434c: 0xe00004f2, 0x434d: 0xe000058e, 0x434e: 0xe000062a, 0x434f: 0xe00006c3,
+ 0x4350: 0x40141120, 0x4351: 0x40141220, 0x4352: 0x40141320, 0x4353: 0x40141420,
+ 0x4354: 0x40141520, 0x4355: 0x40141620, 0x4356: 0x40141720, 0x4357: 0x40141820,
+ 0x4358: 0x40141920, 0x4359: 0x40141a20, 0x435a: 0x40141b20, 0x435b: 0x40141c20,
+ 0x435c: 0x40141d20, 0x435d: 0x40141e20, 0x435e: 0x40141f20, 0x435f: 0x40142020,
+ 0x4360: 0x40142120, 0x4361: 0x40142220, 0x4362: 0x40142320, 0x4363: 0x40142420,
+ 0x4364: 0x40142520, 0x4365: 0x40142620, 0x4366: 0x40142720, 0x4367: 0x40142820,
+ 0x4368: 0x40142920, 0x4369: 0x40142a20, 0x436a: 0x40142b20, 0x436b: 0x40142c20,
+ 0x436c: 0x40142d20, 0x436d: 0x40142e20, 0x436e: 0x40142f20, 0x436f: 0x40143020,
+ 0x4370: 0x40143120, 0x4371: 0x40143220, 0x4372: 0x40143320, 0x4373: 0x40143420,
+ 0x4377: 0x400d4920,
+ 0x4378: 0x400d4a20, 0x4379: 0x400d4b20, 0x437a: 0x400d4c20, 0x437b: 0x400d4d20,
+ 0x437c: 0x400d4e20, 0x437d: 0x400d4f20, 0x437e: 0x400d5020, 0x437f: 0x400d5120,
+ // Block 0x10e, offset 0x4380
+ 0x4380: 0x40143520, 0x4381: 0x40143620, 0x4382: 0xe000011a, 0x4383: 0xe000043e,
+ 0x4384: 0x40143720, 0x4385: 0x40143820, 0x4386: 0x40143920, 0x4387: 0x40143a20,
+ 0x4388: 0xe0000441, 0x4389: 0x40143b20, 0x438a: 0x40143c20, 0x438b: 0x40143d20,
+ 0x438c: 0x40143e20, 0x438d: 0x40143f20, 0x438e: 0x40144020, 0x438f: 0xe0000444,
+ 0x4390: 0x40144120, 0x4391: 0x40144220, 0x4392: 0x40144320, 0x4393: 0x40144420,
+ 0x4394: 0x40144520, 0x4395: 0x40144620, 0x4396: 0x40144720, 0x4397: 0x40144820,
+ 0x4398: 0xe000011d, 0x4399: 0xe0000120, 0x439a: 0xe0000123, 0x439b: 0xe0000201,
+ 0x439c: 0xe0000204, 0x439d: 0xe0000207, 0x439e: 0xe000020a, 0x439f: 0xe0000447,
+ 0x43a0: 0x40144920, 0x43a1: 0x40144a20, 0x43a2: 0x40144b20, 0x43a3: 0x40144c20,
+ 0x43a4: 0x40144d20, 0x43a5: 0x40144e20, 0x43a6: 0x40144f20, 0x43a7: 0x40145020,
+ 0x43a8: 0x40145120, 0x43a9: 0x40145220, 0x43aa: 0x40145320, 0x43ab: 0x40145420,
+ 0x43ac: 0x40145520, 0x43ad: 0x40145620, 0x43ae: 0x40145720, 0x43af: 0x40145820,
+ 0x43b0: 0x40145920, 0x43b1: 0x40145a20, 0x43b2: 0x40145b20, 0x43b3: 0xe000044a,
+ 0x43b4: 0x40145c20, 0x43b5: 0x40145d20, 0x43b6: 0x40145e20, 0x43b7: 0x40145f20,
+ 0x43b8: 0x40146020, 0x43b9: 0x400d5220, 0x43ba: 0x400d5320, 0x43bb: 0x400d5420,
+ 0x43bc: 0x400d5520, 0x43bd: 0x400d5620, 0x43be: 0x400d5720, 0x43bf: 0x400d5820,
+ // Block 0x10f, offset 0x43c0
+ 0x43c0: 0x400d5920, 0x43c1: 0x400d5a20, 0x43c2: 0x400d5b20, 0x43c3: 0x400d5c20,
+ 0x43c4: 0x400d5d20, 0x43c5: 0x400d5e20, 0x43c6: 0x400d5f20, 0x43c7: 0x400d6020,
+ 0x43c8: 0x400d6120, 0x43c9: 0x400d6220, 0x43ca: 0xe0000093,
+ 0x43d0: 0x400d6320, 0x43d1: 0x400d6420, 0x43d2: 0x400d6520, 0x43d3: 0x400d6620,
+ 0x43d4: 0x400d6720, 0x43d5: 0x400d6820, 0x43d6: 0x400d6920, 0x43d7: 0x400d6a20,
+ 0x43d8: 0x400d6b20, 0x43d9: 0x400d6c20, 0x43da: 0x400d6d20, 0x43db: 0x400d6e20,
+ // Block 0x110, offset 0x4400
+ 0x4410: 0x400d6f20, 0x4411: 0x400d7020, 0x4412: 0x400d7120, 0x4413: 0x400d7220,
+ 0x4414: 0x400d7320, 0x4415: 0x400d7420, 0x4416: 0x400d7520, 0x4417: 0x400d7620,
+ 0x4418: 0x400d7720, 0x4419: 0x400d7820, 0x441a: 0x400d7920, 0x441b: 0x400d7a20,
+ 0x441c: 0x400d7b20, 0x441d: 0x400d7c20, 0x441e: 0x400d7d20, 0x441f: 0x400d7e20,
+ 0x4420: 0x400d7f20, 0x4421: 0x400d8020, 0x4422: 0x400d8120, 0x4423: 0x400d8220,
+ 0x4424: 0x400d8320, 0x4425: 0x400d8420, 0x4426: 0x400d8520, 0x4427: 0x400d8620,
+ 0x4428: 0x400d8720, 0x4429: 0x400d8820, 0x442a: 0x400d8920, 0x442b: 0x400d8a20,
+ 0x442c: 0x400d8b20, 0x442d: 0x400d8c20, 0x442e: 0x400d8d20, 0x442f: 0x400d8e20,
+ 0x4430: 0x400d8f20, 0x4431: 0x400d9020, 0x4432: 0x400d9120, 0x4433: 0x400d9220,
+ 0x4434: 0x400d9320, 0x4435: 0x400d9420, 0x4436: 0x400d9520, 0x4437: 0x400d9620,
+ 0x4438: 0x400d9720, 0x4439: 0x400d9820, 0x443a: 0x400d9920, 0x443b: 0x400d9a20,
+ 0x443c: 0x400d9b20, 0x443d: 0x80015e02,
+ // Block 0x111, offset 0x4440
+ 0x4440: 0x4036b620, 0x4441: 0x4036b720, 0x4442: 0x4036b820, 0x4443: 0x4036b920,
+ 0x4444: 0x4036ba20, 0x4445: 0x4036bb20, 0x4446: 0x4036bc20, 0x4447: 0x4036bd20,
+ 0x4448: 0x4036be20, 0x4449: 0x4036bf20, 0x444a: 0x4036c020, 0x444b: 0x4036c120,
+ 0x444c: 0x4036c220, 0x444d: 0x4036c320, 0x444e: 0x4036c420, 0x444f: 0x4036c520,
+ 0x4450: 0x4036c620, 0x4451: 0x4036c720, 0x4452: 0x4036c820, 0x4453: 0x4036c920,
+ 0x4454: 0x4036ca20, 0x4455: 0x4036cb20, 0x4456: 0x4036cc20, 0x4457: 0x4036cd20,
+ 0x4458: 0x4036ce20, 0x4459: 0x4036cf20, 0x445a: 0x4036d020, 0x445b: 0x4036d120,
+ 0x445c: 0x4036d220,
+ 0x4460: 0x4036d320, 0x4461: 0x4036d420, 0x4462: 0x4036d520, 0x4463: 0x4036d620,
+ 0x4464: 0x4036d720, 0x4465: 0x4036d820, 0x4466: 0x4036d920, 0x4467: 0x4036da20,
+ 0x4468: 0x4036db20, 0x4469: 0x4036dc20, 0x446a: 0x4036dd20, 0x446b: 0x4036de20,
+ 0x446c: 0x4036df20, 0x446d: 0x4036e020, 0x446e: 0x4036e120, 0x446f: 0x4036e220,
+ 0x4470: 0x4036e320, 0x4471: 0x4036e420, 0x4472: 0x4036e520, 0x4473: 0x4036e620,
+ 0x4474: 0x4036e720, 0x4475: 0x4036e820, 0x4476: 0x4036e920, 0x4477: 0x4036ea20,
+ 0x4478: 0x4036eb20, 0x4479: 0x4036ec20, 0x447a: 0x4036ed20, 0x447b: 0x4036ee20,
+ 0x447c: 0x4036ef20, 0x447d: 0x4036f020, 0x447e: 0x4036f120, 0x447f: 0x4036f220,
+ // Block 0x112, offset 0x4480
+ 0x4480: 0x4036f320, 0x4481: 0x4036f420, 0x4482: 0x4036f520, 0x4483: 0x4036f620,
+ 0x4484: 0x4036f720, 0x4485: 0x4036f820, 0x4486: 0x4036f920, 0x4487: 0x4036fa20,
+ 0x4488: 0x4036fb20, 0x4489: 0x4036fc20, 0x448a: 0x4036fd20, 0x448b: 0x4036fe20,
+ 0x448c: 0x4036ff20, 0x448d: 0x40370020, 0x448e: 0x40370120, 0x448f: 0x40370220,
+ 0x4490: 0x40370320,
+ // Block 0x113, offset 0x44c0
+ 0x44c0: 0x40371e20, 0x44c1: 0x40371f20, 0x44c2: 0x40372020, 0x44c3: 0x40372120,
+ 0x44c4: 0x40372220, 0x44c5: 0x40372320, 0x44c6: 0x40372420, 0x44c7: 0x40372520,
+ 0x44c8: 0x40372620, 0x44c9: 0x40372720, 0x44ca: 0x40372820, 0x44cb: 0x40372920,
+ 0x44cc: 0x40372a20, 0x44cd: 0x40372b20, 0x44ce: 0x40372c20, 0x44cf: 0x40372d20,
+ 0x44d0: 0x40372e20, 0x44d1: 0x40372f20, 0x44d2: 0x40373020, 0x44d3: 0x40373120,
+ 0x44d4: 0x40373220, 0x44d5: 0x40373320, 0x44d6: 0x40373420, 0x44d7: 0x40373520,
+ 0x44d8: 0x40373620, 0x44d9: 0x40373720, 0x44da: 0x40373820, 0x44db: 0x40373920,
+ 0x44dc: 0x40373a20, 0x44dd: 0x40373b20, 0x44de: 0x40373c20,
+ 0x44e0: 0xe0000126, 0x44e1: 0xe000044d, 0x44e2: 0x40140f20, 0x44e3: 0x40141020,
+ 0x44f0: 0x40373d20, 0x44f1: 0x40373e20, 0x44f2: 0x40373f20, 0x44f3: 0x40374020,
+ 0x44f4: 0x40374120, 0x44f5: 0x40374220, 0x44f6: 0x40374320, 0x44f7: 0x40374420,
+ 0x44f8: 0x40374520, 0x44f9: 0x40374620, 0x44fa: 0x40374720, 0x44fb: 0x40374820,
+ 0x44fc: 0x40374920, 0x44fd: 0x40374a20, 0x44fe: 0x40374b20, 0x44ff: 0x40374c20,
+ // Block 0x114, offset 0x4500
+ 0x4500: 0x40374d20, 0x4501: 0x40374e20, 0x4502: 0x40374f20, 0x4503: 0x40375020,
+ 0x4504: 0x40375120, 0x4505: 0x40375220, 0x4506: 0x40375320, 0x4507: 0x40375420,
+ 0x4508: 0x40375520, 0x4509: 0x40375620, 0x450a: 0x40375720,
+ // Block 0x115, offset 0x4540
+ 0x4540: 0x40396920, 0x4541: 0x40396a20, 0x4542: 0x40396b20, 0x4543: 0x40396c20,
+ 0x4544: 0x40396d20, 0x4545: 0x40396e20, 0x4546: 0x40396f20, 0x4547: 0x40397020,
+ 0x4548: 0x40397120, 0x4549: 0x40397220, 0x454a: 0x40397320, 0x454b: 0x40397420,
+ 0x454c: 0x40397520, 0x454d: 0x40397620, 0x454e: 0x40397720, 0x454f: 0x40397820,
+ 0x4550: 0x40397920, 0x4551: 0x40397a20, 0x4552: 0x40397b20, 0x4553: 0x40397c20,
+ 0x4554: 0x40397d20, 0x4555: 0x40397e20, 0x4556: 0x40397f20, 0x4557: 0x40398020,
+ 0x4558: 0x40398120, 0x4559: 0x40398220, 0x455a: 0x40398320, 0x455b: 0x40398420,
+ 0x455c: 0x40398520, 0x455d: 0x40398620, 0x455f: 0x4001d120,
+ 0x4560: 0x40398720, 0x4561: 0x40398820, 0x4562: 0x40398920, 0x4563: 0x40398a20,
+ 0x4564: 0x40398b20, 0x4565: 0x40398c20, 0x4566: 0x40398d20, 0x4567: 0x40398e20,
+ 0x4568: 0x40398f20, 0x4569: 0x40399020, 0x456a: 0x40399120, 0x456b: 0x40399220,
+ 0x456c: 0x40399320, 0x456d: 0x40399420, 0x456e: 0x40399520, 0x456f: 0x40399620,
+ 0x4570: 0x40399720, 0x4571: 0x40399820, 0x4572: 0x40399920, 0x4573: 0x40399a20,
+ 0x4574: 0x40399b20, 0x4575: 0x40399c20, 0x4576: 0x40399d20, 0x4577: 0x40399e20,
+ 0x4578: 0x40399f20, 0x4579: 0x4039a020, 0x457a: 0x4039a120, 0x457b: 0x4039a220,
+ 0x457c: 0x4039a320, 0x457d: 0x4039a420, 0x457e: 0x4039a520, 0x457f: 0x4039a620,
+ // Block 0x116, offset 0x4580
+ 0x4580: 0x4039a720, 0x4581: 0x4039a820, 0x4582: 0x4039a920, 0x4583: 0x4039aa20,
+ 0x4588: 0x4039ab20, 0x4589: 0x4039ac20, 0x458a: 0x4039ad20, 0x458b: 0x4039ae20,
+ 0x458c: 0x4039af20, 0x458d: 0x4039b020, 0x458e: 0x4039b120, 0x458f: 0x4039b220,
+ 0x4590: 0x4001d220, 0x4591: 0xe0000129, 0x4592: 0xe000020d, 0x4593: 0x40146120,
+ 0x4594: 0x40146220, 0x4595: 0x40146320,
+ // Block 0x117, offset 0x45c0
+ 0x45c0: 0x006eb008, 0x45c1: 0x006eb208, 0x45c2: 0x006eb408, 0x45c3: 0x006eb608,
+ 0x45c4: 0x006eb808, 0x45c5: 0x006eba08, 0x45c6: 0x006ebc08, 0x45c7: 0x006ebe08,
+ 0x45c8: 0x006ec008, 0x45c9: 0x006ec208, 0x45ca: 0x006ec408, 0x45cb: 0x006ec608,
+ 0x45cc: 0x006ec808, 0x45cd: 0x006eca08, 0x45ce: 0x006ecc08, 0x45cf: 0x006ece08,
+ 0x45d0: 0x006ed008, 0x45d1: 0x006ed208, 0x45d2: 0x006ed408, 0x45d3: 0x006ed608,
+ 0x45d4: 0x006ed808, 0x45d5: 0x006eda08, 0x45d6: 0x006edc08, 0x45d7: 0x006ede08,
+ 0x45d8: 0x006ee008, 0x45d9: 0x006ee208, 0x45da: 0x006ee408, 0x45db: 0x006ee608,
+ 0x45dc: 0x006ee808, 0x45dd: 0x006eea08, 0x45de: 0x006eec08, 0x45df: 0x006eee08,
+ 0x45e0: 0x006ef008, 0x45e1: 0x006ef208, 0x45e2: 0x006ef408, 0x45e3: 0x006ef608,
+ 0x45e4: 0x006ef808, 0x45e5: 0x006efa08, 0x45e6: 0x006efc08, 0x45e7: 0x006efe08,
+ 0x45e8: 0x40375820, 0x45e9: 0x40375920, 0x45ea: 0x40375a20, 0x45eb: 0x40375b20,
+ 0x45ec: 0x40375c20, 0x45ed: 0x40375d20, 0x45ee: 0x40375e20, 0x45ef: 0x40375f20,
+ 0x45f0: 0x40376020, 0x45f1: 0x40376120, 0x45f2: 0x40376220, 0x45f3: 0x40376320,
+ 0x45f4: 0x40376420, 0x45f5: 0x40376520, 0x45f6: 0x40376620, 0x45f7: 0x40376720,
+ 0x45f8: 0x40376820, 0x45f9: 0x40376920, 0x45fa: 0x40376a20, 0x45fb: 0x40376b20,
+ 0x45fc: 0x40376c20, 0x45fd: 0x40376d20, 0x45fe: 0x40376e20, 0x45ff: 0x40376f20,
+ // Block 0x118, offset 0x4600
+ 0x4600: 0x40377020, 0x4601: 0x40377120, 0x4602: 0x40377220, 0x4603: 0x40377320,
+ 0x4604: 0x40377420, 0x4605: 0x40377520, 0x4606: 0x40377620, 0x4607: 0x40377720,
+ 0x4608: 0x40377820, 0x4609: 0x40377920, 0x460a: 0x40377a20, 0x460b: 0x40377b20,
+ 0x460c: 0x40377c20, 0x460d: 0x40377d20, 0x460e: 0x40377e20, 0x460f: 0x40377f20,
+ 0x4610: 0x40378020, 0x4611: 0x40378120, 0x4612: 0x40378220, 0x4613: 0x40378320,
+ 0x4614: 0x40378420, 0x4615: 0x40378520, 0x4616: 0x40378620, 0x4617: 0x40378720,
+ 0x4618: 0x40378820, 0x4619: 0x40378920, 0x461a: 0x40378a20, 0x461b: 0x40378b20,
+ 0x461c: 0x40378c20, 0x461d: 0x40378d20, 0x461e: 0x40378e20, 0x461f: 0x40378f20,
+ 0x4620: 0x40379020, 0x4621: 0x40379120, 0x4622: 0x40379220, 0x4623: 0x40379320,
+ 0x4624: 0x40379420, 0x4625: 0x40379520, 0x4626: 0x40379620, 0x4627: 0x40379720,
+ 0x4628: 0x40379820, 0x4629: 0x40379920, 0x462a: 0x40379a20, 0x462b: 0x40379b20,
+ 0x462c: 0x40379c20, 0x462d: 0x40379d20, 0x462e: 0x40379e20, 0x462f: 0x40379f20,
+ 0x4630: 0x4037a020, 0x4631: 0x4037a120, 0x4632: 0x4037a220, 0x4633: 0x4037a320,
+ 0x4634: 0x4037a420, 0x4635: 0x4037a520, 0x4636: 0x4037a620, 0x4637: 0x4037a720,
+ 0x4638: 0x4037a820, 0x4639: 0x4037a920, 0x463a: 0x4037aa20, 0x463b: 0x4037ab20,
+ 0x463c: 0x4037ac20, 0x463d: 0x4037ad20, 0x463e: 0x4037ae20, 0x463f: 0x4037af20,
+ // Block 0x119, offset 0x4640
+ 0x4640: 0x4037b020, 0x4641: 0x4037b120, 0x4642: 0x4037b220, 0x4643: 0x4037b320,
+ 0x4644: 0x4037b420, 0x4645: 0x4037b520, 0x4646: 0x4037b620, 0x4647: 0x4037b720,
+ 0x4648: 0x4037b820, 0x4649: 0x4037b920, 0x464a: 0x4037ba20, 0x464b: 0x4037bb20,
+ 0x464c: 0x4037bc20, 0x464d: 0x4037bd20, 0x464e: 0x4037be20, 0x464f: 0x4037bf20,
+ 0x4650: 0x4037c020, 0x4651: 0x4037c120, 0x4652: 0x4037c220, 0x4653: 0x4037c320,
+ 0x4654: 0x4037c420, 0x4655: 0x4037c520, 0x4656: 0x4037c620, 0x4657: 0x4037c720,
+ 0x4658: 0x4037c820, 0x4659: 0x4037c920, 0x465a: 0x4037ca20, 0x465b: 0x4037cb20,
+ 0x465c: 0x4037cc20, 0x465d: 0x4037cd20,
+ 0x4660: 0xe000002a, 0x4661: 0xe00000a8, 0x4662: 0xe0000192, 0x4663: 0xe0000258,
+ 0x4664: 0xe000031b, 0x4665: 0xe00003d5, 0x4666: 0xe000048c, 0x4667: 0xe0000528,
+ 0x4668: 0xe00005c4, 0x4669: 0xe000065d,
+ // Block 0x11a, offset 0x4680
+ 0x4680: 0x4038a120, 0x4681: 0x4038a220, 0x4682: 0x4038a320, 0x4683: 0x4038a420,
+ 0x4684: 0x4038a520, 0x4685: 0x4038a620,
+ 0x4688: 0x4038a720, 0x468a: 0x4038a820, 0x468b: 0x4038a920,
+ 0x468c: 0x4038aa20, 0x468d: 0x4038ab20, 0x468e: 0x4038ac20, 0x468f: 0x4038ad20,
+ 0x4690: 0x4038ae20, 0x4691: 0x4038af20, 0x4692: 0x4038b020, 0x4693: 0x4038b120,
+ 0x4694: 0x4038b220, 0x4695: 0x4038b320, 0x4696: 0x4038b420, 0x4697: 0x4038b520,
+ 0x4698: 0x4038b620, 0x4699: 0x4038b720, 0x469a: 0x4038b820, 0x469b: 0x4038b920,
+ 0x469c: 0x4038ba20, 0x469d: 0x4038bb20, 0x469e: 0x4038bc20, 0x469f: 0x4038bd20,
+ 0x46a0: 0x4038be20, 0x46a1: 0x4038bf20, 0x46a2: 0x4038c020, 0x46a3: 0x4038c120,
+ 0x46a4: 0x4038c220, 0x46a5: 0x4038c320, 0x46a6: 0x4038c420, 0x46a7: 0x4038c520,
+ 0x46a8: 0x4038c620, 0x46a9: 0x4038c720, 0x46aa: 0x4038c820, 0x46ab: 0x4038c920,
+ 0x46ac: 0x4038ca20, 0x46ad: 0x4038cb20, 0x46ae: 0x4038cc20, 0x46af: 0x4038cd20,
+ 0x46b0: 0x4038ce20, 0x46b1: 0x4038cf20, 0x46b2: 0x4038d020, 0x46b3: 0x4038d120,
+ 0x46b4: 0x4038d220, 0x46b5: 0x4038d320, 0x46b7: 0x4038d420,
+ 0x46b8: 0x4038d520,
+ 0x46bc: 0x4038d620, 0x46bf: 0x4038d720,
+ // Block 0x11b, offset 0x46c0
+ 0x46c0: 0x40392a20, 0x46c1: 0x40392b20, 0x46c2: 0x40392c20, 0x46c3: 0x40392d20,
+ 0x46c4: 0x40392e20, 0x46c5: 0x40392f20, 0x46c6: 0x40393020, 0x46c7: 0x40393120,
+ 0x46c8: 0x40393220, 0x46c9: 0x40393320, 0x46ca: 0x40393420, 0x46cb: 0x40393520,
+ 0x46cc: 0x40393620, 0x46cd: 0x40393720, 0x46ce: 0x40393820, 0x46cf: 0x40393920,
+ 0x46d0: 0x40393a20, 0x46d1: 0x40393b20, 0x46d2: 0x40393c20, 0x46d3: 0x40393d20,
+ 0x46d4: 0x40393e20, 0x46d5: 0x40393f20, 0x46d7: 0x4001b520,
+ 0x46d8: 0xe0000144, 0x46d9: 0xe000022e, 0x46da: 0xe00002f4, 0x46db: 0x40146820,
+ 0x46dc: 0x40146920, 0x46dd: 0x40146a20, 0x46de: 0x40146b20, 0x46df: 0x40146c20,
+ // Block 0x11c, offset 0x4700
+ 0x4700: 0x401c0b20, 0x4701: 0x401c0c20, 0x4702: 0x401c0d20, 0x4703: 0x401c0e20,
+ 0x4704: 0x401c0f20, 0x4705: 0x401c1020, 0x4706: 0x401c1120, 0x4707: 0x401c1220,
+ 0x4708: 0x401c1320, 0x4709: 0x401c1420, 0x470a: 0x401c1520, 0x470b: 0x401c1620,
+ 0x470c: 0x401c1720, 0x470d: 0x401c1820, 0x470e: 0x401c1920, 0x470f: 0x401c1a20,
+ 0x4710: 0x401c1b20, 0x4711: 0x401c1c20, 0x4712: 0x401c1d20, 0x4713: 0x401c1e20,
+ 0x4714: 0x401c1f20, 0x4715: 0x401c2020, 0x4716: 0xe0000141, 0x4717: 0x40146520,
+ 0x4718: 0x40146620, 0x4719: 0x40146720, 0x471a: 0xe000022b, 0x471b: 0xe00002f1,
+ 0x471f: 0x4001d320,
+ 0x4720: 0x40370420, 0x4721: 0x40370520, 0x4722: 0x40370620, 0x4723: 0x40370720,
+ 0x4724: 0x40370820, 0x4725: 0x40370920, 0x4726: 0x40370a20, 0x4727: 0x40370b20,
+ 0x4728: 0x40370c20, 0x4729: 0x40370d20, 0x472a: 0x40370e20, 0x472b: 0x40370f20,
+ 0x472c: 0x40371020, 0x472d: 0x40371120, 0x472e: 0x40371220, 0x472f: 0x40371320,
+ 0x4730: 0x40371420, 0x4731: 0x40371520, 0x4732: 0x40371620, 0x4733: 0x40371720,
+ 0x4734: 0x40371820, 0x4735: 0x40371920, 0x4736: 0x40371a20, 0x4737: 0x40371b20,
+ 0x4738: 0x40371c20, 0x4739: 0x40371d20,
+ 0x473f: 0x4001ce20,
+ // Block 0x11d, offset 0x4740
+ 0x4740: 0x40236b20, 0x4741: 0x40236c20, 0x4742: 0x40236d20, 0x4743: 0x40236e20,
+ 0x4745: 0x40236f20, 0x4746: 0x40237020,
+ 0x474c: 0x40237120, 0x474d: 0x80006002, 0x474e: 0x80011302, 0x474f: 0x80011402,
+ 0x4750: 0x40237220, 0x4751: 0x40237320, 0x4752: 0x40237420, 0x4753: 0x40237520,
+ 0x4755: 0x40237620, 0x4756: 0x40237720, 0x4757: 0x40237820,
+ 0x4759: 0x40237920, 0x475a: 0x40237a20, 0x475b: 0x40237b20,
+ 0x475c: 0x40237c20, 0x475d: 0x40237d20, 0x475e: 0x40237e20, 0x475f: 0x40237f20,
+ 0x4760: 0x40238020, 0x4761: 0x40238120, 0x4762: 0x40238220, 0x4763: 0x40238320,
+ 0x4764: 0x40238420, 0x4765: 0x40238520, 0x4766: 0x40238620, 0x4767: 0x40238720,
+ 0x4768: 0x40238820, 0x4769: 0x40238920, 0x476a: 0x40238a20, 0x476b: 0x40238b20,
+ 0x476c: 0x40238c20, 0x476d: 0x40238d20, 0x476e: 0x40238e20, 0x476f: 0x40238f20,
+ 0x4770: 0x40239020, 0x4771: 0x40239120, 0x4772: 0x40239220, 0x4773: 0x40239320,
+ 0x4778: 0x80011502, 0x4779: 0x80011602, 0x477a: 0x80011702,
+ 0x477f: 0x40239420,
+ // Block 0x11e, offset 0x4780
+ 0x4780: 0xe0000153, 0x4781: 0xe000023d, 0x4782: 0xe0000303, 0x4783: 0xe00003bd,
+ 0x4784: 0x40148020, 0x4785: 0x40148120, 0x4786: 0x40148220, 0x4787: 0x40148320,
+ 0x4790: 0x4002c720, 0x4791: 0x4002c820, 0x4792: 0x4002c920, 0x4793: 0x4002ca20,
+ 0x4794: 0x4002cb20, 0x4795: 0x4002cc20, 0x4796: 0x40019920, 0x4797: 0x40019a20,
+ 0x4798: 0x4002cd20,
+ 0x47a0: 0x4038d820, 0x47a1: 0x4038d920, 0x47a2: 0x4038da20, 0x47a3: 0x4038db20,
+ 0x47a4: 0x4038dc20, 0x47a5: 0x4038dd20, 0x47a6: 0x4038de20, 0x47a7: 0x4038df20,
+ 0x47a8: 0x4038e020, 0x47a9: 0x4038e120, 0x47aa: 0x4038e220, 0x47ab: 0x4038e320,
+ 0x47ac: 0x4038e420, 0x47ad: 0x4038e520, 0x47ae: 0x4038e620, 0x47af: 0x4038e720,
+ 0x47b0: 0x4038e820, 0x47b1: 0x4038e920, 0x47b2: 0x4038ea20, 0x47b3: 0x4038eb20,
+ 0x47b4: 0x4038ec20, 0x47b5: 0x4038ed20, 0x47b6: 0x4038ee20, 0x47b7: 0x4038ef20,
+ 0x47b8: 0x4038f020, 0x47b9: 0x4038f120, 0x47ba: 0x4038f220, 0x47bb: 0x4038f320,
+ 0x47bc: 0x4038f420, 0x47bd: 0xe000013e, 0x47be: 0x40146420, 0x47bf: 0x4002ed20,
+ // Block 0x11f, offset 0x47c0
+ 0x47c0: 0x4038f520, 0x47c1: 0x4038f620, 0x47c2: 0x4038f720, 0x47c3: 0x4038f820,
+ 0x47c4: 0x4038f920, 0x47c5: 0x4038fa20, 0x47c6: 0x4038fb20, 0x47c7: 0x4038fc20,
+ 0x47c8: 0x4038fd20, 0x47c9: 0x4038fe20, 0x47ca: 0x4038ff20, 0x47cb: 0x40390020,
+ 0x47cc: 0x40390120, 0x47cd: 0x40390220, 0x47ce: 0x40390320, 0x47cf: 0x40390420,
+ 0x47d0: 0x40390520, 0x47d1: 0x40390620, 0x47d2: 0x40390720, 0x47d3: 0x40390820,
+ 0x47d4: 0x40390920, 0x47d5: 0x40390a20, 0x47d6: 0x40390b20, 0x47d7: 0x40390c20,
+ 0x47d8: 0x40390d20, 0x47d9: 0x40390e20, 0x47da: 0x40390f20, 0x47db: 0x40391020,
+ 0x47dc: 0x40391120, 0x47dd: 0x40391220, 0x47de: 0x40391320, 0x47df: 0x40391420,
+ 0x47e0: 0x40391520, 0x47e1: 0x40391620, 0x47e2: 0x40391720, 0x47e3: 0x40391820,
+ 0x47e4: 0x40391920, 0x47e5: 0x40391a20, 0x47e6: 0x40391b20, 0x47e7: 0x40391c20,
+ 0x47e8: 0x40391d20, 0x47e9: 0x40391e20, 0x47ea: 0x40391f20, 0x47eb: 0x40392020,
+ 0x47ec: 0x40392120, 0x47ed: 0x40392220, 0x47ee: 0xe0001186, 0x47ef: 0x40392320,
+ 0x47f0: 0x40392420, 0x47f1: 0x40392520, 0x47f2: 0x40392620, 0x47f3: 0x40392720,
+ 0x47f4: 0x40392820, 0x47f5: 0x40392920,
+ 0x47f9: 0x4002ce20, 0x47fa: 0x4001b620, 0x47fb: 0x4001b720,
+ 0x47fc: 0x4001b820, 0x47fd: 0x4001b920, 0x47fe: 0x4001ba20, 0x47ff: 0x4001bb20,
+ // Block 0x120, offset 0x4800
+ 0x4800: 0x40394020, 0x4801: 0x40394120, 0x4802: 0x40394220, 0x4803: 0x40394320,
+ 0x4804: 0x40394420, 0x4805: 0x40394520, 0x4806: 0x40394620, 0x4807: 0x40394720,
+ 0x4808: 0x40394820, 0x4809: 0x40394920, 0x480a: 0x40394a20, 0x480b: 0x40394b20,
+ 0x480c: 0x40394c20, 0x480d: 0x40394d20, 0x480e: 0x40394e20, 0x480f: 0x40394f20,
+ 0x4810: 0x40395020, 0x4811: 0x40395120, 0x4812: 0x40395220, 0x4813: 0x40395320,
+ 0x4814: 0x40395420, 0x4815: 0x40395520,
+ 0x4818: 0xe0000147, 0x4819: 0xe0000231, 0x481a: 0xe00002f7, 0x481b: 0xe00003b1,
+ 0x481c: 0x40146d20, 0x481d: 0x40146e20, 0x481e: 0x40146f20, 0x481f: 0x40147020,
+ 0x4820: 0x40395620, 0x4821: 0x40395720, 0x4822: 0x40395820, 0x4823: 0x40395920,
+ 0x4824: 0x40395a20, 0x4825: 0x40395b20, 0x4826: 0x40395c20, 0x4827: 0x40395d20,
+ 0x4828: 0x40395e20, 0x4829: 0x40395f20, 0x482a: 0x40396020, 0x482b: 0x40396120,
+ 0x482c: 0x40396220, 0x482d: 0x40396320, 0x482e: 0x40396420, 0x482f: 0x40396520,
+ 0x4830: 0x40396620, 0x4831: 0x40396720, 0x4832: 0x40396820,
+ 0x4838: 0xe000014a, 0x4839: 0xe0000234, 0x483a: 0xe00002fa, 0x483b: 0xe00003b4,
+ 0x483c: 0x40147120, 0x483d: 0x40147220, 0x483e: 0x40147320, 0x483f: 0x40147420,
+ // Block 0x121, offset 0x4840
+ 0x4840: 0x402c6e20, 0x4841: 0xe00010de, 0x4842: 0x402c6f20, 0x4843: 0x402c7020,
+ 0x4844: 0xe00010e1, 0x4845: 0x402c7120, 0x4846: 0x402c7220, 0x4847: 0x402c7320,
+ 0x4848: 0xe00010e4, 0x4849: 0x402c7420, 0x484a: 0xe00010e7, 0x484b: 0x402c7520,
+ 0x484c: 0xe00010ea, 0x484d: 0x402c7620, 0x484e: 0xe00010ed, 0x484f: 0x402c7720,
+ 0x4850: 0xe00010f0, 0x4851: 0x402c7820, 0x4852: 0xe00010f3, 0x4853: 0x402c7920,
+ 0x4854: 0x402c7a20, 0x4855: 0xe00010f6, 0x4856: 0x402c7b20, 0x4857: 0xe00010f9,
+ 0x4858: 0x402c7c20, 0x4859: 0xe00010fc, 0x485a: 0x402c7d20, 0x485b: 0xe00010ff,
+ 0x485c: 0x402c7e20, 0x485d: 0xe0001102, 0x485e: 0x402c7f20, 0x485f: 0xe0001105,
+ 0x4860: 0x402c8020, 0x4861: 0x402c8120, 0x4862: 0x402c8220, 0x4863: 0x402c8320,
+ 0x4864: 0x402c8420, 0x4865: 0xe0001108, 0x4866: 0x402c8520, 0x4867: 0xe000110b,
+ 0x4868: 0x402c8620, 0x4869: 0xe000110e, 0x486a: 0x402c8720, 0x486b: 0xe0001111,
+ 0x486c: 0x402c8820, 0x486d: 0x402c8920, 0x486e: 0xe0001114, 0x486f: 0x402c8a20,
+ 0x4870: 0x402c8b20, 0x4871: 0x402c8c20, 0x4872: 0x402c8d20, 0x4873: 0xe0001117,
+ 0x4874: 0x402c8e20, 0x4875: 0xe000111a, 0x4876: 0x402c8f20, 0x4877: 0xe000111d,
+ 0x4878: 0x402c9020, 0x4879: 0xe0001120, 0x487a: 0x402c9120, 0x487b: 0xe0001123,
+ 0x487c: 0x402c9220, 0x487d: 0x402c9320, 0x487e: 0x402c9420, 0x487f: 0x402c9520,
+ // Block 0x122, offset 0x4880
+ 0x4880: 0xe0001126, 0x4881: 0x402c9620, 0x4882: 0xe0001129, 0x4883: 0x402c9720,
+ 0x4884: 0xe000112c, 0x4885: 0x402c9820, 0x4886: 0xe000112f, 0x4887: 0x402c9920,
+ 0x4888: 0x402c9a20,
+ // Block 0x123, offset 0x48c0
+ 0x48e0: 0xe000009f, 0x48e1: 0xe0000189, 0x48e2: 0xe000024f, 0x48e3: 0xe0000312,
+ 0x48e4: 0xe00003cc, 0x48e5: 0xe0000483, 0x48e6: 0xe000051f, 0x48e7: 0xe00005bb,
+ 0x48e8: 0xe0000654, 0x48e9: 0x4013f820, 0x48ea: 0x4013f920, 0x48eb: 0x4013fa20,
+ 0x48ec: 0x4013fb20, 0x48ed: 0x4013fc20, 0x48ee: 0x4013fd20, 0x48ef: 0x4013fe20,
+ 0x48f0: 0x4013ff20, 0x48f1: 0x40140020, 0x48f2: 0x40140120, 0x48f3: 0x40140220,
+ 0x48f4: 0x40140320, 0x48f5: 0x40140420, 0x48f6: 0x40140520, 0x48f7: 0x40140620,
+ 0x48f8: 0x40140720, 0x48f9: 0x40140820, 0x48fa: 0x40140920, 0x48fb: 0x40140a20,
+ 0x48fc: 0x40140b20, 0x48fd: 0x40140c20, 0x48fe: 0x40140d20,
+ // Block 0x124, offset 0x4900
+ 0x4900: 0x80011002, 0x4901: 0x80011102, 0x4902: 0x80011202, 0x4903: 0x40235620,
+ 0x4904: 0x40235720, 0x4905: 0x40232720, 0x4906: 0x40232820, 0x4907: 0x40232920,
+ 0x4908: 0x40232a20, 0x4909: 0x40232b20, 0x490a: 0x40232c20, 0x490b: 0x40232d20,
+ 0x490c: 0x40232e20, 0x490d: 0x40232f20, 0x490e: 0x40233020, 0x490f: 0x40233120,
+ 0x4910: 0x40233220, 0x4911: 0x40233320, 0x4912: 0x40233420, 0x4913: 0x40233520,
+ 0x4914: 0x40233620, 0x4915: 0x40233720, 0x4916: 0x40233820, 0x4917: 0x40233920,
+ 0x4918: 0x40233a20, 0x4919: 0x40233b20, 0x491a: 0x40233c20, 0x491b: 0x40233d20,
+ 0x491c: 0x40233e20, 0x491d: 0x40233f20, 0x491e: 0x40234020, 0x491f: 0x40234120,
+ 0x4920: 0x40234220, 0x4921: 0x40234320, 0x4922: 0x40234420, 0x4923: 0x40234520,
+ 0x4924: 0x40234620, 0x4925: 0x40234720, 0x4926: 0x40234820, 0x4927: 0x40234920,
+ 0x4928: 0x40234a20, 0x4929: 0x40234b20, 0x492a: 0x40234c20, 0x492b: 0x40234d20,
+ 0x492c: 0x40234e20, 0x492d: 0x40234f20, 0x492e: 0x40235020, 0x492f: 0x40235120,
+ 0x4930: 0x40235220, 0x4931: 0x40235320, 0x4932: 0x40235420, 0x4933: 0x40235520,
+ 0x4934: 0x40235820, 0x4935: 0x40235920, 0x4936: 0x40235a20, 0x4937: 0x40235b20,
+ 0x4938: 0x40235c20, 0x4939: 0x40235d20, 0x493a: 0x40235e20, 0x493b: 0x40235f20,
+ 0x493c: 0x40236020, 0x493d: 0x40236120, 0x493e: 0x40236220, 0x493f: 0x40236320,
+ // Block 0x125, offset 0x4940
+ 0x4940: 0x40236420, 0x4941: 0x40236520, 0x4942: 0x40236620, 0x4943: 0x40236720,
+ 0x4944: 0x40236820, 0x4945: 0x40236920, 0x4946: 0x40236a20, 0x4947: 0x40019b20,
+ 0x4948: 0x40019c20, 0x4949: 0x4002c220, 0x494a: 0x4002c320, 0x494b: 0x4002c420,
+ 0x494c: 0x4002c520, 0x494d: 0x4002c620,
+ 0x4952: 0xe0000150, 0x4953: 0xe000023a,
+ 0x4954: 0xe0000300, 0x4955: 0xe00003ba, 0x4956: 0xe0000474, 0x4957: 0xe0000510,
+ 0x4958: 0xe00005ac, 0x4959: 0xe0000645, 0x495a: 0xe00006e4, 0x495b: 0x40147520,
+ 0x495c: 0x40147620, 0x495d: 0x40147720, 0x495e: 0x40147820, 0x495f: 0x40147920,
+ 0x4960: 0x40147a20, 0x4961: 0x40147b20, 0x4962: 0x40147c20, 0x4963: 0x40147d20,
+ 0x4964: 0x40147e20, 0x4965: 0x40147f20, 0x4966: 0xe0000096, 0x4967: 0xe000014d,
+ 0x4968: 0xe0000237, 0x4969: 0xe00002fd, 0x496a: 0xe00003b7, 0x496b: 0xe0000471,
+ 0x496c: 0xe000050d, 0x496d: 0xe00005a9, 0x496e: 0xe0000642, 0x496f: 0xe00006e1,
+ // Block 0x126, offset 0x4980
+ 0x4980: 0x80011902, 0x4981: 0x80011a02, 0x4982: 0x80011b02, 0x4983: 0x4022c920,
+ 0x4984: 0x4022ca20, 0x4985: 0x4022cb20, 0x4986: 0x4022cc20, 0x4987: 0x4022cd20,
+ 0x4988: 0x4022ce20, 0x4989: 0x4022cf20, 0x498a: 0x4022d020, 0x498b: 0x4022d120,
+ 0x498c: 0x4022d220, 0x498d: 0x4022d320, 0x498e: 0x4022d420, 0x498f: 0x4022d520,
+ 0x4990: 0x4022d620, 0x4991: 0x4022d720, 0x4992: 0x4022d820, 0x4993: 0x4022d920,
+ 0x4994: 0x4022da20, 0x4995: 0x4022db20, 0x4996: 0x4022dc20, 0x4997: 0x4022dd20,
+ 0x4998: 0x4022de20, 0x4999: 0x4022df20, 0x499b: 0x4022e020,
+ 0x499d: 0x4022e120, 0x499e: 0x4022e220, 0x499f: 0x4022e320,
+ 0x49a0: 0x4022e420, 0x49a1: 0x4022e520, 0x49a2: 0x4022e620, 0x49a3: 0x4022e720,
+ 0x49a4: 0x4022e820, 0x49a5: 0x4022e920, 0x49a6: 0x4022ea20, 0x49a7: 0x4022eb20,
+ 0x49a8: 0x4022ec20, 0x49a9: 0x4022ed20, 0x49aa: 0x4022ee20,
+ 0x49ac: 0x4022ef20, 0x49ad: 0x4022f020, 0x49ae: 0x4022f120, 0x49af: 0x4022f220,
+ 0x49b0: 0x4022f320, 0x49b1: 0x4022f420, 0x49b2: 0x4022f520, 0x49b3: 0x4022f620,
+ 0x49b4: 0x4022f720, 0x49b5: 0x4022f820, 0x49b6: 0x4022f920, 0x49b7: 0x4022fa20,
+ 0x49b8: 0x4022fb20, 0x49b9: 0x4022fc20, 0x49ba: 0x80011802, 0x49bb: 0x4002cf20,
+ 0x49bc: 0x4002d020, 0x49bd: 0x80000000, 0x49be: 0x4001bc20, 0x49bf: 0x4001bd20,
+ // Block 0x127, offset 0x49c0
+ 0x49c0: 0x40019d20, 0x49c1: 0x40019e20,
+ // Block 0x128, offset 0x4a00
+ 0x4a00: 0x4039b320, 0x4a01: 0x4039b420, 0x4a02: 0x4039b520, 0x4a03: 0x4039b620,
+ 0x4a04: 0x4039b720, 0x4a05: 0x4039b820, 0x4a06: 0x4039b920, 0x4a07: 0x4039ba20,
+ 0x4a08: 0x4039bb20, 0x4a09: 0x4039bc20, 0x4a0a: 0x4039bd20, 0x4a0b: 0x4039be20,
+ 0x4a0c: 0x4039bf20, 0x4a0d: 0x4039c020, 0x4a0e: 0x4039c120, 0x4a0f: 0x4039c220,
+ 0x4a10: 0x4039c320, 0x4a11: 0x4039c420, 0x4a12: 0x4039c520, 0x4a13: 0x4039c620,
+ 0x4a14: 0x4039c720, 0x4a15: 0x4039c820, 0x4a16: 0x4039c920, 0x4a17: 0x4039ca20,
+ 0x4a18: 0x4039cb20, 0x4a19: 0x4039cc20, 0x4a1a: 0x4039cd20, 0x4a1b: 0x4039ce20,
+ 0x4a1c: 0x4039cf20, 0x4a1d: 0x4039d020, 0x4a1e: 0x4039d120, 0x4a1f: 0x4039d220,
+ 0x4a20: 0x4039d320, 0x4a21: 0x4039d420, 0x4a22: 0x4039d520, 0x4a23: 0x4039d620,
+ 0x4a24: 0x4039d720, 0x4a25: 0x4039d820, 0x4a26: 0x4039d920, 0x4a27: 0x4039da20,
+ 0x4a28: 0x4039db20, 0x4a29: 0x4039dc20, 0x4a2a: 0x4039dd20, 0x4a2b: 0x4039de20,
+ 0x4a2c: 0x4039df20, 0x4a2d: 0x4039e020, 0x4a2e: 0x4039e120, 0x4a2f: 0x4039e220,
+ 0x4a30: 0x4039e320, 0x4a31: 0x4039e420, 0x4a32: 0x4039e520, 0x4a33: 0x4039e620,
+ 0x4a34: 0x4039e720, 0x4a35: 0x4039e820, 0x4a36: 0x4039e920, 0x4a37: 0x4039ea20,
+ 0x4a38: 0x4039eb20, 0x4a39: 0x4039ec20, 0x4a3a: 0x4039ed20, 0x4a3b: 0x4039ee20,
+ 0x4a3c: 0x4039ef20, 0x4a3d: 0x4039f020, 0x4a3e: 0x4039f120, 0x4a3f: 0x4039f220,
+ // Block 0x129, offset 0x4a40
+ 0x4a40: 0x4039f320, 0x4a41: 0x4039f420, 0x4a42: 0x4039f520, 0x4a43: 0x4039f620,
+ 0x4a44: 0x4039f720, 0x4a45: 0x4039f820, 0x4a46: 0x4039f920, 0x4a47: 0x4039fa20,
+ 0x4a48: 0x4039fb20, 0x4a49: 0x4039fc20, 0x4a4a: 0x4039fd20, 0x4a4b: 0x4039fe20,
+ 0x4a4c: 0x4039ff20, 0x4a4d: 0x403a0020, 0x4a4e: 0x403a0120, 0x4a4f: 0x403a0220,
+ 0x4a50: 0x403a0320, 0x4a51: 0x403a0420, 0x4a52: 0x403a0520, 0x4a53: 0x403a0620,
+ 0x4a54: 0x403a0720, 0x4a55: 0x403a0820, 0x4a56: 0x403a0920, 0x4a57: 0x403a0a20,
+ 0x4a58: 0x403a0b20, 0x4a59: 0x403a0c20, 0x4a5a: 0x403a0d20, 0x4a5b: 0x403a0e20,
+ 0x4a5c: 0x403a0f20, 0x4a5d: 0x403a1020, 0x4a5e: 0x403a1120, 0x4a5f: 0x403a1220,
+ 0x4a60: 0x403a1320, 0x4a61: 0x403a1420, 0x4a62: 0x403a1520, 0x4a63: 0x403a1620,
+ 0x4a64: 0x403a1720, 0x4a65: 0x403a1820, 0x4a66: 0x403a1920, 0x4a67: 0x403a1a20,
+ 0x4a68: 0x403a1b20, 0x4a69: 0x403a1c20, 0x4a6a: 0x403a1d20, 0x4a6b: 0x403a1e20,
+ 0x4a6c: 0x403a1f20, 0x4a6d: 0x403a2020, 0x4a6e: 0x403a2120, 0x4a6f: 0x403a2220,
+ 0x4a70: 0x403a2320, 0x4a71: 0x403a2420, 0x4a72: 0x403a2520, 0x4a73: 0x403a2620,
+ 0x4a74: 0x403a2720, 0x4a75: 0x403a2820, 0x4a76: 0x403a2920, 0x4a77: 0x403a2a20,
+ 0x4a78: 0x403a2b20, 0x4a79: 0x403a2c20, 0x4a7a: 0x403a2d20, 0x4a7b: 0x403a2e20,
+ 0x4a7c: 0x403a2f20, 0x4a7d: 0x403a3020, 0x4a7e: 0x403a3120, 0x4a7f: 0x403a3220,
+ // Block 0x12a, offset 0x4a80
+ 0x4a80: 0x403a3320, 0x4a81: 0x403a3420, 0x4a82: 0x403a3520, 0x4a83: 0x403a3620,
+ 0x4a84: 0x403a3720, 0x4a85: 0x403a3820, 0x4a86: 0x403a3920, 0x4a87: 0x403a3a20,
+ 0x4a88: 0x403a3b20, 0x4a89: 0x403a3c20, 0x4a8a: 0x403a3d20, 0x4a8b: 0x403a3e20,
+ 0x4a8c: 0x403a3f20, 0x4a8d: 0x403a4020, 0x4a8e: 0x403a4120, 0x4a8f: 0x403a4220,
+ 0x4a90: 0x403a4320, 0x4a91: 0x403a4420, 0x4a92: 0x403a4520, 0x4a93: 0x403a4620,
+ 0x4a94: 0x403a4720, 0x4a95: 0x403a4820, 0x4a96: 0x403a4920, 0x4a97: 0x403a4a20,
+ 0x4a98: 0x403a4b20, 0x4a99: 0x403a4c20, 0x4a9a: 0x403a4d20, 0x4a9b: 0x403a4e20,
+ 0x4a9c: 0x403a4f20, 0x4a9d: 0x403a5020, 0x4a9e: 0x403a5120, 0x4a9f: 0x403a5220,
+ 0x4aa0: 0x403a5320, 0x4aa1: 0x403a5420, 0x4aa2: 0x403a5520, 0x4aa3: 0x403a5620,
+ 0x4aa4: 0x403a5720, 0x4aa5: 0x403a5820, 0x4aa6: 0x403a5920, 0x4aa7: 0x403a5a20,
+ 0x4aa8: 0x403a5b20, 0x4aa9: 0x403a5c20, 0x4aaa: 0x403a5d20, 0x4aab: 0x403a5e20,
+ 0x4aac: 0x403a5f20, 0x4aad: 0x403a6020, 0x4aae: 0x403a6120, 0x4aaf: 0x403a6220,
+ 0x4ab0: 0x403a6320, 0x4ab1: 0x403a6420, 0x4ab2: 0x403a6520, 0x4ab3: 0x403a6620,
+ 0x4ab4: 0x403a6720, 0x4ab5: 0x403a6820, 0x4ab6: 0x403a6920, 0x4ab7: 0x403a6a20,
+ 0x4ab8: 0x403a6b20, 0x4ab9: 0x403a6c20, 0x4aba: 0x403a6d20, 0x4abb: 0x403a6e20,
+ 0x4abc: 0x403a6f20, 0x4abd: 0x403a7020, 0x4abe: 0x403a7120, 0x4abf: 0x403a7220,
+ // Block 0x12b, offset 0x4ac0
+ 0x4ac0: 0x403a7320, 0x4ac1: 0x403a7420, 0x4ac2: 0x403a7520, 0x4ac3: 0x403a7620,
+ 0x4ac4: 0x403a7720, 0x4ac5: 0x403a7820, 0x4ac6: 0x403a7920, 0x4ac7: 0x403a7a20,
+ 0x4ac8: 0x403a7b20, 0x4ac9: 0x403a7c20, 0x4aca: 0x403a7d20, 0x4acb: 0x403a7e20,
+ 0x4acc: 0x403a7f20, 0x4acd: 0x403a8020, 0x4ace: 0x403a8120, 0x4acf: 0x403a8220,
+ 0x4ad0: 0x403a8320, 0x4ad1: 0x403a8420, 0x4ad2: 0x403a8520, 0x4ad3: 0x403a8620,
+ 0x4ad4: 0x403a8720, 0x4ad5: 0x403a8820, 0x4ad6: 0x403a8920, 0x4ad7: 0x403a8a20,
+ 0x4ad8: 0x403a8b20, 0x4ad9: 0x403a8c20, 0x4ada: 0x403a8d20, 0x4adb: 0x403a8e20,
+ 0x4adc: 0x403a8f20, 0x4add: 0x403a9020, 0x4ade: 0x403a9120, 0x4adf: 0x403a9220,
+ 0x4ae0: 0x403a9320, 0x4ae1: 0x403a9420, 0x4ae2: 0x403a9520, 0x4ae3: 0x403a9620,
+ 0x4ae4: 0x403a9720, 0x4ae5: 0x403a9820, 0x4ae6: 0x403a9920, 0x4ae7: 0x403a9a20,
+ 0x4ae8: 0x403a9b20, 0x4ae9: 0x403a9c20, 0x4aea: 0x403a9d20, 0x4aeb: 0x403a9e20,
+ 0x4aec: 0x403a9f20, 0x4aed: 0x403aa020, 0x4aee: 0x403aa120, 0x4aef: 0x403aa220,
+ 0x4af0: 0x403aa320, 0x4af1: 0x403aa420, 0x4af2: 0x403aa520, 0x4af3: 0x403aa620,
+ 0x4af4: 0x403aa720, 0x4af5: 0x403aa820, 0x4af6: 0x403aa920, 0x4af7: 0x403aaa20,
+ 0x4af8: 0x403aab20, 0x4af9: 0x403aac20, 0x4afa: 0x403aad20, 0x4afb: 0x403aae20,
+ 0x4afc: 0x403aaf20, 0x4afd: 0x403ab020, 0x4afe: 0x403ab120, 0x4aff: 0x403ab220,
+ // Block 0x12c, offset 0x4b00
+ 0x4b00: 0x403ab320, 0x4b01: 0x403ab420, 0x4b02: 0x403ab520, 0x4b03: 0x403ab620,
+ 0x4b04: 0x403ab720, 0x4b05: 0x403ab820, 0x4b06: 0x403ab920, 0x4b07: 0x403aba20,
+ 0x4b08: 0x403abb20, 0x4b09: 0x403abc20, 0x4b0a: 0x403abd20, 0x4b0b: 0x403abe20,
+ 0x4b0c: 0x403abf20, 0x4b0d: 0x403ac020, 0x4b0e: 0x403ac120, 0x4b0f: 0x403ac220,
+ 0x4b10: 0x403ac320, 0x4b11: 0x403ac420, 0x4b12: 0x403ac520, 0x4b13: 0x403ac620,
+ 0x4b14: 0x403ac720, 0x4b15: 0x403ac820, 0x4b16: 0x403ac920, 0x4b17: 0x403aca20,
+ 0x4b18: 0x403acb20, 0x4b19: 0x403acc20, 0x4b1a: 0x403acd20, 0x4b1b: 0x403ace20,
+ 0x4b1c: 0x403acf20, 0x4b1d: 0x403ad020, 0x4b1e: 0x403ad120, 0x4b1f: 0x403ad220,
+ 0x4b20: 0x403ad320, 0x4b21: 0x403ad420, 0x4b22: 0x403ad520, 0x4b23: 0x403ad620,
+ 0x4b24: 0x403ad720, 0x4b25: 0x403ad820, 0x4b26: 0x403ad920, 0x4b27: 0x403ada20,
+ 0x4b28: 0x403adb20, 0x4b29: 0x403adc20, 0x4b2a: 0x403add20, 0x4b2b: 0x403ade20,
+ 0x4b2c: 0x403adf20, 0x4b2d: 0x403ae020, 0x4b2e: 0x403ae120, 0x4b2f: 0x403ae220,
+ 0x4b30: 0x403ae320, 0x4b31: 0x403ae420, 0x4b32: 0x403ae520, 0x4b33: 0x403ae620,
+ 0x4b34: 0x403ae720, 0x4b35: 0x403ae820, 0x4b36: 0x403ae920, 0x4b37: 0x403aea20,
+ 0x4b38: 0x403aeb20, 0x4b39: 0x403aec20, 0x4b3a: 0x403aed20, 0x4b3b: 0x403aee20,
+ 0x4b3c: 0x403aef20, 0x4b3d: 0x403af020, 0x4b3e: 0x403af120, 0x4b3f: 0x403af220,
+ // Block 0x12d, offset 0x4b40
+ 0x4b40: 0x403af320, 0x4b41: 0x403af420, 0x4b42: 0x403af520, 0x4b43: 0x403af620,
+ 0x4b44: 0x403af720, 0x4b45: 0x403af820, 0x4b46: 0x403af920, 0x4b47: 0x403afa20,
+ 0x4b48: 0x403afb20, 0x4b49: 0x403afc20, 0x4b4a: 0x403afd20, 0x4b4b: 0x403afe20,
+ 0x4b4c: 0x403aff20, 0x4b4d: 0x403b0020, 0x4b4e: 0x403b0120, 0x4b4f: 0x403b0220,
+ 0x4b50: 0x403b0320, 0x4b51: 0x403b0420, 0x4b52: 0x403b0520, 0x4b53: 0x403b0620,
+ 0x4b54: 0x403b0720, 0x4b55: 0x403b0820, 0x4b56: 0x403b0920, 0x4b57: 0x403b0a20,
+ 0x4b58: 0x403b0b20, 0x4b59: 0x403b0c20, 0x4b5a: 0x403b0d20, 0x4b5b: 0x403b0e20,
+ 0x4b5c: 0x403b0f20, 0x4b5d: 0x403b1020, 0x4b5e: 0x403b1120, 0x4b5f: 0x403b1220,
+ 0x4b60: 0x403b1320, 0x4b61: 0x403b1420, 0x4b62: 0x403b1520, 0x4b63: 0x403b1620,
+ 0x4b64: 0x403b1720, 0x4b65: 0x403b1820, 0x4b66: 0x403b1920, 0x4b67: 0x403b1a20,
+ 0x4b68: 0x403b1b20, 0x4b69: 0x403b1c20, 0x4b6a: 0x403b1d20, 0x4b6b: 0x403b1e20,
+ 0x4b6c: 0x403b1f20, 0x4b6d: 0x403b2020, 0x4b6e: 0x403b2120, 0x4b6f: 0x403b2220,
+ 0x4b70: 0x403b2320, 0x4b71: 0x403b2420, 0x4b72: 0x403b2520, 0x4b73: 0x403b2620,
+ 0x4b74: 0x403b2720, 0x4b75: 0x403b2820, 0x4b76: 0x403b2920, 0x4b77: 0x403b2a20,
+ 0x4b78: 0x403b2b20, 0x4b79: 0x403b2c20, 0x4b7a: 0x403b2d20, 0x4b7b: 0x403b2e20,
+ 0x4b7c: 0x403b2f20, 0x4b7d: 0x403b3020, 0x4b7e: 0x403b3120, 0x4b7f: 0x403b3220,
+ // Block 0x12e, offset 0x4b80
+ 0x4b80: 0x403b3320, 0x4b81: 0x403b3420, 0x4b82: 0x403b3520, 0x4b83: 0x403b3620,
+ 0x4b84: 0x403b3720, 0x4b85: 0x403b3820, 0x4b86: 0x403b3920, 0x4b87: 0x403b3a20,
+ 0x4b88: 0x403b3b20, 0x4b89: 0x403b3c20, 0x4b8a: 0x403b3d20, 0x4b8b: 0x403b3e20,
+ 0x4b8c: 0x403b3f20, 0x4b8d: 0x403b4020, 0x4b8e: 0x403b4120, 0x4b8f: 0x403b4220,
+ 0x4b90: 0x403b4320, 0x4b91: 0x403b4420, 0x4b92: 0x403b4520, 0x4b93: 0x403b4620,
+ 0x4b94: 0x403b4720, 0x4b95: 0x403b4820, 0x4b96: 0x403b4920, 0x4b97: 0x403b4a20,
+ 0x4b98: 0x403b4b20, 0x4b99: 0x403b4c20, 0x4b9a: 0x403b4d20, 0x4b9b: 0x403b4e20,
+ 0x4b9c: 0x403b4f20, 0x4b9d: 0x403b5020, 0x4b9e: 0x403b5120, 0x4b9f: 0x403b5220,
+ 0x4ba0: 0x403b5320, 0x4ba1: 0x403b5420, 0x4ba2: 0x403b5520, 0x4ba3: 0x403b5620,
+ 0x4ba4: 0x403b5720, 0x4ba5: 0x403b5820, 0x4ba6: 0x403b5920, 0x4ba7: 0x403b5a20,
+ 0x4ba8: 0x403b5b20, 0x4ba9: 0x403b5c20, 0x4baa: 0x403b5d20, 0x4bab: 0x403b5e20,
+ 0x4bac: 0x403b5f20, 0x4bad: 0x403b6020, 0x4bae: 0x403b6120, 0x4baf: 0x403b6220,
+ 0x4bb0: 0x403b6320, 0x4bb1: 0x403b6420, 0x4bb2: 0x403b6520, 0x4bb3: 0x403b6620,
+ 0x4bb4: 0x403b6720, 0x4bb5: 0x403b6820, 0x4bb6: 0x403b6920, 0x4bb7: 0x403b6a20,
+ 0x4bb8: 0x403b6b20, 0x4bb9: 0x403b6c20, 0x4bba: 0x403b6d20, 0x4bbb: 0x403b6e20,
+ 0x4bbc: 0x403b6f20, 0x4bbd: 0x403b7020, 0x4bbe: 0x403b7120, 0x4bbf: 0x403b7220,
+ // Block 0x12f, offset 0x4bc0
+ 0x4bc0: 0x403b7320, 0x4bc1: 0x403b7420, 0x4bc2: 0x403b7520, 0x4bc3: 0x403b7620,
+ 0x4bc4: 0x403b7720, 0x4bc5: 0x403b7820, 0x4bc6: 0x403b7920, 0x4bc7: 0x403b7a20,
+ 0x4bc8: 0x403b7b20, 0x4bc9: 0x403b7c20, 0x4bca: 0x403b7d20, 0x4bcb: 0x403b7e20,
+ 0x4bcc: 0x403b7f20, 0x4bcd: 0x403b8020, 0x4bce: 0x403b8120, 0x4bcf: 0x403b8220,
+ 0x4bd0: 0x403b8320, 0x4bd1: 0x403b8420, 0x4bd2: 0x403b8520, 0x4bd3: 0x403b8620,
+ 0x4bd4: 0x403b8720, 0x4bd5: 0x403b8820, 0x4bd6: 0x403b8920, 0x4bd7: 0x403b8a20,
+ 0x4bd8: 0x403b8b20, 0x4bd9: 0x403b8c20, 0x4bda: 0x403b8d20, 0x4bdb: 0x403b8e20,
+ 0x4bdc: 0x403b8f20, 0x4bdd: 0x403b9020, 0x4bde: 0x403b9120, 0x4bdf: 0x403b9220,
+ 0x4be0: 0x403b9320, 0x4be1: 0x403b9420, 0x4be2: 0x403b9520, 0x4be3: 0x403b9620,
+ 0x4be4: 0x403b9720, 0x4be5: 0x403b9820, 0x4be6: 0x403b9920, 0x4be7: 0x403b9a20,
+ 0x4be8: 0x403b9b20, 0x4be9: 0x403b9c20, 0x4bea: 0x403b9d20, 0x4beb: 0x403b9e20,
+ 0x4bec: 0x403b9f20, 0x4bed: 0x403ba020, 0x4bee: 0x403ba120, 0x4bef: 0x403ba220,
+ 0x4bf0: 0x403ba320, 0x4bf1: 0x403ba420, 0x4bf2: 0x403ba520, 0x4bf3: 0x403ba620,
+ 0x4bf4: 0x403ba720, 0x4bf5: 0x403ba820, 0x4bf6: 0x403ba920, 0x4bf7: 0x403baa20,
+ 0x4bf8: 0x403bab20, 0x4bf9: 0x403bac20, 0x4bfa: 0x403bad20, 0x4bfb: 0x403bae20,
+ 0x4bfc: 0x403baf20, 0x4bfd: 0x403bb020, 0x4bfe: 0x403bb120, 0x4bff: 0x403bb220,
+ // Block 0x130, offset 0x4c00
+ 0x4c00: 0x403bb320, 0x4c01: 0x403bb420, 0x4c02: 0x403bb520, 0x4c03: 0x403bb620,
+ 0x4c04: 0x403bb720, 0x4c05: 0x403bb820, 0x4c06: 0x403bb920, 0x4c07: 0x403bba20,
+ 0x4c08: 0x403bbb20, 0x4c09: 0x403bbc20, 0x4c0a: 0x403bbd20, 0x4c0b: 0x403bbe20,
+ 0x4c0c: 0x403bbf20, 0x4c0d: 0x403bc020, 0x4c0e: 0x403bc120, 0x4c0f: 0x403bc220,
+ 0x4c10: 0x403bc320, 0x4c11: 0x403bc420, 0x4c12: 0x403bc520, 0x4c13: 0x403bc620,
+ 0x4c14: 0x403bc720, 0x4c15: 0x403bc820, 0x4c16: 0x403bc920, 0x4c17: 0x403bca20,
+ 0x4c18: 0x403bcb20, 0x4c19: 0x403bcc20, 0x4c1a: 0x403bcd20, 0x4c1b: 0x403bce20,
+ 0x4c1c: 0x403bcf20, 0x4c1d: 0x403bd020, 0x4c1e: 0x403bd120, 0x4c1f: 0x403bd220,
+ 0x4c20: 0x403bd320, 0x4c21: 0x403bd420, 0x4c22: 0x403bd520, 0x4c23: 0x403bd620,
+ 0x4c24: 0x403bd720, 0x4c25: 0x403bd820, 0x4c26: 0x403bd920, 0x4c27: 0x403bda20,
+ 0x4c28: 0x403bdb20, 0x4c29: 0x403bdc20, 0x4c2a: 0x403bdd20, 0x4c2b: 0x403bde20,
+ 0x4c2c: 0x403bdf20, 0x4c2d: 0x403be020, 0x4c2e: 0x403be120, 0x4c2f: 0x403be220,
+ 0x4c30: 0x403be320, 0x4c31: 0x403be420, 0x4c32: 0x403be520, 0x4c33: 0x403be620,
+ 0x4c34: 0x403be720, 0x4c35: 0x403be820, 0x4c36: 0x403be920, 0x4c37: 0x403bea20,
+ 0x4c38: 0x403beb20, 0x4c39: 0x403bec20, 0x4c3a: 0x403bed20, 0x4c3b: 0x403bee20,
+ 0x4c3c: 0x403bef20, 0x4c3d: 0x403bf020, 0x4c3e: 0x403bf120, 0x4c3f: 0x403bf220,
+ // Block 0x131, offset 0x4c40
+ 0x4c40: 0x403bf320, 0x4c41: 0x403bf420, 0x4c42: 0x403bf520, 0x4c43: 0x403bf620,
+ 0x4c44: 0x403bf720, 0x4c45: 0x403bf820, 0x4c46: 0x403bf920, 0x4c47: 0x403bfa20,
+ 0x4c48: 0x403bfb20, 0x4c49: 0x403bfc20, 0x4c4a: 0x403bfd20, 0x4c4b: 0x403bfe20,
+ 0x4c4c: 0x403bff20, 0x4c4d: 0x403c0020, 0x4c4e: 0x403c0120, 0x4c4f: 0x403c0220,
+ 0x4c50: 0x403c0320, 0x4c51: 0x403c0420, 0x4c52: 0x403c0520, 0x4c53: 0x403c0620,
+ 0x4c54: 0x403c0720, 0x4c55: 0x403c0820, 0x4c56: 0x403c0920, 0x4c57: 0x403c0a20,
+ 0x4c58: 0x403c0b20, 0x4c59: 0x403c0c20, 0x4c5a: 0x403c0d20, 0x4c5b: 0x403c0e20,
+ 0x4c5c: 0x403c0f20, 0x4c5d: 0x403c1020, 0x4c5e: 0x403c1120, 0x4c5f: 0x403c1220,
+ 0x4c60: 0x403c1320, 0x4c61: 0x403c1420, 0x4c62: 0x403c1520, 0x4c63: 0x403c1620,
+ 0x4c64: 0x403c1720, 0x4c65: 0x403c1820, 0x4c66: 0x403c1920, 0x4c67: 0x403c1a20,
+ 0x4c68: 0x403c1b20, 0x4c69: 0x403c1c20, 0x4c6a: 0x403c1d20, 0x4c6b: 0x403c1e20,
+ 0x4c6c: 0x403c1f20, 0x4c6d: 0x403c2020, 0x4c6e: 0x403c2120, 0x4c6f: 0x403c2220,
+ 0x4c70: 0x403c2320, 0x4c71: 0x403c2420, 0x4c72: 0x403c2520, 0x4c73: 0x403c2620,
+ 0x4c74: 0x403c2720, 0x4c75: 0x403c2820, 0x4c76: 0x403c2920, 0x4c77: 0x403c2a20,
+ 0x4c78: 0x403c2b20, 0x4c79: 0x403c2c20, 0x4c7a: 0x403c2d20, 0x4c7b: 0x403c2e20,
+ 0x4c7c: 0x403c2f20, 0x4c7d: 0x403c3020, 0x4c7e: 0x403c3120, 0x4c7f: 0x403c3220,
+ // Block 0x132, offset 0x4c80
+ 0x4c80: 0x403c3320, 0x4c81: 0x403c3420, 0x4c82: 0x403c3520, 0x4c83: 0x403c3620,
+ 0x4c84: 0x403c3720, 0x4c85: 0x403c3820, 0x4c86: 0x403c3920, 0x4c87: 0x403c3a20,
+ 0x4c88: 0x403c3b20, 0x4c89: 0x403c3c20, 0x4c8a: 0x403c3d20, 0x4c8b: 0x403c3e20,
+ 0x4c8c: 0x403c3f20, 0x4c8d: 0x403c4020, 0x4c8e: 0x403c4120, 0x4c8f: 0x403c4220,
+ 0x4c90: 0x403c4320, 0x4c91: 0x403c4420, 0x4c92: 0x403c4520, 0x4c93: 0x403c4620,
+ 0x4c94: 0x403c4720, 0x4c95: 0x403c4820, 0x4c96: 0x403c4920, 0x4c97: 0x403c4a20,
+ 0x4c98: 0x403c4b20, 0x4c99: 0x403c4c20, 0x4c9a: 0x403c4d20, 0x4c9b: 0x403c4e20,
+ 0x4c9c: 0x403c4f20, 0x4c9d: 0x403c5020, 0x4c9e: 0x403c5120, 0x4c9f: 0x403c5220,
+ 0x4ca0: 0x403c5320, 0x4ca1: 0x403c5420, 0x4ca2: 0x403c5520, 0x4ca3: 0x403c5620,
+ 0x4ca4: 0x403c5720, 0x4ca5: 0x403c5820, 0x4ca6: 0x403c5920, 0x4ca7: 0x403c5a20,
+ 0x4ca8: 0x403c5b20, 0x4ca9: 0x403c5c20, 0x4caa: 0x403c5d20, 0x4cab: 0x403c5e20,
+ 0x4cac: 0x403c5f20, 0x4cad: 0x403c6020, 0x4cae: 0x403c6120, 0x4caf: 0x403c6220,
+ 0x4cb0: 0x403c6320, 0x4cb1: 0x403c6420, 0x4cb2: 0x403c6520, 0x4cb3: 0x403c6620,
+ 0x4cb4: 0x403c6720, 0x4cb5: 0x403c6820, 0x4cb6: 0x403c6920, 0x4cb7: 0x403c6a20,
+ 0x4cb8: 0x403c6b20, 0x4cb9: 0x403c6c20, 0x4cba: 0x403c6d20, 0x4cbb: 0x403c6e20,
+ 0x4cbc: 0x403c6f20, 0x4cbd: 0x403c7020, 0x4cbe: 0x403c7120, 0x4cbf: 0x403c7220,
+ // Block 0x133, offset 0x4cc0
+ 0x4cc0: 0x403c7320, 0x4cc1: 0x403c7420, 0x4cc2: 0x403c7520, 0x4cc3: 0x403c7620,
+ 0x4cc4: 0x403c7720, 0x4cc5: 0x403c7820, 0x4cc6: 0x403c7920, 0x4cc7: 0x403c7a20,
+ 0x4cc8: 0x403c7b20, 0x4cc9: 0x403c7c20, 0x4cca: 0x403c7d20, 0x4ccb: 0x403c7e20,
+ 0x4ccc: 0x403c7f20, 0x4ccd: 0x403c8020, 0x4cce: 0x403c8120, 0x4ccf: 0x403c8220,
+ 0x4cd0: 0x403c8320, 0x4cd1: 0x403c8420, 0x4cd2: 0x403c8520, 0x4cd3: 0x403c8620,
+ 0x4cd4: 0x403c8720, 0x4cd5: 0x403c8820, 0x4cd6: 0x403c8920, 0x4cd7: 0x403c8a20,
+ 0x4cd8: 0x403c8b20, 0x4cd9: 0x403c8c20, 0x4cda: 0x403c8d20, 0x4cdb: 0x403c8e20,
+ 0x4cdc: 0x403c8f20, 0x4cdd: 0x403c9020, 0x4cde: 0x403c9120, 0x4cdf: 0x403c9220,
+ 0x4ce0: 0x403c9320, 0x4ce1: 0x403c9420, 0x4ce2: 0x403c9520, 0x4ce3: 0x403c9620,
+ 0x4ce4: 0x403c9720, 0x4ce5: 0x403c9820, 0x4ce6: 0x403c9920, 0x4ce7: 0x403c9a20,
+ 0x4ce8: 0x403c9b20, 0x4ce9: 0x403c9c20, 0x4cea: 0x403c9d20, 0x4ceb: 0x403c9e20,
+ 0x4cec: 0x403c9f20, 0x4ced: 0x403ca020, 0x4cee: 0x403ca120, 0x4cef: 0x403ca220,
+ 0x4cf0: 0x403ca320, 0x4cf1: 0x403ca420, 0x4cf2: 0x403ca520, 0x4cf3: 0x403ca620,
+ 0x4cf4: 0x403ca720, 0x4cf5: 0x403ca820, 0x4cf6: 0x403ca920, 0x4cf7: 0x403caa20,
+ 0x4cf8: 0x403cab20, 0x4cf9: 0x403cac20, 0x4cfa: 0x403cad20, 0x4cfb: 0x403cae20,
+ 0x4cfc: 0x403caf20, 0x4cfd: 0x403cb020, 0x4cfe: 0x403cb120, 0x4cff: 0x403cb220,
+ // Block 0x134, offset 0x4d00
+ 0x4d00: 0x403cb320, 0x4d01: 0x403cb420, 0x4d02: 0x403cb520, 0x4d03: 0x403cb620,
+ 0x4d04: 0x403cb720, 0x4d05: 0x403cb820, 0x4d06: 0x403cb920, 0x4d07: 0x403cba20,
+ 0x4d08: 0x403cbb20, 0x4d09: 0x403cbc20, 0x4d0a: 0x403cbd20, 0x4d0b: 0x403cbe20,
+ 0x4d0c: 0x403cbf20, 0x4d0d: 0x403cc020, 0x4d0e: 0x403cc120, 0x4d0f: 0x403cc220,
+ 0x4d10: 0x403cc320, 0x4d11: 0x403cc420, 0x4d12: 0x403cc520, 0x4d13: 0x403cc620,
+ 0x4d14: 0x403cc720, 0x4d15: 0x403cc820, 0x4d16: 0x403cc920, 0x4d17: 0x403cca20,
+ 0x4d18: 0x403ccb20, 0x4d19: 0x403ccc20, 0x4d1a: 0x403ccd20, 0x4d1b: 0x403cce20,
+ 0x4d1c: 0x403ccf20, 0x4d1d: 0x403cd020, 0x4d1e: 0x403cd120, 0x4d1f: 0x403cd220,
+ 0x4d20: 0x403cd320, 0x4d21: 0x403cd420, 0x4d22: 0x403cd520, 0x4d23: 0x403cd620,
+ 0x4d24: 0x403cd720, 0x4d25: 0x403cd820, 0x4d26: 0x403cd920, 0x4d27: 0x403cda20,
+ 0x4d28: 0x403cdb20, 0x4d29: 0x403cdc20, 0x4d2a: 0x403cdd20, 0x4d2b: 0x403cde20,
+ 0x4d2c: 0x403cdf20, 0x4d2d: 0x403ce020, 0x4d2e: 0x403ce120, 0x4d2f: 0x403ce220,
+ 0x4d30: 0x403ce320, 0x4d31: 0x403ce420, 0x4d32: 0x403ce520, 0x4d33: 0x403ce620,
+ 0x4d34: 0x403ce720, 0x4d35: 0x403ce820, 0x4d36: 0x403ce920, 0x4d37: 0x403cea20,
+ 0x4d38: 0x403ceb20, 0x4d39: 0x403cec20, 0x4d3a: 0x403ced20, 0x4d3b: 0x403cee20,
+ 0x4d3c: 0x403cef20, 0x4d3d: 0x403cf020, 0x4d3e: 0x403cf120, 0x4d3f: 0x403cf220,
+ // Block 0x135, offset 0x4d40
+ 0x4d40: 0x403cf320, 0x4d41: 0x403cf420, 0x4d42: 0x403cf520, 0x4d43: 0x403cf620,
+ 0x4d44: 0x403cf720, 0x4d45: 0x403cf820, 0x4d46: 0x403cf920, 0x4d47: 0x403cfa20,
+ 0x4d48: 0x403cfb20, 0x4d49: 0x403cfc20, 0x4d4a: 0x403cfd20, 0x4d4b: 0x403cfe20,
+ 0x4d4c: 0x403cff20, 0x4d4d: 0x403d0020, 0x4d4e: 0x403d0120, 0x4d4f: 0x403d0220,
+ 0x4d50: 0x403d0320, 0x4d51: 0x403d0420, 0x4d52: 0x403d0520, 0x4d53: 0x403d0620,
+ 0x4d54: 0x403d0720, 0x4d55: 0x403d0820, 0x4d56: 0x403d0920, 0x4d57: 0x403d0a20,
+ 0x4d58: 0x403d0b20, 0x4d59: 0x403d0c20, 0x4d5a: 0x403d0d20, 0x4d5b: 0x403d0e20,
+ 0x4d5c: 0x403d0f20, 0x4d5d: 0x403d1020, 0x4d5e: 0x403d1120, 0x4d5f: 0x403d1220,
+ 0x4d60: 0x403d1320, 0x4d61: 0x403d1420, 0x4d62: 0x403d1520, 0x4d63: 0x403d1620,
+ 0x4d64: 0x403d1720, 0x4d65: 0x403d1820, 0x4d66: 0x403d1920, 0x4d67: 0x403d1a20,
+ 0x4d68: 0x403d1b20, 0x4d69: 0x403d1c20, 0x4d6a: 0x403d1d20, 0x4d6b: 0x403d1e20,
+ 0x4d6c: 0x403d1f20, 0x4d6d: 0x403d2020, 0x4d6e: 0x403d2120,
+ // Block 0x136, offset 0x4d80
+ 0x4d80: 0xe0000210, 0x4d81: 0xe00002c7, 0x4d82: 0xe0000384, 0x4d83: 0xe0000450,
+ 0x4d84: 0xe00004f8, 0x4d85: 0xe0000591, 0x4d86: 0xe000062d, 0x4d87: 0xe00006c6,
+ 0x4d88: 0xe00002ca, 0x4d89: 0xe0000387, 0x4d8a: 0xe0000453, 0x4d8b: 0xe00004fb,
+ 0x4d8c: 0xe0000594, 0x4d8d: 0xe0000630, 0x4d8e: 0xe00006c9, 0x4d8f: 0xe000038a,
+ 0x4d90: 0xe0000456, 0x4d91: 0xe00004fe, 0x4d92: 0xe0000597, 0x4d93: 0xe0000633,
+ 0x4d94: 0xe00006cc, 0x4d95: 0xe000012c, 0x4d96: 0xe0000213, 0x4d97: 0xe00002cd,
+ 0x4d98: 0xe000038d, 0x4d99: 0xe0000459, 0x4d9a: 0xe0000501, 0x4d9b: 0xe000059a,
+ 0x4d9c: 0xe0000636, 0x4d9d: 0xe00006cf, 0x4d9e: 0xe000012f, 0x4d9f: 0xe0000216,
+ 0x4da0: 0xe00002d0, 0x4da1: 0xe0000390, 0x4da2: 0xe000045c, 0x4da3: 0xe0000219,
+ 0x4da4: 0xe00002d3, 0x4da5: 0xe00002d6, 0x4da6: 0xe0000393, 0x4da7: 0xe000045f,
+ 0x4da8: 0xe0000504, 0x4da9: 0xe000059d, 0x4daa: 0xe0000639, 0x4dab: 0xe00006d2,
+ 0x4dac: 0xe0000132, 0x4dad: 0xe000021c, 0x4dae: 0xe00002d9, 0x4daf: 0xe00002dc,
+ 0x4db0: 0xe0000396, 0x4db1: 0xe0000462, 0x4db2: 0x40148420, 0x4db3: 0x40148520,
+ 0x4db4: 0xe0000135, 0x4db5: 0xe000021f, 0x4db6: 0xe00002df, 0x4db7: 0xe00002e2,
+ 0x4db8: 0xe0000399, 0x4db9: 0xe0000465, 0x4dba: 0xe00002e5, 0x4dbb: 0xe00002e8,
+ 0x4dbc: 0xe000039c, 0x4dbd: 0xe000039f, 0x4dbe: 0xe00003a2, 0x4dbf: 0xe00003a5,
+ // Block 0x137, offset 0x4dc0
+ 0x4dc0: 0xe0000507, 0x4dc1: 0xe00005a0, 0x4dc2: 0xe00005a3, 0x4dc3: 0xe00005a6,
+ 0x4dc4: 0xe000063c, 0x4dc5: 0xe000063f, 0x4dc6: 0xe00006d5, 0x4dc7: 0xe00006d8,
+ 0x4dc8: 0xe00006db, 0x4dc9: 0xe00006de, 0x4dca: 0xe0000222, 0x4dcb: 0xe00002eb,
+ 0x4dcc: 0xe00003a8, 0x4dcd: 0xe0000468, 0x4dce: 0xe000050a, 0x4dcf: 0xe0000138,
+ 0x4dd0: 0xe0000225, 0x4dd1: 0xe00002ee, 0x4dd2: 0xe00003ab, 0x4dd3: 0xe00003ae,
+ 0x4dd4: 0xe000046b, 0x4dd5: 0xe000046e, 0x4dd6: 0x40148620, 0x4dd7: 0x40148720,
+ 0x4dd8: 0xe000013b, 0x4dd9: 0xe0000228, 0x4dda: 0x40148820, 0x4ddb: 0x40148920,
+ 0x4ddc: 0x40148a20, 0x4ddd: 0x40148b20, 0x4dde: 0x40148c20, 0x4ddf: 0x40148d20,
+ 0x4de0: 0x40148e20, 0x4de1: 0x40148f20, 0x4de2: 0x40149020,
+ 0x4df0: 0x4001d420, 0x4df1: 0x4001d520, 0x4df2: 0x4001d620, 0x4df3: 0x4001d720,
+ // Block 0x138, offset 0x4e00
+ 0x4e00: 0x403d2220, 0x4e01: 0x403d2320, 0x4e02: 0x403d2420, 0x4e03: 0x403d2520,
+ 0x4e04: 0x403d2620, 0x4e05: 0x403d2720, 0x4e06: 0x403d2820, 0x4e07: 0x403d2920,
+ 0x4e08: 0x403d2a20, 0x4e09: 0x403d2b20, 0x4e0a: 0x403d2c20, 0x4e0b: 0x403d2d20,
+ 0x4e0c: 0x403d2e20, 0x4e0d: 0x403d2f20, 0x4e0e: 0x403d3020, 0x4e0f: 0x403d3120,
+ 0x4e10: 0x403d3220, 0x4e11: 0x403d3320, 0x4e12: 0x403d3420, 0x4e13: 0x403d3520,
+ 0x4e14: 0x403d3620, 0x4e15: 0x403d3720, 0x4e16: 0x403d3820, 0x4e17: 0x403d3920,
+ 0x4e18: 0x403d3a20, 0x4e19: 0x403d3b20, 0x4e1a: 0x403d3c20, 0x4e1b: 0x403d3d20,
+ 0x4e1c: 0x403d3e20, 0x4e1d: 0x403d3f20, 0x4e1e: 0x403d4020, 0x4e1f: 0x403d4120,
+ 0x4e20: 0x403d4220, 0x4e21: 0x403d4320, 0x4e22: 0x403d4420, 0x4e23: 0x403d4520,
+ 0x4e24: 0x403d4620, 0x4e25: 0x403d4720, 0x4e26: 0x403d4820, 0x4e27: 0x403d4920,
+ 0x4e28: 0x403d4a20, 0x4e29: 0x403d4b20, 0x4e2a: 0x403d4c20, 0x4e2b: 0x403d4d20,
+ 0x4e2c: 0x403d4e20, 0x4e2d: 0x403d4f20, 0x4e2e: 0x403d5020, 0x4e2f: 0x403d5120,
+ 0x4e30: 0x403d5220, 0x4e31: 0x403d5320, 0x4e32: 0x403d5420, 0x4e33: 0x403d5520,
+ 0x4e34: 0x403d5620, 0x4e35: 0x403d5720, 0x4e36: 0x403d5820, 0x4e37: 0x403d5920,
+ 0x4e38: 0x403d5a20, 0x4e39: 0x403d5b20, 0x4e3a: 0x403d5c20, 0x4e3b: 0x403d5d20,
+ 0x4e3c: 0x403d5e20, 0x4e3d: 0x403d5f20, 0x4e3e: 0x403d6020, 0x4e3f: 0x403d6120,
+ // Block 0x139, offset 0x4e40
+ 0x4e40: 0x403d6220, 0x4e41: 0x403d6320, 0x4e42: 0x403d6420, 0x4e43: 0x403d6520,
+ 0x4e44: 0x403d6620, 0x4e45: 0x403d6720, 0x4e46: 0x403d6820, 0x4e47: 0x403d6920,
+ 0x4e48: 0x403d6a20, 0x4e49: 0x403d6b20, 0x4e4a: 0x403d6c20, 0x4e4b: 0x403d6d20,
+ 0x4e4c: 0x403d6e20, 0x4e4d: 0x403d6f20, 0x4e4e: 0x403d7020, 0x4e4f: 0x403d7120,
+ 0x4e50: 0x403d7220, 0x4e51: 0x403d7320, 0x4e52: 0x403d7420, 0x4e53: 0x403d7520,
+ 0x4e54: 0x403d7620, 0x4e55: 0x403d7720, 0x4e56: 0x403d7820, 0x4e57: 0x403d7920,
+ 0x4e58: 0x403d7a20, 0x4e59: 0x403d7b20, 0x4e5a: 0x403d7c20, 0x4e5b: 0x403d7d20,
+ 0x4e5c: 0x403d7e20, 0x4e5d: 0x403d7f20, 0x4e5e: 0x403d8020, 0x4e5f: 0x403d8120,
+ 0x4e60: 0x403d8220, 0x4e61: 0x403d8320, 0x4e62: 0x403d8420, 0x4e63: 0x403d8520,
+ 0x4e64: 0x403d8620, 0x4e65: 0x403d8720, 0x4e66: 0x403d8820, 0x4e67: 0x403d8920,
+ 0x4e68: 0x403d8a20, 0x4e69: 0x403d8b20, 0x4e6a: 0x403d8c20, 0x4e6b: 0x403d8d20,
+ 0x4e6c: 0x403d8e20, 0x4e6d: 0x403d8f20, 0x4e6e: 0x403d9020, 0x4e6f: 0x403d9120,
+ 0x4e70: 0x403d9220, 0x4e71: 0x403d9320, 0x4e72: 0x403d9420, 0x4e73: 0x403d9520,
+ 0x4e74: 0x403d9620, 0x4e75: 0x403d9720, 0x4e76: 0x403d9820, 0x4e77: 0x403d9920,
+ 0x4e78: 0x403d9a20, 0x4e79: 0x403d9b20, 0x4e7a: 0x403d9c20, 0x4e7b: 0x403d9d20,
+ 0x4e7c: 0x403d9e20, 0x4e7d: 0x403d9f20, 0x4e7e: 0x403da020, 0x4e7f: 0x403da120,
+ // Block 0x13a, offset 0x4e80
+ 0x4e80: 0x403da220, 0x4e81: 0x403da320, 0x4e82: 0x403da420, 0x4e83: 0x403da520,
+ 0x4e84: 0x403da620, 0x4e85: 0x403da720, 0x4e86: 0x403da820, 0x4e87: 0x403da920,
+ 0x4e88: 0x403daa20, 0x4e89: 0x403dab20, 0x4e8a: 0x403dac20, 0x4e8b: 0x403dad20,
+ 0x4e8c: 0x403dae20, 0x4e8d: 0x403daf20, 0x4e8e: 0x403db020, 0x4e8f: 0x403db120,
+ 0x4e90: 0x403db220, 0x4e91: 0x403db320, 0x4e92: 0x403db420, 0x4e93: 0x403db520,
+ 0x4e94: 0x403db620, 0x4e95: 0x403db720, 0x4e96: 0x403db820, 0x4e97: 0x403db920,
+ 0x4e98: 0x403dba20, 0x4e99: 0x403dbb20, 0x4e9a: 0x403dbc20, 0x4e9b: 0x403dbd20,
+ 0x4e9c: 0x403dbe20, 0x4e9d: 0x403dbf20, 0x4e9e: 0x403dc020, 0x4e9f: 0x403dc120,
+ 0x4ea0: 0x403dc220, 0x4ea1: 0x403dc320, 0x4ea2: 0x403dc420, 0x4ea3: 0x403dc520,
+ 0x4ea4: 0x403dc620, 0x4ea5: 0x403dc720, 0x4ea6: 0x403dc820, 0x4ea7: 0x403dc920,
+ 0x4ea8: 0x403dca20, 0x4ea9: 0x403dcb20, 0x4eaa: 0x403dcc20, 0x4eab: 0x403dcd20,
+ 0x4eac: 0x403dce20, 0x4ead: 0x403dcf20, 0x4eae: 0x403dd020, 0x4eaf: 0x403dd120,
+ 0x4eb0: 0x403dd220, 0x4eb1: 0x403dd320, 0x4eb2: 0x403dd420, 0x4eb3: 0x403dd520,
+ 0x4eb4: 0x403dd620, 0x4eb5: 0x403dd720, 0x4eb6: 0x403dd820, 0x4eb7: 0x403dd920,
+ 0x4eb8: 0x403dda20, 0x4eb9: 0x403ddb20, 0x4eba: 0x403ddc20, 0x4ebb: 0x403ddd20,
+ 0x4ebc: 0x403dde20, 0x4ebd: 0x403ddf20, 0x4ebe: 0x403de020, 0x4ebf: 0x403de120,
+ // Block 0x13b, offset 0x4ec0
+ 0x4ec0: 0x403de220, 0x4ec1: 0x403de320, 0x4ec2: 0x403de420, 0x4ec3: 0x403de520,
+ 0x4ec4: 0x403de620, 0x4ec5: 0x403de720, 0x4ec6: 0x403de820, 0x4ec7: 0x403de920,
+ 0x4ec8: 0x403dea20, 0x4ec9: 0x403deb20, 0x4eca: 0x403dec20, 0x4ecb: 0x403ded20,
+ 0x4ecc: 0x403dee20, 0x4ecd: 0x403def20, 0x4ece: 0x403df020, 0x4ecf: 0x403df120,
+ 0x4ed0: 0x403df220, 0x4ed1: 0x403df320, 0x4ed2: 0x403df420, 0x4ed3: 0x403df520,
+ 0x4ed4: 0x403df620, 0x4ed5: 0x403df720, 0x4ed6: 0x403df820, 0x4ed7: 0x403df920,
+ 0x4ed8: 0x403dfa20, 0x4ed9: 0x403dfb20, 0x4eda: 0x403dfc20, 0x4edb: 0x403dfd20,
+ 0x4edc: 0x403dfe20, 0x4edd: 0x403dff20, 0x4ede: 0x403e0020, 0x4edf: 0x403e0120,
+ 0x4ee0: 0x403e0220, 0x4ee1: 0x403e0320, 0x4ee2: 0x403e0420, 0x4ee3: 0x403e0520,
+ 0x4ee4: 0x403e0620, 0x4ee5: 0x403e0720, 0x4ee6: 0x403e0820, 0x4ee7: 0x403e0920,
+ 0x4ee8: 0x403e0a20, 0x4ee9: 0x403e0b20, 0x4eea: 0x403e0c20, 0x4eeb: 0x403e0d20,
+ 0x4eec: 0x403e0e20, 0x4eed: 0x403e0f20, 0x4eee: 0x403e1020, 0x4eef: 0x403e1120,
+ 0x4ef0: 0x403e1220, 0x4ef1: 0x403e1320, 0x4ef2: 0x403e1420, 0x4ef3: 0x403e1520,
+ 0x4ef4: 0x403e1620, 0x4ef5: 0x403e1720, 0x4ef6: 0x403e1820, 0x4ef7: 0x403e1920,
+ 0x4ef8: 0x403e1a20, 0x4ef9: 0x403e1b20, 0x4efa: 0x403e1c20, 0x4efb: 0x403e1d20,
+ 0x4efc: 0x403e1e20, 0x4efd: 0x403e1f20, 0x4efe: 0x403e2020, 0x4eff: 0x403e2120,
+ // Block 0x13c, offset 0x4f00
+ 0x4f00: 0x403e2220, 0x4f01: 0x403e2320, 0x4f02: 0x403e2420, 0x4f03: 0x403e2520,
+ 0x4f04: 0x403e2620, 0x4f05: 0x403e2720, 0x4f06: 0x403e2820, 0x4f07: 0x403e2920,
+ 0x4f08: 0x403e2a20, 0x4f09: 0x403e2b20, 0x4f0a: 0x403e2c20, 0x4f0b: 0x403e2d20,
+ 0x4f0c: 0x403e2e20, 0x4f0d: 0x403e2f20, 0x4f0e: 0x403e3020, 0x4f0f: 0x403e3120,
+ 0x4f10: 0x403e3220, 0x4f11: 0x403e3320, 0x4f12: 0x403e3420, 0x4f13: 0x403e3520,
+ 0x4f14: 0x403e3620, 0x4f15: 0x403e3720, 0x4f16: 0x403e3820, 0x4f17: 0x403e3920,
+ 0x4f18: 0x403e3a20, 0x4f19: 0x403e3b20, 0x4f1a: 0x403e3c20, 0x4f1b: 0x403e3d20,
+ 0x4f1c: 0x403e3e20, 0x4f1d: 0x403e3f20, 0x4f1e: 0x403e4020, 0x4f1f: 0x403e4120,
+ 0x4f20: 0x403e4220, 0x4f21: 0x403e4320, 0x4f22: 0x403e4420, 0x4f23: 0x403e4520,
+ 0x4f24: 0x403e4620, 0x4f25: 0x403e4720, 0x4f26: 0x403e4820, 0x4f27: 0x403e4920,
+ 0x4f28: 0x403e4a20, 0x4f29: 0x403e4b20, 0x4f2a: 0x403e4c20, 0x4f2b: 0x403e4d20,
+ 0x4f2c: 0x403e4e20, 0x4f2d: 0x403e4f20, 0x4f2e: 0x403e5020, 0x4f2f: 0x403e5120,
+ 0x4f30: 0x403e5220, 0x4f31: 0x403e5320, 0x4f32: 0x403e5420, 0x4f33: 0x403e5520,
+ 0x4f34: 0x403e5620, 0x4f35: 0x403e5720, 0x4f36: 0x403e5820, 0x4f37: 0x403e5920,
+ 0x4f38: 0x403e5a20, 0x4f39: 0x403e5b20, 0x4f3a: 0x403e5c20, 0x4f3b: 0x403e5d20,
+ 0x4f3c: 0x403e5e20, 0x4f3d: 0x403e5f20, 0x4f3e: 0x403e6020, 0x4f3f: 0x403e6120,
+ // Block 0x13d, offset 0x4f40
+ 0x4f40: 0x403e6220, 0x4f41: 0x403e6320, 0x4f42: 0x403e6420, 0x4f43: 0x403e6520,
+ 0x4f44: 0x403e6620, 0x4f45: 0x403e6720, 0x4f46: 0x403e6820, 0x4f47: 0x403e6920,
+ 0x4f48: 0x403e6a20, 0x4f49: 0x403e6b20, 0x4f4a: 0x403e6c20, 0x4f4b: 0x403e6d20,
+ 0x4f4c: 0x403e6e20, 0x4f4d: 0x403e6f20, 0x4f4e: 0x403e7020, 0x4f4f: 0x403e7120,
+ 0x4f50: 0x403e7220, 0x4f51: 0x403e7320, 0x4f52: 0x403e7420, 0x4f53: 0x403e7520,
+ 0x4f54: 0x403e7620, 0x4f55: 0x403e7720, 0x4f56: 0x403e7820, 0x4f57: 0x403e7920,
+ 0x4f58: 0x403e7a20, 0x4f59: 0x403e7b20, 0x4f5a: 0x403e7c20, 0x4f5b: 0x403e7d20,
+ 0x4f5c: 0x403e7e20, 0x4f5d: 0x403e7f20, 0x4f5e: 0x403e8020, 0x4f5f: 0x403e8120,
+ 0x4f60: 0x403e8220, 0x4f61: 0x403e8320, 0x4f62: 0x403e8420, 0x4f63: 0x403e8520,
+ 0x4f64: 0x403e8620, 0x4f65: 0x403e8720, 0x4f66: 0x403e8820, 0x4f67: 0x403e8920,
+ 0x4f68: 0x403e8a20, 0x4f69: 0x403e8b20, 0x4f6a: 0x403e8c20, 0x4f6b: 0x403e8d20,
+ 0x4f6c: 0x403e8e20, 0x4f6d: 0x403e8f20, 0x4f6e: 0x403e9020, 0x4f6f: 0x403e9120,
+ 0x4f70: 0x403e9220, 0x4f71: 0x403e9320, 0x4f72: 0x403e9420, 0x4f73: 0x403e9520,
+ 0x4f74: 0x403e9620, 0x4f75: 0x403e9720, 0x4f76: 0x403e9820, 0x4f77: 0x403e9920,
+ 0x4f78: 0x403e9a20, 0x4f79: 0x403e9b20, 0x4f7a: 0x403e9c20, 0x4f7b: 0x403e9d20,
+ 0x4f7c: 0x403e9e20, 0x4f7d: 0x403e9f20, 0x4f7e: 0x403ea020, 0x4f7f: 0x403ea120,
+ // Block 0x13e, offset 0x4f80
+ 0x4f80: 0x403ea220, 0x4f81: 0x403ea320, 0x4f82: 0x403ea420, 0x4f83: 0x403ea520,
+ 0x4f84: 0x403ea620, 0x4f85: 0x403ea720, 0x4f86: 0x403ea820, 0x4f87: 0x403ea920,
+ 0x4f88: 0x403eaa20, 0x4f89: 0x403eab20, 0x4f8a: 0x403eac20, 0x4f8b: 0x403ead20,
+ 0x4f8c: 0x403eae20, 0x4f8d: 0x403eaf20, 0x4f8e: 0x403eb020, 0x4f8f: 0x403eb120,
+ 0x4f90: 0x403eb220, 0x4f91: 0x403eb320, 0x4f92: 0x403eb420, 0x4f93: 0x403eb520,
+ 0x4f94: 0x403eb620, 0x4f95: 0x403eb720, 0x4f96: 0x403eb820, 0x4f97: 0x403eb920,
+ 0x4f98: 0x403eba20, 0x4f99: 0x403ebb20, 0x4f9a: 0x403ebc20, 0x4f9b: 0x403ebd20,
+ 0x4f9c: 0x403ebe20, 0x4f9d: 0x403ebf20, 0x4f9e: 0x403ec020, 0x4f9f: 0x403ec120,
+ 0x4fa0: 0x403ec220, 0x4fa1: 0x403ec320, 0x4fa2: 0x403ec420, 0x4fa3: 0x403ec520,
+ 0x4fa4: 0x403ec620, 0x4fa5: 0x403ec720, 0x4fa6: 0x403ec820, 0x4fa7: 0x403ec920,
+ 0x4fa8: 0x403eca20, 0x4fa9: 0x403ecb20, 0x4faa: 0x403ecc20, 0x4fab: 0x403ecd20,
+ 0x4fac: 0x403ece20, 0x4fad: 0x403ecf20, 0x4fae: 0x403ed020, 0x4faf: 0x403ed120,
+ 0x4fb0: 0x403ed220, 0x4fb1: 0x403ed320, 0x4fb2: 0x403ed420, 0x4fb3: 0x403ed520,
+ 0x4fb4: 0x403ed620, 0x4fb5: 0x403ed720, 0x4fb6: 0x403ed820, 0x4fb7: 0x403ed920,
+ 0x4fb8: 0x403eda20, 0x4fb9: 0x403edb20, 0x4fba: 0x403edc20, 0x4fbb: 0x403edd20,
+ 0x4fbc: 0x403ede20, 0x4fbd: 0x403edf20, 0x4fbe: 0x403ee020, 0x4fbf: 0x403ee120,
+ // Block 0x13f, offset 0x4fc0
+ 0x4fc0: 0x403ee220, 0x4fc1: 0x403ee320, 0x4fc2: 0x403ee420, 0x4fc3: 0x403ee520,
+ 0x4fc4: 0x403ee620, 0x4fc5: 0x403ee720, 0x4fc6: 0x403ee820, 0x4fc7: 0x403ee920,
+ 0x4fc8: 0x403eea20, 0x4fc9: 0x403eeb20, 0x4fca: 0x403eec20, 0x4fcb: 0x403eed20,
+ 0x4fcc: 0x403eee20, 0x4fcd: 0x403eef20, 0x4fce: 0x403ef020, 0x4fcf: 0x403ef120,
+ 0x4fd0: 0x403ef220, 0x4fd1: 0x403ef320, 0x4fd2: 0x403ef420, 0x4fd3: 0x403ef520,
+ 0x4fd4: 0x403ef620, 0x4fd5: 0x403ef720, 0x4fd6: 0x403ef820, 0x4fd7: 0x403ef920,
+ 0x4fd8: 0x403efa20, 0x4fd9: 0x403efb20, 0x4fda: 0x403efc20, 0x4fdb: 0x403efd20,
+ 0x4fdc: 0x403efe20, 0x4fdd: 0x403eff20, 0x4fde: 0x403f0020, 0x4fdf: 0x403f0120,
+ 0x4fe0: 0x403f0220, 0x4fe1: 0x403f0320, 0x4fe2: 0x403f0420, 0x4fe3: 0x403f0520,
+ 0x4fe4: 0x403f0620, 0x4fe5: 0x403f0720, 0x4fe6: 0x403f0820, 0x4fe7: 0x403f0920,
+ 0x4fe8: 0x403f0a20, 0x4fe9: 0x403f0b20, 0x4fea: 0x403f0c20, 0x4feb: 0x403f0d20,
+ 0x4fec: 0x403f0e20, 0x4fed: 0x403f0f20, 0x4fee: 0x403f1020, 0x4fef: 0x403f1120,
+ 0x4ff0: 0x403f1220, 0x4ff1: 0x403f1320, 0x4ff2: 0x403f1420, 0x4ff3: 0x403f1520,
+ 0x4ff4: 0x403f1620, 0x4ff5: 0x403f1720, 0x4ff6: 0x403f1820, 0x4ff7: 0x403f1920,
+ 0x4ff8: 0x403f1a20, 0x4ff9: 0x403f1b20, 0x4ffa: 0x403f1c20, 0x4ffb: 0x403f1d20,
+ 0x4ffc: 0x403f1e20, 0x4ffd: 0x403f1f20, 0x4ffe: 0x403f2020, 0x4fff: 0x403f2120,
+ // Block 0x140, offset 0x5000
+ 0x5000: 0x403f2220, 0x5001: 0x403f2320, 0x5002: 0x403f2420, 0x5003: 0x403f2520,
+ 0x5004: 0x403f2620, 0x5005: 0x403f2720, 0x5006: 0x403f2820, 0x5007: 0x403f2920,
+ 0x5008: 0x403f2a20, 0x5009: 0x403f2b20, 0x500a: 0x403f2c20, 0x500b: 0x403f2d20,
+ 0x500c: 0x403f2e20, 0x500d: 0x403f2f20, 0x500e: 0x403f3020, 0x500f: 0x403f3120,
+ 0x5010: 0x403f3220, 0x5011: 0x403f3320, 0x5012: 0x403f3420, 0x5013: 0x403f3520,
+ 0x5014: 0x403f3620, 0x5015: 0x403f3720, 0x5016: 0x403f3820, 0x5017: 0x403f3920,
+ 0x5018: 0x403f3a20, 0x5019: 0x403f3b20, 0x501a: 0x403f3c20, 0x501b: 0x403f3d20,
+ 0x501c: 0x403f3e20, 0x501d: 0x403f3f20, 0x501e: 0x403f4020, 0x501f: 0x403f4120,
+ 0x5020: 0x403f4220, 0x5021: 0x403f4320, 0x5022: 0x403f4420, 0x5023: 0x403f4520,
+ 0x5024: 0x403f4620, 0x5025: 0x403f4720, 0x5026: 0x403f4820, 0x5027: 0x403f4920,
+ 0x5028: 0x403f4a20, 0x5029: 0x403f4b20, 0x502a: 0x403f4c20, 0x502b: 0x403f4d20,
+ 0x502c: 0x403f4e20, 0x502d: 0x403f4f20, 0x502e: 0x403f5020, 0x502f: 0x403f5120,
+ 0x5030: 0x403f5220, 0x5031: 0x403f5320, 0x5032: 0x403f5420, 0x5033: 0x403f5520,
+ 0x5034: 0x403f5620, 0x5035: 0x403f5720, 0x5036: 0x403f5820, 0x5037: 0x403f5920,
+ 0x5038: 0x403f5a20, 0x5039: 0x403f5b20, 0x503a: 0x403f5c20, 0x503b: 0x403f5d20,
+ 0x503c: 0x403f5e20, 0x503d: 0x403f5f20, 0x503e: 0x403f6020, 0x503f: 0x403f6120,
+ // Block 0x141, offset 0x5040
+ 0x5040: 0x403f6220, 0x5041: 0x403f6320, 0x5042: 0x403f6420, 0x5043: 0x403f6520,
+ 0x5044: 0x403f6620, 0x5045: 0x403f6720, 0x5046: 0x403f6820, 0x5047: 0x403f6920,
+ 0x5048: 0x403f6a20, 0x5049: 0x403f6b20, 0x504a: 0x403f6c20, 0x504b: 0x403f6d20,
+ 0x504c: 0x403f6e20, 0x504d: 0x403f6f20, 0x504e: 0x403f7020, 0x504f: 0x403f7120,
+ 0x5050: 0x403f7220, 0x5051: 0x403f7320, 0x5052: 0x403f7420, 0x5053: 0x403f7520,
+ 0x5054: 0x403f7620, 0x5055: 0x403f7720, 0x5056: 0x403f7820, 0x5057: 0x403f7920,
+ 0x5058: 0x403f7a20, 0x5059: 0x403f7b20, 0x505a: 0x403f7c20, 0x505b: 0x403f7d20,
+ 0x505c: 0x403f7e20, 0x505d: 0x403f7f20, 0x505e: 0x403f8020, 0x505f: 0x403f8120,
+ 0x5060: 0x403f8220, 0x5061: 0x403f8320, 0x5062: 0x403f8420, 0x5063: 0x403f8520,
+ 0x5064: 0x403f8620, 0x5065: 0x403f8720, 0x5066: 0x403f8820, 0x5067: 0x403f8920,
+ 0x5068: 0x403f8a20, 0x5069: 0x403f8b20, 0x506a: 0x403f8c20, 0x506b: 0x403f8d20,
+ 0x506c: 0x403f8e20, 0x506d: 0x403f8f20, 0x506e: 0x403f9020, 0x506f: 0x403f9120,
+ 0x5070: 0x403f9220, 0x5071: 0x403f9320, 0x5072: 0x403f9420, 0x5073: 0x403f9520,
+ 0x5074: 0x403f9620, 0x5075: 0x403f9720, 0x5076: 0x403f9820, 0x5077: 0x403f9920,
+ 0x5078: 0x403f9a20, 0x5079: 0x403f9b20, 0x507a: 0x403f9c20, 0x507b: 0x403f9d20,
+ 0x507c: 0x403f9e20, 0x507d: 0x403f9f20, 0x507e: 0x403fa020, 0x507f: 0x403fa120,
+ // Block 0x142, offset 0x5080
+ 0x5080: 0x403fa220, 0x5081: 0x403fa320, 0x5082: 0x403fa420, 0x5083: 0x403fa520,
+ 0x5084: 0x403fa620, 0x5085: 0x403fa720, 0x5086: 0x403fa820, 0x5087: 0x403fa920,
+ 0x5088: 0x403faa20, 0x5089: 0x403fab20, 0x508a: 0x403fac20, 0x508b: 0x403fad20,
+ 0x508c: 0x403fae20, 0x508d: 0x403faf20, 0x508e: 0x403fb020, 0x508f: 0x403fb120,
+ 0x5090: 0x403fb220, 0x5091: 0x403fb320, 0x5092: 0x403fb420, 0x5093: 0x403fb520,
+ 0x5094: 0x403fb620, 0x5095: 0x403fb720, 0x5096: 0x403fb820, 0x5097: 0x403fb920,
+ 0x5098: 0x403fba20, 0x5099: 0x403fbb20, 0x509a: 0x403fbc20, 0x509b: 0x403fbd20,
+ 0x509c: 0x403fbe20, 0x509d: 0x403fbf20, 0x509e: 0x403fc020, 0x509f: 0x403fc120,
+ 0x50a0: 0x403fc220, 0x50a1: 0x403fc320, 0x50a2: 0x403fc420, 0x50a3: 0x403fc520,
+ 0x50a4: 0x403fc620, 0x50a5: 0x403fc720, 0x50a6: 0x403fc820, 0x50a7: 0x403fc920,
+ 0x50a8: 0x403fca20, 0x50a9: 0x403fcb20, 0x50aa: 0x403fcc20, 0x50ab: 0x403fcd20,
+ 0x50ac: 0x403fce20, 0x50ad: 0x403fcf20, 0x50ae: 0x403fd020, 0x50af: 0x403fd120,
+ 0x50b0: 0x403fd220, 0x50b1: 0x403fd320, 0x50b2: 0x403fd420, 0x50b3: 0x403fd520,
+ 0x50b4: 0x403fd620, 0x50b5: 0x403fd720, 0x50b6: 0x403fd820, 0x50b7: 0x403fd920,
+ 0x50b8: 0x403fda20, 0x50b9: 0x403fdb20, 0x50ba: 0x403fdc20, 0x50bb: 0x403fdd20,
+ 0x50bc: 0x403fde20, 0x50bd: 0x403fdf20, 0x50be: 0x403fe020, 0x50bf: 0x403fe120,
+ // Block 0x143, offset 0x50c0
+ 0x50c0: 0x403fe220, 0x50c1: 0x403fe320, 0x50c2: 0x403fe420, 0x50c3: 0x403fe520,
+ 0x50c4: 0x403fe620, 0x50c5: 0x403fe720, 0x50c6: 0x403fe820, 0x50c7: 0x403fe920,
+ 0x50c8: 0x403fea20, 0x50c9: 0x403feb20, 0x50ca: 0x403fec20, 0x50cb: 0x403fed20,
+ 0x50cc: 0x403fee20, 0x50cd: 0x403fef20, 0x50ce: 0x403ff020, 0x50cf: 0x403ff120,
+ 0x50d0: 0x403ff220, 0x50d1: 0x403ff320, 0x50d2: 0x403ff420, 0x50d3: 0x403ff520,
+ 0x50d4: 0x403ff620, 0x50d5: 0x403ff720, 0x50d6: 0x403ff820, 0x50d7: 0x403ff920,
+ 0x50d8: 0x403ffa20, 0x50d9: 0x403ffb20, 0x50da: 0x403ffc20, 0x50db: 0x403ffd20,
+ 0x50dc: 0x403ffe20, 0x50dd: 0x403fff20, 0x50de: 0x40400020, 0x50df: 0x40400120,
+ 0x50e0: 0x40400220, 0x50e1: 0x40400320, 0x50e2: 0x40400420, 0x50e3: 0x40400520,
+ 0x50e4: 0x40400620, 0x50e5: 0x40400720, 0x50e6: 0x40400820, 0x50e7: 0x40400920,
+ 0x50e8: 0x40400a20, 0x50e9: 0x40400b20, 0x50ea: 0x40400c20, 0x50eb: 0x40400d20,
+ 0x50ec: 0x40400e20, 0x50ed: 0x40400f20, 0x50ee: 0x40401020, 0x50ef: 0x40401120,
+ 0x50f0: 0x40401220, 0x50f1: 0x40401320, 0x50f2: 0x40401420, 0x50f3: 0x40401520,
+ 0x50f4: 0x40401620, 0x50f5: 0x40401720, 0x50f6: 0x40401820, 0x50f7: 0x40401920,
+ 0x50f8: 0x40401a20, 0x50f9: 0x40401b20, 0x50fa: 0x40401c20, 0x50fb: 0x40401d20,
+ 0x50fc: 0x40401e20, 0x50fd: 0x40401f20, 0x50fe: 0x40402020, 0x50ff: 0x40402120,
+ // Block 0x144, offset 0x5100
+ 0x5100: 0x40402220, 0x5101: 0x40402320, 0x5102: 0x40402420, 0x5103: 0x40402520,
+ 0x5104: 0x40402620, 0x5105: 0x40402720, 0x5106: 0x40402820, 0x5107: 0x40402920,
+ 0x5108: 0x40402a20, 0x5109: 0x40402b20, 0x510a: 0x40402c20, 0x510b: 0x40402d20,
+ 0x510c: 0x40402e20, 0x510d: 0x40402f20, 0x510e: 0x40403020, 0x510f: 0x40403120,
+ 0x5110: 0x40403220, 0x5111: 0x40403320, 0x5112: 0x40403420, 0x5113: 0x40403520,
+ 0x5114: 0x40403620, 0x5115: 0x40403720, 0x5116: 0x40403820, 0x5117: 0x40403920,
+ 0x5118: 0x40403a20, 0x5119: 0x40403b20, 0x511a: 0x40403c20, 0x511b: 0x40403d20,
+ 0x511c: 0x40403e20, 0x511d: 0x40403f20, 0x511e: 0x40404020, 0x511f: 0x40404120,
+ 0x5120: 0x40404220, 0x5121: 0x40404320, 0x5122: 0x40404420, 0x5123: 0x40404520,
+ 0x5124: 0x40404620, 0x5125: 0x40404720, 0x5126: 0x40404820, 0x5127: 0x40404920,
+ 0x5128: 0x40404a20, 0x5129: 0x40404b20, 0x512a: 0x40404c20, 0x512b: 0x40404d20,
+ 0x512c: 0x40404e20, 0x512d: 0x40404f20, 0x512e: 0x40405020, 0x512f: 0x40405120,
+ 0x5130: 0x40405220, 0x5131: 0x40405320, 0x5132: 0x40405420, 0x5133: 0x40405520,
+ 0x5134: 0x40405620, 0x5135: 0x40405720, 0x5136: 0x40405820, 0x5137: 0x40405920,
+ 0x5138: 0x40405a20, 0x5139: 0x40405b20, 0x513a: 0x40405c20, 0x513b: 0x40405d20,
+ 0x513c: 0x40405e20, 0x513d: 0x40405f20, 0x513e: 0x40406020, 0x513f: 0x40406120,
+ // Block 0x145, offset 0x5140
+ 0x5140: 0x40406220, 0x5141: 0x40406320, 0x5142: 0x40406420, 0x5143: 0x40406520,
+ 0x5144: 0x40406620, 0x5145: 0x40406720, 0x5146: 0x40406820, 0x5147: 0x40406920,
+ 0x5148: 0x40406a20, 0x5149: 0x40406b20, 0x514a: 0x40406c20, 0x514b: 0x40406d20,
+ 0x514c: 0x40406e20, 0x514d: 0x40406f20, 0x514e: 0x40407020, 0x514f: 0x40407120,
+ 0x5150: 0x40407220, 0x5151: 0x40407320, 0x5152: 0x40407420, 0x5153: 0x40407520,
+ 0x5154: 0x40407620, 0x5155: 0x40407720, 0x5156: 0x40407820, 0x5157: 0x40407920,
+ 0x5158: 0x40407a20, 0x5159: 0x40407b20, 0x515a: 0x40407c20, 0x515b: 0x40407d20,
+ 0x515c: 0x40407e20, 0x515d: 0x40407f20, 0x515e: 0x40408020, 0x515f: 0x40408120,
+ 0x5160: 0x40408220, 0x5161: 0x40408320, 0x5162: 0x40408420, 0x5163: 0x40408520,
+ 0x5164: 0x40408620, 0x5165: 0x40408720, 0x5166: 0x40408820, 0x5167: 0x40408920,
+ 0x5168: 0x40408a20, 0x5169: 0x40408b20, 0x516a: 0x40408c20, 0x516b: 0x40408d20,
+ 0x516c: 0x40408e20, 0x516d: 0x40408f20, 0x516e: 0x40409020, 0x516f: 0x40409120,
+ 0x5170: 0x40409220, 0x5171: 0x40409320, 0x5172: 0x40409420, 0x5173: 0x40409520,
+ 0x5174: 0x40409620, 0x5175: 0x40409720, 0x5176: 0x40409820, 0x5177: 0x40409920,
+ 0x5178: 0x40409a20, 0x5179: 0x40409b20, 0x517a: 0x40409c20, 0x517b: 0x40409d20,
+ 0x517c: 0x40409e20, 0x517d: 0x40409f20, 0x517e: 0x4040a020, 0x517f: 0x4040a120,
+ // Block 0x146, offset 0x5180
+ 0x5180: 0x4040a220, 0x5181: 0x4040a320, 0x5182: 0x4040a420, 0x5183: 0x4040a520,
+ 0x5184: 0x4040a620, 0x5185: 0x4040a720, 0x5186: 0x4040a820, 0x5187: 0x4040a920,
+ 0x5188: 0x4040aa20, 0x5189: 0x4040ab20, 0x518a: 0x4040ac20, 0x518b: 0x4040ad20,
+ 0x518c: 0x4040ae20, 0x518d: 0x4040af20, 0x518e: 0x4040b020, 0x518f: 0x4040b120,
+ 0x5190: 0x4040b220, 0x5191: 0x4040b320, 0x5192: 0x4040b420, 0x5193: 0x4040b520,
+ 0x5194: 0x4040b620, 0x5195: 0x4040b720, 0x5196: 0x4040b820, 0x5197: 0x4040b920,
+ 0x5198: 0x4040ba20, 0x5199: 0x4040bb20, 0x519a: 0x4040bc20, 0x519b: 0x4040bd20,
+ 0x519c: 0x4040be20, 0x519d: 0x4040bf20, 0x519e: 0x4040c020, 0x519f: 0x4040c120,
+ 0x51a0: 0x4040c220, 0x51a1: 0x4040c320, 0x51a2: 0x4040c420, 0x51a3: 0x4040c520,
+ 0x51a4: 0x4040c620, 0x51a5: 0x4040c720, 0x51a6: 0x4040c820, 0x51a7: 0x4040c920,
+ 0x51a8: 0x4040ca20, 0x51a9: 0x4040cb20, 0x51aa: 0x4040cc20, 0x51ab: 0x4040cd20,
+ 0x51ac: 0x4040ce20, 0x51ad: 0x4040cf20, 0x51ae: 0x4040d020, 0x51af: 0x4040d120,
+ 0x51b0: 0x4040d220, 0x51b1: 0x4040d320, 0x51b2: 0x4040d420, 0x51b3: 0x4040d520,
+ 0x51b4: 0x4040d620, 0x51b5: 0x4040d720, 0x51b6: 0x4040d820, 0x51b7: 0x4040d920,
+ 0x51b8: 0x4040da20, 0x51b9: 0x4040db20, 0x51ba: 0x4040dc20, 0x51bb: 0x4040dd20,
+ 0x51bc: 0x4040de20, 0x51bd: 0x4040df20, 0x51be: 0x4040e020, 0x51bf: 0x4040e120,
+ // Block 0x147, offset 0x51c0
+ 0x51c0: 0x4040e220, 0x51c1: 0x4040e320, 0x51c2: 0x4040e420, 0x51c3: 0x4040e520,
+ 0x51c4: 0x4040e620, 0x51c5: 0x4040e720, 0x51c6: 0x4040e820, 0x51c7: 0x4040e920,
+ 0x51c8: 0x4040ea20, 0x51c9: 0x4040eb20, 0x51ca: 0x4040ec20, 0x51cb: 0x4040ed20,
+ 0x51cc: 0x4040ee20, 0x51cd: 0x4040ef20, 0x51ce: 0x4040f020, 0x51cf: 0x4040f120,
+ 0x51d0: 0x4040f220, 0x51d1: 0x4040f320, 0x51d2: 0x4040f420, 0x51d3: 0x4040f520,
+ 0x51d4: 0x4040f620, 0x51d5: 0x4040f720, 0x51d6: 0x4040f820, 0x51d7: 0x4040f920,
+ 0x51d8: 0x4040fa20, 0x51d9: 0x4040fb20, 0x51da: 0x4040fc20, 0x51db: 0x4040fd20,
+ 0x51dc: 0x4040fe20, 0x51dd: 0x4040ff20, 0x51de: 0x40410020, 0x51df: 0x40410120,
+ 0x51e0: 0x40410220, 0x51e1: 0x40410320, 0x51e2: 0x40410420, 0x51e3: 0x40410520,
+ 0x51e4: 0x40410620, 0x51e5: 0x40410720, 0x51e6: 0x40410820, 0x51e7: 0x40410920,
+ 0x51e8: 0x40410a20, 0x51e9: 0x40410b20, 0x51ea: 0x40410c20, 0x51eb: 0x40410d20,
+ 0x51ec: 0x40410e20, 0x51ed: 0x40410f20, 0x51ee: 0x40411020, 0x51ef: 0x40411120,
+ 0x51f0: 0x40411220, 0x51f1: 0x40411320, 0x51f2: 0x40411420, 0x51f3: 0x40411520,
+ 0x51f4: 0x40411620, 0x51f5: 0x40411720, 0x51f6: 0x40411820, 0x51f7: 0x40411920,
+ 0x51f8: 0x40411a20, 0x51f9: 0x40411b20, 0x51fa: 0x40411c20, 0x51fb: 0x40411d20,
+ 0x51fc: 0x40411e20, 0x51fd: 0x40411f20, 0x51fe: 0x40412020, 0x51ff: 0x40412120,
+ // Block 0x148, offset 0x5200
+ 0x5200: 0x40412220, 0x5201: 0x40412320, 0x5202: 0x40412420, 0x5203: 0x40412520,
+ 0x5204: 0x40412620, 0x5205: 0x40412720, 0x5206: 0x40412820, 0x5207: 0x40412920,
+ 0x5208: 0x40412a20, 0x5209: 0x40412b20, 0x520a: 0x40412c20, 0x520b: 0x40412d20,
+ 0x520c: 0x40412e20, 0x520d: 0x40412f20, 0x520e: 0x40413020, 0x520f: 0x40413120,
+ 0x5210: 0x40413220, 0x5211: 0x40413320, 0x5212: 0x40413420, 0x5213: 0x40413520,
+ 0x5214: 0x40413620, 0x5215: 0x40413720, 0x5216: 0x40413820, 0x5217: 0x40413920,
+ 0x5218: 0x40413a20, 0x5219: 0x40413b20, 0x521a: 0x40413c20, 0x521b: 0x40413d20,
+ 0x521c: 0x40413e20, 0x521d: 0x40413f20, 0x521e: 0x40414020, 0x521f: 0x40414120,
+ 0x5220: 0x40414220, 0x5221: 0x40414320, 0x5222: 0x40414420, 0x5223: 0x40414520,
+ 0x5224: 0x40414620, 0x5225: 0x40414720, 0x5226: 0x40414820, 0x5227: 0x40414920,
+ 0x5228: 0x40414a20, 0x5229: 0x40414b20, 0x522a: 0x40414c20, 0x522b: 0x40414d20,
+ 0x522c: 0x40414e20, 0x522d: 0x40414f20, 0x522e: 0x40415020,
+ // Block 0x149, offset 0x5240
+ 0x5240: 0x402df820, 0x5241: 0x402df920, 0x5242: 0x402dfa20, 0x5243: 0x402dfb20,
+ 0x5244: 0x402dfc20, 0x5245: 0x402dfd20, 0x5246: 0x402dfe20, 0x5247: 0x402dff20,
+ 0x5248: 0x402e0020, 0x5249: 0x402e0120, 0x524a: 0x402e0220, 0x524b: 0x402e0320,
+ 0x524c: 0x402e0420, 0x524d: 0x402e0520, 0x524e: 0x402e0620, 0x524f: 0x402e0720,
+ 0x5250: 0x402e0820, 0x5251: 0x402e0920, 0x5252: 0x402e0a20, 0x5253: 0x402e0b20,
+ 0x5254: 0x402e0c20, 0x5255: 0x402e0d20, 0x5256: 0x402e0e20, 0x5257: 0x402e0f20,
+ 0x5258: 0x402e1020, 0x5259: 0x402e1120, 0x525a: 0x402e1220, 0x525b: 0x402e1320,
+ 0x525c: 0x402e1420, 0x525d: 0x402e1520, 0x525e: 0x402e1620, 0x525f: 0x402e1720,
+ 0x5260: 0x402e1820, 0x5261: 0x402e1920, 0x5262: 0x402e1a20, 0x5263: 0x402e1b20,
+ 0x5264: 0x402e1c20, 0x5265: 0x402e1d20, 0x5266: 0x402e1e20, 0x5267: 0x402e1f20,
+ 0x5268: 0x402e2020, 0x5269: 0x402e2120, 0x526a: 0x402e2220, 0x526b: 0x402e2320,
+ 0x526c: 0x402e2420, 0x526d: 0x402e2520, 0x526e: 0x402e2620, 0x526f: 0x402e2720,
+ 0x5270: 0x402e2820, 0x5271: 0x402e2920, 0x5272: 0x402e2a20, 0x5273: 0x402e2b20,
+ 0x5274: 0x402e2c20, 0x5275: 0x402e2d20, 0x5276: 0x402e2e20, 0x5277: 0x402e2f20,
+ 0x5278: 0x402e3020, 0x5279: 0x402e3120, 0x527a: 0x402e3220, 0x527b: 0x402e3320,
+ 0x527c: 0x402e3420, 0x527d: 0x402e3520, 0x527e: 0x402e3620, 0x527f: 0x402e3720,
+ // Block 0x14a, offset 0x5280
+ 0x5280: 0x402e3820, 0x5281: 0x402e3920, 0x5282: 0x402e3a20, 0x5283: 0x402e3b20,
+ 0x5284: 0x402e3c20, 0x5285: 0x402e3d20, 0x5286: 0x402e3e20, 0x5287: 0x402e3f20,
+ 0x5288: 0x402e4020, 0x5289: 0x402e4120, 0x528a: 0x402e4220, 0x528b: 0x402e4320,
+ 0x528c: 0x402e4420, 0x528d: 0x402e4520, 0x528e: 0x402e4620, 0x528f: 0x402e4720,
+ 0x5290: 0x402e4820, 0x5291: 0x402e4920, 0x5292: 0x402e4a20, 0x5293: 0x402e4b20,
+ 0x5294: 0x402e4c20, 0x5295: 0x402e4d20, 0x5296: 0x402e4e20, 0x5297: 0x402e4f20,
+ 0x5298: 0x402e5020, 0x5299: 0x402e5120, 0x529a: 0x402e5220, 0x529b: 0x402e5320,
+ 0x529c: 0x402e5420, 0x529d: 0x402e5520, 0x529e: 0x402e5620, 0x529f: 0x402e5720,
+ 0x52a0: 0x402e5820, 0x52a1: 0x402e5920, 0x52a2: 0x402e5a20, 0x52a3: 0x402e5b20,
+ 0x52a4: 0x402e5c20, 0x52a5: 0x402e5d20, 0x52a6: 0x402e5e20, 0x52a7: 0x402e5f20,
+ 0x52a8: 0x402e6020, 0x52a9: 0x402e6120, 0x52aa: 0x402e6220, 0x52ab: 0x402e6320,
+ 0x52ac: 0x402e6420, 0x52ad: 0x402e6520, 0x52ae: 0x402e6620, 0x52af: 0x402e6720,
+ 0x52b0: 0x402e6820, 0x52b1: 0x402e6920, 0x52b2: 0x402e6a20, 0x52b3: 0x402e6b20,
+ 0x52b4: 0x402e6c20, 0x52b5: 0x402e6d20, 0x52b6: 0x402e6e20, 0x52b7: 0x402e6f20,
+ 0x52b8: 0x402e7020, 0x52b9: 0x402e7120, 0x52ba: 0x402e7220, 0x52bb: 0x402e7320,
+ 0x52bc: 0x402e7420, 0x52bd: 0x402e7520, 0x52be: 0x402e7620, 0x52bf: 0x402e7720,
+ // Block 0x14b, offset 0x52c0
+ 0x52c0: 0x402e7820, 0x52c1: 0x402e7920, 0x52c2: 0x402e7a20, 0x52c3: 0x402e7b20,
+ 0x52c4: 0x402e7c20, 0x52c5: 0x402e7d20, 0x52c6: 0x402e7e20, 0x52c7: 0x402e7f20,
+ 0x52c8: 0x402e8020, 0x52c9: 0x402e8120, 0x52ca: 0x402e8220, 0x52cb: 0x402e8320,
+ 0x52cc: 0x402e8420, 0x52cd: 0x402e8520, 0x52ce: 0x402e8620, 0x52cf: 0x402e8720,
+ 0x52d0: 0x402e8820, 0x52d1: 0x402e8920, 0x52d2: 0x402e8a20, 0x52d3: 0x402e8b20,
+ 0x52d4: 0x402e8c20, 0x52d5: 0x402e8d20, 0x52d6: 0x402e8e20, 0x52d7: 0x402e8f20,
+ 0x52d8: 0x402e9020, 0x52d9: 0x402e9120, 0x52da: 0x402e9220, 0x52db: 0x402e9320,
+ 0x52dc: 0x402e9420, 0x52dd: 0x402e9520, 0x52de: 0x402e9620, 0x52df: 0x402e9720,
+ 0x52e0: 0x402e9820, 0x52e1: 0x402e9920, 0x52e2: 0x402e9a20, 0x52e3: 0x402e9b20,
+ 0x52e4: 0x402e9c20, 0x52e5: 0x402e9d20, 0x52e6: 0x402e9e20, 0x52e7: 0x402e9f20,
+ 0x52e8: 0x402ea020, 0x52e9: 0x402ea120, 0x52ea: 0x402ea220, 0x52eb: 0x402ea320,
+ 0x52ec: 0x402ea420, 0x52ed: 0x402ea520, 0x52ee: 0x402ea620, 0x52ef: 0x402ea720,
+ 0x52f0: 0x402ea820, 0x52f1: 0x402ea920, 0x52f2: 0x402eaa20, 0x52f3: 0x402eab20,
+ 0x52f4: 0x402eac20, 0x52f5: 0x402ead20, 0x52f6: 0x402eae20, 0x52f7: 0x402eaf20,
+ 0x52f8: 0x402eb020, 0x52f9: 0x402eb120, 0x52fa: 0x402eb220, 0x52fb: 0x402eb320,
+ 0x52fc: 0x402eb420, 0x52fd: 0x402eb520, 0x52fe: 0x402eb620, 0x52ff: 0x402eb720,
+ // Block 0x14c, offset 0x5300
+ 0x5300: 0x402eb820, 0x5301: 0x402eb920, 0x5302: 0x402eba20, 0x5303: 0x402ebb20,
+ 0x5304: 0x402ebc20, 0x5305: 0x402ebd20, 0x5306: 0x402ebe20, 0x5307: 0x402ebf20,
+ 0x5308: 0x402ec020, 0x5309: 0x402ec120, 0x530a: 0x402ec220, 0x530b: 0x402ec320,
+ 0x530c: 0x402ec420, 0x530d: 0x402ec520, 0x530e: 0x402ec620, 0x530f: 0x402ec720,
+ 0x5310: 0x402ec820, 0x5311: 0x402ec920, 0x5312: 0x402eca20, 0x5313: 0x402ecb20,
+ 0x5314: 0x402ecc20, 0x5315: 0x402ecd20, 0x5316: 0x402ece20, 0x5317: 0x402ecf20,
+ 0x5318: 0x402ed020, 0x5319: 0x402ed120, 0x531a: 0x402ed220, 0x531b: 0x402ed320,
+ 0x531c: 0x402ed420, 0x531d: 0x402ed520, 0x531e: 0x402ed620, 0x531f: 0x402ed720,
+ 0x5320: 0x402ed820, 0x5321: 0x402ed920, 0x5322: 0x402eda20, 0x5323: 0x402edb20,
+ 0x5324: 0x402edc20, 0x5325: 0x402edd20, 0x5326: 0x402ede20, 0x5327: 0x402edf20,
+ 0x5328: 0x402ee020, 0x5329: 0x402ee120, 0x532a: 0x402ee220, 0x532b: 0x402ee320,
+ 0x532c: 0x402ee420, 0x532d: 0x402ee520, 0x532e: 0x402ee620, 0x532f: 0x402ee720,
+ 0x5330: 0x402ee820, 0x5331: 0x402ee920, 0x5332: 0x402eea20, 0x5333: 0x402eeb20,
+ 0x5334: 0x402eec20, 0x5335: 0x402eed20, 0x5336: 0x402eee20, 0x5337: 0x402eef20,
+ 0x5338: 0x402ef020, 0x5339: 0x402ef120, 0x533a: 0x402ef220, 0x533b: 0x402ef320,
+ 0x533c: 0x402ef420, 0x533d: 0x402ef520, 0x533e: 0x402ef620, 0x533f: 0x402ef720,
+ // Block 0x14d, offset 0x5340
+ 0x5340: 0x402ef820, 0x5341: 0x402ef920, 0x5342: 0x402efa20, 0x5343: 0x402efb20,
+ 0x5344: 0x402efc20, 0x5345: 0x402efd20, 0x5346: 0x402efe20, 0x5347: 0x402eff20,
+ 0x5348: 0x402f0020, 0x5349: 0x402f0120, 0x534a: 0x402f0220, 0x534b: 0x402f0320,
+ 0x534c: 0x402f0420, 0x534d: 0x402f0520, 0x534e: 0x402f0620, 0x534f: 0x402f0720,
+ 0x5350: 0x402f0820, 0x5351: 0x402f0920, 0x5352: 0x402f0a20, 0x5353: 0x402f0b20,
+ 0x5354: 0x402f0c20, 0x5355: 0x402f0d20, 0x5356: 0x402f0e20, 0x5357: 0x402f0f20,
+ 0x5358: 0x402f1020, 0x5359: 0x402f1120, 0x535a: 0x402f1220, 0x535b: 0x402f1320,
+ 0x535c: 0x402f1420, 0x535d: 0x402f1520, 0x535e: 0x402f1620, 0x535f: 0x402f1720,
+ 0x5360: 0x402f1820, 0x5361: 0x402f1920, 0x5362: 0x402f1a20, 0x5363: 0x402f1b20,
+ 0x5364: 0x402f1c20, 0x5365: 0x402f1d20, 0x5366: 0x402f1e20, 0x5367: 0x402f1f20,
+ 0x5368: 0x402f2020, 0x5369: 0x402f2120, 0x536a: 0x402f2220, 0x536b: 0x402f2320,
+ 0x536c: 0x402f2420, 0x536d: 0x402f2520, 0x536e: 0x402f2620, 0x536f: 0x402f2720,
+ 0x5370: 0x402f2820, 0x5371: 0x402f2920, 0x5372: 0x402f2a20, 0x5373: 0x402f2b20,
+ 0x5374: 0x402f2c20, 0x5375: 0x402f2d20, 0x5376: 0x402f2e20, 0x5377: 0x402f2f20,
+ 0x5378: 0x402f3020, 0x5379: 0x402f3120, 0x537a: 0x402f3220, 0x537b: 0x402f3320,
+ 0x537c: 0x402f3420, 0x537d: 0x402f3520, 0x537e: 0x402f3620, 0x537f: 0x402f3720,
+ // Block 0x14e, offset 0x5380
+ 0x5380: 0x402f3820, 0x5381: 0x402f3920, 0x5382: 0x402f3a20, 0x5383: 0x402f3b20,
+ 0x5384: 0x402f3c20, 0x5385: 0x402f3d20, 0x5386: 0x402f3e20, 0x5387: 0x402f3f20,
+ 0x5388: 0x402f4020, 0x5389: 0x402f4120, 0x538a: 0x402f4220, 0x538b: 0x402f4320,
+ 0x538c: 0x402f4420, 0x538d: 0x402f4520, 0x538e: 0x402f4620, 0x538f: 0x402f4720,
+ 0x5390: 0x402f4820, 0x5391: 0x402f4920, 0x5392: 0x402f4a20, 0x5393: 0x402f4b20,
+ 0x5394: 0x402f4c20, 0x5395: 0x402f4d20, 0x5396: 0x402f4e20, 0x5397: 0x402f4f20,
+ 0x5398: 0x402f5020, 0x5399: 0x402f5120, 0x539a: 0x402f5220, 0x539b: 0x402f5320,
+ 0x539c: 0x402f5420, 0x539d: 0x402f5520, 0x539e: 0x402f5620, 0x539f: 0x402f5720,
+ 0x53a0: 0x402f5820, 0x53a1: 0x402f5920, 0x53a2: 0x402f5a20, 0x53a3: 0x402f5b20,
+ 0x53a4: 0x402f5c20, 0x53a5: 0x402f5d20, 0x53a6: 0x402f5e20, 0x53a7: 0x402f5f20,
+ 0x53a8: 0x402f6020, 0x53a9: 0x402f6120, 0x53aa: 0x402f6220, 0x53ab: 0x402f6320,
+ 0x53ac: 0x402f6420, 0x53ad: 0x402f6520, 0x53ae: 0x402f6620, 0x53af: 0x402f6720,
+ 0x53b0: 0x402f6820, 0x53b1: 0x402f6920, 0x53b2: 0x402f6a20, 0x53b3: 0x402f6b20,
+ 0x53b4: 0x402f6c20, 0x53b5: 0x402f6d20, 0x53b6: 0x402f6e20, 0x53b7: 0x402f6f20,
+ 0x53b8: 0x402f7020, 0x53b9: 0x402f7120, 0x53ba: 0x402f7220, 0x53bb: 0x402f7320,
+ 0x53bc: 0x402f7420, 0x53bd: 0x402f7520, 0x53be: 0x402f7620, 0x53bf: 0x402f7720,
+ // Block 0x14f, offset 0x53c0
+ 0x53c0: 0x402f7820, 0x53c1: 0x402f7920, 0x53c2: 0x402f7a20, 0x53c3: 0x402f7b20,
+ 0x53c4: 0x402f7c20, 0x53c5: 0x402f7d20, 0x53c6: 0x402f7e20, 0x53c7: 0x402f7f20,
+ 0x53c8: 0x402f8020, 0x53c9: 0x402f8120, 0x53ca: 0x402f8220, 0x53cb: 0x402f8320,
+ 0x53cc: 0x402f8420, 0x53cd: 0x402f8520, 0x53ce: 0x402f8620, 0x53cf: 0x402f8720,
+ 0x53d0: 0x402f8820, 0x53d1: 0x402f8920, 0x53d2: 0x402f8a20, 0x53d3: 0x402f8b20,
+ 0x53d4: 0x402f8c20, 0x53d5: 0x402f8d20, 0x53d6: 0x402f8e20, 0x53d7: 0x402f8f20,
+ 0x53d8: 0x402f9020, 0x53d9: 0x402f9120, 0x53da: 0x402f9220, 0x53db: 0x402f9320,
+ 0x53dc: 0x402f9420, 0x53dd: 0x402f9520, 0x53de: 0x402f9620, 0x53df: 0x402f9720,
+ 0x53e0: 0x402f9820, 0x53e1: 0x402f9920, 0x53e2: 0x402f9a20, 0x53e3: 0x402f9b20,
+ 0x53e4: 0x402f9c20, 0x53e5: 0x402f9d20, 0x53e6: 0x402f9e20, 0x53e7: 0x402f9f20,
+ 0x53e8: 0x402fa020, 0x53e9: 0x402fa120, 0x53ea: 0x402fa220, 0x53eb: 0x402fa320,
+ 0x53ec: 0x402fa420, 0x53ed: 0x402fa520, 0x53ee: 0x402fa620, 0x53ef: 0x402fa720,
+ 0x53f0: 0x402fa820, 0x53f1: 0x402fa920, 0x53f2: 0x402faa20, 0x53f3: 0x402fab20,
+ 0x53f4: 0x402fac20, 0x53f5: 0x402fad20, 0x53f6: 0x402fae20, 0x53f7: 0x402faf20,
+ 0x53f8: 0x402fb020, 0x53f9: 0x402fb120, 0x53fa: 0x402fb220, 0x53fb: 0x402fb320,
+ 0x53fc: 0x402fb420, 0x53fd: 0x402fb520, 0x53fe: 0x402fb620, 0x53ff: 0x402fb720,
+ // Block 0x150, offset 0x5400
+ 0x5400: 0x402fb820, 0x5401: 0x402fb920, 0x5402: 0x402fba20, 0x5403: 0x402fbb20,
+ 0x5404: 0x402fbc20, 0x5405: 0x402fbd20, 0x5406: 0x402fbe20, 0x5407: 0x402fbf20,
+ 0x5408: 0x402fc020, 0x5409: 0x402fc120, 0x540a: 0x402fc220, 0x540b: 0x402fc320,
+ 0x540c: 0x402fc420, 0x540d: 0x402fc520, 0x540e: 0x402fc620, 0x540f: 0x402fc720,
+ 0x5410: 0x402fc820, 0x5411: 0x402fc920, 0x5412: 0x402fca20, 0x5413: 0x402fcb20,
+ 0x5414: 0x402fcc20, 0x5415: 0x402fcd20, 0x5416: 0x402fce20, 0x5417: 0x402fcf20,
+ 0x5418: 0x402fd020, 0x5419: 0x402fd120, 0x541a: 0x402fd220, 0x541b: 0x402fd320,
+ 0x541c: 0x402fd420, 0x541d: 0x402fd520, 0x541e: 0x402fd620, 0x541f: 0x402fd720,
+ 0x5420: 0x402fd820, 0x5421: 0x402fd920, 0x5422: 0x402fda20, 0x5423: 0x402fdb20,
+ 0x5424: 0x402fdc20, 0x5425: 0x402fdd20, 0x5426: 0x402fde20, 0x5427: 0x402fdf20,
+ 0x5428: 0x402fe020, 0x5429: 0x402fe120, 0x542a: 0x402fe220, 0x542b: 0x402fe320,
+ 0x542c: 0x402fe420, 0x542d: 0x402fe520, 0x542e: 0x402fe620, 0x542f: 0x402fe720,
+ 0x5430: 0x402fe820, 0x5431: 0x402fe920, 0x5432: 0x402fea20, 0x5433: 0x402feb20,
+ 0x5434: 0x402fec20, 0x5435: 0x402fed20, 0x5436: 0x402fee20, 0x5437: 0x402fef20,
+ 0x5438: 0x402ff020, 0x5439: 0x402ff120, 0x543a: 0x402ff220, 0x543b: 0x402ff320,
+ 0x543c: 0x402ff420, 0x543d: 0x402ff520, 0x543e: 0x402ff620, 0x543f: 0x402ff720,
+ // Block 0x151, offset 0x5440
+ 0x5440: 0x402ff820, 0x5441: 0x402ff920, 0x5442: 0x402ffa20, 0x5443: 0x402ffb20,
+ 0x5444: 0x402ffc20, 0x5445: 0x402ffd20, 0x5446: 0x402ffe20, 0x5447: 0x402fff20,
+ 0x5448: 0x40300020, 0x5449: 0x40300120, 0x544a: 0x40300220, 0x544b: 0x40300320,
+ 0x544c: 0x40300420, 0x544d: 0x40300520, 0x544e: 0x40300620, 0x544f: 0x40300720,
+ 0x5450: 0x40300820, 0x5451: 0x40300920, 0x5452: 0x40300a20, 0x5453: 0x40300b20,
+ 0x5454: 0x40300c20, 0x5455: 0x40300d20, 0x5456: 0x40300e20, 0x5457: 0x40300f20,
+ 0x5458: 0x40301020, 0x5459: 0x40301120, 0x545a: 0x40301220, 0x545b: 0x40301320,
+ 0x545c: 0x40301420, 0x545d: 0x40301520, 0x545e: 0x40301620, 0x545f: 0x40301720,
+ 0x5460: 0x40301820, 0x5461: 0x40301920, 0x5462: 0x40301a20, 0x5463: 0x40301b20,
+ 0x5464: 0x40301c20, 0x5465: 0x40301d20, 0x5466: 0x40301e20, 0x5467: 0x40301f20,
+ 0x5468: 0x40302020, 0x5469: 0x40302120, 0x546a: 0x40302220, 0x546b: 0x40302320,
+ 0x546c: 0x40302420, 0x546d: 0x40302520, 0x546e: 0x40302620, 0x546f: 0x40302720,
+ 0x5470: 0x40302820, 0x5471: 0x40302920, 0x5472: 0x40302a20, 0x5473: 0x40302b20,
+ 0x5474: 0x40302c20, 0x5475: 0x40302d20, 0x5476: 0x40302e20, 0x5477: 0x40302f20,
+ 0x5478: 0x40303020,
+ // Block 0x152, offset 0x5480
+ 0x5480: 0x40319920, 0x5481: 0x4031bc20,
+ // Block 0x153, offset 0x54c0
+ 0x54c0: 0x400d9c20, 0x54c1: 0x400d9d20, 0x54c2: 0x400d9e20, 0x54c3: 0x400d9f20,
+ 0x54c4: 0x400da020, 0x54c5: 0x400da120, 0x54c6: 0x400da220, 0x54c7: 0x400da320,
+ 0x54c8: 0x400da420, 0x54c9: 0x400da520, 0x54ca: 0x400da620, 0x54cb: 0x400da720,
+ 0x54cc: 0x400da820, 0x54cd: 0x400da920, 0x54ce: 0x400daa20, 0x54cf: 0x400dab20,
+ 0x54d0: 0x400dac20, 0x54d1: 0x400dad20, 0x54d2: 0x400dae20, 0x54d3: 0x400daf20,
+ 0x54d4: 0x400db020, 0x54d5: 0x400db120, 0x54d6: 0x400db220, 0x54d7: 0x400db320,
+ 0x54d8: 0x400db420, 0x54d9: 0x400db520, 0x54da: 0x400db620, 0x54db: 0x400db720,
+ 0x54dc: 0x400db820, 0x54dd: 0x400db920, 0x54de: 0x400dba20, 0x54df: 0x400dbb20,
+ 0x54e0: 0x400dbc20, 0x54e1: 0x400dbd20, 0x54e2: 0x400dbe20, 0x54e3: 0x400dbf20,
+ 0x54e4: 0x400dc020, 0x54e5: 0x400dc120, 0x54e6: 0x400dc220, 0x54e7: 0x400dc320,
+ 0x54e8: 0x400dc420, 0x54e9: 0x400dc520, 0x54ea: 0x400dc620, 0x54eb: 0x400dc720,
+ 0x54ec: 0x400dc820, 0x54ed: 0x400dc920, 0x54ee: 0x400dca20, 0x54ef: 0x400dcb20,
+ 0x54f0: 0x400dcc20, 0x54f1: 0x400dcd20, 0x54f2: 0x400dce20, 0x54f3: 0x400dcf20,
+ 0x54f4: 0x400dd020, 0x54f5: 0x400dd120, 0x54f6: 0x400dd220, 0x54f7: 0x400dd320,
+ 0x54f8: 0x400dd420, 0x54f9: 0x400dd520, 0x54fa: 0x400dd620, 0x54fb: 0x400dd720,
+ 0x54fc: 0x400dd820, 0x54fd: 0x400dd920, 0x54fe: 0x400dda20, 0x54ff: 0x400ddb20,
+ // Block 0x154, offset 0x5500
+ 0x5500: 0x400ddc20, 0x5501: 0x400ddd20, 0x5502: 0x400dde20, 0x5503: 0x400ddf20,
+ 0x5504: 0x400de020, 0x5505: 0x400de120, 0x5506: 0x400de220, 0x5507: 0x400de320,
+ 0x5508: 0x400de420, 0x5509: 0x400de520, 0x550a: 0x400de620, 0x550b: 0x400de720,
+ 0x550c: 0x400de820, 0x550d: 0x400de920, 0x550e: 0x400dea20, 0x550f: 0x400deb20,
+ 0x5510: 0x400dec20, 0x5511: 0x400ded20, 0x5512: 0x400dee20, 0x5513: 0x400def20,
+ 0x5514: 0x400df020, 0x5515: 0x400df120, 0x5516: 0x400df220, 0x5517: 0x400df320,
+ 0x5518: 0x400df420, 0x5519: 0x400df520, 0x551a: 0x400df620, 0x551b: 0x400df720,
+ 0x551c: 0x400df820, 0x551d: 0x400df920, 0x551e: 0x400dfa20, 0x551f: 0x400dfb20,
+ 0x5520: 0x400dfc20, 0x5521: 0x400dfd20, 0x5522: 0x400dfe20, 0x5523: 0x400dff20,
+ 0x5524: 0x400e0020, 0x5525: 0x400e0120, 0x5526: 0x400e0220, 0x5527: 0x400e0320,
+ 0x5528: 0x400e0420, 0x5529: 0x400e0520, 0x552a: 0x400e0620, 0x552b: 0x400e0720,
+ 0x552c: 0x400e0820, 0x552d: 0x400e0920, 0x552e: 0x400e0a20, 0x552f: 0x400e0b20,
+ 0x5530: 0x400e0c20, 0x5531: 0x400e0d20, 0x5532: 0x400e0e20, 0x5533: 0x400e0f20,
+ 0x5534: 0x400e1020, 0x5535: 0x400e1120, 0x5536: 0x400e1220, 0x5537: 0x400e1320,
+ 0x5538: 0x400e1420, 0x5539: 0x400e1520, 0x553a: 0x400e1620, 0x553b: 0x400e1720,
+ 0x553c: 0x400e1820, 0x553d: 0x400e1920, 0x553e: 0x400e1a20, 0x553f: 0x400e1b20,
+ // Block 0x155, offset 0x5540
+ 0x5540: 0x400e1c20, 0x5541: 0x400e1d20, 0x5542: 0x400e1e20, 0x5543: 0x400e1f20,
+ 0x5544: 0x400e2020, 0x5545: 0x400e2120, 0x5546: 0x400e2220, 0x5547: 0x400e2320,
+ 0x5548: 0x400e2420, 0x5549: 0x400e2520, 0x554a: 0x400e2620, 0x554b: 0x400e2720,
+ 0x554c: 0x400e2820, 0x554d: 0x400e2920, 0x554e: 0x400e2a20, 0x554f: 0x400e2b20,
+ 0x5550: 0x400e2c20, 0x5551: 0x400e2d20, 0x5552: 0x400e2e20, 0x5553: 0x400e2f20,
+ 0x5554: 0x400e3020, 0x5555: 0x400e3120, 0x5556: 0x400e3220, 0x5557: 0x400e3320,
+ 0x5558: 0x400e3420, 0x5559: 0x400e3520, 0x555a: 0x400e3620, 0x555b: 0x400e3720,
+ 0x555c: 0x400e3820, 0x555d: 0x400e3920, 0x555e: 0x400e3a20, 0x555f: 0x400e3b20,
+ 0x5560: 0x400e3c20, 0x5561: 0x400e3d20, 0x5562: 0x400e3e20, 0x5563: 0x400e3f20,
+ 0x5564: 0x400e4020, 0x5565: 0x400e4120, 0x5566: 0x400e4220, 0x5567: 0x400e4320,
+ 0x5568: 0x400e4420, 0x5569: 0x400e4520, 0x556a: 0x400e4620, 0x556b: 0x400e4720,
+ 0x556c: 0x400e4820, 0x556d: 0x400e4920, 0x556e: 0x400e4a20, 0x556f: 0x400e4b20,
+ 0x5570: 0x400e4c20, 0x5571: 0x400e4d20, 0x5572: 0x400e4e20, 0x5573: 0x400e4f20,
+ 0x5574: 0x400e5020, 0x5575: 0x400e5120, 0x5576: 0x400e5220, 0x5577: 0x400e5320,
+ 0x5578: 0x400e5420, 0x5579: 0x400e5520, 0x557a: 0x400e5620, 0x557b: 0x400e5720,
+ 0x557c: 0x400e5820, 0x557d: 0x400e5920, 0x557e: 0x400e5a20, 0x557f: 0x400e5b20,
+ // Block 0x156, offset 0x5580
+ 0x5580: 0x400e5c20, 0x5581: 0x400e5d20, 0x5582: 0x400e5e20, 0x5583: 0x400e5f20,
+ 0x5584: 0x400e6020, 0x5585: 0x400e6120, 0x5586: 0x400e6220, 0x5587: 0x400e6320,
+ 0x5588: 0x400e6420, 0x5589: 0x400e6520, 0x558a: 0x400e6620, 0x558b: 0x400e6720,
+ 0x558c: 0x400e6820, 0x558d: 0x400e6920, 0x558e: 0x400e6a20, 0x558f: 0x400e6b20,
+ 0x5590: 0x400e6c20, 0x5591: 0x400e6d20, 0x5592: 0x400e6e20, 0x5593: 0x400e6f20,
+ 0x5594: 0x400e7020, 0x5595: 0x400e7120, 0x5596: 0x400e7220, 0x5597: 0x400e7320,
+ 0x5598: 0x400e7420, 0x5599: 0x400e7520, 0x559a: 0x400e7620, 0x559b: 0x400e7720,
+ 0x559c: 0x400e7820, 0x559d: 0x400e7920, 0x559e: 0x400e7a20, 0x559f: 0x400e7b20,
+ 0x55a0: 0x400e7c20, 0x55a1: 0x400e7d20, 0x55a2: 0x400e7e20, 0x55a3: 0x400e7f20,
+ 0x55a4: 0x400e8020, 0x55a5: 0x400e8120, 0x55a6: 0x400e8220, 0x55a7: 0x400e8320,
+ 0x55a8: 0x400e8420, 0x55a9: 0x400e8520, 0x55aa: 0x400e8620, 0x55ab: 0x400e8720,
+ 0x55ac: 0x400e8820, 0x55ad: 0x400e8920, 0x55ae: 0x400e8a20, 0x55af: 0x400e8b20,
+ 0x55b0: 0x400e8c20, 0x55b1: 0x400e8d20, 0x55b2: 0x400e8e20, 0x55b3: 0x400e8f20,
+ 0x55b4: 0x400e9020, 0x55b5: 0x400e9120,
+ // Block 0x157, offset 0x55c0
+ 0x55c0: 0x400e9220, 0x55c1: 0x400e9320, 0x55c2: 0x400e9420, 0x55c3: 0x400e9520,
+ 0x55c4: 0x400e9620, 0x55c5: 0x400e9720, 0x55c6: 0x400e9820, 0x55c7: 0x400e9920,
+ 0x55c8: 0x400e9a20, 0x55c9: 0x400e9b20, 0x55ca: 0x400e9c20, 0x55cb: 0x400e9d20,
+ 0x55cc: 0x400e9e20, 0x55cd: 0x400e9f20, 0x55ce: 0x400ea020, 0x55cf: 0x400ea120,
+ 0x55d0: 0x400ea220, 0x55d1: 0x400ea320, 0x55d2: 0x400ea420, 0x55d3: 0x400ea520,
+ 0x55d4: 0x400ea620, 0x55d5: 0x400ea720, 0x55d6: 0x400ea820, 0x55d7: 0x400ea920,
+ 0x55d8: 0x400eaa20, 0x55d9: 0x400eab20, 0x55da: 0x400eac20, 0x55db: 0x400ead20,
+ 0x55dc: 0x400eae20, 0x55dd: 0x400eaf20, 0x55de: 0x400eb020, 0x55df: 0x400eb120,
+ 0x55e0: 0x400eb220, 0x55e1: 0x400eb320, 0x55e2: 0x400eb420, 0x55e3: 0x400eb520,
+ 0x55e4: 0x400eb620, 0x55e5: 0x400eb720, 0x55e6: 0x400eb820,
+ 0x55e9: 0x400ecc20, 0x55ea: 0x400ebc20, 0x55eb: 0x400ebd20,
+ 0x55ec: 0x400ebe20, 0x55ed: 0x400ebf20, 0x55ee: 0x400ec020, 0x55ef: 0x400ec120,
+ 0x55f0: 0x400ec220, 0x55f1: 0x400ec320, 0x55f2: 0x400ec420, 0x55f3: 0x400ec520,
+ 0x55f4: 0x400ec620, 0x55f5: 0x400ec720, 0x55f6: 0x400ec820, 0x55f7: 0x400ec920,
+ 0x55f8: 0x400eca20, 0x55f9: 0x400ecb20, 0x55fa: 0x400ecd20, 0x55fb: 0x400ece20,
+ 0x55fc: 0x400ecf20, 0x55fd: 0x400ed020, 0x55fe: 0x400ed120, 0x55ff: 0x400ed220,
+ // Block 0x158, offset 0x5600
+ 0x5600: 0x400ed320, 0x5601: 0x400ed420, 0x5602: 0x400ed520, 0x5603: 0x400ed620,
+ 0x5604: 0x400ed720, 0x5605: 0x400ed820, 0x5606: 0x400ed920, 0x5607: 0x400eda20,
+ 0x5608: 0x400edb20, 0x5609: 0x400edc20, 0x560a: 0x400edd20, 0x560b: 0x400ede20,
+ 0x560c: 0x400edf20, 0x560d: 0x400ee020, 0x560e: 0x400ee120, 0x560f: 0x400ee220,
+ 0x5610: 0x400ee320, 0x5611: 0x400ee420, 0x5612: 0x400ee520, 0x5613: 0x400ee620,
+ 0x5614: 0x400ee720, 0x5615: 0x400ee820, 0x5616: 0x400ee920, 0x5617: 0x400eea20,
+ 0x5618: 0x400eeb20, 0x5619: 0x400eec20, 0x561a: 0x400eed20, 0x561b: 0x400eee20,
+ 0x561c: 0x400eef20, 0x561d: 0x400ef020, 0x561e: 0x400eea20, 0x561f: 0x400eeb20,
+ 0x5620: 0x400eeb20, 0x5621: 0x400eeb20, 0x5622: 0x400eeb20, 0x5623: 0x400eeb20,
+ 0x5624: 0x400eeb20, 0x5625: 0x80000000, 0x5626: 0x80000000, 0x5627: 0x80000000,
+ 0x5628: 0x80000000, 0x5629: 0x80000000, 0x562a: 0x400ef120, 0x562b: 0x400ef220,
+ 0x562c: 0x400ef320, 0x562d: 0x80000000, 0x562e: 0x80000000, 0x562f: 0x80000000,
+ 0x5630: 0x80000000, 0x5631: 0x80000000, 0x5632: 0x80000000, 0x5633: 0x80000000,
+ 0x5634: 0x80000000, 0x5635: 0x80000000, 0x5636: 0x80000000, 0x5637: 0x80000000,
+ 0x5638: 0x80000000, 0x5639: 0x80000000, 0x563a: 0x80000000, 0x563b: 0x80000000,
+ 0x563c: 0x80000000, 0x563d: 0x80000000, 0x563e: 0x80000000, 0x563f: 0x80000000,
+ // Block 0x159, offset 0x5640
+ 0x5640: 0x80000000, 0x5641: 0x80000000, 0x5642: 0x80000000, 0x5643: 0x400ef420,
+ 0x5644: 0x400ef520, 0x5645: 0x80000000, 0x5646: 0x80000000, 0x5647: 0x80000000,
+ 0x5648: 0x80000000, 0x5649: 0x80000000, 0x564a: 0x80000000, 0x564b: 0x80000000,
+ 0x564c: 0x400ef620, 0x564d: 0x400ef720, 0x564e: 0x400ef820, 0x564f: 0x400ef920,
+ 0x5650: 0x400efa20, 0x5651: 0x400efb20, 0x5652: 0x400efc20, 0x5653: 0x400efd20,
+ 0x5654: 0x400efe20, 0x5655: 0x400eff20, 0x5656: 0x400f0020, 0x5657: 0x400f0120,
+ 0x5658: 0x400f0220, 0x5659: 0x400f0320, 0x565a: 0x400f0420, 0x565b: 0x400f0520,
+ 0x565c: 0x400f0620, 0x565d: 0x400f0720, 0x565e: 0x400f0820, 0x565f: 0x400f0920,
+ 0x5660: 0x400f0a20, 0x5661: 0x400f0b20, 0x5662: 0x400f0c20, 0x5663: 0x400f0d20,
+ 0x5664: 0x400f0e20, 0x5665: 0x400f0f20, 0x5666: 0x400f1020, 0x5667: 0x400f1120,
+ 0x5668: 0x400f1220, 0x5669: 0x400f1320, 0x566a: 0x80000000, 0x566b: 0x80000000,
+ 0x566c: 0x80000000, 0x566d: 0x80000000, 0x566e: 0x400f1420, 0x566f: 0x400f1520,
+ 0x5670: 0x400f1620, 0x5671: 0x400f1720, 0x5672: 0x400f1820, 0x5673: 0x400f1920,
+ 0x5674: 0x400f1a20, 0x5675: 0x400f1b20, 0x5676: 0x400f1c20, 0x5677: 0x400f1d20,
+ 0x5678: 0x400f1e20, 0x5679: 0x400f1f20, 0x567a: 0x400f2020, 0x567b: 0x400f1f20,
+ 0x567c: 0x400f2020, 0x567d: 0x400f1f20, 0x567e: 0x400f2020, 0x567f: 0x400f1f20,
+ // Block 0x15a, offset 0x5680
+ 0x5680: 0x400f2020, 0x5681: 0x400f2120, 0x5682: 0x400f2220, 0x5683: 0x400f2320,
+ 0x5684: 0x400f2420, 0x5685: 0x400f2520, 0x5686: 0x400f2620, 0x5687: 0x400f2720,
+ 0x5688: 0x400f2820, 0x5689: 0x400f2920, 0x568a: 0x400f2a20, 0x568b: 0x400f2b20,
+ 0x568c: 0x400f2c20, 0x568d: 0x400f2d20, 0x568e: 0x400f2e20, 0x568f: 0x400f2f20,
+ 0x5690: 0x400f3020, 0x5691: 0x400f3120, 0x5692: 0x400f3220, 0x5693: 0x400f3320,
+ 0x5694: 0x400f3420, 0x5695: 0x400f3520, 0x5696: 0x400f3620, 0x5697: 0x400f3720,
+ 0x5698: 0x400f3820, 0x5699: 0x400f3920, 0x569a: 0x400f3a20, 0x569b: 0x400f3b20,
+ 0x569c: 0x400f3c20, 0x569d: 0x400f3d20,
+ // Block 0x15b, offset 0x56c0
+ 0x56c0: 0x400f3e20, 0x56c1: 0x400f3f20, 0x56c2: 0x400f4020, 0x56c3: 0x400f4120,
+ 0x56c4: 0x400f4220, 0x56c5: 0x400f4320, 0x56c6: 0x400f4420, 0x56c7: 0x400f4520,
+ 0x56c8: 0x400f4620, 0x56c9: 0x400f4720, 0x56ca: 0x400f4820, 0x56cb: 0x400f4920,
+ 0x56cc: 0x400f4a20, 0x56cd: 0x400f4b20, 0x56ce: 0x400f4c20, 0x56cf: 0x400f4d20,
+ 0x56d0: 0x400f4e20, 0x56d1: 0x400f4f20, 0x56d2: 0x400f5020, 0x56d3: 0x400f5120,
+ 0x56d4: 0x400f5220, 0x56d5: 0x400f5320, 0x56d6: 0x400f5420, 0x56d7: 0x400f5520,
+ 0x56d8: 0x400f5620, 0x56d9: 0x400f5720, 0x56da: 0x400f5820, 0x56db: 0x400f5920,
+ 0x56dc: 0x400f5a20, 0x56dd: 0x400f5b20, 0x56de: 0x400f5c20, 0x56df: 0x400f5d20,
+ 0x56e0: 0x400f5e20, 0x56e1: 0x400f5f20, 0x56e2: 0x400f6020, 0x56e3: 0x400f6120,
+ 0x56e4: 0x400f6220, 0x56e5: 0x400f6320, 0x56e6: 0x400f6420, 0x56e7: 0x400f6520,
+ 0x56e8: 0x400f6620, 0x56e9: 0x400f6720, 0x56ea: 0x400f6820, 0x56eb: 0x400f6920,
+ 0x56ec: 0x400f6a20, 0x56ed: 0x400f6b20, 0x56ee: 0x400f6c20, 0x56ef: 0x400f6d20,
+ 0x56f0: 0x400f6e20, 0x56f1: 0x400f6f20, 0x56f2: 0x400f7020, 0x56f3: 0x400f7120,
+ 0x56f4: 0x400f7220, 0x56f5: 0x400f7320, 0x56f6: 0x400f7420, 0x56f7: 0x400f7520,
+ 0x56f8: 0x400f7620, 0x56f9: 0x400f7720, 0x56fa: 0x400f7820, 0x56fb: 0x400f7920,
+ 0x56fc: 0x400f7a20, 0x56fd: 0x400f7b20, 0x56fe: 0x400f7c20, 0x56ff: 0x400f7d20,
+ // Block 0x15c, offset 0x5700
+ 0x5700: 0x400f7e20, 0x5701: 0x400f7f20, 0x5702: 0x80000000, 0x5703: 0x80000000,
+ 0x5704: 0x80000000, 0x5705: 0x400f8020,
+ // Block 0x15d, offset 0x5740
+ 0x5740: 0x400cbb20, 0x5741: 0x400cbc20, 0x5742: 0x400cbd20, 0x5743: 0x400cbe20,
+ 0x5744: 0x400cbf20, 0x5745: 0x400cc020, 0x5746: 0x400cc120, 0x5747: 0x400cc220,
+ 0x5748: 0x400cc320, 0x5749: 0x400cc420, 0x574a: 0x400cc520, 0x574b: 0x400cc620,
+ 0x574c: 0x400cc720, 0x574d: 0x400cc820, 0x574e: 0x400cc920, 0x574f: 0x400cca20,
+ 0x5750: 0x400ccb20, 0x5751: 0x400ccc20, 0x5752: 0x400ccd20, 0x5753: 0x400cce20,
+ 0x5754: 0x400ccf20, 0x5755: 0x400cd020, 0x5756: 0x400cd120, 0x5757: 0x400cd220,
+ 0x5758: 0x400cd320, 0x5759: 0x400cd420, 0x575a: 0x400cd520, 0x575b: 0x400cd620,
+ 0x575c: 0x400cd720, 0x575d: 0x400cd820, 0x575e: 0x400cd920, 0x575f: 0x400cda20,
+ 0x5760: 0x400cdb20, 0x5761: 0x400cdc20, 0x5762: 0x400cdd20, 0x5763: 0x400cde20,
+ 0x5764: 0x400cdf20, 0x5765: 0x400ce020, 0x5766: 0x400ce120, 0x5767: 0x400ce220,
+ 0x5768: 0x400ce320, 0x5769: 0x400ce420, 0x576a: 0x400ce520, 0x576b: 0x400ce620,
+ 0x576c: 0x400ce720, 0x576d: 0x400ce820, 0x576e: 0x400ce920, 0x576f: 0x400cea20,
+ 0x5770: 0x400ceb20, 0x5771: 0x400cec20, 0x5772: 0x400ced20, 0x5773: 0x400cee20,
+ 0x5774: 0x400cef20, 0x5775: 0x400cf020, 0x5776: 0x400cf120, 0x5777: 0x400cf220,
+ 0x5778: 0x400cf320, 0x5779: 0x400cf420, 0x577a: 0x400cf520, 0x577b: 0x400cf620,
+ 0x577c: 0x400cf720, 0x577d: 0x400cf820, 0x577e: 0x400cf920, 0x577f: 0x400cfa20,
+ // Block 0x15e, offset 0x5780
+ 0x5780: 0x400cfb20, 0x5781: 0x400cfc20, 0x5782: 0x400cfd20, 0x5783: 0x400cfe20,
+ 0x5784: 0x400cff20, 0x5785: 0x400d0020, 0x5786: 0x400d0120, 0x5787: 0x400d0220,
+ 0x5788: 0x400d0320, 0x5789: 0x400d0420, 0x578a: 0x400d0520, 0x578b: 0x400d0620,
+ 0x578c: 0x400d0720, 0x578d: 0x400d0820, 0x578e: 0x400d0920, 0x578f: 0x400d0a20,
+ 0x5790: 0x400d0b20, 0x5791: 0x400d0c20, 0x5792: 0x400d0d20, 0x5793: 0x400d0e20,
+ 0x5794: 0x400d0f20, 0x5795: 0x400d1020, 0x5796: 0x400d1120,
+ 0x57a0: 0xe0000156, 0x57a1: 0xe0000240, 0x57a2: 0xe0000306, 0x57a3: 0xe00003c0,
+ 0x57a4: 0xe0000477, 0x57a5: 0xe0000513, 0x57a6: 0xe00005af, 0x57a7: 0xe0000648,
+ 0x57a8: 0xe00006e7, 0x57a9: 0x40149120, 0x57aa: 0x40149220, 0x57ab: 0x40149320,
+ 0x57ac: 0x40149420, 0x57ad: 0x40149520, 0x57ae: 0x40149620, 0x57af: 0x40149720,
+ 0x57b0: 0x40149820, 0x57b1: 0x40149920,
+ // Block 0x15f, offset 0x57c0
+ 0x57c0: 0xf000000b, 0x57c1: 0xf000000b, 0x57c2: 0xf000000b, 0x57c3: 0xf000000b,
+ 0x57c4: 0xf000000b, 0x57c5: 0xf000000b, 0x57c6: 0xf000000b, 0x57c7: 0xf000000b,
+ 0x57c8: 0xf000000b, 0x57c9: 0xf000000b, 0x57ca: 0xf000000b, 0x57cb: 0xf000000b,
+ 0x57cc: 0xf000000b, 0x57cd: 0xf000000b, 0x57ce: 0xf000000b, 0x57cf: 0xf000000b,
+ 0x57d0: 0xf000000b, 0x57d1: 0xf000000b, 0x57d2: 0xf000000b, 0x57d3: 0xf000000b,
+ 0x57d4: 0xf000000b, 0x57d5: 0xf000000b, 0x57d6: 0xf000000b, 0x57d7: 0xf000000b,
+ 0x57d8: 0xf000000b, 0x57d9: 0xf000000b, 0x57da: 0xf0000005, 0x57db: 0xf0000005,
+ 0x57dc: 0xf0000005, 0x57dd: 0xf0000005, 0x57de: 0xf0000005, 0x57df: 0xf0000005,
+ 0x57e0: 0xf0000005, 0x57e1: 0xf0000005, 0x57e2: 0xf0000005, 0x57e3: 0xf0000005,
+ 0x57e4: 0xf0000005, 0x57e5: 0xf0000005, 0x57e6: 0xf0000005, 0x57e7: 0xf0000005,
+ 0x57e8: 0xf0000005, 0x57e9: 0xf0000005, 0x57ea: 0xf0000005, 0x57eb: 0xf0000005,
+ 0x57ec: 0xf0000005, 0x57ed: 0xf0000005, 0x57ee: 0xf0000005, 0x57ef: 0xf0000005,
+ 0x57f0: 0xf0000005, 0x57f1: 0xf0000005, 0x57f2: 0xf0000005, 0x57f3: 0xf0000005,
+ 0x57f4: 0xf000000b, 0x57f5: 0xf000000b, 0x57f6: 0xf000000b, 0x57f7: 0xf000000b,
+ 0x57f8: 0xf000000b, 0x57f9: 0xf000000b, 0x57fa: 0xf000000b, 0x57fb: 0xf000000b,
+ 0x57fc: 0xf000000b, 0x57fd: 0xf000000b, 0x57fe: 0xf000000b, 0x57ff: 0xf000000b,
+ // Block 0x160, offset 0x5800
+ 0x5800: 0xf000000b, 0x5801: 0xf000000b, 0x5802: 0xf000000b, 0x5803: 0xf000000b,
+ 0x5804: 0xf000000b, 0x5805: 0xf000000b, 0x5806: 0xf000000b, 0x5807: 0xf000000b,
+ 0x5808: 0xf000000b, 0x5809: 0xf000000b, 0x580a: 0xf000000b, 0x580b: 0xf000000b,
+ 0x580c: 0xf000000b, 0x580d: 0xf000000b, 0x580e: 0xf0000005, 0x580f: 0xf0000005,
+ 0x5810: 0xf0000005, 0x5811: 0xf0000005, 0x5812: 0xf0000005, 0x5813: 0xf0000005,
+ 0x5814: 0xf0000005, 0x5816: 0xf0000005, 0x5817: 0xf0000005,
+ 0x5818: 0xf0000005, 0x5819: 0xf0000005, 0x581a: 0xf0000005, 0x581b: 0xf0000005,
+ 0x581c: 0xf0000005, 0x581d: 0xf0000005, 0x581e: 0xf0000005, 0x581f: 0xf0000005,
+ 0x5820: 0xf0000005, 0x5821: 0xf0000005, 0x5822: 0xf0000005, 0x5823: 0xf0000005,
+ 0x5824: 0xf0000005, 0x5825: 0xf0000005, 0x5826: 0xf0000005, 0x5827: 0xf0000005,
+ 0x5828: 0xf000000b, 0x5829: 0xf000000b, 0x582a: 0xf000000b, 0x582b: 0xf000000b,
+ 0x582c: 0xf000000b, 0x582d: 0xf000000b, 0x582e: 0xf000000b, 0x582f: 0xf000000b,
+ 0x5830: 0xf000000b, 0x5831: 0xf000000b, 0x5832: 0xf000000b, 0x5833: 0xf000000b,
+ 0x5834: 0xf000000b, 0x5835: 0xf000000b, 0x5836: 0xf000000b, 0x5837: 0xf000000b,
+ 0x5838: 0xf000000b, 0x5839: 0xf000000b, 0x583a: 0xf000000b, 0x583b: 0xf000000b,
+ 0x583c: 0xf000000b, 0x583d: 0xf000000b, 0x583e: 0xf000000b, 0x583f: 0xf000000b,
+ // Block 0x161, offset 0x5840
+ 0x5840: 0xf000000b, 0x5841: 0xf000000b, 0x5842: 0xf0000005, 0x5843: 0xf0000005,
+ 0x5844: 0xf0000005, 0x5845: 0xf0000005, 0x5846: 0xf0000005, 0x5847: 0xf0000005,
+ 0x5848: 0xf0000005, 0x5849: 0xf0000005, 0x584a: 0xf0000005, 0x584b: 0xf0000005,
+ 0x584c: 0xf0000005, 0x584d: 0xf0000005, 0x584e: 0xf0000005, 0x584f: 0xf0000005,
+ 0x5850: 0xf0000005, 0x5851: 0xf0000005, 0x5852: 0xf0000005, 0x5853: 0xf0000005,
+ 0x5854: 0xf0000005, 0x5855: 0xf0000005, 0x5856: 0xf0000005, 0x5857: 0xf0000005,
+ 0x5858: 0xf0000005, 0x5859: 0xf0000005, 0x585a: 0xf0000005, 0x585b: 0xf0000005,
+ 0x585c: 0xf000000b, 0x585e: 0xf000000b, 0x585f: 0xf000000b,
+ 0x5862: 0xf000000b,
+ 0x5865: 0xf000000b, 0x5866: 0xf000000b,
+ 0x5869: 0xf000000b, 0x586a: 0xf000000b, 0x586b: 0xf000000b,
+ 0x586c: 0xf000000b, 0x586e: 0xf000000b, 0x586f: 0xf000000b,
+ 0x5870: 0xf000000b, 0x5871: 0xf000000b, 0x5872: 0xf000000b, 0x5873: 0xf000000b,
+ 0x5874: 0xf000000b, 0x5875: 0xf000000b, 0x5876: 0xf0000005, 0x5877: 0xf0000005,
+ 0x5878: 0xf0000005, 0x5879: 0xf0000005, 0x587b: 0xf0000005,
+ 0x587d: 0xf0000005, 0x587e: 0xf0000005, 0x587f: 0xf0000005,
+ // Block 0x162, offset 0x5880
+ 0x5880: 0xf0000005, 0x5881: 0xf0000005, 0x5882: 0xf0000005, 0x5883: 0xf0000005,
+ 0x5885: 0xf0000005, 0x5886: 0xf0000005, 0x5887: 0xf0000005,
+ 0x5888: 0xf0000005, 0x5889: 0xf0000005, 0x588a: 0xf0000005, 0x588b: 0xf0000005,
+ 0x588c: 0xf0000005, 0x588d: 0xf0000005, 0x588e: 0xf0000005, 0x588f: 0xf0000005,
+ 0x5890: 0xf000000b, 0x5891: 0xf000000b, 0x5892: 0xf000000b, 0x5893: 0xf000000b,
+ 0x5894: 0xf000000b, 0x5895: 0xf000000b, 0x5896: 0xf000000b, 0x5897: 0xf000000b,
+ 0x5898: 0xf000000b, 0x5899: 0xf000000b, 0x589a: 0xf000000b, 0x589b: 0xf000000b,
+ 0x589c: 0xf000000b, 0x589d: 0xf000000b, 0x589e: 0xf000000b, 0x589f: 0xf000000b,
+ 0x58a0: 0xf000000b, 0x58a1: 0xf000000b, 0x58a2: 0xf000000b, 0x58a3: 0xf000000b,
+ 0x58a4: 0xf000000b, 0x58a5: 0xf000000b, 0x58a6: 0xf000000b, 0x58a7: 0xf000000b,
+ 0x58a8: 0xf000000b, 0x58a9: 0xf000000b, 0x58aa: 0xf0000005, 0x58ab: 0xf0000005,
+ 0x58ac: 0xf0000005, 0x58ad: 0xf0000005, 0x58ae: 0xf0000005, 0x58af: 0xf0000005,
+ 0x58b0: 0xf0000005, 0x58b1: 0xf0000005, 0x58b2: 0xf0000005, 0x58b3: 0xf0000005,
+ 0x58b4: 0xf0000005, 0x58b5: 0xf0000005, 0x58b6: 0xf0000005, 0x58b7: 0xf0000005,
+ 0x58b8: 0xf0000005, 0x58b9: 0xf0000005, 0x58ba: 0xf0000005, 0x58bb: 0xf0000005,
+ 0x58bc: 0xf0000005, 0x58bd: 0xf0000005, 0x58be: 0xf0000005, 0x58bf: 0xf0000005,
+ // Block 0x163, offset 0x58c0
+ 0x58c0: 0xf0000005, 0x58c1: 0xf0000005, 0x58c2: 0xf0000005, 0x58c3: 0xf0000005,
+ 0x58c4: 0xf000000b, 0x58c5: 0xf000000b, 0x58c7: 0xf000000b,
+ 0x58c8: 0xf000000b, 0x58c9: 0xf000000b, 0x58ca: 0xf000000b,
+ 0x58cd: 0xf000000b, 0x58ce: 0xf000000b, 0x58cf: 0xf000000b,
+ 0x58d0: 0xf000000b, 0x58d1: 0xf000000b, 0x58d2: 0xf000000b, 0x58d3: 0xf000000b,
+ 0x58d4: 0xf000000b, 0x58d6: 0xf000000b, 0x58d7: 0xf000000b,
+ 0x58d8: 0xf000000b, 0x58d9: 0xf000000b, 0x58da: 0xf000000b, 0x58db: 0xf000000b,
+ 0x58dc: 0xf000000b, 0x58de: 0xf0000005, 0x58df: 0xf0000005,
+ 0x58e0: 0xf0000005, 0x58e1: 0xf0000005, 0x58e2: 0xf0000005, 0x58e3: 0xf0000005,
+ 0x58e4: 0xf0000005, 0x58e5: 0xf0000005, 0x58e6: 0xf0000005, 0x58e7: 0xf0000005,
+ 0x58e8: 0xf0000005, 0x58e9: 0xf0000005, 0x58ea: 0xf0000005, 0x58eb: 0xf0000005,
+ 0x58ec: 0xf0000005, 0x58ed: 0xf0000005, 0x58ee: 0xf0000005, 0x58ef: 0xf0000005,
+ 0x58f0: 0xf0000005, 0x58f1: 0xf0000005, 0x58f2: 0xf0000005, 0x58f3: 0xf0000005,
+ 0x58f4: 0xf0000005, 0x58f5: 0xf0000005, 0x58f6: 0xf0000005, 0x58f7: 0xf0000005,
+ 0x58f8: 0xf000000b, 0x58f9: 0xf000000b, 0x58fb: 0xf000000b,
+ 0x58fc: 0xf000000b, 0x58fd: 0xf000000b, 0x58fe: 0xf000000b,
+ // Block 0x164, offset 0x5900
+ 0x5900: 0xf000000b, 0x5901: 0xf000000b, 0x5902: 0xf000000b, 0x5903: 0xf000000b,
+ 0x5904: 0xf000000b, 0x5906: 0xf000000b,
+ 0x590a: 0xf000000b, 0x590b: 0xf000000b,
+ 0x590c: 0xf000000b, 0x590d: 0xf000000b, 0x590e: 0xf000000b, 0x590f: 0xf000000b,
+ 0x5910: 0xf000000b, 0x5912: 0xf0000005, 0x5913: 0xf0000005,
+ 0x5914: 0xf0000005, 0x5915: 0xf0000005, 0x5916: 0xf0000005, 0x5917: 0xf0000005,
+ 0x5918: 0xf0000005, 0x5919: 0xf0000005, 0x591a: 0xf0000005, 0x591b: 0xf0000005,
+ 0x591c: 0xf0000005, 0x591d: 0xf0000005, 0x591e: 0xf0000005, 0x591f: 0xf0000005,
+ 0x5920: 0xf0000005, 0x5921: 0xf0000005, 0x5922: 0xf0000005, 0x5923: 0xf0000005,
+ 0x5924: 0xf0000005, 0x5925: 0xf0000005, 0x5926: 0xf0000005, 0x5927: 0xf0000005,
+ 0x5928: 0xf0000005, 0x5929: 0xf0000005, 0x592a: 0xf0000005, 0x592b: 0xf0000005,
+ 0x592c: 0xf000000b, 0x592d: 0xf000000b, 0x592e: 0xf000000b, 0x592f: 0xf000000b,
+ 0x5930: 0xf000000b, 0x5931: 0xf000000b, 0x5932: 0xf000000b, 0x5933: 0xf000000b,
+ 0x5934: 0xf000000b, 0x5935: 0xf000000b, 0x5936: 0xf000000b, 0x5937: 0xf000000b,
+ 0x5938: 0xf000000b, 0x5939: 0xf000000b, 0x593a: 0xf000000b, 0x593b: 0xf000000b,
+ 0x593c: 0xf000000b, 0x593d: 0xf000000b, 0x593e: 0xf000000b, 0x593f: 0xf000000b,
+ // Block 0x165, offset 0x5940
+ 0x5940: 0xf000000b, 0x5941: 0xf000000b, 0x5942: 0xf000000b, 0x5943: 0xf000000b,
+ 0x5944: 0xf000000b, 0x5945: 0xf000000b, 0x5946: 0xf0000005, 0x5947: 0xf0000005,
+ 0x5948: 0xf0000005, 0x5949: 0xf0000005, 0x594a: 0xf0000005, 0x594b: 0xf0000005,
+ 0x594c: 0xf0000005, 0x594d: 0xf0000005, 0x594e: 0xf0000005, 0x594f: 0xf0000005,
+ 0x5950: 0xf0000005, 0x5951: 0xf0000005, 0x5952: 0xf0000005, 0x5953: 0xf0000005,
+ 0x5954: 0xf0000005, 0x5955: 0xf0000005, 0x5956: 0xf0000005, 0x5957: 0xf0000005,
+ 0x5958: 0xf0000005, 0x5959: 0xf0000005, 0x595a: 0xf0000005, 0x595b: 0xf0000005,
+ 0x595c: 0xf0000005, 0x595d: 0xf0000005, 0x595e: 0xf0000005, 0x595f: 0xf0000005,
+ 0x5960: 0xf000000b, 0x5961: 0xf000000b, 0x5962: 0xf000000b, 0x5963: 0xf000000b,
+ 0x5964: 0xf000000b, 0x5965: 0xf000000b, 0x5966: 0xf000000b, 0x5967: 0xf000000b,
+ 0x5968: 0xf000000b, 0x5969: 0xf000000b, 0x596a: 0xf000000b, 0x596b: 0xf000000b,
+ 0x596c: 0xf000000b, 0x596d: 0xf000000b, 0x596e: 0xf000000b, 0x596f: 0xf000000b,
+ 0x5970: 0xf000000b, 0x5971: 0xf000000b, 0x5972: 0xf000000b, 0x5973: 0xf000000b,
+ 0x5974: 0xf000000b, 0x5975: 0xf000000b, 0x5976: 0xf000000b, 0x5977: 0xf000000b,
+ 0x5978: 0xf000000b, 0x5979: 0xf000000b, 0x597a: 0xf0000005, 0x597b: 0xf0000005,
+ 0x597c: 0xf0000005, 0x597d: 0xf0000005, 0x597e: 0xf0000005, 0x597f: 0xf0000005,
+ // Block 0x166, offset 0x5980
+ 0x5980: 0xf0000005, 0x5981: 0xf0000005, 0x5982: 0xf0000005, 0x5983: 0xf0000005,
+ 0x5984: 0xf0000005, 0x5985: 0xf0000005, 0x5986: 0xf0000005, 0x5987: 0xf0000005,
+ 0x5988: 0xf0000005, 0x5989: 0xf0000005, 0x598a: 0xf0000005, 0x598b: 0xf0000005,
+ 0x598c: 0xf0000005, 0x598d: 0xf0000005, 0x598e: 0xf0000005, 0x598f: 0xf0000005,
+ 0x5990: 0xf0000005, 0x5991: 0xf0000005, 0x5992: 0xf0000005, 0x5993: 0xf0000005,
+ 0x5994: 0xf000000b, 0x5995: 0xf000000b, 0x5996: 0xf000000b, 0x5997: 0xf000000b,
+ 0x5998: 0xf000000b, 0x5999: 0xf000000b, 0x599a: 0xf000000b, 0x599b: 0xf000000b,
+ 0x599c: 0xf000000b, 0x599d: 0xf000000b, 0x599e: 0xf000000b, 0x599f: 0xf000000b,
+ 0x59a0: 0xf000000b, 0x59a1: 0xf000000b, 0x59a2: 0xf000000b, 0x59a3: 0xf000000b,
+ 0x59a4: 0xf000000b, 0x59a5: 0xf000000b, 0x59a6: 0xf000000b, 0x59a7: 0xf000000b,
+ 0x59a8: 0xf000000b, 0x59a9: 0xf000000b, 0x59aa: 0xf000000b, 0x59ab: 0xf000000b,
+ 0x59ac: 0xf000000b, 0x59ad: 0xf000000b, 0x59ae: 0xf0000005, 0x59af: 0xf0000005,
+ 0x59b0: 0xf0000005, 0x59b1: 0xf0000005, 0x59b2: 0xf0000005, 0x59b3: 0xf0000005,
+ 0x59b4: 0xf0000005, 0x59b5: 0xf0000005, 0x59b6: 0xf0000005, 0x59b7: 0xf0000005,
+ 0x59b8: 0xf0000005, 0x59b9: 0xf0000005, 0x59ba: 0xf0000005, 0x59bb: 0xf0000005,
+ 0x59bc: 0xf0000005, 0x59bd: 0xf0000005, 0x59be: 0xf0000005, 0x59bf: 0xf0000005,
+ // Block 0x167, offset 0x59c0
+ 0x59c0: 0xf0000005, 0x59c1: 0xf0000005, 0x59c2: 0xf0000005, 0x59c3: 0xf0000005,
+ 0x59c4: 0xf0000005, 0x59c5: 0xf0000005, 0x59c6: 0xf0000005, 0x59c7: 0xf0000005,
+ 0x59c8: 0xf000000b, 0x59c9: 0xf000000b, 0x59ca: 0xf000000b, 0x59cb: 0xf000000b,
+ 0x59cc: 0xf000000b, 0x59cd: 0xf000000b, 0x59ce: 0xf000000b, 0x59cf: 0xf000000b,
+ 0x59d0: 0xf000000b, 0x59d1: 0xf000000b, 0x59d2: 0xf000000b, 0x59d3: 0xf000000b,
+ 0x59d4: 0xf000000b, 0x59d5: 0xf000000b, 0x59d6: 0xf000000b, 0x59d7: 0xf000000b,
+ 0x59d8: 0xf000000b, 0x59d9: 0xf000000b, 0x59da: 0xf000000b, 0x59db: 0xf000000b,
+ 0x59dc: 0xf000000b, 0x59dd: 0xf000000b, 0x59de: 0xf000000b, 0x59df: 0xf000000b,
+ 0x59e0: 0xf000000b, 0x59e1: 0xf000000b, 0x59e2: 0xf0000005, 0x59e3: 0xf0000005,
+ 0x59e4: 0xf0000005, 0x59e5: 0xf0000005, 0x59e6: 0xf0000005, 0x59e7: 0xf0000005,
+ 0x59e8: 0xf0000005, 0x59e9: 0xf0000005, 0x59ea: 0xf0000005, 0x59eb: 0xf0000005,
+ 0x59ec: 0xf0000005, 0x59ed: 0xf0000005, 0x59ee: 0xf0000005, 0x59ef: 0xf0000005,
+ 0x59f0: 0xf0000005, 0x59f1: 0xf0000005, 0x59f2: 0xf0000005, 0x59f3: 0xf0000005,
+ 0x59f4: 0xf0000005, 0x59f5: 0xf0000005, 0x59f6: 0xf0000005, 0x59f7: 0xf0000005,
+ 0x59f8: 0xf0000005, 0x59f9: 0xf0000005, 0x59fa: 0xf0000005, 0x59fb: 0xf0000005,
+ 0x59fc: 0xf000000b, 0x59fd: 0xf000000b, 0x59fe: 0xf000000b, 0x59ff: 0xf000000b,
+ // Block 0x168, offset 0x5a00
+ 0x5a00: 0xf000000b, 0x5a01: 0xf000000b, 0x5a02: 0xf000000b, 0x5a03: 0xf000000b,
+ 0x5a04: 0xf000000b, 0x5a05: 0xf000000b, 0x5a06: 0xf000000b, 0x5a07: 0xf000000b,
+ 0x5a08: 0xf000000b, 0x5a09: 0xf000000b, 0x5a0a: 0xf000000b, 0x5a0b: 0xf000000b,
+ 0x5a0c: 0xf000000b, 0x5a0d: 0xf000000b, 0x5a0e: 0xf000000b, 0x5a0f: 0xf000000b,
+ 0x5a10: 0xf000000b, 0x5a11: 0xf000000b, 0x5a12: 0xf000000b, 0x5a13: 0xf000000b,
+ 0x5a14: 0xf000000b, 0x5a15: 0xf000000b, 0x5a16: 0xf0000005, 0x5a17: 0xf0000005,
+ 0x5a18: 0xf0000005, 0x5a19: 0xf0000005, 0x5a1a: 0xf0000005, 0x5a1b: 0xf0000005,
+ 0x5a1c: 0xf0000005, 0x5a1d: 0xf0000005, 0x5a1e: 0xf0000005, 0x5a1f: 0xf0000005,
+ 0x5a20: 0xf0000005, 0x5a21: 0xf0000005, 0x5a22: 0xf0000005, 0x5a23: 0xf0000005,
+ 0x5a24: 0xf0000005, 0x5a25: 0xf0000005, 0x5a26: 0xf0000005, 0x5a27: 0xf0000005,
+ 0x5a28: 0xf0000005, 0x5a29: 0xf0000005, 0x5a2a: 0xf0000005, 0x5a2b: 0xf0000005,
+ 0x5a2c: 0xf0000005, 0x5a2d: 0xf0000005, 0x5a2e: 0xf0000005, 0x5a2f: 0xf0000005,
+ 0x5a30: 0xf000000b, 0x5a31: 0xf000000b, 0x5a32: 0xf000000b, 0x5a33: 0xf000000b,
+ 0x5a34: 0xf000000b, 0x5a35: 0xf000000b, 0x5a36: 0xf000000b, 0x5a37: 0xf000000b,
+ 0x5a38: 0xf000000b, 0x5a39: 0xf000000b, 0x5a3a: 0xf000000b, 0x5a3b: 0xf000000b,
+ 0x5a3c: 0xf000000b, 0x5a3d: 0xf000000b, 0x5a3e: 0xf000000b, 0x5a3f: 0xf000000b,
+ // Block 0x169, offset 0x5a40
+ 0x5a40: 0xf000000b, 0x5a41: 0xf000000b, 0x5a42: 0xf000000b, 0x5a43: 0xf000000b,
+ 0x5a44: 0xf000000b, 0x5a45: 0xf000000b, 0x5a46: 0xf000000b, 0x5a47: 0xf000000b,
+ 0x5a48: 0xf000000b, 0x5a49: 0xf000000b, 0x5a4a: 0xf0000005, 0x5a4b: 0xf0000005,
+ 0x5a4c: 0xf0000005, 0x5a4d: 0xf0000005, 0x5a4e: 0xf0000005, 0x5a4f: 0xf0000005,
+ 0x5a50: 0xf0000005, 0x5a51: 0xf0000005, 0x5a52: 0xf0000005, 0x5a53: 0xf0000005,
+ 0x5a54: 0xf0000005, 0x5a55: 0xf0000005, 0x5a56: 0xf0000005, 0x5a57: 0xf0000005,
+ 0x5a58: 0xf0000005, 0x5a59: 0xf0000005, 0x5a5a: 0xf0000005, 0x5a5b: 0xf0000005,
+ 0x5a5c: 0xf0000005, 0x5a5d: 0xf0000005, 0x5a5e: 0xf0000005, 0x5a5f: 0xf0000005,
+ 0x5a60: 0xf0000005, 0x5a61: 0xf0000005, 0x5a62: 0xf0000005, 0x5a63: 0xf0000005,
+ 0x5a64: 0xf0000005, 0x5a65: 0xf0000005,
+ 0x5a68: 0xf000000b, 0x5a69: 0xf000000b, 0x5a6a: 0xf000000b, 0x5a6b: 0xf000000b,
+ 0x5a6c: 0xf000000b, 0x5a6d: 0xf000000b, 0x5a6e: 0xf000000b, 0x5a6f: 0xf000000b,
+ 0x5a70: 0xf000000b, 0x5a71: 0xf000000b, 0x5a72: 0xf000000b, 0x5a73: 0xf000000b,
+ 0x5a74: 0xf000000b, 0x5a75: 0xf000000b, 0x5a76: 0xf000000b, 0x5a77: 0xf000000b,
+ 0x5a78: 0xf000000b, 0x5a79: 0xf000000b, 0x5a7a: 0xf000000b, 0x5a7b: 0xf000000b,
+ 0x5a7c: 0xf000000b, 0x5a7d: 0xf000000b, 0x5a7e: 0xf000000b, 0x5a7f: 0xf000000b,
+ // Block 0x16a, offset 0x5a80
+ 0x5a80: 0xf000000b, 0x5a81: 0xf0000005, 0x5a82: 0xf0000005, 0x5a83: 0xf0000005,
+ 0x5a84: 0xf0000005, 0x5a85: 0xf0000005, 0x5a86: 0xf0000005, 0x5a87: 0xf0000005,
+ 0x5a88: 0xf0000005, 0x5a89: 0xf0000005, 0x5a8a: 0xf0000005, 0x5a8b: 0xf0000005,
+ 0x5a8c: 0xf0000005, 0x5a8d: 0xf0000005, 0x5a8e: 0xf0000005, 0x5a8f: 0xf0000005,
+ 0x5a90: 0xf0000005, 0x5a91: 0xf0000005, 0x5a92: 0xf0000005, 0x5a93: 0xf0000005,
+ 0x5a94: 0xf0000005, 0x5a95: 0xf0000005, 0x5a96: 0xf0000005, 0x5a97: 0xf0000005,
+ 0x5a98: 0xf0000005, 0x5a99: 0xf0000005, 0x5a9a: 0xf0000005, 0x5a9b: 0xf0000005,
+ 0x5a9c: 0xf0000005, 0x5a9d: 0xf0000005, 0x5a9e: 0xf0000005, 0x5a9f: 0xf0000005,
+ 0x5aa0: 0xf0000005, 0x5aa1: 0xf0000005, 0x5aa2: 0xf000000b, 0x5aa3: 0xf000000b,
+ 0x5aa4: 0xf000000b, 0x5aa5: 0xf000000b, 0x5aa6: 0xf000000b, 0x5aa7: 0xf000000b,
+ 0x5aa8: 0xf000000b, 0x5aa9: 0xf000000b, 0x5aaa: 0xf000000b, 0x5aab: 0xf000000b,
+ 0x5aac: 0xf000000b, 0x5aad: 0xf000000b, 0x5aae: 0xf000000b, 0x5aaf: 0xf000000b,
+ 0x5ab0: 0xf000000b, 0x5ab1: 0xf000000b, 0x5ab2: 0xf000000b, 0x5ab3: 0xf000000b,
+ 0x5ab4: 0xf000000b, 0x5ab5: 0xf000000b, 0x5ab6: 0xf000000b, 0x5ab7: 0xf000000b,
+ 0x5ab8: 0xf000000b, 0x5ab9: 0xf000000b, 0x5aba: 0xf000000b, 0x5abb: 0xf0000005,
+ 0x5abc: 0xf0000005, 0x5abd: 0xf0000005, 0x5abe: 0xf0000005, 0x5abf: 0xf0000005,
+ // Block 0x16b, offset 0x5ac0
+ 0x5ac0: 0xf0000005, 0x5ac1: 0xf0000005, 0x5ac2: 0xf0000005, 0x5ac3: 0xf0000005,
+ 0x5ac4: 0xf0000005, 0x5ac5: 0xf0000005, 0x5ac6: 0xf0000005, 0x5ac7: 0xf0000005,
+ 0x5ac8: 0xf0000005, 0x5ac9: 0xf0000005, 0x5aca: 0xf0000005, 0x5acb: 0xf0000005,
+ 0x5acc: 0xf0000005, 0x5acd: 0xf0000005, 0x5ace: 0xf0000005, 0x5acf: 0xf0000005,
+ 0x5ad0: 0xf0000005, 0x5ad1: 0xf0000005, 0x5ad2: 0xf0000005, 0x5ad3: 0xf0000005,
+ 0x5ad4: 0xf0000005, 0x5ad5: 0xf0000005, 0x5ad6: 0xf0000005, 0x5ad7: 0xf0000005,
+ 0x5ad8: 0xf0000005, 0x5ad9: 0xf0000005, 0x5ada: 0xf0000005, 0x5adb: 0xf0000005,
+ 0x5adc: 0xf000000b, 0x5add: 0xf000000b, 0x5ade: 0xf000000b, 0x5adf: 0xf000000b,
+ 0x5ae0: 0xf000000b, 0x5ae1: 0xf000000b, 0x5ae2: 0xf000000b, 0x5ae3: 0xf000000b,
+ 0x5ae4: 0xf000000b, 0x5ae5: 0xf000000b, 0x5ae6: 0xf000000b, 0x5ae7: 0xf000000b,
+ 0x5ae8: 0xf000000b, 0x5ae9: 0xf000000b, 0x5aea: 0xf000000b, 0x5aeb: 0xf000000b,
+ 0x5aec: 0xf000000b, 0x5aed: 0xf000000b, 0x5aee: 0xf000000b, 0x5aef: 0xf000000b,
+ 0x5af0: 0xf000000b, 0x5af1: 0xf000000b, 0x5af2: 0xf000000b, 0x5af3: 0xf000000b,
+ 0x5af4: 0xf000000b, 0x5af5: 0xf0000005, 0x5af6: 0xf0000005, 0x5af7: 0xf0000005,
+ 0x5af8: 0xf0000005, 0x5af9: 0xf0000005, 0x5afa: 0xf0000005, 0x5afb: 0xf0000005,
+ 0x5afc: 0xf0000005, 0x5afd: 0xf0000005, 0x5afe: 0xf0000005, 0x5aff: 0xf0000005,
+ // Block 0x16c, offset 0x5b00
+ 0x5b00: 0xf0000005, 0x5b01: 0xf0000005, 0x5b02: 0xf0000005, 0x5b03: 0xf0000005,
+ 0x5b04: 0xf0000005, 0x5b05: 0xf0000005, 0x5b06: 0xf0000005, 0x5b07: 0xf0000005,
+ 0x5b08: 0xf0000005, 0x5b09: 0xf0000005, 0x5b0a: 0xf0000005, 0x5b0b: 0xf0000005,
+ 0x5b0c: 0xf0000005, 0x5b0d: 0xf0000005, 0x5b0e: 0xf0000005, 0x5b0f: 0xf0000005,
+ 0x5b10: 0xf0000005, 0x5b11: 0xf0000005, 0x5b12: 0xf0000005, 0x5b13: 0xf0000005,
+ 0x5b14: 0xf0000005, 0x5b15: 0xf0000005, 0x5b16: 0xf000000b, 0x5b17: 0xf000000b,
+ 0x5b18: 0xf000000b, 0x5b19: 0xf000000b, 0x5b1a: 0xf000000b, 0x5b1b: 0xf000000b,
+ 0x5b1c: 0xf000000b, 0x5b1d: 0xf000000b, 0x5b1e: 0xf000000b, 0x5b1f: 0xf000000b,
+ 0x5b20: 0xf000000b, 0x5b21: 0xf000000b, 0x5b22: 0xf000000b, 0x5b23: 0xf000000b,
+ 0x5b24: 0xf000000b, 0x5b25: 0xf000000b, 0x5b26: 0xf000000b, 0x5b27: 0xf000000b,
+ 0x5b28: 0xf000000b, 0x5b29: 0xf000000b, 0x5b2a: 0xf000000b, 0x5b2b: 0xf000000b,
+ 0x5b2c: 0xf000000b, 0x5b2d: 0xf000000b, 0x5b2e: 0xf000000b, 0x5b2f: 0xf0000005,
+ 0x5b30: 0xf0000005, 0x5b31: 0xf0000005, 0x5b32: 0xf0000005, 0x5b33: 0xf0000005,
+ 0x5b34: 0xf0000005, 0x5b35: 0xf0000005, 0x5b36: 0xf0000005, 0x5b37: 0xf0000005,
+ 0x5b38: 0xf0000005, 0x5b39: 0xf0000005, 0x5b3a: 0xf0000005, 0x5b3b: 0xf0000005,
+ 0x5b3c: 0xf0000005, 0x5b3d: 0xf0000005, 0x5b3e: 0xf0000005, 0x5b3f: 0xf0000005,
+ // Block 0x16d, offset 0x5b40
+ 0x5b40: 0xf0000005, 0x5b41: 0xf0000005, 0x5b42: 0xf0000005, 0x5b43: 0xf0000005,
+ 0x5b44: 0xf0000005, 0x5b45: 0xf0000005, 0x5b46: 0xf0000005, 0x5b47: 0xf0000005,
+ 0x5b48: 0xf0000005, 0x5b49: 0xf0000005, 0x5b4a: 0xf0000005, 0x5b4b: 0xf0000005,
+ 0x5b4c: 0xf0000005, 0x5b4d: 0xf0000005, 0x5b4e: 0xf0000005, 0x5b4f: 0xf0000005,
+ 0x5b50: 0xf000000b, 0x5b51: 0xf000000b, 0x5b52: 0xf000000b, 0x5b53: 0xf000000b,
+ 0x5b54: 0xf000000b, 0x5b55: 0xf000000b, 0x5b56: 0xf000000b, 0x5b57: 0xf000000b,
+ 0x5b58: 0xf000000b, 0x5b59: 0xf000000b, 0x5b5a: 0xf000000b, 0x5b5b: 0xf000000b,
+ 0x5b5c: 0xf000000b, 0x5b5d: 0xf000000b, 0x5b5e: 0xf000000b, 0x5b5f: 0xf000000b,
+ 0x5b60: 0xf000000b, 0x5b61: 0xf000000b, 0x5b62: 0xf000000b, 0x5b63: 0xf000000b,
+ 0x5b64: 0xf000000b, 0x5b65: 0xf000000b, 0x5b66: 0xf000000b, 0x5b67: 0xf000000b,
+ 0x5b68: 0xf000000b, 0x5b69: 0xf0000005, 0x5b6a: 0xf0000005, 0x5b6b: 0xf0000005,
+ 0x5b6c: 0xf0000005, 0x5b6d: 0xf0000005, 0x5b6e: 0xf0000005, 0x5b6f: 0xf0000005,
+ 0x5b70: 0xf0000005, 0x5b71: 0xf0000005, 0x5b72: 0xf0000005, 0x5b73: 0xf0000005,
+ 0x5b74: 0xf0000005, 0x5b75: 0xf0000005, 0x5b76: 0xf0000005, 0x5b77: 0xf0000005,
+ 0x5b78: 0xf0000005, 0x5b79: 0xf0000005, 0x5b7a: 0xf0000005, 0x5b7b: 0xf0000005,
+ 0x5b7c: 0xf0000005, 0x5b7d: 0xf0000005, 0x5b7e: 0xf0000005, 0x5b7f: 0xf0000005,
+ // Block 0x16e, offset 0x5b80
+ 0x5b80: 0xf0000005, 0x5b81: 0xf0000005, 0x5b82: 0xf0000005, 0x5b83: 0xf0000005,
+ 0x5b84: 0xf0000005, 0x5b85: 0xf0000005, 0x5b86: 0xf0000005, 0x5b87: 0xf0000005,
+ 0x5b88: 0xf0000005, 0x5b89: 0xf0000005, 0x5b8a: 0xf000000b, 0x5b8b: 0xf0000005,
+ 0x5b8e: 0xf0000005, 0x5b8f: 0xf0000005,
+ 0x5b90: 0xf0000005, 0x5b91: 0xf0000005, 0x5b92: 0xf0000005, 0x5b93: 0xf0000005,
+ 0x5b94: 0xf0000005, 0x5b95: 0xf0000005, 0x5b96: 0xf0000005, 0x5b97: 0xf0000005,
+ 0x5b98: 0xf0000005, 0x5b99: 0xf0000005, 0x5b9a: 0xf0000005, 0x5b9b: 0xf0000005,
+ 0x5b9c: 0xf0000005, 0x5b9d: 0xf0000005, 0x5b9e: 0xf0000005, 0x5b9f: 0xf0000005,
+ 0x5ba0: 0xf0000005, 0x5ba1: 0xf0000005, 0x5ba2: 0xf0000005, 0x5ba3: 0xf0000005,
+ 0x5ba4: 0xf0000005, 0x5ba5: 0xf0000005, 0x5ba6: 0xf0000005, 0x5ba7: 0xf0000005,
+ 0x5ba8: 0xf0000005, 0x5ba9: 0xf0000005, 0x5baa: 0xf0000005, 0x5bab: 0xf0000005,
+ 0x5bac: 0xf0000005, 0x5bad: 0xf0000005, 0x5bae: 0xf0000005, 0x5baf: 0xf0000005,
+ 0x5bb0: 0xf0000005, 0x5bb1: 0xf0000005, 0x5bb2: 0xf0000005, 0x5bb3: 0xf0000005,
+ 0x5bb4: 0xf0000005, 0x5bb5: 0xf0000005, 0x5bb6: 0xf0000005, 0x5bb7: 0xf0000005,
+ 0x5bb8: 0xf0000005, 0x5bb9: 0xf0000005, 0x5bba: 0xf0000005, 0x5bbb: 0xf0000005,
+ 0x5bbc: 0xf0000005, 0x5bbd: 0xf0000005, 0x5bbe: 0xf0000005, 0x5bbf: 0xf0000005,
+ // Block 0x16f, offset 0x5bc0
+ 0x5bc0: 0x400f8120, 0x5bc1: 0x400f8220, 0x5bc2: 0x400f8320, 0x5bc3: 0x400f8420,
+ 0x5bc4: 0x400f8520, 0x5bc5: 0x400f8620, 0x5bc6: 0x400f8720, 0x5bc7: 0x400f8820,
+ 0x5bc8: 0x400f8920, 0x5bc9: 0x400f8a20, 0x5bca: 0x400f8b20, 0x5bcb: 0x400f8c20,
+ 0x5bcc: 0x400f8d20, 0x5bcd: 0x400f8e20, 0x5bce: 0x400f8f20, 0x5bcf: 0x400f9020,
+ 0x5bd0: 0x400f9120, 0x5bd1: 0x400f9220, 0x5bd2: 0x400f9320, 0x5bd3: 0x400f9420,
+ 0x5bd4: 0x400f9520, 0x5bd5: 0x400f9620, 0x5bd6: 0x400f9720, 0x5bd7: 0x400f9820,
+ 0x5bd8: 0x400f9920, 0x5bd9: 0x400f9a20, 0x5bda: 0x400f9b20, 0x5bdb: 0x400f9c20,
+ 0x5bdc: 0x400f9d20, 0x5bdd: 0x400f9e20, 0x5bde: 0x400f9f20, 0x5bdf: 0x400fa020,
+ 0x5be0: 0x400fa120, 0x5be1: 0x400fa220, 0x5be2: 0x400fa320, 0x5be3: 0x400fa420,
+ 0x5be4: 0x400fa520, 0x5be5: 0x400fa620, 0x5be6: 0x400fa720, 0x5be7: 0x400fa820,
+ 0x5be8: 0x400fa920, 0x5be9: 0x400faa20, 0x5bea: 0x400fab20, 0x5beb: 0x400fac20,
+ 0x5bf0: 0x400fad20, 0x5bf1: 0x400fae20, 0x5bf2: 0x400faf20, 0x5bf3: 0x400fb020,
+ 0x5bf4: 0x400fb120, 0x5bf5: 0x400fb220, 0x5bf6: 0x400fb320, 0x5bf7: 0x400fb420,
+ 0x5bf8: 0x400fb520, 0x5bf9: 0x400fb620, 0x5bfa: 0x400fb720, 0x5bfb: 0x400fb820,
+ 0x5bfc: 0x400fb920, 0x5bfd: 0x400fba20, 0x5bfe: 0x400fbb20, 0x5bff: 0x400fbc20,
+ // Block 0x170, offset 0x5c00
+ 0x5c00: 0x400fbd20, 0x5c01: 0x400fbe20, 0x5c02: 0x400fbf20, 0x5c03: 0x400fc020,
+ 0x5c04: 0x400fc120, 0x5c05: 0x400fc220, 0x5c06: 0x400fc320, 0x5c07: 0x400fc420,
+ 0x5c08: 0x400fc520, 0x5c09: 0x400fc620, 0x5c0a: 0x400fc720, 0x5c0b: 0x400fc820,
+ 0x5c0c: 0x400fc920, 0x5c0d: 0x400fca20, 0x5c0e: 0x400fcb20, 0x5c0f: 0x400fcc20,
+ 0x5c10: 0x400fcd20, 0x5c11: 0x400fce20, 0x5c12: 0x400fcf20, 0x5c13: 0x400fd020,
+ 0x5c14: 0x400fd120, 0x5c15: 0x400fd220, 0x5c16: 0x400fd320, 0x5c17: 0x400fd420,
+ 0x5c18: 0x400fd520, 0x5c19: 0x400fd620, 0x5c1a: 0x400fd720, 0x5c1b: 0x400fd820,
+ 0x5c1c: 0x400fd920, 0x5c1d: 0x400fda20, 0x5c1e: 0x400fdb20, 0x5c1f: 0x400fdc20,
+ 0x5c20: 0x400fdd20, 0x5c21: 0x400fde20, 0x5c22: 0x400fdf20, 0x5c23: 0x400fe020,
+ 0x5c24: 0x400fe120, 0x5c25: 0x400fe220, 0x5c26: 0x400fe320, 0x5c27: 0x400fe420,
+ 0x5c28: 0x400fe520, 0x5c29: 0x400fe620, 0x5c2a: 0x400fe720, 0x5c2b: 0x400fe820,
+ 0x5c2c: 0x400fe920, 0x5c2d: 0x400fea20, 0x5c2e: 0x400feb20, 0x5c2f: 0x400fec20,
+ 0x5c30: 0x400fed20, 0x5c31: 0x400fee20, 0x5c32: 0x400fef20, 0x5c33: 0x400ff020,
+ 0x5c34: 0x400ff120, 0x5c35: 0x400ff220, 0x5c36: 0x400ff320, 0x5c37: 0x400ff420,
+ 0x5c38: 0x400ff520, 0x5c39: 0x400ff620, 0x5c3a: 0x400ff720, 0x5c3b: 0x400ff820,
+ 0x5c3c: 0x400ff920, 0x5c3d: 0x400ffa20, 0x5c3e: 0x400ffb20, 0x5c3f: 0x400ffc20,
+ // Block 0x171, offset 0x5c40
+ 0x5c40: 0x400ffd20, 0x5c41: 0x400ffe20, 0x5c42: 0x400fff20, 0x5c43: 0x40100020,
+ 0x5c44: 0x40100120, 0x5c45: 0x40100220, 0x5c46: 0x40100320, 0x5c47: 0x40100420,
+ 0x5c48: 0x40100520, 0x5c49: 0x40100620, 0x5c4a: 0x40100720, 0x5c4b: 0x40100820,
+ 0x5c4c: 0x40100920, 0x5c4d: 0x40100a20, 0x5c4e: 0x40100b20, 0x5c4f: 0x40100c20,
+ 0x5c50: 0x40100d20, 0x5c51: 0x40100e20, 0x5c52: 0x40100f20, 0x5c53: 0x40101020,
+ 0x5c60: 0x40101120, 0x5c61: 0x40101220, 0x5c62: 0x40101320, 0x5c63: 0x40101420,
+ 0x5c64: 0x40101520, 0x5c65: 0x40101620, 0x5c66: 0x40101720, 0x5c67: 0x40101820,
+ 0x5c68: 0x40101920, 0x5c69: 0x40101a20, 0x5c6a: 0x40101b20, 0x5c6b: 0x40101c20,
+ 0x5c6c: 0x40101d20, 0x5c6d: 0x40101e20, 0x5c6e: 0x40101f20,
+ 0x5c71: 0x40102020, 0x5c72: 0x40102120, 0x5c73: 0x40102220,
+ 0x5c74: 0x40102320, 0x5c75: 0x40102420, 0x5c76: 0x40102520, 0x5c77: 0x40102620,
+ 0x5c78: 0x40102720, 0x5c79: 0x40102820, 0x5c7a: 0x40102920, 0x5c7b: 0x40102a20,
+ 0x5c7c: 0x40102b20, 0x5c7d: 0x40102c20, 0x5c7e: 0x40102d20,
+ // Block 0x172, offset 0x5c80
+ 0x5c81: 0x40102e20, 0x5c82: 0x40102f20, 0x5c83: 0x40103020,
+ 0x5c84: 0x40103120, 0x5c85: 0x40103220, 0x5c86: 0x40103320, 0x5c87: 0x40103420,
+ 0x5c88: 0x40103520, 0x5c89: 0x40103620, 0x5c8a: 0x40103720, 0x5c8b: 0x40103820,
+ 0x5c8c: 0x40103920, 0x5c8d: 0x40103a20, 0x5c8e: 0x40103b20, 0x5c8f: 0x40103c20,
+ 0x5c91: 0x40103d20, 0x5c92: 0x40103e20, 0x5c93: 0x40103f20,
+ 0x5c94: 0x40104020, 0x5c95: 0x40104120, 0x5c96: 0x40104220, 0x5c97: 0x40104320,
+ 0x5c98: 0x40104420, 0x5c99: 0x40104520, 0x5c9a: 0x40104620, 0x5c9b: 0x40104720,
+ 0x5c9c: 0x40104820, 0x5c9d: 0x40104920, 0x5c9e: 0x40104a20, 0x5c9f: 0x40104b20,
+ // Block 0x173, offset 0x5cc0
+ 0x5cc0: 0xf0000404, 0x5cc1: 0xf0000404, 0x5cc2: 0xf0000404, 0x5cc3: 0xf0000404,
+ 0x5cc4: 0xf0000404, 0x5cc5: 0xf0000404, 0x5cc6: 0xf0000404, 0x5cc7: 0xf0000404,
+ 0x5cc8: 0xf0000404, 0x5cc9: 0xf0000404, 0x5cca: 0xf0000404,
+ 0x5cd0: 0xf0000a04, 0x5cd1: 0xf0000a04, 0x5cd2: 0xf0000a04, 0x5cd3: 0xf0000a04,
+ 0x5cd4: 0xf0000a04, 0x5cd5: 0xf0000a04, 0x5cd6: 0xf0000a04, 0x5cd7: 0xf0000a04,
+ 0x5cd8: 0xf0000a04, 0x5cd9: 0xf0000a04, 0x5cda: 0xf0000a04, 0x5cdb: 0xf0000a04,
+ 0x5cdc: 0xf0000a04, 0x5cdd: 0xf0000a04, 0x5cde: 0xf0000a04, 0x5cdf: 0xf0000a04,
+ 0x5ce0: 0xf0000a04, 0x5ce1: 0xf0000a04, 0x5ce2: 0xf0000a04, 0x5ce3: 0xf0000a04,
+ 0x5ce4: 0xf0000a04, 0x5ce5: 0xf0000a04, 0x5ce6: 0xf0000a04, 0x5ce7: 0xf0000a04,
+ 0x5ce8: 0xf0000a04, 0x5ce9: 0xf0000a04, 0x5cea: 0xf0000a04, 0x5ceb: 0xf000000c,
+ 0x5cec: 0xf000000c, 0x5ced: 0xf0000c0c, 0x5cee: 0xf0000c0c,
+ 0x5cf0: 0xf000001d, 0x5cf1: 0xf000001d, 0x5cf2: 0xf000001d, 0x5cf3: 0xf000001d,
+ 0x5cf4: 0xf000001d, 0x5cf5: 0xf000001d, 0x5cf6: 0xf000001d, 0x5cf7: 0xf000001d,
+ 0x5cf8: 0xf000001d, 0x5cf9: 0xf000001d, 0x5cfa: 0xf000001d, 0x5cfb: 0xf000001d,
+ 0x5cfc: 0xf000001d, 0x5cfd: 0xf000001d, 0x5cfe: 0xf000001d, 0x5cff: 0xf000001d,
+ // Block 0x174, offset 0x5d00
+ 0x5d00: 0xf000001d, 0x5d01: 0xf000001d, 0x5d02: 0xf000001d, 0x5d03: 0xf000001d,
+ 0x5d04: 0xf000001d, 0x5d05: 0xf000001d, 0x5d06: 0xf000001d, 0x5d07: 0xf000001d,
+ 0x5d08: 0xf000001d, 0x5d09: 0xf000001d, 0x5d0a: 0xf0001d1d, 0x5d0b: 0xf0001d1d,
+ 0x5d0c: 0xf0001d1d, 0x5d0d: 0xf0001d1d, 0x5d0e: 0xf0001d1d, 0x5d0f: 0xf0001d1d,
+ 0x5d10: 0x002b460c, 0x5d11: 0x002b720c, 0x5d12: 0x002ba20c, 0x5d13: 0x002bc80c,
+ 0x5d14: 0x002bfe0c, 0x5d15: 0x002c6e0c, 0x5d16: 0x002c880c, 0x5d17: 0x002cce0c,
+ 0x5d18: 0x002d000c, 0x5d19: 0x002d320c, 0x5d1a: 0x002d640c, 0x5d1b: 0x002d880c,
+ 0x5d1c: 0x002de80c, 0x5d1d: 0x002e040c, 0x5d1e: 0x002e480c, 0x5d1f: 0x002e920c,
+ 0x5d20: 0x002ebc0c, 0x5d21: 0x002ee00c, 0x5d22: 0x002f4c0c, 0x5d23: 0x002f920c,
+ 0x5d24: 0x002fd20c, 0x5d25: 0x0030240c, 0x5d26: 0x0030480c, 0x5d27: 0x00305c0c,
+ 0x5d28: 0x0030660c, 0x5d29: 0x0030880c,
+ 0x5d30: 0x002b461d, 0x5d31: 0x002b721d, 0x5d32: 0x002ba21d, 0x5d33: 0x002bc81d,
+ 0x5d34: 0x002bfe1d, 0x5d35: 0x002c6e1d, 0x5d36: 0x002c881d, 0x5d37: 0x002cce1d,
+ 0x5d38: 0x002d001d, 0x5d39: 0x002d321d, 0x5d3a: 0x002d641d, 0x5d3b: 0x002d881d,
+ 0x5d3c: 0x002de81d, 0x5d3d: 0x002e041d, 0x5d3e: 0x002e481d, 0x5d3f: 0x002e921d,
+ // Block 0x175, offset 0x5d40
+ 0x5d40: 0x002ebc1d, 0x5d41: 0x002ee01d, 0x5d42: 0x002f4c1d, 0x5d43: 0x002f921d,
+ 0x5d44: 0x002fd21d, 0x5d45: 0x0030241d, 0x5d46: 0x0030481d, 0x5d47: 0x00305c1d,
+ 0x5d48: 0x0030661d, 0x5d49: 0x0030881d, 0x5d4a: 0x002e921d, 0x5d4b: 0xe0000777,
+ 0x5d4c: 0xe00007c5, 0x5d4d: 0xe00007e9, 0x5d4e: 0xe00006f3, 0x5d4f: 0xe0000825,
+ 0x5d50: 0xf0001d1d, 0x5d51: 0xe000072b, 0x5d52: 0xe000072e, 0x5d53: 0xe0000760,
+ 0x5d54: 0xe000077a, 0x5d55: 0xe00007a7, 0x5d56: 0xe00007ab, 0x5d57: 0xe00007bc,
+ 0x5d58: 0xe00007ec, 0x5d59: 0xe0000818, 0x5d5a: 0xe000081c,
+ // Block 0x176, offset 0x5d80
+ 0x5da6: 0x002b460a, 0x5da7: 0x002b720a,
+ 0x5da8: 0x002ba20a, 0x5da9: 0x002bc80a, 0x5daa: 0x002bfe0a, 0x5dab: 0x002c6e0a,
+ 0x5dac: 0x002c880a, 0x5dad: 0x002cce0a, 0x5dae: 0x002d000a, 0x5daf: 0x002d320a,
+ 0x5db0: 0x002d640a, 0x5db1: 0x002d880a, 0x5db2: 0x002de80a, 0x5db3: 0x002e040a,
+ 0x5db4: 0x002e480a, 0x5db5: 0x002e920a, 0x5db6: 0x002ebc0a, 0x5db7: 0x002ee00a,
+ 0x5db8: 0x002f4c0a, 0x5db9: 0x002f920a, 0x5dba: 0x002fd20a, 0x5dbb: 0x0030240a,
+ 0x5dbc: 0x0030480a, 0x5dbd: 0x00305c0a, 0x5dbe: 0x0030660a, 0x5dbf: 0x0030880a,
+ // Block 0x177, offset 0x5dc0
+ 0x5dc0: 0xf0001c1c, 0x5dc1: 0xf0001c1c, 0x5dc2: 0xf000001c,
+ 0x5dd0: 0xf000001c, 0x5dd1: 0xf000001c, 0x5dd2: 0xf000001c, 0x5dd3: 0xf0001c1c,
+ 0x5dd4: 0xf000001c, 0x5dd5: 0xf000001c, 0x5dd6: 0xf000001c, 0x5dd7: 0xf000001c,
+ 0x5dd8: 0xf000001c, 0x5dd9: 0xf000001c, 0x5dda: 0xf000001c, 0x5ddb: 0xf000001c,
+ 0x5ddc: 0xf000001c, 0x5ddd: 0xf000001c, 0x5dde: 0xf000001c, 0x5ddf: 0xf000001c,
+ 0x5de0: 0xf000001c, 0x5de1: 0xf000001c, 0x5de2: 0xf000001c, 0x5de3: 0xf000001c,
+ 0x5de4: 0xf000001c, 0x5de5: 0xf000001c, 0x5de6: 0xf000001c, 0x5de7: 0xf000001c,
+ 0x5de8: 0xf000001c, 0x5de9: 0xf000001c, 0x5dea: 0xf000001c, 0x5deb: 0xf000001c,
+ 0x5dec: 0xf000001c, 0x5ded: 0xf000001c, 0x5dee: 0xf000001c, 0x5def: 0xf000001c,
+ 0x5df0: 0xf000001c, 0x5df1: 0xf000001c, 0x5df2: 0xf000001c, 0x5df3: 0xf000001c,
+ 0x5df4: 0xf000001c, 0x5df5: 0xf000001c, 0x5df6: 0xf000001c, 0x5df7: 0xf000001c,
+ 0x5df8: 0xf000001c, 0x5df9: 0xf000001c, 0x5dfa: 0xf000001c,
+ // Block 0x178, offset 0x5e00
+ 0x5e00: 0xf0000404, 0x5e01: 0xf0000404, 0x5e02: 0xf0000404, 0x5e03: 0xf0000404,
+ 0x5e04: 0xf0000404, 0x5e05: 0xf0000404, 0x5e06: 0xf0000404, 0x5e07: 0xf0000404,
+ 0x5e08: 0xf0000404,
+ 0x5e10: 0xf0000006, 0x5e11: 0xf0000006,
+ // Block 0x179, offset 0x5e40
+ 0x5e40: 0x40104c20, 0x5e41: 0x40104d20, 0x5e42: 0x40104e20, 0x5e43: 0x40104f20,
+ 0x5e44: 0x40105020, 0x5e45: 0x40105120, 0x5e46: 0x40105220, 0x5e47: 0x40105320,
+ 0x5e48: 0x40105420, 0x5e49: 0x40105520, 0x5e4a: 0x40105620, 0x5e4b: 0x40105720,
+ 0x5e4c: 0x40105820, 0x5e4d: 0x40105920, 0x5e4e: 0x40105a20, 0x5e4f: 0x40105b20,
+ 0x5e50: 0x40105c20, 0x5e51: 0x40105d20, 0x5e52: 0x40105e20, 0x5e53: 0x40105f20,
+ 0x5e54: 0x40106020, 0x5e55: 0x40106120, 0x5e56: 0x40106220, 0x5e57: 0x40106320,
+ 0x5e58: 0x40106420, 0x5e59: 0x40106520, 0x5e5a: 0x40106620, 0x5e5b: 0x40106720,
+ 0x5e5c: 0x40106820, 0x5e5d: 0x40106920, 0x5e5e: 0x40106a20, 0x5e5f: 0x40106b20,
+ 0x5e60: 0x40106c20,
+ 0x5e70: 0x40106d20, 0x5e71: 0x40106e20, 0x5e72: 0x40106f20, 0x5e73: 0x40107020,
+ 0x5e74: 0x40107120, 0x5e75: 0x40107220, 0x5e77: 0x40107320,
+ 0x5e78: 0x40107420, 0x5e79: 0x40107520, 0x5e7a: 0x40107620, 0x5e7b: 0x40107720,
+ 0x5e7c: 0x40107820, 0x5e7d: 0x40107920, 0x5e7e: 0x40107a20, 0x5e7f: 0x40107b20,
+ // Block 0x17a, offset 0x5e80
+ 0x5e80: 0x40107c20, 0x5e81: 0x40107d20, 0x5e82: 0x40107e20, 0x5e83: 0x40107f20,
+ 0x5e84: 0x40108020, 0x5e85: 0x40108120, 0x5e86: 0x40108220, 0x5e87: 0x40108320,
+ 0x5e88: 0x40108420, 0x5e89: 0x40108520, 0x5e8a: 0x40108620, 0x5e8b: 0x40108720,
+ 0x5e8c: 0x40108820, 0x5e8d: 0x40108920, 0x5e8e: 0x40108a20, 0x5e8f: 0x40108b20,
+ 0x5e90: 0x40108c20, 0x5e91: 0x40108d20, 0x5e92: 0x40108e20, 0x5e93: 0x40108f20,
+ 0x5e94: 0x40109020, 0x5e95: 0x40109120, 0x5e96: 0x40109220, 0x5e97: 0x40109320,
+ 0x5e98: 0x40109420, 0x5e99: 0x40109520, 0x5e9a: 0x40109620, 0x5e9b: 0x40109720,
+ 0x5e9c: 0x40109820, 0x5e9d: 0x40109920, 0x5e9e: 0x40109a20, 0x5e9f: 0x40109b20,
+ 0x5ea0: 0x40109c20, 0x5ea1: 0x40109d20, 0x5ea2: 0x40109e20, 0x5ea3: 0x40109f20,
+ 0x5ea4: 0x4010a020, 0x5ea5: 0x4010a120, 0x5ea6: 0x4010a220, 0x5ea7: 0x4010a320,
+ 0x5ea8: 0x4010a420, 0x5ea9: 0x4010a520, 0x5eaa: 0x4010a620, 0x5eab: 0x4010a720,
+ 0x5eac: 0x4010a820, 0x5ead: 0x4010a920, 0x5eae: 0x4010aa20, 0x5eaf: 0x4010ab20,
+ 0x5eb0: 0x4010ac20, 0x5eb1: 0x4010ad20, 0x5eb2: 0x4010ae20, 0x5eb3: 0x4010af20,
+ 0x5eb4: 0x4010b020, 0x5eb5: 0x4010b120, 0x5eb6: 0x4010b220, 0x5eb7: 0x4010b320,
+ 0x5eb8: 0x4010b420, 0x5eb9: 0x4010b520, 0x5eba: 0x4010b620, 0x5ebb: 0x4010b720,
+ 0x5ebc: 0x4010b820,
+ // Block 0x17b, offset 0x5ec0
+ 0x5ec0: 0x4010b920, 0x5ec1: 0x4010ba20, 0x5ec2: 0x4010bb20, 0x5ec3: 0x4010bc20,
+ 0x5ec4: 0x4010bd20, 0x5ec5: 0x4010be20, 0x5ec6: 0x4010bf20, 0x5ec7: 0x4010c020,
+ 0x5ec8: 0x4010c120, 0x5ec9: 0x4010c220, 0x5eca: 0x4010c320, 0x5ecb: 0x4010c420,
+ 0x5ecc: 0x4010c520, 0x5ecd: 0x4010c620, 0x5ece: 0x4010c720, 0x5ecf: 0x4010c820,
+ 0x5ed0: 0x4010c920, 0x5ed1: 0x4010ca20, 0x5ed2: 0x4010cb20, 0x5ed3: 0x4010cc20,
+ 0x5ee0: 0x4010cd20, 0x5ee1: 0x4010ce20, 0x5ee2: 0x4010cf20, 0x5ee3: 0x4010d020,
+ 0x5ee4: 0x4010d120, 0x5ee5: 0x4010d220, 0x5ee6: 0x4010d320, 0x5ee7: 0x4010d420,
+ 0x5ee8: 0x4010d520, 0x5ee9: 0x4010d620, 0x5eea: 0x4010d720, 0x5eeb: 0x4010d820,
+ 0x5eec: 0x4010d920, 0x5eed: 0x4010da20, 0x5eee: 0x4010db20, 0x5eef: 0x4010dc20,
+ 0x5ef0: 0x4010dd20, 0x5ef1: 0x4010de20, 0x5ef2: 0x4010df20, 0x5ef3: 0x4010e020,
+ 0x5ef4: 0x4010e120, 0x5ef5: 0x4010e220, 0x5ef6: 0x4010e320, 0x5ef7: 0x4010e420,
+ 0x5ef8: 0x4010e520, 0x5ef9: 0x4010e620, 0x5efa: 0x4010e720, 0x5efb: 0x4010e820,
+ 0x5efc: 0x4010e920, 0x5efd: 0x4010ea20, 0x5efe: 0x4010eb20, 0x5eff: 0x4010ec20,
+ // Block 0x17c, offset 0x5f00
+ 0x5f00: 0x4010ed20, 0x5f01: 0x4010ee20, 0x5f02: 0x4010ef20, 0x5f03: 0x4010f020,
+ 0x5f04: 0x4010f120, 0x5f06: 0x4010f220, 0x5f07: 0x4010f320,
+ 0x5f08: 0x4010f420, 0x5f09: 0x4010f520, 0x5f0a: 0x4010f620,
+ 0x5f20: 0x4010f720, 0x5f21: 0x4010f820, 0x5f22: 0x4010f920, 0x5f23: 0x4010fa20,
+ 0x5f24: 0x4010fb20, 0x5f25: 0x4010fc20, 0x5f26: 0x4010fd20, 0x5f27: 0x4010fe20,
+ 0x5f28: 0x4010ff20, 0x5f29: 0x40110020, 0x5f2a: 0x40110120, 0x5f2b: 0x40110220,
+ 0x5f2c: 0x40110320, 0x5f2d: 0x40110420, 0x5f2e: 0x40110520, 0x5f2f: 0x40110620,
+ 0x5f30: 0x40110720,
+ // Block 0x17d, offset 0x5f40
+ 0x5f40: 0x40110820, 0x5f41: 0x40110920, 0x5f42: 0x40110a20, 0x5f43: 0x40110b20,
+ 0x5f44: 0x40110c20, 0x5f45: 0x40110d20, 0x5f46: 0x40110e20, 0x5f47: 0x40110f20,
+ 0x5f48: 0x40111020, 0x5f49: 0x40111120, 0x5f4a: 0x40111220, 0x5f4b: 0x40111320,
+ 0x5f4c: 0x40111420, 0x5f4d: 0x40111520, 0x5f4e: 0x40111620, 0x5f4f: 0x40111720,
+ 0x5f50: 0x40111820, 0x5f51: 0x40111920, 0x5f52: 0x40111a20, 0x5f53: 0x40111b20,
+ 0x5f54: 0x40111c20, 0x5f55: 0x40111d20, 0x5f56: 0x40111e20, 0x5f57: 0x40111f20,
+ 0x5f58: 0x40112020, 0x5f59: 0x40112120, 0x5f5a: 0x40112220, 0x5f5b: 0x40112320,
+ 0x5f5c: 0x40112420, 0x5f5d: 0x40112520, 0x5f5e: 0x40112620, 0x5f5f: 0x40112720,
+ 0x5f60: 0x40112820, 0x5f61: 0x40112920, 0x5f62: 0x40112a20, 0x5f63: 0x40112b20,
+ 0x5f64: 0x40112c20, 0x5f65: 0x40112d20, 0x5f66: 0x40112e20, 0x5f67: 0x40112f20,
+ 0x5f68: 0x40113020, 0x5f69: 0x40113120, 0x5f6a: 0x40113220, 0x5f6b: 0x40113320,
+ 0x5f6c: 0x40113420, 0x5f6d: 0x40113520, 0x5f6e: 0x40113620, 0x5f6f: 0x40113720,
+ 0x5f70: 0x40113820, 0x5f71: 0x40113920, 0x5f72: 0x40113a20, 0x5f73: 0x40113b20,
+ 0x5f74: 0x40113c20, 0x5f75: 0x40113d20, 0x5f76: 0x40113e20, 0x5f77: 0x40113f20,
+ 0x5f78: 0x40114020, 0x5f79: 0x40114120, 0x5f7a: 0x40114220, 0x5f7b: 0x40114320,
+ 0x5f7c: 0x40114420, 0x5f7d: 0x40114520, 0x5f7e: 0x40114620,
+ // Block 0x17e, offset 0x5f80
+ 0x5f80: 0x40114720, 0x5f82: 0x40114820, 0x5f83: 0x40114920,
+ 0x5f84: 0x40114a20, 0x5f85: 0x40114b20, 0x5f86: 0x40114c20, 0x5f87: 0x40114d20,
+ 0x5f88: 0x40114e20, 0x5f89: 0x40114f20, 0x5f8a: 0x40115020, 0x5f8b: 0x40115120,
+ 0x5f8c: 0x40115220, 0x5f8d: 0x40115320, 0x5f8e: 0x40115420, 0x5f8f: 0x40115520,
+ 0x5f90: 0x40115620, 0x5f91: 0x40115720, 0x5f92: 0x40115820, 0x5f93: 0x40115920,
+ 0x5f94: 0x40115a20, 0x5f95: 0x40115b20, 0x5f96: 0x40115c20, 0x5f97: 0x40115d20,
+ 0x5f98: 0x40115e20, 0x5f99: 0x40115f20, 0x5f9a: 0x40116020, 0x5f9b: 0x40116120,
+ 0x5f9c: 0x40116220, 0x5f9d: 0x40116320, 0x5f9e: 0x40116420, 0x5f9f: 0x40116520,
+ 0x5fa0: 0x40116620, 0x5fa1: 0x40116720, 0x5fa2: 0x40116820, 0x5fa3: 0x40116920,
+ 0x5fa4: 0x40116a20, 0x5fa5: 0x40116b20, 0x5fa6: 0x40116c20, 0x5fa7: 0x40116d20,
+ 0x5fa8: 0x40116e20, 0x5fa9: 0x40116f20, 0x5faa: 0x40117020, 0x5fab: 0x40117120,
+ 0x5fac: 0x40117220, 0x5fad: 0x40117320, 0x5fae: 0x40117420, 0x5faf: 0x40117520,
+ 0x5fb0: 0x40117620, 0x5fb1: 0x40117720, 0x5fb2: 0x40117820, 0x5fb3: 0x40117920,
+ 0x5fb4: 0x40117a20, 0x5fb5: 0x40117b20, 0x5fb6: 0x40117c20, 0x5fb7: 0x40117d20,
+ 0x5fb8: 0x40117e20, 0x5fb9: 0x40117f20, 0x5fba: 0x40118020, 0x5fbb: 0x40118120,
+ 0x5fbc: 0x40118220, 0x5fbd: 0x40118320, 0x5fbe: 0x40118420, 0x5fbf: 0x40118520,
+ // Block 0x17f, offset 0x5fc0
+ 0x5fc0: 0x40118620, 0x5fc1: 0x40118720, 0x5fc2: 0x40118820, 0x5fc3: 0x40118920,
+ 0x5fc4: 0x40118a20, 0x5fc5: 0x40118b20, 0x5fc6: 0x40118c20, 0x5fc7: 0x40118d20,
+ 0x5fc8: 0x40118e20, 0x5fc9: 0x40118f20, 0x5fca: 0x40119020, 0x5fcb: 0x40119120,
+ 0x5fcc: 0x40119220, 0x5fcd: 0x40119320, 0x5fce: 0x40119420, 0x5fcf: 0x40119520,
+ 0x5fd0: 0x40119620, 0x5fd1: 0x40119720, 0x5fd2: 0x40119820, 0x5fd3: 0x40119920,
+ 0x5fd4: 0x40119a20, 0x5fd5: 0x40119b20, 0x5fd6: 0x40119c20, 0x5fd7: 0x40119d20,
+ 0x5fd8: 0x40119e20, 0x5fd9: 0x40119f20, 0x5fda: 0x4011a020, 0x5fdb: 0x4011a120,
+ 0x5fdc: 0x4011a220, 0x5fdd: 0x4011a320, 0x5fde: 0x4011a420, 0x5fdf: 0x4011a520,
+ 0x5fe0: 0x4011a620, 0x5fe1: 0x4011a720, 0x5fe2: 0x4011a820, 0x5fe3: 0x4011a920,
+ 0x5fe4: 0x4011aa20, 0x5fe5: 0x4011ab20, 0x5fe6: 0x4011ac20, 0x5fe7: 0x4011ad20,
+ 0x5fe8: 0x4011ae20, 0x5fe9: 0x4011af20, 0x5fea: 0x4011b020, 0x5feb: 0x4011b120,
+ 0x5fec: 0x4011b220, 0x5fed: 0x4011b320, 0x5fee: 0x4011b420, 0x5fef: 0x4011b520,
+ 0x5ff0: 0x4011b620, 0x5ff1: 0x4011b720, 0x5ff2: 0x4011b820, 0x5ff3: 0x4011b920,
+ 0x5ff4: 0x4011ba20, 0x5ff5: 0x4011bb20, 0x5ff6: 0x4011bc20, 0x5ff7: 0x4011bd20,
+ 0x5ff8: 0x4011be20, 0x5ff9: 0x4011bf20, 0x5ffa: 0x4011c020, 0x5ffb: 0x4011c120,
+ 0x5ffc: 0x4011c220, 0x5ffd: 0x4011c320, 0x5ffe: 0x4011c420, 0x5fff: 0x4011c520,
+ // Block 0x180, offset 0x6000
+ 0x6000: 0x4011c620, 0x6001: 0x4011c720, 0x6002: 0x4011c820, 0x6003: 0x4011c920,
+ 0x6004: 0x4011ca20, 0x6005: 0x4011cb20, 0x6006: 0x4011cc20, 0x6007: 0x4011cd20,
+ 0x6008: 0x4011ce20, 0x6009: 0x4011cf20, 0x600a: 0x4011d020, 0x600b: 0x4011d120,
+ 0x600c: 0x4011d220, 0x600d: 0x4011d320, 0x600e: 0x4011d420, 0x600f: 0x4011d520,
+ 0x6010: 0x4011d620, 0x6011: 0x4011d720, 0x6012: 0x4011d820, 0x6013: 0x4011d920,
+ 0x6014: 0x4011da20, 0x6015: 0x4011db20, 0x6016: 0x4011dc20, 0x6017: 0x4011dd20,
+ 0x6018: 0x4011de20, 0x6019: 0x4011df20, 0x601a: 0x4011e020, 0x601b: 0x4011e120,
+ 0x601c: 0x4011e220, 0x601d: 0x4011e320, 0x601e: 0x4011e420, 0x601f: 0x4011e520,
+ 0x6020: 0x4011e620, 0x6021: 0x4011e720, 0x6022: 0x4011e820, 0x6023: 0x4011e920,
+ 0x6024: 0x4011ea20, 0x6025: 0x4011eb20, 0x6026: 0x4011ec20, 0x6027: 0x4011ed20,
+ 0x6028: 0x4011ee20, 0x6029: 0x4011ef20, 0x602a: 0x4011f020, 0x602b: 0x4011f120,
+ 0x602c: 0x4011f220, 0x602d: 0x4011f320, 0x602e: 0x4011f420, 0x602f: 0x4011f520,
+ 0x6030: 0x4011f620, 0x6031: 0x4011f720, 0x6032: 0x4011f820, 0x6033: 0x4011f920,
+ 0x6034: 0x4011fa20, 0x6035: 0x4011fb20, 0x6036: 0x4011fc20, 0x6037: 0x4011fd20,
+ 0x6039: 0x4011fe20, 0x603a: 0x4011ff20, 0x603b: 0x40120020,
+ 0x603c: 0x40120120,
+ // Block 0x181, offset 0x6040
+ 0x6040: 0x40120220, 0x6041: 0x40120320, 0x6042: 0x40120420, 0x6043: 0x40120520,
+ 0x6044: 0x40120620, 0x6045: 0x40120720, 0x6046: 0x40120820, 0x6047: 0x40120920,
+ 0x6048: 0x40120a20, 0x6049: 0x40120b20, 0x604a: 0x40120c20, 0x604b: 0x40120d20,
+ 0x604c: 0x40120e20, 0x604d: 0x40120f20, 0x604e: 0x40121020, 0x604f: 0x40121120,
+ 0x6050: 0x40121220, 0x6051: 0x40121320, 0x6052: 0x40121420, 0x6053: 0x40121520,
+ 0x6054: 0x40121620, 0x6055: 0x40121720, 0x6056: 0x40121820, 0x6057: 0x40121920,
+ 0x6058: 0x40121a20, 0x6059: 0x40121b20, 0x605a: 0x40121c20, 0x605b: 0x40121d20,
+ 0x605c: 0x40121e20, 0x605d: 0x40121f20, 0x605e: 0x40122020, 0x605f: 0x40122120,
+ 0x6060: 0x40122220, 0x6061: 0x40122320, 0x6062: 0x40122420, 0x6063: 0x40122520,
+ 0x6064: 0x40122620, 0x6065: 0x40122720, 0x6066: 0x40122820, 0x6067: 0x40122920,
+ 0x6068: 0x40122a20, 0x6069: 0x40122b20, 0x606a: 0x40122c20, 0x606b: 0x40122d20,
+ 0x606c: 0x40122e20, 0x606d: 0x40122f20, 0x606e: 0x40123020, 0x606f: 0x40123120,
+ 0x6070: 0x40123220, 0x6071: 0x40123320, 0x6072: 0x40123420, 0x6073: 0x40123520,
+ 0x6074: 0x40123620, 0x6075: 0x40123720, 0x6076: 0x40123820, 0x6077: 0x40123920,
+ 0x6078: 0x40123a20, 0x6079: 0x40123b20, 0x607a: 0x40123c20, 0x607b: 0x40123d20,
+ 0x607c: 0x40123e20, 0x607d: 0x40123f20,
+ // Block 0x182, offset 0x6080
+ 0x6090: 0x40124020, 0x6091: 0x40124120, 0x6092: 0x40124220, 0x6093: 0x40124320,
+ 0x6094: 0x40124420, 0x6095: 0x40124520, 0x6096: 0x40124620, 0x6097: 0x40124720,
+ 0x6098: 0x40124820, 0x6099: 0x40124920, 0x609a: 0x40124a20, 0x609b: 0x40124b20,
+ 0x609c: 0x40124c20, 0x609d: 0x40124d20, 0x609e: 0x40124e20, 0x609f: 0x40124f20,
+ 0x60a0: 0x40125020, 0x60a1: 0x40125120, 0x60a2: 0x40125220, 0x60a3: 0x40125320,
+ 0x60a4: 0x40125420, 0x60a5: 0x40125520, 0x60a6: 0x40125620, 0x60a7: 0x40125720,
+ // Block 0x183, offset 0x60c0
+ 0x60fb: 0x40125820,
+ 0x60fc: 0x40125920, 0x60fd: 0x40125a20, 0x60fe: 0x40125b20, 0x60ff: 0x40125c20,
+ // Block 0x184, offset 0x6100
+ 0x6101: 0x40125d20, 0x6102: 0x40125e20, 0x6103: 0x40125f20,
+ 0x6104: 0x40126020, 0x6105: 0x40126120, 0x6106: 0x40126220, 0x6107: 0x40126320,
+ 0x6108: 0x40126420, 0x6109: 0x40126520, 0x610a: 0x40126620, 0x610b: 0x40126720,
+ 0x610c: 0x40126820, 0x610d: 0x40126920, 0x610e: 0x40126a20, 0x610f: 0x40126b20,
+ 0x6110: 0x40126c20, 0x6112: 0x40126d20, 0x6113: 0x40126e20,
+ 0x6114: 0x40126f20, 0x6116: 0x40127020,
+ 0x6118: 0x40127120, 0x611a: 0x40127220,
+ 0x611c: 0x40127320, 0x611d: 0x40127420, 0x611e: 0x40127520,
+ 0x6120: 0x40127620, 0x6121: 0x40127720, 0x6122: 0x40127820, 0x6123: 0x40127920,
+ 0x6124: 0x40127a20, 0x6125: 0x40127b20,
+ 0x6128: 0x40127c20, 0x6129: 0x40127d20, 0x612a: 0x40127e20, 0x612b: 0x40127f20,
+ 0x612d: 0x40128020,
+ 0x6130: 0x40128120, 0x6131: 0x40128220, 0x6132: 0x40128320, 0x6133: 0x40128420,
+ 0x6135: 0x40128520, 0x6136: 0x40128620, 0x6137: 0x40128720,
+ 0x6138: 0x40128820, 0x6139: 0x40128920, 0x613a: 0x40128a20, 0x613b: 0x40128b20,
+ 0x613c: 0x40128c20, 0x613d: 0x40128d20, 0x613e: 0x40128e20, 0x613f: 0x40128f20,
+ // Block 0x185, offset 0x6140
+ 0x6140: 0x40129020,
+ 0x6145: 0x40129120, 0x6146: 0x40129220, 0x6147: 0x40129320,
+ 0x6148: 0x40129420, 0x6149: 0x40129520, 0x614a: 0x40129620, 0x614b: 0x40129720,
+ 0x614c: 0x40129820, 0x614d: 0x40129920, 0x614e: 0x40129a20, 0x614f: 0x40129b20,
+ // Block 0x186, offset 0x6180
+ 0x6180: 0x40129c20, 0x6181: 0x40129d20, 0x6182: 0x40129e20, 0x6183: 0x40129f20,
+ 0x6184: 0x4012a020, 0x6185: 0x4012a120, 0x6186: 0x4012a220, 0x6187: 0x4012a320,
+ 0x6188: 0x4012a420, 0x6189: 0x4012a520, 0x618a: 0x4012a620, 0x618b: 0x4012a720,
+ 0x618c: 0x4012a820, 0x618d: 0x4012a920, 0x618e: 0x4012aa20, 0x618f: 0x4012ab20,
+ 0x6190: 0x4012ac20, 0x6191: 0x4012ad20, 0x6192: 0x4012ae20, 0x6193: 0x4012af20,
+ 0x6194: 0x4012b020, 0x6195: 0x4012b120, 0x6196: 0x4012b220, 0x6197: 0x4012b320,
+ 0x6198: 0x4012b420, 0x6199: 0x4012b520, 0x619a: 0x4012b620, 0x619b: 0x4012b720,
+ 0x619c: 0x4012b820, 0x619d: 0x4012b920, 0x619e: 0x4012ba20, 0x619f: 0x4012bb20,
+ 0x61a0: 0x4012bc20, 0x61a1: 0x4012bd20, 0x61a2: 0x4012be20, 0x61a3: 0x4012bf20,
+ 0x61a4: 0x4012c020, 0x61a5: 0x4012c120, 0x61a6: 0x4012c220, 0x61a7: 0x4012c320,
+ 0x61a8: 0x4012c420, 0x61a9: 0x4012c520, 0x61aa: 0x4012c620, 0x61ab: 0x4012c720,
+ 0x61ac: 0x4012c820, 0x61ad: 0x4012c920, 0x61ae: 0x4012ca20, 0x61af: 0x4012cb20,
+ 0x61b0: 0x4012cc20, 0x61b1: 0x4012cd20, 0x61b2: 0x4012ce20, 0x61b3: 0x4012cf20,
+ 0x61b4: 0x4012d020, 0x61b5: 0x4012d120, 0x61b6: 0x4012d220, 0x61b7: 0x4012d320,
+ 0x61b8: 0x4012d420, 0x61b9: 0x4012d520, 0x61ba: 0x4012d620, 0x61bb: 0x4012d720,
+ 0x61bc: 0x4012d820, 0x61bd: 0x4012d920, 0x61be: 0x4012da20, 0x61bf: 0x4012db20,
+ // Block 0x187, offset 0x61c0
+ 0x61c0: 0x4012dc20, 0x61c1: 0x4012dd20, 0x61c2: 0x4012de20, 0x61c3: 0x4012df20,
+ 0x61c4: 0x4012e020, 0x61c5: 0x4012e120,
+ // Block 0x188, offset 0x6200
+ 0x6200: 0x4012e220, 0x6201: 0x4012e320, 0x6202: 0x4012e420, 0x6203: 0x4012e520,
+ 0x6204: 0x4012e620, 0x6205: 0x4012e720, 0x6206: 0x4012e820, 0x6207: 0x4012e920,
+ 0x6208: 0x4012ea20, 0x6209: 0x4012eb20, 0x620a: 0x4012ec20, 0x620b: 0x4012ed20,
+ 0x620c: 0x4012ee20, 0x620d: 0x4012ef20, 0x620e: 0x4012f020, 0x620f: 0x4012f120,
+ 0x6210: 0x4012f220, 0x6211: 0x4012f320, 0x6212: 0x4012f420, 0x6213: 0x4012f520,
+ 0x6214: 0x4012f620, 0x6215: 0x4012f720, 0x6216: 0x4012f820, 0x6217: 0x4012f920,
+ 0x6218: 0x4012fa20, 0x6219: 0x4012fb20, 0x621a: 0x4012fc20, 0x621b: 0x4012fd20,
+ 0x621c: 0x4012fe20, 0x621d: 0x4012ff20, 0x621e: 0x40130020, 0x621f: 0x40130120,
+ 0x6220: 0x40130220, 0x6221: 0x40130320, 0x6222: 0x40130420, 0x6223: 0x40130520,
+ 0x6224: 0x40130620, 0x6225: 0x40130720, 0x6226: 0x40130820, 0x6227: 0x40130920,
+ 0x6228: 0x40130a20, 0x6229: 0x40130b20, 0x622a: 0x40130c20, 0x622b: 0x40130d20,
+ 0x622c: 0x40130e20, 0x622d: 0x40130f20, 0x622e: 0x40131020, 0x622f: 0x40131120,
+ 0x6230: 0x40131220, 0x6231: 0x40131320, 0x6232: 0x40131420, 0x6233: 0x40131520,
+ 0x6234: 0x40131620, 0x6235: 0x40131720, 0x6236: 0x40131820, 0x6237: 0x40131920,
+ 0x6238: 0x40131a20, 0x6239: 0x40131b20, 0x623a: 0x40131c20, 0x623b: 0x40131d20,
+ 0x623c: 0x40131e20, 0x623d: 0x40131f20, 0x623e: 0x40132020, 0x623f: 0x40132120,
+ // Block 0x189, offset 0x6240
+ 0x6240: 0x40132220, 0x6241: 0x40132320, 0x6242: 0x40132420, 0x6243: 0x40132520,
+ 0x6244: 0x40132620, 0x6245: 0x40132720, 0x6246: 0x40132820, 0x6247: 0x40132920,
+ 0x6248: 0x40132a20, 0x6249: 0x40132b20, 0x624a: 0x40132c20, 0x624b: 0x40132d20,
+ 0x624c: 0x40132e20, 0x624d: 0x40132f20, 0x624e: 0x40133020, 0x624f: 0x40133120,
+ 0x6250: 0x40133220, 0x6251: 0x40133320, 0x6252: 0x40133420, 0x6253: 0x40133520,
+ 0x6254: 0x40133620, 0x6255: 0x40133720, 0x6256: 0x40133820, 0x6257: 0x40133920,
+ 0x6258: 0x40133a20, 0x6259: 0x40133b20, 0x625a: 0x40133c20, 0x625b: 0x40133d20,
+ 0x625c: 0x40133e20, 0x625d: 0x40133f20, 0x625e: 0x40134020, 0x625f: 0x40134120,
+ 0x6260: 0x40134220, 0x6261: 0x40134320, 0x6262: 0x40134420, 0x6263: 0x40134520,
+ 0x6264: 0x40134620, 0x6265: 0x40134720, 0x6266: 0x40134820, 0x6267: 0x40134920,
+ 0x6268: 0x40134a20, 0x6269: 0x40134b20, 0x626a: 0x40134c20, 0x626b: 0x40134d20,
+ 0x626c: 0x40134e20, 0x626d: 0x40134f20, 0x626e: 0x40135020, 0x626f: 0x40135120,
+ 0x6270: 0x40135220, 0x6271: 0x40135320, 0x6272: 0x40135420, 0x6273: 0x40135520,
+ // Block 0x18a, offset 0x6280
+ 0x6281: 0x80000000,
+ 0x62a0: 0x80000000, 0x62a1: 0x80000000, 0x62a2: 0x80000000, 0x62a3: 0x80000000,
+ 0x62a4: 0x80000000, 0x62a5: 0x80000000, 0x62a6: 0x80000000, 0x62a7: 0x80000000,
+ 0x62a8: 0x80000000, 0x62a9: 0x80000000, 0x62aa: 0x80000000, 0x62ab: 0x80000000,
+ 0x62ac: 0x80000000, 0x62ad: 0x80000000, 0x62ae: 0x80000000, 0x62af: 0x80000000,
+ 0x62b0: 0x80000000, 0x62b1: 0x80000000, 0x62b2: 0x80000000, 0x62b3: 0x80000000,
+ 0x62b4: 0x80000000, 0x62b5: 0x80000000, 0x62b6: 0x80000000, 0x62b7: 0x80000000,
+ 0x62b8: 0x80000000, 0x62b9: 0x80000000, 0x62ba: 0x80000000, 0x62bb: 0x80000000,
+ 0x62bc: 0x80000000, 0x62bd: 0x80000000, 0x62be: 0x80000000, 0x62bf: 0x80000000,
+ // Block 0x18b, offset 0x62c0
+ 0x62c0: 0x80000000, 0x62c1: 0x80000000, 0x62c2: 0x80000000, 0x62c3: 0x80000000,
+ 0x62c4: 0x80000000, 0x62c5: 0x80000000, 0x62c6: 0x80000000, 0x62c7: 0x80000000,
+ 0x62c8: 0x80000000, 0x62c9: 0x80000000, 0x62ca: 0x80000000, 0x62cb: 0x80000000,
+ 0x62cc: 0x80000000, 0x62cd: 0x80000000, 0x62ce: 0x80000000, 0x62cf: 0x80000000,
+ 0x62d0: 0x80000000, 0x62d1: 0x80000000, 0x62d2: 0x80000000, 0x62d3: 0x80000000,
+ 0x62d4: 0x80000000, 0x62d5: 0x80000000, 0x62d6: 0x80000000, 0x62d7: 0x80000000,
+ 0x62d8: 0x80000000, 0x62d9: 0x80000000, 0x62da: 0x80000000, 0x62db: 0x80000000,
+ 0x62dc: 0x80000000, 0x62dd: 0x80000000, 0x62de: 0x80000000, 0x62df: 0x80000000,
+ 0x62e0: 0x80000000, 0x62e1: 0x80000000, 0x62e2: 0x80000000, 0x62e3: 0x80000000,
+ 0x62e4: 0x80000000, 0x62e5: 0x80000000, 0x62e6: 0x80000000, 0x62e7: 0x80000000,
+ 0x62e8: 0x80000000, 0x62e9: 0x80000000, 0x62ea: 0x80000000, 0x62eb: 0x80000000,
+ 0x62ec: 0x80000000, 0x62ed: 0x80000000, 0x62ee: 0x80000000, 0x62ef: 0x80000000,
+ 0x62f0: 0x80000000, 0x62f1: 0x80000000, 0x62f2: 0x80000000, 0x62f3: 0x80000000,
+ 0x62f4: 0x80000000, 0x62f5: 0x80000000, 0x62f6: 0x80000000, 0x62f7: 0x80000000,
+ 0x62f8: 0x80000000, 0x62f9: 0x80000000, 0x62fa: 0x80000000, 0x62fb: 0x80000000,
+ 0x62fc: 0x80000000, 0x62fd: 0x80000000, 0x62fe: 0x80000000, 0x62ff: 0x80000000,
+ // Block 0x18c, offset 0x6300
+ 0x6300: 0x80000000, 0x6301: 0x80000000, 0x6302: 0x80000000, 0x6303: 0x80000000,
+ 0x6304: 0x80000000, 0x6305: 0x80000000, 0x6306: 0x80000000, 0x6307: 0x80000000,
+ 0x6308: 0x80000000, 0x6309: 0x80000000, 0x630a: 0x80000000, 0x630b: 0x80000000,
+ 0x630c: 0x80000000, 0x630d: 0x80000000, 0x630e: 0x80000000, 0x630f: 0x80000000,
+ 0x6310: 0x80000000, 0x6311: 0x80000000, 0x6312: 0x80000000, 0x6313: 0x80000000,
+ 0x6314: 0x80000000, 0x6315: 0x80000000, 0x6316: 0x80000000, 0x6317: 0x80000000,
+ 0x6318: 0x80000000, 0x6319: 0x80000000, 0x631a: 0x80000000, 0x631b: 0x80000000,
+ 0x631c: 0x80000000, 0x631d: 0x80000000, 0x631e: 0x80000000, 0x631f: 0x80000000,
+ 0x6320: 0x80000000, 0x6321: 0x80000000, 0x6322: 0x80000000, 0x6323: 0x80000000,
+ 0x6324: 0x80000000, 0x6325: 0x80000000, 0x6326: 0x80000000, 0x6327: 0x80000000,
+ 0x6328: 0x80000000, 0x6329: 0x80000000, 0x632a: 0x80000000, 0x632b: 0x80000000,
+ 0x632c: 0x80000000, 0x632d: 0x80000000, 0x632e: 0x80000000, 0x632f: 0x80000000,
+}
+
+// mainLookup: 1472 entries, 2944 bytes
+// Block 0 is the null block.
+var mainLookup = [1472]uint16{
+ // Block 0x0, offset 0x0
+ // Block 0x1, offset 0x40
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0x0e0: 0x1f, 0x0e1: 0x20, 0x0e4: 0x21, 0x0e5: 0x22, 0x0e6: 0x23, 0x0e7: 0x24,
+ 0x0e8: 0x25, 0x0e9: 0x26, 0x0ea: 0x27, 0x0eb: 0x28, 0x0ec: 0x29, 0x0ed: 0x2a, 0x0ee: 0x2b, 0x0ef: 0x2c,
+ 0x0f0: 0x2d, 0x0f1: 0x2e, 0x0f2: 0x2f, 0x0f3: 0x30, 0x0f4: 0x31, 0x0f5: 0x32, 0x0f6: 0x33, 0x0f7: 0x34,
+ 0x0f8: 0x35, 0x0f9: 0x36, 0x0fa: 0x37, 0x0fb: 0x38, 0x0fc: 0x39, 0x0fd: 0x3a, 0x0fe: 0x3b, 0x0ff: 0x3c,
+ // Block 0x4, offset 0x100
+ 0x100: 0x3d, 0x101: 0x3e, 0x102: 0x3f, 0x103: 0x40, 0x104: 0x41, 0x105: 0x42, 0x106: 0x43, 0x107: 0x44,
+ 0x108: 0x45, 0x109: 0x46, 0x10a: 0x47, 0x10b: 0x48, 0x10c: 0x49, 0x10d: 0x4a, 0x10e: 0x4b, 0x10f: 0x4c,
+ 0x110: 0x4d, 0x111: 0x4e, 0x112: 0x4f, 0x113: 0x50, 0x114: 0x51, 0x115: 0x52, 0x116: 0x53, 0x117: 0x54,
+ 0x118: 0x55, 0x119: 0x56, 0x11a: 0x57, 0x11b: 0x58, 0x11c: 0x59, 0x11d: 0x5a, 0x11e: 0x5b, 0x11f: 0x5c,
+ 0x120: 0x5d, 0x121: 0x5e, 0x122: 0x5f, 0x123: 0x60, 0x124: 0x61, 0x125: 0x62, 0x126: 0x63, 0x127: 0x64,
+ 0x128: 0x65, 0x129: 0x66, 0x12a: 0x67, 0x12c: 0x68, 0x12d: 0x69, 0x12e: 0x6a, 0x12f: 0x6b,
+ 0x130: 0x6c, 0x131: 0x6d, 0x133: 0x6e, 0x134: 0x6f, 0x135: 0x70, 0x136: 0x71, 0x137: 0x72,
+ 0x13a: 0x73, 0x13b: 0x74, 0x13e: 0x75, 0x13f: 0x76,
+ // Block 0x5, offset 0x140
+ 0x140: 0x77, 0x141: 0x78, 0x142: 0x79, 0x143: 0x7a, 0x144: 0x7b, 0x145: 0x7c, 0x146: 0x7d, 0x147: 0x7e,
+ 0x148: 0x7f, 0x149: 0x80, 0x14a: 0x81, 0x14b: 0x82, 0x14c: 0x83, 0x14d: 0x84, 0x14e: 0x85, 0x14f: 0x86,
+ 0x150: 0x87, 0x151: 0x88, 0x152: 0x89, 0x153: 0x8a, 0x154: 0x8b, 0x155: 0x8c, 0x156: 0x8d, 0x157: 0x8e,
+ 0x158: 0x8f, 0x159: 0x90, 0x15a: 0x91, 0x15b: 0x92, 0x15c: 0x93, 0x15d: 0x94, 0x15e: 0x95, 0x15f: 0x96,
+ 0x160: 0x97, 0x161: 0x98, 0x162: 0x99, 0x163: 0x9a, 0x164: 0x9b, 0x165: 0x9c, 0x166: 0x9d, 0x167: 0x9e,
+ 0x168: 0x9f, 0x169: 0xa0, 0x16a: 0xa1, 0x16b: 0xa2, 0x16c: 0xa3, 0x16d: 0xa4,
+ 0x170: 0xa5, 0x171: 0xa6, 0x172: 0xa7, 0x173: 0xa8, 0x174: 0xa9, 0x175: 0xaa, 0x176: 0xab, 0x177: 0xac,
+ 0x178: 0xad, 0x17a: 0xae, 0x17b: 0xaf, 0x17c: 0xb0, 0x17d: 0xb0, 0x17e: 0xb0, 0x17f: 0xb1,
+ // Block 0x6, offset 0x180
+ 0x180: 0xb2, 0x181: 0xb3, 0x182: 0xb4, 0x183: 0xb5, 0x184: 0xb6, 0x185: 0xb0, 0x186: 0xb7, 0x187: 0xb8,
+ 0x188: 0xb9, 0x189: 0xba, 0x18a: 0xbb, 0x18b: 0xbc, 0x18c: 0xbd, 0x18d: 0xbe, 0x18e: 0xbf, 0x18f: 0xc0,
+ // Block 0x7, offset 0x1c0
+ 0x1f7: 0xc1,
+ // Block 0x8, offset 0x200
+ 0x200: 0xc2, 0x201: 0xc3, 0x202: 0xc4, 0x203: 0xc5, 0x204: 0xc6, 0x205: 0xc7, 0x206: 0xc8, 0x207: 0xc9,
+ 0x208: 0xca, 0x209: 0xcb, 0x20a: 0xcc, 0x20b: 0xcd, 0x20c: 0xce, 0x20d: 0xcf, 0x20e: 0xd0, 0x20f: 0xd1,
+ 0x210: 0xd2, 0x211: 0xd3, 0x212: 0xd4, 0x213: 0xd5, 0x214: 0xd6, 0x215: 0xd7, 0x216: 0xd8, 0x217: 0xd9,
+ 0x218: 0xda, 0x219: 0xdb, 0x21a: 0xdc, 0x21b: 0xdd, 0x21c: 0xde, 0x21d: 0xdf, 0x21e: 0xe0, 0x21f: 0xe1,
+ 0x220: 0xe2, 0x221: 0xe3, 0x222: 0xe4, 0x223: 0xe5, 0x224: 0xe6, 0x225: 0xe7, 0x226: 0xe8, 0x227: 0xe9,
+ 0x228: 0xea, 0x229: 0xeb, 0x22a: 0xec, 0x22b: 0xed, 0x22c: 0xee, 0x22f: 0xef,
+ // Block 0x9, offset 0x240
+ 0x25e: 0xf0, 0x25f: 0xf1,
+ // Block 0xa, offset 0x280
+ 0x2a8: 0xf2, 0x2ac: 0xf3, 0x2ad: 0xf4, 0x2ae: 0xf5, 0x2af: 0xf6,
+ 0x2b0: 0xf7, 0x2b1: 0xf8, 0x2b2: 0xf9, 0x2b3: 0xfa, 0x2b4: 0xfb, 0x2b5: 0xfc, 0x2b6: 0xfd, 0x2b7: 0xfe,
+ 0x2b8: 0xff, 0x2b9: 0x100, 0x2ba: 0x101, 0x2bb: 0x102, 0x2bc: 0x103, 0x2bd: 0x104, 0x2be: 0x105, 0x2bf: 0x106,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x107, 0x2c1: 0x108, 0x2c2: 0x109, 0x2c3: 0x10a, 0x2c4: 0x10b, 0x2c5: 0x10c, 0x2c6: 0x10d, 0x2c7: 0x10e,
+ 0x2ca: 0x10f, 0x2cb: 0x110, 0x2cc: 0x111, 0x2cd: 0x112, 0x2ce: 0x113, 0x2cf: 0x114,
+ 0x2d0: 0x115, 0x2d1: 0x116, 0x2d2: 0x117,
+ 0x2e0: 0x118, 0x2e1: 0x119, 0x2e4: 0x11a,
+ 0x2e8: 0x11b, 0x2e9: 0x11c, 0x2ec: 0x11d, 0x2ed: 0x11e,
+ 0x2f0: 0x11f, 0x2f1: 0x120,
+ 0x2f9: 0x121,
+ // Block 0xc, offset 0x300
+ 0x300: 0x122, 0x301: 0x123, 0x302: 0x124, 0x303: 0x125,
+ // Block 0xd, offset 0x340
+ 0x340: 0x126, 0x341: 0x127, 0x342: 0x128, 0x343: 0x129, 0x344: 0x12a, 0x345: 0x12b, 0x346: 0x12c, 0x347: 0x12d,
+ 0x348: 0x12e, 0x349: 0x12f, 0x34a: 0x130, 0x34b: 0x131, 0x34c: 0x132, 0x34d: 0x133,
+ 0x350: 0x134, 0x351: 0x135,
+ // Block 0xe, offset 0x380
+ 0x380: 0x136, 0x381: 0x137, 0x382: 0x138, 0x383: 0x139, 0x384: 0x13a, 0x385: 0x13b, 0x386: 0x13c, 0x387: 0x13d,
+ 0x388: 0x13e, 0x389: 0x13f, 0x38a: 0x140, 0x38b: 0x141, 0x38c: 0x142, 0x38d: 0x143, 0x38e: 0x144, 0x38f: 0x145,
+ 0x390: 0x146,
+ // Block 0xf, offset 0x3c0
+ 0x3e0: 0x147, 0x3e1: 0x148, 0x3e2: 0x149, 0x3e3: 0x14a, 0x3e4: 0x14b, 0x3e5: 0x14c, 0x3e6: 0x14d, 0x3e7: 0x14e,
+ 0x3e8: 0x14f,
+ // Block 0x10, offset 0x400
+ 0x400: 0x150,
+ // Block 0x11, offset 0x440
+ 0x440: 0x151, 0x441: 0x152, 0x442: 0x153, 0x443: 0x154, 0x444: 0x155, 0x445: 0x156, 0x446: 0x157, 0x447: 0x158,
+ 0x448: 0x159, 0x449: 0x15a, 0x44c: 0x15b, 0x44d: 0x15c,
+ 0x450: 0x15d, 0x451: 0x15e, 0x452: 0x15f, 0x453: 0x160, 0x454: 0x161, 0x455: 0x162, 0x456: 0x163, 0x457: 0x164,
+ 0x458: 0x165, 0x459: 0x166, 0x45a: 0x167, 0x45b: 0x168, 0x45c: 0x169, 0x45d: 0x16a, 0x45e: 0x16b, 0x45f: 0x16c,
+ // Block 0x12, offset 0x480
+ 0x480: 0x16d, 0x481: 0x16e, 0x482: 0x16f, 0x483: 0x170, 0x484: 0x171, 0x485: 0x172, 0x486: 0x173, 0x487: 0x174,
+ 0x488: 0x175, 0x489: 0x176, 0x48c: 0x177, 0x48d: 0x178, 0x48e: 0x179, 0x48f: 0x17a,
+ 0x490: 0x17b, 0x491: 0x17c, 0x492: 0x17d, 0x493: 0x17e, 0x494: 0x17f, 0x495: 0x180, 0x497: 0x181,
+ 0x498: 0x182, 0x499: 0x183, 0x49a: 0x184, 0x49b: 0x185, 0x49c: 0x186, 0x49d: 0x187,
+ // Block 0x13, offset 0x4c0
+ 0x4d0: 0x09, 0x4d1: 0x0a, 0x4d2: 0x0b, 0x4d3: 0x0c, 0x4d6: 0x0d,
+ 0x4db: 0x0e, 0x4dd: 0x0f, 0x4df: 0x10,
+ // Block 0x14, offset 0x500
+ 0x500: 0x188, 0x501: 0x189, 0x504: 0x189, 0x505: 0x189, 0x506: 0x189, 0x507: 0x18a,
+ // Block 0x15, offset 0x540
+ 0x560: 0x12,
+ // Block 0x16, offset 0x580
+ 0x582: 0x01, 0x583: 0x02, 0x584: 0x03, 0x585: 0x04, 0x586: 0x05, 0x587: 0x06,
+ 0x588: 0x07, 0x589: 0x08, 0x58a: 0x09, 0x58b: 0x0a, 0x58c: 0x0b, 0x58d: 0x0c, 0x58e: 0x0d, 0x58f: 0x0e,
+ 0x590: 0x0f, 0x591: 0x10, 0x592: 0x11, 0x593: 0x12, 0x594: 0x13, 0x595: 0x14, 0x596: 0x15, 0x597: 0x16,
+ 0x598: 0x17, 0x599: 0x18, 0x59a: 0x19, 0x59b: 0x1a, 0x59c: 0x1b, 0x59d: 0x1c, 0x59e: 0x1d, 0x59f: 0x1e,
+ 0x5a0: 0x01, 0x5a1: 0x02, 0x5a2: 0x03, 0x5a3: 0x04, 0x5a4: 0x05,
+ 0x5aa: 0x06, 0x5ad: 0x07, 0x5af: 0x08,
+ 0x5b0: 0x11, 0x5b3: 0x13,
+}
+
+// mainCTEntries: 126 entries, 504 bytes
+var mainCTEntries = [126]struct{ l, h, n, i uint8 }{
+ {0xCE, 0x1, 1, 255},
+ {0xC2, 0x0, 1, 255},
+ {0xB7, 0xB7, 0, 1},
+ {0x87, 0x87, 0, 2},
+ {0xCC, 0x0, 2, 255},
+ {0x88, 0x88, 0, 2},
+ {0x86, 0x86, 0, 1},
+ {0xCC, 0x0, 1, 255},
+ {0x88, 0x88, 0, 1},
+ {0xCD, 0x1, 1, 255},
+ {0xCC, 0x0, 1, 255},
+ {0x81, 0x81, 0, 1},
+ {0x81, 0x81, 0, 2},
+ {0xCC, 0x0, 1, 255},
+ {0x86, 0x86, 0, 1},
+ {0xCC, 0x0, 3, 255},
+ {0x8B, 0x8B, 0, 3},
+ {0x88, 0x88, 0, 2},
+ {0x86, 0x86, 0, 1},
+ {0xCC, 0x0, 1, 255},
+ {0x8F, 0x8F, 0, 1},
+ {0xD9, 0x0, 1, 255},
+ {0x93, 0x95, 0, 1},
+ {0xD9, 0x0, 1, 255},
+ {0x94, 0x94, 0, 1},
+ {0xE0, 0x0, 2, 255},
+ {0xA7, 0x1, 1, 255},
+ {0xA6, 0x0, 1, 255},
+ {0xBE, 0xBE, 0, 1},
+ {0x97, 0x97, 0, 2},
+ {0xE0, 0x0, 2, 255},
+ {0xAD, 0x1, 1, 255},
+ {0xAC, 0x0, 1, 255},
+ {0xBE, 0xBE, 0, 1},
+ {0x96, 0x97, 0, 2},
+ {0xE0, 0x0, 1, 255},
+ {0xAF, 0x0, 1, 255},
+ {0x97, 0x97, 0, 1},
+ {0xE0, 0x0, 2, 255},
+ {0xAF, 0x1, 1, 255},
+ {0xAE, 0x0, 1, 255},
+ {0xBE, 0xBE, 0, 1},
+ {0x97, 0x97, 0, 2},
+ {0xE0, 0x0, 1, 255},
+ {0xAE, 0x0, 1, 255},
+ {0xBE, 0xBE, 0, 1},
+ {0xE0, 0x0, 1, 255},
+ {0xB1, 0x0, 1, 255},
+ {0x96, 0x96, 0, 1},
+ {0xE0, 0x0, 1, 255},
+ {0xB3, 0x0, 1, 255},
+ {0x95, 0x95, 0, 1},
+ {0xE0, 0x0, 1, 255},
+ {0xB3, 0x0, 2, 255},
+ {0x95, 0x96, 0, 3},
+ {0x82, 0x0, 1, 2},
+ {0xE0, 0x0, 1, 255},
+ {0xB3, 0x0, 1, 255},
+ {0x95, 0x95, 0, 1},
+ {0xE0, 0x0, 2, 255},
+ {0xB5, 0x1, 1, 255},
+ {0xB4, 0x0, 1, 255},
+ {0xBE, 0xBE, 0, 1},
+ {0x97, 0x97, 0, 2},
+ {0xE0, 0x0, 1, 255},
+ {0xB4, 0x0, 1, 255},
+ {0xBE, 0xBE, 0, 1},
+ {0xE0, 0x0, 1, 255},
+ {0xB7, 0x0, 3, 255},
+ {0x9F, 0x9F, 0, 4},
+ {0x8F, 0x0, 1, 3},
+ {0x8A, 0x8A, 0, 2},
+ {0xE0, 0x0, 1, 255},
+ {0xB7, 0x0, 1, 255},
+ {0x8A, 0x8A, 0, 1},
+ {0xE0, 0x0, 1, 255},
+ {0xB7, 0x0, 1, 255},
+ {0x8A, 0x8A, 0, 1},
+ {0xE0, 0x0, 1, 255},
+ {0xB8, 0x0, 1, 255},
+ {0x81, 0xAE, 0, 1},
+ {0xE0, 0x0, 1, 255},
+ {0xB8, 0x0, 1, 255},
+ {0xB2, 0xB2, 0, 1},
+ {0xE0, 0x0, 2, 255},
+ {0xBB, 0xC, 1, 255},
+ {0xBA, 0x0, 12, 255},
+ {0xAD, 0xAE, 0, 26},
+ {0xAA, 0xAB, 0, 24},
+ {0xA7, 0xA7, 0, 23},
+ {0xA5, 0xA5, 0, 22},
+ {0xA1, 0xA3, 0, 19},
+ {0x99, 0x9F, 0, 12},
+ {0x94, 0x97, 0, 8},
+ {0x8D, 0x8D, 0, 7},
+ {0x8A, 0x8A, 0, 6},
+ {0x87, 0x88, 0, 4},
+ {0x84, 0x84, 0, 3},
+ {0x81, 0x82, 0, 1},
+ {0x9C, 0x9D, 0, 28},
+ {0xE0, 0x0, 1, 255},
+ {0xBA, 0x0, 1, 255},
+ {0xB2, 0xB2, 0, 1},
+ {0xEA, 0x0, 1, 255},
+ {0xAA, 0x0, 1, 255},
+ {0x80, 0xAF, 0, 1},
+ {0xE0, 0x0, 2, 255},
+ {0xBE, 0x4, 1, 255},
+ {0xBD, 0x0, 1, 255},
+ {0xB1, 0x0, 1, 2},
+ {0xE0, 0x0, 1, 255},
+ {0xBE, 0x0, 1, 255},
+ {0x80, 0x80, 0, 1},
+ {0x80, 0x81, 0, 3},
+ {0xE0, 0x0, 2, 255},
+ {0xBE, 0x2, 1, 255},
+ {0xBD, 0x0, 2, 255},
+ {0xB4, 0xB4, 0, 2},
+ {0xB2, 0xB2, 0, 1},
+ {0x80, 0x80, 0, 3},
+ {0xE1, 0x0, 1, 255},
+ {0x80, 0x0, 1, 255},
+ {0xAE, 0xAE, 0, 1},
+ {0xE1, 0x0, 1, 255},
+ {0xAC, 0x0, 1, 255},
+ {0xB5, 0xB5, 0, 1},
+}
+
+// Total size of mainTable is 126988 bytes
diff --git a/libgo/go/exp/locale/collate/tools/colcmp/chars.go b/libgo/go/exp/locale/collate/tools/colcmp/chars.go
new file mode 100644
index 00000000000..c04998d2ec3
--- /dev/null
+++ b/libgo/go/exp/locale/collate/tools/colcmp/chars.go
@@ -0,0 +1,937 @@
+// Generated by running
+// maketables -root=http://unicode.org/Public/UCA/6.0.0/CollationAuxiliary.zip -cldr=http://www.unicode.org/Public/cldr/2.0.1/core.zip
+// DO NOT EDIT
+
+package main
+
+type exemplarType int
+
+const (
+ exCharacters exemplarType = iota
+ exContractions
+ exPunctuation
+ exAuxiliary
+ exCurrency
+ exIndex
+ exN
+)
+
+var exemplarCharacters = map[string][exN]string{
+ "af": {
+ 0: "a á â b c d e é è ê ë f g h i î ï j k l m n o ô ö p q r s t u û v w x y z",
+ 3: "á à â ä ã æ ç é è ê ë í ì î ï ó ò ô ö ú ù û ü ý",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "agq": {
+ 0: "a à â ǎ ā b c d e è ê ě ē ɛ ɛ̀ ɛ̂ ɛ̌ ɛ̄ f g h i ì î ǐ ī ɨ ɨ̀ ɨ̂ ɨ̌ ɨ̄ k l m n ŋ o ò ô ǒ ō ɔ ɔ̀ ɔ̂ ɔ̌ ɔ̄ p s t u ù û ǔ ū ʉ ʉ̀ ʉ̂ ʉ̌ ʉ̄ v w y z ʔ",
+ 3: "q r x",
+ 5: "A B C D E Ɛ F G H I Ɨ K L M N Ŋ O Ɔ P S T U Ʉ V W Y Z ʔ",
+ },
+ "ak": {
+ 0: "a b d e ɛ f g h i k l m n o ɔ p r s t u w y",
+ 3: "c j q v z",
+ 5: "A B C D E Ɛ F G H I J K L M N O Ɔ P Q R S T U V W X Y Z",
+ },
+ "am": {
+ 0: "፟ ሀ ሀ ሁ ሂ ሃ ሄ ህ ሆ ለ ለ ሉ ሊ ላ ሌ ል ሎ ሏ ሐ ሑ ሒ ሓ ሔ ሕ ሖ ሗ መ ሙ ሚ ማ ሜ ም ሞ ሟ ሠ ሡ ሢ ሣ ሤ ሥ ሦ ሧ ረ ሩ ሪ ራ ሬ ር ሮ ሯ ሰ ሱ ሲ ሳ ሴ ስ ሶ ሷ ሸ ሹ ሺ ሻ ሼ ሽ ሾ ሿ ቀ ቁ ቂ ቃ ቄ ቅ ቆ ቈ ቊ ቊ ቋ ቌ ቍ በ በ ቡ ቢ ባ ቤ ብ ቦ ቧ ቨ ቩ ቪ ቫ ቬ ቭ ቮ ቯ ተ ቱ ቲ ታ ቴ ት ቶ ቷ ቸ ቹ ቺ ቻ ቼ ች ቾ ቿ ኀ ኁ ኂ ኃ ኄ ኅ ኆ ኈ ኊ ኊ ኋ ኌ ኍ ነ ነ ኑ ኒ ና ኔ ን ኖ ኗ ኘ ኙ ኚ ኛ ኜ ኝ ኞ ኟ አ ኡ ኢ ኣ ኤ እ ኦ ኧ ከ ኩ ኪ ካ ኬ ክ ኮ ኰ ኲ ኲ ኳ ኴ ኵ ኸ ኸ ኹ ኺ ኻ ኼ ኽ ኾ ወ ወ ዉ ዊ ዋ ዌ ው ዎ ዐ ዐ ዑ ዒ ዓ ዔ ዕ ዖ ዘ ዘ ዙ ዚ ዛ ዜ ዝ ዞ ዟ ዠ ዡ ዢ ዣ ዤ ዥ ዦ ዧ የ ዩ ዪ ያ ዬ ይ ዮ ዯ ደ ዱ ዲ ዳ ዴ ድ ዶ ዷ ጀ ጀ ጁ ጂ ጃ ጄ ጅ ጆ ጇ ገ ጉ ጊ ጋ ጌ ግ ጎ ጐ ጒ ጒ ጓ ጔ ጕ ጠ ጠ ጡ ጢ ጣ ጤ ጥ ጦ ጧ ጨ ጩ ጪ ጫ ጬ ጭ ጮ ጯ ጰ ጱ ጲ ጳ ጴ ጵ ጶ ጷ ጸ ጹ ጺ ጻ ጼ ጽ ጾ ጿ ፀ ፁ ፂ ፃ ፄ ፅ ፆ ፇ ፈ ፉ ፊ ፋ ፌ ፍ ፎ ፏ ፐ ፑ ፒ ፓ ፔ ፕ ፖ ፗ ፘ ፙ ፚ",
+ },
+ "ar": {
+ 0: "ً ٌ ٍ َ ُ ِ ّ ْ ء آ أ ؤ إ ئ ا ب ت ة ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي ى",
+ 3: "\u200c \u200d \u200e \u200f",
+ },
+ "as": {
+ 0: "অ আ ই ঈ উ ঊ ঋ এ ঐ ও ঔ ং ঁ ঃ ক খ গ ঘ ঙ চ ছ জ ঝ ঞ ট ঠ ড ড় ড় ঢ ঢ় ঢ় ণ ত থ দ ধ ন প ফ ব ভ ম য য় ৰ ল ৱ শ ষ স হ া ি ী ু ূ ৃ ে ৈ ো ৌ ্",
+ 3: "\u200c \u200d ৲",
+ },
+ "asa": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y z",
+ 3: "q x",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "az": {
+ 0: "a b c ç d e ə f g ğ h x ı i i̇ j k q l m n o ö p r s ş t u ü v y z",
+ 3: "w",
+ },
+ "az_Cyrl": {
+ 0: "а ә б в г ғ д е ж з и й ј к ҝ л м н о ө п р с т у ү ф х һ ч ҹ ш ы",
+ 3: "ц щ ъ ь э ю я",
+ },
+ "bas": {
+ 0: "a á à â ǎ ā a᷆ a᷇ b ɓ c d e é è ê ě ē e᷆ e᷇ ɛ ɛ́ ɛ̀ ɛ̂ ɛ̌ ɛ̄ ɛ᷆ ɛ᷇ f g h i í ì î ǐ ī i᷆ i᷇ j k l m n ń ǹ ŋ o ó ò ô ǒ ō o᷆ o᷇ ɔ ɔ́ ɔ̀ ɔ̂ ɔ̌ ɔ̄ ɔ᷆ ɔ᷇ p r s t u ú ù û ǔ ū u᷆ u᷇ v w y z",
+ 3: "q x",
+ 5: "A B Ɓ C D E Ɛ F G H I J K L M N Ŋ O Ɔ P R S T U V W Y Z",
+ },
+ "be": {
+ 0: "а б в г д дж дз е ё ж з і й к л м н о п р с т у ў ф х ц ч ш ы ь э ю я",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "bem": {
+ 0: "a b c e f g i j k l m n o p s sh t u w y",
+ 3: "d h q r v x z",
+ 5: "A B C E F G I J K L M N O P S SH T U W Y",
+ },
+ "bez": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w y z",
+ 3: "x",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W Y Z",
+ },
+ "bg": {
+ 0: "а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ь ю я",
+ 3: "а̀ ѐ ѝ о̀ у̀ ъ ѣ ю̀ я̀ ѫ",
+ },
+ "bm": {
+ 0: "a b c d e ɛ f g h i j k l m n ɲ ŋ o ɔ p r s t u w y z",
+ 3: "q v x",
+ 5: "A B C D E Ɛ F G H I J K L M N Ɲ Ŋ O Ɔ P R S T U W Y Z",
+ },
+ "bn": {
+ 0: "৺ অ আ ই ঈ উ ঊ ঋ ৠ ঌ ৡ এ ঐ ও ঔ ় ং ঃ ঁ ক ক্ষ খ গ ঘ ঙ চ ছ জ ঝ ঞ ট ঠ ড ড় ঢ ঢ় ণ ৎ ত থ দ ধ ন প ফ ব ভ ম য য় র ল শ ষ স হ ঽ া ি ী ু ূ ৃ ৄ ৢ ৣ ে ৈ ো ৌ ্ ৗ",
+ 3: "\u200c \u200d ৸ ৹ ৲ ৳ ৰ ৱ ৴ ৵ ৶ ৷",
+ 4: "৳",
+ },
+ "bo": {
+ 0: "ཾ ཿ ཀ ཀྵ ྐ ྐྵ ཁ ྑ ག གྷ ྒ ྒྷ ང ྔ ཅ ྕ ཆ ྖ ཇ ྗ ཉ ྙ ཊ ྚ ཋ ྛ ཌ ཌྷ ྜ ྜྷ ཎ ྞ ཏ ྟ ཐ ྠ ད དྷ ྡ ྡྷ ན ྣ པ ྤ ཕ ྥ བ བྷ ྦ ྦྷ མ ྨ ཙ ྩ ཚ ྪ ཛ ཛྷ ྫ ྫྷ ཝ ྭ ྺ ཞ ྮ ཟ ྯ འ ྰ ཡ ྱ ྻ ར ཪ ྲ ྼ ལ ླ ཤ ྴ ཥ ྵ ས ྶ ཧ ྷ ཨ ྸ ི ཱི ྀ ཱྀ ུ ཱུ ྲྀ ཷ ླྀ ཹ ཹ ེ ཻ ོ ཽ ྄",
+ 3: "ༀ",
+ },
+ "br": {
+ 0: "a b ch cʼh d e ê f g h i j k l m n ñ o p r s t u ù v w x y z",
+ 3: "á à ă â å ä ã ā æ c ç é è ĕ ë ē í ì ĭ î ï ī ó ò ŏ ô ö ø ō œ q ú ŭ û ü ū ÿ",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W X Y Z",
+ },
+ "brx": {
+ 0: "़ ँ ं अ आ इ ई उ ऊ ऍ ए ऐ ऑ ओ औ क ख ग घ च छ ज झ ञ ट ठ ड ड़ ढ ण त थ द ध न प फ ब भ म य र ल ळ व श ष स ह ा ि ी ु ू ृ ॅ े ै ॉ ो ौ ्",
+ 3: "\u200c \u200d",
+ 5: "अ आ इ ई उ ऊ ऍ ए ऐ ऑ ओ औ क ख ग घ च छ ज झ ञ ट ठ ड ड़ ढ ण त थ द ध न प फ ब भ म य र ल ळ व श ष स ह",
+ },
+ "bs": {
+ 0: "a b c č ć d dž đ e f g h i j k l lj m n nj o p r s š t u v z ž",
+ 3: "q w x y",
+ },
+ "byn": {
+ 0: "፟ ሀ ሀ ሁ ሂ ሃ ሄ ህ ሆ ለ ለ ሉ ሊ ላ ሌ ል ሎ ሏ ሐ ሑ ሒ ሓ ሔ ሕ ሖ ሗ መ ሙ ሚ ማ ሜ ም ሞ ሟ ረ ረ ሩ ሪ ራ ሬ ር ሮ ሯ ሰ ሱ ሲ ሳ ሴ ስ ሶ ሷ ሸ ሹ ሺ ሻ ሼ ሽ ሾ ሿ ቀ ቁ ቂ ቃ ቄ ቅ ቆ ቈ ቊ ቊ ቋ ቌ ቍ ቐ ቐ ቑ ቒ ቓ ቔ ቕ ቖ ቘ ቚ ቚ ቛ ቜ ቝ በ በ ቡ ቢ ባ ቤ ብ ቦ ቧ ቨ ቩ ቪ ቫ ቬ ቭ ቮ ቯ ተ ቱ ቲ ታ ቴ ት ቶ ቷ ቸ ቹ ቺ ቻ ቼ ች ቾ ቿ ኀ ኁ ኂ ኃ ኄ ኅ ኆ ኈ ኊ ኊ ኋ ኌ ኍ ነ ነ ኑ ኒ ና ኔ ን ኖ ኗ ኘ ኙ ኚ ኛ ኜ ኝ ኞ ኟ አ ኡ ኢ ኣ ኤ እ ኦ ኧ ከ ኩ ኪ ካ ኬ ክ ኮ ኰ ኲ ኲ ኳ ኴ ኵ ኸ ኸ ኹ ኺ ኻ ኼ ኽ ኾ ዀ ዂ ዂ ዃ ዄ ዅ ወ ወ ዉ ዊ ዋ ዌ ው ዎ ዐ ዐ ዑ ዒ ዓ ዔ ዕ ዖ ዘ ዘ ዙ ዚ ዛ ዜ ዝ ዞ ዟ ዠ ዡ ዢ ዣ ዤ ዥ ዦ ዧ የ ዩ ዪ ያ ዬ ይ ዮ ደ ደ ዱ ዲ ዳ ዴ ድ ዶ ዷ ጀ ጀ ጁ ጂ ጃ ጄ ጅ ጆ ጇ ገ ጉ ጊ ጋ ጌ ግ ጎ ጐ ጒ ጒ ጓ ጔ ጕ ጘ ጘ ጙ ጚ ጛ ጜ ጝ ጞ ጟ ⶓ ⶓ ⶔ ⶕ ⶖ ጠ ጠ ጡ ጢ ጣ ጤ ጥ ጦ ጧ ጨ ጩ ጪ ጫ ጬ ጭ ጮ ጯ ጸ ጸ ጹ ጺ ጻ ጼ ጽ ጾ ጿ ፈ ፈ ፉ ፊ ፋ ፌ ፍ ፎ ፏ ፐ ፑ ፒ ፓ ፔ ፕ ፖ ፗ",
+ },
+ "ca": {
+ 0: "a à b c ç d e é è f g h i í ï j k l ŀ m n o ó ò p q r s t u ú ü v w x y z",
+ 3: "á ă â å ä ã ā æ ĕ ê ë ē ì ĭ î ī ñ º ŏ ô ö ø ō œ ù ŭ û ū ÿ",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "cgg": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "chr": {
+ 0: "Ꭰ Ꭱ Ꭲ Ꭳ Ꭴ Ꭵ Ꭶ Ꭷ Ꭸ Ꭹ Ꭺ Ꭻ Ꭼ Ꭽ Ꭾ Ꭿ Ꮀ Ꮁ Ꮂ Ꮃ Ꮄ Ꮅ Ꮆ Ꮇ Ꮈ Ꮉ Ꮊ Ꮋ Ꮌ Ꮍ Ꮎ Ꮏ Ꮐ Ꮑ Ꮒ Ꮓ Ꮔ Ꮕ Ꮖ Ꮗ Ꮘ Ꮙ Ꮚ Ꮛ Ꮜ Ꮝ Ꮞ Ꮟ Ꮠ Ꮡ Ꮢ Ꮣ Ꮤ Ꮥ Ꮦ Ꮧ Ꮨ Ꮩ Ꮪ Ꮫ Ꮬ Ꮭ Ꮮ Ꮯ Ꮰ Ꮱ Ꮲ Ꮳ Ꮴ Ꮵ Ꮶ Ꮷ Ꮸ Ꮹ Ꮺ Ꮻ Ꮼ Ꮽ Ꮾ Ꮿ Ᏸ Ᏹ Ᏺ Ᏻ Ᏼ",
+ 5: "Ꭰ Ꭶ Ꭽ Ꮃ Ꮉ Ꮎ Ꮖ Ꮜ Ꮣ Ꮬ Ꮳ Ꮹ Ꮿ",
+ },
+ "cs": {
+ 0: "a á b c č d ď e é ě f g h ch i í j k l m n ň o ó p q r ř s š t ť u ú ů v w x y ý z ž",
+ },
+ "cy": {
+ 0: "a á à â ä b c ch d dd e é è ê ë f ff g ng h i í ì î ï l ll m n o ó ò ô ö p ph r rh s t th u ú ù û ü w ẃ ẁ ŵ ẅ y ý ỳ ŷ ÿ",
+ 3: "j k q v x z",
+ },
+ "da": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z æ ø å",
+ 2: "- ‐ – , ; : ! ? . … ' ‘ ’ \" “ ” ( ) [ ] @ * / & # † ′ ″ §",
+ 3: "á é è ê ë ü ä ö",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Æ Ø Å",
+ },
+ "dav": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y z",
+ 3: "q x",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "de": {
+ 0: "a ä b c d e f g h i j k l m n o ö p q r s ß t u ü v w x y z",
+ 2: "- ‐ – — , ; : ! ? . … ' ‘ ‚ \" “ „ « » ( ) [ ] { } @ * / & # §",
+ 3: "á à ă â å ã ā æ ç é è ĕ ê ë ē í ì ĭ î ï ī ñ ó ò ŏ ô ø ō œ ú ù ŭ û ū ÿ",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "dje": {
+ 0: "a ã b c d e ẽ f g h i j k l m n ɲ ŋ o õ p q r s š t u w x y z ž",
+ 3: "v",
+ 5: "A B C D E F G H I J K L M N Ɲ Ŋ O P Q R S T U W X Y Z",
+ },
+ "dua": {
+ 0: "a á b ɓ c d ɗ e é ɛ ɛ́ f g i í j k l m n ny ŋ o ó ɔ ɔ́ p r s t u ú ū w y",
+ 3: "h q v x z",
+ 5: "A B Ɓ C D Ɗ E Ɛ F G I J K L M N Ŋ O Ɔ P S T U W Y",
+ },
+ "dyo": {
+ 0: "a á b c d e é f g h i í j k l m n ñ ŋ o ó p q r s t u ú v w x y",
+ 3: "z",
+ 5: "A B C D E F G H I J K L M N Ñ Ŋ O P Q R S T U V W X Y",
+ },
+ "dz": {
+ 0: "ཀ ྐ ཁ ྑ ག ྒ ང ྔ ཅ ཆ ཇ ྗ ཉ ྙ ཏ ྟ ཐ ད ྡ ན ྣ པ ྤ ཕ བ ྦ མ ྨ ཙ ྩ ཚ ཛ ྫ ཝ ྭ ཞ ཟ འ ཡ ྱ ར ྲ ལ ླ ཤ ྵ ས ཧ ྷ ཨ ི ུ ེ ོ",
+ 3: "ཊ ཋ ཌ ཎ ཥ",
+ },
+ "ebu": {
+ 0: "a b c d e f g h i ĩ j k l m n o p q r s t u ũ v w x y z",
+ 5: "A B C D E F G H I Ĩ J K L M N O P Q R S T U Ũ V W X Y Z",
+ },
+ "ee": {
+ 0: "a á à ã b d ɖ e é è ẽ ɛ ɛ́ ɛ̀ ɛ̃ f ƒ g ɣ h i í ì ĩ k l m n ŋ o ó ò õ ɔ ɔ́ ɔ̀ ɔ̃ p r s t u ú ù ũ v ʋ w x y z",
+ 3: "c j q",
+ 5: "A B C D Ɖ E Ɛ F Ƒ G Ɣ H I J K L M N Ŋ O Ɔ P Q R S T U V Ʋ W X Y Z",
+ },
+ "el": {
+ 0: "α ά β γ δ ε έ ζ η ή θ ι ί ϊ ΐ κ λ μ ν ξ ο ό π ρ σ ς τ υ ύ ϋ ΰ φ χ ψ ω ώ",
+ 2: "- ‐ – — , ; : ! . … \" ( ) [ ] @ * / \\ & §",
+ 4: "α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ σ τ υ φ χ ψ ω",
+ 5: "Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω",
+ },
+ "el_POLYTON": {
+ 0: "α ἀ ἄ ἂ ἆ ἁ ἅ ἃ ἇ ά ὰ ᾶ β γ δ ε ἐ ἔ ἒ ἑ ἕ ἓ έ ὲ ζ η ἠ ἤ ἢ ἦ ἡ ἥ ἣ ἧ ή ὴ ῆ θ ι ἰ ἴ ἲ ἶ ἱ ἵ ἳ ἷ ί ὶ ῖ ϊ ΐ ῒ ῗ κ λ μ ν ξ ο ὄ ὂ ὃ ό ὸ π ρ σ ς τ υ ὐ ὔ ὒ ὖ ὑ ὕ ὓ ὗ ύ ὺ ῦ ϋ ΰ ῢ ῧ φ χ ψ ω ὤ ὢ ὦ ὥ ὣ ὧ ώ ὼ ῶ",
+ },
+ "en": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 2: "- ‐ – — , ; : ! ? . … ' ‘ ’ \" “ ” ( ) [ ] @ * / & # † ‡ ′ ″ §",
+ 3: "á à ă â å ä ã ā æ ç é è ĕ ê ë ē í ì ĭ î ï ī ñ ó ò ŏ ô ö ø ō œ ú ù ŭ û ü ū ÿ",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "en_Dsrt": {
+ 0: "𐐨 𐐩 𐐪 𐐫 𐐬 𐐭 𐐮 𐐯 𐐰 𐐱 𐐲 𐐳 𐐴 𐐵 𐐶 𐐷 𐐸 𐐹 𐐺 𐐻 𐐼 𐐽 𐐾 𐐿 𐑀 𐑁 𐑂 𐑃 𐑄 𐑅 𐑆 𐑇 𐑈 𐑉 𐑊 𐑋 𐑌 𐑍 𐑎 𐑏",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "en_GB": {
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "en_Shaw": {
+ 0: "𐑐 𐑑 𐑒 𐑓 𐑔 𐑕 𐑖 𐑗 𐑘 𐑙 𐑚 𐑛 𐑜 𐑝 𐑞 𐑟 𐑠 𐑡 𐑢 𐑣 𐑤 𐑥 𐑦 𐑧 𐑨 𐑩 𐑪 𐑫 𐑬 𐑭 𐑮 𐑯 𐑰 𐑱 𐑲 𐑳 𐑴 𐑵 𐑶 𐑷 𐑸 𐑹 𐑺 𐑻 𐑼 𐑽 𐑾 𐑿",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "eo": {
+ 0: "a b c ĉ d e f g ĝ h ĥ i j ĵ k l m n o p r s ŝ t u ŭ v z",
+ 3: "q w x y",
+ 5: "A B C Ĉ D E F G Ĝ H Ĥ I J Ĵ K L M N O P R S Ŝ T U Ŭ V Z",
+ },
+ "es": {
+ 0: "a á b c d e é f g h i í j k l m n ñ o ó p q r s t u ú ü v w x y z",
+ 2: "- ‐ – — , ; : ! ¡ ? ¿ . … ' ‘ ’ \" “ ” « » ( ) [ ] @ * / \\ & # † ‡ ′ ″ §",
+ 3: "à ă â å ä ã ā æ ç è ĕ ê ë ē ì ĭ î ï ī º ò ŏ ô ö ø ō œ ù ŭ û ū ÿ",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N Ñ O P Q R S T U V W X Y Z",
+ },
+ "et": {
+ 0: "a b c d e f g h i j k l m n o p q r s š z ž t u v w õ ä ö ü x y",
+ 3: "á à â å ā æ ç é è ê ë ē í ì î ï ī ñ ó ò ŏ ô ø ō œ ú ù û ū",
+ 4: "a b c d e f g h i j k l m n o p q r s š z ž t u v w õ ä ö ü x y",
+ 5: "A B C D E F G H I J K L M N O P Q R S Š Z Ž T U V Õ Ä Ö Ü X Y",
+ },
+ "eu": {
+ 0: "a b c ç d e f g h i j k l m n ñ o p q r s t u v w x y z",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "ewo": {
+ 0: "a á à â ǎ b d dz e é è ê ě ǝ ǝ́ ǝ̀ ǝ̂ ǝ̌ ɛ ɛ́ ɛ̀ ɛ̂ ɛ̌ f g h i í ì î ǐ k kp l m n ń ǹ ng nk ŋ o ó ò ô ǒ ɔ ɔ́ ɔ̀ ɔ̂ ɔ̌ p r s t ts u ú ù û ǔ v w y z",
+ 3: "c j q x",
+ 5: "A B D E Ǝ Ɛ F G H I K L M N Ŋ O Ɔ P R S T U V W Y Z",
+ },
+ "fa": {
+ 0: "ً ٍ ٌ ّ ٔ آ ا ء أ ؤ ئ ب پ ت ث ج چ ح خ د ذ ر ز ژ س ش ص ض ط ظ ع غ ف ق ک گ ل م ن و ه ة ی",
+ 2: "- ‐ ، ٫ ٬ ؛ : ! ؟ . … « » ( ) [ ] * / \\",
+ 3: "\u200c \u200d \u200e \u200f َ ِ ُ ْ ٖ ٰ ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹",
+ 4: "﷼ a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "آ ا ب پ ت ث ج چ ح خ د ذ ر ز ژ س ش ص ض ط ظ ع غ ف ق ک گ ل م ن و ه ی",
+ },
+ "fa_AF": {
+ 3: "ٖ ٰ \u200c \u200d ټ ځ څ ډ ړ ږ ښ ګ ڼ ي",
+ },
+ "ff": {
+ 0: "a b ɓ c d ɗ e f g h i j k l m n ñ ŋ o p r s t u w y ƴ",
+ 3: "q v x z",
+ 5: "A B Ɓ C D Ɗ E F G H I J K L M N Ñ Ŋ O P R S T U W Y Ƴ",
+ },
+ "fi": {
+ 0: "a b c d e f g h i j k l m n o p q r s š t u v w x y z ž å ä ö",
+ 3: "á à â ã č ç đ é è ë ǧ ǥ ȟ í ï ǩ ń ñ ŋ ô õ œ ř ŧ ú ü ʒ ǯ æ ø",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Å Ä Ö",
+ },
+ "fil": {
+ 0: "a b c d e f g h i j k l m n ñ ng o p q r s t u v w x y z",
+ 3: "á à â é è ê í ì î ó ò ô ú ù û",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "fo": {
+ 0: "a á b d ð e f g h i í j k l m n o ó p r s t u ú v x y ý æ ø",
+ 3: "c q w z",
+ },
+ "fr": {
+ 0: "a à â æ b c ç d e é è ê ë f g h i î ï j k l m n o ô œ p q r s t u ù û ü v w x y ÿ z",
+ 2: "- ‐ – — , ; : ! ? . … ’ « » ( ) [ ] @ * / & # † ‡ §",
+ 3: "á å ä ã ā ē í ì ī ñ ó ò ö ø ú ǔ",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "fur": {
+ 0: "a à â b c ç d e è ê f g h i ì î j k l m n o ò ô p q r s t u ù û v w x y z",
+ 3: "å č é ë ğ ï ñ ó š ü",
+ },
+ "ga": {
+ 0: "a á b c d e é f g h i í l m n o ó p r s t u ú",
+ 3: "ḃ ċ ḋ ḟ ġ j k ṁ ṗ q ṡ ṫ v w x y z",
+ },
+ "gl": {
+ 0: "a á b c d e é f g h i í j k l m n ñ o ó p q r s t u ú ü v w x y z",
+ 5: "A B C D E F G H I J K L M N Ñ O P Q R S T U V W X Y Z",
+ },
+ "gsw": {
+ 0: "a ä b c d e f g h i j k l m n o ö p q r s t u ü v w x y z",
+ 3: "á à ă â å ā æ ç é è ĕ ê ë ē í ì ĭ î ï ī ñ ó ò ŏ ô ø ō œ ú ù ŭ û ū ÿ",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "gu": {
+ 0: "઼ ૐ ં ઁ ઃ અ આ ઇ ઈ ઉ ઊ ઋ ૠ ઍ એ ઐ ઑ ઓ ઔ ક ખ ગ ઘ ઙ ચ છ જ ઝ ઞ ટ ઠ ડ ઢ ણ ત થ દ ધ ન પ ફ બ ભ મ ય ર લ વ શ ષ સ હ ળ ઽ ા િ ી ુ ૂ ૃ ૄ ૅ ે ૈ ૉ ો ૌ ્",
+ 3: "\u200c \u200d",
+ 4: "ર ૂ",
+ 5: "અ આ ઇ ઈ ઉ ઊ ઋ એ ઐ ઓ ઔ ક ખ ગ ઘ ઙ ચ છ જ ઝ ઞ ટ ઠ ડ ઢ ણ ત થ દ ધ ન પ ફ બ ભ મ ય ર લ વ શ ષ સ હ ળ",
+ },
+ "guz": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y z",
+ 3: "q x",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "gv": {
+ 0: "a b c ç d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "ha": {
+ 0: "a b ɓ c d ɗ e f g h i j k ƙ l m n o r s sh t ts u w y ʼy z ʼ",
+ 3: "á à â é è ê í ì î ó ò ô p q r̃ ú ù û v x ƴ",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "haw": {
+ 0: "a ā e ē i ī o ō u ū h k l m n p w ʻ",
+ 3: "b c d f g j q r s t v x y z",
+ },
+ "he": {
+ 0: "א ב ג ד ה ו ז ח ט י כ ך ל מ ם נ ן ס ע פ ף צ ץ ק ר ש ת",
+ 3: "ֽ ׄ \u200e \u200f ְ ֱ ֲ ֳ ִ ֵ ֶ ַ ָ ֹ ֻ ׂ ׁ ּ ֿ ־ ׳ ״",
+ 5: "א ב ג ד ה ו ז ח ט י כ ל מ נ ס ע פ צ ק ר ש ת",
+ },
+ "hi": {
+ 0: "़ ॐ ं ँ ः अ आ इ ई उ ऊ ऋ ऌ ऍ ए ऐ ऑ ओ औ क ख ग घ ङ च छ ज झ ञ ट ठ ड ढ ण त थ द ध न प फ ब भ म य र ल ळ व श ष स ह ऽ ा ि ी ु ू ृ ॄ ॅ े ै ॉ ो ौ ्",
+ 3: "\u200c \u200d",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ },
+ "hr": {
+ 0: "a b c č ć d dž đ e f g h i j k l lj m n nj o p r s š t u v z ž",
+ 3: "q w x y",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C Č Ć D DŽ Đ E F G H I J K L LJ M N NJ O P Q R S Š T U V W X Y Z Ž",
+ },
+ "hu": {
+ 0: "a á b c cs ccs d dz ddz dzs ddzs e é f g gy ggy h i í j k l ly lly m n ny nny o ó ö ő p r s sz ssz t ty tty u ú ü ű v z zs zzs",
+ 2: "- – , ; : ! ? . … ' ’ \" ” „ « » ( ) [ ] { } 〈 〉 @ * / & # ⸓ § ~",
+ 3: "à ă â å ä ã ā æ ç è ĕ ê ë ē ì ĭ î ï ī ñ ò ŏ ô ø ō œ q ù ŭ û ū w x y ÿ",
+ 5: "A Á B C CS D DZ DZS E É F G GY H I Í J K L LY M N NY O Ó Ö Ő P Q R S SZ T TY U Ú Ü Ű V W X Y Z ZS",
+ },
+ "hy": {
+ 0: "֊ ՝ ՜ ՞ ՚ ՛ ՟ ա բ գ դ ե զ է ը թ ժ ի լ խ ծ կ հ ձ ղ ճ մ յ ն շ ո չ պ ջ ռ ս վ տ ր ց ւ փ ք և օ ֆ",
+ },
+ "ia": {
+ 0: "a b c ch d e f g h i j k l m n o p ph q r s t u v w x y z",
+ },
+ "id": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "ig": {
+ 0: "a b ch d e ẹ f g gb gh gw h i ị j k kp kw l m n ṅ nw ny o ọ p r s sh t u ụ v w y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "ii": {
+ 0: "ꀀ ꀀ ꀁ ꀂ ꀃ ꀄ ꀅ ꀆ ꀇ ꀈ ꀉ ꀊ ꀋ ꀌ ꀍ ꀎ ꀏ ꀐ ꀑ ꀒ ꀓ ꀔ ꀕ ꀖ ꀗ ꀘ ꀙ ꀚ ꀛ ꀜ ꀝ ꀞ ꀟ ꀠ ꀡ ꀢ ꀣ ꀤ ꀥ ꀦ ꀧ ꀨ ꀩ ꀪ ꀫ ꀬ ꀭ ꀮ ꀯ ꀰ ꀱ ꀲ ꀳ ꀴ ꀵ ꀶ ꀷ ꀸ ꀹ ꀺ ꀻ ꀼ ꀽ ꀾ ꀿ ꁀ ꁁ ꁂ ꁃ ꁄ ꁅ ꁆ ꁇ ꁈ ꁉ ꁊ ꁋ ꁌ ꁍ ꁎ ꁏ ꁐ ꁑ ꁒ ꁓ ꁔ ꁕ ꁖ ꁗ ꁘ ꁙ ꁚ ꁛ ꁜ ꁝ ꁞ ꁟ ꁠ ꁡ ꁢ ꁣ ꁤ ꁥ ꁦ ꁧ ꁨ ꁩ ꁪ ꁫ ꁬ ꁭ ꁮ ꁯ ꁰ ꁱ ꁲ ꁳ ꁴ ꁵ ꁶ ꁷ ꁸ ꁹ ꁺ ꁻ ꁼ ꁽ ꁾ ꁿ ꂀ ꂁ ꂂ ꂃ ꂄ ꂅ ꂆ ꂇ ꂈ ꂉ ꂊ ꂋ ꂌ ꂍ ꂎ ꂏ ꂐ ꂑ ꂒ ꂓ ꂔ ꂕ ꂖ ꂗ ꂘ ꂙ ꂚ ꂛ ꂜ ꂝ ꂞ ꂟ ꂠ ꂡ ꂢ ꂣ ꂤ ꂥ ꂦ ꂧ ꂨ ꂩ ꂪ ꂫ ꂬ ꂭ ꂮ ꂯ ꂰ ꂱ ꂲ ꂳ ꂴ ꂵ ꂶ ꂷ ꂸ ꂹ ꂺ ꂻ ꂼ ꂽ ꂾ ꂿ ꃀ ꃁ ꃂ ꃃ ꃄ ꃅ ꃆ ꃇ ꃈ ꃉ ꃊ ꃋ ꃌ ꃍ ꃎ ꃏ ꃐ ꃑ ꃒ ꃓ ꃔ ꃕ ꃖ ꃗ ꃘ ꃙ ꃚ ꃛ ꃜ ꃝ ꃞ ꃟ ꃠ ꃡ ꃢ ꃣ ꃤ ꃥ ꃦ ꃧ ꃨ ꃩ ꃪ ꃫ ꃬ ꃭ ꃮ ꃯ ꃰ ꃱ ꃲ ꃳ ꃴ ꃵ ꃶ ꃷ ꃸ ꃹ ꃺ ꃻ ꃼ ꃽ ꃾ ꃿ ꄀ ꄁ ꄂ ꄃ ꄄ ꄅ ꄆ ꄇ ꄈ ꄉ ꄊ ꄋ ꄌ ꄍ ꄎ ꄏ ꄐ ꄑ ꄒ ꄓ ꄔ ꄕ ꄖ ꄗ ꄘ ꄙ ꄚ ꄛ ꄜ ꄝ ꄞ ꄟ ꄠ ꄡ ꄢ ꄣ ꄤ ꄥ ꄦ ꄧ ꄨ ꄩ ꄪ ꄫ ꄬ ꄭ ꄮ ꄯ ꄰ ꄱ ꄲ ꄳ ꄴ ꄵ ꄶ ꄷ ꄸ ꄹ ꄺ ꄻ ꄼ ꄽ ꄾ ꄿ ꅀ ꅁ ꅂ ꅃ ꅄ ꅅ ꅆ ꅇ ꅈ ꅉ ꅊ ꅋ ꅌ ꅍ ꅎ ꅏ ꅐ ꅑ ꅒ ꅓ ꅔ ꅕ ꅖ ꅗ ꅘ ꅙ ꅚ ꅛ ꅜ ꅝ ꅞ ꅟ ꅠ ꅡ ꅢ ꅣ ꅤ ꅥ ꅦ ꅧ ꅨ ꅩ ꅪ ꅫ ꅬ ꅭ ꅮ ꅯ ꅰ ꅱ ꅲ ꅳ ꅴ ꅵ ꅶ ꅷ ꅸ ꅹ ꅺ ꅻ ꅼ ꅽ ꅾ ꅿ ꆀ ꆁ ꆂ ꆃ ꆄ ꆅ ꆆ ꆇ ꆈ ꆉ ꆊ ꆋ ꆌ ꆍ ꆎ ꆏ ꆐ ꆑ ꆒ ꆓ ꆔ ꆕ ꆖ ꆗ ꆘ ꆙ ꆚ ꆛ ꆜ ꆝ ꆞ ꆟ ꆠ ꆡ ꆢ ꆣ ꆤ ꆥ ꆦ ꆧ ꆨ ꆩ ꆪ ꆫ ꆬ ꆭ ꆮ ꆯ ꆰ ꆱ ꆲ ꆳ ꆴ ꆵ ꆶ ꆷ ꆸ ꆹ ꆺ ꆻ ꆼ ꆽ ꆾ ꆿ ꇀ ꇁ ꇂ ꇃ ꇄ ꇅ ꇆ ꇇ ꇈ ꇉ ꇊ ꇋ ꇌ ꇍ ꇎ ꇏ ꇐ ꇑ ꇒ ꇓ ꇔ ꇕ ꇖ ꇗ ꇘ ꇙ ꇚ ꇛ ꇜ ꇝ ꇞ ꇟ ꇠ ꇡ ꇢ ꇣ ꇤ ꇥ ꇦ ꇧ ꇨ ꇩ ꇪ ꇫ ꇬ ꇭ ꇮ ꇯ ꇰ ꇱ ꇲ ꇳ ꇴ ꇵ ꇶ ꇷ ꇸ ꇹ ꇺ ꇻ ꇼ ꇽ ꇾ ꇿ ꈀ ꈁ ꈂ ꈃ ꈄ ꈅ ꈆ ꈇ ꈈ ꈉ ꈊ ꈋ ꈌ ꈍ ꈎ ꈏ ꈐ ꈑ ꈒ ꈓ ꈔ ꈕ ꈖ ꈗ ꈘ ꈙ ꈚ ꈛ ꈜ ꈝ ꈞ ꈟ ꈠ ꈡ ꈢ ꈣ ꈤ ꈥ ꈦ ꈧ ꈨ ꈩ ꈪ ꈫ ꈬ ꈭ ꈮ ꈯ ꈰ ꈱ ꈲ ꈳ ꈴ ꈵ ꈶ ꈷ ꈸ ꈹ ꈺ ꈻ ꈼ ꈽ ꈾ ꈿ ꉀ ꉁ ꉂ ꉃ ꉄ ꉅ ꉆ ꉇ ꉈ ꉉ ꉊ ꉋ ꉌ ꉍ ꉎ ꉏ ꉐ ꉑ ꉒ ꉓ ꉔ ꉕ ꉖ ꉗ ꉘ ꉙ ꉚ ꉛ ꉜ ꉝ ꉞ ꉟ ꉠ ꉡ ꉢ ꉣ ꉤ ꉥ ꉦ ꉧ ꉨ ꉩ ꉪ ꉫ ꉬ ꉭ ꉮ ꉯ ꉰ ꉱ ꉲ ꉳ ꉴ ꉵ ꉶ ꉷ ꉸ ꉹ ꉺ ꉻ ꉼ ꉽ ꉾ ꉿ ꊀ ꊁ ꊂ ꊃ ꊄ ꊅ ꊆ ꊇ ꊈ ꊉ ꊊ ꊋ ꊌ ꊍ ꊎ ꊏ ꊐ ꊑ ꊒ ꊓ ꊔ ꊕ ꊖ ꊗ ꊘ ꊙ ꊚ ꊛ ꊜ ꊝ ꊞ ꊟ ꊠ ꊡ ꊢ ꊣ ꊤ ꊥ ꊦ ꊧ ꊨ ꊩ ꊪ ꊫ ꊬ ꊭ ꊮ ꊯ ꊰ ꊱ ꊲ ꊳ ꊴ ꊵ ꊶ ꊷ ꊸ ꊹ ꊺ ꊻ ꊼ ꊽ ꊾ ꊿ ꋀ ꋁ ꋂ ꋃ ꋄ ꋅ ꋆ ꋇ ꋈ ꋉ ꋊ ꋋ ꋌ ꋍ ꋎ ꋏ ꋐ ꋑ ꋒ ꋓ ꋔ ꋕ ꋖ ꋗ ꋘ ꋙ ꋚ ꋛ ꋜ ꋝ ꋞ ꋟ ꋠ ꋡ ꋢ ꋣ ꋤ ꋥ ꋦ ꋧ ꋨ ꋩ ꋪ ꋫ ꋬ ꋭ ꋮ ꋯ ꋰ ꋱ ꋲ ꋳ ꋴ ꋵ ꋶ ꋷ ꋸ ꋹ ꋺ ꋻ ꋼ ꋽ ꋾ ꋿ ꌀ ꌁ ꌂ ꌃ ꌄ ꌅ ꌆ ꌇ ꌈ ꌉ ꌊ ꌋ ꌌ ꌍ ꌎ ꌏ ꌐ ꌑ ꌒ ꌓ ꌔ ꌕ ꌖ ꌗ ꌘ ꌙ ꌚ ꌛ ꌜ ꌝ ꌞ ꌟ ꌠ ꌡ ꌢ ꌣ ꌤ ꌥ ꌦ ꌧ ꌨ ꌩ ꌪ ꌫ ꌬ ꌭ ꌮ ꌯ ꌰ ꌱ ꌲ ꌳ ꌴ ꌵ ꌶ ꌷ ꌸ ꌹ ꌺ ꌻ ꌼ ꌽ ꌾ ꌿ ꍀ ꍁ ꍂ ꍃ ꍄ ꍅ ꍆ ꍇ ꍈ ꍉ ꍊ ꍋ ꍌ ꍍ ꍎ ꍏ ꍐ ꍑ ꍒ ꍓ ꍔ ꍕ ꍖ ꍗ ꍘ ꍙ ꍚ ꍛ ꍜ ꍝ ꍞ ꍟ ꍠ ꍡ ꍢ ꍣ ꍤ ꍥ ꍦ ꍧ ꍨ ꍩ ꍪ ꍫ ꍬ ꍭ ꍮ ꍯ ꍰ ꍱ ꍲ ꍳ ꍴ ꍵ ꍶ ꍷ ꍸ ꍹ ꍺ ꍻ ꍼ ꍽ ꍾ ꍿ ꎀ ꎁ ꎂ ꎃ ꎄ ꎅ ꎆ ꎇ ꎈ ꎉ ꎊ ꎋ ꎌ ꎍ ꎎ ꎏ ꎐ ꎑ ꎒ ꎓ ꎔ ꎕ ꎖ ꎗ ꎘ ꎙ ꎚ ꎛ ꎜ ꎝ ꎞ ꎟ ꎠ ꎡ ꎢ ꎣ ꎤ ꎥ ꎦ ꎧ ꎨ ꎩ ꎪ ꎫ ꎬ ꎭ ꎮ ꎯ ꎰ ꎱ ꎲ ꎳ ꎴ ꎵ ꎶ ꎷ ꎸ ꎹ ꎺ ꎻ ꎼ ꎽ ꎾ ꎿ ꏀ ꏁ ꏂ ꏃ ꏄ ꏅ ꏆ ꏇ ꏈ ꏉ ꏊ ꏋ ꏌ ꏍ ꏎ ꏏ ꏐ ꏑ ꏒ ꏓ ꏔ ꏕ ꏖ ꏗ ꏘ ꏙ ꏚ ꏛ ꏜ ꏝ ꏞ ꏟ ꏠ ꏡ ꏢ ꏣ ꏤ ꏥ ꏦ ꏧ ꏨ ꏩ ꏪ ꏫ ꏬ ꏭ ꏮ ꏯ ꏰ ꏱ ꏲ ꏳ ꏴ ꏵ ꏶ ꏷ ꏸ ꏹ ꏺ ꏻ ꏼ ꏽ ꏾ ꏿ ꐀ ꐁ ꐂ ꐃ ꐄ ꐅ ꐆ ꐇ ꐈ ꐉ ꐊ ꐋ ꐌ ꐍ ꐎ ꐏ ꐐ ꐑ ꐒ ꐓ ꐔ ꐕ ꐖ ꐗ ꐘ ꐙ ꐚ ꐛ ꐜ ꐝ ꐞ ꐟ ꐠ ꐡ ꐢ ꐣ ꐤ ꐥ ꐦ ꐧ ꐨ ꐩ ꐪ ꐫ ꐬ ꐭ ꐮ ꐯ ꐰ ꐱ ꐲ ꐳ ꐴ ꐵ ꐶ ꐷ ꐸ ꐹ ꐺ ꐻ ꐼ ꐽ ꐾ ꐿ ꑀ ꑁ ꑂ ꑃ ꑄ ꑅ ꑆ ꑇ ꑈ ꑉ ꑊ ꑋ ꑌ ꑍ ꑎ ꑏ ꑐ ꑑ ꑒ ꑓ ꑔ ꑕ ꑖ ꑗ ꑘ ꑙ ꑚ ꑛ ꑜ ꑝ ꑞ ꑟ ꑠ ꑡ ꑢ ꑣ ꑤ ꑥ ꑦ ꑧ ꑨ ꑩ ꑪ ꑫ ꑬ ꑭ ꑮ ꑯ ꑰ ꑱ ꑲ ꑳ ꑴ ꑵ ꑶ ꑷ ꑸ ꑹ ꑺ ꑻ ꑼ ꑽ ꑾ ꑿ ꒀ ꒁ ꒂ ꒃ ꒄ ꒅ ꒆ ꒇ ꒈ ꒉ ꒊ ꒋ ꒌ",
+ },
+ "is": {
+ 0: "a á b d ð e é f g h i í j k l m n o ó p r s t u ú v y ý þ æ ö",
+ 3: "c q w x z",
+ },
+ "it": {
+ 0: "a à b c d e é è f g h i ì j k l m n o ó ò p q r s t u ù v w x y z",
+ 2: "- — , ; : ! ? . … “ ” ( ) [ ] { } @ /",
+ 3: "í ï ú",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "ja": {
+ 0: "ゞ ゝ ヽ ヾ ぁ ァ あ ア ぃ ィ い イ ぅ ゥ う ウ ヴ ぇ ェ え エ ぉ ォ お オ ヵ か カ が ガ き キ ぎ ギ く ク ぐ グ ヶ け ケ げ ゲ こ コ ご ゴ さ サ ざ ザ し シ じ ジ す ス ず ズ せ セ ぜ ゼ そ ソ ぞ ゾ た タ だ ダ ち チ ぢ ヂ っ ッ つ ツ づ ヅ て テ で デ と ト ど ド な ナ に ニ ぬ ヌ ね ネ の ノ は ハ ば バ ぱ パ ひ ヒ び ビ ぴ ピ ふ フ ぶ ブ ぷ プ へ ヘ べ ベ ぺ ペ ほ ホ ぼ ボ ぽ ポ ま マ み ミ む ム め メ も モ ゃ ャ や ヤ ゅ ュ ゆ ユ ょ ョ よ ヨ ら ラ り リ る ル れ レ ろ ロ ゎ ヮ わ ワ ゐ ヰ ゑ ヱ を ヲ ん ン 一 丁 七 万 万 丈 三 上 下 不 与 且 世 丘 丙 両 並 中 丸 丹 主 久 乏 乗 乙 九 乱 乳 乾 亀 了 予 争 事 二 互 五 井 亜 亡 交 亨 享 享 京 亭 人 仁 今 介 仏 仕 他 付 仙 代 代 令 以 仮 仰 仲 件 任 企 伏 伏 伐 休 会 伝 伯 伴 伸 伺 似 但 位 位 低 住 佐 体 何 余 作 佳 併 使 例 侍 供 依 価 侮 侯 侵 便 係 促 俊 俗 保 信 修 俳 俵 俸 倉 個 倍 倒 候 借 倣 値 倫 倹 偉 偏 停 健 側 側 偵 偶 偽 傍 傑 傘 備 催 債 傷 傾 働 像 僕 僚 僧 儀 億 儒 償 優 元 元 兄 充 兆 先 光 克 免 児 党 入 全 八 八 公 六 共 兵 具 典 兼 内 円 冊 再 冒 冗 写 冠 冬 冷 准 凍 凝 凡 処 凶 凸 凸 凹 出 刀 刃 分 分 切 刈 刊 刑 列 初 判 別 利 到 制 制 刷 券 刺 刻 則 削 前 剖 剛 剣 剤 副 剰 割 創 劇 力 功 加 劣 助 努 励 労 効 劾 勅 勇 勉 動 勘 務 勝 募 勢 勤 勧 勲 勺 匁 包 化 北 匠 匹 匹 区 医 匿 十 千 升 午 半 卑 卑 卒 卓 協 南 単 博 占 印 危 即 即 却 卵 卸 厄 厘 厚 原 厳 去 参 又 及 及 友 双 反 収 叔 取 受 叙 口 口 古 句 叫 召 可 台 史 右 号 司 各 合 吉 同 同 名 后 吏 吐 向 君 吟 否 含 吸 吹 呈 呈 呉 告 周 味 呼 命 和 咲 哀 品 員 哲 唆 唇 唐 唯 唱 商 問 啓 善 喚 喜 喝 喪 喫 営 嗣 嘆 嘉 嘱 器 噴 嚇 囚 四 回 因 団 困 囲 図 固 国 圏 園 土 圧 在 地 坂 均 坊 坑 坪 垂 型 垣 埋 城 域 執 培 基 堀 堂 堅 堕 堤 堪 報 場 塀 塁 塊 塑 塔 塗 塚 塩 塾 境 墓 増 墜 墨 墳 墾 壁 壇 壊 壌 士 壮 声 声 壱 売 変 夏 夕 外 多 夜 夢 大 天 天 太 夫 央 失 奇 奉 奏 契 奔 奥 奨 奪 奮 女 奴 好 如 如 妃 妄 妊 妙 妥 妨 妹 妻 姉 始 姓 委 姫 姻 姿 威 娘 娠 娯 婆 婚 婦 婿 媒 嫁 嫌 嫡 嬢 子 孔 字 存 孝 季 孤 学 孫 宅 宇 宇 守 安 完 宗 宗 官 宙 定 宜 宝 実 客 客 宣 室 宮 宰 害 害 宴 宵 家 容 宿 寂 寄 密 富 寒 寛 寝 察 寡 寧 審 寮 寸 寺 対 寿 封 専 射 将 尉 尉 尊 尋 導 小 少 尚 就 尺 尼 尼 尽 尾 尿 局 居 屈 届 屋 展 属 層 履 屯 山 岐 岩 岬 岳 岸 峠 峡 峰 島 崇 崎 崩 川 州 巡 巣 工 工 左 巧 巨 差 己 巻 市 布 帆 希 帝 帥 師 席 帯 帰 帳 常 帽 幅 幕 幣 干 干 平 年 幸 幹 幻 幻 幼 幽 幾 庁 広 床 序 底 店 府 度 座 庫 庭 庶 庶 康 庸 廃 廉 廊 延 廷 建 弁 弊 式 弐 弓 弓 弔 引 弘 弟 弦 弧 弱 張 強 弾 当 形 彩 彫 彰 影 役 彼 往 征 径 待 律 後 徐 徒 従 得 御 復 循 微 徳 徴 徹 心 必 忌 忍 志 志 忘 忙 応 忠 快 念 怒 怖 思 怠 急 性 怪 恋 恐 恒 恥 恨 恩 恭 息 恵 悔 悟 悠 患 悦 悩 悪 悲 悼 情 惑 惜 惨 惰 想 愁 愉 意 愚 愛 感 慈 態 慌 慎 慕 慢 慣 慨 慮 慰 慶 憂 憎 憤 憩 憲 憶 憾 懇 懐 懲 懸 成 成 我 戒 戦 戯 戸 戻 房 所 扇 扉 手 才 打 払 扱 扶 批 承 技 抄 把 抑 投 抗 折 抜 択 披 抱 抵 抹 押 抽 担 拍 拐 拒 拓 拘 拙 招 拝 拠 拡 括 拷 拾 持 指 挑 挙 挟 振 挿 捕 捜 捨 据 掃 授 掌 排 掘 掛 採 探 接 控 推 措 掲 描 提 揚 換 握 揮 援 揺 損 搬 搭 携 搾 摂 摘 摩 撃 撤 撮 撲 擁 操 擦 擬 支 改 攻 放 政 故 敏 救 敗 教 敢 散 敬 数 整 敵 敷 文 斉 斎 斗 料 斜 斤 斥 断 新 方 施 旅 旋 族 旗 既 日 旧 旧 旨 早 旬 昆 昇 昌 明 易 昔 星 映 春 昨 昭 是 昼 時 晩 普 景 晴 晶 暁 暇 暑 暖 暗 暦 暫 暮 暴 曇 曜 曲 更 書 曹 替 最 月 有 服 朕 朗 望 朝 期 木 未 未 末 本 札 朱 朴 机 朽 杉 材 村 束 条 来 杯 東 松 板 析 林 枚 果 枝 枠 枢 枯 架 柄 某 染 柔 柱 柳 査 栄 栓 校 株 核 根 格 栽 桃 案 桑 桜 桟 梅 械 棄 棋 棒 棚 棟 森 棺 植 検 業 極 楼 楽 概 構 様 槽 標 模 権 横 樹 橋 機 欄 欠 次 欧 欲 欺 款 歌 歓 止 正 武 歩 歯 歳 歴 死 殉 殉 殊 残 殖 殴 段 殺 殻 殿 母 毎 毒 比 毛 氏 民 気 水 氷 永 汁 求 汎 汗 汚 江 池 決 汽 沈 沖 没 沢 河 沸 油 治 沼 沿 況 泉 泊 泌 法 泡 泡 波 泣 泥 注 泰 泳 洋 洗 洞 津 洪 活 派 流 浄 浅 浜 浦 浪 浮 浴 海 浸 消 涙 涯 液 涼 淑 淡 深 混 添 清 渇 渇 済 渉 渋 渓 減 渡 渦 温 測 港 湖 湯 湾 湾 湿 満 源 準 溝 溶 滅 滋 滑 滝 滞 滴 漁 漂 漆 漏 演 漠 漢 漫 漬 漸 潔 潜 潟 潤 潮 澄 激 濁 濃 濫 濯 瀬 火 灯 灰 災 炉 炊 炎 炭 点 為 烈 無 焦 然 焼 煙 照 煩 煮 熟 熱 燃 燥 爆 爵 父 片 版 牙 牛 牧 物 牲 特 犠 犬 犯 状 狂 狩 独 狭 猛 猟 猫 献 猶 猿 獄 獣 獲 玄 率 玉 王 珍 珠 班 現 球 理 琴 環 璽 瓶 甘 甚 生 産 用 田 田 由 甲 申 男 町 画 界 畑 畔 留 畜 畝 略 番 異 畳 疎 疑 疫 疲 疾 病 症 痘 痛 痢 痴 療 癒 癖 発 登 白 百 的 皆 皇 皮 皿 盆 益 盗 盛 盟 監 盤 目 盲 直 相 盾 省 看 県 真 眠 眺 眼 着 睡 督 瞬 矛 矢 知 短 矯 石 砂 研 砕 砲 破 硝 硫 硬 碁 碑 確 磁 磨 礁 礎 示 礼 社 祈 祉 祖 祚 祝 神 祥 票 祭 禁 禄 禅 禍 禍 禎 福 秀 私 秋 科 秒 秘 租 秩 称 移 程 税 稚 種 稲 稼 稿 穀 穂 積 穏 穫 穴 究 空 突 窃 窒 窓 窮 窯 立 竜 章 童 端 競 竹 笑 笛 符 第 筆 等 筋 筒 答 策 箇 算 管 箱 節 範 築 篤 簡 簿 籍 米 粉 粋 粒 粗 粘 粛 粧 精 糖 糧 糸 系 糾 紀 約 紅 紋 納 純 紙 紙 級 紛 素 素 紡 索 紫 累 細 紳 紹 紺 終 組 経 結 絞 絡 給 統 絵 絶 絹 継 続 維 綱 網 綿 緊 総 緑 緒 線 締 編 緩 緯 練 縁 縄 縛 縦 縫 縮 績 繁 繊 織 繕 繭 繰 缶 罪 置 罰 署 罷 羅 羊 美 群 義 羽 翁 翌 習 翻 翼 老 考 者 耐 耕 耗 耳 聖 聞 聴 職 肉 肌 肖 肝 肢 肥 肩 肪 肯 育 肺 胃 胆 背 胎 胞 胴 胸 能 脂 脅 脈 脚 脱 脳 脹 腐 腕 腰 腸 腹 膚 膜 膨 臓 臣 臨 自 臭 至 致 興 舌 舎 舗 舞 舟 航 般 舶 船 艇 艦 良 色 芋 芝 花 芳 芸 芽 苗 若 苦 英 茂 茎 茶 草 荒 荘 荷 菊 菌 菓 菜 華 落 葉 著 葬 蒸 蓄 蔵 薄 薦 薪 薪 薫 薬 藩 藻 虐 虚 虜 虞 虫 蚊 蚕 蛇 蛍 蛮 融 血 衆 行 術 街 衛 衝 衡 衣 表 衰 衷 袋 被 裁 裂 装 裏 裕 補 裸 製 複 褐 褒 襟 襲 西 要 覆 覇 見 規 視 覚 覧 親 観 角 解 触 言 訂 計 討 訓 託 記 訟 訪 設 許 訳 訴 診 証 詐 詔 評 詞 詠 試 詩 詰 詰 話 該 詳 誇 誉 誌 認 誓 誕 誘 語 誠 誤 説 読 課 調 談 請 論 諭 諮 諸 諾 謀 謁 謄 謙 講 謝 謡 謹 識 譜 警 議 譲 護 谷 豆 豊 豚 象 豪 貝 貞 負 負 財 貢 貧 貧 貨 販 貫 責 貯 貴 買 貸 費 貿 賀 賃 賄 資 賊 賓 賛 賜 賞 賠 賢 賦 質 購 贈 赤 赦 走 赴 起 超 越 趣 足 距 跡 路 跳 践 踊 踏 躍 身 車 軌 軍 軒 軟 転 軸 軽 較 載 輝 輩 輪 輸 轄 辛 辞 辱 農 辺 込 迅 迎 近 返 迫 迭 述 迷 追 退 送 逃 逆 透 逐 逓 途 通 逝 速 造 連 逮 週 進 逸 遂 遅 遇 遊 運 遍 過 道 道 達 違 遠 遣 適 遭 遮 遵 遷 選 遺 避 還 邦 邪 邸 郊 郎 郡 部 郭 郵 郷 都 酌 配 酒 酔 酢 酪 酬 酵 酷 酸 醜 醸 釈 里 里 重 野 量 金 針 釣 鈍 鈴 鉄 鉛 鉢 鉱 銀 銃 銅 銑 銘 銭 鋭 鋳 鋼 錘 錠 錬 錯 録 鍛 鎖 鎮 鏡 鐘 鑑 長 門 閉 開 閑 間 関 閣 閥 閲 闘 防 阻 附 降 限 陛 院 院 陣 除 陥 陪 陰 陳 陵 陶 陸 険 陽 隅 隆 隊 階 随 隔 際 障 隠 隣 隷 隻 雄 雄 雅 集 雇 雉 雌 雑 離 難 雨 雪 雰 雲 零 雷 電 需 震 霊 霜 霧 露 青 静 非 面 革 靴 韓 音 韻 響 頂 項 順 預 預 頑 頒 領 頭 頻 頼 題 額 顔 顕 願 類 顧 風 飛 食 飢 飯 飲 飼 飼 飽 飾 養 餓 館 首 香 馬 駄 駄 駅 駆 駐 騎 騒 験 騰 驚 骨 髄 高 髪 鬼 魂 魅 魔 魚 鮮 鯨 鳥 鳴 鶏 麗 麦 麻 黄 黒 黙 鼓 鼻 齢",
+ 3: "兌 拼 楔 錄 鳯",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ },
+ "jmc": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y z",
+ 3: "q x",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "ka": {
+ 0: "ა ბ გ დ ე ვ ზ ჱ თ ი კ ლ მ ნ ჲ ო პ ჟ რ ს ტ ჳ უ ფ ქ ღ ყ შ ჩ ც ძ წ ჭ ხ ჴ ჯ ჰ ჵ ჶ ჷ ჸ ჹ ჺ",
+ 3: "ⴀ ⴁ ⴂ ⴃ ⴄ ⴅ ⴆ ⴡ ⴇ ⴈ ⴉ ⴊ ⴋ ⴌ ⴢ ⴍ ⴎ ⴏ ⴐ ⴑ ⴒ ⴣ ⴓ ⴔ ⴕ ⴖ ⴗ ⴘ ⴙ ⴚ ⴛ ⴜ ⴝ ⴞ ⴤ ⴟ ⴠ ⴥ",
+ 4: "ა ბ გ დ ე ვ ზ თ ი კ ლ მ ნ ო პ ჟ რ ს ტ უ ფ ქ ღ ყ შ ჩ ც ძ წ ჭ ხ ჯ ჰ",
+ 5: "ა ბ გ დ ე ვ ზ თ ი კ ლ მ ნ ო პ ჟ რ ს ტ უ ფ ქ ღ ყ შ ჩ ც ძ წ ჭ ხ ჯ ჰ",
+ },
+ "kab": {
+ 0: "a b c č d ḍ e ɛ f g ǧ ɣ h ḥ i j k l m n p q r ṛ s ṣ t ṭ u w x y z ẓ",
+ 3: "o v",
+ 5: "A B C Č D Ḍ E Ɛ F G Ǧ Ɣ H Ḥ I J K L M N P Q R Ṛ S Ṣ T Ṭ U W X Y Z Ẓ",
+ },
+ "kam": {
+ 0: "a b c d e f g h i ĩ j k l m n o p q r s t u ũ v w y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "kde": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "kea": {
+ 0: "a b d dj e f g i j k l lh m n nh o p r s t tx u v x z",
+ 3: "á à â ã c ç é ê h í ñ ó ô q ú w y",
+ 5: "A B D E F G H I J K L M N O P R S T U V X Z",
+ },
+ "khq": {
+ 0: "a ã b c d e ẽ f g h i j k l m n ɲ ŋ o õ p q r s š t u w x y z ž",
+ 3: "v",
+ 5: "A Ã B C D E Ẽ F G H I J K L M N Ɲ Ŋ O Õ P Q R S Š T U W X Y Z Ž",
+ },
+ "ki": {
+ 0: "a b c d e g h i ĩ j k m n o r t u ũ w y",
+ 3: "f l p q s v x z",
+ 5: "A B C D E G H I J K M N O R T U W Y",
+ },
+ "kk": {
+ 0: "а ә б в г ғ д е ё ж з и й к қ л м н ң о ө п р с т у ұ ү ф х һ ц ч ш щ ъ ы і ь э ю я",
+ 5: "А Ә Б В Г Ғ Д Е Ё Ж З И Й К Қ Л М Н Ң О Ө П Р С Т У Ұ Ү Ф Х Һ Ц Ч Ш Щ Ъ Ы І Ь Э Ю Я",
+ },
+ "kl": {
+ 0: "a á â ã b c d e é ê f g h i í î ĩ j k l m n o ô p q ĸ r s t u ú û ũ v w x y z æ ø å",
+ },
+ "kln": {
+ 0: "a b c d e g h i j k l m n o p r s t u w y",
+ 3: "f q v x z",
+ 5: "A B C D E G H I J K L M N O P R S T U W Y",
+ },
+ "km": {
+ 0: "៌ ៎ ៏ ៑ ័ ៈ ់ ៉ ៊ ៍ ក ខ គ ឃ ង ច ឆ ជ ឈ ញ ដ ឋ ឌ ឍ ណ ត ថ ទ ធ ន ប ផ ព ភ ម យ រ ឫ ឬ ល ឭ ឮ វ ស ហ ឡ អ អា ឥ ឦ ឧ ឧក ឪ ឩ ឯ ឰ ឱ ឲ ឳ ា ិ ី ឹ ឺ ុ ូ ួ ើ ឿ ៀ េ ែ ៃ ោ ៅ ំ ះ ្",
+ 3: "\u17b4 \u17b5 \u200b ឝ ឞ",
+ },
+ "kn": {
+ 0: "಼ ೦ ೧ ೨ ೩ ೪ ೫ ೬ ೭ ೮ ೯ ಅ ಆ ಇ ಈ ಉ ಊ ಋ ೠ ಌ ೡ ಎ ಏ ಐ ಒ ಓ ಔ ಂ ಃ ಕ ಖ ಗ ಘ ಙ ಚ ಛ ಜ ಝ ಞ ಟ ಠ ಡ ಢ ಣ ತ ಥ ದ ಧ ನ ಪ ಫ ಬ ಭ ಮ ಯ ರ ಱ ಲ ವ ಶ ಷ ಸ ಹ ಳ ೞ ಽ ಾ ಿ ೀ ು ೂ ೃ ೄ ೆ ೇ ೈ ೊ ೋ ೌ ್ ೕ ೖ",
+ 4: "ರ ೂ",
+ },
+ "ko": {
+ 0: "가 가 각 갂 갃 간 갅 갆 갇 갈 갉 갊 갋 갌 갍 갎 갏 감 갑 값 갓 갔 강 갖 갗 갘 같 갚 갛 개 객 갞 갟 갠 갡 갢 갣 갤 갥 갦 갧 갨 갩 갪 갫 갬 갭 갮 갯 갰 갱 갲 갳 갴 갵 갶 갷 갸 갹 갺 갻 갼 갽 갾 갿 걀 걁 걂 걃 걄 걅 걆 걇 걈 걉 걊 걋 걌 걍 걎 걏 걐 걑 걒 걓 걔 걕 걖 걗 걘 걙 걚 걛 걜 걝 걞 걟 걠 걡 걢 걣 걤 걥 걦 걧 걨 걩 걪 걫 걬 걭 걮 걯 거 걱 걲 걳 건 걵 걶 걷 걸 걹 걺 걻 걼 걽 걾 걿 검 겁 겂 것 겄 겅 겆 겇 겈 겉 겊 겋 게 겍 겎 겏 겐 겑 겒 겓 겔 겕 겖 겗 겘 겙 겚 겛 겜 겝 겞 겟 겠 겡 겢 겣 겤 겥 겦 겧 겨 격 겪 겫 견 겭 겮 겯 결 겱 겲 겳 겴 겵 겶 겷 겸 겹 겺 겻 겼 경 겾 겿 곀 곁 곂 곃 계 곅 곆 곇 곈 곉 곊 곋 곌 곍 곎 곏 곐 곑 곒 곓 곔 곕 곖 곗 곘 곙 곚 곛 곜 곝 곞 곟 고 곡 곢 곣 곤 곥 곦 곧 골 곩 곪 곫 곬 곭 곮 곯 곰 곱 곲 곳 곴 공 곶 곷 곸 곹 곺 곻 과 곽 곾 곿 관 괁 괂 괃 괄 괅 괆 괇 괈 괉 괊 괋 괌 괍 괎 괏 괐 광 괒 괓 괔 괕 괖 괗 괘 괙 괚 괛 괜 괝 괞 괟 괠 괡 괢 괣 괤 괥 괦 괧 괨 괩 괪 괫 괬 괭 괮 괯 괰 괱 괲 괳 괴 괵 괶 괷 괸 괹 괺 괻 괼 괽 괾 괿 굀 굁 굂 굃 굄 굅 굆 굇 굈 굉 굊 굋 굌 굍 굎 굏 교 굑 굒 굓 굔 굕 굖 굗 굘 굙 굚 굛 굜 굝 굞 굟 굠 굡 굢 굣 굤 굥 굦 굧 굨 굩 굪 굫 구 국 굮 굯 군 굱 굲 굳 굴 굵 굶 굷 굸 굹 굺 굻 굼 굽 굾 굿 궀 궁 궂 궃 궄 궅 궆 궇 궈 궉 궊 궋 권 궍 궎 궏 궐 궑 궒 궓 궔 궕 궖 궗 궘 궙 궚 궛 궜 궝 궞 궟 궠 궡 궢 궣 궤 궥 궦 궧 궨 궩 궪 궫 궬 궭 궮 궯 궰 궱 궲 궳 궴 궵 궶 궷 궸 궹 궺 궻 궼 궽 궾 궿 귀 귁 귂 귃 귄 귅 귆 귇 귈 귉 귊 귋 귌 귍 귎 귏 귐 귑 귒 귓 귔 귕 귖 귗 귘 귙 귚 귛 규 귝 귞 귟 균 귡 귢 귣 귤 귥 귦 귧 귨 귩 귪 귫 귬 귭 귮 귯 귰 귱 귲 귳 귴 귵 귶 귷 그 극 귺 귻 근 귽 귾 귿 글 긁 긂 긃 긄 긅 긆 긇 금 급 긊 긋 긌 긍 긎 긏 긐 긑 긒 긓 긔 긕 긖 긗 긘 긙 긚 긛 긜 긝 긞 긟 긠 긡 긢 긣 긤 긥 긦 긧 긨 긩 긪 긫 긬 긭 긮 긯 기 긱 긲 긳 긴 긵 긶 긷 길 긹 긺 긻 긼 긽 긾 긿 김 깁 깂 깃 깄 깅 깆 깇 깈 깉 깊 깋 까 깍 깎 깏 깐 깑 깒 깓 깔 깕 깖 깗 깘 깙 깚 깛 깜 깝 깞 깟 깠 깡 깢 깣 깤 깥 깦 깧 깨 깩 깪 깫 깬 깭 깮 깯 깰 깱 깲 깳 깴 깵 깶 깷 깸 깹 깺 깻 깼 깽 깾 깿 꺀 꺁 꺂 꺃 꺄 꺅 꺆 꺇 꺈 꺉 꺊 꺋 꺌 꺍 꺎 꺏 꺐 꺑 꺒 꺓 꺔 꺕 꺖 꺗 꺘 꺙 꺚 꺛 꺜 꺝 꺞 꺟 꺠 꺡 꺢 꺣 꺤 꺥 꺦 꺧 꺨 꺩 꺪 꺫 꺬 꺭 꺮 꺯 꺰 꺱 꺲 꺳 꺴 꺵 꺶 꺷 꺸 꺹 꺺 꺻 꺼 꺽 꺾 꺿 껀 껁 껂 껃 껄 껅 껆 껇 껈 껉 껊 껋 껌 껍 껎 껏 껐 껑 껒 껓 껔 껕 껖 껗 께 껙 껚 껛 껜 껝 껞 껟 껠 껡 껢 껣 껤 껥 껦 껧 껨 껩 껪 껫 껬 껭 껮 껯 껰 껱 껲 껳 껴 껵 껶 껷 껸 껹 껺 껻 껼 껽 껾 껿 꼀 꼁 꼂 꼃 꼄 꼅 꼆 꼇 꼈 꼉 꼊 꼋 꼌 꼍 꼎 꼏 꼐 꼑 꼒 꼓 꼔 꼕 꼖 꼗 꼘 꼙 꼚 꼛 꼜 꼝 꼞 꼟 꼠 꼡 꼢 꼣 꼤 꼥 꼦 꼧 꼨 꼩 꼪 꼫 꼬 꼭 꼮 꼯 꼰 꼱 꼲 꼳 꼴 꼵 꼶 꼷 꼸 꼹 꼺 꼻 꼼 꼽 꼾 꼿 꽀 꽁 꽂 꽃 꽄 꽅 꽆 꽇 꽈 꽉 꽊 꽋 꽌 꽍 꽎 꽏 꽐 꽑 꽒 꽓 꽔 꽕 꽖 꽗 꽘 꽙 꽚 꽛 꽜 꽝 꽞 꽟 꽠 꽡 꽢 꽣 꽤 꽥 꽦 꽧 꽨 꽩 꽪 꽫 꽬 꽭 꽮 꽯 꽰 꽱 꽲 꽳 꽴 꽵 꽶 꽷 꽸 꽹 꽺 꽻 꽼 꽽 꽾 꽿 꾀 꾁 꾂 꾃 꾄 꾅 꾆 꾇 꾈 꾉 꾊 꾋 꾌 꾍 꾎 꾏 꾐 꾑 꾒 꾓 꾔 꾕 꾖 꾗 꾘 꾙 꾚 꾛 꾜 꾝 꾞 꾟 꾠 꾡 꾢 꾣 꾤 꾥 꾦 꾧 꾨 꾩 꾪 꾫 꾬 꾭 꾮 꾯 꾰 꾱 꾲 꾳 꾴 꾵 꾶 꾷 꾸 꾹 꾺 꾻 꾼 꾽 꾾 꾿 꿀 꿁 꿂 꿃 꿄 꿅 꿆 꿇 꿈 꿉 꿊 꿋 꿌 꿍 꿎 꿏 꿐 꿑 꿒 꿓 꿔 꿕 꿖 꿗 꿘 꿙 꿚 꿛 꿜 꿝 꿞 꿟 꿠 꿡 꿢 꿣 꿤 꿥 꿦 꿧 꿨 꿩 꿪 꿫 꿬 꿭 꿮 꿯 꿰 꿱 꿲 꿳 꿴 꿵 꿶 꿷 꿸 꿹 꿺 꿻 꿼 꿽 꿾 꿿 뀀 뀁 뀂 뀃 뀄 뀅 뀆 뀇 뀈 뀉 뀊 뀋 뀌 뀍 뀎 뀏 뀐 뀑 뀒 뀓 뀔 뀕 뀖 뀗 뀘 뀙 뀚 뀛 뀜 뀝 뀞 뀟 뀠 뀡 뀢 뀣 뀤 뀥 뀦 뀧 뀨 뀩 뀪 뀫 뀬 뀭 뀮 뀯 뀰 뀱 뀲 뀳 뀴 뀵 뀶 뀷 뀸 뀹 뀺 뀻 뀼 뀽 뀾 뀿 끀 끁 끂 끃 끄 끅 끆 끇 끈 끉 끊 끋 끌 끍 끎 끏 끐 끑 끒 끓 끔 끕 끖 끗 끘 끙 끚 끛 끜 끝 끞 끟 끠 끡 끢 끣 끤 끥 끦 끧 끨 끩 끪 끫 끬 끭 끮 끯 끰 끱 끲 끳 끴 끵 끶 끷 끸 끹 끺 끻 끼 끽 끾 끿 낀 낁 낂 낃 낄 낅 낆 낇 낈 낉 낊 낋 낌 낍 낎 낏 낐 낑 낒 낓 낔 낕 낖 낗 나 낙 낚 낛 난 낝 낞 낟 날 낡 낢 낣 낤 낥 낦 낧 남 납 낪 낫 났 낭 낮 낯 낰 낱 낲 낳 내 낵 낶 낷 낸 낹 낺 낻 낼 낽 낾 낿 냀 냁 냂 냃 냄 냅 냆 냇 냈 냉 냊 냋 냌 냍 냎 냏 냐 냑 냒 냓 냔 냕 냖 냗 냘 냙 냚 냛 냜 냝 냞 냟 냠 냡 냢 냣 냤 냥 냦 냧 냨 냩 냪 냫 냬 냭 냮 냯 냰 냱 냲 냳 냴 냵 냶 냷 냸 냹 냺 냻 냼 냽 냾 냿 넀 넁 넂 넃 넄 넅 넆 넇 너 넉 넊 넋 넌 넍 넎 넏 널 넑 넒 넓 넔 넕 넖 넗 넘 넙 넚 넛 넜 넝 넞 넟 넠 넡 넢 넣 네 넥 넦 넧 넨 넩 넪 넫 넬 넭 넮 넯 넰 넱 넲 넳 넴 넵 넶 넷 넸 넹 넺 넻 넼 넽 넾 넿 녀 녁 녂 녃 년 녅 녆 녇 녈 녉 녊 녋 녌 녍 녎 녏 념 녑 녒 녓 녔 녕 녖 녗 녘 녙 녚 녛 녜 녝 녞 녟 녠 녡 녢 녣 녤 녥 녦 녧 녨 녩 녪 녫 녬 녭 녮 녯 녰 녱 녲 녳 녴 녵 녶 녷 노 녹 녺 녻 논 녽 녾 녿 놀 놁 놂 놃 놄 놅 놆 놇 놈 놉 놊 놋 놌 농 놎 놏 놐 놑 높 놓 놔 놕 놖 놗 놘 놙 놚 놛 놜 놝 놞 놟 놠 놡 놢 놣 놤 놥 놦 놧 놨 놩 놪 놫 놬 놭 놮 놯 놰 놱 놲 놳 놴 놵 놶 놷 놸 놹 놺 놻 놼 놽 놾 놿 뇀 뇁 뇂 뇃 뇄 뇅 뇆 뇇 뇈 뇉 뇊 뇋 뇌 뇍 뇎 뇏 뇐 뇑 뇒 뇓 뇔 뇕 뇖 뇗 뇘 뇙 뇚 뇛 뇜 뇝 뇞 뇟 뇠 뇡 뇢 뇣 뇤 뇥 뇦 뇧 뇨 뇩 뇪 뇫 뇬 뇭 뇮 뇯 뇰 뇱 뇲 뇳 뇴 뇵 뇶 뇷 뇸 뇹 뇺 뇻 뇼 뇽 뇾 뇿 눀 눁 눂 눃 누 눅 눆 눇 눈 눉 눊 눋 눌 눍 눎 눏 눐 눑 눒 눓 눔 눕 눖 눗 눘 눙 눚 눛 눜 눝 눞 눟 눠 눡 눢 눣 눤 눥 눦 눧 눨 눩 눪 눫 눬 눭 눮 눯 눰 눱 눲 눳 눴 눵 눶 눷 눸 눹 눺 눻 눼 눽 눾 눿 뉀 뉁 뉂 뉃 뉄 뉅 뉆 뉇 뉈 뉉 뉊 뉋 뉌 뉍 뉎 뉏 뉐 뉑 뉒 뉓 뉔 뉕 뉖 뉗 뉘 뉙 뉚 뉛 뉜 뉝 뉞 뉟 뉠 뉡 뉢 뉣 뉤 뉥 뉦 뉧 뉨 뉩 뉪 뉫 뉬 뉭 뉮 뉯 뉰 뉱 뉲 뉳 뉴 뉵 뉶 뉷 뉸 뉹 뉺 뉻 뉼 뉽 뉾 뉿 늀 늁 늂 늃 늄 늅 늆 늇 늈 늉 늊 늋 늌 늍 늎 늏 느 늑 늒 늓 는 늕 늖 늗 늘 늙 늚 늛 늜 늝 늞 늟 늠 늡 늢 늣 늤 능 늦 늧 늨 늩 늪 늫 늬 늭 늮 늯 늰 늱 늲 늳 늴 늵 늶 늷 늸 늹 늺 늻 늼 늽 늾 늿 닀 닁 닂 닃 닄 닅 닆 닇 니 닉 닊 닋 닌 닍 닎 닏 닐 닑 닒 닓 닔 닕 닖 닗 님 닙 닚 닛 닜 닝 닞 닟 닠 닡 닢 닣 다 닥 닦 닧 단 닩 닪 닫 달 닭 닮 닯 닰 닱 닲 닳 담 답 닶 닷 닸 당 닺 닻 닼 닽 닾 닿 대 댁 댂 댃 댄 댅 댆 댇 댈 댉 댊 댋 댌 댍 댎 댏 댐 댑 댒 댓 댔 댕 댖 댗 댘 댙 댚 댛 댜 댝 댞 댟 댠 댡 댢 댣 댤 댥 댦 댧 댨 댩 댪 댫 댬 댭 댮 댯 댰 댱 댲 댳 댴 댵 댶 댷 댸 댹 댺 댻 댼 댽 댾 댿 덀 덁 덂 덃 덄 덅 덆 덇 덈 덉 덊 덋 덌 덍 덎 덏 덐 덑 덒 덓 더 덕 덖 덗 던 덙 덚 덛 덜 덝 덞 덟 덠 덡 덢 덣 덤 덥 덦 덧 덨 덩 덪 덫 덬 덭 덮 덯 데 덱 덲 덳 덴 덵 덶 덷 델 덹 덺 덻 덼 덽 덾 덿 뎀 뎁 뎂 뎃 뎄 뎅 뎆 뎇 뎈 뎉 뎊 뎋 뎌 뎍 뎎 뎏 뎐 뎑 뎒 뎓 뎔 뎕 뎖 뎗 뎘 뎙 뎚 뎛 뎜 뎝 뎞 뎟 뎠 뎡 뎢 뎣 뎤 뎥 뎦 뎧 뎨 뎩 뎪 뎫 뎬 뎭 뎮 뎯 뎰 뎱 뎲 뎳 뎴 뎵 뎶 뎷 뎸 뎹 뎺 뎻 뎼 뎽 뎾 뎿 돀 돁 돂 돃 도 독 돆 돇 돈 돉 돊 돋 돌 돍 돎 돏 돐 돑 돒 돓 돔 돕 돖 돗 돘 동 돚 돛 돜 돝 돞 돟 돠 돡 돢 돣 돤 돥 돦 돧 돨 돩 돪 돫 돬 돭 돮 돯 돰 돱 돲 돳 돴 돵 돶 돷 돸 돹 돺 돻 돼 돽 돾 돿 됀 됁 됂 됃 됄 됅 됆 됇 됈 됉 됊 됋 됌 됍 됎 됏 됐 됑 됒 됓 됔 됕 됖 됗 되 됙 됚 됛 된 됝 됞 됟 될 됡 됢 됣 됤 됥 됦 됧 됨 됩 됪 됫 됬 됭 됮 됯 됰 됱 됲 됳 됴 됵 됶 됷 됸 됹 됺 됻 됼 됽 됾 됿 둀 둁 둂 둃 둄 둅 둆 둇 둈 둉 둊 둋 둌 둍 둎 둏 두 둑 둒 둓 둔 둕 둖 둗 둘 둙 둚 둛 둜 둝 둞 둟 둠 둡 둢 둣 둤 둥 둦 둧 둨 둩 둪 둫 둬 둭 둮 둯 둰 둱 둲 둳 둴 둵 둶 둷 둸 둹 둺 둻 둼 둽 둾 둿 뒀 뒁 뒂 뒃 뒄 뒅 뒆 뒇 뒈 뒉 뒊 뒋 뒌 뒍 뒎 뒏 뒐 뒑 뒒 뒓 뒔 뒕 뒖 뒗 뒘 뒙 뒚 뒛 뒜 뒝 뒞 뒟 뒠 뒡 뒢 뒣 뒤 뒥 뒦 뒧 뒨 뒩 뒪 뒫 뒬 뒭 뒮 뒯 뒰 뒱 뒲 뒳 뒴 뒵 뒶 뒷 뒸 뒹 뒺 뒻 뒼 뒽 뒾 뒿 듀 듁 듂 듃 듄 듅 듆 듇 듈 듉 듊 듋 듌 듍 듎 듏 듐 듑 듒 듓 듔 듕 듖 듗 듘 듙 듚 듛 드 득 듞 듟 든 듡 듢 듣 들 듥 듦 듧 듨 듩 듪 듫 듬 듭 듮 듯 듰 등 듲 듳 듴 듵 듶 듷 듸 듹 듺 듻 듼 듽 듾 듿 딀 딁 딂 딃 딄 딅 딆 딇 딈 딉 딊 딋 딌 딍 딎 딏 딐 딑 딒 딓 디 딕 딖 딗 딘 딙 딚 딛 딜 딝 딞 딟 딠 딡 딢 딣 딤 딥 딦 딧 딨 딩 딪 딫 딬 딭 딮 딯 따 딱 딲 딳 딴 딵 딶 딷 딸 딹 딺 딻 딼 딽 딾 딿 땀 땁 땂 땃 땄 땅 땆 땇 땈 땉 땊 땋 때 땍 땎 땏 땐 땑 땒 땓 땔 땕 땖 땗 땘 땙 땚 땛 땜 땝 땞 땟 땠 땡 땢 땣 땤 땥 땦 땧 땨 땩 땪 땫 땬 땭 땮 땯 땰 땱 땲 땳 땴 땵 땶 땷 땸 땹 땺 땻 땼 땽 땾 땿 떀 떁 떂 떃 떄 떅 떆 떇 떈 떉 떊 떋 떌 떍 떎 떏 떐 떑 떒 떓 떔 떕 떖 떗 떘 떙 떚 떛 떜 떝 떞 떟 떠 떡 떢 떣 떤 떥 떦 떧 떨 떩 떪 떫 떬 떭 떮 떯 떰 떱 떲 떳 떴 떵 떶 떷 떸 떹 떺 떻 떼 떽 떾 떿 뗀 뗁 뗂 뗃 뗄 뗅 뗆 뗇 뗈 뗉 뗊 뗋 뗌 뗍 뗎 뗏 뗐 뗑 뗒 뗓 뗔 뗕 뗖 뗗 뗘 뗙 뗚 뗛 뗜 뗝 뗞 뗟 뗠 뗡 뗢 뗣 뗤 뗥 뗦 뗧 뗨 뗩 뗪 뗫 뗬 뗭 뗮 뗯 뗰 뗱 뗲 뗳 뗴 뗵 뗶 뗷 뗸 뗹 뗺 뗻 뗼 뗽 뗾 뗿 똀 똁 똂 똃 똄 똅 똆 똇 똈 똉 똊 똋 똌 똍 똎 똏 또 똑 똒 똓 똔 똕 똖 똗 똘 똙 똚 똛 똜 똝 똞 똟 똠 똡 똢 똣 똤 똥 똦 똧 똨 똩 똪 똫 똬 똭 똮 똯 똰 똱 똲 똳 똴 똵 똶 똷 똸 똹 똺 똻 똼 똽 똾 똿 뙀 뙁 뙂 뙃 뙄 뙅 뙆 뙇 뙈 뙉 뙊 뙋 뙌 뙍 뙎 뙏 뙐 뙑 뙒 뙓 뙔 뙕 뙖 뙗 뙘 뙙 뙚 뙛 뙜 뙝 뙞 뙟 뙠 뙡 뙢 뙣 뙤 뙥 뙦 뙧 뙨 뙩 뙪 뙫 뙬 뙭 뙮 뙯 뙰 뙱 뙲 뙳 뙴 뙵 뙶 뙷 뙸 뙹 뙺 뙻 뙼 뙽 뙾 뙿 뚀 뚁 뚂 뚃 뚄 뚅 뚆 뚇 뚈 뚉 뚊 뚋 뚌 뚍 뚎 뚏 뚐 뚑 뚒 뚓 뚔 뚕 뚖 뚗 뚘 뚙 뚚 뚛 뚜 뚝 뚞 뚟 뚠 뚡 뚢 뚣 뚤 뚥 뚦 뚧 뚨 뚩 뚪 뚫 뚬 뚭 뚮 뚯 뚰 뚱 뚲 뚳 뚴 뚵 뚶 뚷 뚸 뚹 뚺 뚻 뚼 뚽 뚾 뚿 뛀 뛁 뛂 뛃 뛄 뛅 뛆 뛇 뛈 뛉 뛊 뛋 뛌 뛍 뛎 뛏 뛐 뛑 뛒 뛓 뛔 뛕 뛖 뛗 뛘 뛙 뛚 뛛 뛜 뛝 뛞 뛟 뛠 뛡 뛢 뛣 뛤 뛥 뛦 뛧 뛨 뛩 뛪 뛫 뛬 뛭 뛮 뛯 뛰 뛱 뛲 뛳 뛴 뛵 뛶 뛷 뛸 뛹 뛺 뛻 뛼 뛽 뛾 뛿 뜀 뜁 뜂 뜃 뜄 뜅 뜆 뜇 뜈 뜉 뜊 뜋 뜌 뜍 뜎 뜏 뜐 뜑 뜒 뜓 뜔 뜕 뜖 뜗 뜘 뜙 뜚 뜛 뜜 뜝 뜞 뜟 뜠 뜡 뜢 뜣 뜤 뜥 뜦 뜧 뜨 뜩 뜪 뜫 뜬 뜭 뜮 뜯 뜰 뜱 뜲 뜳 뜴 뜵 뜶 뜷 뜸 뜹 뜺 뜻 뜼 뜽 뜾 뜿 띀 띁 띂 띃 띄 띅 띆 띇 띈 띉 띊 띋 띌 띍 띎 띏 띐 띑 띒 띓 띔 띕 띖 띗 띘 띙 띚 띛 띜 띝 띞 띟 띠 띡 띢 띣 띤 띥 띦 띧 띨 띩 띪 띫 띬 띭 띮 띯 띰 띱 띲 띳 띴 띵 띶 띷 띸 띹 띺 띻 라 락 띾 띿 란 랁 랂 랃 랄 랅 랆 랇 랈 랉 랊 랋 람 랍 랎 랏 랐 랑 랒 랓 랔 랕 랖 랗 래 랙 랚 랛 랜 랝 랞 랟 랠 랡 랢 랣 랤 랥 랦 랧 램 랩 랪 랫 랬 랭 랮 랯 랰 랱 랲 랳 랴 략 랶 랷 랸 랹 랺 랻 랼 랽 랾 랿 럀 럁 럂 럃 럄 럅 럆 럇 럈 량 럊 럋 럌 럍 럎 럏 럐 럑 럒 럓 럔 럕 럖 럗 럘 럙 럚 럛 럜 럝 럞 럟 럠 럡 럢 럣 럤 럥 럦 럧 럨 럩 럪 럫 러 럭 럮 럯 런 럱 럲 럳 럴 럵 럶 럷 럸 럹 럺 럻 럼 럽 럾 럿 렀 렁 렂 렃 렄 렅 렆 렇 레 렉 렊 렋 렌 렍 렎 렏 렐 렑 렒 렓 렔 렕 렖 렗 렘 렙 렚 렛 렜 렝 렞 렟 렠 렡 렢 렣 려 력 렦 렧 련 렩 렪 렫 렬 렭 렮 렯 렰 렱 렲 렳 렴 렵 렶 렷 렸 령 렺 렻 렼 렽 렾 렿 례 롁 롂 롃 롄 롅 롆 롇 롈 롉 롊 롋 롌 롍 롎 롏 롐 롑 롒 롓 롔 롕 롖 롗 롘 롙 롚 롛 로 록 롞 롟 론 롡 롢 롣 롤 롥 롦 롧 롨 롩 롪 롫 롬 롭 롮 롯 롰 롱 롲 롳 롴 롵 롶 롷 롸 롹 롺 롻 롼 롽 롾 롿 뢀 뢁 뢂 뢃 뢄 뢅 뢆 뢇 뢈 뢉 뢊 뢋 뢌 뢍 뢎 뢏 뢐 뢑 뢒 뢓 뢔 뢕 뢖 뢗 뢘 뢙 뢚 뢛 뢜 뢝 뢞 뢟 뢠 뢡 뢢 뢣 뢤 뢥 뢦 뢧 뢨 뢩 뢪 뢫 뢬 뢭 뢮 뢯 뢰 뢱 뢲 뢳 뢴 뢵 뢶 뢷 뢸 뢹 뢺 뢻 뢼 뢽 뢾 뢿 룀 룁 룂 룃 룄 룅 룆 룇 룈 룉 룊 룋 료 룍 룎 룏 룐 룑 룒 룓 룔 룕 룖 룗 룘 룙 룚 룛 룜 룝 룞 룟 룠 룡 룢 룣 룤 룥 룦 룧 루 룩 룪 룫 룬 룭 룮 룯 룰 룱 룲 룳 룴 룵 룶 룷 룸 룹 룺 룻 룼 룽 룾 룿 뤀 뤁 뤂 뤃 뤄 뤅 뤆 뤇 뤈 뤉 뤊 뤋 뤌 뤍 뤎 뤏 뤐 뤑 뤒 뤓 뤔 뤕 뤖 뤗 뤘 뤙 뤚 뤛 뤜 뤝 뤞 뤟 뤠 뤡 뤢 뤣 뤤 뤥 뤦 뤧 뤨 뤩 뤪 뤫 뤬 뤭 뤮 뤯 뤰 뤱 뤲 뤳 뤴 뤵 뤶 뤷 뤸 뤹 뤺 뤻 뤼 뤽 뤾 뤿 륀 륁 륂 륃 륄 륅 륆 륇 륈 륉 륊 륋 륌 륍 륎 륏 륐 륑 륒 륓 륔 륕 륖 륗 류 륙 륚 륛 륜 륝 륞 륟 률 륡 륢 륣 륤 륥 륦 륧 륨 륩 륪 륫 륬 륭 륮 륯 륰 륱 륲 륳 르 륵 륶 륷 른 륹 륺 륻 를 륽 륾 륿 릀 릁 릂 릃 름 릅 릆 릇 릈 릉 릊 릋 릌 릍 릎 릏 릐 릑 릒 릓 릔 릕 릖 릗 릘 릙 릚 릛 릜 릝 릞 릟 릠 릡 릢 릣 릤 릥 릦 릧 릨 릩 릪 릫 리 릭 릮 릯 린 릱 릲 릳 릴 릵 릶 릷 릸 릹 릺 릻 림 립 릾 릿 맀 링 맂 맃 맄 맅 맆 맇 마 막 맊 맋 만 맍 많 맏 말 맑 맒 맓 맔 맕 맖 맗 맘 맙 맚 맛 맜 망 맞 맟 맠 맡 맢 맣 매 맥 맦 맧 맨 맩 맪 맫 맬 맭 맮 맯 맰 맱 맲 맳 맴 맵 맶 맷 맸 맹 맺 맻 맼 맽 맾 맿 먀 먁 먂 먃 먄 먅 먆 먇 먈 먉 먊 먋 먌 먍 먎 먏 먐 먑 먒 먓 먔 먕 먖 먗 먘 먙 먚 먛 먜 먝 먞 먟 먠 먡 먢 먣 먤 먥 먦 먧 먨 먩 먪 먫 먬 먭 먮 먯 먰 먱 먲 먳 먴 먵 먶 먷 머 먹 먺 먻 먼 먽 먾 먿 멀 멁 멂 멃 멄 멅 멆 멇 멈 멉 멊 멋 멌 멍 멎 멏 멐 멑 멒 멓 메 멕 멖 멗 멘 멙 멚 멛 멜 멝 멞 멟 멠 멡 멢 멣 멤 멥 멦 멧 멨 멩 멪 멫 멬 멭 멮 멯 며 멱 멲 멳 면 멵 멶 멷 멸 멹 멺 멻 멼 멽 멾 멿 몀 몁 몂 몃 몄 명 몆 몇 몈 몉 몊 몋 몌 몍 몎 몏 몐 몑 몒 몓 몔 몕 몖 몗 몘 몙 몚 몛 몜 몝 몞 몟 몠 몡 몢 몣 몤 몥 몦 몧 모 목 몪 몫 몬 몭 몮 몯 몰 몱 몲 몳 몴 몵 몶 몷 몸 몹 몺 못 몼 몽 몾 몿 뫀 뫁 뫂 뫃 뫄 뫅 뫆 뫇 뫈 뫉 뫊 뫋 뫌 뫍 뫎 뫏 뫐 뫑 뫒 뫓 뫔 뫕 뫖 뫗 뫘 뫙 뫚 뫛 뫜 뫝 뫞 뫟 뫠 뫡 뫢 뫣 뫤 뫥 뫦 뫧 뫨 뫩 뫪 뫫 뫬 뫭 뫮 뫯 뫰 뫱 뫲 뫳 뫴 뫵 뫶 뫷 뫸 뫹 뫺 뫻 뫼 뫽 뫾 뫿 묀 묁 묂 묃 묄 묅 묆 묇 묈 묉 묊 묋 묌 묍 묎 묏 묐 묑 묒 묓 묔 묕 묖 묗 묘 묙 묚 묛 묜 묝 묞 묟 묠 묡 묢 묣 묤 묥 묦 묧 묨 묩 묪 묫 묬 묭 묮 묯 묰 묱 묲 묳 무 묵 묶 묷 문 묹 묺 묻 물 묽 묾 묿 뭀 뭁 뭂 뭃 뭄 뭅 뭆 뭇 뭈 뭉 뭊 뭋 뭌 뭍 뭎 뭏 뭐 뭑 뭒 뭓 뭔 뭕 뭖 뭗 뭘 뭙 뭚 뭛 뭜 뭝 뭞 뭟 뭠 뭡 뭢 뭣 뭤 뭥 뭦 뭧 뭨 뭩 뭪 뭫 뭬 뭭 뭮 뭯 뭰 뭱 뭲 뭳 뭴 뭵 뭶 뭷 뭸 뭹 뭺 뭻 뭼 뭽 뭾 뭿 뮀 뮁 뮂 뮃 뮄 뮅 뮆 뮇 뮈 뮉 뮊 뮋 뮌 뮍 뮎 뮏 뮐 뮑 뮒 뮓 뮔 뮕 뮖 뮗 뮘 뮙 뮚 뮛 뮜 뮝 뮞 뮟 뮠 뮡 뮢 뮣 뮤 뮥 뮦 뮧 뮨 뮩 뮪 뮫 뮬 뮭 뮮 뮯 뮰 뮱 뮲 뮳 뮴 뮵 뮶 뮷 뮸 뮹 뮺 뮻 뮼 뮽 뮾 뮿 므 믁 믂 믃 믄 믅 믆 믇 믈 믉 믊 믋 믌 믍 믎 믏 믐 믑 믒 믓 믔 믕 믖 믗 믘 믙 믚 믛 믜 믝 믞 믟 믠 믡 믢 믣 믤 믥 믦 믧 믨 믩 믪 믫 믬 믭 믮 믯 믰 믱 믲 믳 믴 믵 믶 믷 미 믹 믺 믻 민 믽 믾 믿 밀 밁 밂 밃 밄 밅 밆 밇 밈 밉 밊 밋 밌 밍 밎 및 밐 밑 밒 밓 바 박 밖 밗 반 밙 밚 받 발 밝 밞 밟 밠 밡 밢 밣 밤 밥 밦 밧 밨 방 밪 밫 밬 밭 밮 밯 배 백 밲 밳 밴 밵 밶 밷 밸 밹 밺 밻 밼 밽 밾 밿 뱀 뱁 뱂 뱃 뱄 뱅 뱆 뱇 뱈 뱉 뱊 뱋 뱌 뱍 뱎 뱏 뱐 뱑 뱒 뱓 뱔 뱕 뱖 뱗 뱘 뱙 뱚 뱛 뱜 뱝 뱞 뱟 뱠 뱡 뱢 뱣 뱤 뱥 뱦 뱧 뱨 뱩 뱪 뱫 뱬 뱭 뱮 뱯 뱰 뱱 뱲 뱳 뱴 뱵 뱶 뱷 뱸 뱹 뱺 뱻 뱼 뱽 뱾 뱿 벀 벁 벂 벃 버 벅 벆 벇 번 벉 벊 벋 벌 벍 벎 벏 벐 벑 벒 벓 범 법 벖 벗 벘 벙 벚 벛 벜 벝 벞 벟 베 벡 벢 벣 벤 벥 벦 벧 벨 벩 벪 벫 벬 벭 벮 벯 벰 벱 벲 벳 벴 벵 벶 벷 벸 벹 벺 벻 벼 벽 벾 벿 변 볁 볂 볃 별 볅 볆 볇 볈 볉 볊 볋 볌 볍 볎 볏 볐 병 볒 볓 볔 볕 볖 볗 볘 볙 볚 볛 볜 볝 볞 볟 볠 볡 볢 볣 볤 볥 볦 볧 볨 볩 볪 볫 볬 볭 볮 볯 볰 볱 볲 볳 보 복 볶 볷 본 볹 볺 볻 볼 볽 볾 볿 봀 봁 봂 봃 봄 봅 봆 봇 봈 봉 봊 봋 봌 봍 봎 봏 봐 봑 봒 봓 봔 봕 봖 봗 봘 봙 봚 봛 봜 봝 봞 봟 봠 봡 봢 봣 봤 봥 봦 봧 봨 봩 봪 봫 봬 봭 봮 봯 봰 봱 봲 봳 봴 봵 봶 봷 봸 봹 봺 봻 봼 봽 봾 봿 뵀 뵁 뵂 뵃 뵄 뵅 뵆 뵇 뵈 뵉 뵊 뵋 뵌 뵍 뵎 뵏 뵐 뵑 뵒 뵓 뵔 뵕 뵖 뵗 뵘 뵙 뵚 뵛 뵜 뵝 뵞 뵟 뵠 뵡 뵢 뵣 뵤 뵥 뵦 뵧 뵨 뵩 뵪 뵫 뵬 뵭 뵮 뵯 뵰 뵱 뵲 뵳 뵴 뵵 뵶 뵷 뵸 뵹 뵺 뵻 뵼 뵽 뵾 뵿 부 북 붂 붃 분 붅 붆 붇 불 붉 붊 붋 붌 붍 붎 붏 붐 붑 붒 붓 붔 붕 붖 붗 붘 붙 붚 붛 붜 붝 붞 붟 붠 붡 붢 붣 붤 붥 붦 붧 붨 붩 붪 붫 붬 붭 붮 붯 붰 붱 붲 붳 붴 붵 붶 붷 붸 붹 붺 붻 붼 붽 붾 붿 뷀 뷁 뷂 뷃 뷄 뷅 뷆 뷇 뷈 뷉 뷊 뷋 뷌 뷍 뷎 뷏 뷐 뷑 뷒 뷓 뷔 뷕 뷖 뷗 뷘 뷙 뷚 뷛 뷜 뷝 뷞 뷟 뷠 뷡 뷢 뷣 뷤 뷥 뷦 뷧 뷨 뷩 뷪 뷫 뷬 뷭 뷮 뷯 뷰 뷱 뷲 뷳 뷴 뷵 뷶 뷷 뷸 뷹 뷺 뷻 뷼 뷽 뷾 뷿 븀 븁 븂 븃 븄 븅 븆 븇 븈 븉 븊 븋 브 븍 븎 븏 븐 븑 븒 븓 블 븕 븖 븗 븘 븙 븚 븛 븜 븝 븞 븟 븠 븡 븢 븣 븤 븥 븦 븧 븨 븩 븪 븫 븬 븭 븮 븯 븰 븱 븲 븳 븴 븵 븶 븷 븸 븹 븺 븻 븼 븽 븾 븿 빀 빁 빂 빃 비 빅 빆 빇 빈 빉 빊 빋 빌 빍 빎 빏 빐 빑 빒 빓 빔 빕 빖 빗 빘 빙 빚 빛 빜 빝 빞 빟 빠 빡 빢 빣 빤 빥 빦 빧 빨 빩 빪 빫 빬 빭 빮 빯 빰 빱 빲 빳 빴 빵 빶 빷 빸 빹 빺 빻 빼 빽 빾 빿 뺀 뺁 뺂 뺃 뺄 뺅 뺆 뺇 뺈 뺉 뺊 뺋 뺌 뺍 뺎 뺏 뺐 뺑 뺒 뺓 뺔 뺕 뺖 뺗 뺘 뺙 뺚 뺛 뺜 뺝 뺞 뺟 뺠 뺡 뺢 뺣 뺤 뺥 뺦 뺧 뺨 뺩 뺪 뺫 뺬 뺭 뺮 뺯 뺰 뺱 뺲 뺳 뺴 뺵 뺶 뺷 뺸 뺹 뺺 뺻 뺼 뺽 뺾 뺿 뻀 뻁 뻂 뻃 뻄 뻅 뻆 뻇 뻈 뻉 뻊 뻋 뻌 뻍 뻎 뻏 뻐 뻑 뻒 뻓 뻔 뻕 뻖 뻗 뻘 뻙 뻚 뻛 뻜 뻝 뻞 뻟 뻠 뻡 뻢 뻣 뻤 뻥 뻦 뻧 뻨 뻩 뻪 뻫 뻬 뻭 뻮 뻯 뻰 뻱 뻲 뻳 뻴 뻵 뻶 뻷 뻸 뻹 뻺 뻻 뻼 뻽 뻾 뻿 뼀 뼁 뼂 뼃 뼄 뼅 뼆 뼇 뼈 뼉 뼊 뼋 뼌 뼍 뼎 뼏 뼐 뼑 뼒 뼓 뼔 뼕 뼖 뼗 뼘 뼙 뼚 뼛 뼜 뼝 뼞 뼟 뼠 뼡 뼢 뼣 뼤 뼥 뼦 뼧 뼨 뼩 뼪 뼫 뼬 뼭 뼮 뼯 뼰 뼱 뼲 뼳 뼴 뼵 뼶 뼷 뼸 뼹 뼺 뼻 뼼 뼽 뼾 뼿 뽀 뽁 뽂 뽃 뽄 뽅 뽆 뽇 뽈 뽉 뽊 뽋 뽌 뽍 뽎 뽏 뽐 뽑 뽒 뽓 뽔 뽕 뽖 뽗 뽘 뽙 뽚 뽛 뽜 뽝 뽞 뽟 뽠 뽡 뽢 뽣 뽤 뽥 뽦 뽧 뽨 뽩 뽪 뽫 뽬 뽭 뽮 뽯 뽰 뽱 뽲 뽳 뽴 뽵 뽶 뽷 뽸 뽹 뽺 뽻 뽼 뽽 뽾 뽿 뾀 뾁 뾂 뾃 뾄 뾅 뾆 뾇 뾈 뾉 뾊 뾋 뾌 뾍 뾎 뾏 뾐 뾑 뾒 뾓 뾔 뾕 뾖 뾗 뾘 뾙 뾚 뾛 뾜 뾝 뾞 뾟 뾠 뾡 뾢 뾣 뾤 뾥 뾦 뾧 뾨 뾩 뾪 뾫 뾬 뾭 뾮 뾯 뾰 뾱 뾲 뾳 뾴 뾵 뾶 뾷 뾸 뾹 뾺 뾻 뾼 뾽 뾾 뾿 뿀 뿁 뿂 뿃 뿄 뿅 뿆 뿇 뿈 뿉 뿊 뿋 뿌 뿍 뿎 뿏 뿐 뿑 뿒 뿓 뿔 뿕 뿖 뿗 뿘 뿙 뿚 뿛 뿜 뿝 뿞 뿟 뿠 뿡 뿢 뿣 뿤 뿥 뿦 뿧 뿨 뿩 뿪 뿫 뿬 뿭 뿮 뿯 뿰 뿱 뿲 뿳 뿴 뿵 뿶 뿷 뿸 뿹 뿺 뿻 뿼 뿽 뿾 뿿 쀀 쀁 쀂 쀃 쀄 쀅 쀆 쀇 쀈 쀉 쀊 쀋 쀌 쀍 쀎 쀏 쀐 쀑 쀒 쀓 쀔 쀕 쀖 쀗 쀘 쀙 쀚 쀛 쀜 쀝 쀞 쀟 쀠 쀡 쀢 쀣 쀤 쀥 쀦 쀧 쀨 쀩 쀪 쀫 쀬 쀭 쀮 쀯 쀰 쀱 쀲 쀳 쀴 쀵 쀶 쀷 쀸 쀹 쀺 쀻 쀼 쀽 쀾 쀿 쁀 쁁 쁂 쁃 쁄 쁅 쁆 쁇 쁈 쁉 쁊 쁋 쁌 쁍 쁎 쁏 쁐 쁑 쁒 쁓 쁔 쁕 쁖 쁗 쁘 쁙 쁚 쁛 쁜 쁝 쁞 쁟 쁠 쁡 쁢 쁣 쁤 쁥 쁦 쁧 쁨 쁩 쁪 쁫 쁬 쁭 쁮 쁯 쁰 쁱 쁲 쁳 쁴 쁵 쁶 쁷 쁸 쁹 쁺 쁻 쁼 쁽 쁾 쁿 삀 삁 삂 삃 삄 삅 삆 삇 삈 삉 삊 삋 삌 삍 삎 삏 삐 삑 삒 삓 삔 삕 삖 삗 삘 삙 삚 삛 삜 삝 삞 삟 삠 삡 삢 삣 삤 삥 삦 삧 삨 삩 삪 삫 사 삭 삮 삯 산 삱 삲 삳 살 삵 삶 삷 삸 삹 삺 삻 삼 삽 삾 삿 샀 상 샂 샃 샄 샅 샆 샇 새 색 샊 샋 샌 샍 샎 샏 샐 샑 샒 샓 샔 샕 샖 샗 샘 샙 샚 샛 샜 생 샞 샟 샠 샡 샢 샣 샤 샥 샦 샧 샨 샩 샪 샫 샬 샭 샮 샯 샰 샱 샲 샳 샴 샵 샶 샷 샸 샹 샺 샻 샼 샽 샾 샿 섀 섁 섂 섃 섄 섅 섆 섇 섈 섉 섊 섋 섌 섍 섎 섏 섐 섑 섒 섓 섔 섕 섖 섗 섘 섙 섚 섛 서 석 섞 섟 선 섡 섢 섣 설 섥 섦 섧 섨 섩 섪 섫 섬 섭 섮 섯 섰 성 섲 섳 섴 섵 섶 섷 세 섹 섺 섻 센 섽 섾 섿 셀 셁 셂 셃 셄 셅 셆 셇 셈 셉 셊 셋 셌 셍 셎 셏 셐 셑 셒 셓 셔 셕 셖 셗 션 셙 셚 셛 셜 셝 셞 셟 셠 셡 셢 셣 셤 셥 셦 셧 셨 셩 셪 셫 셬 셭 셮 셯 셰 셱 셲 셳 셴 셵 셶 셷 셸 셹 셺 셻 셼 셽 셾 셿 솀 솁 솂 솃 솄 솅 솆 솇 솈 솉 솊 솋 소 속 솎 솏 손 솑 솒 솓 솔 솕 솖 솗 솘 솙 솚 솛 솜 솝 솞 솟 솠 송 솢 솣 솤 솥 솦 솧 솨 솩 솪 솫 솬 솭 솮 솯 솰 솱 솲 솳 솴 솵 솶 솷 솸 솹 솺 솻 솼 솽 솾 솿 쇀 쇁 쇂 쇃 쇄 쇅 쇆 쇇 쇈 쇉 쇊 쇋 쇌 쇍 쇎 쇏 쇐 쇑 쇒 쇓 쇔 쇕 쇖 쇗 쇘 쇙 쇚 쇛 쇜 쇝 쇞 쇟 쇠 쇡 쇢 쇣 쇤 쇥 쇦 쇧 쇨 쇩 쇪 쇫 쇬 쇭 쇮 쇯 쇰 쇱 쇲 쇳 쇴 쇵 쇶 쇷 쇸 쇹 쇺 쇻 쇼 쇽 쇾 쇿 숀 숁 숂 숃 숄 숅 숆 숇 숈 숉 숊 숋 숌 숍 숎 숏 숐 숑 숒 숓 숔 숕 숖 숗 수 숙 숚 숛 순 숝 숞 숟 술 숡 숢 숣 숤 숥 숦 숧 숨 숩 숪 숫 숬 숭 숮 숯 숰 숱 숲 숳 숴 숵 숶 숷 숸 숹 숺 숻 숼 숽 숾 숿 쉀 쉁 쉂 쉃 쉄 쉅 쉆 쉇 쉈 쉉 쉊 쉋 쉌 쉍 쉎 쉏 쉐 쉑 쉒 쉓 쉔 쉕 쉖 쉗 쉘 쉙 쉚 쉛 쉜 쉝 쉞 쉟 쉠 쉡 쉢 쉣 쉤 쉥 쉦 쉧 쉨 쉩 쉪 쉫 쉬 쉭 쉮 쉯 쉰 쉱 쉲 쉳 쉴 쉵 쉶 쉷 쉸 쉹 쉺 쉻 쉼 쉽 쉾 쉿 슀 슁 슂 슃 슄 슅 슆 슇 슈 슉 슊 슋 슌 슍 슎 슏 슐 슑 슒 슓 슔 슕 슖 슗 슘 슙 슚 슛 슜 슝 슞 슟 슠 슡 슢 슣 스 슥 슦 슧 슨 슩 슪 슫 슬 슭 슮 슯 슰 슱 슲 슳 슴 습 슶 슷 슸 승 슺 슻 슼 슽 슾 슿 싀 싁 싂 싃 싄 싅 싆 싇 싈 싉 싊 싋 싌 싍 싎 싏 싐 싑 싒 싓 싔 싕 싖 싗 싘 싙 싚 싛 시 식 싞 싟 신 싡 싢 싣 실 싥 싦 싧 싨 싩 싪 싫 심 십 싮 싯 싰 싱 싲 싳 싴 싵 싶 싷 싸 싹 싺 싻 싼 싽 싾 싿 쌀 쌁 쌂 쌃 쌄 쌅 쌆 쌇 쌈 쌉 쌊 쌋 쌌 쌍 쌎 쌏 쌐 쌑 쌒 쌓 쌔 쌕 쌖 쌗 쌘 쌙 쌚 쌛 쌜 쌝 쌞 쌟 쌠 쌡 쌢 쌣 쌤 쌥 쌦 쌧 쌨 쌩 쌪 쌫 쌬 쌭 쌮 쌯 쌰 쌱 쌲 쌳 쌴 쌵 쌶 쌷 쌸 쌹 쌺 쌻 쌼 쌽 쌾 쌿 썀 썁 썂 썃 썄 썅 썆 썇 썈 썉 썊 썋 썌 썍 썎 썏 썐 썑 썒 썓 썔 썕 썖 썗 썘 썙 썚 썛 썜 썝 썞 썟 썠 썡 썢 썣 썤 썥 썦 썧 써 썩 썪 썫 썬 썭 썮 썯 썰 썱 썲 썳 썴 썵 썶 썷 썸 썹 썺 썻 썼 썽 썾 썿 쎀 쎁 쎂 쎃 쎄 쎅 쎆 쎇 쎈 쎉 쎊 쎋 쎌 쎍 쎎 쎏 쎐 쎑 쎒 쎓 쎔 쎕 쎖 쎗 쎘 쎙 쎚 쎛 쎜 쎝 쎞 쎟 쎠 쎡 쎢 쎣 쎤 쎥 쎦 쎧 쎨 쎩 쎪 쎫 쎬 쎭 쎮 쎯 쎰 쎱 쎲 쎳 쎴 쎵 쎶 쎷 쎸 쎹 쎺 쎻 쎼 쎽 쎾 쎿 쏀 쏁 쏂 쏃 쏄 쏅 쏆 쏇 쏈 쏉 쏊 쏋 쏌 쏍 쏎 쏏 쏐 쏑 쏒 쏓 쏔 쏕 쏖 쏗 쏘 쏙 쏚 쏛 쏜 쏝 쏞 쏟 쏠 쏡 쏢 쏣 쏤 쏥 쏦 쏧 쏨 쏩 쏪 쏫 쏬 쏭 쏮 쏯 쏰 쏱 쏲 쏳 쏴 쏵 쏶 쏷 쏸 쏹 쏺 쏻 쏼 쏽 쏾 쏿 쐀 쐁 쐂 쐃 쐄 쐅 쐆 쐇 쐈 쐉 쐊 쐋 쐌 쐍 쐎 쐏 쐐 쐑 쐒 쐓 쐔 쐕 쐖 쐗 쐘 쐙 쐚 쐛 쐜 쐝 쐞 쐟 쐠 쐡 쐢 쐣 쐤 쐥 쐦 쐧 쐨 쐩 쐪 쐫 쐬 쐭 쐮 쐯 쐰 쐱 쐲 쐳 쐴 쐵 쐶 쐷 쐸 쐹 쐺 쐻 쐼 쐽 쐾 쐿 쑀 쑁 쑂 쑃 쑄 쑅 쑆 쑇 쑈 쑉 쑊 쑋 쑌 쑍 쑎 쑏 쑐 쑑 쑒 쑓 쑔 쑕 쑖 쑗 쑘 쑙 쑚 쑛 쑜 쑝 쑞 쑟 쑠 쑡 쑢 쑣 쑤 쑥 쑦 쑧 쑨 쑩 쑪 쑫 쑬 쑭 쑮 쑯 쑰 쑱 쑲 쑳 쑴 쑵 쑶 쑷 쑸 쑹 쑺 쑻 쑼 쑽 쑾 쑿 쒀 쒁 쒂 쒃 쒄 쒅 쒆 쒇 쒈 쒉 쒊 쒋 쒌 쒍 쒎 쒏 쒐 쒑 쒒 쒓 쒔 쒕 쒖 쒗 쒘 쒙 쒚 쒛 쒜 쒝 쒞 쒟 쒠 쒡 쒢 쒣 쒤 쒥 쒦 쒧 쒨 쒩 쒪 쒫 쒬 쒭 쒮 쒯 쒰 쒱 쒲 쒳 쒴 쒵 쒶 쒷 쒸 쒹 쒺 쒻 쒼 쒽 쒾 쒿 쓀 쓁 쓂 쓃 쓄 쓅 쓆 쓇 쓈 쓉 쓊 쓋 쓌 쓍 쓎 쓏 쓐 쓑 쓒 쓓 쓔 쓕 쓖 쓗 쓘 쓙 쓚 쓛 쓜 쓝 쓞 쓟 쓠 쓡 쓢 쓣 쓤 쓥 쓦 쓧 쓨 쓩 쓪 쓫 쓬 쓭 쓮 쓯 쓰 쓱 쓲 쓳 쓴 쓵 쓶 쓷 쓸 쓹 쓺 쓻 쓼 쓽 쓾 쓿 씀 씁 씂 씃 씄 씅 씆 씇 씈 씉 씊 씋 씌 씍 씎 씏 씐 씑 씒 씓 씔 씕 씖 씗 씘 씙 씚 씛 씜 씝 씞 씟 씠 씡 씢 씣 씤 씥 씦 씧 씨 씩 씪 씫 씬 씭 씮 씯 씰 씱 씲 씳 씴 씵 씶 씷 씸 씹 씺 씻 씼 씽 씾 씿 앀 앁 앂 앃 아 악 앆 앇 안 앉 않 앋 알 앍 앎 앏 앐 앑 앒 앓 암 압 앖 앗 았 앙 앚 앛 앜 앝 앞 앟 애 액 앢 앣 앤 앥 앦 앧 앨 앩 앪 앫 앬 앭 앮 앯 앰 앱 앲 앳 앴 앵 앶 앷 앸 앹 앺 앻 야 약 앾 앿 얀 얁 얂 얃 얄 얅 얆 얇 얈 얉 얊 얋 얌 얍 얎 얏 얐 양 얒 얓 얔 얕 얖 얗 얘 얙 얚 얛 얜 얝 얞 얟 얠 얡 얢 얣 얤 얥 얦 얧 얨 얩 얪 얫 얬 얭 얮 얯 얰 얱 얲 얳 어 억 얶 얷 언 얹 얺 얻 얼 얽 얾 얿 엀 엁 엂 엃 엄 업 없 엇 었 엉 엊 엋 엌 엍 엎 엏 에 엑 엒 엓 엔 엕 엖 엗 엘 엙 엚 엛 엜 엝 엞 엟 엠 엡 엢 엣 엤 엥 엦 엧 엨 엩 엪 엫 여 역 엮 엯 연 엱 엲 엳 열 엵 엶 엷 엸 엹 엺 엻 염 엽 엾 엿 였 영 옂 옃 옄 옅 옆 옇 예 옉 옊 옋 옌 옍 옎 옏 옐 옑 옒 옓 옔 옕 옖 옗 옘 옙 옚 옛 옜 옝 옞 옟 옠 옡 옢 옣 오 옥 옦 옧 온 옩 옪 옫 올 옭 옮 옯 옰 옱 옲 옳 옴 옵 옶 옷 옸 옹 옺 옻 옼 옽 옾 옿 와 왁 왂 왃 완 왅 왆 왇 왈 왉 왊 왋 왌 왍 왎 왏 왐 왑 왒 왓 왔 왕 왖 왗 왘 왙 왚 왛 왜 왝 왞 왟 왠 왡 왢 왣 왤 왥 왦 왧 왨 왩 왪 왫 왬 왭 왮 왯 왰 왱 왲 왳 왴 왵 왶 왷 외 왹 왺 왻 왼 왽 왾 왿 욀 욁 욂 욃 욄 욅 욆 욇 욈 욉 욊 욋 욌 욍 욎 욏 욐 욑 욒 욓 요 욕 욖 욗 욘 욙 욚 욛 욜 욝 욞 욟 욠 욡 욢 욣 욤 욥 욦 욧 욨 용 욪 욫 욬 욭 욮 욯 우 욱 욲 욳 운 욵 욶 욷 울 욹 욺 욻 욼 욽 욾 욿 움 웁 웂 웃 웄 웅 웆 웇 웈 웉 웊 웋 워 웍 웎 웏 원 웑 웒 웓 월 웕 웖 웗 웘 웙 웚 웛 웜 웝 웞 웟 웠 웡 웢 웣 웤 웥 웦 웧 웨 웩 웪 웫 웬 웭 웮 웯 웰 웱 웲 웳 웴 웵 웶 웷 웸 웹 웺 웻 웼 웽 웾 웿 윀 윁 윂 윃 위 윅 윆 윇 윈 윉 윊 윋 윌 윍 윎 윏 윐 윑 윒 윓 윔 윕 윖 윗 윘 윙 윚 윛 윜 윝 윞 윟 유 육 윢 윣 윤 윥 윦 윧 율 윩 윪 윫 윬 윭 윮 윯 윰 윱 윲 윳 윴 융 윶 윷 윸 윹 윺 윻 으 윽 윾 윿 은 읁 읂 읃 을 읅 읆 읇 읈 읉 읊 읋 음 읍 읎 읏 읐 응 읒 읓 읔 읕 읖 읗 의 읙 읚 읛 읜 읝 읞 읟 읠 읡 읢 읣 읤 읥 읦 읧 읨 읩 읪 읫 읬 읭 읮 읯 읰 읱 읲 읳 이 익 읶 읷 인 읹 읺 읻 일 읽 읾 읿 잀 잁 잂 잃 임 입 잆 잇 있 잉 잊 잋 잌 잍 잎 잏 자 작 잒 잓 잔 잕 잖 잗 잘 잙 잚 잛 잜 잝 잞 잟 잠 잡 잢 잣 잤 장 잦 잧 잨 잩 잪 잫 재 잭 잮 잯 잰 잱 잲 잳 잴 잵 잶 잷 잸 잹 잺 잻 잼 잽 잾 잿 쟀 쟁 쟂 쟃 쟄 쟅 쟆 쟇 쟈 쟉 쟊 쟋 쟌 쟍 쟎 쟏 쟐 쟑 쟒 쟓 쟔 쟕 쟖 쟗 쟘 쟙 쟚 쟛 쟜 쟝 쟞 쟟 쟠 쟡 쟢 쟣 쟤 쟥 쟦 쟧 쟨 쟩 쟪 쟫 쟬 쟭 쟮 쟯 쟰 쟱 쟲 쟳 쟴 쟵 쟶 쟷 쟸 쟹 쟺 쟻 쟼 쟽 쟾 쟿 저 적 젂 젃 전 젅 젆 젇 절 젉 젊 젋 젌 젍 젎 젏 점 접 젒 젓 젔 정 젖 젗 젘 젙 젚 젛 제 젝 젞 젟 젠 젡 젢 젣 젤 젥 젦 젧 젨 젩 젪 젫 젬 젭 젮 젯 젰 젱 젲 젳 젴 젵 젶 젷 져 젹 젺 젻 젼 젽 젾 젿 졀 졁 졂 졃 졄 졅 졆 졇 졈 졉 졊 졋 졌 졍 졎 졏 졐 졑 졒 졓 졔 졕 졖 졗 졘 졙 졚 졛 졜 졝 졞 졟 졠 졡 졢 졣 졤 졥 졦 졧 졨 졩 졪 졫 졬 졭 졮 졯 조 족 졲 졳 존 졵 졶 졷 졸 졹 졺 졻 졼 졽 졾 졿 좀 좁 좂 좃 좄 종 좆 좇 좈 좉 좊 좋 좌 좍 좎 좏 좐 좑 좒 좓 좔 좕 좖 좗 좘 좙 좚 좛 좜 좝 좞 좟 좠 좡 좢 좣 좤 좥 좦 좧 좨 좩 좪 좫 좬 좭 좮 좯 좰 좱 좲 좳 좴 좵 좶 좷 좸 좹 좺 좻 좼 좽 좾 좿 죀 죁 죂 죃 죄 죅 죆 죇 죈 죉 죊 죋 죌 죍 죎 죏 죐 죑 죒 죓 죔 죕 죖 죗 죘 죙 죚 죛 죜 죝 죞 죟 죠 죡 죢 죣 죤 죥 죦 죧 죨 죩 죪 죫 죬 죭 죮 죯 죰 죱 죲 죳 죴 죵 죶 죷 죸 죹 죺 죻 주 죽 죾 죿 준 줁 줂 줃 줄 줅 줆 줇 줈 줉 줊 줋 줌 줍 줎 줏 줐 중 줒 줓 줔 줕 줖 줗 줘 줙 줚 줛 줜 줝 줞 줟 줠 줡 줢 줣 줤 줥 줦 줧 줨 줩 줪 줫 줬 줭 줮 줯 줰 줱 줲 줳 줴 줵 줶 줷 줸 줹 줺 줻 줼 줽 줾 줿 쥀 쥁 쥂 쥃 쥄 쥅 쥆 쥇 쥈 쥉 쥊 쥋 쥌 쥍 쥎 쥏 쥐 쥑 쥒 쥓 쥔 쥕 쥖 쥗 쥘 쥙 쥚 쥛 쥜 쥝 쥞 쥟 쥠 쥡 쥢 쥣 쥤 쥥 쥦 쥧 쥨 쥩 쥪 쥫 쥬 쥭 쥮 쥯 쥰 쥱 쥲 쥳 쥴 쥵 쥶 쥷 쥸 쥹 쥺 쥻 쥼 쥽 쥾 쥿 즀 즁 즂 즃 즄 즅 즆 즇 즈 즉 즊 즋 즌 즍 즎 즏 즐 즑 즒 즓 즔 즕 즖 즗 즘 즙 즚 즛 즜 증 즞 즟 즠 즡 즢 즣 즤 즥 즦 즧 즨 즩 즪 즫 즬 즭 즮 즯 즰 즱 즲 즳 즴 즵 즶 즷 즸 즹 즺 즻 즼 즽 즾 즿 지 직 짂 짃 진 짅 짆 짇 질 짉 짊 짋 짌 짍 짎 짏 짐 집 짒 짓 짔 징 짖 짗 짘 짙 짚 짛 짜 짝 짞 짟 짠 짡 짢 짣 짤 짥 짦 짧 짨 짩 짪 짫 짬 짭 짮 짯 짰 짱 짲 짳 짴 짵 짶 짷 째 짹 짺 짻 짼 짽 짾 짿 쨀 쨁 쨂 쨃 쨄 쨅 쨆 쨇 쨈 쨉 쨊 쨋 쨌 쨍 쨎 쨏 쨐 쨑 쨒 쨓 쨔 쨕 쨖 쨗 쨘 쨙 쨚 쨛 쨜 쨝 쨞 쨟 쨠 쨡 쨢 쨣 쨤 쨥 쨦 쨧 쨨 쨩 쨪 쨫 쨬 쨭 쨮 쨯 쨰 쨱 쨲 쨳 쨴 쨵 쨶 쨷 쨸 쨹 쨺 쨻 쨼 쨽 쨾 쨿 쩀 쩁 쩂 쩃 쩄 쩅 쩆 쩇 쩈 쩉 쩊 쩋 쩌 쩍 쩎 쩏 쩐 쩑 쩒 쩓 쩔 쩕 쩖 쩗 쩘 쩙 쩚 쩛 쩜 쩝 쩞 쩟 쩠 쩡 쩢 쩣 쩤 쩥 쩦 쩧 쩨 쩩 쩪 쩫 쩬 쩭 쩮 쩯 쩰 쩱 쩲 쩳 쩴 쩵 쩶 쩷 쩸 쩹 쩺 쩻 쩼 쩽 쩾 쩿 쪀 쪁 쪂 쪃 쪄 쪅 쪆 쪇 쪈 쪉 쪊 쪋 쪌 쪍 쪎 쪏 쪐 쪑 쪒 쪓 쪔 쪕 쪖 쪗 쪘 쪙 쪚 쪛 쪜 쪝 쪞 쪟 쪠 쪡 쪢 쪣 쪤 쪥 쪦 쪧 쪨 쪩 쪪 쪫 쪬 쪭 쪮 쪯 쪰 쪱 쪲 쪳 쪴 쪵 쪶 쪷 쪸 쪹 쪺 쪻 쪼 쪽 쪾 쪿 쫀 쫁 쫂 쫃 쫄 쫅 쫆 쫇 쫈 쫉 쫊 쫋 쫌 쫍 쫎 쫏 쫐 쫑 쫒 쫓 쫔 쫕 쫖 쫗 쫘 쫙 쫚 쫛 쫜 쫝 쫞 쫟 쫠 쫡 쫢 쫣 쫤 쫥 쫦 쫧 쫨 쫩 쫪 쫫 쫬 쫭 쫮 쫯 쫰 쫱 쫲 쫳 쫴 쫵 쫶 쫷 쫸 쫹 쫺 쫻 쫼 쫽 쫾 쫿 쬀 쬁 쬂 쬃 쬄 쬅 쬆 쬇 쬈 쬉 쬊 쬋 쬌 쬍 쬎 쬏 쬐 쬑 쬒 쬓 쬔 쬕 쬖 쬗 쬘 쬙 쬚 쬛 쬜 쬝 쬞 쬟 쬠 쬡 쬢 쬣 쬤 쬥 쬦 쬧 쬨 쬩 쬪 쬫 쬬 쬭 쬮 쬯 쬰 쬱 쬲 쬳 쬴 쬵 쬶 쬷 쬸 쬹 쬺 쬻 쬼 쬽 쬾 쬿 쭀 쭁 쭂 쭃 쭄 쭅 쭆 쭇 쭈 쭉 쭊 쭋 쭌 쭍 쭎 쭏 쭐 쭑 쭒 쭓 쭔 쭕 쭖 쭗 쭘 쭙 쭚 쭛 쭜 쭝 쭞 쭟 쭠 쭡 쭢 쭣 쭤 쭥 쭦 쭧 쭨 쭩 쭪 쭫 쭬 쭭 쭮 쭯 쭰 쭱 쭲 쭳 쭴 쭵 쭶 쭷 쭸 쭹 쭺 쭻 쭼 쭽 쭾 쭿 쮀 쮁 쮂 쮃 쮄 쮅 쮆 쮇 쮈 쮉 쮊 쮋 쮌 쮍 쮎 쮏 쮐 쮑 쮒 쮓 쮔 쮕 쮖 쮗 쮘 쮙 쮚 쮛 쮜 쮝 쮞 쮟 쮠 쮡 쮢 쮣 쮤 쮥 쮦 쮧 쮨 쮩 쮪 쮫 쮬 쮭 쮮 쮯 쮰 쮱 쮲 쮳 쮴 쮵 쮶 쮷 쮸 쮹 쮺 쮻 쮼 쮽 쮾 쮿 쯀 쯁 쯂 쯃 쯄 쯅 쯆 쯇 쯈 쯉 쯊 쯋 쯌 쯍 쯎 쯏 쯐 쯑 쯒 쯓 쯔 쯕 쯖 쯗 쯘 쯙 쯚 쯛 쯜 쯝 쯞 쯟 쯠 쯡 쯢 쯣 쯤 쯥 쯦 쯧 쯨 쯩 쯪 쯫 쯬 쯭 쯮 쯯 쯰 쯱 쯲 쯳 쯴 쯵 쯶 쯷 쯸 쯹 쯺 쯻 쯼 쯽 쯾 쯿 찀 찁 찂 찃 찄 찅 찆 찇 찈 찉 찊 찋 찌 찍 찎 찏 찐 찑 찒 찓 찔 찕 찖 찗 찘 찙 찚 찛 찜 찝 찞 찟 찠 찡 찢 찣 찤 찥 찦 찧 차 착 찪 찫 찬 찭 찮 찯 찰 찱 찲 찳 찴 찵 찶 찷 참 찹 찺 찻 찼 창 찾 찿 챀 챁 챂 챃 채 책 챆 챇 챈 챉 챊 챋 챌 챍 챎 챏 챐 챑 챒 챓 챔 챕 챖 챗 챘 챙 챚 챛 챜 챝 챞 챟 챠 챡 챢 챣 챤 챥 챦 챧 챨 챩 챪 챫 챬 챭 챮 챯 챰 챱 챲 챳 챴 챵 챶 챷 챸 챹 챺 챻 챼 챽 챾 챿 첀 첁 첂 첃 첄 첅 첆 첇 첈 첉 첊 첋 첌 첍 첎 첏 첐 첑 첒 첓 첔 첕 첖 첗 처 척 첚 첛 천 첝 첞 첟 철 첡 첢 첣 첤 첥 첦 첧 첨 첩 첪 첫 첬 청 첮 첯 첰 첱 첲 첳 체 첵 첶 첷 첸 첹 첺 첻 첼 첽 첾 첿 쳀 쳁 쳂 쳃 쳄 쳅 쳆 쳇 쳈 쳉 쳊 쳋 쳌 쳍 쳎 쳏 쳐 쳑 쳒 쳓 쳔 쳕 쳖 쳗 쳘 쳙 쳚 쳛 쳜 쳝 쳞 쳟 쳠 쳡 쳢 쳣 쳤 쳥 쳦 쳧 쳨 쳩 쳪 쳫 쳬 쳭 쳮 쳯 쳰 쳱 쳲 쳳 쳴 쳵 쳶 쳷 쳸 쳹 쳺 쳻 쳼 쳽 쳾 쳿 촀 촁 촂 촃 촄 촅 촆 촇 초 촉 촊 촋 촌 촍 촎 촏 촐 촑 촒 촓 촔 촕 촖 촗 촘 촙 촚 촛 촜 총 촞 촟 촠 촡 촢 촣 촤 촥 촦 촧 촨 촩 촪 촫 촬 촭 촮 촯 촰 촱 촲 촳 촴 촵 촶 촷 촸 촹 촺 촻 촼 촽 촾 촿 쵀 쵁 쵂 쵃 쵄 쵅 쵆 쵇 쵈 쵉 쵊 쵋 쵌 쵍 쵎 쵏 쵐 쵑 쵒 쵓 쵔 쵕 쵖 쵗 쵘 쵙 쵚 쵛 최 쵝 쵞 쵟 쵠 쵡 쵢 쵣 쵤 쵥 쵦 쵧 쵨 쵩 쵪 쵫 쵬 쵭 쵮 쵯 쵰 쵱 쵲 쵳 쵴 쵵 쵶 쵷 쵸 쵹 쵺 쵻 쵼 쵽 쵾 쵿 춀 춁 춂 춃 춄 춅 춆 춇 춈 춉 춊 춋 춌 춍 춎 춏 춐 춑 춒 춓 추 축 춖 춗 춘 춙 춚 춛 출 춝 춞 춟 춠 춡 춢 춣 춤 춥 춦 춧 춨 충 춪 춫 춬 춭 춮 춯 춰 춱 춲 춳 춴 춵 춶 춷 춸 춹 춺 춻 춼 춽 춾 춿 췀 췁 췂 췃 췄 췅 췆 췇 췈 췉 췊 췋 췌 췍 췎 췏 췐 췑 췒 췓 췔 췕 췖 췗 췘 췙 췚 췛 췜 췝 췞 췟 췠 췡 췢 췣 췤 췥 췦 췧 취 췩 췪 췫 췬 췭 췮 췯 췰 췱 췲 췳 췴 췵 췶 췷 췸 췹 췺 췻 췼 췽 췾 췿 츀 츁 츂 츃 츄 츅 츆 츇 츈 츉 츊 츋 츌 츍 츎 츏 츐 츑 츒 츓 츔 츕 츖 츗 츘 츙 츚 츛 츜 츝 츞 츟 츠 측 츢 츣 츤 츥 츦 츧 츨 츩 츪 츫 츬 츭 츮 츯 츰 츱 츲 츳 츴 층 츶 츷 츸 츹 츺 츻 츼 츽 츾 츿 칀 칁 칂 칃 칄 칅 칆 칇 칈 칉 칊 칋 칌 칍 칎 칏 칐 칑 칒 칓 칔 칕 칖 칗 치 칙 칚 칛 친 칝 칞 칟 칠 칡 칢 칣 칤 칥 칦 칧 침 칩 칪 칫 칬 칭 칮 칯 칰 칱 칲 칳 카 칵 칶 칷 칸 칹 칺 칻 칼 칽 칾 칿 캀 캁 캂 캃 캄 캅 캆 캇 캈 캉 캊 캋 캌 캍 캎 캏 캐 캑 캒 캓 캔 캕 캖 캗 캘 캙 캚 캛 캜 캝 캞 캟 캠 캡 캢 캣 캤 캥 캦 캧 캨 캩 캪 캫 캬 캭 캮 캯 캰 캱 캲 캳 캴 캵 캶 캷 캸 캹 캺 캻 캼 캽 캾 캿 컀 컁 컂 컃 컄 컅 컆 컇 컈 컉 컊 컋 컌 컍 컎 컏 컐 컑 컒 컓 컔 컕 컖 컗 컘 컙 컚 컛 컜 컝 컞 컟 컠 컡 컢 컣 커 컥 컦 컧 컨 컩 컪 컫 컬 컭 컮 컯 컰 컱 컲 컳 컴 컵 컶 컷 컸 컹 컺 컻 컼 컽 컾 컿 케 켁 켂 켃 켄 켅 켆 켇 켈 켉 켊 켋 켌 켍 켎 켏 켐 켑 켒 켓 켔 켕 켖 켗 켘 켙 켚 켛 켜 켝 켞 켟 켠 켡 켢 켣 켤 켥 켦 켧 켨 켩 켪 켫 켬 켭 켮 켯 켰 켱 켲 켳 켴 켵 켶 켷 켸 켹 켺 켻 켼 켽 켾 켿 콀 콁 콂 콃 콄 콅 콆 콇 콈 콉 콊 콋 콌 콍 콎 콏 콐 콑 콒 콓 코 콕 콖 콗 콘 콙 콚 콛 콜 콝 콞 콟 콠 콡 콢 콣 콤 콥 콦 콧 콨 콩 콪 콫 콬 콭 콮 콯 콰 콱 콲 콳 콴 콵 콶 콷 콸 콹 콺 콻 콼 콽 콾 콿 쾀 쾁 쾂 쾃 쾄 쾅 쾆 쾇 쾈 쾉 쾊 쾋 쾌 쾍 쾎 쾏 쾐 쾑 쾒 쾓 쾔 쾕 쾖 쾗 쾘 쾙 쾚 쾛 쾜 쾝 쾞 쾟 쾠 쾡 쾢 쾣 쾤 쾥 쾦 쾧 쾨 쾩 쾪 쾫 쾬 쾭 쾮 쾯 쾰 쾱 쾲 쾳 쾴 쾵 쾶 쾷 쾸 쾹 쾺 쾻 쾼 쾽 쾾 쾿 쿀 쿁 쿂 쿃 쿄 쿅 쿆 쿇 쿈 쿉 쿊 쿋 쿌 쿍 쿎 쿏 쿐 쿑 쿒 쿓 쿔 쿕 쿖 쿗 쿘 쿙 쿚 쿛 쿜 쿝 쿞 쿟 쿠 쿡 쿢 쿣 쿤 쿥 쿦 쿧 쿨 쿩 쿪 쿫 쿬 쿭 쿮 쿯 쿰 쿱 쿲 쿳 쿴 쿵 쿶 쿷 쿸 쿹 쿺 쿻 쿼 쿽 쿾 쿿 퀀 퀁 퀂 퀃 퀄 퀅 퀆 퀇 퀈 퀉 퀊 퀋 퀌 퀍 퀎 퀏 퀐 퀑 퀒 퀓 퀔 퀕 퀖 퀗 퀘 퀙 퀚 퀛 퀜 퀝 퀞 퀟 퀠 퀡 퀢 퀣 퀤 퀥 퀦 퀧 퀨 퀩 퀪 퀫 퀬 퀭 퀮 퀯 퀰 퀱 퀲 퀳 퀴 퀵 퀶 퀷 퀸 퀹 퀺 퀻 퀼 퀽 퀾 퀿 큀 큁 큂 큃 큄 큅 큆 큇 큈 큉 큊 큋 큌 큍 큎 큏 큐 큑 큒 큓 큔 큕 큖 큗 큘 큙 큚 큛 큜 큝 큞 큟 큠 큡 큢 큣 큤 큥 큦 큧 큨 큩 큪 큫 크 큭 큮 큯 큰 큱 큲 큳 클 큵 큶 큷 큸 큹 큺 큻 큼 큽 큾 큿 킀 킁 킂 킃 킄 킅 킆 킇 킈 킉 킊 킋 킌 킍 킎 킏 킐 킑 킒 킓 킔 킕 킖 킗 킘 킙 킚 킛 킜 킝 킞 킟 킠 킡 킢 킣 키 킥 킦 킧 킨 킩 킪 킫 킬 킭 킮 킯 킰 킱 킲 킳 킴 킵 킶 킷 킸 킹 킺 킻 킼 킽 킾 킿 타 탁 탂 탃 탄 탅 탆 탇 탈 탉 탊 탋 탌 탍 탎 탏 탐 탑 탒 탓 탔 탕 탖 탗 탘 탙 탚 탛 태 택 탞 탟 탠 탡 탢 탣 탤 탥 탦 탧 탨 탩 탪 탫 탬 탭 탮 탯 탰 탱 탲 탳 탴 탵 탶 탷 탸 탹 탺 탻 탼 탽 탾 탿 턀 턁 턂 턃 턄 턅 턆 턇 턈 턉 턊 턋 턌 턍 턎 턏 턐 턑 턒 턓 턔 턕 턖 턗 턘 턙 턚 턛 턜 턝 턞 턟 턠 턡 턢 턣 턤 턥 턦 턧 턨 턩 턪 턫 턬 턭 턮 턯 터 턱 턲 턳 턴 턵 턶 턷 털 턹 턺 턻 턼 턽 턾 턿 텀 텁 텂 텃 텄 텅 텆 텇 텈 텉 텊 텋 테 텍 텎 텏 텐 텑 텒 텓 텔 텕 텖 텗 텘 텙 텚 텛 템 텝 텞 텟 텠 텡 텢 텣 텤 텥 텦 텧 텨 텩 텪 텫 텬 텭 텮 텯 텰 텱 텲 텳 텴 텵 텶 텷 텸 텹 텺 텻 텼 텽 텾 텿 톀 톁 톂 톃 톄 톅 톆 톇 톈 톉 톊 톋 톌 톍 톎 톏 톐 톑 톒 톓 톔 톕 톖 톗 톘 톙 톚 톛 톜 톝 톞 톟 토 톡 톢 톣 톤 톥 톦 톧 톨 톩 톪 톫 톬 톭 톮 톯 톰 톱 톲 톳 톴 통 톶 톷 톸 톹 톺 톻 톼 톽 톾 톿 퇀 퇁 퇂 퇃 퇄 퇅 퇆 퇇 퇈 퇉 퇊 퇋 퇌 퇍 퇎 퇏 퇐 퇑 퇒 퇓 퇔 퇕 퇖 퇗 퇘 퇙 퇚 퇛 퇜 퇝 퇞 퇟 퇠 퇡 퇢 퇣 퇤 퇥 퇦 퇧 퇨 퇩 퇪 퇫 퇬 퇭 퇮 퇯 퇰 퇱 퇲 퇳 퇴 퇵 퇶 퇷 퇸 퇹 퇺 퇻 퇼 퇽 퇾 퇿 툀 툁 툂 툃 툄 툅 툆 툇 툈 툉 툊 툋 툌 툍 툎 툏 툐 툑 툒 툓 툔 툕 툖 툗 툘 툙 툚 툛 툜 툝 툞 툟 툠 툡 툢 툣 툤 툥 툦 툧 툨 툩 툪 툫 투 툭 툮 툯 툰 툱 툲 툳 툴 툵 툶 툷 툸 툹 툺 툻 툼 툽 툾 툿 퉀 퉁 퉂 퉃 퉄 퉅 퉆 퉇 퉈 퉉 퉊 퉋 퉌 퉍 퉎 퉏 퉐 퉑 퉒 퉓 퉔 퉕 퉖 퉗 퉘 퉙 퉚 퉛 퉜 퉝 퉞 퉟 퉠 퉡 퉢 퉣 퉤 퉥 퉦 퉧 퉨 퉩 퉪 퉫 퉬 퉭 퉮 퉯 퉰 퉱 퉲 퉳 퉴 퉵 퉶 퉷 퉸 퉹 퉺 퉻 퉼 퉽 퉾 퉿 튀 튁 튂 튃 튄 튅 튆 튇 튈 튉 튊 튋 튌 튍 튎 튏 튐 튑 튒 튓 튔 튕 튖 튗 튘 튙 튚 튛 튜 튝 튞 튟 튠 튡 튢 튣 튤 튥 튦 튧 튨 튩 튪 튫 튬 튭 튮 튯 튰 튱 튲 튳 튴 튵 튶 튷 트 특 튺 튻 튼 튽 튾 튿 틀 틁 틂 틃 틄 틅 틆 틇 틈 틉 틊 틋 틌 틍 틎 틏 틐 틑 틒 틓 틔 틕 틖 틗 틘 틙 틚 틛 틜 틝 틞 틟 틠 틡 틢 틣 틤 틥 틦 틧 틨 틩 틪 틫 틬 틭 틮 틯 티 틱 틲 틳 틴 틵 틶 틷 틸 틹 틺 틻 틼 틽 틾 틿 팀 팁 팂 팃 팄 팅 팆 팇 팈 팉 팊 팋 파 팍 팎 팏 판 팑 팒 팓 팔 팕 팖 팗 팘 팙 팚 팛 팜 팝 팞 팟 팠 팡 팢 팣 팤 팥 팦 팧 패 팩 팪 팫 팬 팭 팮 팯 팰 팱 팲 팳 팴 팵 팶 팷 팸 팹 팺 팻 팼 팽 팾 팿 퍀 퍁 퍂 퍃 퍄 퍅 퍆 퍇 퍈 퍉 퍊 퍋 퍌 퍍 퍎 퍏 퍐 퍑 퍒 퍓 퍔 퍕 퍖 퍗 퍘 퍙 퍚 퍛 퍜 퍝 퍞 퍟 퍠 퍡 퍢 퍣 퍤 퍥 퍦 퍧 퍨 퍩 퍪 퍫 퍬 퍭 퍮 퍯 퍰 퍱 퍲 퍳 퍴 퍵 퍶 퍷 퍸 퍹 퍺 퍻 퍼 퍽 퍾 퍿 펀 펁 펂 펃 펄 펅 펆 펇 펈 펉 펊 펋 펌 펍 펎 펏 펐 펑 펒 펓 펔 펕 펖 펗 페 펙 펚 펛 펜 펝 펞 펟 펠 펡 펢 펣 펤 펥 펦 펧 펨 펩 펪 펫 펬 펭 펮 펯 펰 펱 펲 펳 펴 펵 펶 펷 편 펹 펺 펻 펼 펽 펾 펿 폀 폁 폂 폃 폄 폅 폆 폇 폈 평 폊 폋 폌 폍 폎 폏 폐 폑 폒 폓 폔 폕 폖 폗 폘 폙 폚 폛 폜 폝 폞 폟 폠 폡 폢 폣 폤 폥 폦 폧 폨 폩 폪 폫 포 폭 폮 폯 폰 폱 폲 폳 폴 폵 폶 폷 폸 폹 폺 폻 폼 폽 폾 폿 퐀 퐁 퐂 퐃 퐄 퐅 퐆 퐇 퐈 퐉 퐊 퐋 퐌 퐍 퐎 퐏 퐐 퐑 퐒 퐓 퐔 퐕 퐖 퐗 퐘 퐙 퐚 퐛 퐜 퐝 퐞 퐟 퐠 퐡 퐢 퐣 퐤 퐥 퐦 퐧 퐨 퐩 퐪 퐫 퐬 퐭 퐮 퐯 퐰 퐱 퐲 퐳 퐴 퐵 퐶 퐷 퐸 퐹 퐺 퐻 퐼 퐽 퐾 퐿 푀 푁 푂 푃 푄 푅 푆 푇 푈 푉 푊 푋 푌 푍 푎 푏 푐 푑 푒 푓 푔 푕 푖 푗 푘 푙 푚 푛 표 푝 푞 푟 푠 푡 푢 푣 푤 푥 푦 푧 푨 푩 푪 푫 푬 푭 푮 푯 푰 푱 푲 푳 푴 푵 푶 푷 푸 푹 푺 푻 푼 푽 푾 푿 풀 풁 풂 풃 풄 풅 풆 풇 품 풉 풊 풋 풌 풍 풎 풏 풐 풑 풒 풓 풔 풕 풖 풗 풘 풙 풚 풛 풜 풝 풞 풟 풠 풡 풢 풣 풤 풥 풦 풧 풨 풩 풪 풫 풬 풭 풮 풯 풰 풱 풲 풳 풴 풵 풶 풷 풸 풹 풺 풻 풼 풽 풾 풿 퓀 퓁 퓂 퓃 퓄 퓅 퓆 퓇 퓈 퓉 퓊 퓋 퓌 퓍 퓎 퓏 퓐 퓑 퓒 퓓 퓔 퓕 퓖 퓗 퓘 퓙 퓚 퓛 퓜 퓝 퓞 퓟 퓠 퓡 퓢 퓣 퓤 퓥 퓦 퓧 퓨 퓩 퓪 퓫 퓬 퓭 퓮 퓯 퓰 퓱 퓲 퓳 퓴 퓵 퓶 퓷 퓸 퓹 퓺 퓻 퓼 퓽 퓾 퓿 픀 픁 픂 픃 프 픅 픆 픇 픈 픉 픊 픋 플 픍 픎 픏 픐 픑 픒 픓 픔 픕 픖 픗 픘 픙 픚 픛 픜 픝 픞 픟 픠 픡 픢 픣 픤 픥 픦 픧 픨 픩 픪 픫 픬 픭 픮 픯 픰 픱 픲 픳 픴 픵 픶 픷 픸 픹 픺 픻 피 픽 픾 픿 핀 핁 핂 핃 필 핅 핆 핇 핈 핉 핊 핋 핌 핍 핎 핏 핐 핑 핒 핓 핔 핕 핖 핗 하 학 핚 핛 한 핝 핞 핟 할 핡 핢 핣 핤 핥 핦 핧 함 합 핪 핫 핬 항 핮 핯 핰 핱 핲 핳 해 핵 핶 핷 핸 핹 핺 핻 핼 핽 핾 핿 햀 햁 햂 햃 햄 햅 햆 햇 했 행 햊 햋 햌 햍 햎 햏 햐 햑 햒 햓 햔 햕 햖 햗 햘 햙 햚 햛 햜 햝 햞 햟 햠 햡 햢 햣 햤 향 햦 햧 햨 햩 햪 햫 햬 햭 햮 햯 햰 햱 햲 햳 햴 햵 햶 햷 햸 햹 햺 햻 햼 햽 햾 햿 헀 헁 헂 헃 헄 헅 헆 헇 허 헉 헊 헋 헌 헍 헎 헏 헐 헑 헒 헓 헔 헕 헖 헗 험 헙 헚 헛 헜 헝 헞 헟 헠 헡 헢 헣 헤 헥 헦 헧 헨 헩 헪 헫 헬 헭 헮 헯 헰 헱 헲 헳 헴 헵 헶 헷 헸 헹 헺 헻 헼 헽 헾 헿 혀 혁 혂 혃 현 혅 혆 혇 혈 혉 혊 혋 혌 혍 혎 혏 혐 협 혒 혓 혔 형 혖 혗 혘 혙 혚 혛 혜 혝 혞 혟 혠 혡 혢 혣 혤 혥 혦 혧 혨 혩 혪 혫 혬 혭 혮 혯 혰 혱 혲 혳 혴 혵 혶 혷 호 혹 혺 혻 혼 혽 혾 혿 홀 홁 홂 홃 홄 홅 홆 홇 홈 홉 홊 홋 홌 홍 홎 홏 홐 홑 홒 홓 화 확 홖 홗 환 홙 홚 홛 활 홝 홞 홟 홠 홡 홢 홣 홤 홥 홦 홧 홨 황 홪 홫 홬 홭 홮 홯 홰 홱 홲 홳 홴 홵 홶 홷 홸 홹 홺 홻 홼 홽 홾 홿 횀 횁 횂 횃 횄 횅 횆 횇 횈 횉 횊 횋 회 획 횎 횏 횐 횑 횒 횓 횔 횕 횖 횗 횘 횙 횚 횛 횜 횝 횞 횟 횠 횡 횢 횣 횤 횥 횦 횧 효 횩 횪 횫 횬 횭 횮 횯 횰 횱 횲 횳 횴 횵 횶 횷 횸 횹 횺 횻 횼 횽 횾 횿 훀 훁 훂 훃 후 훅 훆 훇 훈 훉 훊 훋 훌 훍 훎 훏 훐 훑 훒 훓 훔 훕 훖 훗 훘 훙 훚 훛 훜 훝 훞 훟 훠 훡 훢 훣 훤 훥 훦 훧 훨 훩 훪 훫 훬 훭 훮 훯 훰 훱 훲 훳 훴 훵 훶 훷 훸 훹 훺 훻 훼 훽 훾 훿 휀 휁 휂 휃 휄 휅 휆 휇 휈 휉 휊 휋 휌 휍 휎 휏 휐 휑 휒 휓 휔 휕 휖 휗 휘 휙 휚 휛 휜 휝 휞 휟 휠 휡 휢 휣 휤 휥 휦 휧 휨 휩 휪 휫 휬 휭 휮 휯 휰 휱 휲 휳 휴 휵 휶 휷 휸 휹 휺 휻 휼 휽 휾 휿 흀 흁 흂 흃 흄 흅 흆 흇 흈 흉 흊 흋 흌 흍 흎 흏 흐 흑 흒 흓 흔 흕 흖 흗 흘 흙 흚 흛 흜 흝 흞 흟 흠 흡 흢 흣 흤 흥 흦 흧 흨 흩 흪 흫 희 흭 흮 흯 흰 흱 흲 흳 흴 흵 흶 흷 흸 흹 흺 흻 흼 흽 흾 흿 힀 힁 힂 힃 힄 힅 힆 힇 히 힉 힊 힋 힌 힍 힎 힏 힐 힑 힒 힓 힔 힕 힖 힗 힘 힙 힚 힛 힜 힝 힞 힟 힠 힡 힢 힣",
+ 3: "丘 串 乃 久 乖 九 乞 乫 乾 亂 亘 交 京 仇 今 介 件 价 企 伋 伎 伽 佳 佶 侃 來 侊 供 係 俓 俱 個 倞 倦 倨 假 偈 健 傀 傑 傾 僅 僑 價 儆 儉 儺 光 克 兢 內 公 共 其 具 兼 冀 冠 凱 刊 刮 券 刻 剋 剛 劇 劍 劒 功 加 劤 劫 勁 勍 勘 勤 勸 勻 勾 匡 匣 區 南 卦 却 卵 卷 卿 厥 去 及 口 句 叩 叫 可 各 吉 君 告 呱 呵 咎 咬 哥 哭 啓 喀 喇 喝 喫 喬 嗜 嘉 嘔 器 囊 困 固 圈 國 圭 圻 均 坎 坑 坤 坰 坵 垢 基 埼 堀 堅 堈 堪 堺 塊 塏 境 墾 壙 壞 夔 奇 奈 奎 契 奸 妓 妗 姑 姜 姦 娘 娜 嫁 嬌 孔 季 孤 宏 官 客 宮 家 寄 寇 寡 寬 尻 局 居 屆 屈 岐 岡 岬 崎 崑 崗 嵌 嵐 嶇 嶠 工 巧 巨 己 巾 干 幹 幾 庚 庫 康 廊 廐 廓 廣 建 弓 强 彊 徑 忌 急 怪 怯 恐 恝 恪 恭 悸 愆 感 愧 愷 愾 慊 慣 慤 慨 慶 慷 憩 憬 憾 懃 懇 懦 懶 懼 戈 戒 戟 戡 扱 技 抉 拉 拏 拐 拒 拘 括 拮 拱 拳 拷 拿 捏 据 捲 捺 掘 掛 控 揀 揆 揭 擊 擎 擒 據 擧 攪 攷 改 攻 故 敎 救 敢 敬 敲 斛 斤 旗 旣 昆 昑 景 晷 暇 暖 暠 暻 曠 曲 更 曷 朗 朞 期 机 杆 杞 杰 枏 果 枯 架 枸 柑 柩 柬 柯 校 根 格 桀 桂 桔 桿 梏 梗 械 梱 棄 棋 棍 棘 棨 棺 楗 楠 極 槁 構 槐 槨 槪 槻 槿 樂 橄 橋 橘 機 檄 檎 檢 櫃 欄 權 欺 款 歌 歐 歸 殼 毆 毬 氣 求 江 汨 汲 決 汽 沂 沽 洛 洸 浪 涇 淃 淇 減 渠 渴 湳 溝 溪 滑 滾 漑 潔 潰 澗 激 濫 灌 灸 炅 炚 炬 烙 烱 煖 爛 牽 犬 狂 狗 狡 狼 獗 玖 玘 珂 珏 珖 珙 珞 珪 球 琦 琨 琪 琯 琴 瑾 璂 璟 璣 璥 瓊 瓘 瓜 甄 甘 甲 男 畇 界 畸 畺 畿 疆 疥 疳 痂 痙 痼 癎 癩 癸 皆 皎 皐 盖 監 看 眷 睾 瞰 瞼 瞿 矜 矩 矯 硅 硬 碁 碣 磎 磬 磯 磵 祁 祇 祈 祛 祺 禁 禽 科 稈 稼 稽 稿 穀 究 穹 空 窘 窟 窮 窺 竅 竟 竭 競 竿 筋 筐 筠 箇 箕 箝 管 簡 粳 糠 系 糾 紀 納 紘 級 紺 絅 結 絞 給 絳 絹 絿 經 綱 綺 緊 繫 繭 繼 缺 罐 罫 羅 羈 羌 羔 群 羹 翹 考 耆 耉 耕 耭 耿 肌 肝 股 肩 肯 肱 胛 胱 脚 脛 腔 腱 膈 膏 膠 臘 臼 舅 舊 舡 艮 艱 芎 芥 芩 芹 苛 苟 苦 苽 茄 莖 菅 菊 菌 菓 菫 菰 落 葛 葵 蓋 蕎 蕨 薑 藁 藍 藿 蘭 蘿 虔 蚣 蛟 蝎 螺 蠟 蠱 街 衢 衲 衾 衿 袈 袞 袴 裙 裸 褐 襁 襟 襤 見 規 覡 覲 覺 觀 角 計 記 訣 訶 詭 誇 誡 誥 課 諫 諾 謙 講 謳 謹 譏 警 譴 谷 谿 豈 貢 貫 貴 賈 購 赳 起 跏 距 跨 踞 蹇 蹶 躬 軀 車 軌 軍 軻 較 輕 轎 轟 辜 近 迦 迲 适 逑 逕 逵 過 遣 遽 邏 那 邯 邱 郊 郎 郡 郭 酪 醵 金 鈐 鈞 鉀 鉅 鉗 鉤 銶 鋸 鋼 錡 錤 錦 錮 鍋 鍵 鎌 鎧 鏡 鑑 鑒 鑛 開 間 閘 閣 閨 闕 關 降 階 隔 隙 雇 難 鞏 鞠 鞨 鞫 頃 頸 顆 顧 飢 餃 館 饉 饋 饑 駒 駕 駱 騎 騏 騫 驅 驕 驚 驥 骨 高 鬼 魁 鮫 鯤 鯨 鱇 鳩 鵑 鵠 鷄 鷗 鸞 麒 麴 黔 鼓 龕 龜",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "kok": {
+ 0: "़ ० १ २ ३ ४ ५ ६ ७ ८ ९ ॐ ं ँ ः अ आ इ ई उ ऊ ऋ ऌ ऍ ए ऐ ऑ ओ औ क क़ ख ख़ ग ग़ घ ङ च छ ज ज़ झ ञ ट ठ ड ड़ ढ ढ़ ण त थ द ध न प फ फ़ ब भ म य य़ र ल व श ष स ह ळ ऽ ा ि ी ु ू ृ ॄ ॅ े ै ॉ ो ौ ्",
+ 3: "\u200c \u200d",
+ },
+ "ksb": {
+ 0: "a b c d e f g h i j k l m n o p s t u v w y z",
+ 3: "q r x",
+ 5: "A B C D E F G H I J K L M N O P S T U V W Y Z",
+ },
+ "ksf": {
+ 0: "a á b c d e é ǝ ǝ́ ɛ ɛ́ f g h i í j k l m n ŋ o ó ɔ ɔ́ p r s t u ú v w y z",
+ 3: "q x",
+ 5: "A B C D E Ǝ Ɛ F G H I J K L M N Ŋ O Ɔ P R S T U V W Y Z",
+ },
+ "ksh": {
+ 0: "a å ä æ b c d e ë ė f g h i j k l m n o ö œ p q r s t u ů ü v w x y z",
+ 3: "á à ă â å ä ã ā æ ç é è ĕ ê ë ē ğ í ì ĭ î ï ī ij ı ł ñ ó ò ŏ ô ö ø ō œ ú ù ŭ û ü ū ÿ",
+ },
+ "ku": {
+ 0: "ئ ا ب پ ت ج چ ح خ د ر ز ڕ ژ س ش ع غ ف ڤ ق ک گ ل ڵ م ن ه ھ و ۆ ی ێ",
+ 3: "ً ٌ ٍ َ ُ ِ ّ ْ ء آ أ ؤ إ ئ ا ب ة ث ذ ص ض ط ظ ك ى ي",
+ },
+ "ku_Latn": {
+ 0: "a b c ç d e ê f g h i î j k l m n o p q r s ş t u û v w x y z",
+ },
+ "kw": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "ky": {
+ 0: "а б г д е ё ж з и й к л м н ӊ о ө п р с т у ү х ч ш ъ ы э ю я",
+ 3: "в ф ц щ ь",
+ },
+ "lag": {
+ 0: "a á b c d e é f g h i í ɨ j k l m n o ó p q r s t u ú ʉ v w x y z",
+ 5: "A B C D E F G H I Ɨ J K L M N O P Q R S T U Ʉ V W X Y Z",
+ },
+ "lg": {
+ 0: "a b c d e f g i j k l m n ny ŋ o p r s t u v w y z",
+ 3: "h q x",
+ 5: "A B C D E F G I J K L M N Ŋ O P R S T U V W Y Z",
+ },
+ "ln": {
+ 0: "a á â ǎ b c d e é ê ě ɛ ɛ́ ɛ̂ ɛ̌ f g gb h i í î ǐ k l m mb mp n nd ng nk ns nt ny nz o ó ô ǒ ɔ ɔ́ ɔ̂ ɔ̌ p r s t u ú v w y z",
+ 3: "j q x",
+ 5: "A B C D E Ɛ F G Gb H I K L M Mb Mp N Nd Ng Nk Ns Nt Ny Nz O Ɔ P R S T U V W Y Z",
+ },
+ "lo": {
+ 0: "່ ້ ໊ ໋ ໌ ໍ ໆ ກ ຂ ຄ ງ ຈ ສ ຊ ຍ ດ ຕ ຖ ທ ນ ບ ປ ຜ ຝ ພ ຟ ມ ຢ ຣ ລ ວ ຫ ໜ ໝ ອ ຮ ຯ ະ ັ າ ຳ ິ ີ ຶ ື ຸ ູ ົ ຼ ຽ ເ ແ ໂ ໃ ໄ",
+ 3: "\u200b ໐ ໑ ໒ ໓ ໔ ໕ ໖ ໗ ໘ ໙",
+ },
+ "lt": {
+ 0: "a ą b c č d e ę ė f g h i į y j k l m n o p r s š t u ų ū v z ž",
+ 3: "i̇́ i̇̀ i̇̃ i̇ į̇ j̇ q w x",
+ 4: "a ą b c č d e ę ė f g h i į y j k l m n o p r s š t u ų ū v z ž",
+ 5: "A Ą B C Č D E Ę Ė F G H I Į Y J K L M N O P R S Š T U Ų Ū V Z Ž",
+ },
+ "lu": {
+ 0: "a á à b c d e é è ɛ ɛ́ ɛ̀ f h i í ì j k l m n ng ny o ó ò ɔ ɔ́ ɔ̀ p ph q s shi t u ú ù v w y z",
+ 3: "g r x",
+ 5: "A B C D E F H I J K L M N O P Q S T U V W Y Z",
+ },
+ "luo": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y",
+ 3: "q x z",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y",
+ },
+ "luy": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "lv": {
+ 0: "a ā b c č d e ē f g ģ h i ī j k ķ l ļ m n ņ o p r s š t u ū v z ž",
+ 2: "- ‐ – — , ; : ! ? . … ' ‘ ’ ‚ \" “ ” „ ( ) [ ] @ * / & # † ‡ ′ ″ §",
+ 3: "q w x y",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C Č D E F G Ģ H I J K Ķ L Ļ M N Ņ O P Q R S Š T U V W X Y Z Ž",
+ },
+ "mas": {
+ 0: "a á à â ā b c d e é è ê ē ɛ g h i í ì î ī ɨ j k l m n ny ŋ o ó ò ô ō ɔ p r rr s sh t u ú ù û ū ʉ ʉ́ w wu y yi",
+ 3: "f q v x z",
+ 5: "A B C D E Ɛ G H I Ɨ J K L M N Ŋ O Ɔ P R S T U Ʉ W Y",
+ },
+ "mer": {
+ 0: "a b c d e f g h i ĩ j k l m n o p q r s t u ũ v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "mfe": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W X Y Z",
+ },
+ "mg": {
+ 0: "a à â b d e é è ê ë f g h i ì î ï j k l m n ñ o ô p r s t v y z",
+ 3: "c q u w x",
+ 5: "A B D E F G H I J K L M N O P R S T V Y Z",
+ },
+ "mgh": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y z",
+ 3: "q x",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "mk": {
+ 0: "а б в г д ѓ е ж з ѕ и ј к л љ м н њ о п р с т ќ у ф х ц ч џ ш",
+ 3: "ѐ ѝ",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ 5: "А Б В Г Д Ѓ Е Ж З Ѕ И Ј К Л Љ М Н Њ О П Р С Т Ќ У Ф Х Ц Ч Џ Ш",
+ },
+ "ml": {
+ 0: "\u200c \u200d ഃ അ ആ ഇ ഈ ഉ ഊ ഋ ൠ ഌ ൡ എ ഏ ഐ ഒ ഓ ഔ ക ഖ ഗ ഘ ങ ച ഛ ജ ഝ ഞ ട ഠ ഡ ഢ ണ ത ഥ ദ ധ ന പ ഫ ബ ഭ മ ം യ ര ല വ ശ ഷ സ ഹ ള ഴ റ ാ ി ീ ു ൂ ൃ െ േ ൈ ൊ ോ ൗ ൌ ്",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "mn": {
+ 0: "а б в г д е ё ж з и й к л м н о ө п р с т у ү ф х ц ч ш щ ъ ы ь э ю я",
+ 3: "ә җ ӊ һ",
+ },
+ "mn_Mong": {
+ 0: "᠐ ᠑ ᠒ ᠓ ᠔ ᠕ ᠖ ᠗ ᠘ ᠙ ᠠ ᠡ ᠢ ᠣ ᠤ ᠥ ᠦ ᠧ ᠨ ᠩ ᠪ ᠫ ᠬ ᠭ ᠮ ᠯ ᠰ ᠱ ᠲ ᠳ ᠴ ᠵ ᠶ ᠷ ᠸ ᠹ ᠺ ᠻ ᠼ ᠽ ᠾ ᠿ ᡀ ᡁ ᡂ",
+ },
+ "mr": {
+ 0: "़ ० १ २ ३ ४ ५ ६ ७ ८ ९ ॐ ं ँ ः अ आ इ ई उ ऊ ऋ ऌ ऍ ए ऐ ऑ ओ औ क ख ग घ ङ च छ ज झ ञ ट ठ ड ढ ण त थ द ध न प फ ब भ म य र ल व श ष स ह ळ ऽ ा ि ी ु ू ृ ॄ ॅ े ै ॉ ो ौ ्",
+ 3: "\u200c \u200d",
+ 4: "र ु",
+ 5: "\u200d ॐ ं ः अ आ इ ई उ ऊ ऋ ऌ ए ऐ ऑ ओ औ क ख ग घ ङ च छ ज झ ञ ट ठ ड ढ ण त थ द ध न प फ ब भ म य र ल व श ष स ह ळ ऽ ॅ ्",
+ },
+ "ms": {
+ 0: "a ai au b c d dz e f g h i j k kh l m n ng ngg ny o p q r s sy t ts u ua v w x y z",
+ 3: "á à ă â å ä ã ā æ ç é è ĕ ê ë ē í ì ĭ î ï ī ñ ó ò ŏ ô ö ø ō œ ú ù ŭ û ü ū ÿ",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "mt": {
+ 0: "a à b ċ d e è f ġ g għ h ħ i ì j k l m n o ò p q r s t u ù v w x ż z",
+ 3: "c y",
+ },
+ "mua": {
+ 0: "a ã b ɓ c d ɗ e ë ǝ f g h i ĩ j k l m n ŋ o õ p r s t u v ṽ w y z",
+ 3: "q x",
+ 5: "A B Ɓ C D Ɗ E Ǝ F G H I J K L M N Ŋ O P R S T U V W Y Z",
+ },
+ "my": {
+ 0: "က ခ ဂ ဃ င စ ဆ ဇ ဈ ဉ ည ဋ ဌ ဍ ဎ ဏ တ ထ ဒ ဓ န ပ ဖ ဗ ဘ မ ယ ရ လ ဝ သ ဟ ဠ အ ဣ ဤ ဥ ဦ ဧ ဩ ဪ ာ ါ ိ ီ ု ူ ေ ဲ ံ ဿ ျ ြ ွ ှ ္ ် ့ း",
+ 3: "ၐ ၑ ဨ ဢ ၒ ၓ ၔ ၕ ၖ ၗ ၘ ၙ",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "naq": {
+ 0: "a â b c d e f g h i î k m n o ô p q r s t u û w x y z ǀ ǁ ǂ ǃ",
+ 3: "j l v",
+ 5: "A B C D E F G H I K M N O P Q R S T U W X Y Z",
+ },
+ "nb": {
+ 0: "a à b c d e é f g h i j k l m n o ó ò ô p q r s t u v w x y z æ ø å",
+ 3: "á ǎ ã č ç đ è ê í ń ñ ŋ š ŧ ü ž ä ö",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Æ Ø Å",
+ },
+ "nd": {
+ 0: "a b c d e f g h i j k l m n o p q s t u v w x y z",
+ 3: "r",
+ 5: "A B C D E F G H I J K L M N O P Q S T U V W X Y Z",
+ },
+ "ne": {
+ 0: "़ ँ ं ः ॐ अ आ इ ई उ ऊ ऋ ऌ ऍ ए ऐ ऑ ओ औ क ख ग घ ङ च छ ज झ ञ ट ठ ड ढ ण त थ द ध न प फ ब भ म य र ल ळ व श ष स ह ऽ ा ि ी ु ू ृ ॄ ॅ े ै ॉ ो ौ ्",
+ 3: "\u200c \u200d",
+ },
+ "nl": {
+ 0: "a á ä b c d e é ë f g h i í ï ij j k l m n o ó ö p q r s t u ú ü v w x y z",
+ 2: "- ‐ – — , ; : ! ? . … ' ‘ ’ \" “ ” ( ) [ ] @ * / & # † ‡ ′ ″ §",
+ 3: "å ã ç ñ ô",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "nmg": {
+ 0: "a á ă â ä ā b ɓ c d e é ĕ ê ē ǝ ǝ́ ǝ̆ ǝ̂ ǝ̄ ɛ ɛ́ ɛ̆ ɛ̂ ɛ̄ f g h i í ĭ î ï ī j k l m n ń ŋ o ó ŏ ô ö ō ɔ ɔ́ ɔ̆ ɔ̂ ɔ̄ p r ŕ s t u ú ŭ û ū v w y",
+ 3: "q x z",
+ 5: "A B Ɓ C D E Ǝ Ɛ F G H I J K L M N Ŋ O Ɔ P R S T U V W Y",
+ },
+ "nn": {
+ 0: "a à b c d e é f g h i j k l m n o ó ò ô p q r s t u v w x y z æ ø å",
+ 3: "á ǎ č ç đ è ê ń ñ ŋ š ŧ ü ž ä ö",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Æ Ø Å",
+ },
+ "nso": {
+ 0: "a b d e ê f g h i j k l m n o ô p r s š t u w x y",
+ 3: "c q v z",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "nus": {
+ 0: "a ä a̱ b c d e ë e̱ ɛ ɛ̈ ɛ̱ ɛ̱̈ f g ɣ h i ï i̱ j k l m n ŋ o ö o̱ ɔ ɔ̈ ɔ̱ p q r s t u v w x y z",
+ 5: "A B C D E Ɛ F G Ɣ H I J K L M N Ŋ O Ɔ P Q R S T U V W X Y Z",
+ },
+ "nyn": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "om": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "or": {
+ 0: "଼ ଅ ଆ ଇ ଈ ଉ ଊ ଋ ଏ ଐ ଓ ଔ ଁ ଂ ଃ କ ଖ ଗ ଘ ଙ ଚ ଛ ଜ ଝ ଞ ଟ ଠ ଡ ଡ଼ ଢ ଢ଼ ଣ ତ ଥ ଦ ଧ ନ ପ ଫ ବ ଭ ମ ଯ ୟ ର ଲ ଳ ଵ ୱ ଶ ଷ ସ ହ ା ି ୀ ୁ ୂ ୃ େ ୈ ୋ ୌ ୍",
+ 3: "\u200c \u200d",
+ },
+ "pa": {
+ 0: "ੱ ੰ ਼ ੦ ੧ ੨ ੩ ੪ ੫ ੬ ੭ ੮ ੯ ੴ ੳ ਉ ਊ ਓ ਅ ਆ ਐ ਔ ੲ ਇ ਈ ਏ ਸ ਸ਼ ਹ ਕ ਖ ਖ਼ ਗ ਗ਼ ਘ ਙ ਚ ਛ ਜ ਜ਼ ਝ ਞ ਟ ਠ ਡ ਢ ਣ ਤ ਥ ਦ ਧ ਨ ਪ ਫ ਫ਼ ਬ ਭ ਮ ਯ ਰ ਲ ਵ ੜ ੍ ਾ ਿ ੀ ੁ ੂ ੇ ੈ ੋ ੌ",
+ 3: "\u200c \u200d ਃ ਂ ਁ ਲ਼",
+ },
+ "pa_Arab": {
+ 0: "ُ ء آ ؤ ئ ا ب پ ت ث ٹ ج چ ح خ د ذ ڈ ر ز ڑ ژ س ش ص ض ط ظ ع غ ف ق ک گ ل م ن ں ه ھ ہ و ی ے",
+ 3: "أ ٻ ة ٺ ټ ٽ",
+ },
+ "pl": {
+ 0: "a ą b c ć d e ę f g h i j k l ł m n ń o ó p r s ś t u w y z ź ż",
+ 3: "q v x",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "ps": {
+ 0: "َ ِ ُ ً ٍ ٌ ّ ْ ٔ ٰ آ ا أ ء ب پ ت ټ ث ج ځ چ څ ح خ د ډ ذ ر ړ ز ژ ږ س ش ښ ص ض ط ظ ع غ ف ق ک ګ ل م ن ڼ ه ة و ؤ ی ي ې ۍ ئ",
+ 3: "\u200c \u200d",
+ },
+ "pt": {
+ 0: "a á à â ã b c ç d e é ê f g h i í j k l m n o ó ò ô õ p q r s t u ú v w x y z",
+ 3: "ă å ä ā æ è ĕ ë ē ì ĭ î ï ī ñ ŏ ö ø ō œ ù ŭ û ü ū ÿ",
+ 4: "a b c č d e f g h i j k l ł m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "pt_PT": {
+ 3: "ª ă å ä ā æ è ĕ ë ē ì ĭ î ï ī ñ º ŏ ö ø ō œ ù ŭ û ü ū ÿ",
+ },
+ "rn": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "ro": {
+ 0: "a ă â b c d e f g h i î j k l m n o p r s ș t ț u v x z",
+ 3: "á à å ä ç é è ê ë ñ ö q ş ţ ü w y",
+ 4: "a ă â b c d e f g h i î j k l m n o p q r s ș t ț u v w x y z",
+ 5: "A Ă Â B C D E F G H I Î J K L M N O P Q R S Ș T Ț U V W X Y Z",
+ },
+ "rof": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y z",
+ 3: "q x",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "root": {
+ 2: "- , ; : ! ? . ( ) [ ] { }",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ },
+ "ru": {
+ 0: "а б в г д е ё ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я",
+ 2: "- ‐ – — , ; : ! ? . … ' ‘ ‚ \" “ „ « » ( ) [ ] { } @ * / & # §",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "А Б В Г Д Е Ё Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ы Э Ю Я",
+ },
+ "rw": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "rwk": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y z",
+ 3: "q x",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "sah": {
+ 0: "а б г ҕ д дь и й к л м н нь ҥ о ө п р с т у ү х һ ч ы э",
+ 3: "в е ё ж з ф ц ш щ ъ ь ю я",
+ 5: "А Б Г Ҕ Д Дь И Й К Л М Н Нь Ҥ О Ө П Р С Т У Ү Х Һ Ч Ы Э",
+ },
+ "saq": {
+ 0: "a b c d e g h i j k l m n o p r s t u v w y",
+ 3: "f q x z",
+ 5: "A B C D E G H I J K L M N O P R S T U V W Y",
+ },
+ "sbp": {
+ 0: "a b c d e f g h i j k l m n o p s t u v w y",
+ 3: "q r x z",
+ 5: "A B C D E F G H I J K L M N O P S T U V W Y",
+ },
+ "se": {
+ 0: "a á b c č d đ e f g h i j k l m n ŋ o p r s š t ŧ u v z ž",
+ 3: "à å ä ã æ ç é è í ń ñ ó ò ö ø q ú ü w x y",
+ },
+ "seh": {
+ 0: "a á à â ã b c ç d e é ê f g h i í j k l m n o ó ò ô õ p q r s t u ú v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "ses": {
+ 0: "a ã b c d e ẽ f g h i j k l m n ɲ ŋ o õ p q r s š t u w x y z ž",
+ 3: "v",
+ 5: "A Ã B C D E Ẽ F G H I J K L M N Ɲ Ŋ O Õ P Q R S Š T U W X Y Z Ž",
+ },
+ "sg": {
+ 0: "a â ä b d e ê ë f g h i î ï j k l m n o ô ö p r s t u ù û ü v w y z",
+ 3: "c q x",
+ 5: "A B D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "shi": {
+ 0: "a b c d ḍ e ɛ f g gʷ ɣ h ḥ i j k kʷ l m n q r ṛ s ṣ t ṭ u w x y z",
+ 3: "o p v",
+ 5: "A B C D Ḍ E Ɛ F G Gʷ Ɣ H Ḥ I J K Kʷ L M N Q R Ṛ S Ṣ T Ṭ U W X Y Z",
+ },
+ "shi_Tfng": {
+ 0: "ⴰ ⴱ ⴳ ⴳⵯ ⴷ ⴹ ⴻ ⴼ ⴽ ⴽⵯ ⵀ ⵃ ⵄ ⵅ ⵇ ⵉ ⵊ ⵍ ⵎ ⵏ ⵓ ⵔ ⵕ ⵖ ⵙ ⵚ ⵛ ⵜ ⵟ ⵡ ⵢ ⵣ ⵥ",
+ 5: "ⴰ ⴱ ⴳ ⴷ ⴹ ⴻ ⴼ ⴽ ⵀ ⵃ ⵄ ⵅ ⵇ ⵉ ⵊ ⵍ ⵎ ⵏ ⵓ ⵔ ⵕ ⵖ ⵙ ⵚ ⵛ ⵜ ⵟ ⵡ ⵢ ⵣ ⵥ",
+ },
+ "si": {
+ 0: "අ ආ ඇ ඈ ඉ ඊ උ ඌ ඍ එ ඒ ඓ ඔ ඕ ඖ ං ඃ ක ඛ ග ඝ ඞ ඟ ච ඡ ජ ඣ ඥ ඤ ට ඨ ඩ ඪ ණ ඬ ත ථ ද ධ න ඳ ප ඵ බ භ ම ඹ ය ර ල ව ශ ෂ ස හ ළ ෆ ා ැ ෑ ි ී ු ූ ෘ ෲ ෟ ෙ ේ ෛ ො ෝ ෞ ්",
+ 3: "\u200b \u200c \u200d ඎ ඏ ඐ ඦ ෳ",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "අ ආ ඇ ඈ ඉ ඊ උ ඌ ඍ එ ඒ ඓ ඔ ඕ ඖ ක ඛ ග ඝ ඞ ඟ ච ඡ ජ ඣ ඥ ඤ ට ඨ ඩ ඪ ණ ඬ ත ථ ද ධ න ඳ ප ඵ බ භ ම ඹ ය ර ල ව ශ ෂ ස හ ළ ෆ",
+ },
+ "sk": {
+ 0: "a á ä b c č d ď e é f g h ch i í j k l ĺ ľ m n ň o ó ô p q r ŕ s š t ť u ú v w x y ý z ž",
+ },
+ "sl": {
+ 0: "a b c č d e f g h i j k l m n o p r s š t u v z ž",
+ 3: "á à ă â å ä ā æ ç ć đ é è ĕ ê ë ē í ì ĭ î ï ī ñ ó ò ŏ ô ö ø ō œ q ú ù ŭ û ü ū w x y ÿ",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ 5: "A B C Č Ć D Đ E F G H I J K L M N O P Q R S Š T U V W X Y Z Ž",
+ },
+ "sn": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y z",
+ 3: "q x",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "so": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "sq": {
+ 0: "a b c ç d dh e ë f g gj h i j k l ll m n nj o p q r rr s sh t th u v x xh y z zh",
+ 3: "w",
+ },
+ "sr": {
+ 0: "а б в г д ђ е ж з и ј к л љ м н њ о п р с т ћ у ф х ц ч џ ш",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ },
+ "sr_Latn": {
+ 0: "a b c č ć d dž đ e f g h i j k l lj m n nj o p r s š t u v z ž",
+ 3: "q w x y",
+ },
+ "ss": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "st": {
+ 0: "a b d e f g h i j k l m n o p q r s t u w y",
+ 3: "c v x z",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "sv": {
+ 0: "a à b c d e é f g h i j k l m n o p q r s t u v w x y z å ä ö",
+ 2: "- ‐ – — , ; : ! ? . … ' ‘ ’ \" “ ” ( ) [ ] @ * / & # † ‡ ′ ″ §",
+ 3: "á â ã ā ç ë í î ï ī ñ ó ú ÿ ü æ ø",
+ 4: "a b c č d e f g h i j k l ł m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Å Ä Ö",
+ },
+ "sv_FI": {
+ 3: "ã ç ë í ñ ó š ÿ ü ž",
+ },
+ "sw": {
+ 0: "a b ch d e f g h i j k l m n o p r s t u v w y z",
+ 3: "c q x",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "swc": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y z",
+ 3: "q x",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "ta": {
+ 0: "அ ஆ இ ஈ உ ஊ எ ஏ ஐ ஒ ஓ ஔ ஃ க ங ச ஞ ட ண த ந ப ம ய ர ல வ ழ ள ற ன ஜ ஷ ஸ ஹ ா ி ீ ு ூ ெ ே ை ொ ோ ௌ ்",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "te": {
+ 0: "అ ఆ ఇ ఈ ఉ ఊ ఋ ౠ ఌ ౡ ఎ ఏ ఐ ఒ ఓ ఔ ఁ ం ః క ఖ గ ఘ ఙ చ ఛ జ ఝ ఞ ట ఠ డ ఢ ణ త థ ద ధ న ప ఫ బ భ మ య ర ఱ ల వ శ ష స హ ళ ా ి ీ ు ూ ృ ౄ ె ే ై ొ ో ౌ ్ ౕ ౖ",
+ 3: "\u200c \u200d ౦ ౧ ౨ ౩ ౪ ౫ ౬ ౭ ౮ ౯",
+ 5: "అ ఆ ఇ ఈ ఉ ఊ ఋ ౠ ఎ ఏ ఐ ఒ ఓ ఔ క ఖ గ ఘ ఙ చ ఛ జ ఝ ఞ ట ఠ డ ఢ ణ త థ ద ధ న ప ఫ బ భ మ య ర ఱ ల వ శ ష స హ ళ",
+ },
+ "teo": {
+ 0: "a b c d e g h i j k l m n o p r s t u v w x y",
+ 3: "f q z",
+ 5: "A B C D E G H I J K L M N O P R S T U V W X Y",
+ },
+ "tg": {
+ 0: "а б в г ғ д е ё ж з и ӣ й к қ л м н о п р с т у ӯ ф х ҳ ч ҷ ш ъ э ю я",
+ 3: "ц щ ы ь",
+ },
+ "th": {
+ 0: "๎ ์ ็ ่ ้ ๊ ๋ ฯ ๆ ก ข ฃ ค ฅ ฆ ง จ ฉ ช ซ ฌ ญ ฎ ฏ ฐ ฑ ฒ ณ ด ต ถ ท ธ น บ ป ผ ฝ พ ฟ ภ ม ย ร ฤ ล ฦ ว ศ ษ ส ห ฬ อ ฮ ํ ะ ั า ๅ ำ ิ ี ึ ื ุ ู เ แ โ ใ ไ ฺ",
+ 3: "\u200b",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "ti": {
+ 0: "፟ ሀ ሀ ሁ ሂ ሃ ሄ ህ ሆ ለ ለ ሉ ሊ ላ ሌ ል ሎ ሏ ሐ ሑ ሒ ሓ ሔ ሕ ሖ ሗ መ ሙ ሚ ማ ሜ ም ሞ ሟ ሠ ሡ ሢ ሣ ሤ ሥ ሦ ሧ ረ ሩ ሪ ራ ሬ ር ሮ ሯ ሰ ሱ ሲ ሳ ሴ ስ ሶ ሷ ሸ ሹ ሺ ሻ ሼ ሽ ሾ ሿ ቀ ቁ ቂ ቃ ቄ ቅ ቆ ቈ ቊ ቊ ቋ ቌ ቍ ቐ ቐ ቑ ቒ ቓ ቔ ቕ ቖ ቘ ቚ ቚ ቛ ቜ ቝ በ በ ቡ ቢ ባ ቤ ብ ቦ ቧ ቨ ቩ ቪ ቫ ቬ ቭ ቮ ቯ ተ ቱ ቲ ታ ቴ ት ቶ ቷ ቸ ቹ ቺ ቻ ቼ ች ቾ ቿ ኀ ኁ ኂ ኃ ኄ ኅ ኆ ኈ ኊ ኊ ኋ ኌ ኍ ነ ነ ኑ ኒ ና ኔ ን ኖ ኗ ኘ ኙ ኚ ኛ ኜ ኝ ኞ ኟ አ ኡ ኢ ኣ ኤ እ ኦ ኧ ከ ኩ ኪ ካ ኬ ክ ኮ ኰ ኲ ኲ ኳ ኴ ኵ ኸ ኸ ኹ ኺ ኻ ኼ ኽ ኾ ዀ ዂ ዂ ዃ ዄ ዅ ወ ወ ዉ ዊ ዋ ዌ ው ዎ ዐ ዐ ዑ ዒ ዓ ዔ ዕ ዖ ዘ ዘ ዙ ዚ ዛ ዜ ዝ ዞ ዟ ዠ ዡ ዢ ዣ ዤ ዥ ዦ ዧ የ ዩ ዪ ያ ዬ ይ ዮ ደ ደ ዱ ዲ ዳ ዴ ድ ዶ ዷ ጀ ጀ ጁ ጂ ጃ ጄ ጅ ጆ ጇ ገ ጉ ጊ ጋ ጌ ግ ጎ ጐ ጒ ጒ ጓ ጔ ጕ ጠ ጠ ጡ ጢ ጣ ጤ ጥ ጦ ጧ ጨ ጩ ጪ ጫ ጬ ጭ ጮ ጯ ጰ ጱ ጲ ጳ ጴ ጵ ጶ ጷ ጸ ጹ ጺ ጻ ጼ ጽ ጾ ጿ ፀ ፁ ፂ ፃ ፄ ፅ ፆ ፇ ፈ ፉ ፊ ፋ ፌ ፍ ፎ ፏ ፐ ፑ ፒ ፓ ፔ ፕ ፖ ፗ",
+ 3: "᎐ ᎐ ᎑ ᎒ ᎓ ᎔ ᎕ ᎖ ᎗ ᎘ ᎙ ሇ ⶀ ᎀ ᎀ ᎁ ᎂ ᎃ ⶁ ⶁ ⶂ ⶃ ⶄ ቇ ᎄ ᎄ ᎅ ᎆ ᎇ ⶅ ⶅ ⶆ ⶇ ኇ ⶈ ⶈ ⶉ ⶊ ኯ ዏ ⶋ ዯ ⶌ ዸ ዸ ዹ ዺ ዻ ዼ ዽ ዾ ዿ ⶍ ⶎ ጏ ጘ ጘ ጙ ጚ ጛ ጜ ጝ ጞ ጟ ⶓ ⶓ ⶔ ⶕ ⶖ ⶏ ⶏ ⶐ ⶑ ፇ ᎈ ᎈ ᎉ ᎊ ᎋ ᎌ ᎍ ᎎ ᎏ ⶒ ፘ ፘ ፙ ፚ ⶠ ⶠ ⶡ ⶢ ⶣ ⶤ ⶥ ⶦ ⶨ ⶨ ⶩ ⶪ ⶫ ⶬ ⶭ ⶮ ⶰ ⶰ ⶱ ⶲ ⶳ ⶴ ⶵ ⶶ ⶸ ⶸ ⶹ ⶺ ⶻ ⶼ ⶽ ⶾ ⷀ ⷀ ⷁ ⷂ ⷃ ⷄ ⷅ ⷆ ⷈ ⷈ ⷉ ⷊ ⷋ ⷌ ⷍ ⷎ ⷐ ⷐ ⷑ ⷒ ⷓ ⷔ ⷕ ⷖ ⷘ ⷘ ⷙ ⷚ ⷛ ⷜ ⷝ ⷞ",
+ 5: "ሀ ለ ሐ መ ሠ ረ ሰ ሸ ቀ ቈ ቐ ቘ በ ቨ ተ ቸ ኀ ኈ ነ ኘ አ ከ ኰ ኸ ዀ ወ ዐ ዘ ዠ የ ደ ጀ ገ ጐ ጠ ጨ ጰ ጸ ፀ ፈ ፐ",
+ },
+ "tn": {
+ 0: "a b d e ê f g h i j k l m n o ô p r s t u w y",
+ 3: "c q v x z",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "to": {
+ 0: "a ā e ē f h ʻ i ī k l m n ng o ō p s t u ū v",
+ 3: "à ă â å ä æ b c ç d è ĕ ê ë g ì ĭ î ï j ñ ò ŏ ô ö ø œ q r ù ŭ û ü w x y ÿ z",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A Ā B C D E Ē F G H ʻ I Ī J K L M N O Ō P Q R S T U Ū V W X Y Z",
+ },
+ "tr": {
+ 0: "a b c ç d e f g ğ h ı i i̇ j k l m n o ö p r s ş t u ü v y z",
+ 2: "- ‐ – — , ; : ! ? . … ' ‘ ’ \" “ ” ( ) [ ] @ * / & # † ‡ ′ ″ §",
+ 3: "á à ă â å ä ā æ é è ĕ ê ë ē í ì ĭ î ï ī ñ ó ò ŏ ô ø ō œ q ú ù ŭ û ū w x ÿ",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ 5: "A B C Ç D E F G H I İ J K L M N O Ö P Q R S Ş T U Ü V W X Y Z",
+ },
+ "ts": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "twq": {
+ 0: "a ã b c d e ẽ f g h i j k l m n ŋ ɲ o õ p q r s š t u w x y z ž",
+ 3: "v",
+ },
+ "tzm": {
+ 0: "a b c d ḍ e ɛ f g gʷ ɣ h ḥ i j k kʷ l m n q r ṛ s ṣ t ṭ u w x y z",
+ 3: "o p v",
+ 5: "A B C D Ḍ E Ɛ F G Ɣ H Ḥ I J K L M N Q R Ṛ S Ṣ T Ṭ U W X Y Z",
+ },
+ "uk": {
+ 0: "ʼ а б в г ґ д е є ж з и і ї й к л м н о п р с т у ф х ц ч ш щ ю я ь",
+ 4: "a b c č d e f g h i j k l ł m n o º p q r s t u v w x y z",
+ 5: "А Б В Г Ґ Д Е Є Ж З И І Ї Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ю Я",
+ },
+ "ur": {
+ 0: "ا أ آ ب پ ت ٹ ث ج چ ح خ د ڈ ذ ر ڑ ز ژ س ش ص ض ط ظ ع غ ف ق ک گ ل م ن ں و ؤ ہ ھ ء ی ئ ے ٻ ة ٺ ټ ٽ ه ي",
+ },
+ "uz": {
+ 0: "а б в г ғ д е ё ж з и й к қ л м н о п р с т у ў ф х ҳ ч ш ъ э ю я",
+ 3: "ц щ ы ь",
+ },
+ "uz_Arab": {
+ 0: "ً ٌ ٍ َ ُ ِ ّ ْ ٔ ٰ ء آ أ ؤ ئ ا ب پ ة ت ث ټ ج چ ح خ ځ څ د ذ ډ ر ز ړ ږ ژ س ش ښ ص ض ط ظ ع غ ف ق ک ګ گ ل م ن ڼ ه و ۇ ۉ ي ی ۍ ې",
+ 3: "\u200c \u200d",
+ },
+ "uz_Latn": {
+ 0: "a aʼ b ch d e eʼ f g gʼ h i iʼ j k l m n o oʼ p q r s sh t u uʼ v x y z",
+ 3: "c w",
+ 5: "A B CH D E F G Gʼ H I J K L M N O Oʼ P Q R S SH T U V X Y Z",
+ },
+ "vai": {
+ 0: "꘠ ꘠ ꘡ ꘢ ꘣ ꘤ ꘥ ꘦ ꘧ ꘨ ꘩ ꔀ ꔀ ꔁ ꔂ ꔃ ꔄ ꔅ ꔆ ꔇ ꔈ ꔉ ꔊ ꔋ ꔌ ꘓ ꔍ ꔍ ꔎ ꔏ ꔐ ꔑ ꔒ ꔓ ꔔ ꔕ ꔖ ꔗ ꔘ ꔙ ꔚ ꔛ ꔜ ꔝ ꔞ ꘔ ꔟ ꔟ ꔠ ꔡ ꔢ ꔣ ꔤ ꔥ ꔦ ꔧ ꔨ ꔩ ꔪ ꔫ ꔬ ꔭ ꔮ ꔯ ꔰ ꔱ ꔲ ꔳ ꘕ ꔴ ꔴ ꔵ ꔶ ꔷ ꔸ ꔹ ꔺ ꔻ ꔼ ꔽ ꔾ ꔿ ꕀ ꕁ ꕂ ꕃ ꕄ ꕅ ꕆ ꕇ ꘖ ꕈ ꕈ ꕉ ꕊ ꕋ ꕌ ꕍ ꕎ ꕏ ꕐ ꕑ ꕒ ꘗ ꕓ ꕓ ꕔ ꕕ ꕖ ꕗ ꕘ ꘐ ꘘ ꕙ ꕚ ꘙ ꕛ ꕛ ꕜ ꕝ ꕞ ꕟ ꕠ ꘚ ꕡ ꕡ ꕢ ꕣ ꕤ ꕥ ꕦ ꕧ ꕨ ꕩ ꕪ ꘑ ꕫ ꕫ ꕬ ꕭ ꕮ ꘪ ꕯ ꕯ ꕰ ꕱ ꕲ ꕳ ꕴ ꕵ ꕶ ꕷ ꕸ ꕹ ꕺ ꕻ ꕼ ꕽ ꕾ ꕿ ꖀ ꖁ ꖂ ꖃ ꖄ ꖅ ꘛ ꖆ ꖇ ꘒ ꖈ ꖈ ꖉ ꖊ ꖋ ꖌ ꖍ ꖎ ꖏ ꖐ ꖑ ꖒ ꖓ ꖔ ꖕ ꖖ ꖗ ꖘ ꖙ ꖚ ꖛ ꖜ ꖝ ꖞ ꖟ ꖠ ꖡ ꖢ ꖣ ꖤ ꖥ ꖦ ꖧ ꖨ ꖩ ꖪ ꖫ ꖬ ꖭ ꖮ ꖯ ꖰ ꖱ ꖲ ꖳ ꖴ ꘜ ꖵ ꖵ ꖶ ꖷ ꖸ ꖹ ꖺ ꖻ ꖼ ꖽ ꖾ ꖿ ꗀ ꗁ ꗂ ꗃ ꗄ ꗅ ꗆ ꗇ ꗈ ꗉ ꗊ ꗋ ꘝ ꗌ ꗌ ꗍ ꗎ ꗏ ꗐ ꗑ ꘫ ꘞ ꗒ ꗒ ꗓ ꗔ ꗕ ꗖ ꗗ ꗘ ꘟ ꗙ ꗙ ꗚ ꗛ ꗜ ꗝ ꗞ ꗟ ꗠ ꗡ ꗢ ꗣ ꗤ ꗥ ꗦ ꗧ ꗨ ꗩ ꗪ ꗫ ꗬ ꗭ ꗮ ꗯ ꗰ ꗱ ꗲ ꗳ ꗴ ꗵ ꗶ ꗷ ꗸ ꗹ ꗺ ꗻ ꗼ ꗽ ꗾ ꗿ ꘀ ꘁ ꘂ ꘃ ꘄ ꘅ ꘆ ꘇ ꘈ ꘉ ꘊ ꘋ ꘌ",
+ },
+ "vai_Latn": {
+ 0: "a á ã b ɓ c d ɗ e é ẽ ɛ ɛ́ ɛ̃ f g h i í ĩ j k l m n ŋ o ó õ ɔ ɔ́ ɔ̃ p q r s t u ú ũ v w x y z",
+ 5: "A B Ɓ C D Ɗ E Ɛ F G H I J K L M N Ŋ O Ɔ P Q R S T U V W X Y Z",
+ },
+ "ve": {
+ 0: "a b d ḓ e f g h i k l ḽ m n ṅ ṋ o p r s t ṱ u v w x y z",
+ },
+ "vi": {
+ 0: "a à ả ã á ạ ă ằ ẳ ẵ ắ ặ â ầ ẩ ẫ ấ ậ b c d đ e è ẻ ẽ é ẹ ê ề ể ễ ế ệ f g h i ì ỉ ĩ í ị j k l m n o ò ỏ õ ó ọ ô ồ ổ ỗ ố ộ ơ ờ ở ỡ ớ ợ p q r s t u ù ủ ũ ú ụ ư ừ ử ữ ứ ự v w x y ỳ ỷ ỹ ý ỵ z",
+ 4: "a b c d đ e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "vun": {
+ 0: "a b c d e f g h i j k l m n o p r s t u v w y z",
+ 3: "q x",
+ 5: "A B C D E F G H I J K L M N O P R S T U V W Y Z",
+ },
+ "wae": {
+ 0: "a á ä ã b c č d e é f g h i í j k l m n o ó ö õ p q r s š t u ú ü ũ v w x y z",
+ 3: "à ă â å ā æ ç è ĕ ê ë ē ì ĭ î ï ī ñ ò ŏ ô ø ō œ ß ù ŭ û ū ÿ",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "wal": {
+ 0: "፟ ᎐ ᎐ ᎑ ᎒ ᎓ ᎔ ᎕ ᎖ ᎗ ᎘ ᎙ ሀ ሀ ሁ ሂ ሃ ሄ ህ ሆ ሇ ለ ሉ ሊ ላ ሌ ል ሎ ሏ ⶀ ሐ ሐ ሑ ሒ ሓ ሔ ሕ ሖ ሗ መ ሙ ሚ ማ ሜ ም ሞ ሟ ᎀ ᎀ ᎁ ᎂ ᎃ ⶁ ሠ ሠ ሡ ሢ ሣ ሤ ሥ ሦ ሧ ረ ሩ ሪ ራ ሬ ር ሮ ሯ ⶂ ሰ ሰ ሱ ሲ ሳ ሴ ስ ሶ ሷ ⶃ ሸ ሸ ሹ ሺ ሻ ሼ ሽ ሾ ሿ ⶄ ቀ ቀ ቁ ቂ ቃ ቄ ቅ ቆ ቇ ቈ ቊ ቊ ቋ ቌ ቍ ቐ ቐ ቑ ቒ ቓ ቔ ቕ ቖ ቘ ቚ ቚ ቛ ቜ ቝ በ በ ቡ ቢ ባ ቤ ብ ቦ ቧ ᎄ ᎄ ᎅ ᎆ ᎇ ⶅ ቨ ቨ ቩ ቪ ቫ ቬ ቭ ቮ ቯ ተ ቱ ቲ ታ ቴ ት ቶ ቷ ⶆ ቸ ቸ ቹ ቺ ቻ ቼ ች ቾ ቿ ⶇ ኀ ኀ ኁ ኂ ኃ ኄ ኅ ኆ ኇ ኈ ኊ ኊ ኋ ኌ ኍ ነ ነ ኑ ኒ ና ኔ ን ኖ ኗ ⶈ ኘ ኘ ኙ ኚ ኛ ኜ ኝ ኞ ኟ ⶉ አ አ ኡ ኢ ኣ ኤ እ ኦ ኧ ⶊ ከ ከ ኩ ኪ ካ ኬ ክ ኮ ኯ ኰ ኲ ኲ ኳ ኴ ኵ ኸ ኸ ኹ ኺ ኻ ኼ ኽ ኾ ዀ ዂ ዂ ዃ ዄ ዅ ወ ወ ዉ ዊ ዋ ዌ ው ዎ ዏ ዐ ዑ ዒ ዓ ዔ ዕ ዖ ዘ ዘ ዙ ዚ ዛ ዜ ዝ ዞ ዟ ⶋ ዠ ዠ ዡ ዢ ዣ ዤ ዥ ዦ ዧ የ ዩ ዪ ያ ዬ ይ ዮ ዯ ደ ዱ ዲ ዳ ዴ ድ ዶ ዷ ⶌ ዸ ዸ ዹ ዺ ዻ ዼ ዽ ዾ ዿ ⶍ ጀ ጀ ጁ ጂ ጃ ጄ ጅ ጆ ጇ ⶎ ገ ገ ጉ ጊ ጋ ጌ ግ ጎ ጏ ጐ ጒ ጒ ጓ ጔ ጕ ጘ ጘ ጙ ጚ ጛ ጜ ጝ ጞ ጟ ⶓ ⶓ ⶔ ⶕ ⶖ ጠ ጠ ጡ ጢ ጣ ጤ ጥ ጦ ጧ ⶏ ጨ ጨ ጩ ጪ ጫ ጬ ጭ ጮ ጯ ⶐ ጰ ጰ ጱ ጲ ጳ ጴ ጵ ጶ ጷ ⶑ ጸ ጸ ጹ ጺ ጻ ጼ ጽ ጾ ጿ ፀ ፁ ፂ ፃ ፄ ፅ ፆ ፇ ፈ ፉ ፊ ፋ ፌ ፍ ፎ ፏ ᎈ ᎈ ᎉ ᎊ ᎋ ፐ ፐ ፑ ፒ ፓ ፔ ፕ ፖ ፗ ᎌ ᎌ ᎍ ᎎ ᎏ ⶒ ፘ ፘ ፙ ፚ ⶠ ⶠ ⶡ ⶢ ⶣ ⶤ ⶥ ⶦ ⶨ ⶨ ⶩ ⶪ ⶫ ⶬ ⶭ ⶮ ⶰ ⶰ ⶱ ⶲ ⶳ ⶴ ⶵ ⶶ ⶸ ⶸ ⶹ ⶺ ⶻ ⶼ ⶽ ⶾ ⷀ ⷀ ⷁ ⷂ ⷃ ⷄ ⷅ ⷆ ⷈ ⷈ ⷉ ⷊ ⷋ ⷌ ⷍ ⷎ ⷐ ⷐ ⷑ ⷒ ⷓ ⷔ ⷕ ⷖ ⷘ ⷘ ⷙ ⷚ ⷛ ⷜ ⷝ ⷞ",
+ },
+ "xh": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+ "xog": {
+ 0: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "yav": {
+ 0: "a á à â ǎ ā b c d e é è ɛ ɛ́ ɛ̀ f h i í ì î ī k l m mb n ny ŋ ŋg o ó ò ô ǒ ō ɔ ɔ́ ɔ̀ p s t u ú ù û ǔ ū v w y",
+ 3: "g j q r x z",
+ 5: "A B C D E Ɛ F H I K L M N Ŋ O Ɔ P S T U V W Y",
+ },
+ "yo": {
+ 0: "a á à b d e é è ẹ ẹ́ ẹ̀ f g gb h i í ì j k l m n o ó ò ọ ọ́ ọ̀ p r s ṣ t u ú ù w y",
+ 3: "c q v x z",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "zh": {
+ 0: "一 丁 七 万 万 丈 三 上 下 丌 不 与 专 且 世 丘 丘 丙 业 东 丝 丢 两 严 丧 个 中 丰 串 临 丸 丸 丹 为 主 丽 举 乃 久 么 义 之 之 乌 乍 乎 乏 乐 乔 乖 乘 乙 九 也 也 习 乡 书 买 乱 乾 了 予 争 事 二 于 亏 云 互 五 井 亚 些 亡 交 亦 亨 享 京 亮 亲 人 亿 亿 什 仁 仅 仇 今 介 仍 从 仔 他 付 仙 代 代 令 以 仪 们 仰 仲 件 任 份 仿 企 伊 伍 伏 伏 伐 休 众 伙 会 伟 传 伤 伦 伯 估 伴 伸 似 伽 但 位 位 低 住 佐 佑 体 何 余 佛 作 你 佤 佩 佳 使 例 供 依 侠 侦 侦 侧 侨 侬 侯 侵 便 促 俄 俊 俗 保 信 俩 修 俱 俾 倍 倒 候 倚 借 倦 值 倾 假 偌 偏 做 停 健 偶 偷 储 催 傲 傻 像 僧 儒 允 元 元 兄 充 先 光 克 免 兑 兔 入 全 八 八 公 六 兮 兰 共 关 关 兴 兵 其 具 典 兹 养 养 兼 兽 内 冈 再 冒 写 军 农 冠 冬 冰 冲 冷 准 凌 凝 几 凡 凤 凭 凯 凰 出 击 函 刀 分 切 刊 刑 划 列 列 刘 则 刚 创 初 判 利 别 到 制 制 刷 券 刺 刻 剂 前 剑 剧 剩 剪 副 割 力 劝 劝 办 功 加 务 劣 动 动 助 努 劫 励 励 劲 劳 势 勇 勉 勋 勒 勤 勾 勿 包 匆 匈 化 北 匙 匹 匹 区 医 十 千 升 午 半 华 协 卒 卓 单 单 卖 南 博 占 占 卡 卢 卫 印 危 即 卷 厄 厄 厅 历 厉 压 压 厌 厍 厚 原 去 县 参 又 又 叉 及 友 双 反 发 叔 取 取 受 变 叙 口 口 古 句 另 叫 叫 召 叭 可 台 史 右 叶 叶 号 司 叹 吃 各 合 合 吉 吊 同 同 名 后 吐 向 吓 吗 君 吝 吟 否 吧 含 吵 吸 吹 吻 吾 呀 呆 呈 告 呐 员 呜 呢 呦 周 味 呵 呼 命 和 咖 咦 咧 咪 咬 咯 咱 哀 品 哇 哇 哈 哉 响 哎 哟 哥 哦 哩 哪 哭 哲 唉 唐 唤 唬 售 唯 唱 唷 商 啊 啡 啥 啦 啪 喀 喂 善 喇 喊 喏 喔 喜 喝 喵 喷 喻 嗒 嗨 嗯 嘉 嘛 嘴 嘻 嘿 器 四 回 因 团 园 困 围 固 国 图 圆 圈 土 圣 在 圭 地 场 圾 址 均 坎 坐 坑 块 坚 坚 坛 坜 坡 坤 坦 坪 垂 垃 型 垒 埃 埋 城 埔 域 培 基 堂 堆 堕 堡 堪 塑 塔 塞 填 境 增 墨 壁 壤 士 壮 声 处 备 复 夏 夕 外 多 夜 夥 大 天 天 太 夫 央 失 头 夷 夷 夸 夹 夺 奇 奇 奈 奉 奋 奏 契 奔 套 奥 女 奴 奶 她 好 如 妇 妈 妖 妙 妥 妨 妮 妹 妻 姆 姊 始 姐 姑 姓 委 姿 威 娃 娄 娘 娜 娟 婆 婚 媒 嫁 嫌 嫩 子 孔 孕 字 字 存 孙 孜 孝 孟 季 孤 学 孩 宁 它 宇 宇 守 安 宋 完 宏 宗 宗 官 宙 定 宛 宜 宝 实 审 审 客 宣 室 宪 害 宴 家 容 宽 宽 宾 宿 寂 寄 密 寇 富 寒 寝 寝 寞 察 寡 寨 寸 对 寻 导 寿 封 射 将 尊 小 少 尔 尖 尘 尚 尝 尤 就 尺 尼 尼 尽 尾 局 局 屁 层 居 屋 屏 展 属 屠 山 岁 岂 岗 岘 岚 岛 岳 岸 峡 峰 崇 崩 崴 川 州 巡 工 工 左 巧 巨 巫 差 己 已 巴 巷 币 币 市 布 帅 师 希 帐 帕 帝 带 席 帮 常 帽 幅 幕 干 干 平 年 幸 幻 幻 幼 幽 广 庆 床 序 库 库 应 底 店 庙 府 庞 废 度 座 庭 康 庸 廉 廖 延 廷 建 开 弃 弄 弊 式 引 弗 弘 弟 张 弥 弦 弯 弱 弹 归 当 彝 形 彩 彬 彭 彰 影 彷 役 彻 彼 往 征 径 待 很 律 後 徐 徒 得 循 微 徵 德 心 必 忆 忌 忍 志 志 忘 忙 忠 忧 快 念 忽 怀 态 怎 怒 怕 怖 思 怡 急 性 怨 怪 总 恋 恐 恢 恨 恩 恭 息 恰 恶 恼 悄 悉 悔 悟 悠 患 您 悲 情 惑 惜 惠 惧 惨 惯 想 惹 愁 愈 愉 意 愚 感 愧 慈 慎 慕 慢 慧 慰 憾 懂 懒 戈 戏 戏 成 我 戒 或 战 截 戴 房 房 所 扁 扇 手 才 扎 扑 打 托 扣 执 扩 扫 扫 扬 扭 扮 扯 批 找 找 承 技 抄 把 抑 抓 投 抗 折 抢 护 报 披 抬 抱 抵 抹 抽 担 拆 拉 拍 拒 拔 拖 拘 招 拜 拟 拥 拦 拨 择 括 拳 拷 拼 拾 拿 持 指 按 挑 挖 挝 挡 挤 挥 挪 振 挺 捉 捐 捕 损 捡 换 捷 授 掉 掌 排 探 接 控 控 推 掩 措 掸 描 提 插 握 援 搜 搞 搬 搭 摄 摆 摊 摔 摘 摩 摸 撒 撞 播 操 擎 擦 支 收 改 攻 放 政 故 效 敌 敏 救 教 敝 敢 散 敦 敬 数 敲 整 文 斋 斐 斗 料 斜 斥 断 斯 新 方 於 施 旁 旅 旋 族 旗 无 既 日 日 旦 旧 旨 早 旭 时 旺 昂 昆 昌 明 昏 易 星 映 春 昨 昭 是 显 晃 晋 晒 晓 晚 晨 普 景 晴 晶 智 暂 暑 暖 暗 暮 暴 曰 曲 更 曹 曼 曾 曾 替 最 月 有 朋 服 朗 望 朝 期 木 未 未 末 本 札 术 朱 朵 杀 杂 权 杉 李 材 村 杜 束 条 来 杨 杯 杰 松 板 极 析 林 果 枝 枢 枪 枫 架 柏 某 染 柔 查 柬 柯 柳 柴 标 栋 栏 树 校 样 样 核 根 格 桃 框 案 桌 桑 档 桥 梁 梅 梦 梯 械 梵 检 棉 棋 棒 棚 森 椅 植 椰 楚 楼 概 榜 模 樱 檀 欠 欠 次 欢 欣 欧 欲 欺 款 歉 歌 止 止 正 此 步 武 歪 死 殊 残 段 毅 母 每 毒 比 毕 毛 毫 氏 民 氛 水 永 求 汉 汗 汝 江 江 池 污 汤 汪 汶 汽 沃 沈 沉 沙 沟 沧 河 油 治 沿 泉 泊 法 泛 泡 泡 波 泣 泥 注 泰 泳 泽 洋 洗 洛 洞 津 洪 洲 活 洽 派 流 浅 测 济 浑 浓 浦 浩 浪 浮 浴 海 涅 消 涉 涛 涨 涯 液 涵 淋 淑 淘 淡 深 混 添 清 渐 渡 渣 温 港 渴 游 湖 湾 源 溜 溪 滋 滑 满 滥 滨 滴 漂 漏 演 漠 漫 潘 潜 潮 澎 澳 激 灌 火 灭 灯 灰 灵 灿 炉 炎 炮 炸 点 烂 烈 烤 烦 烧 热 焦 然 煌 煞 照 煮 熊 熟 燃 燕 爆 爪 爬 爱 爵 爵 父 爷 爸 爽 片 版 牌 牙 牛 牡 牢 牧 物 牲 牵 特 牺 犯 状 犹 狂 狐 狗 狠 独 狮 狱 狼 猛 猜 献 玄 率 玉 王 玛 玩 玫 环 现 玲 玻 珀 珊 珍 珠 班 球 理 琊 琪 琳 琴 琼 瑙 瑜 瑞 瑟 瑰 瑶 璃 瓜 瓦 瓶 甘 甚 甜 生 用 田 田 由 甲 申 电 男 甸 画 畅 界 留 略 番 疆 疏 疑 疗 疯 疲 疼 疾 病 痕 痛 痴 登 白 百 的 皆 皇 皮 盈 益 监 盒 盖 盘 盛 盟 目 直 相 盼 盾 省 眉 看 真 眠 眼 睛 睡 督 瞧 矛 矣 知 短 石 矶 码 砂 砍 研 破 础 硕 硬 碍 碎 碗 碟 碧 碰 磁 磅 磨 示 礼 社 祖 祝 神 祥 票 祸 禁 禅 福 秀 私 秋 种 科 秒 秘 租 秤 秦 秩 积 称 移 稀 程 稍 稣 稳 稿 穆 究 穷 穹 空 穿 突 窗 窝 立 站 竞 竞 竟 章 童 端 竹 笑 笔 笛 符 笨 第 等 筋 答 策 筹 签 简 算 管 箭 箱 篇 篮 簿 籍 米 类 粉 粒 粗 粤 粹 精 糊 糕 糖 糟 系 素 索 紧 紫 累 繁 红 约 级 纪 纯 纲 纳 纵 纷 纸 纽 练 组 细 细 织 终 绍 经 结 绕 绘 给 络 统 继 绩 绪 续 维 绵 综 缅 缓 编 缘 缠 缩 缴 缶 缸 缺 罐 罕 罗 罚 罢 罪 置 署 羊 美 羞 群 羯 羽 翁 翅 翔 翘 翠 翰 翻 翼 耀 老 考 者 而 耍 耐 耗 耳 耶 聊 职 联 聚 聪 肉 肖 肚 股 肤 肥 肩 肯 育 胁 胆 背 胎 胖 胞 胡 胶 胸 能 脆 脑 脱 脸 腊 腐 腓 腰 腹 腾 腿 臂 臣 自 臭 至 致 舌 舍 舒 舞 舟 航 般 舰 船 良 色 艺 艾 节 芒 芝 芦 芬 芭 花 芳 苍 苏 苗 若 苦 英 茂 茨 茫 茶 草 荒 荣 药 荷 莉 莎 莪 莫 莱 莲 获 菜 菩 菲 萄 萍 萤 营 萧 萨 落 著 葛 葡 蒂 蒋 蒙 蓉 蓝 蓬 蔑 蔡 薄 薪 藉 藏 藤 虎 虑 虫 虹 虽 虾 蚁 蛇 蛋 蛙 蛮 蜂 蜜 蝶 融 蟹 蠢 血 行 街 衡 衣 补 表 袋 被 袭 裁 裂 装 裕 裤 西 要 覆 见 观 规 视 览 觉 角 解 言 誉 誓 警 计 订 认 讨 让 训 训 议 讯 记 讲 讷 许 论 设 访 证 评 识 诉 词 译 试 诗 诚 话 诞 询 该 详 语 误 说 请 诸 诺 读 课 谁 调 谅 谈 谊 谋 谓 谜 谢 谨 谱 谷 豆 象 豪 貌 贝 贝 贞 负 贡 贡 财 责 贤 败 货 货 质 贩 贪 购 贯 贱 贴 贵 费 贺 贼 贾 资 赋 赌 赏 赐 赔 赖 赚 赛 赞 赠 赢 赤 赫 走 赵 起 趁 超 越 趋 趣 足 跃 跌 跑 距 跟 路 跳 踏 踢 踩 身 躲 车 轨 轩 转 轮 轮 软 轰 轻 载 较 辅 辆 辈 辉 辑 输 辛 辞 辨 辩 辱 边 达 迁 迅 过 迈 迎 运 近 返 还 这 进 进 远 违 连 迟 迦 迪 迫 述 迷 追 退 送 逃 逆 选 逊 透 逐 递 途 通 逛 逝 速 造 逢 逸 逻 逼 遇 遍 道 遗 遭 遮 遵 避 邀 邓 那 邦 邪 邮 邱 邻 郎 郑 部 郭 都 鄂 酋 配 酒 酷 酸 醉 醒 采 释 里 里 重 野 量 金 针 钓 钟 钢 钦 钱 钻 铁 铃 铢 铭 银 销 锁 锅 锋 错 锡 锦 键 锺 镇 镜 镭 长 门 闪 闭 问 间 闷 闹 闻 阁 阐 阔 队 阮 防 防 阳 阴 阵 阶 阻 阿 陀 附 附 际 陆 陈 降 限 院 除 险 陪 陵 陵 陶 陷 隆 随 隐 隔 障 难 雄 雄 雅 集 雨 雪 雯 雳 零 雷 雾 需 震 霍 霖 露 霸 霹 青 靖 静 非 靠 面 革 靼 鞋 鞑 韦 韩 音 页 顶 项 项 顺 须 顽 顽 顾 顿 预 领 颇 频 颗 题 额 风 飘 飙 飞 食 餐 饭 饮 饰 饱 饼 馆 首 香 馨 马 驱 驶 驻 驾 验 骑 骗 骚 骤 骨 高 鬼 魂 魅 魔 鱼 鲁 鲜 鸟 鸣 鸭 鸿 鹅 鹤 鹰 鹿 麦 麻 黄 黎 黑 默 鼓 鼠 鼻 齐 齿 龄 龙 龟",
+ 3: "侣 傣 卑 厘 吕 堤 奎 巽 录 户 撤 楔 楠 滕 瑚 甫 盲 禄 粟 线 脚 钯 铂 锑 镑 魁",
+ 5: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
+ },
+ "zh_Hant": {
+ 0: "一 丁 七 丈 丈 三 上 下 丌 不 且 世 丘 丙 丟 並 中 串 丸 丹 主 乃 久 么 之 乎 乏 乖 乘 乙 九 也 乾 亂 了 予 事 二 于 云 互 五 井 些 亞 亡 交 亦 亨 享 京 亮 人 什 仁 仇 今 介 仍 仔 他 付 仙 代 代 令 以 仰 仲 件 任 份 企 伊 伍 伐 休 伙 伯 估 伴 伸 似 伽 但 佈 位 位 低 住 佔 何 余 佛 作 你 佩 佳 使 來 例 供 依 侯 侵 便 係 係 促 俄 俊 俗 保 俠 信 修 俱 俾 個 倍 們 倒 候 倚 借 倫 值 假 偉 偏 做 停 健 側 側 偵 偶 偷 傑 備 傢 傣 傲 傳 傷 傻 傾 僅 像 僑 僧 價 儀 億 儒 儘 優 允 元 元 兄 充 兇 兇 先 光 克 免 兒 兔 入 內 內 全 兩 八 八 公 六 兮 共 兵 兵 其 具 典 兼 冊 再 冒 冠 冬 冰 冷 准 凌 凝 凡 凰 凱 出 函 刀 分 切 刊 列 初 判 別 利 刪 到 制 刷 刺 刻 則 前 剛 剩 剪 副 割 創 劃 劇 劉 劍 力 功 加 助 助 努 劫 勁 勇 勉 勒 動 務 勝 勞 勢 勤 勵 勸 勿 包 匈 化 北 匹 區 十 千 升 午 半 卒 卒 卓 協 南 博 卡 印 危 即 卷 卻 厄 厘 厚 原 厭 厲 去 參 又 及 友 反 叔 取 受 口 口 古 句 另 叫 叫 召 叭 可 台 史 右 司 吃 各 合 合 吉 吊 同 同 名 后 吐 向 君 吝 吝 吞 吟 否 吧 含 吳 吵 吸 吹 吾 呀 呂 呆 告 呢 周 味 呵 呼 命 和 咖 咦 咧 咪 咬 咱 哀 品 哇 哇 哈 哉 哎 員 哥 哦 哩 哪 哭 哲 唉 唐 唬 售 唯 唱 唷 唸 商 啊 問 啟 啡 啥 啦 啪 喀 喂 善 喇 喊 喔 喜 喝 喬 單 喵 嗎 嗚 嗨 嗯 嘆 嘉 嘗 嘛 嘴 嘻 嘿 器 噴 嚇 嚴 囉 四 回 因 困 固 圈 國 圍 園 圓 圖 團 圜 土 在 圭 地 圾 址 均 坎 坐 坡 坤 坦 坪 垂 垃 型 埃 城 埔 域 執 培 基 堂 堅 堆 堡 堪 報 場 塊 塔 塗 塞 填 塵 境 增 墨 墮 壁 壓 壘 壞 壢 士 壯 壽 夏 夕 外 多 夜 夠 夢 夥 大 天 天 太 夫 央 失 夷 夸 夾 奇 奇 奈 奉 奎 奏 契 奔 套 奧 奪 奮 女 奴 奶 她 好 如 妙 妥 妨 妮 妳 妹 妻 姆 姊 始 姐 姑 姓 委 姿 威 娃 娘 婁 婆 婚 婦 媒 媽 嫌 嫩 子 孔 字 存 孝 孟 季 孤 孩 孫 學 它 宅 宇 宇 守 安 宋 完 宏 宗 宗 官 宙 定 宛 宜 客 客 宣 室 宮 害 家 容 宿 寂 寄 密 富 寒 寞 察 寢 實 實 寧 寨 審 寫 寬 寮 寶 封 射 將 專 尊 尋 對 對 導 小 少 尖 尚 尤 就 尺 尼 尾 局 屁 居 屆 屋 屏 展 屠 層 屬 山 岡 岩 岸 峰 島 峽 崇 崙 崴 嵐 嶺 川 州 巡 工 工 左 巧 巨 巫 差 己 已 巴 巷 市 布 希 帕 帛 帝 帥 師 席 帳 帶 常 帽 幅 幕 幣 幫 干 干 平 年 幸 幹 幻 幻 幼 幽 幾 庇 床 序 底 店 府 度 座 庫 庭 康 庸 廉 廖 廠 廢 廣 廳 延 廷 建 弄 式 引 弗 弘 弟 弦 弱 張 強 彈 彊 彌 彎 彞 形 彥 彩 彬 彭 彰 影 役 彼 往 征 待 很 律 後 徐 徐 徑 徒 得 從 復 微 徵 德 徹 心 必 忌 忍 志 志 忘 忙 忠 快 念 忽 怎 怒 怕 怖 思 怡 急 性 怨 怪 恆 恐 恢 恥 恨 恩 恭 息 恰 悅 悉 悔 悟 悠 您 悲 悶 情 惑 惜 惠 惡 惱 想 惹 愁 愈 愉 意 愚 愛 感 慈 態 慕 慘 慢 慣 慧 慮 慰 慶 慾 憂 憐 憑 憲 憶 憾 懂 應 懶 懷 懼 戀 戈 成 成 我 戒 或 截 戰 戲 戴 戶 房 房 所 扁 扇 手 才 扎 打 托 扣 扥 扭 扯 批 找 找 承 技 抄 把 抓 投 抗 折 披 抬 抱 抵 抹 抽 拆 拉 拋 拍 拒 拔 拖 招 拜 括 拳 拼 拾 拿 持 指 按 挑 挖 挪 振 挺 捐 捕 捨 捲 捷 掃 授 掉 掌 排 掛 採 探 接 控 推 措 描 提 插 揚 換 握 揮 援 損 搖 搜 搞 搬 搭 搶 摘 摩 摸 撐 撒 撞 撣 撥 播 撾 撿 擁 擇 擊 擋 操 擎 擔 據 擠 擦 擬 擴 擺 擾 攝 支 收 改 攻 放 政 故 效 敍 敏 救 敗 敗 敘 教 敝 敢 散 敦 敬 整 敵 數 文 斐 斗 料 斯 新 斷 方 於 施 旁 旅 旋 族 旗 既 日 旦 早 旭 旺 昂 昆 昇 昌 明 昏 易 星 映 春 昨 昭 是 時 晉 晒 晚 晨 普 景 晴 晶 智 暑 暖 暗 暫 暴 曆 曉 曰 曲 更 書 曼 曾 曾 替 最 會 月 有 朋 服 朗 望 朝 期 木 未 未 末 本 札 朱 朵 杉 李 材 村 杜 束 杯 杯 杰 東 松 板 析 林 果 枝 架 柏 某 染 柔 查 柬 柯 柳 柴 校 核 根 格 桃 案 桌 桑 梁 梅 條 梨 梯 械 梵 棄 棉 棋 棒 棚 森 椅 植 椰 楊 楓 楚 業 極 概 榜 榮 構 槍 樂 樓 標 樞 模 樣 樹 橋 機 橫 檀 檔 檢 欄 權 次 欣 欲 欺 欽 款 歉 歌 歐 歡 歡 止 正 此 步 武 歲 歷 歸 死 殊 殘 段 殺 殼 毀 毅 母 每 毒 比 毛 毫 氏 民 氣 水 永 求 汗 汝 江 江 池 污 汪 汶 決 汽 沃 沈 沉 沒 沖 沙 河 油 治 沿 況 泉 泊 法 泡 波 泥 注 泰 泳 洋 洗 洛 洞 洩 洪 洲 活 洽 派 流 浦 浩 浪 浮 海 涇 涇 消 涉 涯 液 涵 涼 淑 淚 淡 淨 深 混 淺 清 減 渡 測 港 游 湖 湯 源 準 溝 溪 溫 滄 滅 滋 滑 滴 滾 滿 漂 漏 演 漠 漢 漫 漲 漸 潔 潘 潛 潮 澤 澳 激 濃 濟 濤 濫 濱 灌 灣 火 灰 災 炎 炮 炸 為 烈 烏 烤 無 焦 然 煙 煞 照 煩 熊 熟 熱 燃 燈 燒 營 爆 爐 爛 爪 爬 爭 爵 父 爸 爺 爽 爾 牆 牆 片 版 牌 牙 牛 牠 牧 物 牲 特 牽 犧 犯 狀 狂 狐 狗 狠 狼 猛 猜 猶 獄 獅 獎 獨 獲 獸 獻 玄 率 玉 王 玩 玫 玲 玻 珊 珍 珠 班 現 球 理 琉 琪 琴 瑙 瑜 瑞 瑟 瑤 瑪 瑰 環 瓜 瓦 瓶 甘 甚 甜 生 產 用 田 田 由 甲 申 男 甸 界 留 畢 略 番 畫 異 當 疆 疏 疑 疼 病 痕 痛 痴 瘋 療 癡 登 登 發 白 百 的 皆 皇 皮 盃 益 盛 盜 盟 盡 監 盤 盧 目 盲 直 相 盼 盾 省 眉 看 真 眠 眼 眾 睛 睡 督 瞧 瞭 矛 矣 知 短 石 砂 砍 研 砲 破 硬 碎 碗 碟 碧 碩 碰 確 碼 磁 磨 磯 礎 礙 示 社 祕 祖 祝 神 祥 票 禁 禍 福 禪 禮 秀 私 秋 科 秒 秘 租 秤 秦 移 稅 程 稍 種 稱 稿 穆 穌 積 穩 究 穹 空 穿 突 窗 窩 窮 立 站 竟 章 童 端 競 竹 笑 笛 符 笨 第 筆 等 筋 答 策 简 算 管 箭 箱 節 範 篇 築 簡 簫 簽 簿 籃 籌 籍 米 粉 粗 粵 精 糊 糕 糟 系 糾 紀 約 紅 納 紐 純 紙 紙 級 紛 素 索 紫 累 細 紹 終 組 結 絕 絡 給 統 絲 經 綜 綠 維 綱 網 緊 緒 線 緣 編 緩 緬 緯 練 縣 縮 縱 總 績 繁 繆 織 繞 繪 繳 繼 續 缸 缺 罕 罪 置 罰 署 罵 罷 羅 羊 美 羞 群 義 羽 翁 習 翔 翰 翹 翻 翼 耀 老 考 者 而 耍 耐 耗 耳 耶 聊 聖 聚 聞 聯 聰 聲 職 聽 肉 肚 股 肥 肩 肯 育 背 胎 胖 胞 胡 胸 能 脆 脫 腓 腔 腦 腰 腳 腿 膽 臉 臘 臣 臥 臨 自 臭 至 致 臺 與 與 興 舉 舊 舌 舍 舒 舞 舟 航 般 船 艦 良 色 艾 芝 芬 花 芳 若 苦 英 茅 茫 茲 茶 草 荒 荷 莉 莊 莎 莫 菜 菩 華 菲 萄 萊 萬 落 葉 著 葛 葡 蒂 蒙 蒲 蒼 蓋 蓮 蔕 蔡 蔣 蕭 薄 薦 薩 薪 藉 藍 藏 藝 藤 藥 蘆 蘇 蘭 虎 處 虛 號 虧 蛋 蛙 蜂 蜜 蝶 融 螢 蟲 蟹 蠍 蠻 血 行 術 街 衛 衝 衡 衣 表 袋 被 裁 裂 裕 補 裝 裡 製 複 褲 西 要 覆 見 規 視 親 覺 覽 觀 角 解 觸 言 訂 計 訊 討 訓 託 記 訥 訪 設 許 訴 註 証 評 詞 詢 試 詩 話 話 該 詳 誇 誌 認 誓 誕 語 誠 誤 說 誰 課 誼 調 談 請 諒 論 諸 諺 諾 謀 謂 講 謝 證 識 譜 警 譯 議 護 譽 讀 變 讓 讚 谷 豆 豈 豐 象 豪 豬 貌 貓 貝 貞 負 負 財 貢 貨 貪 貪 貫 責 貴 買 費 貼 賀 資 賈 賓 賜 賞 賢 賢 賣 賤 賦 質 賭 賴 賺 購 賽 贈 贊 贏 赤 赫 走 起 超 越 趕 趙 趣 趨 足 跌 跎 跑 距 跟 跡 路 跳 踏 踢 蹟 蹤 躍 身 躲 車 軌 軍 軒 軟 較 載 輔 輕 輛 輝 輩 輪 輯 輸 轉 轟 辛 辦 辨 辭 辯 辱 農 迅 迎 近 迦 迪 迫 述 迴 迷 追 退 送 逃 逆 透 逐 途 這 這 通 逛 逝 速 造 逢 連 週 進 逸 逼 遇 遊 運 遍 過 道 道 達 違 遙 遜 遠 適 遭 遮 遲 遷 選 遺 避 避 邀 邁 還 邊 邏 那 邦 邪 邱 郎 部 郭 郵 都 鄂 鄉 鄭 鄰 配 酒 酷 酸 醉 醒 醜 醫 采 釋 釋 里 重 野 量 金 針 釣 鈴 銀 銖 銘 銳 銷 鋒 鋼 錄 錢 錦 錫 錯 鍋 鍵 鍾 鎊 鎖 鎮 鏡 鐘 鐵 鑑 長 門 閃 閉 開 閒 間 閣 閱 闆 闊 闐 關 闡 防 阻 阿 陀 附 降 限 院 院 陣 除 陪 陰 陳 陵 陵 陶 陷 陸 陽 隆 隊 階 隔 際 障 隨 險 隱 隻 雄 雄 雅 集 雖 雙 雜 雞 離 難 雨 雪 雲 零 雷 電 需 震 霍 霧 露 霸 霹 靂 靈 青 靖 靜 非 靠 面 革 靼 鞋 韃 韋 韓 音 韻 響 頁 頂 項 順 須 預 頑 頓 頗 領 頭 頻 顆 題 額 顏 願 類 顧 顯 風 飄 飛 食 飯 飲 飽 飾 餅 養 餐 餘 館 首 香 馬 駐 駕 駛 騎 騙 騷 驅 驗 驚 骨 體 高 髮 鬆 鬥 鬧 鬱 鬼 魁 魂 魅 魔 魚 魯 鮮 鳥 鳳 鳴 鴻 鵝 鷹 鹿 麗 麥 麵 麻 麼 黃 黎 黑 默 點 黨 鼓 鼠 鼻 齊 齋 齒 齡 龍 龜",
+ 3: "伏 侶 兌 兹 别 勳 卑 占 叶 堤 墎 奥 孜 峇 巽 彝 楔 渾 燦 狄 琳 瑚 甫 礁 芒 苗 茨 蚩 蜀 隴",
+ 5: "一 丁 丈 不 且 丞 並 串 乘 乾 亂 亭 傀 僎 僵 儐 償 儳 儷 儻 叢 嚴 囌 囑 廳",
+ },
+ "zu": {
+ 0: "a b bh c ch d dl dy e f g gc gq gx h hh hl i j k kh kl kp l m n nc ngc ngq ngx nhl nk nkc nkq nkx nq ntsh nx ny o p ph q qh r rh s sh t th tl ts tsh u v w x xh y z",
+ 3: "á à ă â å ä ã ā æ ç é è ĕ ê ë ē í ì ĭ î ï ī ñ ó ò ŏ ô ö ø ō œ ú ù ŭ û ü ū ÿ",
+ 4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
+ },
+}
diff --git a/libgo/go/exp/locale/collate/tools/colcmp/col.go b/libgo/go/exp/locale/collate/tools/colcmp/col.go
new file mode 100644
index 00000000000..26e015cb2f9
--- /dev/null
+++ b/libgo/go/exp/locale/collate/tools/colcmp/col.go
@@ -0,0 +1,95 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "exp/locale/collate"
+ "log"
+ "unicode/utf16"
+)
+
+// Input holds an input string in both UTF-8 and UTF-16 format.
+type Input struct {
+ index int // used for restoring to original random order
+ UTF8 []byte
+ UTF16 []uint16
+ key []byte // used for sorting
+}
+
+func (i Input) String() string {
+ return string(i.UTF8)
+}
+
+func makeInput(s8 []byte, s16 []uint16) Input {
+ return Input{UTF8: s8, UTF16: s16}
+}
+
+func makeInputString(s string) Input {
+ return Input{
+ UTF8: []byte(s),
+ UTF16: utf16.Encode([]rune(s)),
+ }
+}
+
+// Collator is an interface for architecture-specific implementations of collation.
+type Collator interface {
+ // Key generates a sort key for the given input. Implemenations
+ // may return nil if a collator does not support sort keys.
+ Key(s Input) []byte
+
+ // Compare returns -1 if a < b, 1 if a > b and 0 if a == b.
+ Compare(a, b Input) int
+}
+
+// CollatorFactory creates a Collator for a given locale.
+type CollatorFactory struct {
+ name string
+ makeFn func(locale string) (Collator, error)
+ description string
+}
+
+var collators = []CollatorFactory{}
+
+// AddFactory registers f as a factory for an implementation of Collator.
+func AddFactory(f CollatorFactory) {
+ collators = append(collators, f)
+}
+
+func getCollator(name, locale string) Collator {
+ for _, f := range collators {
+ if f.name == name {
+ col, err := f.makeFn(locale)
+ if err != nil {
+ log.Fatal(err)
+ }
+ return col
+ }
+ }
+ log.Fatalf("collator of type %q not found", name)
+ return nil
+}
+
+// goCollator is an implemention of Collator using go's own collator.
+type goCollator struct {
+ c *collate.Collator
+ buf collate.Buffer
+}
+
+func init() {
+ AddFactory(CollatorFactory{"go", newGoCollator, "Go's native collator implementation."})
+}
+
+func newGoCollator(locale string) (Collator, error) {
+ c := &goCollator{c: collate.New(locale)}
+ return c, nil
+}
+
+func (c *goCollator) Key(b Input) []byte {
+ return c.c.Key(&c.buf, b.UTF8)
+}
+
+func (c *goCollator) Compare(a, b Input) int {
+ return c.c.Compare(&c.buf, a.UTF8, b.UTF8)
+}
diff --git a/libgo/go/exp/locale/collate/tools/colcmp/colcmp.go b/libgo/go/exp/locale/collate/tools/colcmp/colcmp.go
new file mode 100644
index 00000000000..61c90b55086
--- /dev/null
+++ b/libgo/go/exp/locale/collate/tools/colcmp/colcmp.go
@@ -0,0 +1,528 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "exp/norm"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "runtime/pprof"
+ "sort"
+ "strconv"
+ "strings"
+ "text/template"
+ "time"
+)
+
+var (
+ doNorm = flag.Bool("norm", false, "normalize input strings")
+ cases = flag.Bool("case", false, "generate case variants")
+ verbose = flag.Bool("verbose", false, "print results")
+ debug = flag.Bool("debug", false, "output debug information")
+ locale = flag.String("locale", "en_US", "the locale to use. May be a comma-separated list for some commands.")
+ col = flag.String("col", "go", "collator to test")
+ gold = flag.String("gold", "go", "collator used as the gold standard")
+ usecmp = flag.Bool("usecmp", false,
+ `use comparison instead of sort keys when sorting. Must be "test", "gold" or "both"`)
+ cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
+ exclude = flag.String("exclude", "", "exclude errors that contain any of the characters")
+ limit = flag.Int("limit", 5000000, "maximum number of samples to generate for one run")
+)
+
+func failOnError(err error) {
+ if err != nil {
+ log.Panic(err)
+ }
+}
+
+// Test holds test data for testing a locale-collator pair.
+// Test also provides functionality that is commonly used by the various commands.
+type Test struct {
+ ctxt *Context
+ Name string
+ Locale string
+ ColName string
+
+ Col Collator
+ UseCompare bool
+
+ Input []Input
+ Duration time.Duration
+
+ start time.Time
+ msg string
+ count int
+}
+
+func (t *Test) clear() {
+ t.Col = nil
+ t.Input = nil
+}
+
+const (
+ msgGeneratingInput = "generating input"
+ msgGeneratingKeys = "generating keys"
+ msgSorting = "sorting"
+)
+
+var lastLen = 0
+
+func (t *Test) SetStatus(msg string) {
+ if *debug || *verbose {
+ fmt.Printf("%s: %s...\n", t.Name, msg)
+ } else if t.ctxt.out != nil {
+ fmt.Fprint(t.ctxt.out, strings.Repeat(" ", lastLen))
+ fmt.Fprint(t.ctxt.out, strings.Repeat("\b", lastLen))
+ fmt.Fprint(t.ctxt.out, msg, "...")
+ lastLen = len(msg) + 3
+ fmt.Fprint(t.ctxt.out, strings.Repeat("\b", lastLen))
+ }
+}
+
+// Start is used by commands to signal the start of an operation.
+func (t *Test) Start(msg string) {
+ t.SetStatus(msg)
+ t.count = 0
+ t.msg = msg
+ t.start = time.Now()
+}
+
+// Stop is used by commands to signal the end of an operation.
+func (t *Test) Stop() (time.Duration, int) {
+ d := time.Now().Sub(t.start)
+ t.Duration += d
+ if *debug || *verbose {
+ fmt.Printf("%s: %s done. (%.3fs /%dK ops)\n", t.Name, t.msg, d.Seconds(), t.count/1000)
+ }
+ return d, t.count
+}
+
+// generateKeys generates sort keys for all the inputs.
+func (t *Test) generateKeys() {
+ for i, s := range t.Input {
+ b := t.Col.Key(s)
+ t.Input[i].key = b
+ if *debug {
+ fmt.Printf("%s (%X): %X\n", string(s.UTF8), s.UTF16, b)
+ }
+ }
+}
+
+// Sort sorts the inputs. It generates sort keys if this is required by the
+// chosen sort method.
+func (t *Test) Sort() (tkey, tsort time.Duration, nkey, nsort int) {
+ if *cpuprofile != "" {
+ f, err := os.Create(*cpuprofile)
+ failOnError(err)
+ pprof.StartCPUProfile(f)
+ defer pprof.StopCPUProfile()
+ }
+ if t.UseCompare || t.Col.Key(t.Input[0]) == nil {
+ t.Start(msgSorting)
+ sort.Sort(&testCompare{*t})
+ tsort, nsort = t.Stop()
+ } else {
+ t.Start(msgGeneratingKeys)
+ t.generateKeys()
+ t.count = len(t.Input)
+ tkey, nkey = t.Stop()
+ t.Start(msgSorting)
+ sort.Sort(t)
+ tsort, nsort = t.Stop()
+ }
+ return
+}
+
+func (t *Test) Swap(a, b int) {
+ t.Input[a], t.Input[b] = t.Input[b], t.Input[a]
+}
+
+func (t *Test) Less(a, b int) bool {
+ t.count++
+ return bytes.Compare(t.Input[a].key, t.Input[b].key) == -1
+}
+
+func (t Test) Len() int {
+ return len(t.Input)
+}
+
+type testCompare struct {
+ Test
+}
+
+func (t *testCompare) Less(a, b int) bool {
+ t.count++
+ return t.Col.Compare(t.Input[a], t.Input[b]) == -1
+}
+
+type testRestore struct {
+ Test
+}
+
+func (t *testRestore) Less(a, b int) bool {
+ return t.Input[a].index < t.Input[b].index
+}
+
+// GenerateInput generates input phrases for the locale tested by t.
+func (t *Test) GenerateInput() {
+ t.Input = nil
+ if t.ctxt.lastLocale != t.Locale {
+ gen := phraseGenerator{}
+ gen.init(t.Locale)
+ t.SetStatus(msgGeneratingInput)
+ t.ctxt.lastInput = nil // allow the previous value to be garbage collected.
+ t.Input = gen.generate(*doNorm)
+ t.ctxt.lastInput = t.Input
+ t.ctxt.lastLocale = t.Locale
+ } else {
+ t.Input = t.ctxt.lastInput
+ for i := range t.Input {
+ t.Input[i].key = nil
+ }
+ sort.Sort(&testRestore{*t})
+ }
+}
+
+// Context holds all tests and settings translated from command line options.
+type Context struct {
+ test []*Test
+ last *Test
+
+ lastLocale string
+ lastInput []Input
+
+ out io.Writer
+}
+
+func (ts *Context) Printf(format string, a ...interface{}) {
+ ts.assertBuf()
+ fmt.Fprintf(ts.out, format, a...)
+}
+
+func (ts *Context) Print(a ...interface{}) {
+ ts.assertBuf()
+ fmt.Fprint(ts.out, a...)
+}
+
+// assertBuf sets up an io.Writer for ouput, if it doesn't already exist.
+// In debug and verbose mode, output is buffered so that the regular output
+// will not interfere with the additional output. Otherwise, output is
+// written directly to stdout for a more responsive feel.
+func (ts *Context) assertBuf() {
+ if ts.out != nil {
+ return
+ }
+ if *debug || *verbose {
+ ts.out = &bytes.Buffer{}
+ } else {
+ ts.out = os.Stdout
+ }
+}
+
+// flush flushes the contents of ts.out to stdout, if it is not stdout already.
+func (ts *Context) flush() {
+ if ts.out != nil {
+ if _, ok := ts.out.(io.ReadCloser); !ok {
+ io.Copy(os.Stdout, ts.out.(io.Reader))
+ }
+ }
+}
+
+// parseTests creates all tests from command lines and returns
+// a Context to hold them.
+func parseTests() *Context {
+ ctxt := &Context{}
+ colls := strings.Split(*col, ",")
+ for _, loc := range strings.Split(*locale, ",") {
+ loc = strings.TrimSpace(loc)
+ for _, name := range colls {
+ name = strings.TrimSpace(name)
+ col := getCollator(name, loc)
+ ctxt.test = append(ctxt.test, &Test{
+ ctxt: ctxt,
+ Locale: loc,
+ ColName: name,
+ UseCompare: *usecmp,
+ Col: col,
+ })
+ }
+ }
+ return ctxt
+}
+
+func (c *Context) Len() int {
+ return len(c.test)
+}
+
+func (c *Context) Test(i int) *Test {
+ if c.last != nil {
+ c.last.clear()
+ }
+ c.last = c.test[i]
+ return c.last
+}
+
+func parseInput(args []string) []Input {
+ input := []Input{}
+ for _, s := range args {
+ rs := []rune{}
+ for len(s) > 0 {
+ var r rune
+ r, _, s, _ = strconv.UnquoteChar(s, '\'')
+ rs = append(rs, r)
+ }
+ s = string(rs)
+ if *doNorm {
+ s = norm.NFC.String(s)
+ }
+ input = append(input, makeInputString(s))
+ }
+ return input
+}
+
+// A Command is an implementation of a colcmp command.
+type Command struct {
+ Run func(cmd *Context, args []string)
+ Usage string
+ Short string
+ Long string
+}
+
+func (cmd Command) Name() string {
+ return strings.SplitN(cmd.Usage, " ", 2)[0]
+}
+
+var commands = []*Command{
+ cmdSort,
+ cmdBench,
+ cmdRegress,
+}
+
+const sortHelp = `
+Sort sorts a given list of strings. Strings are separated by whitespace.
+`
+
+var cmdSort = &Command{
+ Run: runSort,
+ Usage: "sort <string>*",
+ Short: "sort a given list of strings",
+ Long: sortHelp,
+}
+
+func runSort(ctxt *Context, args []string) {
+ input := parseInput(args)
+ if len(input) == 0 {
+ log.Fatalf("Nothing to sort.")
+ }
+ if ctxt.Len() > 1 {
+ ctxt.Print("COLL LOCALE RESULT\n")
+ }
+ for i := 0; i < ctxt.Len(); i++ {
+ t := ctxt.Test(i)
+ t.Input = append(t.Input, input...)
+ t.Sort()
+ if ctxt.Len() > 1 {
+ ctxt.Printf("%-5s %-5s ", t.ColName, t.Locale)
+ }
+ for _, s := range t.Input {
+ ctxt.Print(string(s.UTF8), " ")
+ }
+ ctxt.Print("\n")
+ }
+}
+
+const benchHelp = `
+Bench runs a benchmark for the given list of collator implementations.
+If no collator implementations are given, the go collator will be used.
+`
+
+var cmdBench = &Command{
+ Run: runBench,
+ Usage: "bench",
+ Short: "benchmark a given list of collator implementations",
+ Long: benchHelp,
+}
+
+func runBench(ctxt *Context, args []string) {
+ ctxt.Printf("%-7s %-5s %-6s %-24s %-24s %-5s %s\n", "LOCALE", "COLL", "N", "KEYS", "SORT", "AVGLN", "TOTAL")
+ for i := 0; i < ctxt.Len(); i++ {
+ t := ctxt.Test(i)
+ ctxt.Printf("%-7s %-5s ", t.Locale, t.ColName)
+ t.GenerateInput()
+ ctxt.Printf("%-6s ", fmt.Sprintf("%dK", t.Len()/1000))
+ tkey, tsort, nkey, nsort := t.Sort()
+ p := func(dur time.Duration, n int) {
+ s := ""
+ if dur > 0 {
+ s = fmt.Sprintf("%6.3fs ", dur.Seconds())
+ if n > 0 {
+ s += fmt.Sprintf("%15s", fmt.Sprintf("(%4.2f ns/op)", float64(dur)/float64(n)))
+ }
+ }
+ ctxt.Printf("%-24s ", s)
+ }
+ p(tkey, nkey)
+ p(tsort, nsort)
+
+ total := 0
+ for _, s := range t.Input {
+ total += len(s.key)
+ }
+ ctxt.Printf("%-5d ", total/t.Len())
+ ctxt.Printf("%6.3fs\n", t.Duration.Seconds())
+ if *debug {
+ for _, s := range t.Input {
+ fmt.Print(string(s.UTF8), " ")
+ }
+ fmt.Println()
+ }
+ }
+}
+
+const regressHelp = `
+Regress runs a monkey test by comparing the results of randomly generated tests
+between two implementations of a collator. The user may optionally pass a list
+of strings to regress against instead of the default test set.
+`
+
+var cmdRegress = &Command{
+ Run: runRegress,
+ Usage: "regress -gold=<col> -test=<col> [string]*",
+ Short: "run a monkey test between two collators",
+ Long: regressHelp,
+}
+
+const failedKeyCompare = `
+%d: incorrect comparison result for input:
+ a: %q (%.4X)
+ key: %s
+ b: %q (%.4X)
+ key: %s
+ Compare(a, b) = %d; want %d.
+
+ gold keys:
+ a: %s
+ b: %s
+`
+
+const failedCompare = `
+%d: incorrect comparison result for input:
+ a: %q (%.4X)
+ b: %q (%.4X)
+ Compare(a, b) = %d; want %d.
+`
+
+func keyStr(b []byte) string {
+ buf := &bytes.Buffer{}
+ for _, v := range b {
+ fmt.Fprintf(buf, "%.2X ", v)
+ }
+ return buf.String()
+}
+
+func runRegress(ctxt *Context, args []string) {
+ input := parseInput(args)
+ for i := 0; i < ctxt.Len(); i++ {
+ t := ctxt.Test(i)
+ if len(input) > 0 {
+ t.Input = append(t.Input, input...)
+ } else {
+ t.GenerateInput()
+ }
+ t.Sort()
+ count := 0
+ gold := getCollator(*gold, t.Locale)
+ for i := 1; i < len(t.Input); i++ {
+ ia := t.Input[i-1]
+ ib := t.Input[i]
+ if bytes.IndexAny(ib.UTF8, *exclude) != -1 {
+ i++
+ continue
+ }
+ if bytes.IndexAny(ia.UTF8, *exclude) != -1 {
+ continue
+ }
+ goldCmp := gold.Compare(ia, ib)
+ if cmp := bytes.Compare(ia.key, ib.key); cmp != goldCmp {
+ count++
+ a := string(ia.UTF8)
+ b := string(ib.UTF8)
+ fmt.Printf(failedKeyCompare, i-1, a, []rune(a), keyStr(ia.key), b, []rune(b), keyStr(ib.key), cmp, goldCmp, keyStr(gold.Key(ia)), keyStr(gold.Key(ib)))
+ } else if cmp := t.Col.Compare(ia, ib); cmp != goldCmp {
+ count++
+ a := string(ia.UTF8)
+ b := string(ib.UTF8)
+ fmt.Printf(failedKeyCompare, i-1, a, []rune(a), b, []rune(b), cmp, goldCmp)
+ }
+ }
+ if count > 0 {
+ ctxt.Printf("Found %d inconsistencies in %d entries.\n", count, t.Len()-1)
+ }
+ }
+}
+
+const helpTemplate = `
+colcmp is a tool for testing and benchmarking collation
+
+Usage: colcmp command [arguments]
+
+The commands are:
+{{range .}}
+ {{.Name | printf "%-11s"}} {{.Short}}{{end}}
+
+Use "col help [topic]" for more information about that topic.
+`
+
+const detailedHelpTemplate = `
+Usage: colcmp {{.Usage}}
+
+{{.Long | trim}}
+`
+
+func runHelp(args []string) {
+ t := template.New("help")
+ t.Funcs(template.FuncMap{"trim": strings.TrimSpace})
+ if len(args) < 1 {
+ template.Must(t.Parse(helpTemplate))
+ failOnError(t.Execute(os.Stderr, &commands))
+ } else {
+ for _, cmd := range commands {
+ if cmd.Name() == args[0] {
+ template.Must(t.Parse(detailedHelpTemplate))
+ failOnError(t.Execute(os.Stderr, cmd))
+ os.Exit(0)
+ }
+ }
+ log.Fatalf("Unknown command %q. Run 'colcmp help'.", args[0])
+ }
+ os.Exit(0)
+}
+
+func main() {
+ flag.Parse()
+ log.SetFlags(0)
+
+ ctxt := parseTests()
+
+ if flag.NArg() < 1 {
+ runHelp(nil)
+ }
+ args := flag.Args()[1:]
+ if flag.Arg(0) == "help" {
+ runHelp(args)
+ }
+ for _, cmd := range commands {
+ if cmd.Name() == flag.Arg(0) {
+ cmd.Run(ctxt, args)
+ ctxt.flush()
+ return
+ }
+ }
+ runHelp(flag.Args())
+}
diff --git a/libgo/go/exp/locale/collate/tools/colcmp/darwin.go b/libgo/go/exp/locale/collate/tools/colcmp/darwin.go
new file mode 100644
index 00000000000..ce2ab468b19
--- /dev/null
+++ b/libgo/go/exp/locale/collate/tools/colcmp/darwin.go
@@ -0,0 +1,111 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin
+
+package main
+
+/*
+#cgo LDFLAGS: -framework CoreFoundation
+#include <CoreFoundation/CFBase.h>
+#include <CoreFoundation/CoreFoundation.h>
+*/
+import "C"
+import (
+ "unsafe"
+)
+
+func init() {
+ AddFactory(CollatorFactory{"osx", newOSX16Collator,
+ "OS X/Darwin collator, using native strings."})
+ AddFactory(CollatorFactory{"osx8", newOSX8Collator,
+ "OS X/Darwin collator for UTF-8."})
+}
+
+func osxUInt8P(s []byte) *C.UInt8 {
+ return (*C.UInt8)(unsafe.Pointer(&s[0]))
+}
+
+func osxCharP(s []uint16) *C.UniChar {
+ return (*C.UniChar)(unsafe.Pointer(&s[0]))
+}
+
+// osxCollator implements an Collator based on OS X's CoreFoundation.
+type osxCollator struct {
+ loc C.CFLocaleRef
+ opt C.CFStringCompareFlags
+}
+
+func (c *osxCollator) init(locale string) {
+ l := C.CFStringCreateWithBytes(
+ nil,
+ osxUInt8P([]byte(locale)),
+ C.CFIndex(len(locale)),
+ C.kCFStringEncodingUTF8,
+ C.Boolean(0),
+ )
+ c.loc = C.CFLocaleCreate(nil, l)
+}
+
+func newOSX8Collator(locale string) (Collator, error) {
+ c := &osx8Collator{}
+ c.init(locale)
+ return c, nil
+}
+
+func newOSX16Collator(locale string) (Collator, error) {
+ c := &osx16Collator{}
+ c.init(locale)
+ return c, nil
+}
+
+func (c osxCollator) Key(s Input) []byte {
+ return nil // sort keys not supported by OS X CoreFoundation
+}
+
+type osx8Collator struct {
+ osxCollator
+}
+
+type osx16Collator struct {
+ osxCollator
+}
+
+func (c osx16Collator) Compare(a, b Input) int {
+ sa := C.CFStringCreateWithCharactersNoCopy(
+ nil,
+ osxCharP(a.UTF16),
+ C.CFIndex(len(a.UTF16)),
+ C.kCFAllocatorNull,
+ )
+ sb := C.CFStringCreateWithCharactersNoCopy(
+ nil,
+ osxCharP(b.UTF16),
+ C.CFIndex(len(b.UTF16)),
+ C.kCFAllocatorNull,
+ )
+ _range := C.CFRangeMake(0, C.CFStringGetLength(sa))
+ return int(C.CFStringCompareWithOptionsAndLocale(sa, sb, _range, c.opt, c.loc))
+}
+
+func (c osx8Collator) Compare(a, b Input) int {
+ sa := C.CFStringCreateWithBytesNoCopy(
+ nil,
+ osxUInt8P(a.UTF8),
+ C.CFIndex(len(a.UTF8)),
+ C.kCFStringEncodingUTF8,
+ C.Boolean(0),
+ C.kCFAllocatorNull,
+ )
+ sb := C.CFStringCreateWithBytesNoCopy(
+ nil,
+ osxUInt8P(b.UTF8),
+ C.CFIndex(len(b.UTF8)),
+ C.kCFStringEncodingUTF8,
+ C.Boolean(0),
+ C.kCFAllocatorNull,
+ )
+ _range := C.CFRangeMake(0, C.CFStringGetLength(sa))
+ return int(C.CFStringCompareWithOptionsAndLocale(sa, sb, _range, c.opt, c.loc))
+}
diff --git a/libgo/go/exp/locale/collate/tools/colcmp/gen.go b/libgo/go/exp/locale/collate/tools/colcmp/gen.go
new file mode 100644
index 00000000000..f9e31187de1
--- /dev/null
+++ b/libgo/go/exp/locale/collate/tools/colcmp/gen.go
@@ -0,0 +1,179 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "exp/norm"
+ "math"
+ "math/rand"
+ "strings"
+ "unicode"
+ "unicode/utf16"
+ "unicode/utf8"
+)
+
+// parent computes the parent locale for the given locale.
+// It returns false if the parent is already root.
+func parent(locale string) (parent string, ok bool) {
+ if locale == "root" {
+ return "", false
+ }
+ if i := strings.LastIndex(locale, "_"); i != -1 {
+ return locale[:i], true
+ }
+ return "root", true
+}
+
+// rewriter is used to both unique strings and create variants of strings
+// to add to the test set.
+type rewriter struct {
+ seen map[string]bool
+ addCases bool
+}
+
+func newRewriter() *rewriter {
+ return &rewriter{
+ seen: make(map[string]bool),
+ }
+}
+
+func (r *rewriter) insert(a []string, s string) []string {
+ if !r.seen[s] {
+ r.seen[s] = true
+ a = append(a, s)
+ }
+ return a
+}
+
+// rewrite takes a sequence of strings in, adds variants of the these strings
+// based on options and removes duplicates.
+func (r *rewriter) rewrite(ss []string) []string {
+ ns := []string{}
+ for _, s := range ss {
+ ns = r.insert(ns, s)
+ if r.addCases {
+ rs := []rune(s)
+ rn := rs[0]
+ for c := unicode.SimpleFold(rn); c != rn; c = unicode.SimpleFold(c) {
+ rs[0] = c
+ ns = r.insert(ns, string(rs))
+ }
+ }
+ }
+ return ns
+}
+
+// exemplarySet holds a parsed set of characters from the exemplarCharacters table.
+type exemplarySet struct {
+ typ exemplarType
+ set []string
+ charIndex int // cumulative total of phrases, including this set
+}
+
+type phraseGenerator struct {
+ sets [exN]exemplarySet
+ n int
+}
+
+func (g *phraseGenerator) init(locale string) {
+ ec := exemplarCharacters
+ // get sets for locale or parent locale if the set is not defined.
+ for i := range g.sets {
+ for p, ok := locale, true; ok; p, ok = parent(p) {
+ if set, ok := ec[p]; ok && set[i] != "" {
+ g.sets[i].set = strings.Split(set[i], " ")
+ break
+ }
+ }
+ }
+ r := newRewriter()
+ r.addCases = *cases
+ for i := range g.sets {
+ g.sets[i].set = r.rewrite(g.sets[i].set)
+ }
+ // compute indexes
+ for i, set := range g.sets {
+ g.n += len(set.set)
+ g.sets[i].charIndex = g.n
+ }
+}
+
+// phrase returns the ith phrase, where i < g.n.
+func (g *phraseGenerator) phrase(i int) string {
+ for _, set := range g.sets {
+ if i < set.charIndex {
+ return set.set[i-(set.charIndex-len(set.set))]
+ }
+ }
+ panic("index out of range")
+}
+
+// generate generates inputs by combining all pairs of examplar strings.
+// If doNorm is true, all input strings are normalized to NFC.
+// TODO: allow other variations, statistical models, and random
+// trailing sequences.
+func (g *phraseGenerator) generate(doNorm bool) []Input {
+ const (
+ M = 1024 * 1024
+ buf8Size = 30 * M
+ buf16Size = 10 * M
+ )
+ // TODO: use a better way to limit the input size.
+ if sq := int(math.Sqrt(float64(*limit))); g.n > sq {
+ g.n = sq
+ }
+ size := g.n * g.n
+ a := make([]Input, 0, size)
+ buf8 := make([]byte, 0, buf8Size)
+ buf16 := make([]uint16, 0, buf16Size)
+
+ addInput := func(str string) {
+ buf8 = buf8[len(buf8):]
+ buf16 = buf16[len(buf16):]
+ if len(str) > cap(buf8) {
+ buf8 = make([]byte, 0, buf8Size)
+ }
+ if len(str) > cap(buf16) {
+ buf16 = make([]uint16, 0, buf16Size)
+ }
+ if doNorm {
+ buf8 = norm.NFC.AppendString(buf8, str)
+ } else {
+ buf8 = append(buf8, str...)
+ }
+ buf16 = appendUTF16(buf16, buf8)
+ a = append(a, makeInput(buf8, buf16))
+ }
+ for i := 0; i < g.n; i++ {
+ p1 := g.phrase(i)
+ addInput(p1)
+ for j := 0; j < g.n; j++ {
+ p2 := g.phrase(j)
+ addInput(p1 + p2)
+ }
+ }
+ // permutate
+ rnd := rand.New(rand.NewSource(int64(rand.Int())))
+ for i := range a {
+ j := i + rnd.Intn(len(a)-i)
+ a[i], a[j] = a[j], a[i]
+ a[i].index = i // allow restoring this order if input is used multiple times.
+ }
+ return a
+}
+
+func appendUTF16(buf []uint16, s []byte) []uint16 {
+ for len(s) > 0 {
+ r, sz := utf8.DecodeRune(s)
+ s = s[sz:]
+ r1, r2 := utf16.EncodeRune(r)
+ if r1 != 0xFFFD {
+ buf = append(buf, uint16(r1), uint16(r2))
+ } else {
+ buf = append(buf, uint16(r))
+ }
+ }
+ return buf
+}
diff --git a/libgo/go/exp/locale/collate/tools/colcmp/icu.go b/libgo/go/exp/locale/collate/tools/colcmp/icu.go
new file mode 100644
index 00000000000..91980ac98fd
--- /dev/null
+++ b/libgo/go/exp/locale/collate/tools/colcmp/icu.go
@@ -0,0 +1,209 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build icu
+
+package main
+
+/*
+#cgo LDFLAGS: -licui18n -licuuc
+#include <stdlib.h>
+#include <unicode/ucol.h>
+#include <unicode/uiter.h>
+#include <unicode/utypes.h>
+*/
+import "C"
+import (
+ "fmt"
+ "log"
+ "unicode/utf16"
+ "unicode/utf8"
+ "unsafe"
+)
+
+func init() {
+ AddFactory(CollatorFactory{"icu", newUTF16,
+ "Main ICU collator, using native strings."})
+ AddFactory(CollatorFactory{"icu8", newUTF8iter,
+ "ICU collator using ICU iterators to process UTF8."})
+ AddFactory(CollatorFactory{"icu16", newUTF8conv,
+ "ICU collation by first converting UTF8 to UTF16."})
+}
+
+func icuCharP(s []byte) *C.char {
+ return (*C.char)(unsafe.Pointer(&s[0]))
+}
+
+func icuUInt8P(s []byte) *C.uint8_t {
+ return (*C.uint8_t)(unsafe.Pointer(&s[0]))
+}
+
+func icuUCharP(s []uint16) *C.UChar {
+ return (*C.UChar)(unsafe.Pointer(&s[0]))
+}
+func icuULen(s []uint16) C.int32_t {
+ return C.int32_t(len(s))
+}
+func icuSLen(s []byte) C.int32_t {
+ return C.int32_t(len(s))
+}
+
+// icuCollator implements a Collator based on ICU.
+type icuCollator struct {
+ loc *C.char
+ col *C.UCollator
+ keyBuf []byte
+}
+
+const growBufSize = 10 * 1024 * 1024
+
+func (c *icuCollator) init(locale string) error {
+ err := C.UErrorCode(0)
+ c.loc = C.CString(locale)
+ c.col = C.ucol_open(c.loc, &err)
+ if err > 0 {
+ return fmt.Errorf("failed opening collator for %q", locale)
+ } else if err < 0 {
+ loc := C.ucol_getLocaleByType(c.col, 0, &err)
+ fmt, ok := map[int]string{
+ -127: "warning: using default collator: %s",
+ -128: "warning: using fallback collator: %s",
+ }[int(err)]
+ if ok {
+ log.Printf(fmt, C.GoString(loc))
+ }
+ }
+ c.keyBuf = make([]byte, 0, growBufSize)
+ return nil
+}
+
+func (c *icuCollator) buf() (*C.uint8_t, C.int32_t) {
+ if len(c.keyBuf) == cap(c.keyBuf) {
+ c.keyBuf = make([]byte, 0, growBufSize)
+ }
+ b := c.keyBuf[len(c.keyBuf):cap(c.keyBuf)]
+ return icuUInt8P(b), icuSLen(b)
+}
+
+func (c *icuCollator) extendBuf(n C.int32_t) []byte {
+ end := len(c.keyBuf) + int(n)
+ if end > cap(c.keyBuf) {
+ if len(c.keyBuf) == 0 {
+ log.Fatalf("icuCollator: max string size exceeded: %v > %v", n, growBufSize)
+ }
+ c.keyBuf = make([]byte, 0, growBufSize)
+ return nil
+ }
+ b := c.keyBuf[len(c.keyBuf):end]
+ c.keyBuf = c.keyBuf[:end]
+ return b
+}
+
+func (c *icuCollator) Close() error {
+ C.ucol_close(c.col)
+ C.free(unsafe.Pointer(c.loc))
+ return nil
+}
+
+// icuUTF16 implements the Collator interface.
+type icuUTF16 struct {
+ icuCollator
+}
+
+func newUTF16(locale string) (Collator, error) {
+ c := &icuUTF16{}
+ return c, c.init(locale)
+}
+
+func (c *icuUTF16) Compare(a, b Input) int {
+ return int(C.ucol_strcoll(c.col, icuUCharP(a.UTF16), icuULen(a.UTF16), icuUCharP(b.UTF16), icuULen(b.UTF16)))
+}
+
+func (c *icuUTF16) Key(s Input) []byte {
+ bp, bn := c.buf()
+ n := C.ucol_getSortKey(c.col, icuUCharP(s.UTF16), icuULen(s.UTF16), bp, bn)
+ if b := c.extendBuf(n); b != nil {
+ return b
+ }
+ return c.Key(s)
+}
+
+// icuUTF8iter implements the Collator interface
+// This implementation wraps the UTF8 string in an iterator
+// which is passed to the collator.
+type icuUTF8iter struct {
+ icuCollator
+ a, b C.UCharIterator
+}
+
+func newUTF8iter(locale string) (Collator, error) {
+ c := &icuUTF8iter{}
+ return c, c.init(locale)
+}
+
+func (c *icuUTF8iter) Compare(a, b Input) int {
+ err := C.UErrorCode(0)
+ C.uiter_setUTF8(&c.a, icuCharP(a.UTF8), icuSLen(a.UTF8))
+ C.uiter_setUTF8(&c.b, icuCharP(b.UTF8), icuSLen(b.UTF8))
+ return int(C.ucol_strcollIter(c.col, &c.a, &c.b, &err))
+}
+
+func (c *icuUTF8iter) Key(s Input) []byte {
+ err := C.UErrorCode(0)
+ state := [2]C.uint32_t{}
+ C.uiter_setUTF8(&c.a, icuCharP(s.UTF8), icuSLen(s.UTF8))
+ bp, bn := c.buf()
+ n := C.ucol_nextSortKeyPart(c.col, &c.a, &(state[0]), bp, bn, &err)
+ if n >= bn {
+ // Force failure.
+ if c.extendBuf(n+1) != nil {
+ log.Fatal("expected extension to fail")
+ }
+ return c.Key(s)
+ }
+ return c.extendBuf(n)
+}
+
+// icuUTF8conv implementes the Collator interface.
+// This implentation first converts the give UTF8 string
+// to UTF16 and then calls the main ICU collation function.
+type icuUTF8conv struct {
+ icuCollator
+}
+
+func newUTF8conv(locale string) (Collator, error) {
+ c := &icuUTF8conv{}
+ return c, c.init(locale)
+}
+
+func (c *icuUTF8conv) Compare(sa, sb Input) int {
+ a := encodeUTF16(sa.UTF8)
+ b := encodeUTF16(sb.UTF8)
+ return int(C.ucol_strcoll(c.col, icuUCharP(a), icuULen(a), icuUCharP(b), icuULen(b)))
+}
+
+func (c *icuUTF8conv) Key(s Input) []byte {
+ a := encodeUTF16(s.UTF8)
+ bp, bn := c.buf()
+ n := C.ucol_getSortKey(c.col, icuUCharP(a), icuULen(a), bp, bn)
+ if b := c.extendBuf(n); b != nil {
+ return b
+ }
+ return c.Key(s)
+}
+
+func encodeUTF16(b []byte) []uint16 {
+ a := []uint16{}
+ for len(b) > 0 {
+ r, sz := utf8.DecodeRune(b)
+ b = b[sz:]
+ r1, r2 := utf16.EncodeRune(r)
+ if r1 != 0xFFFD {
+ a = append(a, uint16(r1), uint16(r2))
+ } else {
+ a = append(a, uint16(r))
+ }
+ }
+ return a
+}
diff --git a/libgo/go/exp/locale/collate/trie.go b/libgo/go/exp/locale/collate/trie.go
new file mode 100644
index 00000000000..c70a89b089c
--- /dev/null
+++ b/libgo/go/exp/locale/collate/trie.go
@@ -0,0 +1,99 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The trie in this file is used to associate the first full character
+// in an UTF-8 string to a collation element.
+// All but the last byte in a UTF-8 byte sequence are
+// used to lookup offsets in the index table to be used for the next byte.
+// The last byte is used to index into a table of collation elements.
+// For a full description, see exp/locale/collate/build/trie.go.
+
+package collate
+
+const blockSize = 64
+
+type trie struct {
+ index0 []uint16 // index for first byte (0xC0-0xFF)
+ values0 []uint32 // index for first byte (0x00-0x7F)
+ index []uint16
+ values []uint32
+}
+
+const (
+ t1 = 0x00 // 0000 0000
+ tx = 0x80 // 1000 0000
+ t2 = 0xC0 // 1100 0000
+ t3 = 0xE0 // 1110 0000
+ t4 = 0xF0 // 1111 0000
+ t5 = 0xF8 // 1111 1000
+ t6 = 0xFC // 1111 1100
+ te = 0xFE // 1111 1110
+)
+
+func (t *trie) lookupValue(n uint16, b byte) colElem {
+ return colElem(t.values[int(n)<<6+int(b)])
+}
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *trie) lookup(s []byte) (v colElem, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < tx:
+ return colElem(t.values0[c0]), 1
+ case c0 < t2:
+ return 0, 1
+ case c0 < t3:
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := t.index0[c0]
+ c1 := s[1]
+ if c1 < tx || t2 <= c1 {
+ return 0, 1
+ }
+ return t.lookupValue(i, c1), 2
+ case c0 < t4:
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := t.index0[c0]
+ c1 := s[1]
+ if c1 < tx || t2 <= c1 {
+ return 0, 1
+ }
+ o := int(i)<<6 + int(c1)
+ i = t.index[o]
+ c2 := s[2]
+ if c2 < tx || t2 <= c2 {
+ return 0, 2
+ }
+ return t.lookupValue(i, c2), 3
+ case c0 < t5:
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := t.index0[c0]
+ c1 := s[1]
+ if c1 < tx || t2 <= c1 {
+ return 0, 1
+ }
+ o := int(i)<<6 + int(c1)
+ i = t.index[o]
+ c2 := s[2]
+ if c2 < tx || t2 <= c2 {
+ return 0, 2
+ }
+ o = int(i)<<6 + int(c2)
+ i = t.index[o]
+ c3 := s[3]
+ if c3 < tx || t2 <= c3 {
+ return 0, 3
+ }
+ return t.lookupValue(i, c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
diff --git a/libgo/go/exp/locale/collate/trie_test.go b/libgo/go/exp/locale/collate/trie_test.go
new file mode 100644
index 00000000000..00d636c6f8a
--- /dev/null
+++ b/libgo/go/exp/locale/collate/trie_test.go
@@ -0,0 +1,106 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package collate
+
+import (
+ "testing"
+)
+
+// We take the smallest, largest and an arbitrary value for each
+// of the UTF-8 sequence lengths.
+var testRunes = []rune{
+ 0x01, 0x0C, 0x7F, // 1-byte sequences
+ 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
+}
+
+// Test cases for illegal runes.
+type trietest struct {
+ size int
+ bytes []byte
+}
+
+var tests = []trietest{
+ // illegal runes
+ {1, []byte{0x80}},
+ {1, []byte{0xFF}},
+ {1, []byte{t2, tx - 1}},
+ {1, []byte{t2, t2}},
+ {2, []byte{t3, tx, tx - 1}},
+ {2, []byte{t3, tx, t2}},
+ {1, []byte{t3, tx - 1, tx}},
+ {3, []byte{t4, tx, tx, tx - 1}},
+ {3, []byte{t4, tx, tx, t2}},
+ {1, []byte{t4, t2, tx, tx - 1}},
+ {2, []byte{t4, tx, t2, tx - 1}},
+
+ // short runes
+ {0, []byte{t2}},
+ {0, []byte{t3, tx}},
+ {0, []byte{t4, tx, tx}},
+
+ // we only support UTF-8 up to utf8.UTFMax bytes (4 bytes)
+ {1, []byte{t5, tx, tx, tx, tx}},
+ {1, []byte{t6, tx, tx, tx, tx, tx}},
+}
+
+func TestLookupTrie(t *testing.T) {
+ for i, r := range testRunes {
+ b := []byte(string(r))
+ v, sz := testTrie.lookup(b)
+ if int(v) != i {
+ t.Errorf("lookup(%U): found value %#x, expected %#x", r, v, i)
+ }
+ if sz != len(b) {
+ t.Errorf("lookup(%U): found size %d, expected %d", r, sz, len(b))
+ }
+ }
+ for i, tt := range tests {
+ v, sz := testTrie.lookup(tt.bytes)
+ if int(v) != 0 {
+ t.Errorf("lookup of illegal rune, case %d: found value %#x, expected 0", i, v)
+ }
+ if sz != tt.size {
+ t.Errorf("lookup of illegal rune, case %d: found size %d, expected %d", i, sz, tt.size)
+ }
+ }
+}
+
+// test data is taken from exp/collate/locale/build/trie_test.go
+var testValues = [832]uint32{
+ 0x000c: 0x00000001,
+ 0x007f: 0x00000002,
+ 0x00c0: 0x00000003,
+ 0x0100: 0x00000004,
+ 0x0140: 0x0000000c, 0x0141: 0x0000000d, 0x0142: 0x0000000e,
+ 0x0150: 0x0000000f,
+ 0x0155: 0x00000010,
+ 0x01bf: 0x00000005,
+ 0x01c0: 0x00000006,
+ 0x0219: 0x00000007,
+ 0x027f: 0x00000008,
+ 0x0280: 0x00000009,
+ 0x02c1: 0x0000000a,
+ 0x033f: 0x0000000b,
+}
+
+var testLookup = [640]uint16{
+ 0x0e0: 0x05, 0x0e6: 0x06,
+ 0x13f: 0x07,
+ 0x140: 0x08, 0x144: 0x09,
+ 0x190: 0x03,
+ 0x1ff: 0x0a,
+ 0x20f: 0x05,
+ 0x242: 0x01, 0x244: 0x02,
+ 0x248: 0x03,
+ 0x25f: 0x04,
+ 0x260: 0x01,
+ 0x26f: 0x02,
+ 0x270: 0x04, 0x274: 0x06,
+}
+
+var testTrie = trie{testLookup[6*blockSize:], testValues[:], testLookup[:], testValues[:]}
diff --git a/libgo/go/exp/norm/composition.go b/libgo/go/exp/norm/composition.go
index 2cbe1ac730e..7f84b942966 100644
--- a/libgo/go/exp/norm/composition.go
+++ b/libgo/go/exp/norm/composition.go
@@ -22,10 +22,10 @@ const (
// the UTF-8 characters in order. Only the rune array is maintained in sorted
// order. flush writes the resulting segment to a byte array.
type reorderBuffer struct {
- rune [maxBufferSize]runeInfo // Per character info.
- byte [maxByteBufferSize]byte // UTF-8 buffer. Referenced by runeInfo.pos.
- nrune int // Number of runeInfos.
- nbyte uint8 // Number or bytes.
+ rune [maxBufferSize]Properties // Per character info.
+ byte [maxByteBufferSize]byte // UTF-8 buffer. Referenced by runeInfo.pos.
+ nrune int // Number of runeInfos.
+ nbyte uint8 // Number or bytes.
f formInfo
src input
@@ -81,7 +81,7 @@ func (rb *reorderBuffer) flushCopy(buf []byte) int {
// insertOrdered inserts a rune in the buffer, ordered by Canonical Combining Class.
// It returns false if the buffer is not large enough to hold the rune.
// It is used internally by insert and insertString only.
-func (rb *reorderBuffer) insertOrdered(info runeInfo) bool {
+func (rb *reorderBuffer) insertOrdered(info Properties) bool {
n := rb.nrune
if n >= maxCombiningChars+1 {
return false
@@ -107,12 +107,12 @@ func (rb *reorderBuffer) insertOrdered(info runeInfo) bool {
// insert inserts the given rune in the buffer ordered by CCC.
// It returns true if the buffer was large enough to hold the decomposed rune.
-func (rb *reorderBuffer) insert(src input, i int, info runeInfo) bool {
+func (rb *reorderBuffer) insert(src input, i int, info Properties) bool {
if rune := src.hangul(i); rune != 0 {
return rb.decomposeHangul(rune)
}
if info.hasDecomposition() {
- return rb.insertDecomposed(info.decomposition())
+ return rb.insertDecomposed(info.Decomposition())
}
return rb.insertSingle(src, i, info)
}
@@ -136,7 +136,7 @@ func (rb *reorderBuffer) insertDecomposed(dcomp []byte) bool {
// insertSingle inserts an entry in the reorderBuffer for the rune at
// position i. info is the runeInfo for the rune at position i.
-func (rb *reorderBuffer) insertSingle(src input, i int, info runeInfo) bool {
+func (rb *reorderBuffer) insertSingle(src input, i int, info Properties) bool {
// insertOrder changes nbyte
pos := rb.nbyte
if !rb.insertOrdered(info) {
@@ -151,7 +151,7 @@ func (rb *reorderBuffer) appendRune(r rune) {
bn := rb.nbyte
sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
rb.nbyte += utf8.UTFMax
- rb.rune[rb.nrune] = runeInfo{pos: bn, size: uint8(sz)}
+ rb.rune[rb.nrune] = Properties{pos: bn, size: uint8(sz)}
rb.nrune++
}
@@ -159,7 +159,7 @@ func (rb *reorderBuffer) appendRune(r rune) {
func (rb *reorderBuffer) assignRune(pos int, r rune) {
bn := rb.rune[pos].pos
sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
- rb.rune[pos] = runeInfo{pos: bn, size: uint8(sz)}
+ rb.rune[pos] = Properties{pos: bn, size: uint8(sz)}
}
// runeAt returns the rune at position n. It is used for Hangul and recomposition.
diff --git a/libgo/go/exp/norm/forminfo.go b/libgo/go/exp/norm/forminfo.go
index c443b78d825..a982174f54e 100644
--- a/libgo/go/exp/norm/forminfo.go
+++ b/libgo/go/exp/norm/forminfo.go
@@ -32,8 +32,8 @@ const (
headerFlagsMask = 0xC0 // extract the qcInfo bits from the header byte
)
-// runeInfo is a representation for the data stored in charinfoTrie.
-type runeInfo struct {
+// Properties provides access to normalization properties of a rune.
+type Properties struct {
pos uint8 // start position in reorderBuffer; used in composition.go
size uint8 // length of UTF-8 encoding of this rune
ccc uint8 // leading canonical combining class (ccc if not decomposition)
@@ -43,7 +43,7 @@ type runeInfo struct {
}
// functions dispatchable per form
-type lookupFunc func(b input, i int) runeInfo
+type lookupFunc func(b input, i int) Properties
// formInfo holds Form-specific functions and tables.
type formInfo struct {
@@ -75,11 +75,14 @@ func init() {
// We do not distinguish between boundaries for NFC, NFD, etc. to avoid
// unexpected behavior for the user. For example, in NFD, there is a boundary
-// after 'a'. However, a might combine with modifiers, so from the application's
+// after 'a'. However, 'a' might combine with modifiers, so from the application's
// perspective it is not a good boundary. We will therefore always use the
// boundaries for the combining variants.
-func (i runeInfo) boundaryBefore() bool {
- if i.ccc == 0 && !i.combinesBackward() {
+
+// BoundaryBefore returns true if this rune starts a new segment and
+// cannot combine with any rune on the left.
+func (p Properties) BoundaryBefore() bool {
+ if p.ccc == 0 && !p.combinesBackward() {
return true
}
// We assume that the CCC of the first character in a decomposition
@@ -88,8 +91,10 @@ func (i runeInfo) boundaryBefore() bool {
return false
}
-func (i runeInfo) boundaryAfter() bool {
- return i.isInert()
+// BoundaryAfter returns true if this rune cannot combine with runes to the right
+// and always denotes the end of a segment.
+func (p Properties) BoundaryAfter() bool {
+ return p.isInert()
}
// We pack quick check data in 4 bits:
@@ -101,25 +106,52 @@ func (i runeInfo) boundaryAfter() bool {
// influenced by normalization.
type qcInfo uint8
-func (i runeInfo) isYesC() bool { return i.flags&0x4 == 0 }
-func (i runeInfo) isYesD() bool { return i.flags&0x1 == 0 }
+func (p Properties) isYesC() bool { return p.flags&0x4 == 0 }
+func (p Properties) isYesD() bool { return p.flags&0x1 == 0 }
-func (i runeInfo) combinesForward() bool { return i.flags&0x8 != 0 }
-func (i runeInfo) combinesBackward() bool { return i.flags&0x2 != 0 } // == isMaybe
-func (i runeInfo) hasDecomposition() bool { return i.flags&0x1 != 0 } // == isNoD
+func (p Properties) combinesForward() bool { return p.flags&0x8 != 0 }
+func (p Properties) combinesBackward() bool { return p.flags&0x2 != 0 } // == isMaybe
+func (p Properties) hasDecomposition() bool { return p.flags&0x1 != 0 } // == isNoD
-func (r runeInfo) isInert() bool {
- return r.flags&0xf == 0 && r.ccc == 0
+func (p Properties) isInert() bool {
+ return p.flags&0xf == 0 && p.ccc == 0
}
-func (r runeInfo) decomposition() []byte {
- if r.index == 0 {
+// Decomposition returns the decomposition for the underlying rune
+// or nil if there is none.
+func (p Properties) Decomposition() []byte {
+ if p.index == 0 {
return nil
}
- p := r.index
- n := decomps[p] & 0x3F
- p++
- return decomps[p : p+uint16(n)]
+ i := p.index
+ n := decomps[i] & headerLenMask
+ i++
+ return decomps[i : i+uint16(n)]
+}
+
+// Size returns the length of UTF-8 encoding of the rune.
+func (p Properties) Size() int {
+ return int(p.size)
+}
+
+// CCC returns the canonical combining class of the underlying rune.
+func (p Properties) CCC() uint8 {
+ if p.index > firstCCCZeroExcept {
+ return 0
+ }
+ return p.ccc
+}
+
+// LeadCCC returns the CCC of the first rune in the decomposition.
+// If there is no decomposition, LeadCCC equals CCC.
+func (p Properties) LeadCCC() uint8 {
+ return p.ccc
+}
+
+// TrailCCC returns the CCC of the last rune in the decomposition.
+// If there is no decomposition, TrailCCC equals CCC.
+func (p Properties) TrailCCC() uint8 {
+ return p.tccc
}
// Recomposition
@@ -135,24 +167,40 @@ func combine(a, b rune) rune {
return recompMap[key]
}
-func lookupInfoNFC(b input, i int) runeInfo {
+func lookupInfoNFC(b input, i int) Properties {
v, sz := b.charinfoNFC(i)
return compInfo(v, sz)
}
-func lookupInfoNFKC(b input, i int) runeInfo {
+func lookupInfoNFKC(b input, i int) Properties {
v, sz := b.charinfoNFKC(i)
return compInfo(v, sz)
}
+// Properties returns properties for the first rune in s.
+func (f Form) Properties(s []byte) Properties {
+ if f == NFC || f == NFD {
+ return compInfo(nfcTrie.lookup(s))
+ }
+ return compInfo(nfkcTrie.lookup(s))
+}
+
+// PropertiesString returns properties for the first rune in s.
+func (f Form) PropertiesString(s string) Properties {
+ if f == NFC || f == NFD {
+ return compInfo(nfcTrie.lookupString(s))
+ }
+ return compInfo(nfkcTrie.lookupString(s))
+}
+
// compInfo converts the information contained in v and sz
-// to a runeInfo. See the comment at the top of the file
+// to a Properties. See the comment at the top of the file
// for more information on the format.
-func compInfo(v uint16, sz int) runeInfo {
+func compInfo(v uint16, sz int) Properties {
if v == 0 {
- return runeInfo{size: uint8(sz)}
+ return Properties{size: uint8(sz)}
} else if v >= 0x8000 {
- return runeInfo{
+ return Properties{
size: uint8(sz),
ccc: uint8(v),
tccc: uint8(v),
@@ -162,7 +210,7 @@ func compInfo(v uint16, sz int) runeInfo {
// has decomposition
h := decomps[v]
f := (qcInfo(h&headerFlagsMask) >> 4) | 0x1
- ri := runeInfo{size: uint8(sz), flags: f, index: v}
+ ri := Properties{size: uint8(sz), flags: f, index: v}
if v >= firstCCC {
v += uint16(h&headerLenMask) + 1
ri.tccc = decomps[v]
diff --git a/libgo/go/exp/norm/iter.go b/libgo/go/exp/norm/iter.go
index 761ba90cdd4..e37ad7b4103 100644
--- a/libgo/go/exp/norm/iter.go
+++ b/libgo/go/exp/norm/iter.go
@@ -10,8 +10,8 @@ const MaxSegmentSize = maxByteBufferSize
// to a given Form.
type Iter struct {
rb reorderBuffer
- info runeInfo // first character saved from previous iteration
- next iterFunc // implementation of next depends on form
+ info Properties // first character saved from previous iteration
+ next iterFunc // implementation of next depends on form
p int // current position in input source
outStart int // start of current segment in output buffer
@@ -124,7 +124,7 @@ doFast:
break
}
}
- } else if d := i.info.decomposition(); d != nil {
+ } else if d := i.info.Decomposition(); d != nil {
i.rb.src.copySlice(out[outCopyStart:], inCopyStart, i.p)
p := outp + len(d)
if p > i.maxseg && i.setStart(outp, i.p) {
@@ -245,7 +245,7 @@ doFast:
if i.setStart(outp-1, i.p-1) {
i.p--
outp--
- i.info = runeInfo{size: 1}
+ i.info = Properties{size: 1}
break
}
}
@@ -274,7 +274,7 @@ doNorm:
return outp
}
i.info = i.rb.f.info(i.rb.src, i.p)
- if i.info.boundaryBefore() {
+ if i.info.BoundaryBefore() {
break
}
}
diff --git a/libgo/go/exp/norm/maketables.go b/libgo/go/exp/norm/maketables.go
index 1deedc949c2..8ac64ba967d 100644
--- a/libgo/go/exp/norm/maketables.go
+++ b/libgo/go/exp/norm/maketables.go
@@ -23,6 +23,7 @@ import (
"sort"
"strconv"
"strings"
+ "unicode"
)
func main() {
@@ -38,7 +39,7 @@ func main() {
}
var url = flag.String("url",
- "http://www.unicode.org/Public/6.0.0/ucd/",
+ "http://www.unicode.org/Public/"+unicode.Version+"/ucd/",
"URL of Unicode database directory")
var tablelist = flag.String("tables",
"all",
@@ -605,6 +606,10 @@ func printCharInfoTables() int {
lccc := ccc(d[0])
tccc := ccc(d[len(d)-1])
+ cc := ccc(r)
+ if cc != 0 && lccc == 0 && tccc == 0 {
+ logger.Fatalf("%U: trailing and leading ccc are 0 for non-zero ccc %d", r, cc)
+ }
if tccc < lccc && lccc != 0 {
const msg = "%U: lccc (%d) must be <= tcc (%d)"
logger.Fatalf(msg, r, lccc, tccc)
@@ -615,7 +620,13 @@ func printCharInfoTables() int {
index = 1
if lccc > 0 {
s += string([]byte{lccc})
- index |= 2
+ index = 2
+ }
+ if cc != lccc {
+ if cc != 0 {
+ logger.Fatalf("%U: for lccc != ccc, expected ccc to be 0; was %d", r, cc)
+ }
+ index = 3
}
}
return index, s
@@ -642,7 +653,7 @@ func printCharInfoTables() int {
size := 0
positionMap := make(map[string]uint16)
decompositions.WriteString("\000")
- cname := []string{"firstCCC", "firstLeadingCCC", "", "lastDecomp"}
+ cname := []string{"firstCCC", "firstLeadingCCC", "firstCCCZeroExcept", "lastDecomp"}
fmt.Println("const (")
for i, m := range decompSet {
sa := []string{}
diff --git a/libgo/go/exp/norm/normalize.go b/libgo/go/exp/norm/normalize.go
index c1d74f89d01..1c3e49b7719 100644
--- a/libgo/go/exp/norm/normalize.go
+++ b/libgo/go/exp/norm/normalize.go
@@ -185,14 +185,14 @@ func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
}
fd := &rb.f
if doMerge {
- var info runeInfo
+ var info Properties
if p < n {
info = fd.info(src, p)
- if p == 0 && !info.boundaryBefore() {
+ if p == 0 && !info.BoundaryBefore() {
out = decomposeToLastBoundary(rb, out)
}
}
- if info.size == 0 || info.boundaryBefore() {
+ if info.size == 0 || info.BoundaryBefore() {
if fd.composing {
rb.compose()
}
@@ -316,13 +316,13 @@ func firstBoundary(rb *reorderBuffer) int {
}
fd := &rb.f
info := fd.info(src, i)
- for n := 0; info.size != 0 && !info.boundaryBefore(); {
+ for n := 0; info.size != 0 && !info.BoundaryBefore(); {
i += int(info.size)
if n++; n >= maxCombiningChars {
return i
}
if i >= nsrc {
- if !info.boundaryAfter() {
+ if !info.BoundaryAfter() {
return -1
}
return nsrc
@@ -368,11 +368,11 @@ func lastBoundary(fd *formInfo, b []byte) int {
if p+int(info.size) != i { // trailing non-starter bytes: illegal UTF-8
return i
}
- if info.boundaryAfter() {
+ if info.BoundaryAfter() {
return i
}
i = p
- for n := 0; i >= 0 && !info.boundaryBefore(); {
+ for n := 0; i >= 0 && !info.BoundaryBefore(); {
info, p = lastRuneStart(fd, b[:i])
if n++; n >= maxCombiningChars {
return len(b)
@@ -404,7 +404,7 @@ func decomposeSegment(rb *reorderBuffer, sp int) int {
break
}
info = rb.f.info(rb.src, sp)
- bound := info.boundaryBefore()
+ bound := info.BoundaryBefore()
if bound || info.size == 0 {
break
}
@@ -414,12 +414,12 @@ func decomposeSegment(rb *reorderBuffer, sp int) int {
// lastRuneStart returns the runeInfo and position of the last
// rune in buf or the zero runeInfo and -1 if no rune was found.
-func lastRuneStart(fd *formInfo, buf []byte) (runeInfo, int) {
+func lastRuneStart(fd *formInfo, buf []byte) (Properties, int) {
p := len(buf) - 1
for ; p >= 0 && !utf8.RuneStart(buf[p]); p-- {
}
if p < 0 {
- return runeInfo{}, -1
+ return Properties{}, -1
}
return fd.info(inputBytes(buf), p), p
}
@@ -433,15 +433,15 @@ func decomposeToLastBoundary(rb *reorderBuffer, buf []byte) []byte {
// illegal trailing continuation bytes
return buf
}
- if info.boundaryAfter() {
+ if info.BoundaryAfter() {
return buf
}
- var add [maxBackRunes]runeInfo // stores runeInfo in reverse order
+ var add [maxBackRunes]Properties // stores runeInfo in reverse order
add[0] = info
padd := 1
n := 1
p := len(buf) - int(info.size)
- for ; p >= 0 && !info.boundaryBefore(); p -= int(info.size) {
+ for ; p >= 0 && !info.BoundaryBefore(); p -= int(info.size) {
info, i = lastRuneStart(fd, buf[:p])
if int(info.size) != p-i {
break
@@ -452,7 +452,7 @@ func decomposeToLastBoundary(rb *reorderBuffer, buf []byte) []byte {
i += int(info.size)
n++
} else {
- dcomp := info.decomposition()
+ dcomp := info.Decomposition()
for i := 0; i < len(dcomp); {
inf := rb.f.info(inputBytes(dcomp), i)
i += int(inf.size)
diff --git a/libgo/go/exp/norm/normregtest.go b/libgo/go/exp/norm/normregtest.go
index 507de1ae834..6d2188498b1 100644
--- a/libgo/go/exp/norm/normregtest.go
+++ b/libgo/go/exp/norm/normregtest.go
@@ -22,6 +22,7 @@ import (
"strconv"
"strings"
"time"
+ "unicode"
"unicode/utf8"
)
@@ -39,7 +40,7 @@ func main() {
const file = "NormalizationTest.txt"
var url = flag.String("url",
- "http://www.unicode.org/Public/6.0.0/ucd/"+file,
+ "http://www.unicode.org/Public/"+unicode.Version+"/ucd/"+file,
"URL of Unicode database directory")
var localFiles = flag.Bool("local",
false,
@@ -48,7 +49,7 @@ var localFiles = flag.Bool("local",
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/).
+// (taken from http://www.unicode.org/Public/<unicode.Version>/ucd/).
//
// NormalizationTest.txt has form:
// @Part0 # Specific cases
diff --git a/libgo/go/exp/norm/tables.go b/libgo/go/exp/norm/tables.go
index e97b1710722..231d85d898f 100644
--- a/libgo/go/exp/norm/tables.go
+++ b/libgo/go/exp/norm/tables.go
@@ -8,10 +8,11 @@ package norm
const Version = "6.0.0"
const (
- firstCCC = 0x2E45
- firstLeadingCCC = 0x4965
- lastDecomp = 0x49A2
- maxDecomp = 0x8000
+ firstCCC = 0x2E45
+ firstLeadingCCC = 0x4965
+ firstCCCZeroExcept = 0x497B
+ lastDecomp = 0x49A2
+ maxDecomp = 0x8000
)
// decomps: 18850 bytes
@@ -2660,10 +2661,10 @@ var decomps = [...]byte{
0xCC, 0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCF, 0x89,
0xCC, 0x94, 0xCD, 0x82, 0xE6, 0x42, 0xCC, 0x80,
0xE6, 0xE6, 0x42, 0xCC, 0x81, 0xE6, 0xE6, 0x42,
- 0xCC, 0x93, 0xE6, 0xE6, 0x43, 0xE3, 0x82, 0x99,
- 0x08, 0x08, 0x43, 0xE3, 0x82, 0x9A, 0x08, 0x08,
+ 0xCC, 0x93, 0xE6, 0xE6, 0x44, 0xCC, 0x88, 0xCC,
+ 0x81, 0xE6, 0xE6, 0x43, 0xE3, 0x82, 0x99, 0x08,
// Bytes 4980 - 49bf
- 0x44, 0xCC, 0x88, 0xCC, 0x81, 0xE6, 0xE6, 0x46,
+ 0x08, 0x43, 0xE3, 0x82, 0x9A, 0x08, 0x08, 0x46,
0xE0, 0xBD, 0xB1, 0xE0, 0xBD, 0xB2, 0x82, 0x81,
0x46, 0xE0, 0xBD, 0xB1, 0xE0, 0xBD, 0xB4, 0x84,
0x81, 0x46, 0xE0, 0xBD, 0xB1, 0xE0, 0xBE, 0x80,
@@ -2756,7 +2757,7 @@ var nfcValues = [2944]uint16{
0x0236: 0x8001, 0x0237: 0x8001, 0x0238: 0x8601, 0x0239: 0x80dc, 0x023a: 0x80dc, 0x023b: 0x80dc,
0x023c: 0x80dc, 0x023d: 0x80e6, 0x023e: 0x80e6, 0x023f: 0x80e6,
// Block 0x9, offset 0x240
- 0x0240: 0x4965, 0x0241: 0x496a, 0x0242: 0x86e6, 0x0243: 0x496f, 0x0244: 0x4980, 0x0245: 0x86f0,
+ 0x0240: 0x4965, 0x0241: 0x496a, 0x0242: 0x86e6, 0x0243: 0x496f, 0x0244: 0x4974, 0x0245: 0x86f0,
0x0246: 0x80e6, 0x0247: 0x80dc, 0x0248: 0x80dc, 0x0249: 0x80dc, 0x024a: 0x80e6, 0x024b: 0x80e6,
0x024c: 0x80e6, 0x024d: 0x80dc, 0x024e: 0x80dc, 0x0250: 0x80e6, 0x0251: 0x80e6,
0x0252: 0x80e6, 0x0253: 0x80dc, 0x0254: 0x80dc, 0x0255: 0x80dc, 0x0256: 0x80dc, 0x0257: 0x80e6,
@@ -3745,75 +3746,75 @@ var nfcLookup = [1088]uint8{
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
- 0x0c2: 0x2e, 0x0c3: 0x03, 0x0c4: 0x04, 0x0c5: 0x05, 0x0c6: 0x2f, 0x0c7: 0x06,
- 0x0c8: 0x07, 0x0ca: 0x30, 0x0cc: 0x08, 0x0cd: 0x09, 0x0ce: 0x0a, 0x0cf: 0x31,
- 0x0d0: 0x0b, 0x0d1: 0x32, 0x0d2: 0x33, 0x0d3: 0x0c, 0x0d6: 0x0d, 0x0d7: 0x34,
- 0x0d8: 0x35, 0x0d9: 0x0e, 0x0db: 0x36, 0x0dc: 0x37, 0x0dd: 0x38, 0x0df: 0x39,
- 0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07,
- 0x0ea: 0x08, 0x0eb: 0x09, 0x0ec: 0x09, 0x0ed: 0x0a, 0x0ef: 0x0b,
- 0x0f0: 0x10,
+ 0x0c2: 0x2c, 0x0c3: 0x01, 0x0c4: 0x02, 0x0c5: 0x03, 0x0c6: 0x2d, 0x0c7: 0x04,
+ 0x0c8: 0x05, 0x0ca: 0x2e, 0x0cc: 0x06, 0x0cd: 0x07, 0x0ce: 0x08, 0x0cf: 0x2f,
+ 0x0d0: 0x09, 0x0d1: 0x30, 0x0d2: 0x31, 0x0d3: 0x0a, 0x0d6: 0x0b, 0x0d7: 0x32,
+ 0x0d8: 0x33, 0x0d9: 0x0c, 0x0db: 0x34, 0x0dc: 0x35, 0x0dd: 0x36, 0x0df: 0x37,
+ 0x0e0: 0x02, 0x0e1: 0x03, 0x0e2: 0x04, 0x0e3: 0x05,
+ 0x0ea: 0x06, 0x0eb: 0x07, 0x0ec: 0x07, 0x0ed: 0x08, 0x0ef: 0x09,
+ 0x0f0: 0x0e,
// Block 0x4, offset 0x100
- 0x120: 0x3a, 0x121: 0x3b, 0x124: 0x3c, 0x125: 0x3d, 0x126: 0x3e, 0x127: 0x3f,
- 0x128: 0x40, 0x129: 0x41, 0x12a: 0x42, 0x12b: 0x43, 0x12c: 0x3e, 0x12d: 0x44, 0x12e: 0x45, 0x12f: 0x46,
- 0x131: 0x47, 0x132: 0x48, 0x133: 0x49, 0x134: 0x4a, 0x135: 0x4b, 0x137: 0x4c,
- 0x138: 0x4d, 0x139: 0x4e, 0x13a: 0x4f, 0x13b: 0x50, 0x13c: 0x51, 0x13d: 0x52, 0x13e: 0x53, 0x13f: 0x54,
+ 0x120: 0x38, 0x121: 0x39, 0x124: 0x3a, 0x125: 0x3b, 0x126: 0x3c, 0x127: 0x3d,
+ 0x128: 0x3e, 0x129: 0x3f, 0x12a: 0x40, 0x12b: 0x41, 0x12c: 0x3c, 0x12d: 0x42, 0x12e: 0x43, 0x12f: 0x44,
+ 0x131: 0x45, 0x132: 0x46, 0x133: 0x47, 0x134: 0x48, 0x135: 0x49, 0x137: 0x4a,
+ 0x138: 0x4b, 0x139: 0x4c, 0x13a: 0x4d, 0x13b: 0x4e, 0x13c: 0x4f, 0x13d: 0x50, 0x13e: 0x51, 0x13f: 0x52,
// Block 0x5, offset 0x140
- 0x140: 0x55, 0x142: 0x56, 0x144: 0x57, 0x145: 0x58, 0x146: 0x59, 0x147: 0x5a,
- 0x14d: 0x5b,
- 0x15c: 0x5c, 0x15f: 0x5d,
- 0x162: 0x5e, 0x164: 0x5f,
- 0x168: 0x60, 0x169: 0x61, 0x16c: 0x0f, 0x16d: 0x62, 0x16e: 0x63, 0x16f: 0x64,
- 0x170: 0x65, 0x173: 0x66, 0x177: 0x67,
- 0x178: 0x10, 0x179: 0x11, 0x17a: 0x12, 0x17b: 0x13, 0x17c: 0x14, 0x17d: 0x15, 0x17e: 0x16, 0x17f: 0x17,
+ 0x140: 0x53, 0x142: 0x54, 0x144: 0x55, 0x145: 0x56, 0x146: 0x57, 0x147: 0x58,
+ 0x14d: 0x59,
+ 0x15c: 0x5a, 0x15f: 0x5b,
+ 0x162: 0x5c, 0x164: 0x5d,
+ 0x168: 0x5e, 0x169: 0x5f, 0x16c: 0x0d, 0x16d: 0x60, 0x16e: 0x61, 0x16f: 0x62,
+ 0x170: 0x63, 0x173: 0x64, 0x177: 0x65,
+ 0x178: 0x0e, 0x179: 0x0f, 0x17a: 0x10, 0x17b: 0x11, 0x17c: 0x12, 0x17d: 0x13, 0x17e: 0x14, 0x17f: 0x15,
// Block 0x6, offset 0x180
- 0x180: 0x68, 0x183: 0x69, 0x184: 0x6a, 0x186: 0x6b, 0x187: 0x6c,
- 0x188: 0x6d, 0x189: 0x18, 0x18a: 0x19, 0x18b: 0x6e, 0x18c: 0x6f,
- 0x1ab: 0x70,
- 0x1b3: 0x71, 0x1b5: 0x72, 0x1b7: 0x73,
+ 0x180: 0x66, 0x183: 0x67, 0x184: 0x68, 0x186: 0x69, 0x187: 0x6a,
+ 0x188: 0x6b, 0x189: 0x16, 0x18a: 0x17, 0x18b: 0x6c, 0x18c: 0x6d,
+ 0x1ab: 0x6e,
+ 0x1b3: 0x6f, 0x1b5: 0x70, 0x1b7: 0x71,
// Block 0x7, offset 0x1c0
- 0x1c0: 0x74, 0x1c1: 0x1a, 0x1c2: 0x1b, 0x1c3: 0x1c,
+ 0x1c0: 0x72, 0x1c1: 0x18, 0x1c2: 0x19, 0x1c3: 0x1a,
// Block 0x8, offset 0x200
- 0x219: 0x75, 0x21b: 0x76,
- 0x220: 0x77, 0x223: 0x78, 0x224: 0x79, 0x225: 0x7a, 0x226: 0x7b, 0x227: 0x7c,
- 0x22a: 0x7d, 0x22b: 0x7e, 0x22f: 0x7f,
- 0x230: 0x80, 0x231: 0x80, 0x232: 0x80, 0x233: 0x80, 0x234: 0x80, 0x235: 0x80, 0x236: 0x80, 0x237: 0x80,
- 0x238: 0x80, 0x239: 0x80, 0x23a: 0x80, 0x23b: 0x80, 0x23c: 0x80, 0x23d: 0x80, 0x23e: 0x80, 0x23f: 0x80,
+ 0x219: 0x73, 0x21b: 0x74,
+ 0x220: 0x75, 0x223: 0x76, 0x224: 0x77, 0x225: 0x78, 0x226: 0x79, 0x227: 0x7a,
+ 0x22a: 0x7b, 0x22b: 0x7c, 0x22f: 0x7d,
+ 0x230: 0x7e, 0x231: 0x7e, 0x232: 0x7e, 0x233: 0x7e, 0x234: 0x7e, 0x235: 0x7e, 0x236: 0x7e, 0x237: 0x7e,
+ 0x238: 0x7e, 0x239: 0x7e, 0x23a: 0x7e, 0x23b: 0x7e, 0x23c: 0x7e, 0x23d: 0x7e, 0x23e: 0x7e, 0x23f: 0x7e,
// Block 0x9, offset 0x240
- 0x240: 0x80, 0x241: 0x80, 0x242: 0x80, 0x243: 0x80, 0x244: 0x80, 0x245: 0x80, 0x246: 0x80, 0x247: 0x80,
- 0x248: 0x80, 0x249: 0x80, 0x24a: 0x80, 0x24b: 0x80, 0x24c: 0x80, 0x24d: 0x80, 0x24e: 0x80, 0x24f: 0x80,
- 0x250: 0x80, 0x251: 0x80, 0x252: 0x80, 0x253: 0x80, 0x254: 0x80, 0x255: 0x80, 0x256: 0x80, 0x257: 0x80,
- 0x258: 0x80, 0x259: 0x80, 0x25a: 0x80, 0x25b: 0x80, 0x25c: 0x80, 0x25d: 0x80, 0x25e: 0x80, 0x25f: 0x80,
- 0x260: 0x80, 0x261: 0x80, 0x262: 0x80, 0x263: 0x80, 0x264: 0x80, 0x265: 0x80, 0x266: 0x80, 0x267: 0x80,
- 0x268: 0x80, 0x269: 0x80, 0x26a: 0x80, 0x26b: 0x80, 0x26c: 0x80, 0x26d: 0x80, 0x26e: 0x80, 0x26f: 0x80,
- 0x270: 0x80, 0x271: 0x80, 0x272: 0x80, 0x273: 0x80, 0x274: 0x80, 0x275: 0x80, 0x276: 0x80, 0x277: 0x80,
- 0x278: 0x80, 0x279: 0x80, 0x27a: 0x80, 0x27b: 0x80, 0x27c: 0x80, 0x27d: 0x80, 0x27e: 0x80, 0x27f: 0x80,
+ 0x240: 0x7e, 0x241: 0x7e, 0x242: 0x7e, 0x243: 0x7e, 0x244: 0x7e, 0x245: 0x7e, 0x246: 0x7e, 0x247: 0x7e,
+ 0x248: 0x7e, 0x249: 0x7e, 0x24a: 0x7e, 0x24b: 0x7e, 0x24c: 0x7e, 0x24d: 0x7e, 0x24e: 0x7e, 0x24f: 0x7e,
+ 0x250: 0x7e, 0x251: 0x7e, 0x252: 0x7e, 0x253: 0x7e, 0x254: 0x7e, 0x255: 0x7e, 0x256: 0x7e, 0x257: 0x7e,
+ 0x258: 0x7e, 0x259: 0x7e, 0x25a: 0x7e, 0x25b: 0x7e, 0x25c: 0x7e, 0x25d: 0x7e, 0x25e: 0x7e, 0x25f: 0x7e,
+ 0x260: 0x7e, 0x261: 0x7e, 0x262: 0x7e, 0x263: 0x7e, 0x264: 0x7e, 0x265: 0x7e, 0x266: 0x7e, 0x267: 0x7e,
+ 0x268: 0x7e, 0x269: 0x7e, 0x26a: 0x7e, 0x26b: 0x7e, 0x26c: 0x7e, 0x26d: 0x7e, 0x26e: 0x7e, 0x26f: 0x7e,
+ 0x270: 0x7e, 0x271: 0x7e, 0x272: 0x7e, 0x273: 0x7e, 0x274: 0x7e, 0x275: 0x7e, 0x276: 0x7e, 0x277: 0x7e,
+ 0x278: 0x7e, 0x279: 0x7e, 0x27a: 0x7e, 0x27b: 0x7e, 0x27c: 0x7e, 0x27d: 0x7e, 0x27e: 0x7e, 0x27f: 0x7e,
// Block 0xa, offset 0x280
- 0x280: 0x80, 0x281: 0x80, 0x282: 0x80, 0x283: 0x80, 0x284: 0x80, 0x285: 0x80, 0x286: 0x80, 0x287: 0x80,
- 0x288: 0x80, 0x289: 0x80, 0x28a: 0x80, 0x28b: 0x80, 0x28c: 0x80, 0x28d: 0x80, 0x28e: 0x80, 0x28f: 0x80,
- 0x290: 0x80, 0x291: 0x80, 0x292: 0x80, 0x293: 0x80, 0x294: 0x80, 0x295: 0x80, 0x296: 0x80, 0x297: 0x80,
- 0x298: 0x80, 0x299: 0x80, 0x29a: 0x80, 0x29b: 0x80, 0x29c: 0x80, 0x29d: 0x80, 0x29e: 0x81,
+ 0x280: 0x7e, 0x281: 0x7e, 0x282: 0x7e, 0x283: 0x7e, 0x284: 0x7e, 0x285: 0x7e, 0x286: 0x7e, 0x287: 0x7e,
+ 0x288: 0x7e, 0x289: 0x7e, 0x28a: 0x7e, 0x28b: 0x7e, 0x28c: 0x7e, 0x28d: 0x7e, 0x28e: 0x7e, 0x28f: 0x7e,
+ 0x290: 0x7e, 0x291: 0x7e, 0x292: 0x7e, 0x293: 0x7e, 0x294: 0x7e, 0x295: 0x7e, 0x296: 0x7e, 0x297: 0x7e,
+ 0x298: 0x7e, 0x299: 0x7e, 0x29a: 0x7e, 0x29b: 0x7e, 0x29c: 0x7e, 0x29d: 0x7e, 0x29e: 0x7f,
// Block 0xb, offset 0x2c0
- 0x2e4: 0x1d, 0x2e5: 0x1e, 0x2e6: 0x1f, 0x2e7: 0x20,
- 0x2e8: 0x21, 0x2e9: 0x22, 0x2ea: 0x23, 0x2eb: 0x24, 0x2ec: 0x82, 0x2ed: 0x83,
- 0x2f8: 0x84,
+ 0x2e4: 0x1b, 0x2e5: 0x1c, 0x2e6: 0x1d, 0x2e7: 0x1e,
+ 0x2e8: 0x1f, 0x2e9: 0x20, 0x2ea: 0x21, 0x2eb: 0x22, 0x2ec: 0x80, 0x2ed: 0x81,
+ 0x2f8: 0x82,
// Block 0xc, offset 0x300
- 0x307: 0x85,
- 0x328: 0x86,
+ 0x307: 0x83,
+ 0x328: 0x84,
// Block 0xd, offset 0x340
- 0x341: 0x77, 0x342: 0x87,
+ 0x341: 0x75, 0x342: 0x85,
// Block 0xe, offset 0x380
- 0x385: 0x88, 0x386: 0x89, 0x387: 0x8a,
- 0x389: 0x8b,
+ 0x385: 0x86, 0x386: 0x87, 0x387: 0x88,
+ 0x389: 0x89,
// Block 0xf, offset 0x3c0
- 0x3e0: 0x25, 0x3e1: 0x26, 0x3e2: 0x27, 0x3e3: 0x28, 0x3e4: 0x29, 0x3e5: 0x2a, 0x3e6: 0x2b, 0x3e7: 0x2c,
- 0x3e8: 0x2d,
+ 0x3e0: 0x23, 0x3e1: 0x24, 0x3e2: 0x25, 0x3e3: 0x26, 0x3e4: 0x27, 0x3e5: 0x28, 0x3e6: 0x29, 0x3e7: 0x2a,
+ 0x3e8: 0x2b,
// Block 0x10, offset 0x400
- 0x410: 0x0c, 0x411: 0x0d,
- 0x41d: 0x0e,
- 0x42f: 0x0f,
+ 0x410: 0x0a, 0x411: 0x0b,
+ 0x41d: 0x0c,
+ 0x42f: 0x0d,
}
-var nfcTrie = trie{nfcLookup[:], nfcValues[:], nfcSparseValues[:], nfcSparseOffset[:], 46}
+var nfcTrie = trie{nfcLookup[:], nfcValues[:], nfcSparseValues[:], nfcSparseOffset[:], 44}
// nfkcValues: 5568 entries, 11136 bytes
// Block 2 is the null block.
@@ -3903,7 +3904,7 @@ var nfkcValues = [5568]uint16{
0x0236: 0x8001, 0x0237: 0x8001, 0x0238: 0x8601, 0x0239: 0x80dc, 0x023a: 0x80dc, 0x023b: 0x80dc,
0x023c: 0x80dc, 0x023d: 0x80e6, 0x023e: 0x80e6, 0x023f: 0x80e6,
// Block 0x9, offset 0x240
- 0x0240: 0x4965, 0x0241: 0x496a, 0x0242: 0x86e6, 0x0243: 0x496f, 0x0244: 0x4980, 0x0245: 0x86f0,
+ 0x0240: 0x4965, 0x0241: 0x496a, 0x0242: 0x86e6, 0x0243: 0x496f, 0x0244: 0x4974, 0x0245: 0x86f0,
0x0246: 0x80e6, 0x0247: 0x80dc, 0x0248: 0x80dc, 0x0249: 0x80dc, 0x024a: 0x80e6, 0x024b: 0x80e6,
0x024c: 0x80e6, 0x024d: 0x80dc, 0x024e: 0x80dc, 0x0250: 0x80e6, 0x0251: 0x80e6,
0x0252: 0x80e6, 0x0253: 0x80dc, 0x0254: 0x80dc, 0x0255: 0x80dc, 0x0256: 0x80dc, 0x0257: 0x80e6,
@@ -4609,7 +4610,7 @@ var nfkcValues = [5568]uint16{
0x124c: 0x0a89, 0x124d: 0x0a8d, 0x124e: 0x0a91, 0x124f: 0x0a95, 0x1250: 0x0a99, 0x1251: 0x0a9d,
0x1252: 0x0aa1, 0x1253: 0x0aa5, 0x1254: 0x0aad, 0x1255: 0x0ab5, 0x1256: 0x0abd, 0x1257: 0x0ac1,
0x1258: 0x0ac5, 0x1259: 0x0ac9, 0x125a: 0x0acd, 0x125b: 0x0ad1, 0x125c: 0x0ad5, 0x125d: 0x0ae5,
- 0x125e: 0x4974, 0x125f: 0x497a, 0x1260: 0x0889, 0x1261: 0x07d9, 0x1262: 0x07dd, 0x1263: 0x0901,
+ 0x125e: 0x497b, 0x125f: 0x4981, 0x1260: 0x0889, 0x1261: 0x07d9, 0x1262: 0x07dd, 0x1263: 0x0901,
0x1264: 0x07e1, 0x1265: 0x0905, 0x1266: 0x0909, 0x1267: 0x07e5, 0x1268: 0x07e9, 0x1269: 0x07ed,
0x126a: 0x090d, 0x126b: 0x0911, 0x126c: 0x0915, 0x126d: 0x0919, 0x126e: 0x091d, 0x126f: 0x0921,
0x1270: 0x082d, 0x1271: 0x07f1, 0x1272: 0x07f5, 0x1273: 0x07f9, 0x1274: 0x0841, 0x1275: 0x07fd,
@@ -5641,84 +5642,84 @@ var nfkcLookup = [1152]uint8{
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
- 0x0c2: 0x57, 0x0c3: 0x03, 0x0c4: 0x04, 0x0c5: 0x05, 0x0c6: 0x58, 0x0c7: 0x06,
- 0x0c8: 0x07, 0x0ca: 0x59, 0x0cb: 0x5a, 0x0cc: 0x08, 0x0cd: 0x09, 0x0ce: 0x0a, 0x0cf: 0x0b,
- 0x0d0: 0x0c, 0x0d1: 0x5b, 0x0d2: 0x5c, 0x0d3: 0x0d, 0x0d6: 0x0e, 0x0d7: 0x5d,
- 0x0d8: 0x5e, 0x0d9: 0x0f, 0x0db: 0x5f, 0x0dc: 0x60, 0x0dd: 0x61, 0x0df: 0x62,
- 0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07,
- 0x0ea: 0x08, 0x0eb: 0x09, 0x0ec: 0x09, 0x0ed: 0x0a, 0x0ef: 0x0b,
- 0x0f0: 0x11,
+ 0x0c2: 0x55, 0x0c3: 0x01, 0x0c4: 0x02, 0x0c5: 0x03, 0x0c6: 0x56, 0x0c7: 0x04,
+ 0x0c8: 0x05, 0x0ca: 0x57, 0x0cb: 0x58, 0x0cc: 0x06, 0x0cd: 0x07, 0x0ce: 0x08, 0x0cf: 0x09,
+ 0x0d0: 0x0a, 0x0d1: 0x59, 0x0d2: 0x5a, 0x0d3: 0x0b, 0x0d6: 0x0c, 0x0d7: 0x5b,
+ 0x0d8: 0x5c, 0x0d9: 0x0d, 0x0db: 0x5d, 0x0dc: 0x5e, 0x0dd: 0x5f, 0x0df: 0x60,
+ 0x0e0: 0x02, 0x0e1: 0x03, 0x0e2: 0x04, 0x0e3: 0x05,
+ 0x0ea: 0x06, 0x0eb: 0x07, 0x0ec: 0x07, 0x0ed: 0x08, 0x0ef: 0x09,
+ 0x0f0: 0x0f,
// Block 0x4, offset 0x100
- 0x120: 0x63, 0x121: 0x64, 0x124: 0x65, 0x125: 0x66, 0x126: 0x67, 0x127: 0x68,
- 0x128: 0x69, 0x129: 0x6a, 0x12a: 0x6b, 0x12b: 0x6c, 0x12c: 0x67, 0x12d: 0x6d, 0x12e: 0x6e, 0x12f: 0x6f,
- 0x131: 0x70, 0x132: 0x71, 0x133: 0x72, 0x134: 0x73, 0x135: 0x74, 0x137: 0x75,
- 0x138: 0x76, 0x139: 0x77, 0x13a: 0x78, 0x13b: 0x79, 0x13c: 0x7a, 0x13d: 0x7b, 0x13e: 0x7c, 0x13f: 0x7d,
+ 0x120: 0x61, 0x121: 0x62, 0x124: 0x63, 0x125: 0x64, 0x126: 0x65, 0x127: 0x66,
+ 0x128: 0x67, 0x129: 0x68, 0x12a: 0x69, 0x12b: 0x6a, 0x12c: 0x65, 0x12d: 0x6b, 0x12e: 0x6c, 0x12f: 0x6d,
+ 0x131: 0x6e, 0x132: 0x6f, 0x133: 0x70, 0x134: 0x71, 0x135: 0x72, 0x137: 0x73,
+ 0x138: 0x74, 0x139: 0x75, 0x13a: 0x76, 0x13b: 0x77, 0x13c: 0x78, 0x13d: 0x79, 0x13e: 0x7a, 0x13f: 0x7b,
// Block 0x5, offset 0x140
- 0x140: 0x7e, 0x142: 0x7f, 0x143: 0x80, 0x144: 0x81, 0x145: 0x82, 0x146: 0x83, 0x147: 0x84,
- 0x14d: 0x85,
- 0x15c: 0x86, 0x15f: 0x87,
- 0x162: 0x88, 0x164: 0x89,
- 0x168: 0x8a, 0x169: 0x8b, 0x16c: 0x10, 0x16d: 0x8c, 0x16e: 0x8d, 0x16f: 0x8e,
- 0x170: 0x8f, 0x173: 0x90, 0x174: 0x91, 0x175: 0x11, 0x176: 0x12, 0x177: 0x92,
- 0x178: 0x13, 0x179: 0x14, 0x17a: 0x15, 0x17b: 0x16, 0x17c: 0x17, 0x17d: 0x18, 0x17e: 0x19, 0x17f: 0x1a,
+ 0x140: 0x7c, 0x142: 0x7d, 0x143: 0x7e, 0x144: 0x7f, 0x145: 0x80, 0x146: 0x81, 0x147: 0x82,
+ 0x14d: 0x83,
+ 0x15c: 0x84, 0x15f: 0x85,
+ 0x162: 0x86, 0x164: 0x87,
+ 0x168: 0x88, 0x169: 0x89, 0x16c: 0x0e, 0x16d: 0x8a, 0x16e: 0x8b, 0x16f: 0x8c,
+ 0x170: 0x8d, 0x173: 0x8e, 0x174: 0x8f, 0x175: 0x0f, 0x176: 0x10, 0x177: 0x90,
+ 0x178: 0x11, 0x179: 0x12, 0x17a: 0x13, 0x17b: 0x14, 0x17c: 0x15, 0x17d: 0x16, 0x17e: 0x17, 0x17f: 0x18,
// Block 0x6, offset 0x180
- 0x180: 0x93, 0x181: 0x94, 0x182: 0x95, 0x183: 0x96, 0x184: 0x1b, 0x185: 0x1c, 0x186: 0x97, 0x187: 0x98,
- 0x188: 0x99, 0x189: 0x1d, 0x18a: 0x1e, 0x18b: 0x9a, 0x18c: 0x9b,
- 0x191: 0x1f, 0x192: 0x20, 0x193: 0x9c,
- 0x1a8: 0x9d, 0x1a9: 0x9e, 0x1ab: 0x9f,
- 0x1b1: 0xa0, 0x1b3: 0xa1, 0x1b5: 0xa2, 0x1b7: 0xa3,
- 0x1ba: 0xa4, 0x1bb: 0xa5, 0x1bc: 0x21, 0x1bd: 0x22, 0x1be: 0x23, 0x1bf: 0xa6,
+ 0x180: 0x91, 0x181: 0x92, 0x182: 0x93, 0x183: 0x94, 0x184: 0x19, 0x185: 0x1a, 0x186: 0x95, 0x187: 0x96,
+ 0x188: 0x97, 0x189: 0x1b, 0x18a: 0x1c, 0x18b: 0x98, 0x18c: 0x99,
+ 0x191: 0x1d, 0x192: 0x1e, 0x193: 0x9a,
+ 0x1a8: 0x9b, 0x1a9: 0x9c, 0x1ab: 0x9d,
+ 0x1b1: 0x9e, 0x1b3: 0x9f, 0x1b5: 0xa0, 0x1b7: 0xa1,
+ 0x1ba: 0xa2, 0x1bb: 0xa3, 0x1bc: 0x1f, 0x1bd: 0x20, 0x1be: 0x21, 0x1bf: 0xa4,
// Block 0x7, offset 0x1c0
- 0x1c0: 0xa7, 0x1c1: 0x24, 0x1c2: 0x25, 0x1c3: 0x26, 0x1c4: 0xa8, 0x1c5: 0xa9, 0x1c6: 0x27,
- 0x1c8: 0x28, 0x1c9: 0x29, 0x1ca: 0x2a, 0x1cb: 0x2b, 0x1cc: 0x2c, 0x1cd: 0x2d, 0x1ce: 0x2e, 0x1cf: 0x2f,
+ 0x1c0: 0xa5, 0x1c1: 0x22, 0x1c2: 0x23, 0x1c3: 0x24, 0x1c4: 0xa6, 0x1c5: 0xa7, 0x1c6: 0x25,
+ 0x1c8: 0x26, 0x1c9: 0x27, 0x1ca: 0x28, 0x1cb: 0x29, 0x1cc: 0x2a, 0x1cd: 0x2b, 0x1ce: 0x2c, 0x1cf: 0x2d,
// Block 0x8, offset 0x200
- 0x219: 0xaa, 0x21b: 0xab, 0x21d: 0xac,
- 0x220: 0xad, 0x223: 0xae, 0x224: 0xaf, 0x225: 0xb0, 0x226: 0xb1, 0x227: 0xb2,
- 0x22a: 0xb3, 0x22b: 0xb4, 0x22f: 0xb5,
- 0x230: 0xb6, 0x231: 0xb6, 0x232: 0xb6, 0x233: 0xb6, 0x234: 0xb6, 0x235: 0xb6, 0x236: 0xb6, 0x237: 0xb6,
- 0x238: 0xb6, 0x239: 0xb6, 0x23a: 0xb6, 0x23b: 0xb6, 0x23c: 0xb6, 0x23d: 0xb6, 0x23e: 0xb6, 0x23f: 0xb6,
+ 0x219: 0xa8, 0x21b: 0xa9, 0x21d: 0xaa,
+ 0x220: 0xab, 0x223: 0xac, 0x224: 0xad, 0x225: 0xae, 0x226: 0xaf, 0x227: 0xb0,
+ 0x22a: 0xb1, 0x22b: 0xb2, 0x22f: 0xb3,
+ 0x230: 0xb4, 0x231: 0xb4, 0x232: 0xb4, 0x233: 0xb4, 0x234: 0xb4, 0x235: 0xb4, 0x236: 0xb4, 0x237: 0xb4,
+ 0x238: 0xb4, 0x239: 0xb4, 0x23a: 0xb4, 0x23b: 0xb4, 0x23c: 0xb4, 0x23d: 0xb4, 0x23e: 0xb4, 0x23f: 0xb4,
// Block 0x9, offset 0x240
- 0x240: 0xb6, 0x241: 0xb6, 0x242: 0xb6, 0x243: 0xb6, 0x244: 0xb6, 0x245: 0xb6, 0x246: 0xb6, 0x247: 0xb6,
- 0x248: 0xb6, 0x249: 0xb6, 0x24a: 0xb6, 0x24b: 0xb6, 0x24c: 0xb6, 0x24d: 0xb6, 0x24e: 0xb6, 0x24f: 0xb6,
- 0x250: 0xb6, 0x251: 0xb6, 0x252: 0xb6, 0x253: 0xb6, 0x254: 0xb6, 0x255: 0xb6, 0x256: 0xb6, 0x257: 0xb6,
- 0x258: 0xb6, 0x259: 0xb6, 0x25a: 0xb6, 0x25b: 0xb6, 0x25c: 0xb6, 0x25d: 0xb6, 0x25e: 0xb6, 0x25f: 0xb6,
- 0x260: 0xb6, 0x261: 0xb6, 0x262: 0xb6, 0x263: 0xb6, 0x264: 0xb6, 0x265: 0xb6, 0x266: 0xb6, 0x267: 0xb6,
- 0x268: 0xb6, 0x269: 0xb6, 0x26a: 0xb6, 0x26b: 0xb6, 0x26c: 0xb6, 0x26d: 0xb6, 0x26e: 0xb6, 0x26f: 0xb6,
- 0x270: 0xb6, 0x271: 0xb6, 0x272: 0xb6, 0x273: 0xb6, 0x274: 0xb6, 0x275: 0xb6, 0x276: 0xb6, 0x277: 0xb6,
- 0x278: 0xb6, 0x279: 0xb6, 0x27a: 0xb6, 0x27b: 0xb6, 0x27c: 0xb6, 0x27d: 0xb6, 0x27e: 0xb6, 0x27f: 0xb6,
+ 0x240: 0xb4, 0x241: 0xb4, 0x242: 0xb4, 0x243: 0xb4, 0x244: 0xb4, 0x245: 0xb4, 0x246: 0xb4, 0x247: 0xb4,
+ 0x248: 0xb4, 0x249: 0xb4, 0x24a: 0xb4, 0x24b: 0xb4, 0x24c: 0xb4, 0x24d: 0xb4, 0x24e: 0xb4, 0x24f: 0xb4,
+ 0x250: 0xb4, 0x251: 0xb4, 0x252: 0xb4, 0x253: 0xb4, 0x254: 0xb4, 0x255: 0xb4, 0x256: 0xb4, 0x257: 0xb4,
+ 0x258: 0xb4, 0x259: 0xb4, 0x25a: 0xb4, 0x25b: 0xb4, 0x25c: 0xb4, 0x25d: 0xb4, 0x25e: 0xb4, 0x25f: 0xb4,
+ 0x260: 0xb4, 0x261: 0xb4, 0x262: 0xb4, 0x263: 0xb4, 0x264: 0xb4, 0x265: 0xb4, 0x266: 0xb4, 0x267: 0xb4,
+ 0x268: 0xb4, 0x269: 0xb4, 0x26a: 0xb4, 0x26b: 0xb4, 0x26c: 0xb4, 0x26d: 0xb4, 0x26e: 0xb4, 0x26f: 0xb4,
+ 0x270: 0xb4, 0x271: 0xb4, 0x272: 0xb4, 0x273: 0xb4, 0x274: 0xb4, 0x275: 0xb4, 0x276: 0xb4, 0x277: 0xb4,
+ 0x278: 0xb4, 0x279: 0xb4, 0x27a: 0xb4, 0x27b: 0xb4, 0x27c: 0xb4, 0x27d: 0xb4, 0x27e: 0xb4, 0x27f: 0xb4,
// Block 0xa, offset 0x280
- 0x280: 0xb6, 0x281: 0xb6, 0x282: 0xb6, 0x283: 0xb6, 0x284: 0xb6, 0x285: 0xb6, 0x286: 0xb6, 0x287: 0xb6,
- 0x288: 0xb6, 0x289: 0xb6, 0x28a: 0xb6, 0x28b: 0xb6, 0x28c: 0xb6, 0x28d: 0xb6, 0x28e: 0xb6, 0x28f: 0xb6,
- 0x290: 0xb6, 0x291: 0xb6, 0x292: 0xb6, 0x293: 0xb6, 0x294: 0xb6, 0x295: 0xb6, 0x296: 0xb6, 0x297: 0xb6,
- 0x298: 0xb6, 0x299: 0xb6, 0x29a: 0xb6, 0x29b: 0xb6, 0x29c: 0xb6, 0x29d: 0xb6, 0x29e: 0xb7,
+ 0x280: 0xb4, 0x281: 0xb4, 0x282: 0xb4, 0x283: 0xb4, 0x284: 0xb4, 0x285: 0xb4, 0x286: 0xb4, 0x287: 0xb4,
+ 0x288: 0xb4, 0x289: 0xb4, 0x28a: 0xb4, 0x28b: 0xb4, 0x28c: 0xb4, 0x28d: 0xb4, 0x28e: 0xb4, 0x28f: 0xb4,
+ 0x290: 0xb4, 0x291: 0xb4, 0x292: 0xb4, 0x293: 0xb4, 0x294: 0xb4, 0x295: 0xb4, 0x296: 0xb4, 0x297: 0xb4,
+ 0x298: 0xb4, 0x299: 0xb4, 0x29a: 0xb4, 0x29b: 0xb4, 0x29c: 0xb4, 0x29d: 0xb4, 0x29e: 0xb5,
// Block 0xb, offset 0x2c0
- 0x2e4: 0x30, 0x2e5: 0x31, 0x2e6: 0x32, 0x2e7: 0x33,
- 0x2e8: 0x34, 0x2e9: 0x35, 0x2ea: 0x36, 0x2eb: 0x37, 0x2ec: 0x38, 0x2ed: 0x39, 0x2ee: 0x3a, 0x2ef: 0x3b,
- 0x2f0: 0x3c, 0x2f1: 0x3d, 0x2f2: 0x3e, 0x2f3: 0x3f, 0x2f4: 0x40, 0x2f5: 0x41, 0x2f6: 0x42, 0x2f7: 0x43,
- 0x2f8: 0x44, 0x2f9: 0x45, 0x2fa: 0x46, 0x2fb: 0x47, 0x2fc: 0xb8, 0x2fd: 0x48, 0x2fe: 0x49, 0x2ff: 0xb9,
+ 0x2e4: 0x2e, 0x2e5: 0x2f, 0x2e6: 0x30, 0x2e7: 0x31,
+ 0x2e8: 0x32, 0x2e9: 0x33, 0x2ea: 0x34, 0x2eb: 0x35, 0x2ec: 0x36, 0x2ed: 0x37, 0x2ee: 0x38, 0x2ef: 0x39,
+ 0x2f0: 0x3a, 0x2f1: 0x3b, 0x2f2: 0x3c, 0x2f3: 0x3d, 0x2f4: 0x3e, 0x2f5: 0x3f, 0x2f6: 0x40, 0x2f7: 0x41,
+ 0x2f8: 0x42, 0x2f9: 0x43, 0x2fa: 0x44, 0x2fb: 0x45, 0x2fc: 0xb6, 0x2fd: 0x46, 0x2fe: 0x47, 0x2ff: 0xb7,
// Block 0xc, offset 0x300
- 0x307: 0xba,
- 0x328: 0xbb,
+ 0x307: 0xb8,
+ 0x328: 0xb9,
// Block 0xd, offset 0x340
- 0x341: 0xad, 0x342: 0xbc,
+ 0x341: 0xab, 0x342: 0xba,
// Block 0xe, offset 0x380
- 0x385: 0xbd, 0x386: 0xbe, 0x387: 0xbf,
- 0x389: 0xc0,
- 0x390: 0xc1, 0x391: 0xc2, 0x392: 0xc3, 0x393: 0xc4, 0x394: 0xc5, 0x395: 0xc6, 0x396: 0xc7, 0x397: 0xc8,
- 0x398: 0xc9, 0x399: 0xca, 0x39a: 0x4a, 0x39b: 0xcb, 0x39c: 0xcc, 0x39d: 0xcd, 0x39e: 0xce, 0x39f: 0x4b,
+ 0x385: 0xbb, 0x386: 0xbc, 0x387: 0xbd,
+ 0x389: 0xbe,
+ 0x390: 0xbf, 0x391: 0xc0, 0x392: 0xc1, 0x393: 0xc2, 0x394: 0xc3, 0x395: 0xc4, 0x396: 0xc5, 0x397: 0xc6,
+ 0x398: 0xc7, 0x399: 0xc8, 0x39a: 0x48, 0x39b: 0xc9, 0x39c: 0xca, 0x39d: 0xcb, 0x39e: 0xcc, 0x39f: 0x49,
// Block 0xf, offset 0x3c0
- 0x3c4: 0x4c, 0x3c5: 0xcf, 0x3c6: 0xd0,
- 0x3c8: 0x4d, 0x3c9: 0xd1,
+ 0x3c4: 0x4a, 0x3c5: 0xcd, 0x3c6: 0xce,
+ 0x3c8: 0x4b, 0x3c9: 0xcf,
// Block 0x10, offset 0x400
- 0x420: 0x4e, 0x421: 0x4f, 0x422: 0x50, 0x423: 0x51, 0x424: 0x52, 0x425: 0x53, 0x426: 0x54, 0x427: 0x55,
- 0x428: 0x56,
+ 0x420: 0x4c, 0x421: 0x4d, 0x422: 0x4e, 0x423: 0x4f, 0x424: 0x50, 0x425: 0x51, 0x426: 0x52, 0x427: 0x53,
+ 0x428: 0x54,
// Block 0x11, offset 0x440
- 0x450: 0x0c, 0x451: 0x0d,
- 0x45d: 0x0e, 0x45f: 0x0f,
- 0x46f: 0x10,
+ 0x450: 0x0a, 0x451: 0x0b,
+ 0x45d: 0x0c, 0x45f: 0x0d,
+ 0x46f: 0x0e,
}
-var nfkcTrie = trie{nfkcLookup[:], nfkcValues[:], nfkcSparseValues[:], nfkcSparseOffset[:], 87}
+var nfkcTrie = trie{nfkcLookup[:], nfkcValues[:], nfkcSparseValues[:], nfkcSparseOffset[:], 85}
// recompMap: 7448 bytes (entries only)
var recompMap = map[uint32]rune{
diff --git a/libgo/go/exp/norm/trie.go b/libgo/go/exp/norm/trie.go
index 93cb9c33903..82267a8d37f 100644
--- a/libgo/go/exp/norm/trie.go
+++ b/libgo/go/exp/norm/trie.go
@@ -23,7 +23,7 @@ type trie struct {
// 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)]
+ return t.values[uint16(n)<<6+uint16(b)]
}
offset := t.sparseOffset[n-t.cutoff]
header := t.sparse[offset]
@@ -53,11 +53,6 @@ const (
t5 = 0xF8 // 1111 1000
t6 = 0xFC // 1111 1100
te = 0xFE // 1111 1110
-
- maskx = 0x3F // 0011 1111
- mask2 = 0x1F // 0001 1111
- mask3 = 0x0F // 0000 1111
- mask4 = 0x07 // 0000 0111
)
// lookup returns the trie value for the first UTF-8 encoding in s and
@@ -89,7 +84,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
+ o := uint16(i)<<6 + uint16(c1)
i = t.index[o]
c2 := s[2]
if c2 < tx || t2 <= c2 {
@@ -105,13 +100,13 @@ 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
+ o := uint16(i)<<6 + uint16(c1)
i = t.index[o]
c2 := s[2]
if c2 < tx || t2 <= c2 {
return 0, 2
}
- o = uint16(i)<<6 + uint16(c2)&maskx
+ o = uint16(i)<<6 + uint16(c2)
i = t.index[o]
c3 := s[3]
if c3 < tx || t2 <= c3 {
@@ -152,7 +147,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
+ o := uint16(i)<<6 + uint16(c1)
i = t.index[o]
c2 := s[2]
if c2 < tx || t2 <= c2 {
@@ -168,13 +163,13 @@ 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
+ o := uint16(i)<<6 + uint16(c1)
i = t.index[o]
c2 := s[2]
if c2 < tx || t2 <= c2 {
return 0, 2
}
- o = uint16(i)<<6 + uint16(c2)&maskx
+ o = uint16(i)<<6 + uint16(c2)
i = t.index[o]
c3 := s[3]
if c3 < tx || t2 <= c3 {
@@ -200,11 +195,11 @@ func (t *trie) lookupUnsafe(s []byte) uint16 {
if c0 < t3 {
return t.lookupValue(i, s[1])
}
- i = t.index[uint16(i)<<6+uint16(s[1])&maskx]
+ i = t.index[uint16(i)<<6+uint16(s[1])]
if c0 < t4 {
return t.lookupValue(i, s[2])
}
- i = t.index[uint16(i)<<6+uint16(s[2])&maskx]
+ i = t.index[uint16(i)<<6+uint16(s[2])]
if c0 < t5 {
return t.lookupValue(i, s[3])
}
@@ -225,11 +220,11 @@ func (t *trie) lookupStringUnsafe(s string) uint16 {
if c0 < t3 {
return t.lookupValue(i, s[1])
}
- i = t.index[uint16(i)<<6+uint16(s[1])&maskx]
+ i = t.index[uint16(i)<<6+uint16(s[1])]
if c0 < t4 {
return t.lookupValue(i, s[2])
}
- i = t.index[uint16(i)<<6+uint16(s[2])&maskx]
+ i = t.index[uint16(i)<<6+uint16(s[2])]
if c0 < t5 {
return t.lookupValue(i, s[3])
}
diff --git a/libgo/go/exp/norm/trie_test.go b/libgo/go/exp/norm/trie_test.go
index c457c9d974a..1a75cc70568 100644
--- a/libgo/go/exp/norm/trie_test.go
+++ b/libgo/go/exp/norm/trie_test.go
@@ -96,13 +96,17 @@ func TestLookup(t *testing.T) {
}
for i, tt := range tests {
v, sz := testdata.lookup(tt.bytes)
- if int(v) != 0 {
+ if v != 0 {
t.Errorf("lookup of illegal rune, case %d: found value %#x, expected 0", i, v)
}
if sz != tt.size {
t.Errorf("lookup of illegal rune, case %d: found size %d, expected %d", i, sz, tt.size)
}
}
+ // Verify defaults.
+ if v, _ := testdata.lookup([]byte{0xC1, 0x8C}); v != 0 {
+ t.Errorf("lookup of non-existing rune should be 0; found %X", v)
+ }
}
func TestLookupUnsafe(t *testing.T) {
diff --git a/libgo/go/exp/norm/triedata_test.go b/libgo/go/exp/norm/triedata_test.go
index 7f6276096c5..d6c832d46a1 100644
--- a/libgo/go/exp/norm/triedata_test.go
+++ b/libgo/go/exp/norm/triedata_test.go
@@ -4,7 +4,7 @@
package norm
-var testRunes = []rune{1, 12, 127, 128, 256, 2047, 2048, 2457, 65535, 65536, 65793, 1114111, 512, 513, 514, 528, 533}
+var testRunes = []int32{1, 12, 127, 128, 256, 2047, 2048, 2457, 65535, 65536, 65793, 1114111, 512, 513, 514, 528, 533}
// testdataValues: 192 entries, 384 bytes
// Block 2 is the null block.
@@ -62,24 +62,24 @@ var testdataLookup = [640]uint8{
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
- 0x0c2: 0x03, 0x0c4: 0x04,
- 0x0c8: 0x05,
- 0x0df: 0x06,
- 0x0e0: 0x04,
- 0x0ef: 0x05,
- 0x0f0: 0x07, 0x0f4: 0x09,
+ 0x0c2: 0x01, 0x0c4: 0x02,
+ 0x0c8: 0x03,
+ 0x0df: 0x04,
+ 0x0e0: 0x02,
+ 0x0ef: 0x03,
+ 0x0f0: 0x05, 0x0f4: 0x07,
// Block 0x4, offset 0x100
- 0x120: 0x07, 0x126: 0x08,
+ 0x120: 0x05, 0x126: 0x06,
// Block 0x5, offset 0x140
- 0x17f: 0x09,
+ 0x17f: 0x07,
// Block 0x6, offset 0x180
- 0x180: 0x0a, 0x184: 0x0b,
+ 0x180: 0x08, 0x184: 0x09,
// Block 0x7, offset 0x1c0
- 0x1d0: 0x06,
+ 0x1d0: 0x04,
// Block 0x8, offset 0x200
- 0x23f: 0x0c,
+ 0x23f: 0x0a,
// Block 0x9, offset 0x240
- 0x24f: 0x08,
+ 0x24f: 0x06,
}
-var testdataTrie = trie{testdataLookup[:], testdataValues[:], testdataSparseValues[:], testdataSparseOffset[:], 3}
+var testdataTrie = trie{testdataLookup[:], testdataValues[:], testdataSparseValues[:], testdataSparseOffset[:], 1}
diff --git a/libgo/go/exp/norm/triegen.go b/libgo/go/exp/norm/triegen.go
index 2e275a06254..1780ac7129d 100644
--- a/libgo/go/exp/norm/triegen.go
+++ b/libgo/go/exp/norm/triegen.go
@@ -19,8 +19,11 @@ import (
"unicode/utf8"
)
-const blockSize = 64
-const maxSparseEntries = 16
+const (
+ blockSize = 64
+ blockOffset = 2 // Substract two blocks to compensate for the 0x80 added to continuation bytes.
+ maxSparseEntries = 16
+)
// Intermediate trie structure
type trieNode struct {
@@ -157,7 +160,7 @@ func computeOffsets(index *nodeIndex, n *trieNode) int {
if n.isInternal() {
v, ok := index.lookupBlockIdx[h]
if !ok {
- v = len(index.lookupBlocks)
+ v = len(index.lookupBlocks) - blockOffset
index.lookupBlocks = append(index.lookupBlocks, n)
index.lookupBlockIdx[h] = v
}
@@ -166,7 +169,7 @@ func computeOffsets(index *nodeIndex, n *trieNode) int {
v, ok := index.valueBlockIdx[h]
if !ok {
if c := n.countSparseEntries(); c > maxSparseEntries {
- v = len(index.valueBlocks)
+ v = len(index.valueBlocks) - blockOffset
index.valueBlocks = append(index.valueBlocks, n)
index.valueBlockIdx[h] = v
} else {
@@ -295,7 +298,7 @@ func (t *trieNode) printTables(name string) int {
}
fmt.Print("\n}\n\n")
- cutoff := len(index.valueBlocks)
+ cutoff := len(index.valueBlocks) - blockOffset
ni := len(index.lookupBlocks) * blockSize
fmt.Printf("// %sLookup: %d bytes\n", name, ni)
fmt.Printf("// Block 0 is the null block.\n")
diff --git a/libgo/go/exp/types/check.go b/libgo/go/exp/types/check.go
index ae0beb4e9b0..bd947a1639f 100644
--- a/libgo/go/exp/types/check.go
+++ b/libgo/go/exp/types/check.go
@@ -30,6 +30,7 @@ func (c *checker) errorf(pos token.Pos, format string, args ...interface{}) stri
// collectFields collects struct fields tok = token.STRUCT), interface methods
// (tok = token.INTERFACE), and function arguments/results (tok = token.FUNC).
+//
func (c *checker) collectFields(tok token.Token, list *ast.FieldList, cycleOk bool) (fields ObjList, tags []string, isVariadic bool) {
if list != nil {
for _, field := range list.List {
@@ -104,7 +105,7 @@ func (c *checker) makeType(x ast.Expr, cycleOk bool) (typ Type) {
obj := t.Obj
if obj == nil {
// unresolved identifier (error has been reported before)
- return &Bad{Msg: "unresolved identifier"}
+ return &Bad{Msg: fmt.Sprintf("%s is unresolved", t.Name)}
}
if obj.Kind != ast.Typ {
msg := c.errorf(t.Pos(), "%s is not a type", t.Name)
@@ -112,10 +113,7 @@ func (c *checker) makeType(x ast.Expr, cycleOk bool) (typ Type) {
}
c.checkObj(obj, cycleOk)
if !cycleOk && obj.Type.(*Name).Underlying == nil {
- // TODO(gri) Enable this message again once its position
- // is independent of the underlying map implementation.
- // msg := c.errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name)
- msg := "illegal cycle"
+ msg := c.errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name)
return &Bad{Msg: msg}
}
return obj.Type.(Type)
@@ -158,8 +156,8 @@ func (c *checker) makeType(x ast.Expr, cycleOk bool) (typ Type) {
return &Struct{Fields: fields, Tags: tags}
case *ast.FuncType:
- params, _, _ := c.collectFields(token.FUNC, t.Params, true)
- results, _, isVariadic := c.collectFields(token.FUNC, t.Results, true)
+ params, _, isVariadic := c.collectFields(token.FUNC, t.Params, true)
+ results, _, _ := c.collectFields(token.FUNC, t.Results, true)
return &Func{Recv: nil, Params: params, Results: results, IsVariadic: isVariadic}
case *ast.InterfaceType:
@@ -168,7 +166,7 @@ func (c *checker) makeType(x ast.Expr, cycleOk bool) (typ Type) {
return &Interface{Methods: methods}
case *ast.MapType:
- return &Map{Key: c.makeType(t.Key, true), Elt: c.makeType(t.Key, true)}
+ return &Map{Key: c.makeType(t.Key, true), Elt: c.makeType(t.Value, true)}
case *ast.ChanType:
return &Chan{Dir: t.Dir, Elt: c.makeType(t.Value, true)}
@@ -200,7 +198,21 @@ func (c *checker) checkObj(obj *ast.Object, ref bool) {
// TODO(gri) complete this
case ast.Fun:
- // TODO(gri) complete this
+ fdecl := obj.Decl.(*ast.FuncDecl)
+ ftyp := c.makeType(fdecl.Type, ref).(*Func)
+ obj.Type = ftyp
+ if fdecl.Recv != nil {
+ recvField := fdecl.Recv.List[0]
+ if len(recvField.Names) > 0 {
+ ftyp.Recv = recvField.Names[0].Obj
+ } else {
+ ftyp.Recv = ast.NewObj(ast.Var, "_")
+ ftyp.Recv.Decl = recvField
+ }
+ c.checkObj(ftyp.Recv, ref)
+ // TODO(axw) add method to a list in the receiver type.
+ }
+ // TODO(axw) check function body, if non-nil.
default:
panic("unreachable")
@@ -213,11 +225,25 @@ func (c *checker) checkObj(obj *ast.Object, ref bool) {
// there are errors.
//
func Check(fset *token.FileSet, pkg *ast.Package) (types map[ast.Expr]Type, err error) {
+ // Sort objects so that we get reproducible error
+ // positions (this is only needed for testing).
+ // TODO(gri): Consider ast.Scope implementation that
+ // provides both a list and a map for fast lookup.
+ // Would permit the use of scopes instead of ObjMaps
+ // elsewhere.
+ list := make(ObjList, len(pkg.Scope.Objects))
+ i := 0
+ for _, obj := range pkg.Scope.Objects {
+ list[i] = obj
+ i++
+ }
+ list.Sort()
+
var c checker
c.fset = fset
c.types = make(map[ast.Expr]Type)
- for _, obj := range pkg.Scope.Objects {
+ for _, obj := range list {
c.checkObj(obj, false)
}
diff --git a/libgo/go/exp/types/check_test.go b/libgo/go/exp/types/check_test.go
index 34c26c9908c..50c58e3691e 100644
--- a/libgo/go/exp/types/check_test.go
+++ b/libgo/go/exp/types/check_test.go
@@ -23,13 +23,13 @@
package types
import (
- "fmt"
+ // "fmt"
"go/ast"
"go/parser"
"go/scanner"
"go/token"
"io/ioutil"
- "os"
+ // "os"
"regexp"
"testing"
)
@@ -167,6 +167,10 @@ func eliminate(t *testing.T, expected map[token.Pos]string, errors error) {
}
}
+/*
+
+This test doesn't work with gccgo--it can't read gccgo imports.
+
func check(t *testing.T, testname string, testfiles []string) {
// TODO(gri) Eventually all these different phases should be
// subsumed into a single function call that takes
@@ -203,7 +207,7 @@ func check(t *testing.T, testname string, testfiles []string) {
func TestCheck(t *testing.T) {
// For easy debugging w/o changing the testing code,
// if there is a local test file, only test that file.
- const testfile = "test.go"
+ const testfile = "testdata/test.go"
if fi, err := os.Stat(testfile); err == nil && !fi.IsDir() {
fmt.Printf("WARNING: Testing only %s (remove it to run all tests)\n", testfile)
check(t, testfile, []string{testfile})
@@ -215,3 +219,5 @@ func TestCheck(t *testing.T) {
check(t, test.name, test.files)
}
}
+
+*/
diff --git a/libgo/go/exp/types/exportdata.go b/libgo/go/exp/types/exportdata.go
index bca2038804e..22190153bbf 100644
--- a/libgo/go/exp/types/exportdata.go
+++ b/libgo/go/exp/types/exportdata.go
@@ -52,13 +52,14 @@ func FindGcExportData(r *bufio.Reader) (err error) {
var name string
var size int
- // First entry should be __.SYMDEF.
+ // First entry should be __.GOSYMDEF.
+ // Older archives used __.SYMDEF, so allow that too.
// Read and discard.
if name, size, err = readGopackHeader(r); err != nil {
return
}
- if name != "__.SYMDEF" {
- err = errors.New("go archive does not begin with __.SYMDEF")
+ if name != "__.SYMDEF" && name != "__.GOSYMDEF" {
+ err = errors.New("go archive does not begin with __.SYMDEF or __.GOSYMDEF")
return
}
const block = 4096
diff --git a/libgo/go/exp/types/gcimporter.go b/libgo/go/exp/types/gcimporter.go
index 07ab087abf8..51121b76674 100644
--- a/libgo/go/exp/types/gcimporter.go
+++ b/libgo/go/exp/types/gcimporter.go
@@ -42,7 +42,8 @@ func FindPkg(path, srcDir string) (filename, id string) {
switch {
default:
// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
- bp, _ := build.Import(path, srcDir, build.FindOnly)
+ // Don't require the source files to be present.
+ bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
if bp.PkgObj == "" {
return
}
@@ -89,10 +90,6 @@ func GcImportData(imports map[string]*ast.Object, filename, id string, data *buf
fmt.Printf("importing %s (%s)\n", id, filename)
}
- if imports[id] != nil {
- panic(fmt.Sprintf("package %s already imported", id))
- }
-
// support for gcParser error handling
defer func() {
if r := recover(); r != nil {
@@ -128,9 +125,12 @@ func GcImport(imports map[string]*ast.Object, path string) (pkg *ast.Object, err
return
}
- if pkg = imports[id]; pkg != nil {
- return // package was imported before
- }
+ // Note: imports[id] may already contain a partially imported package.
+ // We must continue doing the full import here since we don't
+ // know if something is missing.
+ // TODO: There's no need to re-import a package if we know that we
+ // have done a full import before. At the moment we cannot
+ // tell from the available information in this function alone.
// open file
f, err := os.Open(filename)
@@ -182,7 +182,7 @@ func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*
func (p *gcParser) next() {
p.tok = p.scanner.Scan()
switch p.tok {
- case scanner.Ident, scanner.Int, scanner.String:
+ case scanner.Ident, scanner.Int, scanner.String, '·':
p.lit = p.scanner.TokenText()
default:
p.lit = ""
@@ -294,9 +294,8 @@ func (p *gcParser) parsePkgId() *ast.Object {
pkg := p.imports[id]
if pkg == nil {
- scope = ast.NewScope(nil)
pkg = ast.NewObj(ast.Pkg, "")
- pkg.Data = scope
+ pkg.Data = ast.NewScope(nil)
p.imports[id] = pkg
}
@@ -509,32 +508,21 @@ func (p *gcParser) parseSignature() *Func {
return &Func{Params: params, Results: results, IsVariadic: isVariadic}
}
-// MethodOrEmbedSpec = Name [ Signature ] .
+// InterfaceType = "interface" "{" [ MethodList ] "}" .
+// MethodList = Method { ";" Method } .
+// Method = Name Signature .
//
-func (p *gcParser) parseMethodOrEmbedSpec() *ast.Object {
- p.parseName()
- if p.tok == '(' {
- p.parseSignature()
- // TODO(gri) compute method object
- return ast.NewObj(ast.Fun, "_")
- }
- // TODO lookup name and return that type
- return ast.NewObj(ast.Typ, "_")
-}
-
-// InterfaceType = "interface" "{" [ MethodOrEmbedList ] "}" .
-// MethodOrEmbedList = MethodOrEmbedSpec { ";" MethodOrEmbedSpec } .
+// (The methods of embedded interfaces are always "inlined"
+// by the compiler and thus embedded interfaces are never
+// visible in the export data.)
//
func (p *gcParser) parseInterfaceType() Type {
var methods ObjList
parseMethod := func() {
- switch m := p.parseMethodOrEmbedSpec(); m.Kind {
- case ast.Typ:
- // TODO expand embedded methods
- case ast.Fun:
- methods = append(methods, m)
- }
+ obj := ast.NewObj(ast.Fun, p.parseName())
+ obj.Type = p.parseSignature()
+ methods = append(methods, obj)
}
p.expectKeyword("interface")
@@ -664,7 +652,7 @@ func (p *gcParser) parseInt() (sign, val string) {
func (p *gcParser) parseNumber() Const {
// mantissa
sign, val := p.parseInt()
- mant, ok := new(big.Int).SetString(sign+val, 10)
+ mant, ok := new(big.Int).SetString(sign+val, 0)
assert(ok)
if p.lit == "p" {
@@ -693,7 +681,7 @@ func (p *gcParser) parseNumber() Const {
// ConstDecl = "const" ExportedName [ Type ] "=" Literal .
// Literal = bool_lit | int_lit | float_lit | complex_lit | string_lit .
// bool_lit = "true" | "false" .
-// complex_lit = "(" float_lit "+" float_lit ")" .
+// complex_lit = "(" float_lit "+" float_lit "i" ")" .
// rune_lit = "(" int_lit "+" int_lit ")" .
// string_lit = `"` { unicode_char } `"` .
//
@@ -737,6 +725,7 @@ func (p *gcParser) parseConstDecl() {
re := p.parseNumber()
p.expect('+')
im := p.parseNumber()
+ p.expectKeyword("i")
p.expect(')')
x = Const{cmplx{re.val.(*big.Rat), im.val.(*big.Rat)}}
typ = Complex128.Underlying
@@ -867,10 +856,12 @@ func (p *gcParser) parseExport() *ast.Object {
}
p.expect('\n')
- assert(p.imports[p.id] == nil)
- pkg := ast.NewObj(ast.Pkg, name)
- pkg.Data = ast.NewScope(nil)
- p.imports[p.id] = pkg
+ pkg := p.imports[p.id]
+ if pkg == nil {
+ pkg = ast.NewObj(ast.Pkg, name)
+ pkg.Data = ast.NewScope(nil)
+ p.imports[p.id] = pkg
+ }
for p.tok != '$' && p.tok != scanner.EOF {
p.parseDecl()
diff --git a/libgo/go/exp/types/gcimporter_test.go b/libgo/go/exp/types/gcimporter_test.go
index 20247b0dc44..0fed72abdd5 100644
--- a/libgo/go/exp/types/gcimporter_test.go
+++ b/libgo/go/exp/types/gcimporter_test.go
@@ -36,15 +36,17 @@ func init() {
gcPath = filepath.Join(build.ToolDir, gc)
}
-func compile(t *testing.T, dirname, filename string) {
+func compile(t *testing.T, dirname, filename string) string {
cmd := exec.Command(gcPath, filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
- t.Errorf("%s %s failed: %s", gcPath, filename, err)
- return
+ t.Logf("%s", out)
+ t.Fatalf("%s %s failed: %s", gcPath, filename, err)
}
- t.Logf("%s", string(out))
+ archCh, _ := build.ArchChar(runtime.GOARCH)
+ // filename should end with ".go"
+ return filepath.Join(dirname, filename[:len(filename)-2]+archCh)
}
// Use the same global imports map for all tests. The effect is
@@ -99,7 +101,9 @@ func TestGcImport(t *testing.T) {
return
}
- compile(t, "testdata", "exports.go")
+ if outFn := compile(t, "testdata", "exports.go"); outFn != "" {
+ defer os.Remove(outFn)
+ }
nimports := 0
if testPath(t, "./testdata/exports") {
@@ -108,3 +112,48 @@ func TestGcImport(t *testing.T) {
nimports += testDir(t, "", time.Now().Add(maxTime)) // installed packages
t.Logf("tested %d imports", nimports)
}
+
+/*
+
+Does not work with gccgo.
+
+var importedObjectTests = []struct {
+ name string
+ kind ast.ObjKind
+ typ string
+}{
+ {"unsafe.Pointer", ast.Typ, "Pointer"},
+ {"math.Pi", ast.Con, "basicType"}, // TODO(gri) need to complete BasicType
+ {"io.Reader", ast.Typ, "interface{Read(p []byte) (n int, err error)}"},
+ {"io.ReadWriter", ast.Typ, "interface{Read(p []byte) (n int, err error); Write(p []byte) (n int, err error)}"},
+ {"math.Sin", ast.Fun, "func(x float64) (_ float64)"},
+ // TODO(gri) add more tests
+}
+
+func TestGcImportedTypes(t *testing.T) {
+ for _, test := range importedObjectTests {
+ s := strings.Split(test.name, ".")
+ if len(s) != 2 {
+ t.Fatal("inconsistent test data")
+ }
+ importPath := s[0]
+ objName := s[1]
+
+ pkg, err := GcImport(imports, importPath)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+
+ obj := pkg.Data.(*ast.Scope).Lookup(objName)
+ if obj.Kind != test.kind {
+ t.Errorf("%s: got kind = %q; want %q", test.name, obj.Kind, test.kind)
+ }
+ typ := TypeString(Underlying(obj.Type.(Type)))
+ if typ != test.typ {
+ t.Errorf("%s: got type = %q; want %q", test.name, typ, test.typ)
+ }
+ }
+}
+
+*/
diff --git a/libgo/go/exp/types/resolver_test.go b/libgo/go/exp/types/resolver_test.go
new file mode 100644
index 00000000000..15b01419327
--- /dev/null
+++ b/libgo/go/exp/types/resolver_test.go
@@ -0,0 +1,136 @@
+// 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 types
+
+import (
+ "fmt"
+ "go/ast"
+ // "go/parser"
+ "go/scanner"
+ "go/token"
+ // "testing"
+)
+
+var sources = []string{
+ `package p
+ import "fmt"
+ import "math"
+ const pi = math.Pi
+ func sin(x float64) float64 {
+ return math.Sin(x)
+ }
+ var Println = fmt.Println
+ `,
+ `package p
+ import "fmt"
+ func f() string {
+ return fmt.Sprintf("%d", g())
+ }
+ `,
+ `package p
+ import . "go/parser"
+ func g() Mode { return ImportsOnly }`,
+}
+
+var pkgnames = []string{
+ "fmt",
+ "go/parser",
+ "math",
+}
+
+// ResolveQualifiedIdents resolves the selectors of qualified
+// identifiers by associating the correct ast.Object with them.
+// TODO(gri): Eventually, this functionality should be subsumed
+// by Check.
+//
+func ResolveQualifiedIdents(fset *token.FileSet, pkg *ast.Package) error {
+ var errors scanner.ErrorList
+
+ findObj := func(pkg *ast.Object, name *ast.Ident) *ast.Object {
+ scope := pkg.Data.(*ast.Scope)
+ obj := scope.Lookup(name.Name)
+ if obj == nil {
+ errors.Add(fset.Position(name.Pos()), fmt.Sprintf("no %s in package %s", name.Name, pkg.Name))
+ }
+ return obj
+ }
+
+ ast.Inspect(pkg, func(n ast.Node) bool {
+ if s, ok := n.(*ast.SelectorExpr); ok {
+ if x, ok := s.X.(*ast.Ident); ok && x.Obj != nil && x.Obj.Kind == ast.Pkg {
+ // find selector in respective package
+ s.Sel.Obj = findObj(x.Obj, s.Sel)
+ }
+ return false
+ }
+ return true
+ })
+
+ return errors.Err()
+}
+
+/*
+
+Does not work with gccgo.
+
+func TestResolveQualifiedIdents(t *testing.T) {
+ // parse package files
+ fset := token.NewFileSet()
+ files := make(map[string]*ast.File)
+ for i, src := range sources {
+ filename := fmt.Sprintf("file%d", i)
+ f, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
+ if err != nil {
+ t.Fatal(err)
+ }
+ files[filename] = f
+ }
+
+ // resolve package AST
+ pkg, err := ast.NewPackage(fset, files, GcImport, Universe)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // check that all packages were imported
+ for _, name := range pkgnames {
+ if pkg.Imports[name] == nil {
+ t.Errorf("package %s not imported", name)
+ }
+ }
+
+ // check that there are no top-level unresolved identifiers
+ for _, f := range pkg.Files {
+ for _, x := range f.Unresolved {
+ t.Errorf("%s: unresolved global identifier %s", fset.Position(x.Pos()), x.Name)
+ }
+ }
+
+ // resolve qualified identifiers
+ if err := ResolveQualifiedIdents(fset, pkg); err != nil {
+ t.Error(err)
+ }
+
+ // check that qualified identifiers are resolved
+ ast.Inspect(pkg, func(n ast.Node) bool {
+ if s, ok := n.(*ast.SelectorExpr); ok {
+ if x, ok := s.X.(*ast.Ident); ok {
+ if x.Obj == nil {
+ t.Errorf("%s: unresolved qualified identifier %s", fset.Position(x.Pos()), x.Name)
+ return false
+ }
+ if x.Obj.Kind == ast.Pkg && s.Sel != nil && s.Sel.Obj == nil {
+ t.Errorf("%s: unresolved selector %s", fset.Position(s.Sel.Pos()), s.Sel.Name)
+ return false
+ }
+ return false
+ }
+ return false
+ }
+ return true
+ })
+}
+
+*/
diff --git a/libgo/go/exp/types/staging/builtins.go b/libgo/go/exp/types/staging/builtins.go
new file mode 100644
index 00000000000..ef9ae80e2b5
--- /dev/null
+++ b/libgo/go/exp/types/staging/builtins.go
@@ -0,0 +1,349 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements typechecking of builtin function calls.
+
+package types
+
+import (
+ "go/ast"
+ "go/token"
+)
+
+// builtin typechecks a built-in call. The built-in type is bin, and iota is the current
+// value of iota or -1 if iota doesn't have a value in the current context. The result
+// of the call is returned via x. If the call has type errors, the returned x is marked
+// as invalid (x.mode == invalid).
+//
+func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *builtin, iota int) {
+ args := call.Args
+ id := bin.id
+
+ // declare before goto's
+ var arg0 ast.Expr
+ var typ0 Type
+
+ // check argument count
+ n := len(args)
+ msg := ""
+ if n < bin.nargs {
+ msg = "not enough"
+ } else if !bin.isVariadic && n > bin.nargs {
+ msg = "too many"
+ }
+ if msg != "" {
+ check.invalidOp(call.Pos(), msg+"arguments for %s (expected %d, found %d)", call, bin.nargs, n)
+ goto Error
+ }
+
+ // common case: evaluate first argument if present;
+ // if it is an expression, x has the expression value
+ if n > 0 {
+ arg0 = args[0]
+ switch id {
+ case _Make, _New:
+ // argument must be a type
+ typ0 = underlying(check.typ(arg0, false))
+ if typ0 == Typ[Invalid] {
+ goto Error
+ }
+ case _Trace:
+ // _Trace implementation does the work
+ default:
+ // argument must be an expression
+ check.expr(x, arg0, nil, iota)
+ if x.mode == invalid {
+ goto Error
+ }
+ typ0 = underlying(x.typ)
+ }
+ }
+
+ switch id {
+ case _Append:
+ s, ok := typ0.(*Slice)
+ if !ok {
+ check.invalidArg(x.pos(), "%s is not a typed slice", x)
+ goto Error
+ }
+ for _, arg := range args[1:] {
+ check.expr(x, arg, nil, iota)
+ if x.mode == invalid {
+ goto Error
+ }
+ // TODO(gri) check assignability
+ }
+ x.mode = value
+ x.typ = s
+
+ case _Cap, _Len:
+ mode := invalid
+ var val interface{}
+ switch typ := implicitDeref(typ0).(type) {
+ case *Basic:
+ if isString(typ) && id == _Len {
+ if x.mode == constant {
+ mode = constant
+ val = int64(len(x.val.(string)))
+ } else {
+ mode = value
+ }
+ }
+
+ case *Array:
+ mode = value
+ if !containsCallsOrReceives(arg0) {
+ mode = constant
+ val = typ.Len
+ }
+
+ case *Slice, *Chan:
+ mode = value
+
+ case *Map:
+ if id == _Len {
+ mode = value
+ }
+ }
+
+ if mode == invalid {
+ check.invalidArg(x.pos(), "%s for %s", x, bin.name)
+ goto Error
+ }
+ x.mode = mode
+ x.typ = Typ[Int]
+ x.val = val
+
+ case _Close:
+ ch, ok := typ0.(*Chan)
+ if !ok {
+ check.invalidArg(x.pos(), "%s is not a channel", x)
+ goto Error
+ }
+ if ch.Dir&ast.SEND == 0 {
+ check.invalidArg(x.pos(), "%s must not be a receive-only channel", x)
+ goto Error
+ }
+ x.mode = novalue
+
+ case _Complex:
+ var y operand
+ check.expr(&y, args[1], nil, iota)
+ if y.mode == invalid {
+ goto Error
+ }
+ // TODO(gri) handle complex(a, b) like (a + toImag(b))
+ unimplemented()
+
+ case _Copy:
+ // TODO(gri) implements checks
+ unimplemented()
+ x.mode = value
+ x.typ = Typ[Int]
+
+ case _Delete:
+ m, ok := typ0.(*Map)
+ if !ok {
+ check.invalidArg(x.pos(), "%s is not a map", x)
+ goto Error
+ }
+ check.expr(x, args[1], nil, iota)
+ if x.mode == invalid {
+ goto Error
+ }
+ if !x.isAssignable(m.Key) {
+ check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.Key)
+ goto Error
+ }
+ x.mode = novalue
+
+ case _Imag, _Real:
+ if !isComplex(typ0) {
+ check.invalidArg(x.pos(), "%s must be a complex number", x)
+ goto Error
+ }
+ if x.mode == constant {
+ // nothing to do for x.val == 0
+ if !isZeroConst(x.val) {
+ c := x.val.(complex)
+ if id == _Real {
+ x.val = c.re
+ } else {
+ x.val = c.im
+ }
+ }
+ } else {
+ x.mode = value
+ }
+ k := Invalid
+ switch typ0.(*Basic).Kind {
+ case Complex64:
+ k = Float32
+ case Complex128:
+ k = Float64
+ case UntypedComplex:
+ k = UntypedFloat
+ default:
+ unreachable()
+ }
+ x.typ = Typ[k]
+
+ case _Make:
+ var min int // minimum number of arguments
+ switch typ0.(type) {
+ case *Slice:
+ min = 2
+ case *Map, *Chan:
+ min = 1
+ default:
+ check.invalidArg(arg0.Pos(), "cannot make %s; type must be slice, map, or channel", arg0)
+ goto Error
+ }
+ if n := len(args); n < min || min+1 < n {
+ check.errorf(call.Pos(), "%s expects %d or %d arguments; found %d", call, min, min+1, n)
+ goto Error
+ }
+ for _, arg := range args[1:] {
+ check.expr(x, arg, nil, iota)
+ if !x.isInteger() {
+ check.invalidArg(x.pos(), "%s must be an integer", x)
+ // safe to continue
+ }
+ }
+ x.mode = variable
+ x.typ = typ0
+
+ case _New:
+ x.mode = variable
+ x.typ = &Pointer{Base: typ0}
+
+ case _Panic, _Print, _Println:
+ x.mode = novalue
+
+ case _Recover:
+ x.mode = value
+ x.typ = emptyInterface
+
+ case _Alignof:
+ x.mode = constant
+ x.typ = Typ[Uintptr]
+ // For now we return 1 always as it satisfies the spec's alignment guarantees.
+ // TODO(gri) Extend typechecker API so that platform-specific values can be
+ // provided.
+ x.val = int64(1)
+
+ case _Offsetof:
+ if _, ok := unparen(x.expr).(*ast.SelectorExpr); !ok {
+ check.invalidArg(x.pos(), "%s is not a selector", x)
+ goto Error
+ }
+ x.mode = constant
+ x.typ = Typ[Uintptr]
+ // because of the size guarantees for basic types (> 0 for some),
+ // returning 0 is only correct if two distinct non-zero size
+ // structs can have the same address (the spec permits that)
+ x.val = int64(0)
+
+ case _Sizeof:
+ // basic types with specified sizes have size guarantees; for all others we use 0
+ var size int64
+ if typ, ok := typ0.(*Basic); ok {
+ size = typ.Size
+ }
+ x.mode = constant
+ x.typ = Typ[Uintptr]
+ x.val = size
+
+ case _Assert:
+ // assert(pred) causes a typechecker error if pred is false.
+ // The result of assert is the value of pred if there is no error.
+ // Note: assert is only available in self-test mode.
+ if x.mode != constant || !isBoolean(typ0) {
+ check.invalidArg(x.pos(), "%s is not a boolean constant", x)
+ goto Error
+ }
+ pred, ok := x.val.(bool)
+ if !ok {
+ check.errorf(x.pos(), "internal error: value of %s should be a boolean constant", x)
+ goto Error
+ }
+ if !pred {
+ check.errorf(call.Pos(), "%s failed", call)
+ // compile-time assertion failure - safe to continue
+ }
+
+ case _Trace:
+ // trace(x, y, z, ...) dumps the positions, expressions, and
+ // values of its arguments. The result of trace is the value
+ // of the first argument.
+ // Note: trace is only available in self-test mode.
+ if len(args) == 0 {
+ check.dump("%s: trace() without arguments", call.Pos())
+ x.mode = novalue
+ x.expr = call
+ return
+ }
+ var t operand
+ x1 := x
+ for _, arg := range args {
+ check.exprOrType(x1, arg, nil, iota, true) // permit trace for types, e.g.: new(trace(T))
+ check.dump("%s: %s", x1.pos(), x1)
+ x1 = &t // use incoming x only for first argument
+ }
+
+ default:
+ check.invalidAST(call.Pos(), "unknown builtin id %d", id)
+ goto Error
+ }
+
+ x.expr = call
+ return
+
+Error:
+ x.mode = invalid
+ x.expr = call
+}
+
+// implicitDeref returns A if typ is of the form *A and A is an array;
+// otherwise it returns typ.
+//
+func implicitDeref(typ Type) Type {
+ if p, ok := typ.(*Pointer); ok {
+ if a, ok := underlying(p.Base).(*Array); ok {
+ return a
+ }
+ }
+ return typ
+}
+
+// containsCallsOrReceives returns true if the expression x contains
+// function calls or channel receives; it returns false otherwise.
+//
+func containsCallsOrReceives(x ast.Expr) bool {
+ res := false
+ ast.Inspect(x, func(x ast.Node) bool {
+ switch x := x.(type) {
+ case *ast.CallExpr:
+ res = true
+ return false
+ case *ast.UnaryExpr:
+ if x.Op == token.ARROW {
+ res = true
+ return false
+ }
+ }
+ return true
+ })
+ return res
+}
+
+// unparen removes any parentheses surrounding an expression and returns
+// the naked expression.
+//
+func unparen(x ast.Expr) ast.Expr {
+ if p, ok := x.(*ast.ParenExpr); ok {
+ return unparen(p.X)
+ }
+ return x
+}
diff --git a/libgo/go/exp/types/staging/check.go b/libgo/go/exp/types/staging/check.go
new file mode 100644
index 00000000000..1fc41342d9b
--- /dev/null
+++ b/libgo/go/exp/types/staging/check.go
@@ -0,0 +1,352 @@
+// 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.
+
+// This file implements the Check function, which typechecks a package.
+
+package types
+
+import (
+ "fmt"
+ "go/ast"
+ "go/token"
+ "sort"
+)
+
+type checker struct {
+ fset *token.FileSet
+ pkg *ast.Package
+ errh func(token.Pos, string)
+ mapf func(ast.Expr, Type)
+
+ // lazily initialized
+ firsterr error
+ filenames []string // sorted list of package file names for reproducible iteration order
+ initexprs map[*ast.ValueSpec][]ast.Expr // "inherited" initialization expressions for constant declarations
+}
+
+// declare declares an object of the given kind and name (ident) in scope;
+// decl is the corresponding declaration in the AST. An error is reported
+// if the object was declared before.
+//
+// TODO(gri) This is very similar to the declare function in go/parser; it
+// is only used to associate methods with their respective receiver base types.
+// In a future version, it might be simpler and cleaner do to all the resolution
+// in the type-checking phase. It would simplify the parser, AST, and also
+// reduce some amount of code duplication.
+//
+func (check *checker) declare(scope *ast.Scope, kind ast.ObjKind, ident *ast.Ident, decl ast.Decl) {
+ assert(ident.Obj == nil) // identifier already declared or resolved
+ obj := ast.NewObj(kind, ident.Name)
+ obj.Decl = decl
+ ident.Obj = obj
+ if ident.Name != "_" {
+ if alt := scope.Insert(obj); alt != nil {
+ prevDecl := ""
+ if pos := alt.Pos(); pos.IsValid() {
+ prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", check.fset.Position(pos))
+ }
+ check.errorf(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
+ }
+ }
+}
+
+func (check *checker) valueSpec(pos token.Pos, obj *ast.Object, lhs []*ast.Ident, typ ast.Expr, rhs []ast.Expr, iota int) {
+ if len(lhs) == 0 {
+ check.invalidAST(pos, "missing lhs in declaration")
+ return
+ }
+
+ var t Type
+ if typ != nil {
+ t = check.typ(typ, false)
+ }
+
+ // len(lhs) >= 1
+ if len(lhs) == len(rhs) {
+ // check only corresponding lhs and rhs
+ var l, r ast.Expr
+ for i, ident := range lhs {
+ if ident.Obj == obj {
+ l = lhs[i]
+ r = rhs[i]
+ break
+ }
+ }
+ assert(l != nil)
+ obj.Type = t
+ // check rhs
+ var x operand
+ check.expr(&x, r, t, iota)
+ // assign to lhs
+ check.assignment(l, &x, true)
+ return
+ }
+
+ if t != nil {
+ for _, name := range lhs {
+ name.Obj.Type = t
+ }
+ }
+
+ // check initial values, if any
+ if len(rhs) > 0 {
+ // TODO(gri) should try to avoid this conversion
+ lhx := make([]ast.Expr, len(lhs))
+ for i, e := range lhs {
+ lhx[i] = e
+ }
+ check.assignNtoM(lhx, rhs, true, iota)
+ }
+}
+
+// ident type checks an identifier.
+func (check *checker) ident(name *ast.Ident, cycleOk bool) {
+ obj := name.Obj
+ if obj == nil {
+ check.invalidAST(name.Pos(), "missing object for %s", name.Name)
+ return
+ }
+
+ if obj.Type != nil {
+ // object has already been type checked
+ return
+ }
+
+ switch obj.Kind {
+ case ast.Bad, ast.Pkg:
+ // nothing to do
+
+ case ast.Con, ast.Var:
+ // The obj.Data field for constants and variables is initialized
+ // to the respective (hypothetical, for variables) iota value by
+ // the parser. The object's fields can be in one of the following
+ // states:
+ // Type != nil => the constant value is Data
+ // Type == nil => the object is not typechecked yet, and Data can be:
+ // Data is int => Data is the value of iota for this declaration
+ // Data == nil => the object's expression is being evaluated
+ if obj.Data == nil {
+ check.errorf(obj.Pos(), "illegal cycle in initialization of %s", obj.Name)
+ return
+ }
+ spec := obj.Decl.(*ast.ValueSpec)
+ iota := obj.Data.(int)
+ obj.Data = nil
+ // determine initialization expressions
+ values := spec.Values
+ if len(values) == 0 && obj.Kind == ast.Con {
+ values = check.initexprs[spec]
+ }
+ check.valueSpec(spec.Pos(), obj, spec.Names, spec.Type, values, iota)
+
+ case ast.Typ:
+ typ := &NamedType{Obj: obj}
+ obj.Type = typ // "mark" object so recursion terminates
+ typ.Underlying = underlying(check.typ(obj.Decl.(*ast.TypeSpec).Type, cycleOk))
+ // collect associated methods, if any
+ if obj.Data != nil {
+ scope := obj.Data.(*ast.Scope)
+ // struct fields must not conflict with methods
+ if t, ok := typ.Underlying.(*Struct); ok {
+ for _, f := range t.Fields {
+ if m := scope.Lookup(f.Name); m != nil {
+ check.errorf(m.Pos(), "type %s has both field and method named %s", obj.Name, f.Name)
+ }
+ }
+ }
+ // collect methods
+ methods := make(ObjList, len(scope.Objects))
+ i := 0
+ for _, m := range scope.Objects {
+ methods[i] = m
+ i++
+ }
+ methods.Sort()
+ typ.Methods = methods
+ // methods cannot be associated with an interface type
+ // (do this check after sorting for reproducible error positions - needed for testing)
+ if _, ok := typ.Underlying.(*Interface); ok {
+ for _, m := range methods {
+ recv := m.Decl.(*ast.FuncDecl).Recv.List[0].Type
+ check.errorf(recv.Pos(), "invalid receiver type %s (%s is an interface type)", obj.Name, obj.Name)
+ }
+ }
+ }
+
+ case ast.Fun:
+ fdecl := obj.Decl.(*ast.FuncDecl)
+ ftyp := check.typ(fdecl.Type, cycleOk).(*Signature)
+ obj.Type = ftyp
+ if fdecl.Recv != nil {
+ // TODO(gri) handle method receiver
+ }
+ check.stmt(fdecl.Body)
+
+ default:
+ panic("unreachable")
+ }
+}
+
+// assocInitvals associates "inherited" initialization expressions
+// with the corresponding *ast.ValueSpec in the check.initexprs map
+// for constant declarations without explicit initialization expressions.
+//
+func (check *checker) assocInitvals(decl *ast.GenDecl) {
+ var values []ast.Expr
+ for _, s := range decl.Specs {
+ if s, ok := s.(*ast.ValueSpec); ok {
+ if len(s.Values) > 0 {
+ values = s.Values
+ } else {
+ check.initexprs[s] = values
+ }
+ }
+ }
+ if len(values) == 0 {
+ check.invalidAST(decl.Pos(), "no initialization values provided")
+ }
+}
+
+// assocMethod associates a method declaration with the respective
+// receiver base type. meth.Recv must exist.
+//
+func (check *checker) assocMethod(meth *ast.FuncDecl) {
+ // The receiver type is one of the following (enforced by parser):
+ // - *ast.Ident
+ // - *ast.StarExpr{*ast.Ident}
+ // - *ast.BadExpr (parser error)
+ typ := meth.Recv.List[0].Type
+ if ptr, ok := typ.(*ast.StarExpr); ok {
+ typ = ptr.X
+ }
+ // determine receiver base type object (or nil if error)
+ var obj *ast.Object
+ if ident, ok := typ.(*ast.Ident); ok && ident.Obj != nil {
+ obj = ident.Obj
+ if obj.Kind != ast.Typ {
+ check.errorf(ident.Pos(), "%s is not a type", ident.Name)
+ obj = nil
+ }
+ // TODO(gri) determine if obj was defined in this package
+ /*
+ if check.notLocal(obj) {
+ check.errorf(ident.Pos(), "cannot define methods on non-local type %s", ident.Name)
+ obj = nil
+ }
+ */
+ } else {
+ // If it's not an identifier or the identifier wasn't declared/resolved,
+ // the parser/resolver already reported an error. Nothing to do here.
+ }
+ // determine base type scope (or nil if error)
+ var scope *ast.Scope
+ if obj != nil {
+ if obj.Data != nil {
+ scope = obj.Data.(*ast.Scope)
+ } else {
+ scope = ast.NewScope(nil)
+ obj.Data = scope
+ }
+ } else {
+ // use a dummy scope so that meth can be declared in
+ // presence of an error and get an associated object
+ // (always use a new scope so that we don't get double
+ // declaration errors)
+ scope = ast.NewScope(nil)
+ }
+ check.declare(scope, ast.Fun, meth.Name, meth)
+}
+
+func (check *checker) assocInitvalsOrMethod(decl ast.Decl) {
+ switch d := decl.(type) {
+ case *ast.GenDecl:
+ if d.Tok == token.CONST {
+ check.assocInitvals(d)
+ }
+ case *ast.FuncDecl:
+ if d.Recv != nil {
+ check.assocMethod(d)
+ }
+ }
+}
+
+func (check *checker) decl(decl ast.Decl) {
+ switch d := decl.(type) {
+ case *ast.BadDecl:
+ // ignore
+ case *ast.GenDecl:
+ for _, spec := range d.Specs {
+ switch s := spec.(type) {
+ case *ast.ImportSpec:
+ // nothing to do (handled by ast.NewPackage)
+ case *ast.ValueSpec:
+ for _, name := range s.Names {
+ if name.Name == "_" {
+ // TODO(gri) why is _ special here?
+ } else {
+ check.ident(name, false)
+ }
+ }
+ case *ast.TypeSpec:
+ check.ident(s.Name, false)
+ default:
+ check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
+ }
+ }
+ case *ast.FuncDecl:
+ check.ident(d.Name, false)
+ default:
+ check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
+ }
+}
+
+// iterate calls f for each package-level declaration.
+func (check *checker) iterate(f func(*checker, ast.Decl)) {
+ list := check.filenames
+
+ if list == nil {
+ // initialize lazily
+ for filename := range check.pkg.Files {
+ list = append(list, filename)
+ }
+ sort.Strings(list)
+ check.filenames = list
+ }
+
+ for _, filename := range list {
+ for _, decl := range check.pkg.Files[filename].Decls {
+ f(check, decl)
+ }
+ }
+}
+
+// A bailout panic is raised to indicate early termination.
+type bailout struct{}
+
+func check(fset *token.FileSet, pkg *ast.Package, errh func(token.Pos, string), f func(ast.Expr, Type)) (err error) {
+ // initialize checker
+ var check checker
+ check.fset = fset
+ check.pkg = pkg
+ check.errh = errh
+ check.mapf = f
+ check.initexprs = make(map[*ast.ValueSpec][]ast.Expr)
+
+ // handle bailouts
+ defer func() {
+ if p := recover(); p != nil {
+ _ = p.(bailout) // re-panic if not a bailout
+ }
+ err = check.firsterr
+ }()
+
+ // determine missing constant initialization expressions
+ // and associate methods with types
+ check.iterate((*checker).assocInitvalsOrMethod)
+
+ // typecheck all declarations
+ check.iterate((*checker).decl)
+
+ return
+}
diff --git a/libgo/go/exp/types/staging/check_test.go b/libgo/go/exp/types/staging/check_test.go
new file mode 100644
index 00000000000..abcfcfb2cd3
--- /dev/null
+++ b/libgo/go/exp/types/staging/check_test.go
@@ -0,0 +1,257 @@
+// 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.
+
+// This file implements a typechecker test harness. The packages specified
+// in tests are typechecked. Error messages reported by the typechecker are
+// compared against the error messages expected in the test files.
+//
+// Expected errors are indicated in the test files by putting a comment
+// of the form /* ERROR "rx" */ immediately following an offending token.
+// The harness will verify that an error matching the regular expression
+// rx is reported at that source position. Consecutive comments may be
+// used to indicate multiple errors for the same token position.
+//
+// For instance, the following test file indicates that a "not declared"
+// error should be reported for the undeclared variable x:
+//
+// package p
+// func f() {
+// _ = x /* ERROR "not declared" */ + 1
+// }
+
+package types
+
+import (
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/scanner"
+ "go/token"
+ "io/ioutil"
+ "os"
+ "regexp"
+ "testing"
+)
+
+var listErrors = flag.Bool("list", false, "list errors")
+
+func init() {
+ // declare builtins for testing
+ def(ast.Fun, "assert").Type = &builtin{aType, _Assert, "assert", 1, false, true}
+ def(ast.Fun, "trace").Type = &builtin{aType, _Trace, "trace", 0, true, true}
+}
+
+// The test filenames do not end in .go so that they are invisible
+// to gofmt since they contain comments that must not change their
+// positions relative to surrounding tokens.
+
+var tests = []struct {
+ name string
+ files []string
+}{
+ {"decls0", []string{"testdata/decls0.src"}},
+ {"decls1", []string{"testdata/decls1.src"}},
+ {"decls2", []string{"testdata/decls2a.src", "testdata/decls2b.src"}},
+ {"const0", []string{"testdata/const0.src"}},
+ {"expr0", []string{"testdata/expr0.src"}},
+ {"expr1", []string{"testdata/expr1.src"}},
+ {"expr2", []string{"testdata/expr2.src"}},
+ {"expr3", []string{"testdata/expr3.src"}},
+ {"builtins", []string{"testdata/builtins.src"}},
+ {"conversions", []string{"testdata/conversions.src"}},
+ {"stmt0", []string{"testdata/stmt0.src"}},
+}
+
+var fset = token.NewFileSet()
+
+func getFile(filename string) (file *token.File) {
+ fset.Iterate(func(f *token.File) bool {
+ if f.Name() == filename {
+ file = f
+ return false // end iteration
+ }
+ return true
+ })
+ return file
+}
+
+func getPos(filename string, offset int) token.Pos {
+ if f := getFile(filename); f != nil {
+ return f.Pos(offset)
+ }
+ return token.NoPos
+}
+
+func parseFiles(t *testing.T, testname string, filenames []string) (map[string]*ast.File, error) {
+ files := make(map[string]*ast.File)
+ var errors scanner.ErrorList
+ for _, filename := range filenames {
+ if _, exists := files[filename]; exists {
+ t.Fatalf("%s: duplicate file %s", testname, filename)
+ }
+ file, err := parser.ParseFile(fset, filename, nil, parser.DeclarationErrors)
+ if file == nil {
+ t.Fatalf("%s: could not parse file %s", testname, filename)
+ }
+ files[filename] = file
+ if err != nil {
+ // if the parser returns a non-scanner.ErrorList error
+ // the file couldn't be read in the first place and
+ // file == nil; in that case we shouldn't reach here
+ errors = append(errors, err.(scanner.ErrorList)...)
+ }
+
+ }
+ return files, errors
+}
+
+// ERROR comments must be of the form /* ERROR "rx" */ and rx is
+// a regular expression that matches the expected error message.
+//
+var errRx = regexp.MustCompile(`^/\* *ERROR *"([^"]*)" *\*/$`)
+
+// expectedErrors collects the regular expressions of ERROR comments found
+// in files and returns them as a map of error positions to error messages.
+//
+func expectedErrors(t *testing.T, testname string, files map[string]*ast.File) map[token.Pos][]string {
+ errors := make(map[token.Pos][]string)
+
+ for filename := range files {
+ src, err := ioutil.ReadFile(filename)
+ if err != nil {
+ t.Fatalf("%s: could not read %s", testname, filename)
+ }
+
+ var s scanner.Scanner
+ // file was parsed already - do not add it again to the file
+ // set otherwise the position information returned here will
+ // not match the position information collected by the parser
+ s.Init(getFile(filename), src, nil, scanner.ScanComments)
+ var prev token.Pos // position of last non-comment, non-semicolon token
+
+ scanFile:
+ for {
+ pos, tok, lit := s.Scan()
+ switch tok {
+ case token.EOF:
+ break scanFile
+ case token.COMMENT:
+ s := errRx.FindStringSubmatch(lit)
+ if len(s) == 2 {
+ list := errors[prev]
+ errors[prev] = append(list, string(s[1]))
+ }
+ case token.SEMICOLON:
+ // ignore automatically inserted semicolon
+ if lit == "\n" {
+ break
+ }
+ fallthrough
+ default:
+ prev = pos
+ }
+ }
+ }
+
+ return errors
+}
+
+func eliminate(t *testing.T, expected map[token.Pos][]string, errors error) {
+ if *listErrors || errors == nil {
+ return
+ }
+ for _, error := range errors.(scanner.ErrorList) {
+ // error.Pos is a token.Position, but we want
+ // a token.Pos so we can do a map lookup
+ pos := getPos(error.Pos.Filename, error.Pos.Offset)
+ list := expected[pos]
+ index := -1 // list index of matching message, if any
+ // we expect one of the messages in list to match the error at pos
+ for i, msg := range list {
+ rx, err := regexp.Compile(msg)
+ if err != nil {
+ t.Errorf("%s: %v", error.Pos, err)
+ continue
+ }
+ if match := rx.MatchString(error.Msg); match {
+ index = i
+ break
+ }
+ }
+ if index >= 0 {
+ // eliminate from list
+ n := len(list) - 1
+ if n > 0 {
+ // not the last entry - swap in last element and shorten list by 1
+ list[index] = list[n]
+ expected[pos] = list[:n]
+ } else {
+ // last entry - remove list from map
+ delete(expected, pos)
+ }
+ } else {
+ t.Errorf("%s: no error expected: %q", error.Pos, error.Msg)
+ continue
+ }
+ }
+}
+
+func checkFiles(t *testing.T, testname string, testfiles []string) {
+ // TODO(gri) Eventually all these different phases should be
+ // subsumed into a single function call that takes
+ // a set of files and creates a fully resolved and
+ // type-checked AST.
+
+ files, err := parseFiles(t, testname, testfiles)
+
+ // we are expecting the following errors
+ // (collect these after parsing the files so that
+ // they are found in the file set)
+ errors := expectedErrors(t, testname, files)
+
+ // verify errors returned by the parser
+ eliminate(t, errors, err)
+
+ // verify errors returned after resolving identifiers
+ pkg, err := ast.NewPackage(fset, files, GcImport, Universe)
+ eliminate(t, errors, err)
+
+ // verify errors returned by the typechecker
+ var list scanner.ErrorList
+ errh := func(pos token.Pos, msg string) {
+ list.Add(fset.Position(pos), msg)
+ }
+ err = Check(fset, pkg, errh, nil)
+ eliminate(t, errors, list)
+
+ if *listErrors {
+ scanner.PrintError(os.Stdout, err)
+ return
+ }
+
+ // there should be no expected errors left
+ if len(errors) > 0 {
+ t.Errorf("%s: %d errors not reported:", testname, len(errors))
+ for pos, msg := range errors {
+ t.Errorf("%s: %s\n", fset.Position(pos), msg)
+ }
+ }
+}
+
+func TestCheck(t *testing.T) {
+ // For easy debugging w/o changing the testing code,
+ // if there is a local test file, only test that file.
+ const testfile = "testdata/test.go"
+ if fi, err := os.Stat(testfile); err == nil && !fi.IsDir() {
+ fmt.Printf("WARNING: Testing only %s (remove it to run all tests)\n", testfile)
+ checkFiles(t, testfile, []string{testfile})
+ return
+ }
+
+ // Otherwise, run all the tests.
+ for _, test := range tests {
+ checkFiles(t, test.name, test.files)
+ }
+}
diff --git a/libgo/go/exp/types/staging/const.go b/libgo/go/exp/types/staging/const.go
new file mode 100644
index 00000000000..e817f1fd858
--- /dev/null
+++ b/libgo/go/exp/types/staging/const.go
@@ -0,0 +1,662 @@
+// 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.
+
+// This file implements operations on constant values.
+
+package types
+
+import (
+ "fmt"
+ "go/token"
+ "math/big"
+ "strconv"
+)
+
+// TODO(gri) At the moment, constants are different types
+// passed around as interface{} values. Consider introducing
+// a Const type and use methods instead of xConst functions.
+
+// Representation of constant values.
+//
+// bool -> bool (true, false)
+// numeric -> int64, *big.Int, *big.Rat, complex (ordered by increasing data structure "size")
+// string -> string
+// nil -> nilType (nilConst)
+//
+// Numeric constants are normalized after each operation such
+// that they are represented by the "smallest" data structure
+// required to represent the constant, independent of actual
+// type. Non-numeric constants are always normalized.
+
+// Representation of complex numbers.
+type complex struct {
+ re, im *big.Rat
+}
+
+func (c complex) String() string {
+ if c.re.Sign() == 0 {
+ return fmt.Sprintf("%si", c.im)
+ }
+ // normalized complex values always have an imaginary part
+ return fmt.Sprintf("(%s + %si)", c.re, c.im)
+}
+
+// Representation of nil.
+type nilType struct{}
+
+func (nilType) String() string {
+ return "nil"
+}
+
+// Frequently used constants.
+var (
+ zeroConst = int64(0)
+ oneConst = int64(1)
+ minusOneConst = int64(-1)
+ nilConst = new(nilType)
+)
+
+// int64 bounds
+var (
+ minInt64 = big.NewInt(-1 << 63)
+ maxInt64 = big.NewInt(1<<63 - 1)
+)
+
+// normalizeIntConst returns the smallest constant representation
+// for the specific value of x; either an int64 or a *big.Int value.
+//
+func normalizeIntConst(x *big.Int) interface{} {
+ if minInt64.Cmp(x) <= 0 && x.Cmp(maxInt64) <= 0 {
+ return x.Int64()
+ }
+ return x
+}
+
+// normalizeRatConst returns the smallest constant representation
+// for the specific value of x; either an int64, *big.Int value,
+// or *big.Rat value.
+//
+func normalizeRatConst(x *big.Rat) interface{} {
+ if x.IsInt() {
+ return normalizeIntConst(x.Num())
+ }
+ return x
+}
+
+// normalizeComplexConst returns the smallest constant representation
+// for the specific value of x; either an int64, *big.Int value, *big.Rat,
+// or complex value.
+//
+func normalizeComplexConst(x complex) interface{} {
+ if x.im.Sign() == 0 {
+ return normalizeRatConst(x.re)
+ }
+ return x
+}
+
+// makeRuneConst returns the int64 code point for the rune literal
+// lit. The result is nil if lit is not a correct rune literal.
+//
+func makeRuneConst(lit string) interface{} {
+ if n := len(lit); n >= 2 {
+ if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil {
+ return int64(code)
+ }
+ }
+ return nil
+}
+
+// makeRuneConst returns the smallest integer constant representation
+// (int64, *big.Int) for the integer literal lit. The result is nil if
+// lit is not a correct integer literal.
+//
+func makeIntConst(lit string) interface{} {
+ if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
+ return x
+ }
+ if x, ok := new(big.Int).SetString(lit, 0); ok {
+ return x
+ }
+ return nil
+}
+
+// makeFloatConst returns the smallest floating-point constant representation
+// (int64, *big.Int, *big.Rat) for the floating-point literal lit. The result
+// is nil if lit is not a correct floating-point literal.
+//
+func makeFloatConst(lit string) interface{} {
+ if x, ok := new(big.Rat).SetString(lit); ok {
+ return normalizeRatConst(x)
+ }
+ return nil
+}
+
+// makeComplexConst returns the complex constant representation (complex) for
+// the imaginary literal lit. The result is nil if lit is not a correct imaginary
+// literal.
+//
+func makeComplexConst(lit string) interface{} {
+ n := len(lit)
+ if n > 0 && lit[n-1] == 'i' {
+ if im, ok := new(big.Rat).SetString(lit[0 : n-1]); ok {
+ return normalizeComplexConst(complex{big.NewRat(0, 1), im})
+ }
+ }
+ return nil
+}
+
+// makeStringConst returns the string constant representation (string) for
+// the string literal lit. The result is nil if lit is not a correct string
+// literal.
+//
+func makeStringConst(lit string) interface{} {
+ if s, err := strconv.Unquote(lit); err == nil {
+ return s
+ }
+ return nil
+}
+
+// isZeroConst reports whether the value of constant x is 0.
+// x must be normalized.
+//
+func isZeroConst(x interface{}) bool {
+ i, ok := x.(int64) // good enough since constants are normalized
+ return ok && i == 0
+}
+
+// isNegConst reports whether the value of constant x is < 0.
+// x must be a non-complex numeric value.
+//
+func isNegConst(x interface{}) bool {
+ switch x := x.(type) {
+ case int64:
+ return x < 0
+ case *big.Int:
+ return x.Sign() < 0
+ case *big.Rat:
+ return x.Sign() < 0
+ }
+ unreachable()
+ return false
+}
+
+// isRepresentableConst reports whether the value of constant x can
+// be represented as a value of the basic type Typ[as] without loss
+// of precision.
+//
+func isRepresentableConst(x interface{}, as BasicKind) bool {
+ const intBits = 32 // TODO(gri) implementation-specific constant
+ const ptrBits = 64 // TODO(gri) implementation-specific constant
+
+ switch x := x.(type) {
+ case bool:
+ return as == Bool || as == UntypedBool
+
+ case int64:
+ switch as {
+ case Int:
+ return -1<<(intBits-1) <= x && x <= 1<<(intBits-1)-1
+ case Int8:
+ return -1<<(8-1) <= x && x <= 1<<(8-1)-1
+ case Int16:
+ return -1<<(16-1) <= x && x <= 1<<(16-1)-1
+ case Int32, UntypedRune:
+ return -1<<(32-1) <= x && x <= 1<<(32-1)-1
+ case Int64:
+ return true
+ case Uint:
+ return 0 <= x && x <= 1<<intBits-1
+ case Uint8:
+ return 0 <= x && x <= 1<<8-1
+ case Uint16:
+ return 0 <= x && x <= 1<<16-1
+ case Uint32:
+ return 0 <= x && x <= 1<<32-1
+ case Uint64:
+ return 0 <= x
+ case Uintptr:
+ assert(ptrBits == 64)
+ return 0 <= x
+ case Float32:
+ return true // TODO(gri) fix this
+ case Float64:
+ return true // TODO(gri) fix this
+ case Complex64:
+ return true // TODO(gri) fix this
+ case Complex128:
+ return true // TODO(gri) fix this
+ case UntypedInt, UntypedFloat, UntypedComplex:
+ return true
+ }
+
+ case *big.Int:
+ switch as {
+ case Uint:
+ return x.Sign() >= 0 && x.BitLen() <= intBits
+ case Uint64:
+ return x.Sign() >= 0 && x.BitLen() <= 64
+ case Uintptr:
+ return x.Sign() >= 0 && x.BitLen() <= ptrBits
+ case Float32:
+ return true // TODO(gri) fix this
+ case Float64:
+ return true // TODO(gri) fix this
+ case Complex64:
+ return true // TODO(gri) fix this
+ case Complex128:
+ return true // TODO(gri) fix this
+ case UntypedInt, UntypedFloat, UntypedComplex:
+ return true
+ }
+
+ case *big.Rat:
+ switch as {
+ case Float32:
+ return true // TODO(gri) fix this
+ case Float64:
+ return true // TODO(gri) fix this
+ case Complex64:
+ return true // TODO(gri) fix this
+ case Complex128:
+ return true // TODO(gri) fix this
+ case UntypedFloat, UntypedComplex:
+ return true
+ }
+
+ case complex:
+ switch as {
+ case Complex64:
+ return true // TODO(gri) fix this
+ case Complex128:
+ return true // TODO(gri) fix this
+ case UntypedComplex:
+ return true
+ }
+
+ case string:
+ return as == String || as == UntypedString
+
+ case nilType:
+ return as == UntypedNil
+
+ default:
+ unreachable()
+ }
+
+ return false
+}
+
+var (
+ int1 = big.NewInt(1)
+ rat0 = big.NewRat(0, 1)
+)
+
+// complexity returns a measure of representation complexity for constant x.
+func complexity(x interface{}) int {
+ switch x.(type) {
+ case bool, string, nilType:
+ return 1
+ case int64:
+ return 2
+ case *big.Int:
+ return 3
+ case *big.Rat:
+ return 4
+ case complex:
+ return 5
+ }
+ unreachable()
+ return 0
+}
+
+// matchConst returns the matching representation (same type) with the
+// smallest complexity for two constant values x and y. They must be
+// of the same "kind" (boolean, numeric, string, or nilType).
+//
+func matchConst(x, y interface{}) (_, _ interface{}) {
+ if complexity(x) > complexity(y) {
+ y, x = matchConst(y, x)
+ return x, y
+ }
+ // complexity(x) <= complexity(y)
+
+ switch x := x.(type) {
+ case bool, complex, string, nilType:
+ return x, y
+
+ case int64:
+ switch y := y.(type) {
+ case int64:
+ return x, y
+ case *big.Int:
+ return big.NewInt(x), y
+ case *big.Rat:
+ return big.NewRat(x, 1), y
+ case complex:
+ return complex{big.NewRat(x, 1), rat0}, y
+ }
+
+ case *big.Int:
+ switch y := y.(type) {
+ case *big.Int:
+ return x, y
+ case *big.Rat:
+ return new(big.Rat).SetFrac(x, int1), y
+ case complex:
+ return complex{new(big.Rat).SetFrac(x, int1), rat0}, y
+ }
+
+ case *big.Rat:
+ switch y := y.(type) {
+ case *big.Rat:
+ return x, y
+ case complex:
+ return complex{x, rat0}, y
+ }
+ }
+
+ unreachable()
+ return nil, nil
+}
+
+// is32bit reports whether x can be represented using 32 bits.
+func is32bit(x int64) bool {
+ return -1<<31 <= x && x <= 1<<31-1
+}
+
+// is63bit reports whether x can be represented using 63 bits.
+func is63bit(x int64) bool {
+ return -1<<62 <= x && x <= 1<<62-1
+}
+
+// binaryOpConst returns the result of the constant evaluation x op y;
+// both operands must be of the same "kind" (boolean, numeric, or string).
+// If intDiv is true, division (op == token.QUO) is using integer division
+// (and the result is guaranteed to be integer) rather than floating-point
+// division. Division by zero leads to a run-time panic.
+//
+func binaryOpConst(x, y interface{}, op token.Token, intDiv bool) interface{} {
+ x, y = matchConst(x, y)
+
+ switch x := x.(type) {
+ case bool:
+ y := y.(bool)
+ switch op {
+ case token.LAND:
+ return x && y
+ case token.LOR:
+ return x || y
+ default:
+ unreachable()
+ }
+
+ case int64:
+ y := y.(int64)
+ switch op {
+ case token.ADD:
+ // TODO(gri) can do better than this
+ if is63bit(x) && is63bit(y) {
+ return x + y
+ }
+ return normalizeIntConst(new(big.Int).Add(big.NewInt(x), big.NewInt(y)))
+ case token.SUB:
+ // TODO(gri) can do better than this
+ if is63bit(x) && is63bit(y) {
+ return x - y
+ }
+ return normalizeIntConst(new(big.Int).Sub(big.NewInt(x), big.NewInt(y)))
+ case token.MUL:
+ // TODO(gri) can do better than this
+ if is32bit(x) && is32bit(y) {
+ return x * y
+ }
+ return normalizeIntConst(new(big.Int).Mul(big.NewInt(x), big.NewInt(y)))
+ case token.REM:
+ return x % y
+ case token.QUO:
+ if intDiv {
+ return x / y
+ }
+ return normalizeRatConst(new(big.Rat).SetFrac(big.NewInt(x), big.NewInt(y)))
+ case token.AND:
+ return x & y
+ case token.OR:
+ return x | y
+ case token.XOR:
+ return x ^ y
+ case token.AND_NOT:
+ return x &^ y
+ default:
+ unreachable()
+ }
+
+ case *big.Int:
+ y := y.(*big.Int)
+ var z big.Int
+ switch op {
+ case token.ADD:
+ z.Add(x, y)
+ case token.SUB:
+ z.Sub(x, y)
+ case token.MUL:
+ z.Mul(x, y)
+ case token.REM:
+ z.Rem(x, y)
+ case token.QUO:
+ if intDiv {
+ z.Quo(x, y)
+ } else {
+ return normalizeRatConst(new(big.Rat).SetFrac(x, y))
+ }
+ case token.AND:
+ z.And(x, y)
+ case token.OR:
+ z.Or(x, y)
+ case token.XOR:
+ z.Xor(x, y)
+ case token.AND_NOT:
+ z.AndNot(x, y)
+ default:
+ unreachable()
+ }
+ return normalizeIntConst(&z)
+
+ case *big.Rat:
+ y := y.(*big.Rat)
+ var z big.Rat
+ switch op {
+ case token.ADD:
+ z.Add(x, y)
+ case token.SUB:
+ z.Sub(x, y)
+ case token.MUL:
+ z.Mul(x, y)
+ case token.QUO:
+ z.Quo(x, y)
+ default:
+ unreachable()
+ }
+ return normalizeRatConst(&z)
+
+ case complex:
+ y := y.(complex)
+ a, b := x.re, x.im
+ c, d := y.re, y.im
+ var re, im big.Rat
+ switch op {
+ case token.ADD:
+ // (a+c) + i(b+d)
+ re.Add(a, c)
+ im.Add(b, d)
+ case token.SUB:
+ // (a-c) + i(b-d)
+ re.Sub(a, c)
+ im.Sub(b, d)
+ case token.MUL:
+ // (ac-bd) + i(bc+ad)
+ var ac, bd, bc, ad big.Rat
+ ac.Mul(a, c)
+ bd.Mul(b, d)
+ bc.Mul(b, c)
+ ad.Mul(a, d)
+ re.Sub(&ac, &bd)
+ im.Add(&bc, &ad)
+ case token.QUO:
+ // (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
+ var ac, bd, bc, ad, s big.Rat
+ ac.Mul(a, c)
+ bd.Mul(b, d)
+ bc.Mul(b, c)
+ ad.Mul(a, d)
+ s.Add(c.Mul(c, c), d.Mul(d, d))
+ re.Add(&ac, &bd)
+ re.Quo(&re, &s)
+ im.Sub(&bc, &ad)
+ im.Quo(&im, &s)
+ default:
+ unreachable()
+ }
+ return normalizeComplexConst(complex{&re, &im})
+
+ case string:
+ if op == token.ADD {
+ return x + y.(string)
+ }
+ }
+
+ unreachable()
+ return nil
+}
+
+// shiftConst returns the result of the constant evaluation x op s
+// where op is token.SHL or token.SHR (<< or >>). x must be an
+// integer constant.
+//
+func shiftConst(x interface{}, s uint, op token.Token) interface{} {
+ switch x := x.(type) {
+ case int64:
+ switch op {
+ case token.SHL:
+ z := big.NewInt(x)
+ return normalizeIntConst(z.Lsh(z, s))
+ case token.SHR:
+ return x >> s
+ }
+
+ case *big.Int:
+ var z big.Int
+ switch op {
+ case token.SHL:
+ return normalizeIntConst(z.Lsh(x, s))
+ case token.SHR:
+ return normalizeIntConst(z.Rsh(x, s))
+ }
+ }
+
+ unreachable()
+ return nil
+}
+
+// compareConst returns the result of the constant comparison x op y;
+// both operands must be of the same "kind" (boolean, numeric, string,
+// or nilType).
+//
+func compareConst(x, y interface{}, op token.Token) (z bool) {
+ x, y = matchConst(x, y)
+
+ // x == y => x == y
+ // x != y => x != y
+ // x > y => y < x
+ // x >= y => u <= x
+ swap := false
+ switch op {
+ case token.GTR:
+ swap = true
+ op = token.LSS
+ case token.GEQ:
+ swap = true
+ op = token.LEQ
+ }
+
+ // x == y => x == y
+ // x != y => !(x == y)
+ // x < y => x < y
+ // x <= y => !(y < x)
+ negate := false
+ switch op {
+ case token.NEQ:
+ negate = true
+ op = token.EQL
+ case token.LEQ:
+ swap = !swap
+ negate = true
+ op = token.LSS
+ }
+
+ if negate {
+ defer func() { z = !z }()
+ }
+
+ if swap {
+ x, y = y, x
+ }
+
+ switch x := x.(type) {
+ case bool:
+ if op == token.EQL {
+ return x == y.(bool)
+ }
+
+ case int64:
+ y := y.(int64)
+ switch op {
+ case token.EQL:
+ return x == y
+ case token.LSS:
+ return x < y
+ }
+
+ case *big.Int:
+ s := x.Cmp(y.(*big.Int))
+ switch op {
+ case token.EQL:
+ return s == 0
+ case token.LSS:
+ return s < 0
+ }
+
+ case *big.Rat:
+ s := x.Cmp(y.(*big.Rat))
+ switch op {
+ case token.EQL:
+ return s == 0
+ case token.LSS:
+ return s < 0
+ }
+
+ case complex:
+ y := y.(complex)
+ if op == token.EQL {
+ return x.re.Cmp(y.re) == 0 && x.im.Cmp(y.im) == 0
+ }
+
+ case string:
+ y := y.(string)
+ switch op {
+ case token.EQL:
+ return x == y
+ case token.LSS:
+ return x < y
+ }
+
+ case nilType:
+ if op == token.EQL {
+ return x == y.(nilType)
+ }
+ }
+
+ fmt.Printf("x = %s (%T), y = %s (%T)\n", x, x, y, y)
+ unreachable()
+ return
+}
diff --git a/libgo/go/exp/types/staging/conversions.go b/libgo/go/exp/types/staging/conversions.go
new file mode 100644
index 00000000000..ac4d59fde7c
--- /dev/null
+++ b/libgo/go/exp/types/staging/conversions.go
@@ -0,0 +1,39 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements typechecking of conversions.
+
+package types
+
+import (
+ "go/ast"
+)
+
+// conversion typechecks the type conversion conv to type typ. iota is the current
+// value of iota or -1 if iota doesn't have a value in the current context. The result
+// of the conversion is returned via x. If the conversion has type errors, the returned
+// x is marked as invalid (x.mode == invalid).
+//
+func (check *checker) conversion(x *operand, conv *ast.CallExpr, typ Type, iota int) {
+ // all conversions have one argument
+ if len(conv.Args) != 1 {
+ check.invalidOp(conv.Pos(), "%s conversion requires exactly one argument", conv)
+ goto Error
+ }
+
+ // evaluate argument
+ check.expr(x, conv.Args[0], nil, iota)
+ if x.mode == invalid {
+ goto Error
+ }
+
+ // TODO(gri) fix this - implement all checks and constant evaluation
+ x.mode = value
+ x.expr = conv
+ x.typ = typ
+ return
+
+Error:
+ x.mode = invalid
+}
diff --git a/libgo/go/exp/types/staging/errors.go b/libgo/go/exp/types/staging/errors.go
new file mode 100644
index 00000000000..64ce25f0f35
--- /dev/null
+++ b/libgo/go/exp/types/staging/errors.go
@@ -0,0 +1,301 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements various error reporters.
+
+package types
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/token"
+)
+
+// debugging flags
+const debug = false
+const trace = false
+
+// TODO(gri) eventually assert and unimplemented should disappear.
+func assert(p bool) {
+ if !p {
+ panic("assertion failed")
+ }
+}
+
+func unimplemented() {
+ if debug {
+ panic("unimplemented")
+ }
+}
+
+func unreachable() {
+ panic("unreachable")
+}
+
+func (check *checker) formatMsg(format string, args []interface{}) string {
+ for i, arg := range args {
+ switch a := arg.(type) {
+ case token.Pos:
+ args[i] = check.fset.Position(a)
+ case ast.Expr:
+ args[i] = exprString(a)
+ case Type:
+ args[i] = typeString(a)
+ case operand:
+ panic("internal error: should always pass *operand")
+ }
+ }
+ return fmt.Sprintf(format, args...)
+}
+
+// dump is only needed for debugging
+func (check *checker) dump(format string, args ...interface{}) {
+ fmt.Println(check.formatMsg(format, args))
+}
+
+func (check *checker) errorf(pos token.Pos, format string, args ...interface{}) {
+ msg := check.formatMsg(format, args)
+ if check.firsterr == nil {
+ check.firsterr = fmt.Errorf("%s: %s", check.fset.Position(pos), msg)
+ }
+ if check.errh == nil {
+ panic(bailout{}) // report only first error
+ }
+ check.errh(pos, msg)
+}
+
+func (check *checker) invalidAST(pos token.Pos, format string, args ...interface{}) {
+ check.errorf(pos, "invalid AST: "+format, args...)
+}
+
+func (check *checker) invalidArg(pos token.Pos, format string, args ...interface{}) {
+ check.errorf(pos, "invalid argument: "+format, args...)
+}
+
+func (check *checker) invalidOp(pos token.Pos, format string, args ...interface{}) {
+ check.errorf(pos, "invalid operation: "+format, args...)
+}
+
+// exprString returns a (simplified) string representation for an expression.
+func exprString(expr ast.Expr) string {
+ var buf bytes.Buffer
+ writeExpr(&buf, expr)
+ return buf.String()
+}
+
+// TODO(gri) Need to merge with typeString since some expressions are types (try: ([]int)(a))
+func writeExpr(buf *bytes.Buffer, expr ast.Expr) {
+ switch x := expr.(type) {
+ case *ast.Ident:
+ buf.WriteString(x.Name)
+
+ case *ast.BasicLit:
+ buf.WriteString(x.Value)
+
+ case *ast.FuncLit:
+ buf.WriteString("(func literal)")
+
+ case *ast.CompositeLit:
+ buf.WriteString("(composite literal)")
+
+ case *ast.ParenExpr:
+ buf.WriteByte('(')
+ writeExpr(buf, x.X)
+ buf.WriteByte(')')
+
+ case *ast.SelectorExpr:
+ writeExpr(buf, x.X)
+ buf.WriteByte('.')
+ buf.WriteString(x.Sel.Name)
+
+ case *ast.IndexExpr:
+ writeExpr(buf, x.X)
+ buf.WriteByte('[')
+ writeExpr(buf, x.Index)
+ buf.WriteByte(']')
+
+ case *ast.SliceExpr:
+ writeExpr(buf, x.X)
+ buf.WriteByte('[')
+ if x.Low != nil {
+ writeExpr(buf, x.Low)
+ }
+ buf.WriteByte(':')
+ if x.High != nil {
+ writeExpr(buf, x.High)
+ }
+ buf.WriteByte(']')
+
+ case *ast.TypeAssertExpr:
+ writeExpr(buf, x.X)
+ buf.WriteString(".(...)")
+
+ case *ast.CallExpr:
+ writeExpr(buf, x.Fun)
+ buf.WriteByte('(')
+ for i, arg := range x.Args {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ writeExpr(buf, arg)
+ }
+ buf.WriteByte(')')
+
+ case *ast.StarExpr:
+ buf.WriteByte('*')
+ writeExpr(buf, x.X)
+
+ case *ast.UnaryExpr:
+ buf.WriteString(x.Op.String())
+ writeExpr(buf, x.X)
+
+ case *ast.BinaryExpr:
+ // The AST preserves source-level parentheses so there is
+ // no need to introduce parentheses here for correctness.
+ writeExpr(buf, x.X)
+ buf.WriteByte(' ')
+ buf.WriteString(x.Op.String())
+ buf.WriteByte(' ')
+ writeExpr(buf, x.Y)
+
+ default:
+ fmt.Fprintf(buf, "<expr %T>", x)
+ }
+}
+
+// typeString returns a string representation for typ.
+func typeString(typ Type) string {
+ var buf bytes.Buffer
+ writeType(&buf, typ)
+ return buf.String()
+}
+
+func writeParams(buf *bytes.Buffer, params ObjList, isVariadic bool) {
+ buf.WriteByte('(')
+ for i, par := range params {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ if par.Name != "" {
+ buf.WriteString(par.Name)
+ buf.WriteByte(' ')
+ }
+ if isVariadic && i == len(params)-1 {
+ buf.WriteString("...")
+ }
+ writeType(buf, par.Type.(Type))
+ }
+ buf.WriteByte(')')
+}
+
+func writeSignature(buf *bytes.Buffer, sig *Signature) {
+ writeParams(buf, sig.Params, sig.IsVariadic)
+ if len(sig.Results) == 0 {
+ // no result
+ return
+ }
+
+ buf.WriteByte(' ')
+ if len(sig.Results) == 1 && sig.Results[0].Name == "" {
+ // single unnamed result
+ writeType(buf, sig.Results[0].Type.(Type))
+ return
+ }
+
+ // multiple or named result(s)
+ writeParams(buf, sig.Results, false)
+}
+
+func writeType(buf *bytes.Buffer, typ Type) {
+ switch t := typ.(type) {
+ case nil:
+ buf.WriteString("<nil>")
+
+ case *Basic:
+ buf.WriteString(t.Name)
+
+ case *Array:
+ fmt.Fprintf(buf, "[%d]", t.Len)
+ writeType(buf, t.Elt)
+
+ case *Slice:
+ buf.WriteString("[]")
+ writeType(buf, t.Elt)
+
+ case *Struct:
+ buf.WriteString("struct{")
+ for i, f := range t.Fields {
+ if i > 0 {
+ buf.WriteString("; ")
+ }
+ if !f.IsAnonymous {
+ buf.WriteString(f.Name)
+ buf.WriteByte(' ')
+ }
+ writeType(buf, f.Type)
+ if f.Tag != "" {
+ fmt.Fprintf(buf, " %q", f.Tag)
+ }
+ }
+ buf.WriteByte('}')
+
+ case *Pointer:
+ buf.WriteByte('*')
+ writeType(buf, t.Base)
+
+ case *tuple:
+ buf.WriteByte('(')
+ for i, typ := range t.list {
+ if i > 0 {
+ buf.WriteString("; ")
+ }
+ writeType(buf, typ)
+ }
+ buf.WriteByte(')')
+
+ case *Signature:
+ buf.WriteString("func")
+ writeSignature(buf, t)
+
+ case *builtin:
+ fmt.Fprintf(buf, "<type of %s>", t.name)
+
+ case *Interface:
+ buf.WriteString("interface{")
+ for i, m := range t.Methods {
+ if i > 0 {
+ buf.WriteString("; ")
+ }
+ buf.WriteString(m.Name)
+ writeSignature(buf, m.Type.(*Signature))
+ }
+ buf.WriteByte('}')
+
+ case *Map:
+ buf.WriteString("map[")
+ writeType(buf, t.Key)
+ buf.WriteByte(']')
+ writeType(buf, t.Elt)
+
+ case *Chan:
+ var s string
+ switch t.Dir {
+ case ast.SEND:
+ s = "chan<- "
+ case ast.RECV:
+ s = "<-chan "
+ default:
+ s = "chan "
+ }
+ buf.WriteString(s)
+ writeType(buf, t.Elt)
+
+ case *NamedType:
+ buf.WriteString(t.Obj.Name)
+
+ default:
+ fmt.Fprintf(buf, "<type %T>", t)
+ }
+}
diff --git a/libgo/go/exp/types/staging/exportdata.go b/libgo/go/exp/types/staging/exportdata.go
new file mode 100644
index 00000000000..22190153bbf
--- /dev/null
+++ b/libgo/go/exp/types/staging/exportdata.go
@@ -0,0 +1,110 @@
+// 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.
+
+// This file implements FindGcExportData.
+
+package types
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+)
+
+func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
+ // See $GOROOT/include/ar.h.
+ hdr := make([]byte, 16+12+6+6+8+10+2)
+ _, err = io.ReadFull(r, hdr)
+ if err != nil {
+ return
+ }
+ if trace {
+ fmt.Printf("header: %s", hdr)
+ }
+ s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
+ size, err = strconv.Atoi(s)
+ if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
+ err = errors.New("invalid archive header")
+ return
+ }
+ name = strings.TrimSpace(string(hdr[:16]))
+ return
+}
+
+// FindGcExportData positions the reader r at the beginning of the
+// export data section of an underlying GC-created object/archive
+// file by reading from it. The reader must be positioned at the
+// start of the file before calling this function.
+//
+func FindGcExportData(r *bufio.Reader) (err error) {
+ // Read first line to make sure this is an object file.
+ line, err := r.ReadSlice('\n')
+ if err != nil {
+ return
+ }
+ if string(line) == "!<arch>\n" {
+ // Archive file. Scan to __.PKGDEF, which should
+ // be second archive entry.
+ var name string
+ var size int
+
+ // First entry should be __.GOSYMDEF.
+ // Older archives used __.SYMDEF, so allow that too.
+ // Read and discard.
+ if name, size, err = readGopackHeader(r); err != nil {
+ return
+ }
+ if name != "__.SYMDEF" && name != "__.GOSYMDEF" {
+ err = errors.New("go archive does not begin with __.SYMDEF or __.GOSYMDEF")
+ return
+ }
+ const block = 4096
+ tmp := make([]byte, block)
+ for size > 0 {
+ n := size
+ if n > block {
+ n = block
+ }
+ if _, err = io.ReadFull(r, tmp[:n]); err != nil {
+ return
+ }
+ size -= n
+ }
+
+ // Second entry should be __.PKGDEF.
+ if name, size, err = readGopackHeader(r); err != nil {
+ return
+ }
+ if name != "__.PKGDEF" {
+ err = errors.New("go archive is missing __.PKGDEF")
+ return
+ }
+
+ // Read first line of __.PKGDEF data, so that line
+ // is once again the first line of the input.
+ if line, err = r.ReadSlice('\n'); err != nil {
+ return
+ }
+ }
+
+ // Now at __.PKGDEF in archive or still at beginning of file.
+ // Either way, line should begin with "go object ".
+ if !strings.HasPrefix(string(line), "go object ") {
+ err = errors.New("not a go object file")
+ return
+ }
+
+ // Skip over object header to export data.
+ // Begins after first line with $$.
+ for line[0] != '$' {
+ if line, err = r.ReadSlice('\n'); err != nil {
+ return
+ }
+ }
+
+ return
+}
diff --git a/libgo/go/exp/types/staging/expr.go b/libgo/go/exp/types/staging/expr.go
new file mode 100644
index 00000000000..560b16c16f3
--- /dev/null
+++ b/libgo/go/exp/types/staging/expr.go
@@ -0,0 +1,867 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements typechecking of expressions.
+
+package types
+
+import (
+ "go/ast"
+ "go/token"
+ "strconv"
+)
+
+// TODO(gri)
+// - don't print error messages referring to invalid types (they are likely spurious errors)
+// - simplify invalid handling: maybe just use Typ[Invalid] as marker, get rid of invalid Mode for values?
+
+func (check *checker) tag(field *ast.Field) string {
+ if t := field.Tag; t != nil {
+ assert(t.Kind == token.STRING)
+ if tag, err := strconv.Unquote(t.Value); err == nil {
+ return tag
+ }
+ check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value)
+ }
+ return ""
+}
+
+// collectFields collects interface methods (tok = token.INTERFACE), and function arguments/results (tok = token.FUNC).
+func (check *checker) collectFields(tok token.Token, list *ast.FieldList, cycleOk bool) (fields ObjList, tags []string, isVariadic bool) {
+ if list != nil {
+ for _, field := range list.List {
+ ftype := field.Type
+ if t, ok := ftype.(*ast.Ellipsis); ok {
+ ftype = t.Elt
+ isVariadic = true
+ }
+ typ := check.typ(ftype, cycleOk)
+ tag := check.tag(field)
+ if len(field.Names) > 0 {
+ // named fields
+ for _, name := range field.Names {
+ obj := name.Obj
+ obj.Type = typ
+ fields = append(fields, obj)
+ if tok == token.STRUCT {
+ tags = append(tags, tag)
+ }
+ }
+ } else {
+ // anonymous field
+ switch tok {
+ case token.FUNC:
+ obj := ast.NewObj(ast.Var, "")
+ obj.Type = typ
+ fields = append(fields, obj)
+ case token.INTERFACE:
+ utyp := underlying(typ)
+ if typ, ok := utyp.(*Interface); ok {
+ // TODO(gri) This is not good enough. Check for double declarations!
+ fields = append(fields, typ.Methods...)
+ } else if utyp != Typ[Invalid] {
+ // if utyp is invalid, don't complain (the root cause was reported before)
+ check.errorf(ftype.Pos(), "interface contains embedded non-interface type")
+ }
+ default:
+ panic("unreachable")
+ }
+ }
+ }
+ }
+ return
+}
+
+func (check *checker) collectStructFields(list *ast.FieldList, cycleOk bool) (fields []*StructField) {
+ if list == nil {
+ return
+ }
+ for _, f := range list.List {
+ typ := check.typ(f.Type, cycleOk)
+ tag := check.tag(f)
+ if len(f.Names) > 0 {
+ // named fields
+ for _, name := range f.Names {
+ fields = append(fields, &StructField{name.Name, typ, tag, false})
+ }
+ } else {
+ // anonymous field
+ switch t := deref(typ).(type) {
+ case *Basic:
+ fields = append(fields, &StructField{t.Name, t, tag, true})
+ case *NamedType:
+ fields = append(fields, &StructField{t.Obj.Name, t, tag, true})
+ default:
+ if typ != Typ[Invalid] {
+ check.errorf(f.Type.Pos(), "invalid anonymous field type %s", typ)
+ }
+ }
+ }
+ }
+ return
+}
+
+type opPredicates map[token.Token]func(Type) bool
+
+var unaryOpPredicates = opPredicates{
+ token.ADD: isNumeric,
+ token.SUB: isNumeric,
+ token.XOR: isInteger,
+ token.NOT: isBoolean,
+ token.ARROW: func(typ Type) bool { t, ok := underlying(typ).(*Chan); return ok && t.Dir&ast.RECV != 0 },
+}
+
+func (check *checker) op(m opPredicates, x *operand, op token.Token) bool {
+ if pred := m[op]; pred != nil {
+ if !pred(x.typ) {
+ // TODO(gri) better error message for <-x where x is a send-only channel
+ // (<- is defined but not permitted). Special-case here or
+ // handle higher up.
+ check.invalidOp(x.pos(), "operator %s not defined for %s", op, x)
+ return false
+ }
+ } else {
+ check.invalidAST(x.pos(), "unknown operator %s", op)
+ return false
+ }
+ return true
+}
+
+func (check *checker) unary(x *operand, op token.Token) {
+ if op == token.AND {
+ // TODO(gri) need to check for composite literals, somehow (they are not variables, in general)
+ if x.mode != variable {
+ check.invalidOp(x.pos(), "cannot take address of %s", x)
+ x.mode = invalid
+ return
+ }
+ x.typ = &Pointer{Base: x.typ}
+ return
+ }
+
+ if !check.op(unaryOpPredicates, x, op) {
+ x.mode = invalid
+ return
+ }
+
+ if x.mode == constant {
+ switch op {
+ case token.ADD:
+ // nothing to do
+ case token.SUB:
+ x.val = binaryOpConst(zeroConst, x.val, token.SUB, false)
+ case token.XOR:
+ x.val = binaryOpConst(minusOneConst, x.val, token.XOR, false)
+ case token.NOT:
+ x.val = !x.val.(bool)
+ default:
+ unreachable()
+ }
+ // Typed constants must be representable in
+ // their type after each constant operation.
+ check.isRepresentable(x, x.typ.(*Basic))
+ return
+ }
+
+ x.mode = value
+}
+
+func isShift(op token.Token) bool {
+ return op == token.SHL || op == token.SHR
+}
+
+func isComparison(op token.Token) bool {
+ // Note: tokens are not ordered well to make this much easier
+ switch op {
+ case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ:
+ return true
+ }
+ return false
+}
+
+// isRepresentable checks that a constant operand is representable in the given type.
+func (check *checker) isRepresentable(x *operand, typ *Basic) {
+ if x.mode != constant || isUntyped(typ) {
+ return
+ }
+
+ if !isRepresentableConst(x.val, typ.Kind) {
+ var msg string
+ if isNumeric(x.typ) && isNumeric(typ) {
+ msg = "%s overflows %s"
+ } else {
+ msg = "cannot convert %s to %s"
+ }
+ check.errorf(x.pos(), msg, x, typ)
+ x.mode = invalid
+ }
+}
+
+// convertUntyped attempts to set the type of an untyped value to the target type.
+func (check *checker) convertUntyped(x *operand, target Type) {
+ if x.mode == invalid || !isUntyped(x.typ) {
+ return
+ }
+
+ // TODO(gri) Sloppy code - clean up. This function is central
+ // to assignment and expression checking.
+
+ if isUntyped(target) {
+ // both x and target are untyped
+ xkind := x.typ.(*Basic).Kind
+ tkind := target.(*Basic).Kind
+ if isNumeric(x.typ) && isNumeric(target) {
+ if xkind < tkind {
+ x.typ = target
+ }
+ } else if xkind != tkind {
+ check.errorf(x.pos(), "cannot convert %s to %s", x, target)
+ x.mode = invalid // avoid spurious errors
+ }
+ return
+ }
+
+ // typed target
+ switch t := underlying(target).(type) {
+ case *Basic:
+ check.isRepresentable(x, t)
+
+ case *Pointer, *Signature, *Interface, *Slice, *Map, *Chan:
+ if x.typ != Typ[UntypedNil] {
+ check.errorf(x.pos(), "cannot convert %s to %s", x, target)
+ x.mode = invalid
+ }
+ }
+
+ x.typ = target
+}
+
+func (check *checker) comparison(x, y *operand, op token.Token) {
+ // TODO(gri) deal with interface vs non-interface comparison
+
+ valid := false
+ if x.isAssignable(y.typ) || y.isAssignable(x.typ) {
+ switch op {
+ case token.EQL, token.NEQ:
+ valid = isComparable(x.typ)
+ case token.LSS, token.LEQ, token.GTR, token.GEQ:
+ valid = isOrdered(y.typ)
+ default:
+ unreachable()
+ }
+ }
+
+ if !valid {
+ check.invalidOp(x.pos(), "cannot compare %s and %s", x, y)
+ x.mode = invalid
+ return
+ }
+
+ if x.mode == constant && y.mode == constant {
+ x.val = compareConst(x.val, y.val, op)
+ } else {
+ x.mode = value
+ }
+
+ x.typ = Typ[UntypedBool]
+}
+
+// untyped lhs shift operands convert to the hint type
+// TODO(gri) shift hinting is not correct
+func (check *checker) shift(x, y *operand, op token.Token, hint Type) {
+ // The right operand in a shift expression must have unsigned integer type
+ // or be an untyped constant that can be converted to unsigned integer type.
+ if y.mode == constant && isUntyped(y.typ) {
+ if isRepresentableConst(y.val, UntypedInt) {
+ y.typ = Typ[UntypedInt]
+ }
+ }
+ if !isInteger(y.typ) || !isUnsigned(y.typ) && !isUntyped(y.typ) {
+ check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y)
+ x.mode = invalid
+ return
+ }
+
+ // If the left operand of a non-constant shift expression is an untyped
+ // constant, the type of the constant is what it would be if the shift
+ // expression were replaced by its left operand alone; the type is int
+ // if it cannot be determined from the context (for instance, if the
+ // shift expression is an operand in a comparison against an untyped
+ // constant)
+ if x.mode == constant && isUntyped(x.typ) {
+ if y.mode == constant {
+ // constant shift - accept values of any (untyped) type
+ // as long as the value is representable as an integer
+ if isRepresentableConst(x.val, UntypedInt) {
+ x.typ = Typ[UntypedInt]
+ }
+ } else {
+ // non-constant shift
+ if hint != nil {
+ check.convertUntyped(x, hint)
+ if x.mode == invalid {
+ return
+ }
+ }
+ }
+ }
+
+ if !isInteger(x.typ) {
+ check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
+ x.mode = invalid
+ return
+ }
+
+ if y.mode == constant {
+ const stupidShift = 1024
+ s, ok := y.val.(int64)
+ if !ok || s < 0 || s >= stupidShift {
+ check.invalidOp(y.pos(), "%s: stupid shift", y)
+ x.mode = invalid
+ return
+ }
+ if x.mode == constant {
+ x.val = shiftConst(x.val, uint(s), op)
+ return
+ }
+ x.mode = value
+ }
+
+ // x.mode, x.Typ are unchanged
+}
+
+var binaryOpPredicates = opPredicates{
+ token.ADD: func(typ Type) bool { return isNumeric(typ) || isString(typ) },
+ token.SUB: isNumeric,
+ token.MUL: isNumeric,
+ token.QUO: isNumeric,
+ token.REM: isInteger,
+
+ token.AND: isInteger,
+ token.OR: isInteger,
+ token.XOR: isInteger,
+ token.AND_NOT: isInteger,
+
+ token.LAND: isBoolean,
+ token.LOR: isBoolean,
+}
+
+func (check *checker) binary(x, y *operand, op token.Token, hint Type) {
+ if isShift(op) {
+ check.shift(x, y, op, hint)
+ return
+ }
+
+ check.convertUntyped(x, y.typ)
+ if x.mode == invalid {
+ return
+ }
+ check.convertUntyped(y, x.typ)
+ if y.mode == invalid {
+ x.mode = invalid
+ return
+ }
+
+ if isComparison(op) {
+ check.comparison(x, y, op)
+ return
+ }
+
+ if !isIdentical(x.typ, y.typ) {
+ check.invalidOp(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
+ x.mode = invalid
+ return
+ }
+
+ if !check.op(binaryOpPredicates, x, op) {
+ x.mode = invalid
+ return
+ }
+
+ if (op == token.QUO || op == token.REM) && y.mode == constant && isZeroConst(y.val) {
+ check.invalidOp(y.pos(), "division by zero")
+ x.mode = invalid
+ return
+ }
+
+ if x.mode == constant && y.mode == constant {
+ x.val = binaryOpConst(x.val, y.val, op, isInteger(x.typ))
+ // Typed constants must be representable in
+ // their type after each constant operation.
+ check.isRepresentable(x, x.typ.(*Basic))
+ return
+ }
+
+ x.mode = value
+ // x.typ is unchanged
+}
+
+// index checks an index expression for validity. If length >= 0, it is the upper
+// bound for the index. The result is a valid constant index >= 0, or a negative
+// value.
+//
+func (check *checker) index(index ast.Expr, length int64, iota int) int64 {
+ var x operand
+ var i int64 // index value, valid if >= 0
+
+ check.expr(&x, index, nil, iota)
+ if !x.isInteger() {
+ check.errorf(x.pos(), "index %s must be integer", &x)
+ return -1
+ }
+ if x.mode != constant {
+ return -1 // we cannot check more
+ }
+ // x.mode == constant and the index value must be >= 0
+ if isNegConst(x.val) {
+ check.errorf(x.pos(), "index %s must not be negative", &x)
+ return -1
+ }
+ var ok bool
+ if i, ok = x.val.(int64); !ok {
+ // index value doesn't fit into an int64
+ i = length // trigger out of bounds check below if we know length (>= 0)
+ }
+
+ if length >= 0 && i >= length {
+ check.errorf(x.pos(), "index %s is out of bounds (>= %d)", &x, length)
+ return -1
+ }
+
+ return i
+}
+
+func (check *checker) callRecord(x *operand) {
+ if x.mode != invalid {
+ check.mapf(x.expr, x.typ)
+ }
+}
+
+// expr typechecks expression e and initializes x with the expression
+// value or type. If an error occured, x.mode is set to invalid.
+// A hint != nil is used as operand type for untyped shifted operands;
+// iota >= 0 indicates that the expression is part of a constant declaration.
+// cycleOk indicates whether it is ok for a type expression to refer to itself.
+//
+func (check *checker) exprOrType(x *operand, e ast.Expr, hint Type, iota int, cycleOk bool) {
+ if check.mapf != nil {
+ defer check.callRecord(x)
+ }
+
+ switch e := e.(type) {
+ case *ast.BadExpr:
+ x.mode = invalid
+
+ case *ast.Ident:
+ if e.Name == "_" {
+ check.invalidOp(e.Pos(), "cannot use _ as value or type")
+ goto Error
+ }
+ obj := e.Obj
+ if obj == nil {
+ // unresolved identifier (error has been reported before)
+ goto Error
+ }
+ check.ident(e, cycleOk)
+ switch obj.Kind {
+ case ast.Bad:
+ goto Error
+ case ast.Pkg:
+ check.errorf(e.Pos(), "use of package %s not in selector", obj.Name)
+ goto Error
+ case ast.Con:
+ if obj.Data == nil {
+ goto Error // cycle detected
+ }
+ x.mode = constant
+ if obj == universeIota {
+ if iota < 0 {
+ check.invalidAST(e.Pos(), "cannot use iota outside constant declaration")
+ goto Error
+ }
+ x.val = int64(iota)
+ } else {
+ x.val = obj.Data
+ }
+ case ast.Typ:
+ x.mode = typexpr
+ if !cycleOk && underlying(obj.Type.(Type)) == nil {
+ check.errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name)
+ x.expr = e
+ x.typ = Typ[Invalid]
+ return // don't goto Error - need x.mode == typexpr
+ }
+ case ast.Var:
+ x.mode = variable
+ case ast.Fun:
+ x.mode = value
+ default:
+ unreachable()
+ }
+ x.typ = obj.Type.(Type)
+
+ case *ast.BasicLit:
+ x.setConst(e.Kind, e.Value)
+ if x.mode == invalid {
+ check.invalidAST(e.Pos(), "invalid literal %v", e.Value)
+ goto Error
+ }
+
+ case *ast.FuncLit:
+ x.mode = value
+ x.typ = check.typ(e.Type, false)
+ check.stmt(e.Body)
+
+ case *ast.CompositeLit:
+ // TODO(gri)
+ // - determine element type if nil
+ // - deal with map elements
+ for _, e := range e.Elts {
+ var x operand
+ check.expr(&x, e, hint, iota)
+ // TODO(gri) check assignment compatibility to element type
+ }
+ x.mode = value // TODO(gri) composite literals are addressable
+
+ case *ast.ParenExpr:
+ check.exprOrType(x, e.X, hint, iota, cycleOk)
+
+ case *ast.SelectorExpr:
+ // If the identifier refers to a package, handle everything here
+ // so we don't need a "package" mode for operands: package names
+ // can only appear in qualified identifiers which are mapped to
+ // selector expressions.
+ if ident, ok := e.X.(*ast.Ident); ok {
+ if obj := ident.Obj; obj != nil && obj.Kind == ast.Pkg {
+ exp := obj.Data.(*ast.Scope).Lookup(e.Sel.Name)
+ if exp == nil {
+ check.errorf(e.Sel.Pos(), "cannot refer to unexported %s", e.Sel.Name)
+ goto Error
+ }
+ // simplified version of the code for *ast.Idents:
+ // imported objects are always fully initialized
+ switch exp.Kind {
+ case ast.Con:
+ assert(exp.Data != nil)
+ x.mode = constant
+ x.val = exp.Data
+ case ast.Typ:
+ x.mode = typexpr
+ case ast.Var:
+ x.mode = variable
+ case ast.Fun:
+ x.mode = value
+ default:
+ unreachable()
+ }
+ x.expr = e
+ x.typ = exp.Type.(Type)
+ return
+ }
+ }
+
+ // TODO(gri) lots of checks missing below - just raw outline
+ check.expr(x, e.X, hint, iota)
+ switch typ := x.typ.(type) {
+ case *Struct:
+ if fld := lookupField(typ, e.Sel.Name); fld != nil {
+ // TODO(gri) only variable if struct is variable
+ x.mode = variable
+ x.expr = e
+ x.typ = fld.Type
+ return
+ }
+ case *Interface:
+ unimplemented()
+ case *NamedType:
+ unimplemented()
+ }
+ check.invalidOp(e.Pos(), "%s has no field or method %s", x.typ, e.Sel.Name)
+ goto Error
+
+ case *ast.IndexExpr:
+ check.expr(x, e.X, hint, iota)
+
+ valid := false
+ length := int64(-1) // valid if >= 0
+ switch typ := underlying(x.typ).(type) {
+ case *Basic:
+ if isString(typ) {
+ valid = true
+ if x.mode == constant {
+ length = int64(len(x.val.(string)))
+ }
+ // an indexed string always yields a byte value
+ // (not a constant) even if the string and the
+ // index are constant
+ x.mode = value
+ x.typ = Typ[Byte]
+ }
+
+ case *Array:
+ valid = true
+ length = typ.Len
+ if x.mode != variable {
+ x.mode = value
+ }
+ x.typ = typ.Elt
+
+ case *Slice:
+ valid = true
+ x.mode = variable
+ x.typ = typ.Elt
+
+ case *Map:
+ // TODO(gri) check index type
+ x.mode = variable
+ x.typ = typ.Elt
+ return
+ }
+
+ if !valid {
+ check.invalidOp(x.pos(), "cannot index %s", x)
+ goto Error
+ }
+
+ if e.Index == nil {
+ check.invalidAST(e.Pos(), "missing index expression for %s", x)
+ return
+ }
+
+ check.index(e.Index, length, iota)
+ // ok to continue
+
+ case *ast.SliceExpr:
+ check.expr(x, e.X, hint, iota)
+
+ valid := false
+ length := int64(-1) // valid if >= 0
+ switch typ := underlying(x.typ).(type) {
+ case *Basic:
+ if isString(typ) {
+ valid = true
+ if x.mode == constant {
+ length = int64(len(x.val.(string))) + 1 // +1 for slice
+ }
+ // a sliced string always yields a string value
+ // of the same type as the original string (not
+ // a constant) even if the string and the indexes
+ // are constant
+ x.mode = value
+ // x.typ doesn't change
+ }
+
+ case *Array:
+ valid = true
+ length = typ.Len + 1 // +1 for slice
+ if x.mode != variable {
+ check.invalidOp(x.pos(), "cannot slice %s (value not addressable)", x)
+ goto Error
+ }
+ x.typ = &Slice{Elt: typ.Elt}
+
+ case *Slice:
+ valid = true
+ x.mode = variable
+ // x.typ doesn't change
+ }
+
+ if !valid {
+ check.invalidOp(x.pos(), "cannot slice %s", x)
+ goto Error
+ }
+
+ var lo int64
+ if e.Low != nil {
+ lo = check.index(e.Low, length, iota)
+ }
+
+ var hi int64 = length
+ if e.High != nil {
+ hi = check.index(e.High, length, iota)
+ }
+
+ if hi >= 0 && lo > hi {
+ check.errorf(e.Low.Pos(), "inverted slice range: %d > %d", lo, hi)
+ // ok to continue
+ }
+
+ case *ast.TypeAssertExpr:
+ check.expr(x, e.X, hint, iota)
+ if _, ok := x.typ.(*Interface); !ok {
+ check.invalidOp(e.X.Pos(), "non-interface type %s in type assertion", x.typ)
+ // ok to continue
+ }
+ // TODO(gri) some type asserts are compile-time decidable
+ x.mode = valueok
+ x.expr = e
+ x.typ = check.typ(e.Type, false)
+
+ case *ast.CallExpr:
+ check.exprOrType(x, e.Fun, nil, iota, false)
+ if x.mode == typexpr {
+ check.conversion(x, e, x.typ, iota)
+
+ } else if sig, ok := underlying(x.typ).(*Signature); ok {
+ // check parameters
+ // TODO(gri) complete this
+ // - deal with various forms of calls
+ // - handle variadic calls
+ if len(sig.Params) == len(e.Args) {
+ var z, x operand
+ z.mode = variable
+ for i, arg := range e.Args {
+ z.expr = nil // TODO(gri) can we do better here?
+ z.typ = sig.Params[i].Type.(Type) // TODO(gri) should become something like checkObj(&z, ...) eventually
+ check.expr(&x, arg, z.typ, iota)
+ if x.mode == invalid {
+ goto Error
+ }
+ check.assignOperand(&z, &x)
+ }
+ }
+
+ // determine result
+ x.mode = value
+ if len(sig.Results) == 1 {
+ x.typ = sig.Results[0].Type.(Type)
+ } else {
+ // TODO(gri) change Signature representation to use tuples,
+ // then this conversion is not required
+ list := make([]Type, len(sig.Results))
+ for i, obj := range sig.Results {
+ list[i] = obj.Type.(Type)
+ }
+ x.typ = &tuple{list: list}
+ }
+
+ } else if bin, ok := x.typ.(*builtin); ok {
+ check.builtin(x, e, bin, iota)
+
+ } else {
+ check.invalidOp(x.pos(), "cannot call non-function %s", x)
+ goto Error
+ }
+
+ case *ast.StarExpr:
+ check.exprOrType(x, e.X, hint, iota, true)
+ switch x.mode {
+ case novalue:
+ check.errorf(x.pos(), "%s used as value or type", x)
+ goto Error
+ case typexpr:
+ x.typ = &Pointer{Base: x.typ}
+ default:
+ if typ, ok := x.typ.(*Pointer); ok {
+ x.mode = variable
+ x.typ = typ.Base
+ } else {
+ check.invalidOp(x.pos(), "cannot indirect %s", x)
+ goto Error
+ }
+ }
+
+ case *ast.UnaryExpr:
+ check.expr(x, e.X, hint, iota)
+ check.unary(x, e.Op)
+
+ case *ast.BinaryExpr:
+ var y operand
+ check.expr(x, e.X, hint, iota)
+ check.expr(&y, e.Y, hint, iota)
+ check.binary(x, &y, e.Op, hint)
+
+ case *ast.KeyValueExpr:
+ unimplemented()
+
+ case *ast.ArrayType:
+ if e.Len != nil {
+ check.expr(x, e.Len, nil, 0)
+ if x.mode == invalid {
+ goto Error
+ }
+ var n int64 = -1
+ if x.mode == constant {
+ if i, ok := x.val.(int64); ok && i == int64(int(i)) {
+ n = i
+ }
+ }
+ if n < 0 {
+ check.errorf(e.Len.Pos(), "invalid array bound %s", e.Len)
+ // ok to continue
+ n = 0
+ }
+ x.typ = &Array{Len: n, Elt: check.typ(e.Elt, cycleOk)}
+ } else {
+ x.typ = &Slice{Elt: check.typ(e.Elt, true)}
+ }
+ x.mode = typexpr
+
+ case *ast.StructType:
+ x.mode = typexpr
+ x.typ = &Struct{Fields: check.collectStructFields(e.Fields, cycleOk)}
+
+ case *ast.FuncType:
+ params, _, isVariadic := check.collectFields(token.FUNC, e.Params, true)
+ results, _, _ := check.collectFields(token.FUNC, e.Results, true)
+ x.mode = typexpr
+ x.typ = &Signature{Recv: nil, Params: params, Results: results, IsVariadic: isVariadic}
+
+ case *ast.InterfaceType:
+ methods, _, _ := check.collectFields(token.INTERFACE, e.Methods, cycleOk)
+ methods.Sort()
+ x.mode = typexpr
+ x.typ = &Interface{Methods: methods}
+
+ case *ast.MapType:
+ x.mode = typexpr
+ x.typ = &Map{Key: check.typ(e.Key, true), Elt: check.typ(e.Value, true)}
+
+ case *ast.ChanType:
+ x.mode = typexpr
+ x.typ = &Chan{Dir: e.Dir, Elt: check.typ(e.Value, true)}
+
+ default:
+ check.dump("e = %s", e)
+ unreachable()
+ }
+
+ // everything went well
+ x.expr = e
+ return
+
+Error:
+ x.mode = invalid
+ x.expr = e
+}
+
+// expr is like exprOrType but also checks that e represents a value (rather than a type).
+func (check *checker) expr(x *operand, e ast.Expr, hint Type, iota int) {
+ check.exprOrType(x, e, hint, iota, false)
+ switch x.mode {
+ case novalue:
+ check.errorf(x.pos(), "%s used as value", x)
+ x.mode = invalid
+ case typexpr:
+ check.errorf(x.pos(), "%s is not an expression", x)
+ x.mode = invalid
+ }
+}
+
+// typ is like exprOrType but also checks that e represents a type (rather than a value).
+// If an error occured, the result is Typ[Invalid].
+//
+func (check *checker) typ(e ast.Expr, cycleOk bool) Type {
+ var x operand
+ check.exprOrType(&x, e, nil, -1, cycleOk)
+ switch {
+ case x.mode == novalue:
+ check.errorf(x.pos(), "%s used as type", &x)
+ x.typ = Typ[Invalid]
+ case x.mode != typexpr:
+ check.errorf(x.pos(), "%s is not a type", &x)
+ x.typ = Typ[Invalid]
+ }
+ return x.typ
+}
diff --git a/libgo/go/exp/types/staging/gcimporter.go b/libgo/go/exp/types/staging/gcimporter.go
new file mode 100644
index 00000000000..b15238710e9
--- /dev/null
+++ b/libgo/go/exp/types/staging/gcimporter.go
@@ -0,0 +1,889 @@
+// 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.
+
+// This file implements an ast.Importer for gc-generated object files.
+// TODO(gri) Eventually move this into a separate package outside types.
+
+package types
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "go/ast"
+ "go/build"
+ "go/token"
+ "io"
+ "math/big"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "text/scanner"
+)
+
+var pkgExts = [...]string{".a", ".5", ".6", ".8"}
+
+// FindPkg returns the filename and unique package id for an import
+// path based on package information provided by build.Import (using
+// the build.Default build.Context).
+// If no file was found, an empty filename is returned.
+//
+func FindPkg(path, srcDir string) (filename, id string) {
+ if len(path) == 0 {
+ return
+ }
+
+ id = path
+ var noext string
+ switch {
+ default:
+ // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
+ // Don't require the source files to be present.
+ bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
+ if bp.PkgObj == "" {
+ return
+ }
+ noext = bp.PkgObj
+ if strings.HasSuffix(noext, ".a") {
+ noext = noext[:len(noext)-len(".a")]
+ }
+
+ case build.IsLocalImport(path):
+ // "./x" -> "/this/directory/x.ext", "/this/directory/x"
+ noext = filepath.Join(srcDir, path)
+ id = noext
+
+ case filepath.IsAbs(path):
+ // for completeness only - go/build.Import
+ // does not support absolute imports
+ // "/x" -> "/x.ext", "/x"
+ noext = path
+ }
+
+ // try extensions
+ for _, ext := range pkgExts {
+ filename = noext + ext
+ if f, err := os.Stat(filename); err == nil && !f.IsDir() {
+ return
+ }
+ }
+
+ filename = "" // not found
+ return
+}
+
+// GcImportData imports a package by reading the gc-generated export data,
+// adds the corresponding package object to the imports map indexed by id,
+// and returns the object.
+//
+// The imports map must contains all packages already imported, and no map
+// entry with id as the key must be present. The data reader position must
+// be the beginning of the export data section. The filename is only used
+// in error messages.
+//
+func GcImportData(imports map[string]*ast.Object, filename, id string, data *bufio.Reader) (pkg *ast.Object, err error) {
+ if trace {
+ fmt.Printf("importing %s (%s)\n", id, filename)
+ }
+
+ // support for gcParser error handling
+ defer func() {
+ if r := recover(); r != nil {
+ err = r.(importError) // will re-panic if r is not an importError
+ }
+ }()
+
+ var p gcParser
+ p.init(filename, id, data, imports)
+ pkg = p.parseExport()
+
+ return
+}
+
+// GcImport imports a gc-generated package given its import path, adds the
+// corresponding package object to the imports map, and returns the object.
+// Local import paths are interpreted relative to the current working directory.
+// The imports map must contains all packages already imported.
+// GcImport satisfies the ast.Importer signature.
+//
+func GcImport(imports map[string]*ast.Object, path string) (pkg *ast.Object, err error) {
+ if path == "unsafe" {
+ return Unsafe, nil
+ }
+
+ srcDir, err := os.Getwd()
+ if err != nil {
+ return
+ }
+ filename, id := FindPkg(path, srcDir)
+ if filename == "" {
+ err = errors.New("can't find import: " + id)
+ return
+ }
+
+ // Note: imports[id] may already contain a partially imported package.
+ // We must continue doing the full import here since we don't
+ // know if something is missing.
+ // TODO: There's no need to re-import a package if we know that we
+ // have done a full import before. At the moment we cannot
+ // tell from the available information in this function alone.
+
+ // open file
+ f, err := os.Open(filename)
+ if err != nil {
+ return
+ }
+ defer func() {
+ f.Close()
+ if err != nil {
+ // Add file name to error.
+ err = fmt.Errorf("reading export data: %s: %v", filename, err)
+ }
+ }()
+
+ buf := bufio.NewReader(f)
+ if err = FindGcExportData(buf); err != nil {
+ return
+ }
+
+ pkg, err = GcImportData(imports, filename, id, buf)
+
+ return
+}
+
+// ----------------------------------------------------------------------------
+// gcParser
+
+// gcParser parses the exports inside a gc compiler-produced
+// object/archive file and populates its scope with the results.
+type gcParser struct {
+ scanner scanner.Scanner
+ tok rune // current token
+ lit string // literal string; only valid for Ident, Int, String tokens
+ id string // package id of imported package
+ imports map[string]*ast.Object // package id -> package object
+}
+
+func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*ast.Object) {
+ p.scanner.Init(src)
+ p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
+ p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+ p.scanner.Whitespace = 1<<'\t' | 1<<' '
+ p.scanner.Filename = filename // for good error messages
+ p.next()
+ p.id = id
+ p.imports = imports
+}
+
+func (p *gcParser) next() {
+ p.tok = p.scanner.Scan()
+ switch p.tok {
+ case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·':
+ p.lit = p.scanner.TokenText()
+ default:
+ p.lit = ""
+ }
+ if trace {
+ fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
+ }
+}
+
+// Declare inserts a named object of the given kind in scope.
+func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object {
+ // the object may have been imported before - if it exists
+ // already in the respective package scope, return that object
+ if obj := scope.Lookup(name); obj != nil {
+ assert(obj.Kind == kind)
+ return obj
+ }
+
+ // otherwise create a new object and insert it into the package scope
+ obj := ast.NewObj(kind, name)
+ if scope.Insert(obj) != nil {
+ p.errorf("already declared: %v %s", kind, obj.Name)
+ }
+
+ // if the new type object is a named type it may be referred
+ // to before the underlying type is known - set it up
+ if kind == ast.Typ {
+ obj.Type = &NamedType{Obj: obj}
+ }
+
+ return obj
+}
+
+// ----------------------------------------------------------------------------
+// Error handling
+
+// Internal errors are boxed as importErrors.
+type importError struct {
+ pos scanner.Position
+ err error
+}
+
+func (e importError) Error() string {
+ return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
+}
+
+func (p *gcParser) error(err interface{}) {
+ if s, ok := err.(string); ok {
+ err = errors.New(s)
+ }
+ // panic with a runtime.Error if err is not an error
+ panic(importError{p.scanner.Pos(), err.(error)})
+}
+
+func (p *gcParser) errorf(format string, args ...interface{}) {
+ p.error(fmt.Sprintf(format, args...))
+}
+
+func (p *gcParser) expect(tok rune) string {
+ lit := p.lit
+ if p.tok != tok {
+ p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
+ }
+ p.next()
+ return lit
+}
+
+func (p *gcParser) expectSpecial(tok string) {
+ sep := 'x' // not white space
+ i := 0
+ for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
+ sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+ p.next()
+ i++
+ }
+ if i < len(tok) {
+ p.errorf("expected %q, got %q", tok, tok[0:i])
+ }
+}
+
+func (p *gcParser) expectKeyword(keyword string) {
+ lit := p.expect(scanner.Ident)
+ if lit != keyword {
+ p.errorf("expected keyword %s, got %q", keyword, lit)
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Import declarations
+
+// ImportPath = string_lit .
+//
+func (p *gcParser) parsePkgId() *ast.Object {
+ id, err := strconv.Unquote(p.expect(scanner.String))
+ if err != nil {
+ p.error(err)
+ }
+
+ switch id {
+ case "":
+ // id == "" stands for the imported package id
+ // (only known at time of package installation)
+ id = p.id
+ case "unsafe":
+ // package unsafe is not in the imports map - handle explicitly
+ return Unsafe
+ }
+
+ pkg := p.imports[id]
+ if pkg == nil {
+ pkg = ast.NewObj(ast.Pkg, "")
+ pkg.Data = ast.NewScope(nil)
+ p.imports[id] = pkg
+ }
+
+ return pkg
+}
+
+// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
+func (p *gcParser) parseDotIdent() string {
+ ident := ""
+ if p.tok != scanner.Int {
+ sep := 'x' // not white space
+ for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
+ ident += p.lit
+ sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+ p.next()
+ }
+ }
+ if ident == "" {
+ p.expect(scanner.Ident) // use expect() for error handling
+ }
+ return ident
+}
+
+// ExportedName = "@" ImportPath "." dotIdentifier .
+//
+func (p *gcParser) parseExportedName() (*ast.Object, string) {
+ p.expect('@')
+ pkg := p.parsePkgId()
+ p.expect('.')
+ name := p.parseDotIdent()
+ return pkg, name
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+// BasicType = identifier .
+//
+func (p *gcParser) parseBasicType() Type {
+ id := p.expect(scanner.Ident)
+ obj := Universe.Lookup(id)
+ if obj == nil || obj.Kind != ast.Typ {
+ p.errorf("not a basic type: %s", id)
+ }
+ return obj.Type.(Type)
+}
+
+// ArrayType = "[" int_lit "]" Type .
+//
+func (p *gcParser) parseArrayType() Type {
+ // "[" already consumed and lookahead known not to be "]"
+ lit := p.expect(scanner.Int)
+ p.expect(']')
+ elt := p.parseType()
+ n, err := strconv.ParseInt(lit, 10, 64)
+ if err != nil {
+ p.error(err)
+ }
+ return &Array{Len: n, Elt: elt}
+}
+
+// MapType = "map" "[" Type "]" Type .
+//
+func (p *gcParser) parseMapType() Type {
+ p.expectKeyword("map")
+ p.expect('[')
+ key := p.parseType()
+ p.expect(']')
+ elt := p.parseType()
+ return &Map{Key: key, Elt: elt}
+}
+
+// Name = identifier | "?" | ExportedName .
+//
+func (p *gcParser) parseName() (name string) {
+ switch p.tok {
+ case scanner.Ident:
+ name = p.lit
+ p.next()
+ case '?':
+ // anonymous
+ p.next()
+ case '@':
+ // exported name prefixed with package path
+ _, name = p.parseExportedName()
+ default:
+ p.error("name expected")
+ }
+ return
+}
+
+// Field = Name Type [ string_lit ] .
+//
+func (p *gcParser) parseField() *StructField {
+ var f StructField
+ f.Name = p.parseName()
+ f.Type = p.parseType()
+ if p.tok == scanner.String {
+ f.Tag = p.expect(scanner.String)
+ }
+ if f.Name == "" {
+ // anonymous field - typ must be T or *T and T must be a type name
+ if typ, ok := deref(f.Type).(*NamedType); ok && typ.Obj != nil {
+ f.Name = typ.Obj.Name
+ } else {
+ p.errorf("anonymous field expected")
+ }
+ }
+ return &f
+}
+
+// StructType = "struct" "{" [ FieldList ] "}" .
+// FieldList = Field { ";" Field } .
+//
+func (p *gcParser) parseStructType() Type {
+ var fields []*StructField
+
+ parseField := func() {
+ fields = append(fields, p.parseField())
+ }
+
+ p.expectKeyword("struct")
+ p.expect('{')
+ if p.tok != '}' {
+ parseField()
+ for p.tok == ';' {
+ p.next()
+ parseField()
+ }
+ }
+ p.expect('}')
+
+ return &Struct{Fields: fields}
+}
+
+// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
+//
+func (p *gcParser) parseParameter() (par *ast.Object, isVariadic bool) {
+ name := p.parseName()
+ if name == "" {
+ name = "_" // cannot access unnamed identifiers
+ }
+ if p.tok == '.' {
+ p.expectSpecial("...")
+ isVariadic = true
+ }
+ ptyp := p.parseType()
+ // ignore argument tag (e.g. "noescape")
+ if p.tok == scanner.String {
+ p.expect(scanner.String)
+ }
+ par = ast.NewObj(ast.Var, name)
+ par.Type = ptyp
+ return
+}
+
+// Parameters = "(" [ ParameterList ] ")" .
+// ParameterList = { Parameter "," } Parameter .
+//
+func (p *gcParser) parseParameters() (list []*ast.Object, isVariadic bool) {
+ parseParameter := func() {
+ par, variadic := p.parseParameter()
+ list = append(list, par)
+ if variadic {
+ if isVariadic {
+ p.error("... not on final argument")
+ }
+ isVariadic = true
+ }
+ }
+
+ p.expect('(')
+ if p.tok != ')' {
+ parseParameter()
+ for p.tok == ',' {
+ p.next()
+ parseParameter()
+ }
+ }
+ p.expect(')')
+
+ return
+}
+
+// Signature = Parameters [ Result ] .
+// Result = Type | Parameters .
+//
+func (p *gcParser) parseSignature() *Signature {
+ params, isVariadic := p.parseParameters()
+
+ // optional result type
+ var results []*ast.Object
+ switch p.tok {
+ case scanner.Ident, '[', '*', '<', '@':
+ // single, unnamed result
+ result := ast.NewObj(ast.Var, "_")
+ result.Type = p.parseType()
+ results = []*ast.Object{result}
+ case '(':
+ // named or multiple result(s)
+ var variadic bool
+ results, variadic = p.parseParameters()
+ if variadic {
+ p.error("... not permitted on result type")
+ }
+ }
+
+ return &Signature{Params: params, Results: results, IsVariadic: isVariadic}
+}
+
+// InterfaceType = "interface" "{" [ MethodList ] "}" .
+// MethodList = Method { ";" Method } .
+// Method = Name Signature .
+//
+// (The methods of embedded interfaces are always "inlined"
+// by the compiler and thus embedded interfaces are never
+// visible in the export data.)
+//
+func (p *gcParser) parseInterfaceType() Type {
+ var methods ObjList
+
+ parseMethod := func() {
+ obj := ast.NewObj(ast.Fun, p.parseName())
+ obj.Type = p.parseSignature()
+ methods = append(methods, obj)
+ }
+
+ p.expectKeyword("interface")
+ p.expect('{')
+ if p.tok != '}' {
+ parseMethod()
+ for p.tok == ';' {
+ p.next()
+ parseMethod()
+ }
+ }
+ p.expect('}')
+
+ methods.Sort()
+ return &Interface{Methods: methods}
+}
+
+// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
+//
+func (p *gcParser) parseChanType() Type {
+ dir := ast.SEND | ast.RECV
+ if p.tok == scanner.Ident {
+ p.expectKeyword("chan")
+ if p.tok == '<' {
+ p.expectSpecial("<-")
+ dir = ast.SEND
+ }
+ } else {
+ p.expectSpecial("<-")
+ p.expectKeyword("chan")
+ dir = ast.RECV
+ }
+ elt := p.parseType()
+ return &Chan{Dir: dir, Elt: elt}
+}
+
+// Type =
+// BasicType | TypeName | ArrayType | SliceType | StructType |
+// PointerType | FuncType | InterfaceType | MapType | ChanType |
+// "(" Type ")" .
+// BasicType = ident .
+// TypeName = ExportedName .
+// SliceType = "[" "]" Type .
+// PointerType = "*" Type .
+// FuncType = "func" Signature .
+//
+func (p *gcParser) parseType() Type {
+ switch p.tok {
+ case scanner.Ident:
+ switch p.lit {
+ default:
+ return p.parseBasicType()
+ case "struct":
+ return p.parseStructType()
+ case "func":
+ // FuncType
+ p.next()
+ return p.parseSignature()
+ case "interface":
+ return p.parseInterfaceType()
+ case "map":
+ return p.parseMapType()
+ case "chan":
+ return p.parseChanType()
+ }
+ case '@':
+ // TypeName
+ pkg, name := p.parseExportedName()
+ return p.declare(pkg.Data.(*ast.Scope), ast.Typ, name).Type.(Type)
+ case '[':
+ p.next() // look ahead
+ if p.tok == ']' {
+ // SliceType
+ p.next()
+ return &Slice{Elt: p.parseType()}
+ }
+ return p.parseArrayType()
+ case '*':
+ // PointerType
+ p.next()
+ return &Pointer{Base: p.parseType()}
+ case '<':
+ return p.parseChanType()
+ case '(':
+ // "(" Type ")"
+ p.next()
+ typ := p.parseType()
+ p.expect(')')
+ return typ
+ }
+ p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+ return nil
+}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+// ImportDecl = "import" identifier string_lit .
+//
+func (p *gcParser) parseImportDecl() {
+ p.expectKeyword("import")
+ // The identifier has no semantic meaning in the import data.
+ // It exists so that error messages can print the real package
+ // name: binary.ByteOrder instead of "encoding/binary".ByteOrder.
+ name := p.expect(scanner.Ident)
+ pkg := p.parsePkgId()
+ assert(pkg.Name == "" || pkg.Name == name)
+ pkg.Name = name
+}
+
+// int_lit = [ "+" | "-" ] { "0" ... "9" } .
+//
+func (p *gcParser) parseInt() (neg bool, val string) {
+ switch p.tok {
+ case '-':
+ neg = true
+ fallthrough
+ case '+':
+ p.next()
+ }
+ val = p.expect(scanner.Int)
+ return
+}
+
+// number = int_lit [ "p" int_lit ] .
+//
+func (p *gcParser) parseNumber() (x operand) {
+ x.mode = constant
+
+ // mantissa
+ neg, val := p.parseInt()
+ mant, ok := new(big.Int).SetString(val, 0)
+ assert(ok)
+ if neg {
+ mant.Neg(mant)
+ }
+
+ if p.lit == "p" {
+ // exponent (base 2)
+ p.next()
+ neg, val = p.parseInt()
+ exp64, err := strconv.ParseUint(val, 10, 0)
+ if err != nil {
+ p.error(err)
+ }
+ exp := uint(exp64)
+ if neg {
+ denom := big.NewInt(1)
+ denom.Lsh(denom, exp)
+ x.typ = Typ[UntypedFloat]
+ x.val = normalizeRatConst(new(big.Rat).SetFrac(mant, denom))
+ return
+ }
+ if exp > 0 {
+ mant.Lsh(mant, exp)
+ }
+ x.typ = Typ[UntypedFloat]
+ x.val = normalizeIntConst(mant)
+ return
+ }
+
+ x.typ = Typ[UntypedInt]
+ x.val = normalizeIntConst(mant)
+ return
+}
+
+// ConstDecl = "const" ExportedName [ Type ] "=" Literal .
+// Literal = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit .
+// bool_lit = "true" | "false" .
+// complex_lit = "(" float_lit "+" float_lit "i" ")" .
+// rune_lit = "(" int_lit "+" int_lit ")" .
+// string_lit = `"` { unicode_char } `"` .
+//
+func (p *gcParser) parseConstDecl() {
+ p.expectKeyword("const")
+ pkg, name := p.parseExportedName()
+ obj := p.declare(pkg.Data.(*ast.Scope), ast.Con, name)
+ var x operand
+ if p.tok != '=' {
+ obj.Type = p.parseType()
+ }
+ p.expect('=')
+ switch p.tok {
+ case scanner.Ident:
+ // bool_lit
+ if p.lit != "true" && p.lit != "false" {
+ p.error("expected true or false")
+ }
+ x.typ = Typ[UntypedBool]
+ x.val = p.lit == "true"
+ p.next()
+
+ case '-', scanner.Int:
+ // int_lit
+ x = p.parseNumber()
+
+ case '(':
+ // complex_lit or rune_lit
+ p.next()
+ if p.tok == scanner.Char {
+ p.next()
+ p.expect('+')
+ x = p.parseNumber()
+ x.typ = Typ[UntypedRune]
+ p.expect(')')
+ break
+ }
+ re := p.parseNumber()
+ p.expect('+')
+ im := p.parseNumber()
+ p.expectKeyword("i")
+ p.expect(')')
+ x.typ = Typ[UntypedComplex]
+ // TODO(gri) fix this
+ _, _ = re, im
+ x.val = zeroConst
+
+ case scanner.Char:
+ // rune_lit
+ x.setConst(token.CHAR, p.lit)
+ p.next()
+
+ case scanner.String:
+ // string_lit
+ x.setConst(token.STRING, p.lit)
+ p.next()
+
+ default:
+ p.errorf("expected literal got %s", scanner.TokenString(p.tok))
+ }
+ if obj.Type == nil {
+ obj.Type = x.typ
+ }
+ assert(x.val != nil)
+ obj.Data = x.val
+}
+
+// TypeDecl = "type" ExportedName Type .
+//
+func (p *gcParser) parseTypeDecl() {
+ p.expectKeyword("type")
+ pkg, name := p.parseExportedName()
+ obj := p.declare(pkg.Data.(*ast.Scope), ast.Typ, name)
+
+ // The type object may have been imported before and thus already
+ // have a type associated with it. We still need to parse the type
+ // structure, but throw it away if the object already has a type.
+ // This ensures that all imports refer to the same type object for
+ // a given type declaration.
+ typ := p.parseType()
+
+ if name := obj.Type.(*NamedType); name.Underlying == nil {
+ name.Underlying = typ
+ }
+}
+
+// VarDecl = "var" ExportedName Type .
+//
+func (p *gcParser) parseVarDecl() {
+ p.expectKeyword("var")
+ pkg, name := p.parseExportedName()
+ obj := p.declare(pkg.Data.(*ast.Scope), ast.Var, name)
+ obj.Type = p.parseType()
+}
+
+// FuncBody = "{" ... "}" .
+//
+func (p *gcParser) parseFuncBody() {
+ p.expect('{')
+ for i := 1; i > 0; p.next() {
+ switch p.tok {
+ case '{':
+ i++
+ case '}':
+ i--
+ }
+ }
+}
+
+// FuncDecl = "func" ExportedName Signature [ FuncBody ] .
+//
+func (p *gcParser) parseFuncDecl() {
+ // "func" already consumed
+ pkg, name := p.parseExportedName()
+ obj := p.declare(pkg.Data.(*ast.Scope), ast.Fun, name)
+ obj.Type = p.parseSignature()
+ if p.tok == '{' {
+ p.parseFuncBody()
+ }
+}
+
+// MethodDecl = "func" Receiver Name Signature .
+// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ].
+//
+func (p *gcParser) parseMethodDecl() {
+ // "func" already consumed
+ p.expect('(')
+ p.parseParameter() // receiver
+ p.expect(')')
+ p.parseName() // unexported method names in imports are qualified with their package.
+ p.parseSignature()
+ if p.tok == '{' {
+ p.parseFuncBody()
+ }
+}
+
+// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
+//
+func (p *gcParser) parseDecl() {
+ switch p.lit {
+ case "import":
+ p.parseImportDecl()
+ case "const":
+ p.parseConstDecl()
+ case "type":
+ p.parseTypeDecl()
+ case "var":
+ p.parseVarDecl()
+ case "func":
+ p.next() // look ahead
+ if p.tok == '(' {
+ p.parseMethodDecl()
+ } else {
+ p.parseFuncDecl()
+ }
+ }
+ p.expect('\n')
+}
+
+// ----------------------------------------------------------------------------
+// Export
+
+// Export = "PackageClause { Decl } "$$" .
+// PackageClause = "package" identifier [ "safe" ] "\n" .
+//
+func (p *gcParser) parseExport() *ast.Object {
+ p.expectKeyword("package")
+ name := p.expect(scanner.Ident)
+ if p.tok != '\n' {
+ // A package is safe if it was compiled with the -u flag,
+ // which disables the unsafe package.
+ // TODO(gri) remember "safe" package
+ p.expectKeyword("safe")
+ }
+ p.expect('\n')
+
+ pkg := p.imports[p.id]
+ if pkg == nil {
+ pkg = ast.NewObj(ast.Pkg, name)
+ pkg.Data = ast.NewScope(nil)
+ p.imports[p.id] = pkg
+ }
+
+ for p.tok != '$' && p.tok != scanner.EOF {
+ p.parseDecl()
+ }
+
+ if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
+ // don't call next()/expect() since reading past the
+ // export data may cause scanner errors (e.g. NUL chars)
+ p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
+ }
+
+ if n := p.scanner.ErrorCount; n != 0 {
+ p.errorf("expected no scanner errors, got %d", n)
+ }
+
+ return pkg
+}
diff --git a/libgo/go/exp/types/staging/gcimporter_test.go b/libgo/go/exp/types/staging/gcimporter_test.go
new file mode 100644
index 00000000000..2f89d3ac912
--- /dev/null
+++ b/libgo/go/exp/types/staging/gcimporter_test.go
@@ -0,0 +1,153 @@
+// 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 types
+
+import (
+ "go/ast"
+ "go/build"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "testing"
+ "time"
+)
+
+var gcPath string // Go compiler path
+
+func init() {
+ // determine compiler
+ var gc string
+ switch runtime.GOARCH {
+ case "386":
+ gc = "8g"
+ case "amd64":
+ gc = "6g"
+ case "arm":
+ gc = "5g"
+ default:
+ gcPath = "unknown-GOARCH-compiler"
+ return
+ }
+ gcPath = filepath.Join(build.ToolDir, gc)
+}
+
+func compile(t *testing.T, dirname, filename string) string {
+ cmd := exec.Command(gcPath, filename)
+ cmd.Dir = dirname
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Logf("%s", out)
+ t.Fatalf("%s %s failed: %s", gcPath, filename, err)
+ }
+ archCh, _ := build.ArchChar(runtime.GOARCH)
+ // filename should end with ".go"
+ return filepath.Join(dirname, filename[:len(filename)-2]+archCh)
+}
+
+// Use the same global imports map for all tests. The effect is
+// as if all tested packages were imported into a single package.
+var imports = make(map[string]*ast.Object)
+
+func testPath(t *testing.T, path string) bool {
+ _, err := GcImport(imports, path)
+ if err != nil {
+ t.Errorf("testPath(%s): %s", path, err)
+ return false
+ }
+ return true
+}
+
+const maxTime = 3 * time.Second
+
+func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
+ dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
+ list, err := ioutil.ReadDir(dirname)
+ if err != nil {
+ t.Errorf("testDir(%s): %s", dirname, err)
+ }
+ for _, f := range list {
+ if time.Now().After(endTime) {
+ t.Log("testing time used up")
+ return
+ }
+ switch {
+ case !f.IsDir():
+ // try extensions
+ for _, ext := range pkgExts {
+ if strings.HasSuffix(f.Name(), ext) {
+ name := f.Name()[0 : len(f.Name())-len(ext)] // remove extension
+ if testPath(t, filepath.Join(dir, name)) {
+ nimports++
+ }
+ }
+ }
+ case f.IsDir():
+ nimports += testDir(t, filepath.Join(dir, f.Name()), endTime)
+ }
+ }
+ return
+}
+
+func TestGcImport(t *testing.T) {
+ // On cross-compile builds, the path will not exist.
+ // Need to use GOHOSTOS, which is not available.
+ if _, err := os.Stat(gcPath); err != nil {
+ t.Logf("skipping test: %v", err)
+ return
+ }
+
+ if outFn := compile(t, "testdata", "exports.go"); outFn != "" {
+ defer os.Remove(outFn)
+ }
+
+ nimports := 0
+ if testPath(t, "./testdata/exports") {
+ nimports++
+ }
+ nimports += testDir(t, "", time.Now().Add(maxTime)) // installed packages
+ t.Logf("tested %d imports", nimports)
+}
+
+var importedObjectTests = []struct {
+ name string
+ kind ast.ObjKind
+ typ string
+}{
+ {"unsafe.Pointer", ast.Typ, "Pointer"},
+ {"math.Pi", ast.Con, "untyped float"},
+ {"io.Reader", ast.Typ, "interface{Read(p []byte) (n int, err error)}"},
+ {"io.ReadWriter", ast.Typ, "interface{Read(p []byte) (n int, err error); Write(p []byte) (n int, err error)}"},
+ {"math.Sin", ast.Fun, "func(x float64) (_ float64)"},
+ // TODO(gri) add more tests
+}
+
+func TestGcImportedTypes(t *testing.T) {
+ for _, test := range importedObjectTests {
+ s := strings.Split(test.name, ".")
+ if len(s) != 2 {
+ t.Fatal("inconsistent test data")
+ }
+ importPath := s[0]
+ objName := s[1]
+
+ pkg, err := GcImport(imports, importPath)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+
+ obj := pkg.Data.(*ast.Scope).Lookup(objName)
+ if obj.Kind != test.kind {
+ t.Errorf("%s: got kind = %q; want %q", test.name, obj.Kind, test.kind)
+ }
+ typ := typeString(underlying(obj.Type.(Type)))
+ if typ != test.typ {
+ t.Errorf("%s: got type = %q; want %q", test.name, typ, test.typ)
+ }
+ }
+}
diff --git a/libgo/go/exp/types/staging/operand.go b/libgo/go/exp/types/staging/operand.go
new file mode 100644
index 00000000000..f2440c2999e
--- /dev/null
+++ b/libgo/go/exp/types/staging/operand.go
@@ -0,0 +1,201 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file defines operands and associated operations.
+
+package types
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/token"
+)
+
+// An operandMode specifies the (addressing) mode of an operand.
+type operandMode int
+
+const (
+ invalid operandMode = iota // operand is invalid (due to an earlier error) - ignore
+ novalue // operand represents no value (result of a function call w/o result)
+ typexpr // operand is a type
+ constant // operand is a constant; the operand's typ is a Basic type
+ variable // operand is an addressable variable
+ value // operand is a computed value
+ valueok // like mode == value, but operand may be used in a comma,ok expression
+)
+
+var operandModeString = [...]string{
+ invalid: "invalid",
+ novalue: "no value",
+ typexpr: "type",
+ constant: "constant",
+ variable: "variable",
+ value: "value",
+ valueok: "value,ok",
+}
+
+// An operand represents an intermediate value during type checking.
+// Operands have an (addressing) mode, the expression evaluating to
+// the operand, the operand's type, and for constants a constant value.
+//
+type operand struct {
+ mode operandMode
+ expr ast.Expr
+ typ Type
+ val interface{}
+}
+
+// pos returns the position of the expression corresponding to x.
+// If x is invalid the position is token.NoPos.
+//
+func (x *operand) pos() token.Pos {
+ // x.expr may not be set if x is invalid
+ if x.expr == nil {
+ return token.NoPos
+ }
+ return x.expr.Pos()
+}
+
+func (x *operand) String() string {
+ if x.mode == invalid {
+ return "invalid operand"
+ }
+ var buf bytes.Buffer
+ if x.expr != nil {
+ buf.WriteString(exprString(x.expr))
+ buf.WriteString(" (")
+ }
+ buf.WriteString(operandModeString[x.mode])
+ if x.mode == constant {
+ fmt.Fprintf(&buf, " %v", x.val)
+ }
+ if x.mode != novalue && (x.mode != constant || !isUntyped(x.typ)) {
+ fmt.Fprintf(&buf, " of type %s", typeString(x.typ))
+ }
+ if x.expr != nil {
+ buf.WriteByte(')')
+ }
+ return buf.String()
+}
+
+// setConst sets x to the untyped constant for literal lit.
+func (x *operand) setConst(tok token.Token, lit string) {
+ x.mode = invalid
+
+ var kind BasicKind
+ var val interface{}
+ switch tok {
+ case token.INT:
+ kind = UntypedInt
+ val = makeIntConst(lit)
+
+ case token.FLOAT:
+ kind = UntypedFloat
+ val = makeFloatConst(lit)
+
+ case token.IMAG:
+ kind = UntypedComplex
+ val = makeComplexConst(lit)
+
+ case token.CHAR:
+ kind = UntypedRune
+ val = makeRuneConst(lit)
+
+ case token.STRING:
+ kind = UntypedString
+ val = makeStringConst(lit)
+ }
+
+ if val != nil {
+ x.mode = constant
+ x.typ = Typ[kind]
+ x.val = val
+ }
+}
+
+// implements reports whether x implements interface T.
+func (x *operand) implements(T *Interface) bool {
+ if x.mode == invalid {
+ return true // avoid spurious errors
+ }
+
+ unimplemented()
+ return true
+}
+
+// isAssignable reports whether x is assignable to a variable of type T.
+func (x *operand) isAssignable(T Type) bool {
+ if x.mode == invalid || T == Typ[Invalid] {
+ return true // avoid spurious errors
+ }
+
+ V := x.typ
+
+ // x's type is identical to T
+ if isIdentical(V, T) {
+ return true
+ }
+
+ Vu := underlying(V)
+ Tu := underlying(T)
+
+ // x's type V and T have identical underlying types
+ // and at least one of V or T is not a named type
+ if isIdentical(Vu, Tu) {
+ return !isNamed(V) || !isNamed(T)
+ }
+
+ // T is an interface type and x implements T
+ if Ti, ok := Tu.(*Interface); ok && x.implements(Ti) {
+ return true
+ }
+
+ // x is a bidirectional channel value, T is a channel
+ // type, x's type V and T have identical element types,
+ // and at least one of V or T is not a named type
+ if Vc, ok := Vu.(*Chan); ok && Vc.Dir == ast.SEND|ast.RECV {
+ if Tc, ok := Tu.(*Chan); ok && isIdentical(Vc.Elt, Tc.Elt) {
+ return !isNamed(V) || !isNamed(T)
+ }
+ }
+
+ // x is the predeclared identifier nil and T is a pointer,
+ // function, slice, map, channel, or interface type
+ if x.typ == Typ[UntypedNil] {
+ switch Tu.(type) {
+ case *Pointer, *Signature, *Slice, *Map, *Chan, *Interface:
+ return true
+ }
+ return false
+ }
+
+ // x is an untyped constant representable by a value of type T
+ // - this is taken care of in the assignment check
+ // TODO(gri) double-check - isAssignable is used elsewhere
+
+ return false
+}
+
+// isInteger reports whether x is a (typed or untyped) integer value.
+func (x *operand) isInteger() bool {
+ return x.mode == invalid ||
+ isInteger(x.typ) ||
+ x.mode == constant && isRepresentableConst(x.val, UntypedInt)
+}
+
+// lookupField returns the struct field with the given name in typ.
+// If no such field exists, the result is nil.
+// TODO(gri) should this be a method of Struct?
+//
+func lookupField(typ *Struct, name string) *StructField {
+ // TODO(gri) deal with embedding and conflicts - this is
+ // a very basic version to get going for now.
+ for _, f := range typ.Fields {
+ if f.Name == name {
+ return f
+ }
+ }
+ return nil
+}
diff --git a/libgo/go/exp/types/staging/predicates.go b/libgo/go/exp/types/staging/predicates.go
new file mode 100644
index 00000000000..35fcf858b61
--- /dev/null
+++ b/libgo/go/exp/types/staging/predicates.go
@@ -0,0 +1,236 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements commonly used type predicates.
+
+package types
+
+func isNamed(typ Type) bool {
+ if _, ok := typ.(*Basic); ok {
+ return ok
+ }
+ _, ok := typ.(*NamedType)
+ return ok
+}
+
+func isBoolean(typ Type) bool {
+ t, ok := underlying(typ).(*Basic)
+ return ok && t.Info&IsBoolean != 0
+}
+
+func isInteger(typ Type) bool {
+ t, ok := underlying(typ).(*Basic)
+ return ok && t.Info&IsInteger != 0
+}
+
+func isUnsigned(typ Type) bool {
+ t, ok := underlying(typ).(*Basic)
+ return ok && t.Info&IsUnsigned != 0
+}
+
+func isFloat(typ Type) bool {
+ t, ok := underlying(typ).(*Basic)
+ return ok && t.Info&IsFloat != 0
+}
+
+func isComplex(typ Type) bool {
+ t, ok := underlying(typ).(*Basic)
+ return ok && t.Info&IsComplex != 0
+}
+
+func isNumeric(typ Type) bool {
+ t, ok := underlying(typ).(*Basic)
+ return ok && t.Info&IsNumeric != 0
+}
+
+func isString(typ Type) bool {
+ t, ok := underlying(typ).(*Basic)
+ return ok && t.Info&IsString != 0
+}
+
+func isUntyped(typ Type) bool {
+ t, ok := underlying(typ).(*Basic)
+ return ok && t.Info&IsUntyped != 0
+}
+
+func isOrdered(typ Type) bool {
+ t, ok := underlying(typ).(*Basic)
+ return ok && t.Info&IsOrdered != 0
+}
+
+func isComparable(typ Type) bool {
+ switch t := underlying(typ).(type) {
+ case *Basic:
+ return t.Kind != Invalid
+ case *Pointer, *Chan, *Interface:
+ // assumes types are equal for pointers and channels
+ return true
+ case *Struct:
+ for _, f := range t.Fields {
+ if !isComparable(f.Type) {
+ return false
+ }
+ }
+ return true
+ case *Array:
+ return isComparable(t.Elt)
+ }
+ return false
+}
+
+// identical returns true if x and y are identical.
+func isIdentical(x, y Type) bool {
+ if x == y {
+ return true
+ }
+
+ switch x := x.(type) {
+ case *Basic:
+ // Basic types are singletons except for the rune and byte
+ // aliases, thus we cannot solely rely on the x == y check
+ // above.
+ if y, ok := y.(*Basic); ok {
+ return x.Kind == y.Kind
+ }
+
+ case *Array:
+ // Two array types are identical if they have identical element types
+ // and the same array length.
+ if y, ok := y.(*Array); ok {
+ return x.Len == y.Len && isIdentical(x.Elt, y.Elt)
+ }
+
+ case *Slice:
+ // Two slice types are identical if they have identical element types.
+ if y, ok := y.(*Slice); ok {
+ return isIdentical(x.Elt, y.Elt)
+ }
+
+ case *Struct:
+ // Two struct types are identical if they have the same sequence of fields,
+ // and if corresponding fields have the same names, and identical types,
+ // and identical tags. Two anonymous fields are considered to have the same
+ // name. Lower-case field names from different packages are always different.
+ if y, ok := y.(*Struct); ok {
+ // TODO(gri) handle structs from different packages
+ if len(x.Fields) == len(y.Fields) {
+ for i, f := range x.Fields {
+ g := y.Fields[i]
+ if f.Name != g.Name ||
+ !isIdentical(f.Type, g.Type) ||
+ f.Tag != g.Tag ||
+ f.IsAnonymous != g.IsAnonymous {
+ return false
+ }
+ }
+ return true
+ }
+ }
+
+ case *Pointer:
+ // Two pointer types are identical if they have identical base types.
+ if y, ok := y.(*Pointer); ok {
+ return isIdentical(x.Base, y.Base)
+ }
+
+ case *Signature:
+ // Two function types are identical if they have the same number of parameters
+ // and result values, corresponding parameter and result types are identical,
+ // and either both functions are variadic or neither is. Parameter and result
+ // names are not required to match.
+ if y, ok := y.(*Signature); ok {
+ return identicalTypes(x.Params, y.Params) &&
+ identicalTypes(x.Results, y.Results) &&
+ x.IsVariadic == y.IsVariadic
+ }
+
+ case *Interface:
+ // Two interface types are identical if they have the same set of methods with
+ // the same names and identical function types. Lower-case method names from
+ // different packages are always different. The order of the methods is irrelevant.
+ if y, ok := y.(*Interface); ok {
+ return identicalTypes(x.Methods, y.Methods) // methods are sorted
+ }
+
+ case *Map:
+ // Two map types are identical if they have identical key and value types.
+ if y, ok := y.(*Map); ok {
+ return isIdentical(x.Key, y.Key) && isIdentical(x.Elt, y.Elt)
+ }
+
+ case *Chan:
+ // Two channel types are identical if they have identical value types
+ // and the same direction.
+ if y, ok := y.(*Chan); ok {
+ return x.Dir == y.Dir && isIdentical(x.Elt, y.Elt)
+ }
+
+ case *NamedType:
+ // Two named types are identical if their type names originate
+ // in the same type declaration.
+ if y, ok := y.(*NamedType); ok {
+ return x.Obj == y.Obj
+ }
+ }
+
+ return false
+}
+
+// identicalTypes returns true if both lists a and b have the
+// same length and corresponding objects have identical types.
+func identicalTypes(a, b ObjList) bool {
+ if len(a) == len(b) {
+ for i, x := range a {
+ y := b[i]
+ if !isIdentical(x.Type.(Type), y.Type.(Type)) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
+
+// underlying returns the underlying type of typ.
+func underlying(typ Type) Type {
+ // Basic types are representing themselves directly even though they are named.
+ if typ, ok := typ.(*NamedType); ok {
+ return typ.Underlying // underlying types are never NamedTypes
+ }
+ return typ
+}
+
+// deref returns a pointer's base type; otherwise it returns typ.
+func deref(typ Type) Type {
+ if typ, ok := underlying(typ).(*Pointer); ok {
+ return typ.Base
+ }
+ return typ
+}
+
+// defaultType returns the default "typed" type for an "untyped" type;
+// it returns the argument typ for all other types.
+func defaultType(typ Type) Type {
+ if t, ok := typ.(*Basic); ok {
+ var k BasicKind
+ switch t.Kind {
+ case UntypedBool:
+ k = Bool
+ case UntypedRune:
+ k = Rune
+ case UntypedInt:
+ k = Int
+ case UntypedFloat:
+ k = Float64
+ case UntypedComplex:
+ k = Complex128
+ case UntypedString:
+ k = String
+ default:
+ unreachable()
+ }
+ typ = Typ[k]
+ }
+ return typ
+}
diff --git a/libgo/go/exp/types/staging/resolver_test.go b/libgo/go/exp/types/staging/resolver_test.go
new file mode 100644
index 00000000000..4e9aa0938d9
--- /dev/null
+++ b/libgo/go/exp/types/staging/resolver_test.go
@@ -0,0 +1,130 @@
+// 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 types
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/scanner"
+ "go/token"
+ "testing"
+)
+
+var sources = []string{
+ `package p
+ import "fmt"
+ import "math"
+ const pi = math.Pi
+ func sin(x float64) float64 {
+ return math.Sin(x)
+ }
+ var Println = fmt.Println
+ `,
+ `package p
+ import "fmt"
+ func f() string {
+ return fmt.Sprintf("%d", g())
+ }
+ `,
+ `package p
+ import . "go/parser"
+ func g() Mode { return ImportsOnly }`,
+}
+
+var pkgnames = []string{
+ "fmt",
+ "go/parser",
+ "math",
+}
+
+// ResolveQualifiedIdents resolves the selectors of qualified
+// identifiers by associating the correct ast.Object with them.
+// TODO(gri): Eventually, this functionality should be subsumed
+// by Check.
+//
+func ResolveQualifiedIdents(fset *token.FileSet, pkg *ast.Package) error {
+ var errors scanner.ErrorList
+
+ findObj := func(pkg *ast.Object, name *ast.Ident) *ast.Object {
+ scope := pkg.Data.(*ast.Scope)
+ obj := scope.Lookup(name.Name)
+ if obj == nil {
+ errors.Add(fset.Position(name.Pos()), fmt.Sprintf("no %s in package %s", name.Name, pkg.Name))
+ }
+ return obj
+ }
+
+ ast.Inspect(pkg, func(n ast.Node) bool {
+ if s, ok := n.(*ast.SelectorExpr); ok {
+ if x, ok := s.X.(*ast.Ident); ok && x.Obj != nil && x.Obj.Kind == ast.Pkg {
+ // find selector in respective package
+ s.Sel.Obj = findObj(x.Obj, s.Sel)
+ }
+ return false
+ }
+ return true
+ })
+
+ return errors.Err()
+}
+
+func TestResolveQualifiedIdents(t *testing.T) {
+ // parse package files
+ fset := token.NewFileSet()
+ files := make(map[string]*ast.File)
+ for i, src := range sources {
+ filename := fmt.Sprintf("file%d", i)
+ f, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
+ if err != nil {
+ t.Fatal(err)
+ }
+ files[filename] = f
+ }
+
+ // resolve package AST
+ pkg, err := ast.NewPackage(fset, files, GcImport, Universe)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // check that all packages were imported
+ for _, name := range pkgnames {
+ if pkg.Imports[name] == nil {
+ t.Errorf("package %s not imported", name)
+ }
+ }
+
+ // check that there are no top-level unresolved identifiers
+ for _, f := range pkg.Files {
+ for _, x := range f.Unresolved {
+ t.Errorf("%s: unresolved global identifier %s", fset.Position(x.Pos()), x.Name)
+ }
+ }
+
+ // resolve qualified identifiers
+ if err := ResolveQualifiedIdents(fset, pkg); err != nil {
+ t.Error(err)
+ }
+
+ // check that qualified identifiers are resolved
+ ast.Inspect(pkg, func(n ast.Node) bool {
+ if s, ok := n.(*ast.SelectorExpr); ok {
+ if x, ok := s.X.(*ast.Ident); ok {
+ if x.Obj == nil {
+ t.Errorf("%s: unresolved qualified identifier %s", fset.Position(x.Pos()), x.Name)
+ return false
+ }
+ if x.Obj.Kind == ast.Pkg && s.Sel != nil && s.Sel.Obj == nil {
+ t.Errorf("%s: unresolved selector %s", fset.Position(s.Sel.Pos()), s.Sel.Name)
+ return false
+ }
+ return false
+ }
+ return false
+ }
+ return true
+ })
+}
diff --git a/libgo/go/exp/types/staging/stmt.go b/libgo/go/exp/types/staging/stmt.go
new file mode 100644
index 00000000000..be5caa1e364
--- /dev/null
+++ b/libgo/go/exp/types/staging/stmt.go
@@ -0,0 +1,473 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements typechecking of statements.
+
+package types
+
+import (
+ "go/ast"
+ "go/token"
+)
+
+func (check *checker) assignOperand(z, x *operand) {
+ if t, ok := x.typ.(*tuple); ok {
+ // TODO(gri) elsewhere we use "assignment count mismatch" (consolidate)
+ check.errorf(x.pos(), "%d-valued expression %s used as single value", len(t.list), x)
+ x.mode = invalid
+ return
+ }
+
+ check.convertUntyped(x, z.typ)
+
+ if !x.isAssignable(z.typ) {
+ check.errorf(x.pos(), "cannot assign %s to %s", x, z)
+ x.mode = invalid
+ }
+}
+
+// assignment typechecks a single assignment of the form lhs := x. If decl is set,
+// the lhs operand must be an identifier. If its type is not set, it is deduced
+// from the type or value of x.
+//
+func (check *checker) assignment(lhs ast.Expr, x *operand, decl bool) {
+ if decl {
+ ident, ok := lhs.(*ast.Ident)
+ if !ok {
+ check.errorf(lhs.Pos(), "cannot declare %s", lhs)
+ return
+ }
+
+ obj := ident.Obj
+ if obj.Type == nil {
+ // determine type from rhs expression
+ var typ Type = Typ[Invalid]
+ if x.mode != invalid {
+ typ = x.typ
+ // determine the default type for variables
+ if obj.Kind == ast.Var && isUntyped(typ) {
+ typ = defaultType(typ)
+ }
+ }
+ obj.Type = typ
+ }
+
+ var z operand
+ switch obj.Kind {
+ case ast.Con:
+ z.mode = constant
+ case ast.Var:
+ z.mode = variable
+ default:
+ unreachable()
+ }
+ z.expr = ident
+ z.typ = obj.Type.(Type)
+
+ check.assignOperand(&z, x)
+
+ // for constants, set the constant value
+ if obj.Kind == ast.Con {
+ assert(obj.Data == nil)
+ if x.mode != invalid && x.mode != constant {
+ check.errorf(x.pos(), "%s is not constant", x) // TODO(gri) better error position
+ x.mode = invalid
+ }
+ if x.mode == constant {
+ obj.Data = x.val
+ } else {
+ // set the constant to the type's zero value to reduce spurious errors
+ // TODO(gri) factor this out - useful elsewhere
+ switch typ := underlying(obj.Type.(Type)); {
+ case typ == Typ[Invalid]:
+ // ignore
+ case isBoolean(typ):
+ obj.Data = false
+ case isNumeric(typ):
+ obj.Data = int64(0)
+ case isString(typ):
+ obj.Data = ""
+ default:
+ check.dump("%s: typ(%s) = %s", obj.Pos(), obj.Name, typ)
+ unreachable()
+ }
+ }
+ }
+
+ return
+ }
+
+ // regular assignment
+ var z operand
+ check.expr(&z, lhs, nil, -1)
+ check.assignOperand(&z, x)
+ if x.mode != invalid && z.mode == constant {
+ check.errorf(x.pos(), "cannot assign %s to %s", x, z)
+ }
+}
+
+func (check *checker) assign1to1(lhs, rhs ast.Expr, decl bool, iota int) {
+ ident, _ := lhs.(*ast.Ident)
+
+ if ident != nil && ident.Name == "_" {
+ // anything can be assigned to a blank identifier - check rhs only
+ var x operand
+ check.expr(&x, rhs, nil, iota)
+ return
+ }
+
+ if !decl {
+ // regular assignment - start with lhs[0] to obtain a type hint
+ var z operand
+ check.expr(&z, lhs, nil, -1)
+ if z.mode == invalid {
+ z.typ = nil // so we can proceed with rhs
+ }
+
+ var x operand
+ check.expr(&x, rhs, z.typ, -1)
+ if x.mode == invalid {
+ return
+ }
+
+ check.assignOperand(&z, &x)
+ return
+ }
+
+ // declaration - rhs may or may not be typed yet
+ if ident == nil {
+ check.errorf(lhs.Pos(), "cannot declare %s", lhs)
+ return
+ }
+
+ obj := ident.Obj
+ var typ Type
+ if obj.Type != nil {
+ typ = obj.Type.(Type)
+ }
+
+ var x operand
+ check.expr(&x, rhs, typ, iota)
+ if x.mode == invalid {
+ return
+ }
+
+ if typ == nil {
+ // determine lhs type from rhs expression;
+ // for variables, convert untyped types to
+ // default types
+ typ = x.typ
+ if obj.Kind == ast.Var && isUntyped(typ) {
+ // TODO(gri) factor this out
+ var k BasicKind
+ switch typ.(*Basic).Kind {
+ case UntypedBool:
+ k = Bool
+ case UntypedRune:
+ k = Rune
+ case UntypedInt:
+ k = Int
+ case UntypedFloat:
+ k = Float64
+ case UntypedComplex:
+ k = Complex128
+ case UntypedString:
+ k = String
+ default:
+ unreachable()
+ }
+ typ = Typ[k]
+ }
+ obj.Type = typ
+ }
+
+ var z operand
+ switch obj.Kind {
+ case ast.Con:
+ z.mode = constant
+ case ast.Var:
+ z.mode = variable
+ default:
+ unreachable()
+ }
+ z.expr = ident
+ z.typ = typ
+
+ check.assignOperand(&z, &x)
+
+ // for constants, set their value
+ if obj.Kind == ast.Con {
+ assert(obj.Data == nil)
+ if x.mode != constant {
+ check.errorf(x.pos(), "%s is not constant", x)
+ // set the constant to the type's zero value to reduce spurious errors
+ // TODO(gri) factor this out - useful elsewhere
+ switch typ := underlying(typ); {
+ case typ == Typ[Invalid]:
+ // ignore
+ case isBoolean(typ):
+ obj.Data = false
+ case isNumeric(typ):
+ obj.Data = int64(0)
+ case isString(typ):
+ obj.Data = ""
+ default:
+ unreachable()
+ }
+ return
+ }
+ obj.Data = x.val
+ }
+}
+
+// assignNtoM typechecks a general assignment. If decl is set, the lhs operands
+// must be identifiers. If their types are not set, they are deduced from the
+// types of the corresponding rhs expressions. iota >= 0 indicates that the
+// "assignment" is part of a constant declaration.
+// Precondition: len(lhs) > 0 .
+//
+func (check *checker) assignNtoM(lhs, rhs []ast.Expr, decl bool, iota int) {
+ assert(len(lhs) >= 1)
+
+ if len(lhs) == len(rhs) {
+ for i, e := range rhs {
+ check.assign1to1(lhs[i], e, decl, iota)
+ }
+ return
+ }
+
+ if len(rhs) == 1 {
+ // len(lhs) >= 2; therefore a correct rhs expression
+ // cannot be a shift and we don't need a type hint -
+ // ok to evaluate rhs first
+ var x operand
+ check.expr(&x, rhs[0], nil, iota)
+ if x.mode == invalid {
+ return
+ }
+
+ if t, ok := x.typ.(*tuple); ok && len(lhs) == len(t.list) {
+ // function result
+ x.mode = value
+ for i, typ := range t.list {
+ x.expr = nil // TODO(gri) should do better here
+ x.typ = typ
+ check.assignment(lhs[i], &x, decl)
+ }
+ return
+ }
+
+ if x.mode == valueok && len(lhs) == 2 {
+ // comma-ok expression
+ x.mode = value
+ check.assignment(lhs[0], &x, decl)
+
+ x.mode = value
+ x.typ = Typ[UntypedBool]
+ check.assignment(lhs[1], &x, decl)
+ return
+ }
+ }
+
+ check.errorf(lhs[0].Pos(), "assignment count mismatch: %d = %d", len(lhs), len(rhs))
+
+ // avoid checking the same declaration over and over
+ // again for each lhs identifier that has no type yet
+ if iota >= 0 {
+ // declaration
+ for _, e := range lhs {
+ if ident, ok := e.(*ast.Ident); ok {
+ ident.Obj.Type = Typ[Invalid]
+ }
+ }
+ }
+}
+
+func (check *checker) optionalStmt(s ast.Stmt) {
+ if s != nil {
+ check.stmt(s)
+ }
+}
+
+func (check *checker) stmtList(list []ast.Stmt) {
+ for _, s := range list {
+ check.stmt(s)
+ }
+}
+
+// stmt typechecks statement s.
+func (check *checker) stmt(s ast.Stmt) {
+ switch s := s.(type) {
+ case *ast.BadStmt, *ast.EmptyStmt:
+ // ignore
+
+ case *ast.DeclStmt:
+ unimplemented()
+
+ case *ast.LabeledStmt:
+ unimplemented()
+
+ case *ast.ExprStmt:
+ var x operand
+ used := false
+ switch e := unparen(s.X).(type) {
+ case *ast.CallExpr:
+ // function calls are permitted
+ used = true
+ // but some builtins are excluded
+ check.expr(&x, e.Fun, nil, -1)
+ if x.mode != invalid {
+ if b, ok := x.typ.(*builtin); ok && !b.isStatement {
+ used = false
+ }
+ }
+ case *ast.UnaryExpr:
+ // receive operations are permitted
+ if e.Op == token.ARROW {
+ used = true
+ }
+ }
+ if !used {
+ check.errorf(s.Pos(), "%s not used", s.X)
+ // ok to continue
+ }
+ check.exprOrType(&x, s.X, nil, -1, false)
+ if x.mode == typexpr {
+ check.errorf(x.pos(), "%s is not an expression", x)
+ }
+
+ case *ast.SendStmt:
+ var ch, x operand
+ check.expr(&ch, s.Chan, nil, -1)
+ check.expr(&x, s.Value, nil, -1)
+ if ch.mode == invalid || x.mode == invalid {
+ return
+ }
+ if tch, ok := underlying(ch.typ).(*Chan); !ok || tch.Dir&ast.SEND == 0 || !x.isAssignable(tch.Elt) {
+ check.invalidOp(ch.pos(), "cannot send %s to channel %s", &x, &ch)
+ }
+
+ case *ast.IncDecStmt:
+ unimplemented()
+
+ case *ast.AssignStmt:
+ switch s.Tok {
+ case token.ASSIGN, token.DEFINE:
+ if len(s.Lhs) == 0 {
+ check.invalidAST(s.Pos(), "missing lhs in assignment")
+ return
+ }
+ check.assignNtoM(s.Lhs, s.Rhs, s.Tok == token.DEFINE, -1)
+ default:
+ // assignment operations
+ if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
+ check.errorf(s.TokPos, "assignment operation %s requires single-valued expressions", s.Tok)
+ return
+ }
+ // TODO(gri) make this conversion more efficient
+ var op token.Token
+ switch s.Tok {
+ case token.ADD_ASSIGN:
+ op = token.ADD
+ case token.SUB_ASSIGN:
+ op = token.SUB
+ case token.MUL_ASSIGN:
+ op = token.MUL
+ case token.QUO_ASSIGN:
+ op = token.QUO
+ case token.REM_ASSIGN:
+ op = token.REM
+ case token.AND_ASSIGN:
+ op = token.AND
+ case token.OR_ASSIGN:
+ op = token.OR
+ case token.XOR_ASSIGN:
+ op = token.XOR
+ case token.SHL_ASSIGN:
+ op = token.SHL
+ case token.SHR_ASSIGN:
+ op = token.SHR
+ case token.AND_NOT_ASSIGN:
+ op = token.AND_NOT
+ }
+ var x, y operand
+ check.expr(&x, s.Lhs[0], nil, -1)
+ check.expr(&y, s.Rhs[0], nil, -1)
+ check.binary(&x, &y, op, nil)
+ check.assignment(s.Lhs[0], &x, false)
+ }
+
+ case *ast.GoStmt:
+ unimplemented()
+
+ case *ast.DeferStmt:
+ unimplemented()
+
+ case *ast.ReturnStmt:
+ unimplemented()
+
+ case *ast.BranchStmt:
+ unimplemented()
+
+ case *ast.BlockStmt:
+ check.stmtList(s.List)
+
+ case *ast.IfStmt:
+ check.optionalStmt(s.Init)
+ var x operand
+ check.expr(&x, s.Cond, nil, -1)
+ if !isBoolean(x.typ) {
+ check.errorf(s.Cond.Pos(), "non-boolean condition in if statement")
+ }
+ check.stmt(s.Body)
+ check.optionalStmt(s.Else)
+
+ case *ast.SwitchStmt:
+ check.optionalStmt(s.Init)
+ var x operand
+ if s.Tag != nil {
+ check.expr(&x, s.Tag, nil, -1)
+ } else {
+ x.mode = constant
+ x.typ = Typ[UntypedBool]
+ x.val = true
+ }
+ for _, s := range s.Body.List {
+ if clause, ok := s.(*ast.CaseClause); ok {
+ for _, expr := range clause.List {
+ var y operand
+ check.expr(&y, expr, nil, -1)
+ // TODO(gri) x and y must be comparable
+ }
+ check.stmtList(clause.Body)
+ } else {
+ check.errorf(s.Pos(), "invalid AST: case clause expected")
+ }
+ }
+
+ case *ast.TypeSwitchStmt:
+ unimplemented()
+
+ case *ast.SelectStmt:
+ unimplemented()
+
+ case *ast.ForStmt:
+ check.optionalStmt(s.Init)
+ if s.Cond != nil {
+ var x operand
+ check.expr(&x, s.Cond, nil, -1)
+ if !isBoolean(x.typ) {
+ check.errorf(s.Cond.Pos(), "non-boolean condition in for statement")
+ }
+ }
+ check.optionalStmt(s.Post)
+ check.stmt(s.Body)
+
+ case *ast.RangeStmt:
+ unimplemented()
+
+ default:
+ check.errorf(s.Pos(), "invalid statement")
+ }
+}
diff --git a/libgo/go/exp/types/staging/testdata/builtins.src b/libgo/go/exp/types/staging/testdata/builtins.src
new file mode 100644
index 00000000000..c641537e93c
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/builtins.src
@@ -0,0 +1,258 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// builtin calls
+
+package builtins
+
+import "unsafe"
+
+func _append() {
+ var x int
+ var s []byte
+ _0 := append /* ERROR "argument" */ ()
+ _1 := append("foo" /* ERROR "not a typed slice" */)
+ _2 := append(nil /* ERROR "not a typed slice" */, s)
+ _3 := append(x /* ERROR "not a typed slice" */, s)
+ _4 := append(s)
+ append /* ERROR "not used" */ (s)
+}
+
+func _cap() {
+ var a [10]bool
+ var p *[20]int
+ var s []int
+ var c chan string
+ _0 := cap /* ERROR "argument" */ ()
+ _1 := cap /* ERROR "argument" */ (1, 2)
+ _2 := cap(42 /* ERROR "invalid" */)
+ const _3 = cap(a)
+ assert(_3 == 10)
+ const _4 = cap(p)
+ assert(_4 == 20)
+ _5 := cap(c)
+ cap /* ERROR "not used" */ (c)
+}
+
+func _close() {
+ var c chan int
+ var r <-chan int
+ close /* ERROR "argument" */ ()
+ close /* ERROR "argument" */ (1, 2)
+ close(42 /* ERROR "not a channel" */)
+ close(r /* ERROR "receive-only channel" */)
+ close(c)
+}
+
+func _complex() {
+ _0 := complex /* ERROR "argument" */ ()
+ _1 := complex /* ERROR "argument" */ (1)
+ _2 := complex(1, 2)
+ // TODO(gri) add tests checking types
+ complex /* ERROR "not used" */ (1, 2)
+}
+
+func _delete() {
+ var m map[string]int
+ var s string
+ delete /* ERROR "argument" */ ()
+ delete /* ERROR "argument" */ (1)
+ delete /* ERROR "argument" */ (1, 2, 3)
+ delete(m, 0 /* ERROR "not assignable" */)
+ delete(m, s)
+}
+
+func _imag() {
+ var f32 float32
+ var f64 float64
+ var c64 complex64
+ var c128 complex128
+ _0 := imag /* ERROR "argument" */ ()
+ _1 := imag /* ERROR "argument" */ (1, 2)
+ _2 := imag(10 /* ERROR "must be a complex number" */)
+ _3 := imag(2.7182818 /* ERROR "must be a complex number" */)
+ _4 := imag("foo" /* ERROR "must be a complex number" */)
+ const _5 = imag(1 + 2i)
+ assert(_5 == 2)
+ f32 = _5
+ f64 = _5
+ const _6 = imag(0i)
+ assert(_6 == 0)
+ f32 = imag(c64)
+ f64 = imag(c128)
+ f32 = imag /* ERROR "cannot assign" */ (c128)
+ f64 = imag /* ERROR "cannot assign" */ (c64)
+ imag /* ERROR "not used" */ (c64)
+}
+
+func _len() {
+ const c = "foobar"
+ var a [10]bool
+ var p *[20]int
+ var s []int
+ var m map[string]complex128
+ _0 := len /* ERROR "argument" */ ()
+ _1 := len /* ERROR "argument" */ (1, 2)
+ _2 := len(42 /* ERROR "invalid" */)
+ const _3 = len(c)
+ assert(_3 == 6)
+ const _4 = len(a)
+ assert(_4 == 10)
+ const _5 = len(p)
+ assert(_5 == 20)
+ _6 := len(m)
+ len /* ERROR "not used" */ (c)
+
+ // esoteric case
+ var t string
+ var hash map[interface{}][]*[10]int
+ const n = len /* ERROR "not constant" */ (hash[recover()][len(t)])
+ assert /* ERROR "failed" */ (n == 10)
+ var ch <-chan int
+ const nn = len /* ERROR "not constant" */ (hash[<-ch][len(t)])
+ _7 := nn // TODO(gri) remove this once unused constants get type-checked
+}
+
+func _make() {
+ n := 0
+
+ _0 := make /* ERROR "argument" */ ()
+ _1 := make(1 /* ERROR "not a type" */)
+ _2 := make(int /* ERROR "cannot make" */)
+
+ // slices
+ _3 := make/* ERROR "arguments" */ ([]int)
+ _4 := make/* ERROR "arguments" */ ([]int, 2, 3, 4)
+ _5 := make([]int, int /* ERROR "not an expression" */)
+ _6 := make([]int, 10, float32 /* ERROR "not an expression" */)
+ _7 := make([]int, "foo" /* ERROR "must be an integer" */)
+ _8 := make([]int, 10, 2.3 /* ERROR "must be an integer" */)
+ _9 := make([]int, 5, 10.0)
+ _10 := make([]int, 0i)
+ _11 := make([]int, -1, 1<<100) // out-of-range constants lead to run-time errors
+
+ // maps
+ _12 := make /* ERROR "arguments" */ (map[int]string, 10, 20)
+ _13 := make(map[int]float32, int /* ERROR "not an expression" */)
+ _14 := make(map[int]float32, "foo" /* ERROR "must be an integer" */)
+ _15 := make(map[int]float32, 10)
+ _16 := make(map[int]float32, n)
+ _17 := make(map[int]float32, int64(n))
+
+ // channels
+ _22 := make /* ERROR "arguments" */ (chan int, 10, 20)
+ _23 := make(chan int, int /* ERROR "not an expression" */)
+ _24 := make(chan<- int, "foo" /* ERROR "must be an integer" */)
+ _25 := make(<-chan float64, 10)
+ _26 := make(chan chan int, n)
+ _27 := make(chan string, int64(n))
+
+ make /* ERROR "not used" */ ([]int, 10)
+}
+
+func _new() {
+ _0 := new /* ERROR "argument" */ ()
+ _1 := new /* ERROR "argument" */ (1, 2)
+ _3 := new("foo" /* ERROR "not a type" */)
+ _4 := new(float64)
+ _5 := new(struct{ x, y int })
+ _6 := new(*float64)
+ _7 := *_4 == **_6
+ new /* ERROR "not used" */ (int)
+}
+
+func _real() {
+ var f32 float32
+ var f64 float64
+ var c64 complex64
+ var c128 complex128
+ _0 := real /* ERROR "argument" */ ()
+ _1 := real /* ERROR "argument" */ (1, 2)
+ _2 := real(10 /* ERROR "must be a complex number" */)
+ _3 := real(2.7182818 /* ERROR "must be a complex number" */)
+ _4 := real("foo" /* ERROR "must be a complex number" */)
+ const _5 = real(1 + 2i)
+ assert(_5 == 1)
+ f32 = _5
+ f64 = _5
+ const _6 = real(0i)
+ assert(_6 == 0)
+ f32 = real(c64)
+ f64 = real(c128)
+ f32 = real /* ERROR "cannot assign" */ (c128)
+ f64 = real /* ERROR "cannot assign" */ (c64)
+ real /* ERROR "not used" */ (c64)
+}
+
+func _recover() {
+ _0 := recover()
+ _1 := recover /* ERROR "argument" */ (10)
+ recover()
+}
+
+func _Alignof() {
+ var x int
+ _0 := unsafe /* ERROR "argument" */ .Alignof()
+ _1 := unsafe /* ERROR "argument" */ .Alignof(1, 2)
+ _3 := unsafe.Alignof(int /* ERROR "not an expression" */)
+ _4 := unsafe.Alignof(42)
+ _5 := unsafe.Alignof(new(struct{}))
+ unsafe /* ERROR "not used" */ .Alignof(x)
+}
+
+func _Offsetof() {
+ var x struct{ f int }
+ _0 := unsafe /* ERROR "argument" */ .Offsetof()
+ _1 := unsafe /* ERROR "argument" */ .Offsetof(1, 2)
+ _2 := unsafe.Offsetof(int /* ERROR "not an expression" */)
+ _3 := unsafe.Offsetof(x /* ERROR "not a selector" */)
+ _4 := unsafe.Offsetof(x.f)
+ _5 := unsafe.Offsetof((x.f))
+ _6 := unsafe.Offsetof((((((((x))).f)))))
+ unsafe /* ERROR "not used" */ .Offsetof(x.f)
+}
+
+func _Sizeof() {
+ var x int
+ _0 := unsafe /* ERROR "argument" */ .Sizeof()
+ _1 := unsafe /* ERROR "argument" */ .Sizeof(1, 2)
+ _2 := unsafe.Sizeof(int /* ERROR "not an expression" */)
+ _3 := unsafe.Sizeof(42)
+ _4 := unsafe.Sizeof(new(complex128))
+ unsafe /* ERROR "not used" */ .Sizeof(x)
+
+ // basic types have size guarantees
+ assert(unsafe.Sizeof(byte(0)) == 1)
+ assert(unsafe.Sizeof(uint8(0)) == 1)
+ assert(unsafe.Sizeof(int8(0)) == 1)
+ assert(unsafe.Sizeof(uint16(0)) == 2)
+ assert(unsafe.Sizeof(int16(0)) == 2)
+ assert(unsafe.Sizeof(uint32(0)) == 4)
+ assert(unsafe.Sizeof(int32(0)) == 4)
+ assert(unsafe.Sizeof(float32(0)) == 4)
+ assert(unsafe.Sizeof(uint64(0)) == 8)
+ assert(unsafe.Sizeof(int64(0)) == 8)
+ assert(unsafe.Sizeof(float64(0)) == 8)
+ assert(unsafe.Sizeof(complex64(0)) == 8)
+ assert(unsafe.Sizeof(complex128(0)) == 16)
+}
+
+// self-testing only
+func _assert() {
+ var x int
+ assert /* ERROR "argument" */ ()
+ assert /* ERROR "argument" */ (1, 2)
+ assert("foo" /* ERROR "boolean constant" */ )
+ assert(x /* ERROR "boolean constant" */)
+ assert(true)
+ assert /* ERROR "failed" */ (false)
+}
+
+// self-testing only
+func _trace() {
+ // Uncomment the code below to test trace - will produce console output
+ // _0 := trace /* ERROR "no value" */ ()
+ // _1 := trace(1)
+ // _2 := trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar")
+}
diff --git a/libgo/go/exp/types/staging/testdata/const0.src b/libgo/go/exp/types/staging/testdata/const0.src
new file mode 100644
index 00000000000..4599397c7a5
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/const0.src
@@ -0,0 +1,209 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// constant declarations
+
+package const0
+
+// constants declarations must be initialized by constants
+var x = 0
+const c0 = x /* ERROR "not constant" */
+
+// untyped constants
+const (
+ // boolean values
+ ub0 = false
+ ub1 = true
+ ub2 = 2 < 1
+ ub3 = ui1 == uf1
+ ub4 = true /* ERROR "cannot convert" */ == 0
+
+ // integer values
+ ui0 = 0
+ ui1 = 1
+ ui2 = 42
+ ui3 = 3141592653589793238462643383279502884197169399375105820974944592307816406286
+ ui4 = -10
+
+ ui5 = ui0 + ui1
+ ui6 = ui1 - ui1
+ ui7 = ui2 * ui1
+ ui8 = ui3 / ui3
+ ui9 = ui3 % ui3
+
+ ui10 = 1 / 0 /* ERROR "division by zero" */
+ ui11 = ui1 / 0 /* ERROR "division by zero" */
+ ui12 = ui3 / ui0 /* ERROR "division by zero" */
+ ui13 = 1 % 0 /* ERROR "division by zero" */
+ ui14 = ui1 % 0 /* ERROR "division by zero" */
+ ui15 = ui3 % ui0 /* ERROR "division by zero" */
+
+ ui16 = ui2 & ui3
+ ui17 = ui2 | ui3
+ ui18 = ui2 ^ ui3
+
+ // floating point values
+ uf0 = 0.
+ uf1 = 1.
+ uf2 = 4.2e1
+ uf3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
+ uf4 = 1e-1
+
+ uf5 = uf0 + uf1
+ uf6 = uf1 - uf1
+ uf7 = uf2 * uf1
+ uf8 = uf3 / uf3
+ uf9 = uf3 /* ERROR "not defined" */ % uf3
+
+ uf10 = 1 / 0 /* ERROR "division by zero" */
+ uf11 = uf1 / 0 /* ERROR "division by zero" */
+ uf12 = uf3 / uf0 /* ERROR "division by zero" */
+
+ uf16 = uf2 /* ERROR "not defined" */ & uf3
+ uf17 = uf2 /* ERROR "not defined" */ | uf3
+ uf18 = uf2 /* ERROR "not defined" */ ^ uf3
+
+ // complex values
+ uc0 = 0.i
+ uc1 = 1.i
+ uc2 = 4.2e1i
+ uc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i
+ uc4 = 1e-1i
+
+ uc5 = uc0 + uc1
+ uc6 = uc1 - uc1
+ uc7 = uc2 * uc1
+ uc8 = uc3 / uc3
+ uc9 = uc3 /* ERROR "not defined" */ % uc3
+
+ uc10 = 1 / 0 /* ERROR "division by zero" */
+ uc11 = uc1 / 0 /* ERROR "division by zero" */
+ uc12 = uc3 / uc0 /* ERROR "division by zero" */
+
+ uc16 = uc2 /* ERROR "not defined" */ & uc3
+ uc17 = uc2 /* ERROR "not defined" */ | uc3
+ uc18 = uc2 /* ERROR "not defined" */ ^ uc3
+)
+
+type (
+ mybool bool
+ myint int
+ myfloat float64
+ mycomplex complex128
+)
+
+// typed constants
+const (
+ // boolean values
+ tb0 bool = false
+ tb1 bool = true
+ tb2 mybool = 2 < 1
+ tb3 mybool = ti1 /* ERROR "cannot compare" */ == tf1
+
+ // integer values
+ ti0 int8 = ui0
+ ti1 int32 = ui1
+ ti2 int64 = ui2
+ ti3 myint = ui3 /* ERROR "overflows" */
+ ti4 myint = ui4
+
+ ti5 = ti0 /* ERROR "mismatched types" */ + ti1
+ ti6 = ti1 - ti1
+ ti7 = ti2 /* ERROR "mismatched types" */ * ti1
+ //ti8 = ti3 / ti3 // TODO(gri) enable this
+ //ti9 = ti3 % ti3 // TODO(gri) enable this
+
+ ti10 = 1 / 0 /* ERROR "division by zero" */
+ ti11 = ti1 / 0 /* ERROR "division by zero" */
+ ti12 = ti3 /* ERROR "mismatched types" */ / ti0
+ ti13 = 1 % 0 /* ERROR "division by zero" */
+ ti14 = ti1 % 0 /* ERROR "division by zero" */
+ ti15 = ti3 /* ERROR "mismatched types" */ % ti0
+
+ ti16 = ti2 /* ERROR "mismatched types" */ & ti3
+ ti17 = ti2 /* ERROR "mismatched types" */ | ti4
+ ti18 = ti2 ^ ti5 // no mismatched types error because the type of ti5 is unknown
+
+ // floating point values
+ tf0 float32 = 0.
+ tf1 float32 = 1.
+ tf2 float64 = 4.2e1
+ tf3 myfloat = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
+ tf4 myfloat = 1e-1
+
+ tf5 = tf0 + tf1
+ tf6 = tf1 - tf1
+ tf7 = tf2 /* ERROR "mismatched types" */ * tf1
+ // tf8 = tf3 / tf3 // TODO(gri) enable this
+ tf9 = tf3 /* ERROR "not defined" */ % tf3
+
+ tf10 = 1 / 0 /* ERROR "division by zero" */
+ tf11 = tf1 / 0 /* ERROR "division by zero" */
+ tf12 = tf3 /* ERROR "mismatched types" */ / tf0
+
+ tf16 = tf2 /* ERROR "mismatched types" */ & tf3
+ tf17 = tf2 /* ERROR "mismatched types" */ | tf3
+ tf18 = tf2 /* ERROR "mismatched types" */ ^ tf3
+
+ // complex values
+ tc0 = 0.i
+ tc1 = 1.i
+ tc2 = 4.2e1i
+ tc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i
+ tc4 = 1e-1i
+
+ tc5 = tc0 + tc1
+ tc6 = tc1 - tc1
+ tc7 = tc2 * tc1
+ tc8 = tc3 / tc3
+ tc9 = tc3 /* ERROR "not defined" */ % tc3
+
+ tc10 = 1 / 0 /* ERROR "division by zero" */
+ tc11 = tc1 / 0 /* ERROR "division by zero" */
+ tc12 = tc3 / tc0 /* ERROR "division by zero" */
+
+ tc16 = tc2 /* ERROR "not defined" */ & tc3
+ tc17 = tc2 /* ERROR "not defined" */ | tc3
+ tc18 = tc2 /* ERROR "not defined" */ ^ tc3
+)
+
+// initialization cycles
+const (
+ a /* ERROR "cycle" */ = a
+ b /* ERROR "cycle" */ , c /* ERROR "cycle" */, d, e = e, d, c, b // TODO(gri) should only have one cycle error
+ f float64 = d
+)
+
+// multiple initialization
+const (
+ a1, a2, a3 = 7, 3.1415926, "foo"
+ b1, b2, b3 = b3, b1, 42
+ _p0 = assert(a1 == 7)
+ _p1 = assert(a2 == 3.1415926)
+ _p2 = assert(a3 == "foo")
+ _p3 = assert(b1 == 42)
+ _p4 = assert(b2 == 42)
+ _p5 = assert(b3 == 42)
+)
+
+// iota
+const (
+ iota0 = iota
+ iota1 = iota
+ iota2 = iota*2
+ _a0 = assert(iota0 == 0)
+ _a1 = assert(iota1 == 1)
+ _a2 = assert(iota2 == 4)
+ iota6 = iota*3
+
+ iota7
+ iota8
+ _a3 = assert(iota7 == 21)
+ _a4 = assert(iota8 == 24)
+)
+
+const (
+ _b0 = iota
+ _b1 = assert(iota + iota2 == 5)
+) \ No newline at end of file
diff --git a/libgo/go/exp/types/staging/testdata/conversions.src b/libgo/go/exp/types/staging/testdata/conversions.src
new file mode 100644
index 00000000000..1b1518366f3
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/conversions.src
@@ -0,0 +1,18 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// conversions
+
+package conversions
+
+// argument count
+var (
+ _v0 = int /* ERROR "one argument" */ ()
+ _v1 = int /* ERROR "one argument" */ (1, 2)
+)
+
+//
+var (
+ _v2 = int8(0)
+) \ No newline at end of file
diff --git a/libgo/go/exp/types/staging/testdata/decls0.src b/libgo/go/exp/types/staging/testdata/decls0.src
new file mode 100644
index 00000000000..e8ae53b2208
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/decls0.src
@@ -0,0 +1,168 @@
+// 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.
+
+// type declarations
+
+package decls0
+
+import (
+ "unsafe"
+ // we can have multiple blank imports (was bug)
+ _ "math"
+ _ "net/rpc"
+)
+
+const pi = 3.1415
+
+type (
+ N undeclared /* ERROR "undeclared" */ /* ERROR "not a type" */
+ B bool
+ I int32
+ A [10]P
+ T struct {
+ x, y P
+ }
+ P *T
+ R (*R)
+ F func(A) I
+ Y interface {
+ f(A) I
+ }
+ S [](((P)))
+ M map[I]F
+ C chan<- I
+
+ // blank types must be typechecked
+ _ pi /* ERROR "not a type" */
+ _ struct{}
+ _ struct{ pi /* ERROR "not a type" */ }
+)
+
+
+type (
+ p1 pi /* ERROR "no field or method foo" */ /* ERROR "not a type" */ .foo
+ p2 unsafe.Pointer
+)
+
+
+type (
+ Pi pi /* ERROR "not a type" */
+
+ a /* ERROR "illegal cycle" */ a
+ a /* ERROR "redeclared" */ int
+
+ // where the cycle error appears depends on the
+ // order in which declarations are processed
+ // (which depends on the order in which a map
+ // is iterated through)
+ b /* ERROR "illegal cycle" */ c
+ c d
+ d e
+ e b
+
+ t *t
+
+ U V
+ V *W
+ W U
+
+ P1 *S2
+ P2 P1
+
+ S0 struct {
+ }
+ S1 struct {
+ a, b, c int
+ u, v, a /* ERROR "redeclared" */ float32
+ }
+ S2 struct {
+ U // anonymous field
+ // TODO(gri) recognize double-declaration below
+ // U /* ERROR "redeclared" */ int
+ }
+ S3 struct {
+ x S2
+ }
+ S4/* ERROR "illegal cycle" */ struct {
+ S4
+ }
+ S5 /* ERROR "illegal cycle" */ struct {
+ S6
+ }
+ S6 struct {
+ field S7
+ }
+ S7 struct {
+ S5
+ }
+
+ L1 []L1
+ L2 []int
+
+ A1 [10.0]int
+ A2 /* ERROR "illegal cycle" */ [10]A2
+ A3 /* ERROR "illegal cycle" */ [10]struct {
+ x A4
+ }
+ A4 [10]A3
+
+ F1 func()
+ F2 func(x, y, z float32)
+ F3 func(x, y, x /* ERROR "redeclared" */ float32)
+ F4 func() (x, y, x /* ERROR "redeclared" */ float32)
+ F5 func(x int) (x /* ERROR "redeclared" */ float32)
+ F6 func(x ...int)
+
+ I1 interface{}
+ I2 interface {
+ m1()
+ }
+ I3 interface {
+ m1()
+ m1 /* ERROR "redeclared" */ ()
+ }
+ I4 interface {
+ m1(x, y, x /* ERROR "redeclared" */ float32)
+ m2() (x, y, x /* ERROR "redeclared" */ float32)
+ m3(x int) (x /* ERROR "redeclared" */ float32)
+ }
+ I5 interface {
+ m1(I5)
+ }
+ I6 interface {
+ S0 /* ERROR "non-interface" */
+ }
+ I7 interface {
+ I1
+ I1
+ }
+ I8 /* ERROR "illegal cycle" */ interface {
+ I8
+ }
+ // Use I09 (rather than I9) because it appears lexically before
+ // I10 so that we get the illegal cycle here rather then in the
+ // declaration of I10. If the implementation sorts by position
+ // rather than name, the error message will still be here.
+ I09 /* ERROR "illegal cycle" */ interface {
+ I10
+ }
+ I10 interface {
+ I11
+ }
+ I11 interface {
+ I09
+ }
+
+ C1 chan int
+ C2 <-chan int
+ C3 chan<- C3
+ C4 chan C5
+ C5 chan C6
+ C6 chan C4
+
+ M1 map[Last]string
+ M2 map[string]M2
+
+ Last int
+)
diff --git a/libgo/go/exp/types/staging/testdata/decls1.src b/libgo/go/exp/types/staging/testdata/decls1.src
new file mode 100644
index 00000000000..32859fc0ee5
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/decls1.src
@@ -0,0 +1,123 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// variable declarations
+
+package decls1
+
+import (
+ "math"
+)
+
+// Global variables without initialization
+var (
+ a, b bool
+ c byte
+ d uint8
+ r rune
+ i int
+ j, k, l int
+ x, y float32
+ xx, yy float64
+ u, v complex64
+ uu, vv complex128
+ s, t string
+ array []byte
+ iface interface{}
+
+ blank _ /* ERROR "cannot use _" */ /* ERROR "not a type" */
+)
+
+// Global variables with initialization
+var (
+ s1 = i + j
+ s2 = i /* ERROR "mismatched types" */ + x
+ s3 = c + d
+ s4 = s + t
+ s5 = s /* ERROR "invalid operation" */ / t
+ s6 = array[t1]
+ s7 = array[x /* ERROR "index" */]
+ s8 = &a
+ s10 = &42 /* ERROR "cannot take address" */
+ s11 = &v
+ s12 = -(u + *t11) / *&v
+ s13 = a /* ERROR "shifted operand" */ << d
+ s14 = i << j /* ERROR "must be unsigned" */
+ s18 = math.Pi * 10.0
+ s19 = s1 /* ERROR "cannot call" */ ()
+ s20 = f0 /* ERROR "used as single value" */ ()
+ s21 = f6(1, s1, i)
+ s22 = f6(1, s1, uu /* ERROR "cannot assign" */ )
+
+ t1 int = i + j
+ t2 int = i /* ERROR "mismatched types" */ + x
+ t3 int = c /* ERROR "cannot assign" */ + d
+ t4 string = s + t
+ t5 string = s /* ERROR "invalid operation" */ / t
+ t6 byte = array[t1]
+ t7 byte = array[x /* ERROR "index" */]
+ t8 *int = & /* ERROR "cannot assign" */ a
+ t10 *int = &42 /* ERROR "cannot take address" */
+ t11 *complex64 = &v
+ t12 complex64 = -(u + *t11) / *&v
+ t13 int = a /* ERROR "shifted operand" */ << d
+ t14 int = i << j /* ERROR "must be unsigned" */
+ t15 math /* ERROR "not in selector" */ /* ERROR "not a type" */
+ t16 math /* ERROR "not a type" */ .xxx /* ERROR "unexported" */
+ t17 math /* ERROR "not a type" */ .Pi
+ t18 float64 = math.Pi * 10.0
+ t19 int = t1 /* ERROR "cannot call" */ ()
+ t20 int = f0 /* ERROR "used as single value" */ ()
+)
+
+// Various more complex expressions
+var (
+ u1 = x /* ERROR "non-interface type" */ .(int)
+ u2 = iface.([]int)
+ u3 = iface.(a /* ERROR "not a type" */ )
+ u4, ok = iface.(int)
+ u5 /* ERROR "assignment count mismatch" */ , ok2, ok3 = iface.(int)
+)
+
+// Constant expression initializations
+var (
+ v1 = 1 /* ERROR "cannot convert" */ + "foo"
+ v2 = c + 255
+ v3 = c + 256 /* ERROR "overflows" */
+ v4 = r + 2147483647
+ v5 = r + 2147483648 /* ERROR "overflows" */
+ v6 = 42
+ v7 = v6 + 2147483647
+ v8 = v6 + 2147483648 /* ERROR "overflows" */
+ v9 = i + 1 << 10
+ v10 byte = 1024 /* ERROR "overflows" */
+ v11 = xx/yy*yy - xx
+ v12 = true && false
+)
+
+// Multiple assignment expressions
+var (
+ m1a, m1b = 1, 2
+ m2a /* ERROR "assignment count mismatch" */ , m2b, m2c = 1, 2
+ m3a /* ERROR "assignment count mismatch" */ , m3b = 1, 2, 3
+)
+
+// Declaration of parameters and results
+func f0() {}
+func f1(a /* ERROR "not a type" */) {}
+func f2(a, b, c d /* ERROR "not a type" */) {}
+
+func f3() int {}
+func f4() a /* ERROR "not a type" */ {}
+func f5() (a, b, c d /* ERROR "not a type" */) {}
+
+func f6(a, b, c int) complex128 { return 0 }
+
+// Declaration of receivers
+type T struct{}
+
+func (T) m0() {}
+func (*T) m1() {}
+func (x T) m2() {}
+func (x *T) m3() {}
diff --git a/libgo/go/exp/types/staging/testdata/decls2a.src b/libgo/go/exp/types/staging/testdata/decls2a.src
new file mode 100644
index 00000000000..738bcb76ae6
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/decls2a.src
@@ -0,0 +1,66 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// method declarations
+
+package decls2
+
+import "time"
+
+// T1 declared before its methods.
+type T1 struct{
+ f int
+}
+
+func (T1) m() {}
+func (T1) m /* ERROR "redeclared" */ () {}
+func (x *T1) f /* ERROR "field and method" */ () {}
+
+// T2's method declared before the type.
+func (*T2) f /* ERROR "field and method" */ () {}
+
+type T2 struct {
+ f int
+}
+
+// Methods declared without a declared type.
+func (undeclared /* ERROR "undeclared" */) m() {}
+func (x *undeclared /* ERROR "undeclared" */) m() {}
+
+func (pi /* ERROR "not a type" */) m1() {}
+func (x pi /* ERROR "not a type" */) m2() {}
+func (x *pi /* ERROR "not a type" */) m3() {}
+
+// Blank types.
+type _ struct { m int }
+type _ struct { m int }
+
+// TODO(gri) blank idents not fully checked - disabled for now
+// func (_ /* ERROR "cannot use _" */) m() {}
+// func (_ /* ERROR "cannot use _" */) m() {}
+
+// Methods with receiver base type declared in another file.
+func (T3) m1() {}
+func (*T3) m2() {}
+func (x T3) m3() {}
+func (x *T3) f /* ERROR "field and method" */ () {}
+
+// Methods of non-struct type.
+type T4 func()
+
+func (self T4) m() func() { return self }
+
+// Methods associated with an interface.
+type T5 interface {
+ m() int
+}
+
+func (T5 /* ERROR "invalid receiver" */) m1() {}
+func (T5 /* ERROR "invalid receiver" */) m2() {}
+
+// Methods associated with non-local or unnamed types.
+// func (int) m() {} TODO(gri) check for methods associated with external (not package-local) types
+func ([ /* ERROR "expected" */ ]int) m() {}
+func (time /* ERROR "expected" */ .Time) m() {}
+func (x interface /* ERROR "expected" */ {}) m() {}
diff --git a/libgo/go/exp/types/staging/testdata/decls2b.src b/libgo/go/exp/types/staging/testdata/decls2b.src
new file mode 100644
index 00000000000..9537c081e92
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/decls2b.src
@@ -0,0 +1,15 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// method declarations
+
+package decls2
+
+const pi = 3.1415
+
+func (T1) m /* ERROR "redeclared" */ () {}
+
+type T3 struct {
+ f *T3
+}
diff --git a/libgo/go/exp/types/staging/testdata/exports.go b/libgo/go/exp/types/staging/testdata/exports.go
new file mode 100644
index 00000000000..8ee28b0942b
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/exports.go
@@ -0,0 +1,89 @@
+// 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.
+
+// This file is used to generate an object file which
+// serves as test file for gcimporter_test.go.
+
+package exports
+
+import (
+ "go/ast"
+)
+
+// Issue 3682: Correctly read dotted identifiers from export data.
+const init1 = 0
+
+func init() {}
+
+const (
+ C0 int = 0
+ C1 = 3.14159265
+ C2 = 2.718281828i
+ C3 = -123.456e-789
+ C4 = +123.456E+789
+ C5 = 1234i
+ C6 = "foo\n"
+ C7 = `bar\n`
+)
+
+type (
+ T1 int
+ T2 [10]int
+ T3 []int
+ T4 *int
+ T5 chan int
+ T6a chan<- int
+ T6b chan (<-chan int)
+ T6c chan<- (chan int)
+ T7 <-chan *ast.File
+ T8 struct{}
+ T9 struct {
+ a int
+ b, c float32
+ d []string `go:"tag"`
+ }
+ T10 struct {
+ T8
+ T9
+ _ *T10
+ }
+ T11 map[int]string
+ T12 interface{}
+ T13 interface {
+ m1()
+ m2(int) float32
+ }
+ T14 interface {
+ T12
+ T13
+ m3(x ...struct{}) []T9
+ }
+ T15 func()
+ T16 func(int)
+ T17 func(x int)
+ T18 func() float32
+ T19 func() (x float32)
+ T20 func(...interface{})
+ T21 struct{ next *T21 }
+ T22 struct{ link *T23 }
+ T23 struct{ link *T22 }
+ T24 *T24
+ T25 *T26
+ T26 *T27
+ T27 *T25
+ T28 func(T28) T28
+)
+
+var (
+ V0 int
+ V1 = -991.0
+)
+
+func F1() {}
+func F2(x int) {}
+func F3() int { return 0 }
+func F4() float32 { return 0 }
+func F5(a, b, c int, u, v, w struct{ x, y T1 }, more ...interface{}) (p, q, r chan<- T10)
+
+func (p *T1) M1()
diff --git a/libgo/go/exp/types/staging/testdata/expr0.src b/libgo/go/exp/types/staging/testdata/expr0.src
new file mode 100644
index 00000000000..c54d42b8819
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/expr0.src
@@ -0,0 +1,135 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// unary expressions
+
+package expr0
+
+var (
+ // bool
+ b0 = true
+ b1 bool = b0
+ b2 = !true
+ b3 = !b1
+ b4 bool = !true
+ b5 bool = !b4
+ b6 = +b0 /* ERROR "not defined" */
+ b7 = -b0 /* ERROR "not defined" */
+ b8 = ^b0 /* ERROR "not defined" */
+ b9 = *b0 /* ERROR "cannot indirect" */
+ b10 = &true /* ERROR "cannot take address" */
+ b11 = &b0
+ b12 = <-b0 /* ERROR "not defined" */
+
+ // int
+ i0 = 1
+ i1 int = i0
+ i2 = +1
+ i3 = +i0
+ i4 int = +1
+ i5 int = +i4
+ i6 = -1
+ i7 = -i0
+ i8 int = -1
+ i9 int = -i4
+ i10 = !i0 /* ERROR "not defined" */
+ i11 = ^1
+ i12 = ^i0
+ i13 int = ^1
+ i14 int = ^i4
+ i15 = *i0 /* ERROR "cannot indirect" */
+ i16 = &i0
+ i17 = *i16
+ i18 = <-i16 /* ERROR "not defined" */
+
+ // uint
+ u0 = uint(1)
+ u1 uint = u0
+ u2 = +1
+ u3 = +u0
+ u4 uint = +1
+ u5 uint = +u4
+ u6 = -1
+ u7 = -u0
+ u8 uint = - /* ERROR "overflows" */ 1
+ u9 uint = -u4
+ u10 = !u0 /* ERROR "not defined" */
+ u11 = ^1
+ u12 = ^i0
+ u13 uint = ^ /* ERROR "overflows" */ 1
+ u14 uint = ^u4
+ u15 = *u0 /* ERROR "cannot indirect" */
+ u16 = &u0
+ u17 = *u16
+ u18 = <-u16 /* ERROR "not defined" */
+
+ // float64
+ f0 = float64(1)
+ f1 float64 = f0
+ f2 = +1
+ f3 = +f0
+ f4 float64 = +1
+ f5 float64 = +f4 /* ERROR not defined */
+ f6 = -1
+ f7 = -f0
+ f8 float64 = -1
+ f9 float64 = -f4
+ f10 = !f0 /* ERROR "not defined" */
+ f11 = ^1
+ f12 = ^i0
+ f13 float64 = ^1
+ f14 float64 = ^f4 /* ERROR "not defined" */
+ f15 = *f0 /* ERROR "cannot indirect" */
+ f16 = &f0
+ f17 = *u16
+ f18 = <-u16 /* ERROR "not defined" */
+
+ // complex128
+ c0 = complex128(1)
+ c1 complex128 = c0
+ c2 = +1
+ c3 = +c0
+ c4 complex128 = +1
+ c5 complex128 = +c4 /* ERROR not defined */
+ c6 = -1
+ c7 = -c0
+ c8 complex128 = -1
+ c9 complex128 = -c4
+ c10 = !c0 /* ERROR "not defined" */
+ c11 = ^1
+ c12 = ^i0
+ c13 complex128 = ^1
+ c14 complex128 = ^c4 /* ERROR "not defined" */
+ c15 = *c0 /* ERROR "cannot indirect" */
+ c16 = &c0
+ c17 = *u16
+ c18 = <-u16 /* ERROR "not defined" */
+
+ // string
+ s0 = "foo"
+ s1 = +"foo" /* ERROR "not defined" */
+ s2 = -s0 /* ERROR "not defined" */
+ s3 = !s0 /* ERROR "not defined" */
+ s4 = ^s0 /* ERROR "not defined" */
+ s5 = *s4 /* ERROR "cannot indirect" */
+ s6 = &s4
+ s7 = *s6
+ s8 = <-s7 /* ERROR "not defined" */
+
+ // channel
+ ch chan int
+ rc <-chan float64
+ sc chan <- string
+ ch0 = +ch /* ERROR "not defined" */
+ ch1 = -ch /* ERROR "not defined" */
+ ch2 = !ch /* ERROR "not defined" */
+ ch3 = ^ch /* ERROR "not defined" */
+ ch4 = *ch /* ERROR "cannot indirect" */
+ ch5 = &ch
+ ch6 = *ch5
+ ch7 = <-ch
+ ch8 = <-rc
+ ch9 = <-sc /* ERROR "not defined" */
+
+) \ No newline at end of file
diff --git a/libgo/go/exp/types/staging/testdata/expr1.src b/libgo/go/exp/types/staging/testdata/expr1.src
new file mode 100644
index 00000000000..8ef0aed6d2e
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/expr1.src
@@ -0,0 +1,7 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// binary expressions
+
+package expr1
diff --git a/libgo/go/exp/types/staging/testdata/expr2.src b/libgo/go/exp/types/staging/testdata/expr2.src
new file mode 100644
index 00000000000..a3167f45054
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/expr2.src
@@ -0,0 +1,7 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// comparisons
+
+package expr2
diff --git a/libgo/go/exp/types/staging/testdata/expr3.src b/libgo/go/exp/types/staging/testdata/expr3.src
new file mode 100644
index 00000000000..5635e12eeb0
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/expr3.src
@@ -0,0 +1,115 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// various expressions
+
+package expr3
+
+// TODO(gri) Move the code below into function "shifts" once we check
+// declarations with initilizations inside functions.
+var (
+ i0 int
+ u0 uint
+)
+
+var (
+ v0 = 1<<0
+ v1 = 1<<i0 /* ERROR "must be unsigned" */
+ v2 = 1<<u0
+ v3 = 1<<"foo" /* ERROR "must be unsigned" */
+ v4 = 1<<- /* ERROR "stupid shift" */ 1
+ v5 = 1<<1025 /* ERROR "stupid shift" */
+ v6 = 1 /* ERROR "overflows" */ <<100
+
+ v10 uint = 1 << 0
+ v11 uint = 1 << u0
+ v12 float32 = 1 /* ERROR "must be integer" */ << u0
+)
+
+// TODO(gri) enable commented out tests below.
+
+// from the spec
+var (
+ s uint = 33
+ i = 1<<s // 1 has type int
+ j int32 = 1<<s // 1 has type int32; j == 0
+ k = uint64(1<<s) // 1 has type uint64; k == 1<<33
+ m int = 1.0<<s // 1.0 has type int
+// n = 1.0<<s != 0 // 1.0 has type int; n == false if ints are 32bits in size
+ o = 1<<s == 2<<s // 1 and 2 have type int; o == true if ints are 32bits in size
+// p = 1<<s == 1 /* ERROR "overflows" */ <<33 // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
+ u = 1.0 /* ERROR "must be integer" */ <<s // illegal: 1.0 has type float64, cannot shift
+ v float32 = 1 /* ERROR "must be integer" */ <<s // illegal: 1 has type float32, cannot shift
+ w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression
+)
+
+// TODO(gri) The error messages below depond on adjusting the spec
+// to reflect what gc is doing at the moment (the spec
+// asks for run-time errors at the moment - see issue 4231).
+//
+func indexes() {
+ _ = 1 /* ERROR "cannot index" */ [0]
+ _ = indexes /* ERROR "cannot index" */ [0]
+ _ = ( /* ERROR "cannot slice" */ 12 + 3)[1:2]
+
+ var a [10]int
+ _ = a[true /* ERROR "must be integer" */ ]
+ _ = a["foo" /* ERROR "must be integer" */ ]
+ _ = a[1.1 /* ERROR "must be integer" */ ]
+ _ = a[1.0]
+ _ = a[- /* ERROR "index .* negative" */ 1]
+ _ = a[- /* ERROR "index .* negative" */ 1 :]
+ _ = a[: - /* ERROR "index .* negative" */ 1]
+ var a0 int
+ a0 = a[0]
+ var a1 int32
+ a1 = a /* ERROR "cannot assign" */ [1]
+ _ = a[9]
+ _ = a[10 /* ERROR "index .* out of bounds" */ ]
+ _ = a[10:]
+ _ = a[:10]
+ _ = a[10:10]
+ _ = a[11 /* ERROR "index .* out of bounds" */ :]
+ _ = a[: 11 /* ERROR "index .* out of bounds" */ ]
+
+ var b [0]int
+ _ = b[0 /* ERROR "index .* out of bounds" */ ]
+ _ = b[:]
+ _ = b[0:]
+ _ = b[:0]
+ _ = b[0:0]
+
+ var s []int
+ _ = s[- /* ERROR "index .* negative" */ 1]
+ _ = s[- /* ERROR "index .* negative" */ 1 :]
+ _ = s[: - /* ERROR "index .* negative" */ 1]
+ _ = s[0]
+ _ = s[1 : 2]
+ _ = s[2 /* ERROR "inverted slice range" */ : 1]
+ _ = s[2 :]
+
+ var t string
+ _ = t[- /* ERROR "index .* negative" */ 1]
+ _ = t[- /* ERROR "index .* negative" */ 1 :]
+ _ = t[: - /* ERROR "index .* negative" */ 1]
+ var t0 byte
+ t0 = t[0]
+ var t1 rune
+ t1 = t /* ERROR "cannot assign" */ [2]
+ _ = ("foo" + "bar")[5]
+ _ = ("foo" + "bar")[6 /* ERROR "index .* out of bounds" */ ]
+
+ const c = "foo"
+ _ = c[- /* ERROR "index .* negative" */ 1]
+ _ = c[- /* ERROR "index .* negative" */ 1 :]
+ _ = c[: - /* ERROR "index .* negative" */ 1]
+ var c0 byte
+ c0 = c[0]
+ var c2 float32
+ c2 = c /* ERROR "cannot assign" */ [2]
+ _ = c[3 /* ERROR "index .* out of bounds" */ ]
+ _ = ""[0 /* ERROR "index .* out of bounds" */ ]
+
+ _ = s[1<<30] // no compile-time error here
+}
diff --git a/libgo/go/exp/types/staging/testdata/stmt0.src b/libgo/go/exp/types/staging/testdata/stmt0.src
new file mode 100644
index 00000000000..a98c930454a
--- /dev/null
+++ b/libgo/go/exp/types/staging/testdata/stmt0.src
@@ -0,0 +1,42 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// statements
+
+package stmt0
+
+func _() {
+ b, i, f, c, s := false, 1, 1.0, 1i, "foo"
+ b = i /* ERROR "cannot assign" */
+ i = f /* ERROR "cannot assign" */
+ f = c /* ERROR "cannot assign" */
+ c = s /* ERROR "cannot assign" */
+ s = b /* ERROR "cannot assign" */
+
+ v0 /* ERROR "mismatch" */, v1, v2 := 1, 2, 3, 4
+
+ b = true
+
+ i += 1
+ i += "foo" /* ERROR "cannot convert.*int" */
+
+ f -= 1
+ f -= "foo" /* ERROR "cannot convert.*float64" */
+
+ c *= 1
+ c /= 0 /* ERROR "division by zero" */
+
+ s += "bar"
+ s += 1 /* ERROR "cannot convert.*string" */
+}
+
+func _sends() {
+ var ch chan int
+ var rch <-chan int
+ var x int
+ x /* ERROR "cannot send" */ <- x
+ rch /* ERROR "cannot send" */ <- x
+ ch /* ERROR "cannot send" */ <- "foo"
+ ch <- x
+} \ No newline at end of file
diff --git a/libgo/go/exp/types/staging/types.go b/libgo/go/exp/types/staging/types.go
new file mode 100644
index 00000000000..b6e7c1edb7a
--- /dev/null
+++ b/libgo/go/exp/types/staging/types.go
@@ -0,0 +1,235 @@
+// 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 types declares the data structures for representing
+// Go types and implements typechecking of an *ast.Package.
+//
+// PACKAGE UNDER CONSTRUCTION. ANY AND ALL PARTS MAY CHANGE.
+//
+package types
+
+import (
+ "go/ast"
+ "go/token"
+ "sort"
+)
+
+// Check typechecks a package pkg. It returns the first error, or nil.
+//
+// Check augments the AST by assigning types to ast.Objects. It
+// calls err with the error position and message for each error.
+// It calls f with each valid AST expression and corresponding
+// type. If err == nil, Check terminates as soon as the first error
+// is found. If f is nil, it is not invoked.
+//
+func Check(fset *token.FileSet, pkg *ast.Package, err func(token.Pos, string), f func(ast.Expr, Type)) error {
+ return check(fset, pkg, err, f)
+}
+
+// All types implement the Type interface.
+// TODO(gri) Eventually determine what common Type functionality should be exported.
+type Type interface {
+ aType()
+}
+
+// BasicKind describes the kind of basic type.
+type BasicKind int
+
+const (
+ Invalid BasicKind = iota // type is invalid
+
+ // predeclared types
+ Bool
+ Int
+ Int8
+ Int16
+ Int32
+ Int64
+ Uint
+ Uint8
+ Uint16
+ Uint32
+ Uint64
+ Uintptr
+ Float32
+ Float64
+ Complex64
+ Complex128
+ String
+ UnsafePointer
+
+ // types for untyped values
+ UntypedBool
+ UntypedInt
+ UntypedRune
+ UntypedFloat
+ UntypedComplex
+ UntypedString
+ UntypedNil
+
+ // aliases
+ Byte = Uint8
+ Rune = Int32
+)
+
+// BasicInfo is a set of flags describing properties of a basic type.
+type BasicInfo int
+
+// Properties of basic types.
+const (
+ IsBoolean BasicInfo = 1 << iota
+ IsInteger
+ IsUnsigned
+ IsFloat
+ IsComplex
+ IsString
+ IsUntyped
+
+ IsOrdered = IsInteger | IsFloat | IsString
+ IsNumeric = IsInteger | IsFloat | IsComplex
+)
+
+// A Basic represents a basic type.
+type Basic struct {
+ implementsType
+ Kind BasicKind
+ Info BasicInfo
+ Size int64 // > 0 if valid
+ Name string
+}
+
+// An Array represents an array type [Len]Elt.
+type Array struct {
+ implementsType
+ Len int64
+ Elt Type
+}
+
+// A Slice represents a slice type []Elt.
+type Slice struct {
+ implementsType
+ Elt Type
+}
+
+type StructField struct {
+ Name string // unqualified type name for anonymous fields
+ Type Type
+ Tag string
+ IsAnonymous bool
+}
+
+// A Struct represents a struct type struct{...}.
+type Struct struct {
+ implementsType
+ Fields []*StructField
+}
+
+// A Pointer represents a pointer type *Base.
+type Pointer struct {
+ implementsType
+ Base Type
+}
+
+// A tuple represents a multi-value function return.
+// TODO(gri) use better name to avoid confusion (Go doesn't have tuples).
+type tuple struct {
+ implementsType
+ list []Type
+}
+
+// A Signature represents a user-defined function type func(...) (...).
+// TODO(gri) consider using "tuples" to represent parameters and results (see comment on tuples).
+type Signature struct {
+ implementsType
+ Recv *ast.Object // nil if not a method
+ Params ObjList // (incoming) parameters from left to right; or nil
+ Results ObjList // (outgoing) results from left to right; or nil
+ IsVariadic bool // true if the last parameter's type is of the form ...T
+}
+
+// builtinId is an id of a builtin function.
+type builtinId int
+
+// Predeclared builtin functions.
+const (
+ // Universe scope
+ _Append builtinId = iota
+ _Cap
+ _Close
+ _Complex
+ _Copy
+ _Delete
+ _Imag
+ _Len
+ _Make
+ _New
+ _Panic
+ _Print
+ _Println
+ _Real
+ _Recover
+
+ // Unsafe package
+ _Alignof
+ _Offsetof
+ _Sizeof
+
+ // Testing support
+ _Assert
+ _Trace
+)
+
+// A builtin represents the type of a built-in function.
+type builtin struct {
+ implementsType
+ id builtinId
+ name string
+ nargs int // number of arguments (minimum if variadic)
+ isVariadic bool
+ isStatement bool // true if the built-in is valid as an expression statement
+}
+
+// An Interface represents an interface type interface{...}.
+type Interface struct {
+ implementsType
+ Methods ObjList // interface methods sorted by name; or nil
+}
+
+// A Map represents a map type map[Key]Elt.
+type Map struct {
+ implementsType
+ Key, Elt Type
+}
+
+// A Chan represents a channel type chan Elt, <-chan Elt, or chan<-Elt.
+type Chan struct {
+ implementsType
+ Dir ast.ChanDir
+ Elt Type
+}
+
+// A NamedType represents a named type as declared in a type declaration.
+type NamedType struct {
+ implementsType
+ Obj *ast.Object // corresponding declared object
+ Underlying Type // nil if not fully declared yet, never a *NamedType
+ Methods ObjList // associated methods; or nil
+}
+
+// An ObjList represents an ordered (in some fashion) list of objects.
+type ObjList []*ast.Object
+
+// ObjList implements sort.Interface.
+func (list ObjList) Len() int { return len(list) }
+func (list ObjList) Less(i, j int) bool { return list[i].Name < list[j].Name }
+func (list ObjList) Swap(i, j int) { list[i], list[j] = list[j], list[i] }
+
+// Sort sorts an object list by object name.
+func (list ObjList) Sort() { sort.Sort(list) }
+
+// All concrete types embed implementsType which
+// ensures that all types implement the Type interface.
+type implementsType struct{}
+
+func (*implementsType) aType() {}
diff --git a/libgo/go/exp/types/staging/types_test.go b/libgo/go/exp/types/staging/types_test.go
new file mode 100644
index 00000000000..e6959bceeb0
--- /dev/null
+++ b/libgo/go/exp/types/staging/types_test.go
@@ -0,0 +1,181 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests verifying the types associated with an AST after
+// type checking.
+
+package types
+
+import (
+ "go/ast"
+ "go/parser"
+ "testing"
+)
+
+const filename = "<src>"
+
+func makePkg(t *testing.T, src string) (*ast.Package, error) {
+ file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
+ if err != nil {
+ return nil, err
+ }
+ files := map[string]*ast.File{filename: file}
+ pkg, err := ast.NewPackage(fset, files, GcImport, Universe)
+ if err != nil {
+ return nil, err
+ }
+ if err := Check(fset, pkg, nil, nil); err != nil {
+ return nil, err
+ }
+ return pkg, nil
+}
+
+type testEntry struct {
+ src, str string
+}
+
+// dup returns a testEntry where both src and str are the same.
+func dup(s string) testEntry {
+ return testEntry{s, s}
+}
+
+var testTypes = []testEntry{
+ // basic types
+ dup("int"),
+ dup("float32"),
+ dup("string"),
+
+ // arrays
+ dup("[10]int"),
+
+ // slices
+ dup("[]int"),
+ dup("[][]int"),
+
+ // structs
+ dup("struct{}"),
+ dup("struct{x int}"),
+ {`struct {
+ x, y int
+ z float32 "foo"
+ }`, `struct{x int; y int; z float32 "foo"}`},
+ {`struct {
+ string
+ elems []T
+ }`, `struct{string; elems []T}`},
+
+ // pointers
+ dup("*int"),
+ dup("***struct{}"),
+ dup("*struct{a int; b float32}"),
+
+ // functions
+ dup("func()"),
+ dup("func(x int)"),
+ {"func(x, y int)", "func(x int, y int)"},
+ {"func(x, y int, z string)", "func(x int, y int, z string)"},
+ dup("func(int)"),
+ {"func(int, string, byte)", "func(int, string, byte)"},
+
+ dup("func() int"),
+ {"func() (string)", "func() string"},
+ dup("func() (u int)"),
+ {"func() (u, v int, w string)", "func() (u int, v int, w string)"},
+
+ dup("func(int) string"),
+ dup("func(x int) string"),
+ dup("func(x int) (u string)"),
+ {"func(x, y int) (u string)", "func(x int, y int) (u string)"},
+
+ dup("func(...int) string"),
+ dup("func(x ...int) string"),
+ dup("func(x ...int) (u string)"),
+ {"func(x, y ...int) (u string)", "func(x int, y ...int) (u string)"},
+
+ // interfaces
+ dup("interface{}"),
+ dup("interface{m()}"),
+ {`interface{
+ m(int) float32
+ String() string
+ }`, `interface{String() string; m(int) float32}`}, // methods are sorted
+ // TODO(gri) add test for interface w/ anonymous field
+
+ // maps
+ dup("map[string]int"),
+ {"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"},
+
+ // channels
+ dup("chan int"),
+ dup("chan<- func()"),
+ dup("<-chan []func() int"),
+}
+
+func TestTypes(t *testing.T) {
+ for _, test := range testTypes {
+ src := "package p; type T " + test.src
+ pkg, err := makePkg(t, src)
+ if err != nil {
+ t.Errorf("%s: %s", src, err)
+ continue
+ }
+ typ := underlying(pkg.Scope.Lookup("T").Type.(Type))
+ str := typeString(typ)
+ if str != test.str {
+ t.Errorf("%s: got %s, want %s", test.src, str, test.str)
+ }
+ }
+}
+
+var testExprs = []testEntry{
+ // basic type literals
+ dup("x"),
+ dup("true"),
+ dup("42"),
+ dup("3.1415"),
+ dup("2.71828i"),
+ dup(`'a'`),
+ dup(`"foo"`),
+ dup("`bar`"),
+
+ // arbitrary expressions
+ dup("&x"),
+ dup("*x"),
+ dup("(x)"),
+ dup("x + y"),
+ dup("x + y * 10"),
+ dup("s.foo"),
+ dup("s[0]"),
+ dup("s[x:y]"),
+ dup("s[:y]"),
+ dup("s[x:]"),
+ dup("s[:]"),
+ dup("f(1, 2.3)"),
+ dup("-f(10, 20)"),
+ dup("f(x + y, +3.1415)"),
+ {"func(a, b int) {}", "(func literal)"},
+ {"func(a, b int) []int {}()[x]", "(func literal)()[x]"},
+ {"[]int{1, 2, 3}", "(composite literal)"},
+ {"[]int{1, 2, 3}[x:]", "(composite literal)[x:]"},
+ {"x.([]string)", "x.(...)"},
+}
+
+func TestExprs(t *testing.T) {
+ for _, test := range testExprs {
+ src := "package p; var _ = " + test.src + "; var (x, y int; s []string; f func(int, float32))"
+ pkg, err := makePkg(t, src)
+ if err != nil {
+ t.Errorf("%s: %s", src, err)
+ continue
+ }
+ // TODO(gri) writing the code below w/o the decl variable will
+ // cause a 386 compiler error (out of fixed registers)
+ decl := pkg.Files[filename].Decls[0].(*ast.GenDecl)
+ expr := decl.Specs[0].(*ast.ValueSpec).Values[0]
+ str := exprString(expr)
+ if str != test.str {
+ t.Errorf("%s: got %s, want %s", test.src, str, test.str)
+ }
+ }
+}
diff --git a/libgo/go/exp/types/staging/universe.go b/libgo/go/exp/types/staging/universe.go
new file mode 100644
index 00000000000..bb8b6a2bdac
--- /dev/null
+++ b/libgo/go/exp/types/staging/universe.go
@@ -0,0 +1,159 @@
+// 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.
+
+// This file implements the universe and unsafe package scopes.
+
+package types
+
+import (
+ "go/ast"
+ "strings"
+)
+
+var (
+ aType implementsType
+ Universe, unsafe *ast.Scope
+ Unsafe *ast.Object // package unsafe
+)
+
+// Predeclared types, indexed by BasicKind.
+var Typ = [...]*Basic{
+ Invalid: {aType, Invalid, 0, 0, "invalid type"},
+
+ Bool: {aType, Bool, IsBoolean, 1, "bool"},
+ Int: {aType, Int, IsInteger, 0, "int"},
+ Int8: {aType, Int8, IsInteger, 1, "int8"},
+ Int16: {aType, Int16, IsInteger, 2, "int16"},
+ Int32: {aType, Int32, IsInteger, 4, "int32"},
+ Int64: {aType, Int64, IsInteger, 8, "int64"},
+ Uint: {aType, Uint, IsInteger | IsUnsigned, 0, "uint"},
+ Uint8: {aType, Uint8, IsInteger | IsUnsigned, 1, "uint8"},
+ Uint16: {aType, Uint16, IsInteger | IsUnsigned, 2, "uint16"},
+ Uint32: {aType, Uint32, IsInteger | IsUnsigned, 4, "uint32"},
+ Uint64: {aType, Uint64, IsInteger | IsUnsigned, 8, "uint64"},
+ Uintptr: {aType, Uintptr, IsInteger | IsUnsigned, 0, "uintptr"},
+ Float32: {aType, Float32, IsFloat, 4, "float32"},
+ Float64: {aType, Float64, IsFloat, 8, "float64"},
+ Complex64: {aType, Complex64, IsComplex, 8, "complex64"},
+ Complex128: {aType, Complex128, IsComplex, 16, "complex128"},
+ String: {aType, String, IsString, 0, "string"},
+ UnsafePointer: {aType, UnsafePointer, 0, 0, "Pointer"},
+
+ UntypedBool: {aType, UntypedBool, IsBoolean | IsUntyped, 0, "untyped boolean"},
+ UntypedInt: {aType, UntypedInt, IsInteger | IsUntyped, 0, "untyped integer"},
+ UntypedRune: {aType, UntypedRune, IsInteger | IsUntyped, 0, "untyped rune"},
+ UntypedFloat: {aType, UntypedFloat, IsFloat | IsUntyped, 0, "untyped float"},
+ UntypedComplex: {aType, UntypedComplex, IsComplex | IsUntyped, 0, "untyped complex"},
+ UntypedString: {aType, UntypedString, IsString | IsUntyped, 0, "untyped string"},
+ UntypedNil: {aType, UntypedNil, IsUntyped, 0, "untyped nil"},
+}
+
+var aliases = [...]*Basic{
+ {aType, Byte, IsInteger | IsUnsigned, 1, "byte"},
+ {aType, Rune, IsInteger, 4, "rune"},
+}
+
+var predeclaredConstants = [...]*struct {
+ kind BasicKind
+ name string
+ val interface{}
+}{
+ {UntypedBool, "true", true},
+ {UntypedBool, "false", false},
+ {UntypedInt, "iota", zeroConst},
+ {UntypedNil, "nil", nilConst},
+}
+
+var predeclaredFunctions = [...]*builtin{
+ {aType, _Append, "append", 1, true, false},
+ {aType, _Cap, "cap", 1, false, false},
+ {aType, _Close, "close", 1, false, true},
+ {aType, _Complex, "complex", 2, false, false},
+ {aType, _Copy, "copy", 2, false, true},
+ {aType, _Delete, "delete", 2, false, true},
+ {aType, _Imag, "imag", 1, false, false},
+ {aType, _Len, "len", 1, false, false},
+ {aType, _Make, "make", 1, true, false},
+ {aType, _New, "new", 1, false, false},
+ {aType, _Panic, "panic", 1, false, true},
+ {aType, _Print, "print", 1, true, true},
+ {aType, _Println, "println", 1, true, true},
+ {aType, _Real, "real", 1, false, false},
+ {aType, _Recover, "recover", 0, false, true},
+
+ {aType, _Alignof, "Alignof", 1, false, false},
+ {aType, _Offsetof, "Offsetof", 1, false, false},
+ {aType, _Sizeof, "Sizeof", 1, false, false},
+}
+
+// commonly used types
+var (
+ emptyInterface = new(Interface)
+)
+
+// commonly used constants
+var (
+ universeIota *ast.Object
+)
+
+func init() {
+ // Universe scope
+ Universe = ast.NewScope(nil)
+
+ // unsafe package and its scope
+ unsafe = ast.NewScope(nil)
+ Unsafe = ast.NewObj(ast.Pkg, "unsafe")
+ Unsafe.Data = unsafe
+
+ // predeclared types
+ for _, t := range Typ {
+ def(ast.Typ, t.Name).Type = t
+ }
+ for _, t := range aliases {
+ def(ast.Typ, t.Name).Type = t
+ }
+
+ // error type
+ {
+ obj := def(ast.Typ, "error")
+ // TODO(gri) set up correct interface type
+ typ := &NamedType{Underlying: &Interface{}, Obj: obj}
+ obj.Type = typ
+ }
+
+ // predeclared constants
+ for _, t := range predeclaredConstants {
+ obj := def(ast.Con, t.name)
+ obj.Type = Typ[t.kind]
+ obj.Data = t.val
+ }
+
+ // predeclared functions
+ for _, f := range predeclaredFunctions {
+ def(ast.Fun, f.name).Type = f
+ }
+
+ universeIota = Universe.Lookup("iota")
+}
+
+// Objects with names containing blanks are internal and not entered into
+// a scope. Objects with exported names are inserted in the unsafe package
+// scope; other objects are inserted in the universe scope.
+//
+func def(kind ast.ObjKind, name string) *ast.Object {
+ obj := ast.NewObj(kind, name)
+ // insert non-internal objects into respective scope
+ if strings.Index(name, " ") < 0 {
+ scope := Universe
+ // exported identifiers go into package unsafe
+ if ast.IsExported(name) {
+ scope = unsafe
+ }
+ if scope.Insert(obj) != nil {
+ panic("internal error: double declaration")
+ }
+ obj.Decl = scope
+ }
+ return obj
+}
diff --git a/libgo/go/exp/types/testdata/exports.go b/libgo/go/exp/types/testdata/exports.go
index ed63bf9adec..8ee28b0942b 100644
--- a/libgo/go/exp/types/testdata/exports.go
+++ b/libgo/go/exp/types/testdata/exports.go
@@ -11,6 +11,11 @@ import (
"go/ast"
)
+// Issue 3682: Correctly read dotted identifiers from export data.
+const init1 = 0
+
+func init() {}
+
const (
C0 int = 0
C1 = 3.14159265
diff --git a/libgo/go/exp/types/testdata/test0.src b/libgo/go/exp/types/testdata/test0.src
index 84a1abe2701..a770a19b803 100644
--- a/libgo/go/exp/types/testdata/test0.src
+++ b/libgo/go/exp/types/testdata/test0.src
@@ -6,7 +6,12 @@
package test0
-import "unsafe"
+import (
+ "unsafe"
+ // we can have multiple blank imports (was bug)
+ _ "math"
+ _ "net/rpc"
+)
const pi = 3.1415
@@ -39,15 +44,15 @@ type (
type (
Pi pi /* ERROR "not a type" */
- a /* DISABLED "illegal cycle" */ a
+ a /* ERROR "illegal cycle" */ a
a /* ERROR "redeclared" */ int
// where the cycle error appears depends on the
// order in which declarations are processed
// (which depends on the order in which a map
// is iterated through)
- b c
- c /* DISABLED "illegal cycle" */ d
+ b /* ERROR "illegal cycle" */ c
+ c d
d e
e b
@@ -74,13 +79,13 @@ type (
S3 struct {
x S2
}
- S4/* DISABLED "illegal cycle" */ struct {
+ S4/* ERROR "illegal cycle" */ struct {
S4
}
- S5 struct {
+ S5 /* ERROR "illegal cycle" */ struct {
S6
}
- S6 /* DISABLED "illegal cycle" */ struct {
+ S6 struct {
field S7
}
S7 struct {
@@ -91,8 +96,8 @@ type (
L2 []int
A1 [10]int
- A2 /* DISABLED "illegal cycle" */ [10]A2
- A3 /* DISABLED "illegal cycle" */ [10]struct {
+ A2 /* ERROR "illegal cycle" */ [10]A2
+ A3 /* ERROR "illegal cycle" */ [10]struct {
x A4
}
A4 [10]A3
@@ -127,17 +132,21 @@ type (
I1
I1
}
- I8 /* DISABLED "illegal cycle" */ interface {
+ I8 /* ERROR "illegal cycle" */ interface {
I8
}
- I9 /* DISABLED "illegal cycle" */ interface {
+ // Use I09 (rather than I9) because it appears lexically before
+ // I10 so that we get the illegal cycle here rather then in the
+ // declaration of I10. If the implementation sorts by position
+ // rather than name, the error message will still be here.
+ I09 /* ERROR "illegal cycle" */ interface {
I10
}
I10 interface {
I11
}
I11 interface {
- I9
+ I09
}
C1 chan int
diff --git a/libgo/go/exp/types/types.go b/libgo/go/exp/types/types.go
index 85d244cf04a..50d85b76443 100644
--- a/libgo/go/exp/types/types.go
+++ b/libgo/go/exp/types/types.go
@@ -8,6 +8,8 @@
package types
import (
+ "bytes"
+ "fmt"
"go/ast"
"sort"
)
@@ -17,41 +19,41 @@ type Type interface {
isType()
}
-// All concrete types embed ImplementsType which
+// All concrete types embed implementsType which
// ensures that all types implement the Type interface.
-type ImplementsType struct{}
+type implementsType struct{}
-func (t *ImplementsType) isType() {}
+func (t *implementsType) isType() {}
// A Bad type is a non-nil placeholder type when we don't know a type.
type Bad struct {
- ImplementsType
+ implementsType
Msg string // for better error reporting/debugging
}
// A Basic represents a (unnamed) basic type.
type Basic struct {
- ImplementsType
+ implementsType
// TODO(gri) need a field specifying the exact basic type
}
// An Array represents an array type [Len]Elt.
type Array struct {
- ImplementsType
+ implementsType
Len uint64
Elt Type
}
// A Slice represents a slice type []Elt.
type Slice struct {
- ImplementsType
+ implementsType
Elt Type
}
// A Struct represents a struct type struct{...}.
// Anonymous fields are represented by objects with empty names.
type Struct struct {
- ImplementsType
+ implementsType
Fields ObjList // struct fields; or nil
Tags []string // corresponding tags; or nil
// TODO(gri) This type needs some rethinking:
@@ -62,14 +64,14 @@ type Struct struct {
// A Pointer represents a pointer type *Base.
type Pointer struct {
- ImplementsType
+ implementsType
Base Type
}
// A Func represents a function type func(...) (...).
// Unnamed parameters are represented by objects with empty names.
type Func struct {
- ImplementsType
+ implementsType
Recv *ast.Object // nil if not a method
Params ObjList // (incoming) parameters from left to right; or nil
Results ObjList // (outgoing) results from left to right; or nil
@@ -78,31 +80,151 @@ type Func struct {
// An Interface represents an interface type interface{...}.
type Interface struct {
- ImplementsType
+ implementsType
Methods ObjList // interface methods sorted by name; or nil
}
// A Map represents a map type map[Key]Elt.
type Map struct {
- ImplementsType
+ implementsType
Key, Elt Type
}
// A Chan represents a channel type chan Elt, <-chan Elt, or chan<-Elt.
type Chan struct {
- ImplementsType
+ implementsType
Dir ast.ChanDir
Elt Type
}
// A Name represents a named type as declared in a type declaration.
type Name struct {
- ImplementsType
+ implementsType
Underlying Type // nil if not fully declared
Obj *ast.Object // corresponding declared object
// TODO(gri) need to remember fields and methods.
}
+func writeParams(buf *bytes.Buffer, params ObjList, isVariadic bool) {
+ buf.WriteByte('(')
+ for i, par := range params {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ if par.Name != "" {
+ buf.WriteString(par.Name)
+ buf.WriteByte(' ')
+ }
+ if isVariadic && i == len(params)-1 {
+ buf.WriteString("...")
+ }
+ writeType(buf, par.Type.(Type))
+ }
+ buf.WriteByte(')')
+}
+
+func writeSignature(buf *bytes.Buffer, t *Func) {
+ writeParams(buf, t.Params, t.IsVariadic)
+ if len(t.Results) == 0 {
+ // no result
+ return
+ }
+
+ buf.WriteByte(' ')
+ if len(t.Results) == 1 && t.Results[0].Name == "" {
+ // single unnamed result
+ writeType(buf, t.Results[0].Type.(Type))
+ return
+ }
+
+ // multiple or named result(s)
+ writeParams(buf, t.Results, false)
+}
+
+func writeType(buf *bytes.Buffer, typ Type) {
+ switch t := typ.(type) {
+ case *Bad:
+ fmt.Fprintf(buf, "badType(%s)", t.Msg)
+
+ case *Basic:
+ buf.WriteString("basicType") // TODO(gri) print actual type information
+
+ case *Array:
+ fmt.Fprintf(buf, "[%d]", t.Len)
+ writeType(buf, t.Elt)
+
+ case *Slice:
+ buf.WriteString("[]")
+ writeType(buf, t.Elt)
+
+ case *Struct:
+ buf.WriteString("struct{")
+ for i, fld := range t.Fields {
+ if i > 0 {
+ buf.WriteString("; ")
+ }
+ if fld.Name != "" {
+ buf.WriteString(fld.Name)
+ buf.WriteByte(' ')
+ }
+ writeType(buf, fld.Type.(Type))
+ if i < len(t.Tags) && t.Tags[i] != "" {
+ fmt.Fprintf(buf, " %q", t.Tags[i])
+ }
+ }
+ buf.WriteByte('}')
+
+ case *Pointer:
+ buf.WriteByte('*')
+ writeType(buf, t.Base)
+
+ case *Func:
+ buf.WriteString("func")
+ writeSignature(buf, t)
+
+ case *Interface:
+ buf.WriteString("interface{")
+ for i, m := range t.Methods {
+ if i > 0 {
+ buf.WriteString("; ")
+ }
+ buf.WriteString(m.Name)
+ writeSignature(buf, m.Type.(*Func))
+ }
+ buf.WriteByte('}')
+
+ case *Map:
+ buf.WriteString("map[")
+ writeType(buf, t.Key)
+ buf.WriteByte(']')
+ writeType(buf, t.Elt)
+
+ case *Chan:
+ var s string
+ switch t.Dir {
+ case ast.SEND:
+ s = "chan<- "
+ case ast.RECV:
+ s = "<-chan "
+ default:
+ s = "chan "
+ }
+ buf.WriteString(s)
+ writeType(buf, t.Elt)
+
+ case *Name:
+ buf.WriteString(t.Obj.Name)
+
+ }
+}
+
+// TypeString returns a string representation for typ.
+func TypeString(typ Type) string {
+ var buf bytes.Buffer
+ writeType(&buf, typ)
+ return buf.String()
+}
+
// If typ is a pointer type, Deref returns the pointer's base type;
// otherwise it returns typ.
func Deref(typ Type) Type {
diff --git a/libgo/go/exp/types/types_test.go b/libgo/go/exp/types/types_test.go
new file mode 100644
index 00000000000..c49f366a863
--- /dev/null
+++ b/libgo/go/exp/types/types_test.go
@@ -0,0 +1,128 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests verifying the types associated with an AST after
+// type checking.
+
+package types
+
+import (
+ "go/ast"
+ "go/parser"
+ "testing"
+)
+
+func makePkg(t *testing.T, src string) (*ast.Package, error) {
+ const filename = "<src>"
+ file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
+ if err != nil {
+ return nil, err
+ }
+ files := map[string]*ast.File{filename: file}
+ pkg, err := ast.NewPackage(fset, files, GcImport, Universe)
+ if err != nil {
+ return nil, err
+ }
+ if _, err := Check(fset, pkg); err != nil {
+ return nil, err
+ }
+ return pkg, nil
+}
+
+type testEntry struct {
+ src, str string
+}
+
+// dup returns a testEntry where both src and str are the same.
+func dup(s string) testEntry {
+ return testEntry{s, s}
+}
+
+var testTypes = []testEntry{
+ // basic types
+ dup("int"),
+ dup("float32"),
+ dup("string"),
+
+ // arrays
+ {"[10]int", "[0]int"}, // TODO(gri) fix array length, add more array tests
+
+ // slices
+ dup("[]int"),
+ dup("[][]int"),
+
+ // structs
+ dup("struct{}"),
+ dup("struct{x int}"),
+ {`struct {
+ x, y int
+ z float32 "foo"
+ }`, `struct{x int; y int; z float32 "foo"}`},
+ {`struct {
+ string
+ elems []T
+ }`, `struct{string; elems []T}`},
+
+ // pointers
+ dup("*int"),
+ dup("***struct{}"),
+ dup("*struct{a int; b float32}"),
+
+ // functions
+ dup("func()"),
+ dup("func(x int)"),
+ {"func(x, y int)", "func(x int, y int)"},
+ {"func(x, y int, z string)", "func(x int, y int, z string)"},
+ dup("func(int)"),
+ dup("func(int, string, byte)"),
+
+ dup("func() int"),
+ {"func() (string)", "func() string"},
+ dup("func() (u int)"),
+ {"func() (u, v int, w string)", "func() (u int, v int, w string)"},
+
+ dup("func(int) string"),
+ dup("func(x int) string"),
+ dup("func(x int) (u string)"),
+ {"func(x, y int) (u string)", "func(x int, y int) (u string)"},
+
+ dup("func(...int) string"),
+ dup("func(x ...int) string"),
+ dup("func(x ...int) (u string)"),
+ {"func(x, y ...int) (u string)", "func(x int, y ...int) (u string)"},
+
+ // interfaces
+ dup("interface{}"),
+ dup("interface{m()}"),
+ {`interface{
+ m(int) float32
+ String() string
+ }`, `interface{String() string; m(int) float32}`}, // methods are sorted
+ // TODO(gri) add test for interface w/ anonymous field
+
+ // maps
+ dup("map[string]int"),
+ {"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"},
+
+ // channels
+ dup("chan int"),
+ dup("chan<- func()"),
+ dup("<-chan []func() int"),
+}
+
+func TestTypes(t *testing.T) {
+ for _, test := range testTypes {
+ src := "package p; type T " + test.src
+ pkg, err := makePkg(t, src)
+ if err != nil {
+ t.Errorf("%s: %s", src, err)
+ continue
+ }
+ typ := Underlying(pkg.Scope.Lookup("T").Type.(Type))
+ str := TypeString(typ)
+ if str != test.str {
+ t.Errorf("%s: got %s, want %s", test.src, str, test.str)
+ }
+ }
+}
diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go
index 98ebfb74161..f704b7d03e8 100644
--- a/libgo/go/fmt/fmt_test.go
+++ b/libgo/go/fmt/fmt_test.go
@@ -127,6 +127,10 @@ var fmttests = []struct {
{"%s", []byte("abc"), "abc"},
{"%x", []byte("abc"), "616263"},
{"% x", []byte("abc\xff"), "61 62 63 ff"},
+ {"%#x", []byte("abc\xff"), "0x610x620x630xff"},
+ {"%#X", []byte("abc\xff"), "0X610X620X630XFF"},
+ {"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"},
+ {"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"},
{"% X", []byte("abc\xff"), "61 62 63 FF"},
{"%x", []byte("xyz"), "78797a"},
{"%X", []byte("xyz"), "78797A"},
@@ -350,10 +354,12 @@ var fmttests = []struct {
{"%+v", B{1, 2}, `{I:<1> j:2}`},
{"%+v", C{1, B{2, 3}}, `{i:1 B:{I:<2> j:3}}`},
- // q on Stringable items
+ // other formats on Stringable items
{"%s", I(23), `<23>`},
{"%q", I(23), `"<23>"`},
{"%x", I(23), `3c32333e`},
+ {"%#x", I(23), `0x3c0x320x330x3e`},
+ {"%# x", I(23), `0x3c 0x32 0x33 0x3e`},
{"%d", I(23), `23`}, // Stringer applies only to string formats.
// go syntax
@@ -375,6 +381,7 @@ var fmttests = []struct {
{"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
{"%#v", map[int]byte(nil), `map[int]uint8(nil)`},
{"%#v", map[int]byte{}, `map[int]uint8{}`},
+ {"%#v", "foo", `"foo"`},
// slices with other formats
{"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`},
@@ -441,6 +448,11 @@ var fmttests = []struct {
{"%v", (*int)(nil), "<nil>"},
{"%v", new(int), "0xPTR"},
+ // %d etc. pointers use specified base.
+ {"%d", new(int), "PTR_d"},
+ {"%o", new(int), "PTR_o"},
+ {"%x", new(int), "PTR_x"},
+
// %d on Stringer should give integer if possible
{"%s", time.Time{}.Month(), "January"},
{"%d", time.Time{}.Month(), "1"},
@@ -470,14 +482,26 @@ func TestSprintf(t *testing.T) {
for _, tt := range fmttests {
s := Sprintf(tt.fmt, tt.val)
if i := strings.Index(tt.out, "PTR"); i >= 0 {
+ pattern := "PTR"
+ chars := "0123456789abcdefABCDEF"
+ switch {
+ case strings.HasPrefix(tt.out[i:], "PTR_d"):
+ pattern = "PTR_d"
+ chars = chars[:10]
+ case strings.HasPrefix(tt.out[i:], "PTR_o"):
+ pattern = "PTR_o"
+ chars = chars[:8]
+ case strings.HasPrefix(tt.out[i:], "PTR_x"):
+ pattern = "PTR_x"
+ }
j := i
for ; j < len(s); j++ {
c := s[j]
- if (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F') {
+ if !strings.ContainsRune(chars, rune(c)) {
break
}
}
- s = s[0:i] + "PTR" + s[j:]
+ s = s[0:i] + pattern + s[j:]
}
if s != tt.out {
if _, ok := tt.val.(string); ok {
@@ -527,6 +551,14 @@ func BenchmarkSprintfFloat(b *testing.B) {
}
}
+func BenchmarkManyArgs(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world")
+ }
+}
+
var mallocBuf bytes.Buffer
// gccgo numbers are different because gccgo does not have escape
diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go
index caf900d5c30..ce801162d6e 100644
--- a/libgo/go/fmt/format.go
+++ b/libgo/go/fmt/format.go
@@ -110,11 +110,11 @@ func (f *fmt) writePadding(n int, padding []byte) {
// Append b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus)
// clear flags afterwards.
func (f *fmt) pad(b []byte) {
- var padding []byte
- var left, right int
- if f.widPresent && f.wid != 0 {
- padding, left, right = f.computePadding(len(b))
+ if !f.widPresent || f.wid == 0 {
+ f.buf.Write(b)
+ return
}
+ padding, left, right := f.computePadding(len(b))
if left > 0 {
f.writePadding(left, padding)
}
@@ -127,11 +127,11 @@ func (f *fmt) pad(b []byte) {
// append s to buf, padded on left (w > 0) or right (w < 0 or f.minus).
// clear flags afterwards.
func (f *fmt) padString(s string) {
- var padding []byte
- var left, right int
- if f.widPresent && f.wid != 0 {
- padding, left, right = f.computePadding(utf8.RuneCountInString(s))
+ if !f.widPresent || f.wid == 0 {
+ f.buf.WriteString(s)
+ return
}
+ padding, left, right := f.computePadding(utf8.RuneCountInString(s))
if left > 0 {
f.writePadding(left, padding)
}
@@ -285,18 +285,41 @@ func (f *fmt) fmt_s(s string) {
f.padString(s)
}
-// fmt_sx formats a string as a hexadecimal encoding of its bytes.
-func (f *fmt) fmt_sx(s, digits string) {
+// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
+func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
+ n := len(b)
+ if b == nil {
+ n = len(s)
+ }
+ x := digits[10] - 'a' + 'x'
// TODO: Avoid buffer by pre-padding.
- var b []byte
- for i := 0; i < len(s); i++ {
+ var buf []byte
+ for i := 0; i < n; i++ {
if i > 0 && f.space {
- b = append(b, ' ')
+ buf = append(buf, ' ')
+ }
+ if f.sharp {
+ buf = append(buf, '0', x)
+ }
+ var c byte
+ if b == nil {
+ c = s[i]
+ } else {
+ c = b[i]
}
- v := s[i]
- b = append(b, digits[v>>4], digits[v&0xF])
+ buf = append(buf, digits[c>>4], digits[c&0xF])
}
- f.pad(b)
+ f.pad(buf)
+}
+
+// fmt_sx formats a string as a hexadecimal encoding of its bytes.
+func (f *fmt) fmt_sx(s, digits string) {
+ f.fmt_sbx(s, nil, digits)
+}
+
+// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
+func (f *fmt) fmt_bx(b []byte, digits string) {
+ f.fmt_sbx("", b, digits)
}
// fmt_q formats a string as a double-quoted, escaped Go string constant.
diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go
index f29e8c8e9f1..13e58737f96 100644
--- a/libgo/go/fmt/print.go
+++ b/libgo/go/fmt/print.go
@@ -569,24 +569,27 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, depth int) {
}
return
}
- s := string(v)
switch verb {
case 's':
- p.fmt.fmt_s(s)
+ p.fmt.fmt_s(string(v))
case 'x':
- p.fmt.fmt_sx(s, ldigits)
+ p.fmt.fmt_bx(v, ldigits)
case 'X':
- p.fmt.fmt_sx(s, udigits)
+ p.fmt.fmt_bx(v, udigits)
case 'q':
- p.fmt.fmt_q(s)
+ p.fmt.fmt_q(string(v))
default:
p.badVerb(verb)
}
}
func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
+ use0x64 := true
switch verb {
- case 'p', 'v', 'b', 'd', 'o', 'x', 'X':
+ case 'p', 'v':
+ // ok
+ case 'b', 'd', 'o', 'x', 'X':
+ use0x64 = false
// ok
default:
p.badVerb(verb)
@@ -616,7 +619,11 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
} else if verb == 'v' && u == 0 {
p.buf.Write(nilAngleBytes)
} else {
- p.fmt0x64(uint64(u), !p.fmt.sharp)
+ if use0x64 {
+ p.fmt0x64(uint64(u), !p.fmt.sharp)
+ } else {
+ p.fmtUint64(uint64(u), verb, false)
+ }
}
}
@@ -735,8 +742,17 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
return false
}
- if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
- return wasString
+ // Clear flags for base formatters.
+ // handleMethods needs them, so we must restore them later.
+ // We could call handleMethods here and avoid this work, but
+ // handleMethods is expensive enough to be worth delaying.
+ oldPlus := p.fmt.plus
+ oldSharp := p.fmt.sharp
+ if plus {
+ p.fmt.plus = false
+ }
+ if goSyntax {
+ p.fmt.sharp = false
}
// Some types can be done without reflection.
@@ -780,6 +796,13 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
p.fmtBytes(f, verb, goSyntax, depth)
wasString = verb == 's'
default:
+ // Restore flags in case handleMethods finds a Formatter.
+ p.fmt.plus = oldPlus
+ p.fmt.sharp = oldSharp
+ // If the type is not simple, it might have methods.
+ if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
+ return wasString
+ }
// Need to use reflection
return p.printReflectValue(reflect.ValueOf(field), verb, plus, goSyntax, depth)
}
diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go
index 0b3e04069a0..d69911c7d72 100644
--- a/libgo/go/fmt/scan.go
+++ b/libgo/go/fmt/scan.go
@@ -1090,7 +1090,8 @@ func (s *ss) advance(format string) (i int) {
// There was space in the format, so there should be space (EOF)
// in the input.
inputc := s.getRune()
- if inputc == eof {
+ if inputc == eof || inputc == '\n' {
+ // If we've reached a newline, stop now; don't read ahead.
return
}
if !isSpace(inputc) {
diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go
index 320857b73e2..cc09e910aad 100644
--- a/libgo/go/fmt/scan_test.go
+++ b/libgo/go/fmt/scan_test.go
@@ -810,6 +810,33 @@ func TestMultiLine(t *testing.T) {
}
}
+// simpleReader is a strings.Reader that implements only Read, not ReadRune.
+// Good for testing readahead.
+type simpleReader struct {
+ sr *strings.Reader
+}
+
+func (s *simpleReader) Read(b []byte) (n int, err error) {
+ return s.sr.Read(b)
+}
+
+// Test that Fscanf does not read past newline. Issue 3481.
+func TestLineByLineFscanf(t *testing.T) {
+ r := &simpleReader{strings.NewReader("1\n2\n")}
+ var i, j int
+ n, err := Fscanf(r, "%v\n", &i)
+ if n != 1 || err != nil {
+ t.Fatalf("first read: %d %q", n, err)
+ }
+ n, err = Fscanf(r, "%v\n", &j)
+ if n != 1 || err != nil {
+ t.Fatalf("second read: %d %q", n, err)
+ }
+ if i != 1 || j != 2 {
+ t.Errorf("wrong values; wanted 1 2 got %d %d", i, j)
+ }
+}
+
// RecursiveInt accepts a string matching %d.%d.%d....
// and parses it into a linked list.
// It allows us to benchmark recursive descent style scanners.
diff --git a/libgo/go/go/ast/ast.go b/libgo/go/go/ast/ast.go
index d2e75dc1c03..e1582c30064 100644
--- a/libgo/go/go/ast/ast.go
+++ b/libgo/go/go/ast/ast.go
@@ -407,6 +407,7 @@ type (
// A ChanType node represents a channel type.
ChanType struct {
Begin token.Pos // position of "chan" keyword or "<-" (whichever comes first)
+ Arrow token.Pos // position of "<-" (noPos if there is no "<-")
Dir ChanDir // channel direction
Value Expr // value type
}
diff --git a/libgo/go/go/ast/commentmap.go b/libgo/go/go/ast/commentmap.go
new file mode 100644
index 00000000000..201c9485603
--- /dev/null
+++ b/libgo/go/go/ast/commentmap.go
@@ -0,0 +1,332 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ast
+
+import (
+ "bytes"
+ "fmt"
+ "go/token"
+ "sort"
+)
+
+type byPos []*CommentGroup
+
+func (a byPos) Len() int { return len(a) }
+func (a byPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
+func (a byPos) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+// sortComments sorts the list of comment groups in source order.
+//
+func sortComments(list []*CommentGroup) {
+ // TODO(gri): Does it make sense to check for sorted-ness
+ // first (because we know that sorted-ness is
+ // very likely)?
+ if orderedList := byPos(list); !sort.IsSorted(orderedList) {
+ sort.Sort(orderedList)
+ }
+}
+
+// A CommentMap maps an AST node to a list of comment groups
+// associated with it. See NewCommentMap for a description of
+// the association.
+//
+type CommentMap map[Node][]*CommentGroup
+
+func (cmap CommentMap) addComment(n Node, c *CommentGroup) {
+ list := cmap[n]
+ if len(list) == 0 {
+ list = []*CommentGroup{c}
+ } else {
+ list = append(list, c)
+ }
+ cmap[n] = list
+}
+
+type byInterval []Node
+
+func (a byInterval) Len() int { return len(a) }
+func (a byInterval) Less(i, j int) bool {
+ pi, pj := a[i].Pos(), a[j].Pos()
+ return pi < pj || pi == pj && a[i].End() > a[j].End()
+}
+func (a byInterval) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+// nodeList returns the list of nodes of the AST n in source order.
+//
+func nodeList(n Node) []Node {
+ var list []Node
+ Inspect(n, func(n Node) bool {
+ // don't collect comments
+ switch n.(type) {
+ case nil, *CommentGroup, *Comment:
+ return false
+ }
+ list = append(list, n)
+ return true
+ })
+ // Note: The current implementation assumes that Inspect traverses the
+ // AST in depth-first and thus _source_ order. If AST traversal
+ // does not follow source order, the sorting call below will be
+ // required.
+ // sort.Sort(byInterval(list))
+ return list
+}
+
+// A commentListReader helps iterating through a list of comment groups.
+//
+type commentListReader struct {
+ fset *token.FileSet
+ list []*CommentGroup
+ index int
+ comment *CommentGroup // comment group at current index
+ pos, end token.Position // source interval of comment group at current index
+}
+
+func (r *commentListReader) eol() bool {
+ return r.index >= len(r.list)
+}
+
+func (r *commentListReader) next() {
+ if !r.eol() {
+ r.comment = r.list[r.index]
+ r.pos = r.fset.Position(r.comment.Pos())
+ r.end = r.fset.Position(r.comment.End())
+ r.index++
+ }
+}
+
+// A nodeStack keeps track of nested nodes.
+// A node lower on the stack lexically contains the nodes higher on the stack.
+//
+type nodeStack []Node
+
+// push pops all nodes that appear lexically before n
+// and then pushes n on the stack.
+//
+func (s *nodeStack) push(n Node) {
+ s.pop(n.Pos())
+ *s = append((*s), n)
+}
+
+// pop pops all nodes that appear lexically before pos
+// (i.e., whose lexical extent has ended before or at pos).
+// It returns the last node popped.
+//
+func (s *nodeStack) pop(pos token.Pos) (top Node) {
+ i := len(*s)
+ for i > 0 && (*s)[i-1].End() <= pos {
+ top = (*s)[i-1]
+ i--
+ }
+ *s = (*s)[0:i]
+ return top
+}
+
+// NewCommentMap creates a new comment map by associating comment groups
+// of the comments list with the nodes of the AST specified by node.
+//
+// A comment group g is associated with a node n if:
+//
+// - g starts on the same line as n ends
+// - g starts on the line immediately following n, and there is
+// at least one empty line after g and before the next node
+// - g starts before n and is not associated to the node before n
+// via the previous rules
+//
+// NewCommentMap tries to associate a comment group to the "largest"
+// node possible: For instance, if the comment is a line comment
+// trailing an assignment, the comment is associated with the entire
+// assignment rather than just the last operand in the assignment.
+//
+func NewCommentMap(fset *token.FileSet, node Node, comments []*CommentGroup) CommentMap {
+ if len(comments) == 0 {
+ return nil // no comments to map
+ }
+
+ cmap := make(CommentMap)
+
+ // set up comment reader r
+ tmp := make([]*CommentGroup, len(comments))
+ copy(tmp, comments) // don't change incomming comments
+ sortComments(tmp)
+ r := commentListReader{fset: fset, list: tmp} // !r.eol() because len(comments) > 0
+ r.next()
+
+ // create node list in lexical order
+ nodes := nodeList(node)
+ nodes = append(nodes, nil) // append sentinel
+
+ // set up iteration variables
+ var (
+ p Node // previous node
+ pend token.Position // end of p
+ pg Node // previous node group (enclosing nodes of "importance")
+ pgend token.Position // end of pg
+ stack nodeStack // stack of node groups
+ )
+
+ for _, q := range nodes {
+ var qpos token.Position
+ if q != nil {
+ qpos = fset.Position(q.Pos()) // current node position
+ } else {
+ // set fake sentinel position to infinity so that
+ // all comments get processed before the sentinel
+ const infinity = 1 << 30
+ qpos.Offset = infinity
+ qpos.Line = infinity
+ }
+
+ // process comments before current node
+ for r.end.Offset <= qpos.Offset {
+ // determine recent node group
+ if top := stack.pop(r.comment.Pos()); top != nil {
+ pg = top
+ pgend = fset.Position(pg.End())
+ }
+ // Try to associate a comment first with a node group
+ // (i.e., a node of "importance" such as a declaration);
+ // if that fails, try to associate it with the most recent
+ // node.
+ // TODO(gri) try to simplify the logic below
+ var assoc Node
+ switch {
+ case pg != nil &&
+ (pgend.Line == r.pos.Line ||
+ pgend.Line+1 == r.pos.Line && r.end.Line+1 < qpos.Line):
+ // 1) comment starts on same line as previous node group ends, or
+ // 2) comment starts on the line immediately after the
+ // previous node group and there is an empty line before
+ // the current node
+ // => associate comment with previous node group
+ assoc = pg
+ case p != nil &&
+ (pend.Line == r.pos.Line ||
+ pend.Line+1 == r.pos.Line && r.end.Line+1 < qpos.Line ||
+ q == nil):
+ // same rules apply as above for p rather than pg,
+ // but also associate with p if we are at the end (q == nil)
+ assoc = p
+ default:
+ // otherwise, associate comment with current node
+ if q == nil {
+ // we can only reach here if there was no p
+ // which would imply that there were no nodes
+ panic("internal error: no comments should be associated with sentinel")
+ }
+ assoc = q
+ }
+ cmap.addComment(assoc, r.comment)
+ if r.eol() {
+ return cmap
+ }
+ r.next()
+ }
+
+ // update previous node
+ p = q
+ pend = fset.Position(p.End())
+
+ // update previous node group if we see an "important" node
+ switch q.(type) {
+ case *File, *Field, Decl, Spec, Stmt:
+ stack.push(q)
+ }
+ }
+
+ return cmap
+}
+
+// Update replaces an old node in the comment map with the new node
+// and returns the new node. Comments that were associated with the
+// old node are associated with the new node.
+//
+func (cmap CommentMap) Update(old, new Node) Node {
+ if list := cmap[old]; len(list) > 0 {
+ delete(cmap, old)
+ cmap[new] = append(cmap[new], list...)
+ }
+ return new
+}
+
+// Filter returns a new comment map consisting of only those
+// entries of cmap for which a corresponding node exists in
+// the AST specified by node.
+//
+func (cmap CommentMap) Filter(node Node) CommentMap {
+ umap := make(CommentMap)
+ Inspect(node, func(n Node) bool {
+ if g := cmap[n]; len(g) > 0 {
+ umap[n] = g
+ }
+ return true
+ })
+ return umap
+}
+
+// Comments returns the list of comment groups in the comment map.
+// The result is sorted is source order.
+//
+func (cmap CommentMap) Comments() []*CommentGroup {
+ list := make([]*CommentGroup, 0, len(cmap))
+ for _, e := range cmap {
+ list = append(list, e...)
+ }
+ sortComments(list)
+ return list
+}
+
+func summary(list []*CommentGroup) string {
+ const maxLen = 40
+ var buf bytes.Buffer
+
+ // collect comments text
+loop:
+ for _, group := range list {
+ // Note: CommentGroup.Text() does too much work for what we
+ // need and would only replace this innermost loop.
+ // Just do it explicitly.
+ for _, comment := range group.List {
+ if buf.Len() >= maxLen {
+ break loop
+ }
+ buf.WriteString(comment.Text)
+ }
+ }
+
+ // truncate if too long
+ if buf.Len() > maxLen {
+ buf.Truncate(maxLen - 3)
+ buf.WriteString("...")
+ }
+
+ // replace any invisibles with blanks
+ bytes := buf.Bytes()
+ for i, b := range bytes {
+ switch b {
+ case '\t', '\n', '\r':
+ bytes[i] = ' '
+ }
+ }
+
+ return string(bytes)
+}
+
+func (cmap CommentMap) String() string {
+ var buf bytes.Buffer
+ fmt.Fprintln(&buf, "CommentMap {")
+ for node, comment := range cmap {
+ // print name of identifiers; print node type for other nodes
+ var s string
+ if ident, ok := node.(*Ident); ok {
+ s = ident.Name
+ } else {
+ s = fmt.Sprintf("%T", node)
+ }
+ fmt.Fprintf(&buf, "\t%p %20s: %s\n", node, s, summary(comment))
+ }
+ fmt.Fprintln(&buf, "}")
+ return buf.String()
+}
diff --git a/libgo/go/go/ast/commentmap_test.go b/libgo/go/go/ast/commentmap_test.go
new file mode 100644
index 00000000000..e372eab745b
--- /dev/null
+++ b/libgo/go/go/ast/commentmap_test.go
@@ -0,0 +1,143 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// To avoid a cyclic dependency with go/parser, this file is in a separate package.
+
+package ast_test
+
+import (
+ "bytes"
+ "fmt"
+ . "go/ast"
+ "go/parser"
+ "go/token"
+ "sort"
+ "testing"
+)
+
+const src = `
+// the very first comment
+
+// package p
+package p /* the name is p */
+
+// imports
+import (
+ "bytes" // bytes
+ "fmt" // fmt
+ "go/ast"
+ "go/parser"
+)
+
+// T
+type T struct {
+ a, b, c int // associated with a, b, c
+ // associated with x, y
+ x, y float64 // float values
+ z complex128 // complex value
+}
+// also associated with T
+
+// x
+var x = 0 // x = 0
+// also associated with x
+
+// f1
+func f1() {
+ /* associated with s1 */
+ s1()
+ // also associated with s1
+
+ // associated with s2
+
+ // also associated with s2
+ s2() // line comment for s2
+}
+// associated with f1
+// also associated with f1
+
+// associated with f2
+
+// f2
+func f2() {
+}
+
+func f3() {
+ i := 1 /* 1 */ + 2 // addition
+ _ = i
+}
+
+// the very last comment
+`
+
+// res maps a key of the form "line number: node type"
+// to the associated comments' text.
+//
+var res = map[string]string{
+ " 5: *ast.File": "the very first comment\npackage p\n",
+ " 5: *ast.Ident": " the name is p\n",
+ " 8: *ast.GenDecl": "imports\n",
+ " 9: *ast.ImportSpec": "bytes\n",
+ "10: *ast.ImportSpec": "fmt\n",
+ "16: *ast.GenDecl": "T\nalso associated with T\n",
+ "17: *ast.Field": "associated with a, b, c\n",
+ "19: *ast.Field": "associated with x, y\nfloat values\n",
+ "20: *ast.Field": "complex value\n",
+ "25: *ast.GenDecl": "x\nx = 0\nalso associated with x\n",
+ "29: *ast.FuncDecl": "f1\nassociated with f1\nalso associated with f1\n",
+ "31: *ast.ExprStmt": " associated with s1\nalso associated with s1\n",
+ "37: *ast.ExprStmt": "associated with s2\nalso associated with s2\nline comment for s2\n",
+ "45: *ast.FuncDecl": "associated with f2\nf2\n",
+ "49: *ast.AssignStmt": "addition\n",
+ "49: *ast.BasicLit": " 1\n",
+ "50: *ast.Ident": "the very last comment\n",
+}
+
+func ctext(list []*CommentGroup) string {
+ var buf bytes.Buffer
+ for _, g := range list {
+ buf.WriteString(g.Text())
+ }
+ return buf.String()
+}
+
+func TestCommentMap(t *testing.T) {
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
+ if err != nil {
+ t.Fatal(err)
+ }
+ cmap := NewCommentMap(fset, f, f.Comments)
+
+ // very correct association of comments
+ for n, list := range cmap {
+ key := fmt.Sprintf("%2d: %T", fset.Position(n.Pos()).Line, n)
+ got := ctext(list)
+ want := res[key]
+ if got != want {
+ t.Errorf("%s: got %q; want %q", key, got, want)
+ }
+ }
+
+ // verify that no comments got lost
+ if n := len(cmap.Comments()); n != len(f.Comments) {
+ t.Errorf("got %d comment groups in map; want %d", n, len(f.Comments))
+ }
+
+ // support code to update test:
+ // set genMap to true to generate res map
+ const genMap = false
+ if genMap {
+ out := make([]string, 0, len(cmap))
+ for n, list := range cmap {
+ out = append(out, fmt.Sprintf("\t\"%2d: %T\":\t%q,", fset.Position(n.Pos()).Line, n, ctext(list)))
+ }
+ sort.Strings(out)
+ for _, s := range out {
+ fmt.Println(s)
+ }
+ }
+}
+
+// TODO(gri): add tests for Filter.
diff --git a/libgo/go/go/ast/print.go b/libgo/go/go/ast/print.go
index 2de9af299e5..4a1ce480f42 100644
--- a/libgo/go/go/ast/print.go
+++ b/libgo/go/go/ast/print.go
@@ -108,8 +108,10 @@ func (p *printer) Write(data []byte) (n int, err error) {
}
p.last = b
}
- m, err = p.output.Write(data[n:])
- n += m
+ if len(data) > n {
+ m, err = p.output.Write(data[n:])
+ n += m
+ }
return
}
diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go
index 67e73c5e4a4..b8b1c13b5b8 100644
--- a/libgo/go/go/build/build.go
+++ b/libgo/go/go/build/build.go
@@ -33,6 +33,7 @@ type Context struct {
GOPATH string // Go path
CgoEnabled bool // whether cgo can be used
BuildTags []string // additional tags to recognize in +build lines
+ InstallTag string // package install directory suffix
UseAllFiles bool // use files regardless of +build lines, file names
Compiler string // compiler to assume when computing target paths
@@ -213,10 +214,13 @@ var Default Context = defaultContext()
var cgoEnabled = map[string]bool{
"darwin/386": true,
"darwin/amd64": true,
- "linux/386": true,
- "linux/amd64": true,
"freebsd/386": true,
"freebsd/amd64": true,
+ "linux/386": true,
+ "linux/amd64": true,
+ "linux/arm": true,
+ "netbsd/386": true,
+ "netbsd/amd64": true,
"windows/386": true,
"windows/amd64": true,
}
@@ -278,12 +282,14 @@ type Package struct {
PkgObj string // installed .a file
// Source files
- GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
- CgoFiles []string // .go source files that import "C"
- CFiles []string // .c source files
- HFiles []string // .h source files
- SFiles []string // .s source files
- SysoFiles []string // .syso system object files to add to archive
+ GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+ CgoFiles []string // .go source files that import "C"
+ CFiles []string // .c source files
+ HFiles []string // .h source files
+ SFiles []string // .s source files
+ SysoFiles []string // .syso system object files to add to archive
+ SwigFiles []string // .swig files
+ SwigCXXFiles []string // .swigcxx files
// Cgo directives
CgoPkgConfig []string // Cgo pkg-config directives
@@ -346,6 +352,9 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
p := &Package{
ImportPath: path,
}
+ if path == "" {
+ return p, fmt.Errorf("import %q: invalid import path", path)
+ }
var pkga string
var pkgerr error
@@ -354,7 +363,11 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
dir, elem := pathpkg.Split(p.ImportPath)
pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a"
case "gc":
- pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + p.ImportPath + ".a"
+ tag := ""
+ if ctxt.InstallTag != "" {
+ tag = "_" + ctxt.InstallTag
+ }
+ pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + tag + "/" + p.ImportPath + ".a"
default:
// Save error for end of function.
pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)
@@ -486,7 +499,7 @@ Found:
}
ext := name[i:]
switch ext {
- case ".go", ".c", ".s", ".h", ".S":
+ case ".go", ".c", ".s", ".h", ".S", ".swig", ".swigcxx":
// tentatively okay - read to make sure
case ".syso":
// binary objects to add to package archive
@@ -504,7 +517,13 @@ Found:
if err != nil {
return p, err
}
- data, err := ioutil.ReadAll(f)
+
+ var data []byte
+ if strings.HasSuffix(filename, ".go") {
+ data, err = readImports(f, false)
+ } else {
+ data, err = readComments(f)
+ }
f.Close()
if err != nil {
return p, fmt.Errorf("read %s: %v", filename, err)
@@ -529,6 +548,12 @@ Found:
case ".S":
Sfiles = append(Sfiles, name)
continue
+ case ".swig":
+ p.SwigFiles = append(p.SwigFiles, name)
+ continue
+ case ".swigcxx":
+ p.SwigCXXFiles = append(p.SwigCXXFiles, name)
+ continue
}
pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments)
diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go
index caa4f26f332..d8cf98840d7 100644
--- a/libgo/go/go/build/build_test.go
+++ b/libgo/go/go/build/build_test.go
@@ -61,6 +61,19 @@ func TestDotSlashImport(t *testing.T) {
}
}
+func TestEmptyImport(t *testing.T) {
+ p, err := Import("", Default.GOROOT, FindOnly)
+ if err == nil {
+ t.Fatal(`Import("") returned nil error.`)
+ }
+ if p == nil {
+ t.Fatal(`Import("") returned nil package.`)
+ }
+ if p.ImportPath != "" {
+ t.Fatalf("ImportPath=%q, want %q.", p.ImportPath, "")
+ }
+}
+
func TestLocalDirectory(t *testing.T) {
cwd, err := os.Getwd()
if err != nil {
diff --git a/libgo/go/go/build/deps_test.go b/libgo/go/go/build/deps_test.go
index 4e9f32a036f..efed739dd21 100644
--- a/libgo/go/go/build/deps_test.go
+++ b/libgo/go/go/build/deps_test.go
@@ -30,7 +30,7 @@ var pkgDeps = map[string][]string{
"errors": {},
"io": {"errors", "sync"},
"runtime": {"unsafe"},
- "sync": {"sync/atomic"},
+ "sync": {"sync/atomic", "unsafe"},
"sync/atomic": {"unsafe"},
"unsafe": {},
@@ -177,7 +177,7 @@ var pkgDeps = map[string][]string{
},
// One of a kind.
- "archive/tar": {"L4", "OS"},
+ "archive/tar": {"L4", "OS", "syscall"},
"archive/zip": {"L4", "OS", "compress/flate"},
"compress/bzip2": {"L4"},
"compress/flate": {"L4"},
@@ -300,7 +300,10 @@ var pkgDeps = map[string][]string{
"L4", "CRYPTO-MATH", "CGO", "OS",
"crypto/x509", "encoding/pem", "net", "syscall",
},
- "crypto/x509": {"L4", "CRYPTO-MATH", "OS", "CGO", "crypto/x509/pkix", "encoding/pem", "syscall"},
+ "crypto/x509": {
+ "L4", "CRYPTO-MATH", "OS", "CGO",
+ "crypto/x509/pkix", "encoding/pem", "encoding/hex", "syscall",
+ },
"crypto/x509/pkix": {"L4", "CRYPTO-MATH"},
// Simple net+crypto-aware packages.
diff --git a/libgo/go/go/build/doc.go b/libgo/go/go/build/doc.go
index 9b7a946f2b8..04e48c1547b 100644
--- a/libgo/go/go/build/doc.go
+++ b/libgo/go/go/build/doc.go
@@ -100,7 +100,7 @@
// default functionality for other systems, which in this case would
// carry the constraint:
//
-// // +build !linux !darwin !cgo
+// // +build !linux,!darwin !cgo
//
// Naming a file dns_windows.go will cause it to be included only when
// building the package for Windows; similarly, math_386.s will be included
diff --git a/libgo/go/go/build/read.go b/libgo/go/go/build/read.go
new file mode 100644
index 00000000000..c8079dfd15d
--- /dev/null
+++ b/libgo/go/go/build/read.go
@@ -0,0 +1,238 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "bufio"
+ "errors"
+ "io"
+)
+
+type importReader struct {
+ b *bufio.Reader
+ buf []byte
+ peek byte
+ err error
+ eof bool
+ nerr int
+}
+
+func isIdent(c byte) bool {
+ return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= 0x80
+}
+
+var (
+ errSyntax = errors.New("syntax error")
+ errNUL = errors.New("unexpected NUL in input")
+)
+
+// syntaxError records a syntax error, but only if an I/O error has not already been recorded.
+func (r *importReader) syntaxError() {
+ if r.err == nil {
+ r.err = errSyntax
+ }
+}
+
+// readByte reads the next byte from the input, saves it in buf, and returns it.
+// If an error occurs, readByte records the error in r.err and returns 0.
+func (r *importReader) readByte() byte {
+ c, err := r.b.ReadByte()
+ if err == nil {
+ r.buf = append(r.buf, c)
+ if c == 0 {
+ err = errNUL
+ }
+ }
+ if err != nil {
+ if err == io.EOF {
+ r.eof = true
+ } else if r.err == nil {
+ r.err = err
+ }
+ c = 0
+ }
+ return c
+}
+
+// peekByte returns the next byte from the input reader but does not advance beyond it.
+// If skipSpace is set, peekByte skips leading spaces and comments.
+func (r *importReader) peekByte(skipSpace bool) byte {
+ if r.err != nil {
+ if r.nerr++; r.nerr > 10000 {
+ panic("go/build: import reader looping")
+ }
+ return 0
+ }
+
+ // Use r.peek as first input byte.
+ // Don't just return r.peek here: it might have been left by peekByte(false)
+ // and this might be peekByte(true).
+ c := r.peek
+ if c == 0 {
+ c = r.readByte()
+ }
+ for r.err == nil && !r.eof {
+ if skipSpace {
+ // For the purposes of this reader, semicolons are never necessary to
+ // understand the input and are treated as spaces.
+ switch c {
+ case ' ', '\f', '\t', '\r', '\n', ';':
+ c = r.readByte()
+ continue
+
+ case '/':
+ c = r.readByte()
+ if c == '/' {
+ for c != '\n' && r.err == nil && !r.eof {
+ c = r.readByte()
+ }
+ } else if c == '*' {
+ var c1 byte
+ for (c != '*' || c1 != '/') && r.err == nil {
+ if r.eof {
+ r.syntaxError()
+ }
+ c, c1 = c1, r.readByte()
+ }
+ } else {
+ r.syntaxError()
+ }
+ c = r.readByte()
+ continue
+ }
+ }
+ break
+ }
+ r.peek = c
+ return r.peek
+}
+
+// nextByte is like peekByte but advances beyond the returned byte.
+func (r *importReader) nextByte(skipSpace bool) byte {
+ c := r.peekByte(skipSpace)
+ r.peek = 0
+ return c
+}
+
+// readKeyword reads the given keyword from the input.
+// If the keyword is not present, readKeyword records a syntax error.
+func (r *importReader) readKeyword(kw string) {
+ r.peekByte(true)
+ for i := 0; i < len(kw); i++ {
+ if r.nextByte(false) != kw[i] {
+ r.syntaxError()
+ return
+ }
+ }
+ if isIdent(r.peekByte(false)) {
+ r.syntaxError()
+ }
+}
+
+// readIdent reads an identifier from the input.
+// If an identifier is not present, readIdent records a syntax error.
+func (r *importReader) readIdent() {
+ c := r.peekByte(true)
+ if !isIdent(c) {
+ r.syntaxError()
+ return
+ }
+ for isIdent(r.peekByte(false)) {
+ r.peek = 0
+ }
+}
+
+// readString reads a quoted string literal from the input.
+// If an identifier is not present, readString records a syntax error.
+func (r *importReader) readString() {
+ switch r.nextByte(true) {
+ case '`':
+ for r.err == nil {
+ if r.nextByte(false) == '`' {
+ break
+ }
+ if r.eof {
+ r.syntaxError()
+ }
+ }
+ case '"':
+ for r.err == nil {
+ c := r.nextByte(false)
+ if c == '"' {
+ break
+ }
+ if r.eof || c == '\n' {
+ r.syntaxError()
+ }
+ if c == '\\' {
+ r.nextByte(false)
+ }
+ }
+ default:
+ r.syntaxError()
+ }
+}
+
+// readImport reads an import clause - optional identifier followed by quoted string -
+// from the input.
+func (r *importReader) readImport() {
+ c := r.peekByte(true)
+ if c == '.' {
+ r.peek = 0
+ } else if isIdent(c) {
+ r.readIdent()
+ }
+ r.readString()
+}
+
+// readComments is like ioutil.ReadAll, except that it only reads the leading
+// block of comments in the file.
+func readComments(f io.Reader) ([]byte, error) {
+ r := &importReader{b: bufio.NewReader(f)}
+ r.peekByte(true)
+ if r.err == nil && !r.eof {
+ // Didn't reach EOF, so must have found a non-space byte. Remove it.
+ r.buf = r.buf[:len(r.buf)-1]
+ }
+ return r.buf, r.err
+}
+
+// readImports is like ioutil.ReadAll, except that it expects a Go file as input
+// and stops reading the input once the imports have completed.
+func readImports(f io.Reader, reportSyntaxError bool) ([]byte, error) {
+ r := &importReader{b: bufio.NewReader(f)}
+
+ r.readKeyword("package")
+ r.readIdent()
+ for r.peekByte(true) == 'i' {
+ r.readKeyword("import")
+ if r.peekByte(true) == '(' {
+ r.nextByte(false)
+ for r.peekByte(true) != ')' && r.err == nil {
+ r.readImport()
+ }
+ r.nextByte(false)
+ } else {
+ r.readImport()
+ }
+ }
+
+ // If we stopped successfully before EOF, we read a byte that told us we were done.
+ // Return all but that last byte, which would cause a syntax error if we let it through.
+ if r.err == nil && !r.eof {
+ return r.buf[:len(r.buf)-1], nil
+ }
+
+ // If we stopped for a syntax error, consume the whole file so that
+ // we are sure we don't change the errors that go/parser returns.
+ if r.err == errSyntax && !reportSyntaxError {
+ r.err = nil
+ for r.err == nil && !r.eof {
+ r.readByte()
+ }
+ }
+
+ return r.buf, r.err
+}
diff --git a/libgo/go/go/build/read_test.go b/libgo/go/go/build/read_test.go
new file mode 100644
index 00000000000..2dcc1208f71
--- /dev/null
+++ b/libgo/go/go/build/read_test.go
@@ -0,0 +1,226 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package build
+
+import (
+ "io"
+ "strings"
+ "testing"
+)
+
+const quote = "`"
+
+type readTest struct {
+ // Test input contains ℙ where readImports should stop.
+ in string
+ err string
+}
+
+var readImportsTests = []readTest{
+ {
+ `package p`,
+ "",
+ },
+ {
+ `package p; import "x"`,
+ "",
+ },
+ {
+ `package p; import . "x"`,
+ "",
+ },
+ {
+ `package p; import "x";ℙvar x = 1`,
+ "",
+ },
+ {
+ `package p
+
+ // comment
+
+ import "x"
+ import _ "x"
+ import a "x"
+
+ /* comment */
+
+ import (
+ "x" /* comment */
+ _ "x"
+ a "x" // comment
+ ` + quote + `x` + quote + `
+ _ /*comment*/ ` + quote + `x` + quote + `
+ a ` + quote + `x` + quote + `
+ )
+ import (
+ )
+ import ()
+ import()import()import()
+ import();import();import()
+
+ ℙvar x = 1
+ `,
+ "",
+ },
+}
+
+var readCommentsTests = []readTest{
+ {
+ `ℙpackage p`,
+ "",
+ },
+ {
+ `ℙpackage p; import "x"`,
+ "",
+ },
+ {
+ `ℙpackage p; import . "x"`,
+ "",
+ },
+ {
+ `// foo
+
+ /* bar */
+
+ /* quux */ // baz
+
+ /*/ zot */
+
+ // asdf
+ ℙHello, world`,
+ "",
+ },
+}
+
+func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) {
+ for i, tt := range tests {
+ var in, testOut string
+ j := strings.Index(tt.in, "ℙ")
+ if j < 0 {
+ in = tt.in
+ testOut = tt.in
+ } else {
+ in = tt.in[:j] + tt.in[j+len("ℙ"):]
+ testOut = tt.in[:j]
+ }
+ r := strings.NewReader(in)
+ buf, err := read(r)
+ if err != nil {
+ if tt.err == "" {
+ t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf))
+ continue
+ }
+ if !strings.Contains(err.Error(), tt.err) {
+ t.Errorf("#%d: err=%q, expected %q", i, err, tt.err)
+ continue
+ }
+ continue
+ }
+ if err == nil && tt.err != "" {
+ t.Errorf("#%d: success, expected %q", i, tt.err)
+ continue
+ }
+
+ out := string(buf)
+ if out != testOut {
+ t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut)
+ }
+ }
+}
+
+func TestReadImports(t *testing.T) {
+ testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return readImports(r, true) })
+}
+
+func TestReadComments(t *testing.T) {
+ testRead(t, readCommentsTests, readComments)
+}
+
+var readFailuresTests = []readTest{
+ {
+ `package`,
+ "syntax error",
+ },
+ {
+ "package p\n\x00\nimport `math`\n",
+ "unexpected NUL in input",
+ },
+ {
+ `package p; import`,
+ "syntax error",
+ },
+ {
+ `package p; import "`,
+ "syntax error",
+ },
+ {
+ "package p; import ` \n\n",
+ "syntax error",
+ },
+ {
+ `package p; import "x`,
+ "syntax error",
+ },
+ {
+ `package p; import _`,
+ "syntax error",
+ },
+ {
+ `package p; import _ "`,
+ "syntax error",
+ },
+ {
+ `package p; import _ "x`,
+ "syntax error",
+ },
+ {
+ `package p; import .`,
+ "syntax error",
+ },
+ {
+ `package p; import . "`,
+ "syntax error",
+ },
+ {
+ `package p; import . "x`,
+ "syntax error",
+ },
+ {
+ `package p; import (`,
+ "syntax error",
+ },
+ {
+ `package p; import ("`,
+ "syntax error",
+ },
+ {
+ `package p; import ("x`,
+ "syntax error",
+ },
+ {
+ `package p; import ("x"`,
+ "syntax error",
+ },
+}
+
+func TestReadFailures(t *testing.T) {
+ // Errors should be reported (true arg to readImports).
+ testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return readImports(r, true) })
+}
+
+func TestReadFailuresIgnored(t *testing.T) {
+ // Syntax errors should not be reported (false arg to readImports).
+ // Instead, entire file should be the output and no error.
+ // Convert tests not to return syntax errors.
+ tests := make([]readTest, len(readFailuresTests))
+ copy(tests, readFailuresTests)
+ for i := range tests {
+ tt := &tests[i]
+ if !strings.Contains(tt.err, "NUL") {
+ tt.err = ""
+ }
+ }
+ testRead(t, tests, func(r io.Reader) ([]byte, error) { return readImports(r, false) })
+}
diff --git a/libgo/go/go/doc/example.go b/libgo/go/go/doc/example.go
index a7e0e250a2e..79053b9a735 100644
--- a/libgo/go/go/doc/example.go
+++ b/libgo/go/go/doc/example.go
@@ -9,8 +9,10 @@ package doc
import (
"go/ast"
"go/token"
+ "path"
"regexp"
"sort"
+ "strconv"
"strings"
"unicode"
"unicode/utf8"
@@ -20,6 +22,7 @@ type Example struct {
Name string // name of the item being exemplified
Doc string // example function doc string
Code ast.Node
+ Play *ast.File // a whole program version of the example
Comments []*ast.CommentGroup
Output string // expected output
}
@@ -56,8 +59,9 @@ func Examples(files ...*ast.File) []*Example {
Name: name[len("Example"):],
Doc: doc,
Code: f.Body,
+ Play: playExample(file, f.Body),
Comments: file.Comments,
- Output: exampleOutput(f, file.Comments),
+ Output: exampleOutput(f.Body, file.Comments),
})
}
if !hasTests && numDecl > 1 && len(flist) == 1 {
@@ -65,6 +69,7 @@ func Examples(files ...*ast.File) []*Example {
// other top-level declarations, and no tests or
// benchmarks, use the whole file as the example.
flist[0].Code = file
+ flist[0].Play = playExampleFile(file)
}
list = append(list, flist...)
}
@@ -74,19 +79,8 @@ func Examples(files ...*ast.File) []*Example {
var outputPrefix = regexp.MustCompile(`(?i)^[[:space:]]*output:`)
-func exampleOutput(fun *ast.FuncDecl, comments []*ast.CommentGroup) string {
- // find the last comment in the function
- var last *ast.CommentGroup
- for _, cg := range comments {
- if cg.Pos() < fun.Pos() {
- continue
- }
- if cg.End() > fun.End() {
- break
- }
- last = cg
- }
- if last != nil {
+func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) string {
+ if _, last := lastComment(b, comments); last != nil {
// test that it begins with the correct prefix
text := last.Text()
if loc := outputPrefix.FindStringIndex(text); loc != nil {
@@ -115,3 +109,172 @@ type exampleByName []*Example
func (s exampleByName) Len() int { return len(s) }
func (s exampleByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s exampleByName) Less(i, j int) bool { return s[i].Name < s[j].Name }
+
+// playExample synthesizes a new *ast.File based on the provided
+// file with the provided function body as the body of main.
+func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
+ if !strings.HasSuffix(file.Name.Name, "_test") {
+ // We don't support examples that are part of the
+ // greater package (yet).
+ return nil
+ }
+
+ // Find unresolved identifiers
+ unresolved := make(map[string]bool)
+ ast.Inspect(body, func(n ast.Node) bool {
+ // For an expression like fmt.Println, only add "fmt" to the
+ // set of unresolved names.
+ if e, ok := n.(*ast.SelectorExpr); ok {
+ if id, ok := e.X.(*ast.Ident); ok && id.Obj == nil {
+ unresolved[id.Name] = true
+ }
+ return false
+ }
+ if id, ok := n.(*ast.Ident); ok && id.Obj == nil {
+ unresolved[id.Name] = true
+ }
+ return true
+ })
+
+ // Remove predeclared identifiers from unresolved list.
+ for n := range unresolved {
+ if predeclaredTypes[n] || predeclaredConstants[n] || predeclaredFuncs[n] {
+ delete(unresolved, n)
+ }
+ }
+
+ // Use unresolved identifiers to determine the imports used by this
+ // example. The heuristic assumes package names match base import
+ // paths. (Should be good enough most of the time.)
+ imports := make(map[string]string) // [name]path
+ for _, s := range file.Imports {
+ p, err := strconv.Unquote(s.Path.Value)
+ if err != nil {
+ continue
+ }
+ n := path.Base(p)
+ if s.Name != nil {
+ if s.Name.Name == "." {
+ // We can't resolve dot imports (yet).
+ return nil
+ }
+ n = s.Name.Name
+ }
+ if unresolved[n] {
+ imports[n] = p
+ delete(unresolved, n)
+ }
+ }
+
+ // If there are other unresolved identifiers, give up because this
+ // synthesized file is not going to build.
+ if len(unresolved) > 0 {
+ return nil
+ }
+
+ // Filter out comments that are outside the function body.
+ var comments []*ast.CommentGroup
+ for _, c := range file.Comments {
+ if c.Pos() < body.Pos() || c.Pos() >= body.End() {
+ continue
+ }
+ comments = append(comments, c)
+ }
+
+ // Strip "Output:" commment and adjust body end position.
+ body, comments = stripOutputComment(body, comments)
+
+ // Synthesize import declaration.
+ importDecl := &ast.GenDecl{
+ Tok: token.IMPORT,
+ Lparen: 1, // Need non-zero Lparen and Rparen so that printer
+ Rparen: 1, // treats this as a factored import.
+ }
+ for n, p := range imports {
+ s := &ast.ImportSpec{Path: &ast.BasicLit{Value: strconv.Quote(p)}}
+ if path.Base(p) != n {
+ s.Name = ast.NewIdent(n)
+ }
+ importDecl.Specs = append(importDecl.Specs, s)
+ }
+
+ // Synthesize main function.
+ funcDecl := &ast.FuncDecl{
+ Name: ast.NewIdent("main"),
+ Type: &ast.FuncType{},
+ Body: body,
+ }
+
+ // Synthesize file.
+ return &ast.File{
+ Name: ast.NewIdent("main"),
+ Decls: []ast.Decl{importDecl, funcDecl},
+ Comments: comments,
+ }
+}
+
+// playExample takes a whole file example and synthesizes a new *ast.File
+// such that the example is function main in package main.
+func playExampleFile(file *ast.File) *ast.File {
+ // Strip copyright comment if present.
+ comments := file.Comments
+ if len(comments) > 0 && strings.HasPrefix(comments[0].Text(), "Copyright") {
+ comments = comments[1:]
+ }
+
+ // Copy declaration slice, rewriting the ExampleX function to main.
+ var decls []ast.Decl
+ for _, d := range file.Decls {
+ if f, ok := d.(*ast.FuncDecl); ok && isTest(f.Name.Name, "Example") {
+ // Copy the FuncDecl, as it may be used elsewhere.
+ newF := *f
+ newF.Name = ast.NewIdent("main")
+ newF.Body, comments = stripOutputComment(f.Body, comments)
+ d = &newF
+ }
+ decls = append(decls, d)
+ }
+
+ // Copy the File, as it may be used elsewhere.
+ f := *file
+ f.Name = ast.NewIdent("main")
+ f.Decls = decls
+ f.Comments = comments
+ return &f
+}
+
+// stripOutputComment finds and removes an "Output:" commment from body
+// and comments, and adjusts the body block's end position.
+func stripOutputComment(body *ast.BlockStmt, comments []*ast.CommentGroup) (*ast.BlockStmt, []*ast.CommentGroup) {
+ // Do nothing if no "Output:" comment found.
+ i, last := lastComment(body, comments)
+ if last == nil || !outputPrefix.MatchString(last.Text()) {
+ return body, comments
+ }
+
+ // Copy body and comments, as the originals may be used elsewhere.
+ newBody := &ast.BlockStmt{
+ Lbrace: body.Lbrace,
+ List: body.List,
+ Rbrace: last.Pos(),
+ }
+ newComments := make([]*ast.CommentGroup, len(comments)-1)
+ copy(newComments, comments[:i])
+ copy(newComments[i:], comments[i+1:])
+ return newBody, newComments
+}
+
+// lastComment returns the last comment inside the provided block.
+func lastComment(b *ast.BlockStmt, c []*ast.CommentGroup) (i int, last *ast.CommentGroup) {
+ pos, end := b.Pos(), b.End()
+ for j, cg := range c {
+ if cg.Pos() < pos {
+ continue
+ }
+ if cg.End() > end {
+ break
+ }
+ i, last = j, cg
+ }
+ return
+}
diff --git a/libgo/go/go/doc/reader.go b/libgo/go/go/doc/reader.go
index 60b174fecd8..de42d47d9fe 100644
--- a/libgo/go/go/doc/reader.go
+++ b/libgo/go/go/doc/reader.go
@@ -515,29 +515,6 @@ func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
// ----------------------------------------------------------------------------
// Types
-var predeclaredTypes = map[string]bool{
- "bool": true,
- "byte": true,
- "complex64": true,
- "complex128": true,
- "error": true,
- "float32": true,
- "float64": true,
- "int": true,
- "int8": true,
- "int16": true,
- "int32": true,
- "int64": true,
- "rune": true,
- "string": true,
- "uint": true,
- "uint8": true,
- "uint16": true,
- "uint32": true,
- "uint64": true,
- "uintptr": true,
-}
-
func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func {
if f == nil || f.Decl == nil || f.Decl.Recv == nil || len(f.Decl.Recv.List) != 1 {
return f // shouldn't happen, but be safe
@@ -772,3 +749,54 @@ func sortedFuncs(m methodSet, allMethods bool) []*Func {
)
return list
}
+
+// ----------------------------------------------------------------------------
+// Predeclared identifiers
+
+var predeclaredTypes = map[string]bool{
+ "bool": true,
+ "byte": true,
+ "complex64": true,
+ "complex128": true,
+ "error": true,
+ "float32": true,
+ "float64": true,
+ "int": true,
+ "int8": true,
+ "int16": true,
+ "int32": true,
+ "int64": true,
+ "rune": true,
+ "string": true,
+ "uint": true,
+ "uint8": true,
+ "uint16": true,
+ "uint32": true,
+ "uint64": true,
+ "uintptr": true,
+}
+
+var predeclaredFuncs = map[string]bool{
+ "append": true,
+ "cap": true,
+ "close": true,
+ "complex": true,
+ "copy": true,
+ "delete": true,
+ "imag": true,
+ "len": true,
+ "make": true,
+ "new": true,
+ "panic": true,
+ "print": true,
+ "println": true,
+ "real": true,
+ "recover": true,
+}
+
+var predeclaredConstants = map[string]bool{
+ "false": true,
+ "iota": true,
+ "nil": true,
+ "true": true,
+}
diff --git a/libgo/go/go/doc/synopsis.go b/libgo/go/go/doc/synopsis.go
index 2192d78c0cd..2d18174393e 100644
--- a/libgo/go/go/doc/synopsis.go
+++ b/libgo/go/go/doc/synopsis.go
@@ -4,7 +4,10 @@
package doc
-import "unicode"
+import (
+ "strings"
+ "unicode"
+)
// firstSentenceLen returns the length of the first sentence in s.
// The sentence ends after the first period followed by space and
@@ -24,17 +27,12 @@ func firstSentenceLen(s string) int {
return len(s)
}
-// Synopsis returns a cleaned version of the first sentence in s.
-// That sentence ends after the first period followed by space and
-// not preceded by exactly one uppercase letter. The result string
-// has no \n, \r, or \t characters and uses only single spaces between
-// words.
-//
-func Synopsis(s string) string {
- n := firstSentenceLen(s)
+// clean replaces each sequence of space, \n, \r, or \t characters
+// with a single space and removes any trailing and leading spaces.
+func clean(s string) string {
var b []byte
p := byte(' ')
- for i := 0; i < n; i++ {
+ for i := 0; i < len(s); i++ {
q := s[i]
if q == '\n' || q == '\r' || q == '\t' {
q = ' '
@@ -50,3 +48,26 @@ func Synopsis(s string) string {
}
return string(b)
}
+
+// Synopsis returns a cleaned version of the first sentence in s.
+// That sentence ends after the first period followed by space and
+// not preceded by exactly one uppercase letter. The result string
+// has no \n, \r, or \t characters and uses only single spaces between
+// words. If s starts with any of the IllegalPrefixes, the result
+// is the empty string.
+//
+func Synopsis(s string) string {
+ s = clean(s[0:firstSentenceLen(s)])
+ for _, prefix := range IllegalPrefixes {
+ if strings.HasPrefix(strings.ToLower(s), prefix) {
+ return ""
+ }
+ }
+ return s
+}
+
+var IllegalPrefixes = []string{
+ "copyright",
+ "all rights",
+ "author",
+}
diff --git a/libgo/go/go/doc/synopsis_test.go b/libgo/go/go/doc/synopsis_test.go
index dfc6598af47..fd7081a07c2 100644
--- a/libgo/go/go/doc/synopsis_test.go
+++ b/libgo/go/go/doc/synopsis_test.go
@@ -28,6 +28,11 @@ var tests = []struct {
{"P. Q. ", 8, "P. Q."},
{"Package Καλημέρα κόσμε.", 36, "Package Καλημέρα κόσμε."},
{"Package こんにちは 世界\n", 31, "Package こんにちは 世界"},
+ {"Package foo does bar.", 21, "Package foo does bar."},
+ {"Copyright 2012 Google, Inc. Package foo does bar.", 27, ""},
+ {"All Rights reserved. Package foo does bar.", 20, ""},
+ {"All rights reserved. Package foo does bar.", 20, ""},
+ {"Authors: foo@bar.com. Package foo does bar.", 21, ""},
}
func TestSynopsis(t *testing.T) {
diff --git a/libgo/go/go/doc/testdata/benchmark.go b/libgo/go/go/doc/testdata/benchmark.go
index 0aded5bb4c7..905e49644ad 100644
--- a/libgo/go/go/doc/testdata/benchmark.go
+++ b/libgo/go/go/doc/testdata/benchmark.go
@@ -13,7 +13,7 @@ import (
)
var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
-var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
+var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
// An internal type but exported because it is cross-package; part of the implementation
// of go test.
@@ -151,7 +151,7 @@ func (b *B) launch() {
b.runN(n)
// Run the benchmark for at least the specified amount of time.
- d := time.Duration(*benchTime * float64(time.Second))
+ d := *benchTime
for !b.failed && b.duration < d && n < 1e9 {
last := n
// Predict iterations/sec.
diff --git a/libgo/go/go/doc/testdata/testing.1.golden b/libgo/go/go/doc/testdata/testing.1.golden
index d26a4685ca0..ffdb5c3b588 100644
--- a/libgo/go/go/doc/testdata/testing.1.golden
+++ b/libgo/go/go/doc/testdata/testing.1.golden
@@ -45,7 +45,7 @@ VARIABLES
)
//
- var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
+ var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
//
var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
diff --git a/libgo/go/go/parser/interface.go b/libgo/go/go/parser/interface.go
index 5c203a7846e..4a84a97ae79 100644
--- a/libgo/go/go/parser/interface.go
+++ b/libgo/go/go/parser/interface.go
@@ -90,6 +90,15 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode)
var p parser
p.init(fset, filename, text, mode)
f := p.parseFile()
+ if f == nil {
+ // source is not a valid Go source file - satisfy
+ // ParseFile API and return a valid (but) empty
+ // *ast.File
+ f = &ast.File{
+ Name: new(ast.Ident),
+ Scope: ast.NewScope(nil),
+ }
+ }
// sort errors
if p.mode&SpuriousErrors == 0 {
diff --git a/libgo/go/go/parser/parser.go b/libgo/go/go/parser/parser.go
index 20e505d97a8..26b31b247ad 100644
--- a/libgo/go/go/parser/parser.go
+++ b/libgo/go/go/parser/parser.go
@@ -28,7 +28,7 @@ type parser struct {
// Tracing/debugging
mode Mode // parsing mode
trace bool // == (mode & Trace != 0)
- indent uint // indentation used for tracing output
+ indent int // indentation used for tracing output
// Comments
comments []*ast.CommentGroup
@@ -56,7 +56,7 @@ type parser struct {
unresolved []*ast.Ident // unresolved identifiers
imports []*ast.ImportSpec // list of imports
- // Label scope
+ // Label scopes
// (maintained by open/close LabelScope)
labelScope *ast.Scope // label scope for current function
targetStack [][]*ast.Ident // stack of unresolved labels
@@ -75,14 +75,6 @@ func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mod
p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
p.next()
-
- // set up the pkgScope here (as opposed to in parseFile) because
- // there are other parser entry points (ParseExpr, etc.)
- p.openScope()
- p.pkgScope = p.topScope
-
- // for the same reason, set up a label scope
- p.openLabelScope()
}
// ----------------------------------------------------------------------------
@@ -199,15 +191,16 @@ func (p *parser) resolve(x ast.Expr) {
// Parsing support
func (p *parser) printTrace(a ...interface{}) {
- const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " +
- ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
- const n = uint(len(dots))
+ const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
+ const n = len(dots)
pos := p.file.Position(p.pos)
fmt.Printf("%5d:%3d: ", pos.Line, pos.Column)
i := 2 * p.indent
- for ; i > n; i -= n {
+ for i > n {
fmt.Print(dots)
+ i -= n
}
+ // i <= n
fmt.Print(dots[0:i])
fmt.Println(a...)
}
@@ -218,7 +211,7 @@ func trace(p *parser, msg string) *parser {
return p
}
-// Usage pattern: defer un(trace(p, "..."));
+// Usage pattern: defer un(trace(p, "..."))
func un(p *parser) {
p.indent--
p.printTrace(")")
@@ -304,14 +297,14 @@ func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline
func (p *parser) next() {
p.leadComment = nil
p.lineComment = nil
- line := p.file.Line(p.pos) // current line
+ prev := p.pos
p.next0()
if p.tok == token.COMMENT {
var comment *ast.CommentGroup
var endline int
- if p.file.Line(p.pos) == line {
+ if p.file.Line(p.pos) == p.file.Line(prev) {
// The comment is on same line as the previous token; it
// cannot be a lead comment but may be a line comment.
comment, endline = p.consumeCommentGroup(0)
@@ -931,20 +924,22 @@ func (p *parser) parseChanType() *ast.ChanType {
pos := p.pos
dir := ast.SEND | ast.RECV
+ var arrow token.Pos
if p.tok == token.CHAN {
p.next()
if p.tok == token.ARROW {
+ arrow = p.pos
p.next()
dir = ast.SEND
}
} else {
- p.expect(token.ARROW)
+ arrow = p.expect(token.ARROW)
p.expect(token.CHAN)
dir = ast.RECV
}
value := p.parseType()
- return &ast.ChanType{Begin: pos, Dir: dir, Value: value}
+ return &ast.ChanType{Begin: pos, Arrow: arrow, Dir: dir, Value: value}
}
// If the result is an identifier, it is not resolved.
@@ -1404,16 +1399,49 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
case token.ARROW:
// channel type or receive expression
- pos := p.pos
+ arrow := p.pos
p.next()
- if p.tok == token.CHAN {
- p.next()
- value := p.parseType()
- return &ast.ChanType{Begin: pos, Dir: ast.RECV, Value: value}
- }
+
+ // If the next token is token.CHAN we still don't know if it
+ // is a channel type or a receive operation - we only know
+ // once we have found the end of the unary expression. There
+ // are two cases:
+ //
+ // <- type => (<-type) must be channel type
+ // <- expr => <-(expr) is a receive from an expression
+ //
+ // In the first case, the arrow must be re-associated with
+ // the channel type parsed already:
+ //
+ // <- (chan type) => (<-chan type)
+ // <- (chan<- type) => (<-chan (<-type))
x := p.parseUnaryExpr(false)
- return &ast.UnaryExpr{OpPos: pos, Op: token.ARROW, X: p.checkExpr(x)}
+
+ // determine which case we have
+ if typ, ok := x.(*ast.ChanType); ok {
+ // (<-type)
+
+ // re-associate position info and <-
+ dir := ast.SEND
+ for ok && dir == ast.SEND {
+ if typ.Dir == ast.RECV {
+ // error: (<-type) is (<-(<-chan T))
+ p.errorExpected(typ.Arrow, "'chan'")
+ }
+ arrow, typ.Begin, typ.Arrow = typ.Arrow, arrow, arrow
+ dir, typ.Dir = typ.Dir, ast.RECV
+ typ, ok = typ.Value.(*ast.ChanType)
+ }
+ if dir == ast.SEND {
+ p.errorExpected(arrow, "channel type")
+ }
+
+ return x
+ }
+
+ // <-(expr)
+ return &ast.UnaryExpr{OpPos: arrow, Op: token.ARROW, X: p.checkExpr(x)}
case token.MUL:
// pointer type or unary "*" expression
@@ -2012,7 +2040,7 @@ func (p *parser) parseStmt() (s ast.Stmt) {
// ----------------------------------------------------------------------------
// Declarations
-type parseSpecFunction func(p *parser, doc *ast.CommentGroup, iota int) ast.Spec
+type parseSpecFunction func(p *parser, doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
func isValidImport(lit string) bool {
const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
@@ -2025,7 +2053,7 @@ func isValidImport(lit string) bool {
return s != ""
}
-func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
+func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
if p.trace {
defer un(trace(p, "ImportSpec"))
}
@@ -2063,15 +2091,15 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
return spec
}
-func parseConstSpec(p *parser, doc *ast.CommentGroup, iota int) ast.Spec {
+func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec {
if p.trace {
- defer un(trace(p, "ConstSpec"))
+ defer un(trace(p, keyword.String()+"Spec"))
}
idents := p.parseIdentList()
typ := p.tryType()
var values []ast.Expr
- if typ != nil || p.tok == token.ASSIGN || iota == 0 {
+ if p.tok == token.ASSIGN || keyword == token.CONST && (typ != nil || iota == 0) || keyword == token.VAR && typ == nil {
p.expect(token.ASSIGN)
values = p.parseRhsList()
}
@@ -2088,12 +2116,16 @@ func parseConstSpec(p *parser, doc *ast.CommentGroup, iota int) ast.Spec {
Values: values,
Comment: p.lineComment,
}
- p.declare(spec, iota, p.topScope, ast.Con, idents...)
+ kind := ast.Con
+ if keyword == token.VAR {
+ kind = ast.Var
+ }
+ p.declare(spec, iota, p.topScope, kind, idents...)
return spec
}
-func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
+func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
if p.trace {
defer un(trace(p, "TypeSpec"))
}
@@ -2114,36 +2146,6 @@ func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
return spec
}
-func parseVarSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
- if p.trace {
- defer un(trace(p, "VarSpec"))
- }
-
- idents := p.parseIdentList()
- typ := p.tryType()
- var values []ast.Expr
- if typ == nil || p.tok == token.ASSIGN {
- p.expect(token.ASSIGN)
- values = p.parseRhsList()
- }
- p.expectSemi() // call before accessing p.linecomment
-
- // Go spec: The scope of a constant or variable identifier declared inside
- // a function begins at the end of the ConstSpec or VarSpec and ends at
- // the end of the innermost containing block.
- // (Global identifiers are resolved in a separate phase after parsing.)
- spec := &ast.ValueSpec{
- Doc: doc,
- Names: idents,
- Type: typ,
- Values: values,
- Comment: p.lineComment,
- }
- p.declare(spec, nil, p.topScope, ast.Var, idents...)
-
- return spec
-}
-
func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl {
if p.trace {
defer un(trace(p, "GenDecl("+keyword.String()+")"))
@@ -2157,12 +2159,12 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen
lparen = p.pos
p.next()
for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ {
- list = append(list, f(p, p.leadComment, iota))
+ list = append(list, f(p, p.leadComment, keyword, iota))
}
rparen = p.expect(token.RPAREN)
p.expectSemi()
} else {
- list = append(list, f(p, nil, 0))
+ list = append(list, f(p, nil, keyword, 0))
}
return &ast.GenDecl{
@@ -2262,14 +2264,11 @@ func (p *parser) parseDecl(sync func(*parser)) ast.Decl {
var f parseSpecFunction
switch p.tok {
- case token.CONST:
- f = parseConstSpec
+ case token.CONST, token.VAR:
+ f = (*parser).parseValueSpec
case token.TYPE:
- f = parseTypeSpec
-
- case token.VAR:
- f = parseVarSpec
+ f = (*parser).parseTypeSpec
case token.FUNC:
return p.parseFuncDecl()
@@ -2292,6 +2291,12 @@ func (p *parser) parseFile() *ast.File {
defer un(trace(p, "File"))
}
+ // Don't bother parsing the rest if we had errors scanning the first token.
+ // Likely not a Go source file at all.
+ if p.errors.Len() != 0 {
+ return nil
+ }
+
// package clause
doc := p.leadComment
pos := p.expect(token.PACKAGE)
@@ -2303,15 +2308,19 @@ func (p *parser) parseFile() *ast.File {
}
p.expectSemi()
- var decls []ast.Decl
-
- // Don't bother parsing the rest if we had errors already.
+ // Don't bother parsing the rest if we had errors parsing the package clause.
// Likely not a Go source file at all.
+ if p.errors.Len() != 0 {
+ return nil
+ }
- if p.errors.Len() == 0 && p.mode&PackageClauseOnly == 0 {
+ p.openScope()
+ p.pkgScope = p.topScope
+ var decls []ast.Decl
+ if p.mode&PackageClauseOnly == 0 {
// import decls
for p.tok == token.IMPORT {
- decls = append(decls, p.parseGenDecl(token.IMPORT, parseImportSpec))
+ decls = append(decls, p.parseGenDecl(token.IMPORT, (*parser).parseImportSpec))
}
if p.mode&ImportsOnly == 0 {
@@ -2321,8 +2330,9 @@ func (p *parser) parseFile() *ast.File {
}
}
}
-
- assert(p.topScope == p.pkgScope, "imbalanced scopes")
+ p.closeScope()
+ assert(p.topScope == nil, "unbalanced scopes")
+ assert(p.labelScope == nil, "unbalanced label scopes")
// resolve global identifiers within the same file
i := 0
diff --git a/libgo/go/go/parser/parser_test.go b/libgo/go/go/parser/parser_test.go
index 1b7a41b1bf1..1960377b0a6 100644
--- a/libgo/go/go/parser/parser_test.go
+++ b/libgo/go/go/parser/parser_test.go
@@ -135,6 +135,53 @@ func TestVarScope(t *testing.T) {
}
}
+func TestObjects(t *testing.T) {
+ const src = `
+package p
+import fmt "fmt"
+const pi = 3.14
+type T struct{}
+var x int
+func f() { L: }
+`
+
+ f, err := ParseFile(fset, "", src, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ objects := map[string]ast.ObjKind{
+ "p": ast.Bad, // not in a scope
+ "fmt": ast.Bad, // not resolved yet
+ "pi": ast.Con,
+ "T": ast.Typ,
+ "x": ast.Var,
+ "int": ast.Bad, // not resolved yet
+ "f": ast.Fun,
+ "L": ast.Lbl,
+ }
+
+ ast.Inspect(f, func(n ast.Node) bool {
+ if ident, ok := n.(*ast.Ident); ok {
+ obj := ident.Obj
+ if obj == nil {
+ if objects[ident.Name] != ast.Bad {
+ t.Errorf("no object for %s", ident.Name)
+ }
+ return true
+ }
+ if obj.Name != ident.Name {
+ t.Errorf("names don't match: obj.Name = %s, ident.Name = %s", obj.Name, ident.Name)
+ }
+ kind := objects[ident.Name]
+ if obj.Kind != kind {
+ t.Errorf("%s: obj.Kind = %s; want %s", ident.Name, obj.Kind, kind)
+ }
+ }
+ return true
+ })
+}
+
func TestUnresolved(t *testing.T) {
f, err := ParseFile(fset, "", `
package p
diff --git a/libgo/go/go/parser/performance_test.go b/libgo/go/go/parser/performance_test.go
new file mode 100644
index 00000000000..f2732c0e2b1
--- /dev/null
+++ b/libgo/go/go/parser/performance_test.go
@@ -0,0 +1,30 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package parser
+
+import (
+ "go/token"
+ "io/ioutil"
+ "testing"
+)
+
+var src = readFile("parser.go")
+
+func readFile(filename string) []byte {
+ data, err := ioutil.ReadFile(filename)
+ if err != nil {
+ panic(err)
+ }
+ return data
+}
+
+func BenchmarkParse(b *testing.B) {
+ b.SetBytes(int64(len(src)))
+ for i := 0; i < b.N; i++ {
+ if _, err := ParseFile(token.NewFileSet(), "", src, ParseComments); err != nil {
+ b.Fatalf("benchmark failed due to parse error: %s", err)
+ }
+ }
+}
diff --git a/libgo/go/go/parser/short_test.go b/libgo/go/go/parser/short_test.go
index 238492bf3f7..daba8530886 100644
--- a/libgo/go/go/parser/short_test.go
+++ b/libgo/go/go/parser/short_test.go
@@ -13,8 +13,10 @@ var valids = []string{
`package p;`,
`package p; import "fmt"; func f() { fmt.Println("Hello, World!") };`,
`package p; func f() { if f(T{}) {} };`,
- `package p; func f() { _ = (<-chan int)(x) };`,
- `package p; func f() { _ = (<-chan <-chan int)(x) };`,
+ `package p; func f() { _ = <-chan int(nil) };`,
+ `package p; func f() { _ = (<-chan int)(nil) };`,
+ `package p; func f() { _ = (<-chan <-chan int)(nil) };`,
+ `package p; func f() { _ = <-chan <-chan <-chan <-chan <-int(nil) };`,
`package p; func f(func() func() func());`,
`package p; func f(...T);`,
`package p; func f(float, ...int);`,
@@ -64,8 +66,10 @@ var invalids = []string{
`package p; var a = []int{[ /* ERROR "expected expression" */ ]int};`,
`package p; var a = ( /* ERROR "expected expression" */ []int);`,
`package p; var a = a[[ /* ERROR "expected expression" */ ]int:[]int];`,
- `package p; var a = <- /* ERROR "expected expression" */ chan int;`,
- `package p; func f() { select { case _ <- chan /* ERROR "expected expression" */ int: } };`,
+ `package p; var a = <- /* ERROR "expected expression" */ chan int;`,
+ `package p; func f() { select { case _ <- chan /* ERROR "expected expression" */ int: } };`,
+ `package p; func f() { _ = (<-<- /* ERROR "expected 'chan'" */ chan int)(nil) };`,
+ `package p; func f() { _ = (<-chan<-chan<-chan<-chan<-chan<- /* ERROR "expected channel type" */ int)(nil) };`,
}
func TestInvalid(t *testing.T) {
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go
index e346b93643b..e99a2e36d4f 100644
--- a/libgo/go/go/printer/nodes.go
+++ b/libgo/go/go/printer/nodes.go
@@ -203,7 +203,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
} else {
const r = 4 // threshold
ratio := float64(size) / float64(prevSize)
- useFF = ratio <= 1/r || r <= ratio
+ useFF = ratio <= 1.0/r || r <= ratio
}
}
@@ -791,7 +791,14 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
if len(x.Args) > 1 {
depth++
}
- p.expr1(x.Fun, token.HighestPrec, depth)
+ if _, ok := x.Fun.(*ast.FuncType); ok {
+ // conversions to literal function types require parentheses around the type
+ p.print(token.LPAREN)
+ p.expr1(x.Fun, token.HighestPrec, depth)
+ p.print(token.RPAREN)
+ } else {
+ p.expr1(x.Fun, token.HighestPrec, depth)
+ }
p.print(x.Lparen, token.LPAREN)
if x.Ellipsis.IsValid() {
p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis)
@@ -853,9 +860,9 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
case ast.SEND | ast.RECV:
p.print(token.CHAN)
case ast.RECV:
- p.print(token.ARROW, token.CHAN)
+ p.print(token.ARROW, token.CHAN) // x.Arrow and x.Pos() are the same
case ast.SEND:
- p.print(token.CHAN, token.ARROW)
+ p.print(token.CHAN, x.Arrow, token.ARROW)
}
p.print(blank)
p.expr(x.Value)
@@ -882,28 +889,32 @@ func (p *printer) expr(x ast.Expr) {
// Print the statement list indented, but without a newline after the last statement.
// Extra line breaks between statements in the source are respected but at most one
// empty line is printed between statements.
-func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
- // TODO(gri): fix _indent code
- if _indent > 0 {
+func (p *printer) stmtList(list []ast.Stmt, nindent int, nextIsRBrace bool) {
+ if nindent > 0 {
p.print(indent)
}
multiLine := false
- for i, s := range list {
- // _indent == 0 only for lists of switch/select case clauses;
- // in those cases each clause is a new section
- p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || _indent == 0 || multiLine)
- p.stmt(s, nextIsRBrace && i == len(list)-1)
- multiLine = p.isMultiLine(s)
- }
- if _indent > 0 {
+ i := 0
+ for _, s := range list {
+ // ignore empty statements (was issue 3466)
+ if _, isEmpty := s.(*ast.EmptyStmt); !isEmpty {
+ // _indent == 0 only for lists of switch/select case clauses;
+ // in those cases each clause is a new section
+ p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || nindent == 0 || multiLine)
+ p.stmt(s, nextIsRBrace && i == len(list)-1)
+ multiLine = p.isMultiLine(s)
+ i++
+ }
+ }
+ if nindent > 0 {
p.print(unindent)
}
}
// block prints an *ast.BlockStmt; it always spans at least two lines.
-func (p *printer) block(s *ast.BlockStmt, indent int) {
+func (p *printer) block(s *ast.BlockStmt, nindent int) {
p.print(s.Pos(), token.LBRACE)
- p.stmtList(s.List, indent, true)
+ p.stmtList(s.List, nindent, true)
p.linebreak(p.lineFor(s.Rbrace), 1, ignore, true)
p.print(s.Rbrace, token.RBRACE)
}
diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go
index a027d32da89..516c37161c1 100644
--- a/libgo/go/go/printer/printer.go
+++ b/libgo/go/go/printer/printer.go
@@ -449,11 +449,17 @@ func commonPrefix(a, b string) string {
return a[0:i]
}
+// stripCommonPrefix removes a common prefix from /*-style comment lines (unless no
+// comment line is indented, all but the first line have some form of space prefix).
+// The prefix is computed using heuristics such that is is likely that the comment
+// contents are nicely laid out after re-printing each line using the printer's
+// current indentation.
+//
func stripCommonPrefix(lines []string) {
- if len(lines) < 2 {
+ if len(lines) <= 1 {
return // at most one line - nothing to do
}
- // len(lines) >= 2
+ // len(lines) > 1
// The heuristic in this function tries to handle a few
// common patterns of /*-style comments: Comments where
@@ -479,7 +485,7 @@ func stripCommonPrefix(lines []string) {
for i, line := range lines[1 : len(lines)-1] {
switch {
case isBlank(line):
- lines[1+i] = "" // range starts at line 1
+ lines[1+i] = "" // range starts with lines[1]
case first:
prefix = commonPrefix(line, line)
first = false
@@ -570,9 +576,9 @@ func stripCommonPrefix(lines []string) {
}
// Remove the common prefix from all but the first and empty lines.
- for i, line := range lines[1:] {
- if len(line) != 0 {
- lines[1+i] = line[len(prefix):] // range starts at line 1
+ for i, line := range lines {
+ if i > 0 && line != "" {
+ lines[i] = line[len(prefix):]
}
}
}
@@ -612,6 +618,19 @@ func (p *printer) writeComment(comment *ast.Comment) {
// for /*-style comments, print line by line and let the
// write function take care of the proper indentation
lines := split(text)
+
+ // The comment started in the first column but is going
+ // to be indented. For an idempotent result, add indentation
+ // to all lines such that they look like they were indented
+ // before - this will make sure the common prefix computation
+ // is the same independent of how many times formatting is
+ // applied (was issue 1835).
+ if pos.IsValid() && pos.Column == 1 && p.indent > 0 {
+ for i, line := range lines[1:] {
+ lines[1+i] = " " + line
+ }
+ }
+
stripCommonPrefix(lines)
// write comment lines, separated by formfeed,
@@ -1140,7 +1159,7 @@ func (p *trimmer) Write(data []byte) (n int, err error) {
// ----------------------------------------------------------------------------
// Public interface
-// A Mode value is a set of flags (or 0). They coontrol printing.
+// A Mode value is a set of flags (or 0). They control printing.
type Mode uint
const (
diff --git a/libgo/go/go/printer/printer_test.go b/libgo/go/go/printer/printer_test.go
index ab9e9b2ec8c..36d1bf74d3f 100644
--- a/libgo/go/go/printer/printer_test.go
+++ b/libgo/go/go/printer/printer_test.go
@@ -6,7 +6,9 @@ package printer
import (
"bytes"
+ "errors"
"flag"
+ "fmt"
"go/ast"
"go/parser"
"go/token"
@@ -25,33 +27,28 @@ var update = flag.Bool("update", false, "update golden files")
var fset = token.NewFileSet()
-func lineString(text []byte, i int) string {
- i0 := i
- for i < len(text) && text[i] != '\n' {
- i++
- }
- return string(text[i0:i])
-}
-
type checkMode uint
const (
export checkMode = 1 << iota
rawFormat
+ idempotent
)
-func runcheck(t *testing.T, source, golden string, mode checkMode) {
- // parse source
- prog, err := parser.ParseFile(fset, source, nil, parser.ParseComments)
+// format parses src, prints the corresponding AST, verifies the resulting
+// src is syntactically correct, and returns the resulting src or an error
+// if any.
+func format(src []byte, mode checkMode) ([]byte, error) {
+ // parse src
+ f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
if err != nil {
- t.Error(err)
- return
+ return nil, fmt.Errorf("parse: %s\n%s", err, src)
}
// filter exports if necessary
if mode&export != 0 {
- ast.FileExports(prog) // ignore result
- prog.Comments = nil // don't print comments that are not in AST
+ ast.FileExports(f) // ignore result
+ f.Comments = nil // don't print comments that are not in AST
}
// determine printer configuration
@@ -60,17 +57,72 @@ func runcheck(t *testing.T, source, golden string, mode checkMode) {
cfg.Mode |= RawFormat
}
- // format source
+ // print AST
var buf bytes.Buffer
- if err := cfg.Fprint(&buf, fset, prog); err != nil {
- t.Error(err)
+ if err := cfg.Fprint(&buf, fset, f); err != nil {
+ return nil, fmt.Errorf("print: %s", err)
}
- res := buf.Bytes()
- // formatted source must be valid
+ // make sure formated output is syntactically correct
+ res := buf.Bytes()
if _, err := parser.ParseFile(fset, "", res, 0); err != nil {
+ return nil, fmt.Errorf("re-parse: %s\n%s", err, buf.Bytes())
+ }
+
+ return res, nil
+}
+
+// lineAt returns the line in text starting at offset offs.
+func lineAt(text []byte, offs int) []byte {
+ i := offs
+ for i < len(text) && text[i] != '\n' {
+ i++
+ }
+ return text[offs:i]
+}
+
+// diff compares a and b.
+func diff(aname, bname string, a, b []byte) error {
+ var buf bytes.Buffer // holding long error message
+
+ // compare lengths
+ if len(a) != len(b) {
+ fmt.Fprintf(&buf, "\nlength changed: len(%s) = %d, len(%s) = %d", aname, len(a), bname, len(b))
+ }
+
+ // compare contents
+ line := 1
+ offs := 1
+ for i := 0; i < len(a) && i < len(b); i++ {
+ ch := a[i]
+ if ch != b[i] {
+ fmt.Fprintf(&buf, "\n%s:%d:%d: %s", aname, line, i-offs+1, lineAt(a, offs))
+ fmt.Fprintf(&buf, "\n%s:%d:%d: %s", bname, line, i-offs+1, lineAt(b, offs))
+ fmt.Fprintf(&buf, "\n\n")
+ break
+ }
+ if ch == '\n' {
+ line++
+ offs = i + 1
+ }
+ }
+
+ if buf.Len() > 0 {
+ return errors.New(buf.String())
+ }
+ return nil
+}
+
+func runcheck(t *testing.T, source, golden string, mode checkMode) {
+ src, err := ioutil.ReadFile(source)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ res, err := format(src, mode)
+ if err != nil {
t.Error(err)
- t.Logf("\n%s", res)
return
}
@@ -89,23 +141,19 @@ func runcheck(t *testing.T, source, golden string, mode checkMode) {
return
}
- // compare lengths
- if len(res) != len(gld) {
- t.Errorf("len = %d, expected %d (= len(%s))", len(res), len(gld), golden)
+ // formatted source and golden must be the same
+ if err := diff(source, golden, res, gld); err != nil {
+ t.Error(err)
+ return
}
- // compare contents
- for i, line, offs := 0, 1, 0; i < len(res) && i < len(gld); i++ {
- ch := res[i]
- if ch != gld[i] {
- t.Errorf("%s:%d:%d: %s", source, line, i-offs+1, lineString(res, offs))
- t.Errorf("%s:%d:%d: %s", golden, line, i-offs+1, lineString(gld, offs))
- t.Error()
- return
- }
- if ch == '\n' {
- line++
- offs = i + 1
+ if mode&idempotent != 0 {
+ // formatting golden must be idempotent
+ // (This is very difficult to achieve in general and for now
+ // it is only checked for files explicitly marked as such.)
+ res, err = format(gld, mode)
+ if err := diff(golden, fmt.Sprintf("format(%s)", golden), gld, res); err != nil {
+ t.Errorf("golden is not idempotent: %s", err)
}
}
}
@@ -142,15 +190,16 @@ type entry struct {
// Use go test -update to create/update the respective golden files.
var data = []entry{
- {"empty.input", "empty.golden", 0},
+ {"empty.input", "empty.golden", idempotent},
{"comments.input", "comments.golden", 0},
{"comments.input", "comments.x", export},
- {"linebreaks.input", "linebreaks.golden", 0},
- {"expressions.input", "expressions.golden", 0},
- {"expressions.input", "expressions.raw", rawFormat},
+ {"comments2.input", "comments2.golden", idempotent},
+ {"linebreaks.input", "linebreaks.golden", idempotent},
+ {"expressions.input", "expressions.golden", idempotent},
+ {"expressions.input", "expressions.raw", rawFormat | idempotent},
{"declarations.input", "declarations.golden", 0},
{"statements.input", "statements.golden", 0},
- {"slow.input", "slow.golden", 0},
+ {"slow.input", "slow.golden", idempotent},
}
func TestFiles(t *testing.T) {
@@ -248,7 +297,7 @@ func testComment(t *testing.T, f *ast.File, srclen int, comment *ast.Comment) {
}
}
-// Verify that the printer produces always produces a correct program
+// Verify that the printer produces a correct program
// even if the position information of comments introducing newlines
// is incorrect.
func TestBadComments(t *testing.T) {
@@ -421,21 +470,8 @@ func TestX(t *testing.T) {
package p
func _() {}
`
- // parse original
- f, err := parser.ParseFile(fset, "src", src, parser.ParseComments)
+ _, err := format([]byte(src), 0)
if err != nil {
- t.Fatal(err)
- }
-
- // pretty-print original
- var buf bytes.Buffer
- if err = (&Config{Mode: UseSpaces, Tabwidth: 8}).Fprint(&buf, fset, f); err != nil {
- t.Fatal(err)
- }
-
- // parse pretty printed original
- if _, err := parser.ParseFile(fset, "", buf.Bytes(), 0); err != nil {
- t.Fatalf("%s\n%s", err, buf.Bytes())
+ t.Error(err)
}
-
}
diff --git a/libgo/go/go/printer/testdata/comments2.golden b/libgo/go/go/printer/testdata/comments2.golden
new file mode 100644
index 00000000000..d3b50bf3e05
--- /dev/null
+++ b/libgo/go/go/printer/testdata/comments2.golden
@@ -0,0 +1,79 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This is a package for testing comment placement by go/printer.
+//
+package main
+
+// Test cases for idempotent comment formatting (was issue 1835).
+/*
+c1a
+*/
+/*
+ c1b
+*/
+/* foo
+c1c
+*/
+/* foo
+ c1d
+*/
+/*
+c1e
+foo */
+/*
+ c1f
+ foo */
+
+func f() {
+ /*
+ c2a
+ */
+ /*
+ c2b
+ */
+ /* foo
+ c2c
+ */
+ /* foo
+ c2d
+ */
+ /*
+ c2e
+ foo */
+ /*
+ c2f
+ foo */
+}
+
+func g() {
+ /*
+ c3a
+ */
+ /*
+ c3b
+ */
+ /* foo
+ c3c
+ */
+ /* foo
+ c3d
+ */
+ /*
+ c3e
+ foo */
+ /*
+ c3f
+ foo */
+}
+
+// Test case taken literally from issue 1835.
+func main() {
+ /*
+ prints test 5 times
+ */
+ for i := 0; i < 5; i++ {
+ println("test")
+ }
+}
diff --git a/libgo/go/go/printer/testdata/comments2.input b/libgo/go/go/printer/testdata/comments2.input
new file mode 100644
index 00000000000..6f8c85c94aa
--- /dev/null
+++ b/libgo/go/go/printer/testdata/comments2.input
@@ -0,0 +1,79 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This is a package for testing comment placement by go/printer.
+//
+package main
+
+// Test cases for idempotent comment formatting (was issue 1835).
+/*
+c1a
+*/
+/*
+ c1b
+*/
+/* foo
+c1c
+*/
+/* foo
+ c1d
+*/
+/*
+c1e
+foo */
+/*
+ c1f
+ foo */
+
+func f() {
+/*
+c2a
+*/
+/*
+ c2b
+*/
+/* foo
+c2c
+*/
+/* foo
+ c2d
+*/
+/*
+c2e
+foo */
+/*
+ c2f
+ foo */
+}
+
+func g() {
+/*
+c3a
+*/
+/*
+ c3b
+*/
+/* foo
+c3c
+*/
+/* foo
+ c3d
+*/
+/*
+c3e
+foo */
+/*
+ c3f
+ foo */
+}
+
+// Test case taken literally from issue 1835.
+func main() {
+/*
+prints test 5 times
+*/
+ for i := 0; i < 5; i++ {
+ println("test")
+ }
+} \ No newline at end of file
diff --git a/libgo/go/go/printer/testdata/declarations.golden b/libgo/go/go/printer/testdata/declarations.golden
index 71ed32ed145..21bbf2b2d42 100644
--- a/libgo/go/go/printer/testdata/declarations.golden
+++ b/libgo/go/go/printer/testdata/declarations.golden
@@ -654,6 +654,35 @@ var _ = map[int]int{
abcde: a, // align with previous line
}
+// alignment of map composite entries: test cases from issue 3965
+// aligned
+var _ = T1{
+ a: x,
+ b: y,
+ cccccccccccccccccccc: z,
+}
+
+// not aligned
+var _ = T2{
+ a: x,
+ b: y,
+ ccccccccccccccccccccc: z,
+}
+
+// aligned
+var _ = T3{
+ aaaaaaaaaaaaaaaaaaaa: x,
+ b: y,
+ c: z,
+}
+
+// not aligned
+var _ = T4{
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: x,
+ b: y,
+ c: z,
+}
+
func _() {
var _ = T{
a, // must introduce trailing comma
diff --git a/libgo/go/go/printer/testdata/declarations.input b/libgo/go/go/printer/testdata/declarations.input
index d74cff25d1f..6ac00369926 100644
--- a/libgo/go/go/printer/testdata/declarations.input
+++ b/libgo/go/go/printer/testdata/declarations.input
@@ -667,6 +667,35 @@ var _ = map[int]int{
abcde: a, // align with previous line
}
+// alignment of map composite entries: test cases from issue 3965
+// aligned
+var _ = T1{
+ a: x,
+ b: y,
+ cccccccccccccccccccc: z,
+}
+
+// not aligned
+var _ = T2{
+ a: x,
+ b: y,
+ ccccccccccccccccccccc: z,
+}
+
+// aligned
+var _ = T3{
+ aaaaaaaaaaaaaaaaaaaa: x,
+ b: y,
+ c: z,
+}
+
+// not aligned
+var _ = T4{
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: x,
+ b: y,
+ c: z,
+}
+
func _() {
var _ = T{
diff --git a/libgo/go/go/printer/testdata/expressions.golden b/libgo/go/go/printer/testdata/expressions.golden
index 45fa4d97a4a..4291c557ce2 100644
--- a/libgo/go/go/printer/testdata/expressions.golden
+++ b/libgo/go/go/printer/testdata/expressions.golden
@@ -647,3 +647,18 @@ func _() {
a...,
)
}
+
+// Literal function types in conversions must be parenthesized;
+// for now go/parser accepts the unparenthesized form where it
+// is non-ambiguous.
+func _() {
+ // these conversions should be rewritten to look
+ // the same as the parenthesized conversions below
+ _ = (func())(nil)
+ _ = (func(x int) float)(nil)
+ _ = (func() func() func())(nil)
+
+ _ = (func())(nil)
+ _ = (func(x int) float)(nil)
+ _ = (func() func() func())(nil)
+}
diff --git a/libgo/go/go/printer/testdata/expressions.input b/libgo/go/go/printer/testdata/expressions.input
index f545c66057c..1ec12a05049 100644
--- a/libgo/go/go/printer/testdata/expressions.input
+++ b/libgo/go/go/printer/testdata/expressions.input
@@ -676,3 +676,18 @@ func _() {
a...,
)
}
+
+// Literal function types in conversions must be parenthesized;
+// for now go/parser accepts the unparenthesized form where it
+// is non-ambiguous.
+func _() {
+ // these conversions should be rewritten to look
+ // the same as the parenthesized conversions below
+ _ = func()()(nil)
+ _ = func(x int)(float)(nil)
+ _ = func() func() func()()(nil)
+
+ _ = (func()())(nil)
+ _ = (func(x int)(float))(nil)
+ _ = (func() func() func()())(nil)
+}
diff --git a/libgo/go/go/printer/testdata/expressions.raw b/libgo/go/go/printer/testdata/expressions.raw
index 87a4b00836d..062900e0724 100644
--- a/libgo/go/go/printer/testdata/expressions.raw
+++ b/libgo/go/go/printer/testdata/expressions.raw
@@ -647,3 +647,18 @@ func _() {
a...,
)
}
+
+// Literal function types in conversions must be parenthesized;
+// for now go/parser accepts the unparenthesized form where it
+// is non-ambiguous.
+func _() {
+ // these conversions should be rewritten to look
+ // the same as the parenthesized conversions below
+ _ = (func())(nil)
+ _ = (func(x int) float)(nil)
+ _ = (func() func() func())(nil)
+
+ _ = (func())(nil)
+ _ = (func(x int) float)(nil)
+ _ = (func() func() func())(nil)
+}
diff --git a/libgo/go/go/printer/testdata/statements.golden b/libgo/go/go/printer/testdata/statements.golden
index 4d70617bf13..1f3cabe75ec 100644
--- a/libgo/go/go/printer/testdata/statements.golden
+++ b/libgo/go/go/printer/testdata/statements.golden
@@ -527,3 +527,29 @@ AVeryLongLabelThatShouldNotAffectFormatting:
// There should be a single empty line before this comment.
MoreCode()
}
+
+// Formatting of empty statements.
+func _() {
+
+}
+
+func _() {
+}
+
+func _() {
+}
+
+func _() {
+ f()
+}
+
+func _() {
+L:
+ ;
+}
+
+func _() {
+L:
+ ;
+ f()
+}
diff --git a/libgo/go/go/printer/testdata/statements.input b/libgo/go/go/printer/testdata/statements.input
index bd03bc98b77..f93eea89253 100644
--- a/libgo/go/go/printer/testdata/statements.input
+++ b/libgo/go/go/printer/testdata/statements.input
@@ -468,3 +468,27 @@ AVeryLongLabelThatShouldNotAffectFormatting:
// There should be a single empty line before this comment.
MoreCode()
}
+
+
+// Formatting of empty statements.
+func _() {
+ ;;;;;;;;;;;;;;;;;;;;;;;;;
+}
+
+func _() {;;;;;;;;;;;;;;;;;;;;;;;;;
+}
+
+func _() {;;;;;;;;;;;;;;;;;;;;;;;;;}
+
+func _() {
+f();;;;;;;;;;;;;;;;;;;;;;;;;
+}
+
+func _() {
+L:;;;;;;;;;;;;
+}
+
+func _() {
+L:;;;;;;;;;;;;
+ f()
+}
diff --git a/libgo/go/go/scanner/scanner.go b/libgo/go/go/scanner/scanner.go
index 6ef3e14d0bd..3322c58b339 100644
--- a/libgo/go/go/scanner/scanner.go
+++ b/libgo/go/go/scanner/scanner.go
@@ -125,6 +125,9 @@ func (s *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode
s.ErrorCount = 0
s.next()
+ if s.ch == '\uFEFF' {
+ s.next() // ignore BOM
+ }
}
func (s *Scanner) error(offs int, msg string) {
@@ -157,11 +160,15 @@ func (s *Scanner) interpretLineComment(text []byte) {
func (s *Scanner) scanComment() string {
// initial '/' already consumed; s.ch == '/' || s.ch == '*'
offs := s.offset - 1 // position of initial '/'
+ hasCR := false
if s.ch == '/' {
//-style comment
s.next()
for s.ch != '\n' && s.ch >= 0 {
+ if s.ch == '\r' {
+ hasCR = true
+ }
s.next()
}
if offs == s.lineOffset {
@@ -175,6 +182,9 @@ func (s *Scanner) scanComment() string {
s.next()
for s.ch >= 0 {
ch := s.ch
+ if ch == '\r' {
+ hasCR = true
+ }
s.next()
if ch == '*' && s.ch == '/' {
s.next()
@@ -185,7 +195,12 @@ func (s *Scanner) scanComment() string {
s.error(offs, "comment not terminated")
exit:
- return string(s.src[offs:s.offset])
+ lit := s.src[offs:s.offset]
+ if hasCR {
+ lit = stripCR(lit)
+ }
+
+ return string(lit)
}
func (s *Scanner) findLineEnd() bool {
@@ -378,7 +393,7 @@ func (s *Scanner) scanEscape(quote rune) {
for ; i > 0 && s.ch != quote && s.ch >= 0; i-- {
s.next()
}
- if x > max || 0xd800 <= x && x < 0xe000 {
+ if x > max || 0xD800 <= x && x < 0xE000 {
s.error(offs, "escape sequence is invalid Unicode code point")
}
}
@@ -527,6 +542,8 @@ func (s *Scanner) switch4(tok0, tok1 token.Token, ch2 rune, tok2, tok3 token.Tok
// token.IMAG, token.CHAR, token.STRING) or token.COMMENT, the literal string
// has the corresponding value.
//
+// If the returned token is a keyword, the literal string is the keyword.
+//
// If the returned token is token.SEMICOLON, the corresponding
// literal string is ";" if the semicolon was present in the source,
// and "\n" if the semicolon was inserted because of a newline or
@@ -560,12 +577,18 @@ scanAgain:
switch ch := s.ch; {
case isLetter(ch):
lit = s.scanIdentifier()
- tok = token.Lookup(lit)
- switch tok {
- case token.IDENT, token.BREAK, token.CONTINUE, token.FALLTHROUGH, token.RETURN:
+ if len(lit) > 1 {
+ // keywords are longer than one letter - avoid lookup otherwise
+ tok = token.Lookup(lit)
+ switch tok {
+ case token.IDENT, token.BREAK, token.CONTINUE, token.FALLTHROUGH, token.RETURN:
+ insertSemi = true
+ }
+ } else {
insertSemi = true
+ tok = token.IDENT
}
- case digitVal(ch) < 10:
+ case '0' <= ch && ch <= '9':
insertSemi = true
tok, lit = s.scanNumber(false)
default:
@@ -598,7 +621,7 @@ scanAgain:
case ':':
tok = s.switch2(token.COLON, token.DEFINE)
case '.':
- if digitVal(s.ch) < 10 {
+ if '0' <= s.ch && s.ch <= '9' {
insertSemi = true
tok, lit = s.scanNumber(true)
} else if s.ch == '.' {
diff --git a/libgo/go/go/scanner/scanner_test.go b/libgo/go/go/scanner/scanner_test.go
index 06223e23bd8..1c19053e64e 100644
--- a/libgo/go/go/scanner/scanner_test.go
+++ b/libgo/go/go/scanner/scanner_test.go
@@ -6,6 +6,7 @@ package scanner
import (
"go/token"
+ "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -43,12 +44,16 @@ var tokens = [...]elt{
// Special tokens
{token.COMMENT, "/* a comment */", special},
{token.COMMENT, "// a comment \n", special},
+ {token.COMMENT, "/*\r*/", special},
+ {token.COMMENT, "//\r\n", special},
// Identifiers and basic type literals
{token.IDENT, "foobar", literal},
{token.IDENT, "a۰۱۸", literal},
{token.IDENT, "foo६४", literal},
{token.IDENT, "bar9876", literal},
+ {token.IDENT, "ŝ", literal}, // was bug (issue 4000)
+ {token.IDENT, "ŝfoo", literal}, // was bug (issue 4000)
{token.INT, "0", literal},
{token.INT, "1", literal},
{token.INT, "123456789012345678890", literal},
@@ -214,8 +219,6 @@ func checkPos(t *testing.T, lit string, p token.Pos, expected token.Position) {
// Verify that calling Scan() provides the correct results.
func TestScan(t *testing.T) {
- // make source
- src_linecount := newlineCount(string(source))
whitespace_linecount := newlineCount(whitespace)
// error handler
@@ -226,59 +229,81 @@ func TestScan(t *testing.T) {
// verify scan
var s Scanner
s.Init(fset.AddFile("", fset.Base(), len(source)), source, eh, ScanComments|dontInsertSemis)
- index := 0
- // epos is the expected position
+
+ // set up expected position
epos := token.Position{
Filename: "",
Offset: 0,
Line: 1,
Column: 1,
}
+
+ index := 0
for {
pos, tok, lit := s.Scan()
- if lit == "" {
- // no literal value for non-literal tokens
- lit = tok.String()
+
+ // check position
+ if tok == token.EOF {
+ // correction for EOF
+ epos.Line = newlineCount(string(source))
+ epos.Column = 2
}
+ checkPos(t, lit, pos, epos)
+
+ // check token
e := elt{token.EOF, "", special}
if index < len(tokens) {
e = tokens[index]
+ index++
}
- if tok == token.EOF {
- lit = "<EOF>"
- epos.Line = src_linecount
- epos.Column = 2
- }
- checkPos(t, lit, pos, epos)
if tok != e.tok {
t.Errorf("bad token for %q: got %s, expected %s", lit, tok, e.tok)
}
- if e.tok.IsLiteral() {
- // no CRs in raw string literals
- elit := e.lit
- if elit[0] == '`' {
- elit = string(stripCR([]byte(elit)))
- epos.Offset += len(e.lit) - len(lit) // correct position
- }
- if lit != elit {
- t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, elit)
- }
- }
+
+ // check token class
if tokenclass(tok) != e.class {
t.Errorf("bad class for %q: got %d, expected %d", lit, tokenclass(tok), e.class)
}
- epos.Offset += len(lit) + len(whitespace)
- epos.Line += newlineCount(lit) + whitespace_linecount
- if tok == token.COMMENT && lit[1] == '/' {
- // correct for unaccounted '/n' in //-style comment
- epos.Offset++
- epos.Line++
+
+ // check literal
+ elit := ""
+ switch e.tok {
+ case token.COMMENT:
+ // no CRs in comments
+ elit = string(stripCR([]byte(e.lit)))
+ //-style comment literal doesn't contain newline
+ if elit[1] == '/' {
+ elit = elit[0 : len(elit)-1]
+ }
+ case token.IDENT:
+ elit = e.lit
+ case token.SEMICOLON:
+ elit = ";"
+ default:
+ if e.tok.IsLiteral() {
+ // no CRs in raw string literals
+ elit = e.lit
+ if elit[0] == '`' {
+ elit = string(stripCR([]byte(elit)))
+ }
+ } else if e.tok.IsKeyword() {
+ elit = e.lit
+ }
+ }
+ if lit != elit {
+ t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, elit)
}
- index++
+
if tok == token.EOF {
break
}
+
+ // update position
+ epos.Offset += len(e.lit) + len(whitespace)
+ epos.Line += newlineCount(e.lit) + whitespace_linecount
+
}
+
if s.ErrorCount != 0 {
t.Errorf("found %d errors", s.ErrorCount)
}
@@ -321,6 +346,7 @@ var lines = []string{
// # indicates a semicolon present in the source
// $ indicates an automatically inserted semicolon
"",
+ "\ufeff#;", // first BOM is ignored
"#;",
"foo$\n",
"123$\n",
@@ -521,7 +547,7 @@ func TestLineComments(t *testing.T) {
}
}
-// Verify that initializing the same scanner more then once works correctly.
+// Verify that initializing the same scanner more than once works correctly.
func TestInit(t *testing.T) {
var s Scanner
@@ -669,6 +695,7 @@ var errors = []struct {
{"0X", token.INT, 0, "illegal hexadecimal number"},
{"\"abc\x00def\"", token.STRING, 4, "illegal character NUL"},
{"\"abc\x80def\"", token.STRING, 4, "illegal UTF-8 encoding"},
+ {"\ufeff\ufeff", token.ILLEGAL, 3, "illegal character U+FEFF"}, // only first BOM is ignored
}
func TestScanErrors(t *testing.T) {
@@ -683,7 +710,7 @@ func BenchmarkScan(b *testing.B) {
file := fset.AddFile("", fset.Base(), len(source))
var s Scanner
b.StartTimer()
- for i := b.N - 1; i >= 0; i-- {
+ for i := 0; i < b.N; i++ {
s.Init(file, source, nil, ScanComments)
for {
_, tok, _ := s.Scan()
@@ -693,3 +720,26 @@ func BenchmarkScan(b *testing.B) {
}
}
}
+
+func BenchmarkScanFile(b *testing.B) {
+ b.StopTimer()
+ const filename = "scanner.go"
+ src, err := ioutil.ReadFile(filename)
+ if err != nil {
+ panic(err)
+ }
+ fset := token.NewFileSet()
+ file := fset.AddFile(filename, fset.Base(), len(src))
+ b.SetBytes(int64(len(src)))
+ var s Scanner
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ s.Init(file, src, nil, ScanComments)
+ for {
+ _, tok, _ := s.Scan()
+ if tok == token.EOF {
+ break
+ }
+ }
+ }
+}
diff --git a/libgo/go/hash/adler32/adler32.go b/libgo/go/hash/adler32/adler32.go
index 64fe68c443f..7c80796bf9f 100644
--- a/libgo/go/hash/adler32/adler32.go
+++ b/libgo/go/hash/adler32/adler32.go
@@ -3,7 +3,8 @@
// license that can be found in the LICENSE file.
// Package adler32 implements the Adler-32 checksum.
-// Defined in RFC 1950:
+//
+// It is defined in RFC 1950:
// Adler-32 is composed of two sums accumulated per byte: s1 is
// the sum of all bytes, s2 is the sum of all s1 values. Both sums
// are done modulo 65521. s1 is initialized to 1, s2 to zero. The
@@ -14,20 +15,22 @@ package adler32
import "hash"
const (
+ // mod is the largest prime that is less than 65536.
mod = 65521
+ // nmax is the largest n such that
+ // 255 * n * (n+1) / 2 + (n+1) * (mod-1) <= 2^32-1.
+ // It is mentioned in RFC 1950 (search for "5552").
+ nmax = 5552
)
// The size of an Adler-32 checksum in bytes.
const Size = 4
// digest represents the partial evaluation of a checksum.
-type digest struct {
- // invariant: (a < mod && b < mod) || a <= b
- // invariant: a + b + 255 <= 0xffffffff
- a, b uint32
-}
+// The low 16 bits are s1, the high 16 bits are s2.
+type digest uint32
-func (d *digest) Reset() { d.a, d.b = 1, 0 }
+func (d *digest) Reset() { *d = 1 }
// New returns a new hash.Hash32 computing the Adler-32 checksum.
func New() hash.Hash32 {
@@ -40,47 +43,36 @@ func (d *digest) Size() int { return Size }
func (d *digest) BlockSize() int { return 1 }
-// Add p to the running checksum a, b.
-func update(a, b uint32, p []byte) (aa, bb uint32) {
- for _, pi := range p {
- a += uint32(pi)
- b += a
- // invariant: a <= b
- if b > (0xffffffff-255)/2 {
- a %= mod
- b %= mod
- // invariant: a < mod && b < mod
- } else {
- // invariant: a + b + 255 <= 2 * b + 255 <= 0xffffffff
+// Add p to the running checksum d.
+func update(d digest, p []byte) digest {
+ s1, s2 := uint32(d&0xffff), uint32(d>>16)
+ for len(p) > 0 {
+ var q []byte
+ if len(p) > nmax {
+ p, q = p[:nmax], p[nmax:]
}
+ for _, x := range p {
+ s1 += uint32(x)
+ s2 += s1
+ }
+ s1 %= mod
+ s2 %= mod
+ p = q
}
- return a, b
-}
-
-// Return the 32-bit checksum corresponding to a, b.
-func finish(a, b uint32) uint32 {
- if b >= mod {
- a %= mod
- b %= mod
- }
- return b<<16 | a
+ return digest(s2<<16 | s1)
}
func (d *digest) Write(p []byte) (nn int, err error) {
- d.a, d.b = update(d.a, d.b, p)
+ *d = update(*d, p)
return len(p), nil
}
-func (d *digest) Sum32() uint32 { return finish(d.a, d.b) }
+func (d *digest) Sum32() uint32 { return uint32(*d) }
func (d *digest) Sum(in []byte) []byte {
- s := d.Sum32()
- in = append(in, byte(s>>24))
- in = append(in, byte(s>>16))
- in = append(in, byte(s>>8))
- in = append(in, byte(s))
- return in
+ s := uint32(*d)
+ return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
}
// Checksum returns the Adler-32 checksum of data.
-func Checksum(data []byte) uint32 { return finish(update(1, 0, data)) }
+func Checksum(data []byte) uint32 { return uint32(update(1, data)) }
diff --git a/libgo/go/hash/adler32/adler32_test.go b/libgo/go/hash/adler32/adler32_test.go
index 01f931c6859..0e9c938d80c 100644
--- a/libgo/go/hash/adler32/adler32_test.go
+++ b/libgo/go/hash/adler32/adler32_test.go
@@ -5,26 +5,23 @@
package adler32
import (
- "bytes"
- "io"
+ "strings"
"testing"
)
-type _Adler32Test struct {
+var golden = []struct {
out uint32
in string
-}
-
-var golden = []_Adler32Test{
- {0x1, ""},
- {0x620062, "a"},
- {0x12600c4, "ab"},
- {0x24d0127, "abc"},
- {0x3d8018b, "abcd"},
- {0x5c801f0, "abcde"},
- {0x81e0256, "abcdef"},
- {0xadb02bd, "abcdefg"},
- {0xe000325, "abcdefgh"},
+}{
+ {0x00000001, ""},
+ {0x00620062, "a"},
+ {0x012600c4, "ab"},
+ {0x024d0127, "abc"},
+ {0x03d8018b, "abcd"},
+ {0x05c801f0, "abcde"},
+ {0x081e0256, "abcdef"},
+ {0x0adb02bd, "abcdefg"},
+ {0x0e000325, "abcdefgh"},
{0x118e038e, "abcdefghi"},
{0x158603f8, "abcdefghij"},
{0x3f090f02, "Discard medicine more than two years old."},
@@ -48,30 +45,61 @@ var golden = []_Adler32Test{
{0x91dd304f, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"},
{0x2e5d1316, "How can you write a big system without C++? -Paul Glick"},
{0xd0201df6, "'Invariant assertions' is the most elegant programming technique! -Tom Szymanski"},
+ {0x211297c8, strings.Repeat("\xff", 5548) + "8"},
+ {0xbaa198c8, strings.Repeat("\xff", 5549) + "9"},
+ {0x553499be, strings.Repeat("\xff", 5550) + "0"},
+ {0xf0c19abe, strings.Repeat("\xff", 5551) + "1"},
+ {0x8d5c9bbe, strings.Repeat("\xff", 5552) + "2"},
+ {0x2af69cbe, strings.Repeat("\xff", 5553) + "3"},
+ {0xc9809dbe, strings.Repeat("\xff", 5554) + "4"},
+ {0x69189ebe, strings.Repeat("\xff", 5555) + "5"},
+ {0x86af0001, strings.Repeat("\x00", 1e5)},
+ {0x79660b4d, strings.Repeat("a", 1e5)},
+ {0x110588ee, strings.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1e4)},
+}
+
+// checksum is a slow but simple implementation of the Adler-32 checksum.
+// It is a straight port of the sample code in RFC 1950 section 9.
+func checksum(p []byte) uint32 {
+ s1, s2 := uint32(1), uint32(0)
+ for _, x := range p {
+ s1 = (s1 + uint32(x)) % mod
+ s2 = (s2 + s1) % mod
+ }
+ return s2<<16 | s1
}
func TestGolden(t *testing.T) {
- for i := 0; i < len(golden); i++ {
- g := golden[i]
- c := New()
- io.WriteString(c, g.in)
- s := c.Sum32()
- if s != g.out {
- t.Errorf("adler32(%s) = 0x%x want 0x%x", g.in, s, g.out)
- t.FailNow()
+ for _, g := range golden {
+ in := g.in
+ if len(in) > 220 {
+ in = in[:100] + "..." + in[len(in)-100:]
+ }
+ p := []byte(g.in)
+ if got := checksum(p); got != g.out {
+ t.Errorf("simple implementation: checksum(%q) = 0x%x want 0x%x", in, got, g.out)
+ continue
+ }
+ if got := Checksum(p); got != g.out {
+ t.Errorf("optimized implementation: Checksum(%q) = 0x%x want 0x%x", in, got, g.out)
+ continue
}
}
}
-func BenchmarkGolden(b *testing.B) {
- b.StopTimer()
- c := New()
- var buf bytes.Buffer
- for _, g := range golden {
- buf.Write([]byte(g.in))
+func BenchmarkAdler32KB(b *testing.B) {
+ b.SetBytes(1024)
+ data := make([]byte, 1024)
+ for i := range data {
+ data[i] = byte(i)
}
- b.StartTimer()
+ h := New()
+ in := make([]byte, 0, h.Size())
+
+ b.ResetTimer()
for i := 0; i < b.N; i++ {
- c.Write(buf.Bytes())
+ h.Reset()
+ h.Write(data)
+ h.Sum(in)
}
}
diff --git a/libgo/go/hash/crc32/crc32.go b/libgo/go/hash/crc32/crc32.go
index 236d7787289..a2a21a06f95 100644
--- a/libgo/go/hash/crc32/crc32.go
+++ b/libgo/go/hash/crc32/crc32.go
@@ -123,11 +123,7 @@ func (d *digest) Sum32() uint32 { return d.crc }
func (d *digest) Sum(in []byte) []byte {
s := d.Sum32()
- in = append(in, byte(s>>24))
- in = append(in, byte(s>>16))
- in = append(in, byte(s>>8))
- in = append(in, byte(s))
- return in
+ return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
}
// Checksum returns the CRC-32 checksum of data
diff --git a/libgo/go/hash/crc32/crc32_amd64.go b/libgo/go/hash/crc32/crc32_amd64.go
index 83349bc6c22..b5bc6d3cf07 100644
--- a/libgo/go/hash/crc32/crc32_amd64.go
+++ b/libgo/go/hash/crc32/crc32_amd64.go
@@ -13,7 +13,7 @@ func haveSSE42() bool
// castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32
// instruction.
-func castagnoliSSE42(uint32, []byte) uint32
+func castagnoliSSE42(crc uint32, p []byte) uint32
var sse42 = haveSSE42()
diff --git a/libgo/go/hash/crc32/crc32_test.go b/libgo/go/hash/crc32/crc32_test.go
index 7e82dd755e7..75dc26e7cc2 100644
--- a/libgo/go/hash/crc32/crc32_test.go
+++ b/libgo/go/hash/crc32/crc32_test.go
@@ -82,16 +82,18 @@ func TestGolden(t *testing.T) {
}
func BenchmarkCrc32KB(b *testing.B) {
- b.StopTimer()
- data := make([]uint8, 1024)
- for i := 0; i < 1024; i++ {
- data[i] = uint8(i)
+ b.SetBytes(1024)
+ data := make([]byte, 1024)
+ for i := range data {
+ data[i] = byte(i)
}
- c := NewIEEE()
- b.StartTimer()
- b.SetBytes(int64(len(data)))
+ h := NewIEEE()
+ in := make([]byte, 0, h.Size())
+ b.ResetTimer()
for i := 0; i < b.N; i++ {
- c.Write(data)
+ h.Reset()
+ h.Write(data)
+ h.Sum(in)
}
}
diff --git a/libgo/go/hash/crc64/crc64.go b/libgo/go/hash/crc64/crc64.go
index 5b64390f3d5..69258679884 100644
--- a/libgo/go/hash/crc64/crc64.go
+++ b/libgo/go/hash/crc64/crc64.go
@@ -79,15 +79,7 @@ func (d *digest) Sum64() uint64 { return d.crc }
func (d *digest) Sum(in []byte) []byte {
s := d.Sum64()
- in = append(in, byte(s>>56))
- in = append(in, byte(s>>48))
- in = append(in, byte(s>>40))
- in = append(in, byte(s>>32))
- in = append(in, byte(s>>24))
- in = append(in, byte(s>>16))
- in = append(in, byte(s>>8))
- in = append(in, byte(s))
- return in
+ return append(in, byte(s>>56), byte(s>>48), byte(s>>40), byte(s>>32), byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
}
// Checksum returns the CRC-64 checksum of data
diff --git a/libgo/go/hash/crc64/crc64_test.go b/libgo/go/hash/crc64/crc64_test.go
index e932524e092..81a87b56e35 100644
--- a/libgo/go/hash/crc64/crc64_test.go
+++ b/libgo/go/hash/crc64/crc64_test.go
@@ -64,15 +64,18 @@ func TestGolden(t *testing.T) {
}
func BenchmarkCrc64KB(b *testing.B) {
- b.StopTimer()
- data := make([]uint8, 1024)
- for i := 0; i < 1024; i++ {
- data[i] = uint8(i)
+ b.SetBytes(1024)
+ data := make([]byte, 1024)
+ for i := range data {
+ data[i] = byte(i)
}
- c := New(tab)
- b.StartTimer()
+ h := New(tab)
+ in := make([]byte, 0, h.Size())
+ b.ResetTimer()
for i := 0; i < b.N; i++ {
- c.Write(data)
+ h.Reset()
+ h.Write(data)
+ h.Sum(in)
}
}
diff --git a/libgo/go/hash/fnv/fnv.go b/libgo/go/hash/fnv/fnv.go
index ea50198180f..b5ecd4a7c6d 100644
--- a/libgo/go/hash/fnv/fnv.go
+++ b/libgo/go/hash/fnv/fnv.go
@@ -111,44 +111,20 @@ func (s *sum64a) BlockSize() int { return 1 }
func (s *sum32) Sum(in []byte) []byte {
v := uint32(*s)
- in = append(in, byte(v>>24))
- in = append(in, byte(v>>16))
- in = append(in, byte(v>>8))
- in = append(in, byte(v))
- return in
+ return append(in, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}
func (s *sum32a) Sum(in []byte) []byte {
v := uint32(*s)
- in = append(in, byte(v>>24))
- in = append(in, byte(v>>16))
- in = append(in, byte(v>>8))
- in = append(in, byte(v))
- return in
+ return append(in, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}
func (s *sum64) Sum(in []byte) []byte {
v := uint64(*s)
- in = append(in, byte(v>>56))
- in = append(in, byte(v>>48))
- in = append(in, byte(v>>40))
- in = append(in, byte(v>>32))
- in = append(in, byte(v>>24))
- in = append(in, byte(v>>16))
- in = append(in, byte(v>>8))
- in = append(in, byte(v))
- return in
+ return append(in, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}
func (s *sum64a) Sum(in []byte) []byte {
v := uint64(*s)
- in = append(in, byte(v>>56))
- in = append(in, byte(v>>48))
- in = append(in, byte(v>>40))
- in = append(in, byte(v>>32))
- in = append(in, byte(v>>24))
- in = append(in, byte(v>>16))
- in = append(in, byte(v>>8))
- in = append(in, byte(v))
- return in
+ return append(in, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}
diff --git a/libgo/go/hash/fnv/fnv_test.go b/libgo/go/hash/fnv/fnv_test.go
index 17454deda90..89d39b38ad3 100644
--- a/libgo/go/hash/fnv/fnv_test.go
+++ b/libgo/go/hash/fnv/fnv_test.go
@@ -11,8 +11,6 @@ import (
"testing"
)
-const testDataSize = 40
-
type golden struct {
sum []byte
text string
@@ -134,34 +132,34 @@ func testIntegrity(t *testing.T, h hash.Hash) {
}
}
-func Benchmark32(b *testing.B) {
- benchmark(b, New32())
+func BenchmarkFnv32KB(b *testing.B) {
+ benchmarkKB(b, New32())
}
-func Benchmark32a(b *testing.B) {
- benchmark(b, New32a())
+func BenchmarkFnv32aKB(b *testing.B) {
+ benchmarkKB(b, New32a())
}
-func Benchmark64(b *testing.B) {
- benchmark(b, New64())
+func BenchmarkFnv64KB(b *testing.B) {
+ benchmarkKB(b, New64())
}
-func Benchmark64a(b *testing.B) {
- benchmark(b, New64a())
+func BenchmarkFnv64aKB(b *testing.B) {
+ benchmarkKB(b, New64a())
}
-func benchmark(b *testing.B, h hash.Hash) {
- b.ResetTimer()
- b.SetBytes(testDataSize)
- data := make([]byte, testDataSize)
+func benchmarkKB(b *testing.B, h hash.Hash) {
+ b.SetBytes(1024)
+ data := make([]byte, 1024)
for i := range data {
- data[i] = byte(i + 'a')
+ data[i] = byte(i)
}
+ in := make([]byte, 0, h.Size())
- b.StartTimer()
- for todo := b.N; todo != 0; todo-- {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
h.Reset()
h.Write(data)
- h.Sum(nil)
+ h.Sum(in)
}
}
diff --git a/libgo/go/html/entity.go b/libgo/go/html/entity.go
index bd830752359..af8a007ed04 100644
--- a/libgo/go/html/entity.go
+++ b/libgo/go/html/entity.go
@@ -75,2083 +75,2083 @@ var entity = map[string]rune{
"Copf;": '\U00002102',
"Coproduct;": '\U00002210',
"CounterClockwiseContourIntegral;": '\U00002233',
- "Cross;": '\U00002A2F',
- "Cscr;": '\U0001D49E',
- "Cup;": '\U000022D3',
- "CupCap;": '\U0000224D',
- "DD;": '\U00002145',
- "DDotrahd;": '\U00002911',
- "DJcy;": '\U00000402',
- "DScy;": '\U00000405',
- "DZcy;": '\U0000040F',
- "Dagger;": '\U00002021',
- "Darr;": '\U000021A1',
- "Dashv;": '\U00002AE4',
- "Dcaron;": '\U0000010E',
- "Dcy;": '\U00000414',
- "Del;": '\U00002207',
- "Delta;": '\U00000394',
- "Dfr;": '\U0001D507',
- "DiacriticalAcute;": '\U000000B4',
- "DiacriticalDot;": '\U000002D9',
- "DiacriticalDoubleAcute;": '\U000002DD',
- "DiacriticalGrave;": '\U00000060',
- "DiacriticalTilde;": '\U000002DC',
- "Diamond;": '\U000022C4',
- "DifferentialD;": '\U00002146',
- "Dopf;": '\U0001D53B',
- "Dot;": '\U000000A8',
- "DotDot;": '\U000020DC',
- "DotEqual;": '\U00002250',
- "DoubleContourIntegral;": '\U0000222F',
- "DoubleDot;": '\U000000A8',
- "DoubleDownArrow;": '\U000021D3',
- "DoubleLeftArrow;": '\U000021D0',
- "DoubleLeftRightArrow;": '\U000021D4',
- "DoubleLeftTee;": '\U00002AE4',
- "DoubleLongLeftArrow;": '\U000027F8',
- "DoubleLongLeftRightArrow;": '\U000027FA',
- "DoubleLongRightArrow;": '\U000027F9',
- "DoubleRightArrow;": '\U000021D2',
- "DoubleRightTee;": '\U000022A8',
- "DoubleUpArrow;": '\U000021D1',
- "DoubleUpDownArrow;": '\U000021D5',
- "DoubleVerticalBar;": '\U00002225',
- "DownArrow;": '\U00002193',
- "DownArrowBar;": '\U00002913',
- "DownArrowUpArrow;": '\U000021F5',
- "DownBreve;": '\U00000311',
- "DownLeftRightVector;": '\U00002950',
- "DownLeftTeeVector;": '\U0000295E',
- "DownLeftVector;": '\U000021BD',
- "DownLeftVectorBar;": '\U00002956',
- "DownRightTeeVector;": '\U0000295F',
- "DownRightVector;": '\U000021C1',
- "DownRightVectorBar;": '\U00002957',
- "DownTee;": '\U000022A4',
- "DownTeeArrow;": '\U000021A7',
- "Downarrow;": '\U000021D3',
- "Dscr;": '\U0001D49F',
- "Dstrok;": '\U00000110',
- "ENG;": '\U0000014A',
- "ETH;": '\U000000D0',
- "Eacute;": '\U000000C9',
- "Ecaron;": '\U0000011A',
- "Ecirc;": '\U000000CA',
- "Ecy;": '\U0000042D',
- "Edot;": '\U00000116',
- "Efr;": '\U0001D508',
- "Egrave;": '\U000000C8',
- "Element;": '\U00002208',
- "Emacr;": '\U00000112',
- "EmptySmallSquare;": '\U000025FB',
- "EmptyVerySmallSquare;": '\U000025AB',
- "Eogon;": '\U00000118',
- "Eopf;": '\U0001D53C',
- "Epsilon;": '\U00000395',
- "Equal;": '\U00002A75',
- "EqualTilde;": '\U00002242',
- "Equilibrium;": '\U000021CC',
- "Escr;": '\U00002130',
- "Esim;": '\U00002A73',
- "Eta;": '\U00000397',
- "Euml;": '\U000000CB',
- "Exists;": '\U00002203',
- "ExponentialE;": '\U00002147',
- "Fcy;": '\U00000424',
- "Ffr;": '\U0001D509',
- "FilledSmallSquare;": '\U000025FC',
- "FilledVerySmallSquare;": '\U000025AA',
- "Fopf;": '\U0001D53D',
- "ForAll;": '\U00002200',
- "Fouriertrf;": '\U00002131',
- "Fscr;": '\U00002131',
- "GJcy;": '\U00000403',
- "GT;": '\U0000003E',
- "Gamma;": '\U00000393',
- "Gammad;": '\U000003DC',
- "Gbreve;": '\U0000011E',
- "Gcedil;": '\U00000122',
- "Gcirc;": '\U0000011C',
- "Gcy;": '\U00000413',
- "Gdot;": '\U00000120',
- "Gfr;": '\U0001D50A',
- "Gg;": '\U000022D9',
- "Gopf;": '\U0001D53E',
- "GreaterEqual;": '\U00002265',
- "GreaterEqualLess;": '\U000022DB',
- "GreaterFullEqual;": '\U00002267',
- "GreaterGreater;": '\U00002AA2',
- "GreaterLess;": '\U00002277',
- "GreaterSlantEqual;": '\U00002A7E',
- "GreaterTilde;": '\U00002273',
- "Gscr;": '\U0001D4A2',
- "Gt;": '\U0000226B',
- "HARDcy;": '\U0000042A',
- "Hacek;": '\U000002C7',
- "Hat;": '\U0000005E',
- "Hcirc;": '\U00000124',
- "Hfr;": '\U0000210C',
- "HilbertSpace;": '\U0000210B',
- "Hopf;": '\U0000210D',
- "HorizontalLine;": '\U00002500',
- "Hscr;": '\U0000210B',
- "Hstrok;": '\U00000126',
- "HumpDownHump;": '\U0000224E',
- "HumpEqual;": '\U0000224F',
- "IEcy;": '\U00000415',
- "IJlig;": '\U00000132',
- "IOcy;": '\U00000401',
- "Iacute;": '\U000000CD',
- "Icirc;": '\U000000CE',
- "Icy;": '\U00000418',
- "Idot;": '\U00000130',
- "Ifr;": '\U00002111',
- "Igrave;": '\U000000CC',
- "Im;": '\U00002111',
- "Imacr;": '\U0000012A',
- "ImaginaryI;": '\U00002148',
- "Implies;": '\U000021D2',
- "Int;": '\U0000222C',
- "Integral;": '\U0000222B',
- "Intersection;": '\U000022C2',
- "InvisibleComma;": '\U00002063',
- "InvisibleTimes;": '\U00002062',
- "Iogon;": '\U0000012E',
- "Iopf;": '\U0001D540',
- "Iota;": '\U00000399',
- "Iscr;": '\U00002110',
- "Itilde;": '\U00000128',
- "Iukcy;": '\U00000406',
- "Iuml;": '\U000000CF',
- "Jcirc;": '\U00000134',
- "Jcy;": '\U00000419',
- "Jfr;": '\U0001D50D',
- "Jopf;": '\U0001D541',
- "Jscr;": '\U0001D4A5',
- "Jsercy;": '\U00000408',
- "Jukcy;": '\U00000404',
- "KHcy;": '\U00000425',
- "KJcy;": '\U0000040C',
- "Kappa;": '\U0000039A',
- "Kcedil;": '\U00000136',
- "Kcy;": '\U0000041A',
- "Kfr;": '\U0001D50E',
- "Kopf;": '\U0001D542',
- "Kscr;": '\U0001D4A6',
- "LJcy;": '\U00000409',
- "LT;": '\U0000003C',
- "Lacute;": '\U00000139',
- "Lambda;": '\U0000039B',
- "Lang;": '\U000027EA',
- "Laplacetrf;": '\U00002112',
- "Larr;": '\U0000219E',
- "Lcaron;": '\U0000013D',
- "Lcedil;": '\U0000013B',
- "Lcy;": '\U0000041B',
- "LeftAngleBracket;": '\U000027E8',
- "LeftArrow;": '\U00002190',
- "LeftArrowBar;": '\U000021E4',
- "LeftArrowRightArrow;": '\U000021C6',
- "LeftCeiling;": '\U00002308',
- "LeftDoubleBracket;": '\U000027E6',
- "LeftDownTeeVector;": '\U00002961',
- "LeftDownVector;": '\U000021C3',
- "LeftDownVectorBar;": '\U00002959',
- "LeftFloor;": '\U0000230A',
- "LeftRightArrow;": '\U00002194',
- "LeftRightVector;": '\U0000294E',
- "LeftTee;": '\U000022A3',
- "LeftTeeArrow;": '\U000021A4',
- "LeftTeeVector;": '\U0000295A',
- "LeftTriangle;": '\U000022B2',
- "LeftTriangleBar;": '\U000029CF',
- "LeftTriangleEqual;": '\U000022B4',
- "LeftUpDownVector;": '\U00002951',
- "LeftUpTeeVector;": '\U00002960',
- "LeftUpVector;": '\U000021BF',
- "LeftUpVectorBar;": '\U00002958',
- "LeftVector;": '\U000021BC',
- "LeftVectorBar;": '\U00002952',
- "Leftarrow;": '\U000021D0',
- "Leftrightarrow;": '\U000021D4',
- "LessEqualGreater;": '\U000022DA',
- "LessFullEqual;": '\U00002266',
- "LessGreater;": '\U00002276',
- "LessLess;": '\U00002AA1',
- "LessSlantEqual;": '\U00002A7D',
- "LessTilde;": '\U00002272',
- "Lfr;": '\U0001D50F',
- "Ll;": '\U000022D8',
- "Lleftarrow;": '\U000021DA',
- "Lmidot;": '\U0000013F',
- "LongLeftArrow;": '\U000027F5',
- "LongLeftRightArrow;": '\U000027F7',
- "LongRightArrow;": '\U000027F6',
- "Longleftarrow;": '\U000027F8',
- "Longleftrightarrow;": '\U000027FA',
- "Longrightarrow;": '\U000027F9',
- "Lopf;": '\U0001D543',
- "LowerLeftArrow;": '\U00002199',
- "LowerRightArrow;": '\U00002198',
- "Lscr;": '\U00002112',
- "Lsh;": '\U000021B0',
- "Lstrok;": '\U00000141',
- "Lt;": '\U0000226A',
- "Map;": '\U00002905',
- "Mcy;": '\U0000041C',
- "MediumSpace;": '\U0000205F',
- "Mellintrf;": '\U00002133',
- "Mfr;": '\U0001D510',
- "MinusPlus;": '\U00002213',
- "Mopf;": '\U0001D544',
- "Mscr;": '\U00002133',
- "Mu;": '\U0000039C',
- "NJcy;": '\U0000040A',
- "Nacute;": '\U00000143',
- "Ncaron;": '\U00000147',
- "Ncedil;": '\U00000145',
- "Ncy;": '\U0000041D',
- "NegativeMediumSpace;": '\U0000200B',
- "NegativeThickSpace;": '\U0000200B',
- "NegativeThinSpace;": '\U0000200B',
- "NegativeVeryThinSpace;": '\U0000200B',
- "NestedGreaterGreater;": '\U0000226B',
- "NestedLessLess;": '\U0000226A',
- "NewLine;": '\U0000000A',
- "Nfr;": '\U0001D511',
- "NoBreak;": '\U00002060',
- "NonBreakingSpace;": '\U000000A0',
- "Nopf;": '\U00002115',
- "Not;": '\U00002AEC',
- "NotCongruent;": '\U00002262',
- "NotCupCap;": '\U0000226D',
- "NotDoubleVerticalBar;": '\U00002226',
- "NotElement;": '\U00002209',
- "NotEqual;": '\U00002260',
- "NotExists;": '\U00002204',
- "NotGreater;": '\U0000226F',
- "NotGreaterEqual;": '\U00002271',
- "NotGreaterLess;": '\U00002279',
- "NotGreaterTilde;": '\U00002275',
- "NotLeftTriangle;": '\U000022EA',
- "NotLeftTriangleEqual;": '\U000022EC',
- "NotLess;": '\U0000226E',
- "NotLessEqual;": '\U00002270',
- "NotLessGreater;": '\U00002278',
- "NotLessTilde;": '\U00002274',
- "NotPrecedes;": '\U00002280',
- "NotPrecedesSlantEqual;": '\U000022E0',
- "NotReverseElement;": '\U0000220C',
- "NotRightTriangle;": '\U000022EB',
- "NotRightTriangleEqual;": '\U000022ED',
- "NotSquareSubsetEqual;": '\U000022E2',
- "NotSquareSupersetEqual;": '\U000022E3',
- "NotSubsetEqual;": '\U00002288',
- "NotSucceeds;": '\U00002281',
- "NotSucceedsSlantEqual;": '\U000022E1',
- "NotSupersetEqual;": '\U00002289',
- "NotTilde;": '\U00002241',
- "NotTildeEqual;": '\U00002244',
- "NotTildeFullEqual;": '\U00002247',
- "NotTildeTilde;": '\U00002249',
- "NotVerticalBar;": '\U00002224',
- "Nscr;": '\U0001D4A9',
- "Ntilde;": '\U000000D1',
- "Nu;": '\U0000039D',
- "OElig;": '\U00000152',
- "Oacute;": '\U000000D3',
- "Ocirc;": '\U000000D4',
- "Ocy;": '\U0000041E',
- "Odblac;": '\U00000150',
- "Ofr;": '\U0001D512',
- "Ograve;": '\U000000D2',
- "Omacr;": '\U0000014C',
- "Omega;": '\U000003A9',
- "Omicron;": '\U0000039F',
- "Oopf;": '\U0001D546',
- "OpenCurlyDoubleQuote;": '\U0000201C',
- "OpenCurlyQuote;": '\U00002018',
- "Or;": '\U00002A54',
- "Oscr;": '\U0001D4AA',
- "Oslash;": '\U000000D8',
- "Otilde;": '\U000000D5',
- "Otimes;": '\U00002A37',
- "Ouml;": '\U000000D6',
- "OverBar;": '\U0000203E',
- "OverBrace;": '\U000023DE',
- "OverBracket;": '\U000023B4',
- "OverParenthesis;": '\U000023DC',
- "PartialD;": '\U00002202',
- "Pcy;": '\U0000041F',
- "Pfr;": '\U0001D513',
- "Phi;": '\U000003A6',
- "Pi;": '\U000003A0',
- "PlusMinus;": '\U000000B1',
- "Poincareplane;": '\U0000210C',
- "Popf;": '\U00002119',
- "Pr;": '\U00002ABB',
- "Precedes;": '\U0000227A',
- "PrecedesEqual;": '\U00002AAF',
- "PrecedesSlantEqual;": '\U0000227C',
- "PrecedesTilde;": '\U0000227E',
- "Prime;": '\U00002033',
- "Product;": '\U0000220F',
- "Proportion;": '\U00002237',
- "Proportional;": '\U0000221D',
- "Pscr;": '\U0001D4AB',
- "Psi;": '\U000003A8',
- "QUOT;": '\U00000022',
- "Qfr;": '\U0001D514',
- "Qopf;": '\U0000211A',
- "Qscr;": '\U0001D4AC',
- "RBarr;": '\U00002910',
- "REG;": '\U000000AE',
- "Racute;": '\U00000154',
- "Rang;": '\U000027EB',
- "Rarr;": '\U000021A0',
- "Rarrtl;": '\U00002916',
- "Rcaron;": '\U00000158',
- "Rcedil;": '\U00000156',
- "Rcy;": '\U00000420',
- "Re;": '\U0000211C',
- "ReverseElement;": '\U0000220B',
- "ReverseEquilibrium;": '\U000021CB',
- "ReverseUpEquilibrium;": '\U0000296F',
- "Rfr;": '\U0000211C',
- "Rho;": '\U000003A1',
- "RightAngleBracket;": '\U000027E9',
- "RightArrow;": '\U00002192',
- "RightArrowBar;": '\U000021E5',
- "RightArrowLeftArrow;": '\U000021C4',
- "RightCeiling;": '\U00002309',
- "RightDoubleBracket;": '\U000027E7',
- "RightDownTeeVector;": '\U0000295D',
- "RightDownVector;": '\U000021C2',
- "RightDownVectorBar;": '\U00002955',
- "RightFloor;": '\U0000230B',
- "RightTee;": '\U000022A2',
- "RightTeeArrow;": '\U000021A6',
- "RightTeeVector;": '\U0000295B',
- "RightTriangle;": '\U000022B3',
- "RightTriangleBar;": '\U000029D0',
- "RightTriangleEqual;": '\U000022B5',
- "RightUpDownVector;": '\U0000294F',
- "RightUpTeeVector;": '\U0000295C',
- "RightUpVector;": '\U000021BE',
- "RightUpVectorBar;": '\U00002954',
- "RightVector;": '\U000021C0',
- "RightVectorBar;": '\U00002953',
- "Rightarrow;": '\U000021D2',
- "Ropf;": '\U0000211D',
- "RoundImplies;": '\U00002970',
- "Rrightarrow;": '\U000021DB',
- "Rscr;": '\U0000211B',
- "Rsh;": '\U000021B1',
- "RuleDelayed;": '\U000029F4',
- "SHCHcy;": '\U00000429',
- "SHcy;": '\U00000428',
- "SOFTcy;": '\U0000042C',
- "Sacute;": '\U0000015A',
- "Sc;": '\U00002ABC',
- "Scaron;": '\U00000160',
- "Scedil;": '\U0000015E',
- "Scirc;": '\U0000015C',
- "Scy;": '\U00000421',
- "Sfr;": '\U0001D516',
- "ShortDownArrow;": '\U00002193',
- "ShortLeftArrow;": '\U00002190',
- "ShortRightArrow;": '\U00002192',
- "ShortUpArrow;": '\U00002191',
- "Sigma;": '\U000003A3',
- "SmallCircle;": '\U00002218',
- "Sopf;": '\U0001D54A',
- "Sqrt;": '\U0000221A',
- "Square;": '\U000025A1',
- "SquareIntersection;": '\U00002293',
- "SquareSubset;": '\U0000228F',
- "SquareSubsetEqual;": '\U00002291',
- "SquareSuperset;": '\U00002290',
- "SquareSupersetEqual;": '\U00002292',
- "SquareUnion;": '\U00002294',
- "Sscr;": '\U0001D4AE',
- "Star;": '\U000022C6',
- "Sub;": '\U000022D0',
- "Subset;": '\U000022D0',
- "SubsetEqual;": '\U00002286',
- "Succeeds;": '\U0000227B',
- "SucceedsEqual;": '\U00002AB0',
- "SucceedsSlantEqual;": '\U0000227D',
- "SucceedsTilde;": '\U0000227F',
- "SuchThat;": '\U0000220B',
- "Sum;": '\U00002211',
- "Sup;": '\U000022D1',
- "Superset;": '\U00002283',
- "SupersetEqual;": '\U00002287',
- "Supset;": '\U000022D1',
- "THORN;": '\U000000DE',
- "TRADE;": '\U00002122',
- "TSHcy;": '\U0000040B',
- "TScy;": '\U00000426',
- "Tab;": '\U00000009',
- "Tau;": '\U000003A4',
- "Tcaron;": '\U00000164',
- "Tcedil;": '\U00000162',
- "Tcy;": '\U00000422',
- "Tfr;": '\U0001D517',
- "Therefore;": '\U00002234',
- "Theta;": '\U00000398',
- "ThinSpace;": '\U00002009',
- "Tilde;": '\U0000223C',
- "TildeEqual;": '\U00002243',
- "TildeFullEqual;": '\U00002245',
- "TildeTilde;": '\U00002248',
- "Topf;": '\U0001D54B',
- "TripleDot;": '\U000020DB',
- "Tscr;": '\U0001D4AF',
- "Tstrok;": '\U00000166',
- "Uacute;": '\U000000DA',
- "Uarr;": '\U0000219F',
- "Uarrocir;": '\U00002949',
- "Ubrcy;": '\U0000040E',
- "Ubreve;": '\U0000016C',
- "Ucirc;": '\U000000DB',
- "Ucy;": '\U00000423',
- "Udblac;": '\U00000170',
- "Ufr;": '\U0001D518',
- "Ugrave;": '\U000000D9',
- "Umacr;": '\U0000016A',
- "UnderBar;": '\U0000005F',
- "UnderBrace;": '\U000023DF',
- "UnderBracket;": '\U000023B5',
- "UnderParenthesis;": '\U000023DD',
- "Union;": '\U000022C3',
- "UnionPlus;": '\U0000228E',
- "Uogon;": '\U00000172',
- "Uopf;": '\U0001D54C',
- "UpArrow;": '\U00002191',
- "UpArrowBar;": '\U00002912',
- "UpArrowDownArrow;": '\U000021C5',
- "UpDownArrow;": '\U00002195',
- "UpEquilibrium;": '\U0000296E',
- "UpTee;": '\U000022A5',
- "UpTeeArrow;": '\U000021A5',
- "Uparrow;": '\U000021D1',
- "Updownarrow;": '\U000021D5',
- "UpperLeftArrow;": '\U00002196',
- "UpperRightArrow;": '\U00002197',
- "Upsi;": '\U000003D2',
- "Upsilon;": '\U000003A5',
- "Uring;": '\U0000016E',
- "Uscr;": '\U0001D4B0',
- "Utilde;": '\U00000168',
- "Uuml;": '\U000000DC',
- "VDash;": '\U000022AB',
- "Vbar;": '\U00002AEB',
- "Vcy;": '\U00000412',
- "Vdash;": '\U000022A9',
- "Vdashl;": '\U00002AE6',
- "Vee;": '\U000022C1',
- "Verbar;": '\U00002016',
- "Vert;": '\U00002016',
- "VerticalBar;": '\U00002223',
- "VerticalLine;": '\U0000007C',
- "VerticalSeparator;": '\U00002758',
- "VerticalTilde;": '\U00002240',
- "VeryThinSpace;": '\U0000200A',
- "Vfr;": '\U0001D519',
- "Vopf;": '\U0001D54D',
- "Vscr;": '\U0001D4B1',
- "Vvdash;": '\U000022AA',
- "Wcirc;": '\U00000174',
- "Wedge;": '\U000022C0',
- "Wfr;": '\U0001D51A',
- "Wopf;": '\U0001D54E',
- "Wscr;": '\U0001D4B2',
- "Xfr;": '\U0001D51B',
- "Xi;": '\U0000039E',
- "Xopf;": '\U0001D54F',
- "Xscr;": '\U0001D4B3',
- "YAcy;": '\U0000042F',
- "YIcy;": '\U00000407',
- "YUcy;": '\U0000042E',
- "Yacute;": '\U000000DD',
- "Ycirc;": '\U00000176',
- "Ycy;": '\U0000042B',
- "Yfr;": '\U0001D51C',
- "Yopf;": '\U0001D550',
- "Yscr;": '\U0001D4B4',
- "Yuml;": '\U00000178',
- "ZHcy;": '\U00000416',
- "Zacute;": '\U00000179',
- "Zcaron;": '\U0000017D',
- "Zcy;": '\U00000417',
- "Zdot;": '\U0000017B',
- "ZeroWidthSpace;": '\U0000200B',
- "Zeta;": '\U00000396',
- "Zfr;": '\U00002128',
- "Zopf;": '\U00002124',
- "Zscr;": '\U0001D4B5',
- "aacute;": '\U000000E1',
- "abreve;": '\U00000103',
- "ac;": '\U0000223E',
- "acd;": '\U0000223F',
- "acirc;": '\U000000E2',
- "acute;": '\U000000B4',
- "acy;": '\U00000430',
- "aelig;": '\U000000E6',
- "af;": '\U00002061',
- "afr;": '\U0001D51E',
- "agrave;": '\U000000E0',
- "alefsym;": '\U00002135',
- "aleph;": '\U00002135',
- "alpha;": '\U000003B1',
- "amacr;": '\U00000101',
- "amalg;": '\U00002A3F',
- "amp;": '\U00000026',
- "and;": '\U00002227',
- "andand;": '\U00002A55',
- "andd;": '\U00002A5C',
- "andslope;": '\U00002A58',
- "andv;": '\U00002A5A',
- "ang;": '\U00002220',
- "ange;": '\U000029A4',
- "angle;": '\U00002220',
- "angmsd;": '\U00002221',
- "angmsdaa;": '\U000029A8',
- "angmsdab;": '\U000029A9',
- "angmsdac;": '\U000029AA',
- "angmsdad;": '\U000029AB',
- "angmsdae;": '\U000029AC',
- "angmsdaf;": '\U000029AD',
- "angmsdag;": '\U000029AE',
- "angmsdah;": '\U000029AF',
- "angrt;": '\U0000221F',
- "angrtvb;": '\U000022BE',
- "angrtvbd;": '\U0000299D',
- "angsph;": '\U00002222',
- "angst;": '\U000000C5',
- "angzarr;": '\U0000237C',
- "aogon;": '\U00000105',
- "aopf;": '\U0001D552',
- "ap;": '\U00002248',
- "apE;": '\U00002A70',
- "apacir;": '\U00002A6F',
- "ape;": '\U0000224A',
- "apid;": '\U0000224B',
- "apos;": '\U00000027',
- "approx;": '\U00002248',
- "approxeq;": '\U0000224A',
- "aring;": '\U000000E5',
- "ascr;": '\U0001D4B6',
- "ast;": '\U0000002A',
- "asymp;": '\U00002248',
- "asympeq;": '\U0000224D',
- "atilde;": '\U000000E3',
- "auml;": '\U000000E4',
- "awconint;": '\U00002233',
- "awint;": '\U00002A11',
- "bNot;": '\U00002AED',
- "backcong;": '\U0000224C',
- "backepsilon;": '\U000003F6',
- "backprime;": '\U00002035',
- "backsim;": '\U0000223D',
- "backsimeq;": '\U000022CD',
- "barvee;": '\U000022BD',
- "barwed;": '\U00002305',
- "barwedge;": '\U00002305',
- "bbrk;": '\U000023B5',
- "bbrktbrk;": '\U000023B6',
- "bcong;": '\U0000224C',
- "bcy;": '\U00000431',
- "bdquo;": '\U0000201E',
- "becaus;": '\U00002235',
- "because;": '\U00002235',
- "bemptyv;": '\U000029B0',
- "bepsi;": '\U000003F6',
- "bernou;": '\U0000212C',
- "beta;": '\U000003B2',
- "beth;": '\U00002136',
- "between;": '\U0000226C',
- "bfr;": '\U0001D51F',
- "bigcap;": '\U000022C2',
- "bigcirc;": '\U000025EF',
- "bigcup;": '\U000022C3',
- "bigodot;": '\U00002A00',
- "bigoplus;": '\U00002A01',
- "bigotimes;": '\U00002A02',
- "bigsqcup;": '\U00002A06',
- "bigstar;": '\U00002605',
- "bigtriangledown;": '\U000025BD',
- "bigtriangleup;": '\U000025B3',
- "biguplus;": '\U00002A04',
- "bigvee;": '\U000022C1',
- "bigwedge;": '\U000022C0',
- "bkarow;": '\U0000290D',
- "blacklozenge;": '\U000029EB',
- "blacksquare;": '\U000025AA',
- "blacktriangle;": '\U000025B4',
- "blacktriangledown;": '\U000025BE',
- "blacktriangleleft;": '\U000025C2',
- "blacktriangleright;": '\U000025B8',
- "blank;": '\U00002423',
- "blk12;": '\U00002592',
- "blk14;": '\U00002591',
- "blk34;": '\U00002593',
- "block;": '\U00002588',
- "bnot;": '\U00002310',
- "bopf;": '\U0001D553',
- "bot;": '\U000022A5',
- "bottom;": '\U000022A5',
- "bowtie;": '\U000022C8',
- "boxDL;": '\U00002557',
- "boxDR;": '\U00002554',
- "boxDl;": '\U00002556',
- "boxDr;": '\U00002553',
- "boxH;": '\U00002550',
- "boxHD;": '\U00002566',
- "boxHU;": '\U00002569',
- "boxHd;": '\U00002564',
- "boxHu;": '\U00002567',
- "boxUL;": '\U0000255D',
- "boxUR;": '\U0000255A',
- "boxUl;": '\U0000255C',
- "boxUr;": '\U00002559',
- "boxV;": '\U00002551',
- "boxVH;": '\U0000256C',
- "boxVL;": '\U00002563',
- "boxVR;": '\U00002560',
- "boxVh;": '\U0000256B',
- "boxVl;": '\U00002562',
- "boxVr;": '\U0000255F',
- "boxbox;": '\U000029C9',
- "boxdL;": '\U00002555',
- "boxdR;": '\U00002552',
- "boxdl;": '\U00002510',
- "boxdr;": '\U0000250C',
- "boxh;": '\U00002500',
- "boxhD;": '\U00002565',
- "boxhU;": '\U00002568',
- "boxhd;": '\U0000252C',
- "boxhu;": '\U00002534',
- "boxminus;": '\U0000229F',
- "boxplus;": '\U0000229E',
- "boxtimes;": '\U000022A0',
- "boxuL;": '\U0000255B',
- "boxuR;": '\U00002558',
- "boxul;": '\U00002518',
- "boxur;": '\U00002514',
- "boxv;": '\U00002502',
- "boxvH;": '\U0000256A',
- "boxvL;": '\U00002561',
- "boxvR;": '\U0000255E',
- "boxvh;": '\U0000253C',
- "boxvl;": '\U00002524',
- "boxvr;": '\U0000251C',
- "bprime;": '\U00002035',
- "breve;": '\U000002D8',
- "brvbar;": '\U000000A6',
- "bscr;": '\U0001D4B7',
- "bsemi;": '\U0000204F',
- "bsim;": '\U0000223D',
- "bsime;": '\U000022CD',
- "bsol;": '\U0000005C',
- "bsolb;": '\U000029C5',
- "bsolhsub;": '\U000027C8',
- "bull;": '\U00002022',
- "bullet;": '\U00002022',
- "bump;": '\U0000224E',
- "bumpE;": '\U00002AAE',
- "bumpe;": '\U0000224F',
- "bumpeq;": '\U0000224F',
- "cacute;": '\U00000107',
- "cap;": '\U00002229',
- "capand;": '\U00002A44',
- "capbrcup;": '\U00002A49',
- "capcap;": '\U00002A4B',
- "capcup;": '\U00002A47',
- "capdot;": '\U00002A40',
- "caret;": '\U00002041',
- "caron;": '\U000002C7',
- "ccaps;": '\U00002A4D',
- "ccaron;": '\U0000010D',
- "ccedil;": '\U000000E7',
- "ccirc;": '\U00000109',
- "ccups;": '\U00002A4C',
- "ccupssm;": '\U00002A50',
- "cdot;": '\U0000010B',
- "cedil;": '\U000000B8',
- "cemptyv;": '\U000029B2',
- "cent;": '\U000000A2',
- "centerdot;": '\U000000B7',
- "cfr;": '\U0001D520',
- "chcy;": '\U00000447',
- "check;": '\U00002713',
- "checkmark;": '\U00002713',
- "chi;": '\U000003C7',
- "cir;": '\U000025CB',
- "cirE;": '\U000029C3',
- "circ;": '\U000002C6',
- "circeq;": '\U00002257',
- "circlearrowleft;": '\U000021BA',
- "circlearrowright;": '\U000021BB',
- "circledR;": '\U000000AE',
- "circledS;": '\U000024C8',
- "circledast;": '\U0000229B',
- "circledcirc;": '\U0000229A',
- "circleddash;": '\U0000229D',
- "cire;": '\U00002257',
- "cirfnint;": '\U00002A10',
- "cirmid;": '\U00002AEF',
- "cirscir;": '\U000029C2',
- "clubs;": '\U00002663',
- "clubsuit;": '\U00002663',
- "colon;": '\U0000003A',
- "colone;": '\U00002254',
- "coloneq;": '\U00002254',
- "comma;": '\U0000002C',
- "commat;": '\U00000040',
- "comp;": '\U00002201',
- "compfn;": '\U00002218',
- "complement;": '\U00002201',
- "complexes;": '\U00002102',
- "cong;": '\U00002245',
- "congdot;": '\U00002A6D',
- "conint;": '\U0000222E',
- "copf;": '\U0001D554',
- "coprod;": '\U00002210',
- "copy;": '\U000000A9',
- "copysr;": '\U00002117',
- "crarr;": '\U000021B5',
- "cross;": '\U00002717',
- "cscr;": '\U0001D4B8',
- "csub;": '\U00002ACF',
- "csube;": '\U00002AD1',
- "csup;": '\U00002AD0',
- "csupe;": '\U00002AD2',
- "ctdot;": '\U000022EF',
- "cudarrl;": '\U00002938',
- "cudarrr;": '\U00002935',
- "cuepr;": '\U000022DE',
- "cuesc;": '\U000022DF',
- "cularr;": '\U000021B6',
- "cularrp;": '\U0000293D',
- "cup;": '\U0000222A',
- "cupbrcap;": '\U00002A48',
- "cupcap;": '\U00002A46',
- "cupcup;": '\U00002A4A',
- "cupdot;": '\U0000228D',
- "cupor;": '\U00002A45',
- "curarr;": '\U000021B7',
- "curarrm;": '\U0000293C',
- "curlyeqprec;": '\U000022DE',
- "curlyeqsucc;": '\U000022DF',
- "curlyvee;": '\U000022CE',
- "curlywedge;": '\U000022CF',
- "curren;": '\U000000A4',
- "curvearrowleft;": '\U000021B6',
- "curvearrowright;": '\U000021B7',
- "cuvee;": '\U000022CE',
- "cuwed;": '\U000022CF',
- "cwconint;": '\U00002232',
- "cwint;": '\U00002231',
- "cylcty;": '\U0000232D',
- "dArr;": '\U000021D3',
- "dHar;": '\U00002965',
- "dagger;": '\U00002020',
- "daleth;": '\U00002138',
- "darr;": '\U00002193',
- "dash;": '\U00002010',
- "dashv;": '\U000022A3',
- "dbkarow;": '\U0000290F',
- "dblac;": '\U000002DD',
- "dcaron;": '\U0000010F',
- "dcy;": '\U00000434',
- "dd;": '\U00002146',
- "ddagger;": '\U00002021',
- "ddarr;": '\U000021CA',
- "ddotseq;": '\U00002A77',
- "deg;": '\U000000B0',
- "delta;": '\U000003B4',
- "demptyv;": '\U000029B1',
- "dfisht;": '\U0000297F',
- "dfr;": '\U0001D521',
- "dharl;": '\U000021C3',
- "dharr;": '\U000021C2',
- "diam;": '\U000022C4',
- "diamond;": '\U000022C4',
- "diamondsuit;": '\U00002666',
- "diams;": '\U00002666',
- "die;": '\U000000A8',
- "digamma;": '\U000003DD',
- "disin;": '\U000022F2',
- "div;": '\U000000F7',
- "divide;": '\U000000F7',
- "divideontimes;": '\U000022C7',
- "divonx;": '\U000022C7',
- "djcy;": '\U00000452',
- "dlcorn;": '\U0000231E',
- "dlcrop;": '\U0000230D',
- "dollar;": '\U00000024',
- "dopf;": '\U0001D555',
- "dot;": '\U000002D9',
- "doteq;": '\U00002250',
- "doteqdot;": '\U00002251',
- "dotminus;": '\U00002238',
- "dotplus;": '\U00002214',
- "dotsquare;": '\U000022A1',
- "doublebarwedge;": '\U00002306',
- "downarrow;": '\U00002193',
- "downdownarrows;": '\U000021CA',
- "downharpoonleft;": '\U000021C3',
- "downharpoonright;": '\U000021C2',
- "drbkarow;": '\U00002910',
- "drcorn;": '\U0000231F',
- "drcrop;": '\U0000230C',
- "dscr;": '\U0001D4B9',
- "dscy;": '\U00000455',
- "dsol;": '\U000029F6',
- "dstrok;": '\U00000111',
- "dtdot;": '\U000022F1',
- "dtri;": '\U000025BF',
- "dtrif;": '\U000025BE',
- "duarr;": '\U000021F5',
- "duhar;": '\U0000296F',
- "dwangle;": '\U000029A6',
- "dzcy;": '\U0000045F',
- "dzigrarr;": '\U000027FF',
- "eDDot;": '\U00002A77',
- "eDot;": '\U00002251',
- "eacute;": '\U000000E9',
- "easter;": '\U00002A6E',
- "ecaron;": '\U0000011B',
- "ecir;": '\U00002256',
- "ecirc;": '\U000000EA',
- "ecolon;": '\U00002255',
- "ecy;": '\U0000044D',
- "edot;": '\U00000117',
- "ee;": '\U00002147',
- "efDot;": '\U00002252',
- "efr;": '\U0001D522',
- "eg;": '\U00002A9A',
- "egrave;": '\U000000E8',
- "egs;": '\U00002A96',
- "egsdot;": '\U00002A98',
- "el;": '\U00002A99',
- "elinters;": '\U000023E7',
- "ell;": '\U00002113',
- "els;": '\U00002A95',
- "elsdot;": '\U00002A97',
- "emacr;": '\U00000113',
- "empty;": '\U00002205',
- "emptyset;": '\U00002205',
- "emptyv;": '\U00002205',
- "emsp;": '\U00002003',
- "emsp13;": '\U00002004',
- "emsp14;": '\U00002005',
- "eng;": '\U0000014B',
- "ensp;": '\U00002002',
- "eogon;": '\U00000119',
- "eopf;": '\U0001D556',
- "epar;": '\U000022D5',
- "eparsl;": '\U000029E3',
- "eplus;": '\U00002A71',
- "epsi;": '\U000003B5',
- "epsilon;": '\U000003B5',
- "epsiv;": '\U000003F5',
- "eqcirc;": '\U00002256',
- "eqcolon;": '\U00002255',
- "eqsim;": '\U00002242',
- "eqslantgtr;": '\U00002A96',
- "eqslantless;": '\U00002A95',
- "equals;": '\U0000003D',
- "equest;": '\U0000225F',
- "equiv;": '\U00002261',
- "equivDD;": '\U00002A78',
- "eqvparsl;": '\U000029E5',
- "erDot;": '\U00002253',
- "erarr;": '\U00002971',
- "escr;": '\U0000212F',
- "esdot;": '\U00002250',
- "esim;": '\U00002242',
- "eta;": '\U000003B7',
- "eth;": '\U000000F0',
- "euml;": '\U000000EB',
- "euro;": '\U000020AC',
- "excl;": '\U00000021',
- "exist;": '\U00002203',
- "expectation;": '\U00002130',
- "exponentiale;": '\U00002147',
- "fallingdotseq;": '\U00002252',
- "fcy;": '\U00000444',
- "female;": '\U00002640',
- "ffilig;": '\U0000FB03',
- "fflig;": '\U0000FB00',
- "ffllig;": '\U0000FB04',
- "ffr;": '\U0001D523',
- "filig;": '\U0000FB01',
- "flat;": '\U0000266D',
- "fllig;": '\U0000FB02',
- "fltns;": '\U000025B1',
- "fnof;": '\U00000192',
- "fopf;": '\U0001D557',
- "forall;": '\U00002200',
- "fork;": '\U000022D4',
- "forkv;": '\U00002AD9',
- "fpartint;": '\U00002A0D',
- "frac12;": '\U000000BD',
- "frac13;": '\U00002153',
- "frac14;": '\U000000BC',
- "frac15;": '\U00002155',
- "frac16;": '\U00002159',
- "frac18;": '\U0000215B',
- "frac23;": '\U00002154',
- "frac25;": '\U00002156',
- "frac34;": '\U000000BE',
- "frac35;": '\U00002157',
- "frac38;": '\U0000215C',
- "frac45;": '\U00002158',
- "frac56;": '\U0000215A',
- "frac58;": '\U0000215D',
- "frac78;": '\U0000215E',
- "frasl;": '\U00002044',
- "frown;": '\U00002322',
- "fscr;": '\U0001D4BB',
- "gE;": '\U00002267',
- "gEl;": '\U00002A8C',
- "gacute;": '\U000001F5',
- "gamma;": '\U000003B3',
- "gammad;": '\U000003DD',
- "gap;": '\U00002A86',
- "gbreve;": '\U0000011F',
- "gcirc;": '\U0000011D',
- "gcy;": '\U00000433',
- "gdot;": '\U00000121',
- "ge;": '\U00002265',
- "gel;": '\U000022DB',
- "geq;": '\U00002265',
- "geqq;": '\U00002267',
- "geqslant;": '\U00002A7E',
- "ges;": '\U00002A7E',
- "gescc;": '\U00002AA9',
- "gesdot;": '\U00002A80',
- "gesdoto;": '\U00002A82',
- "gesdotol;": '\U00002A84',
- "gesles;": '\U00002A94',
- "gfr;": '\U0001D524',
- "gg;": '\U0000226B',
- "ggg;": '\U000022D9',
- "gimel;": '\U00002137',
- "gjcy;": '\U00000453',
- "gl;": '\U00002277',
- "glE;": '\U00002A92',
- "gla;": '\U00002AA5',
- "glj;": '\U00002AA4',
- "gnE;": '\U00002269',
- "gnap;": '\U00002A8A',
- "gnapprox;": '\U00002A8A',
- "gne;": '\U00002A88',
- "gneq;": '\U00002A88',
- "gneqq;": '\U00002269',
- "gnsim;": '\U000022E7',
- "gopf;": '\U0001D558',
- "grave;": '\U00000060',
- "gscr;": '\U0000210A',
- "gsim;": '\U00002273',
- "gsime;": '\U00002A8E',
- "gsiml;": '\U00002A90',
- "gt;": '\U0000003E',
- "gtcc;": '\U00002AA7',
- "gtcir;": '\U00002A7A',
- "gtdot;": '\U000022D7',
- "gtlPar;": '\U00002995',
- "gtquest;": '\U00002A7C',
- "gtrapprox;": '\U00002A86',
- "gtrarr;": '\U00002978',
- "gtrdot;": '\U000022D7',
- "gtreqless;": '\U000022DB',
- "gtreqqless;": '\U00002A8C',
- "gtrless;": '\U00002277',
- "gtrsim;": '\U00002273',
- "hArr;": '\U000021D4',
- "hairsp;": '\U0000200A',
- "half;": '\U000000BD',
- "hamilt;": '\U0000210B',
- "hardcy;": '\U0000044A',
- "harr;": '\U00002194',
- "harrcir;": '\U00002948',
- "harrw;": '\U000021AD',
- "hbar;": '\U0000210F',
- "hcirc;": '\U00000125',
- "hearts;": '\U00002665',
- "heartsuit;": '\U00002665',
- "hellip;": '\U00002026',
- "hercon;": '\U000022B9',
- "hfr;": '\U0001D525',
- "hksearow;": '\U00002925',
- "hkswarow;": '\U00002926',
- "hoarr;": '\U000021FF',
- "homtht;": '\U0000223B',
- "hookleftarrow;": '\U000021A9',
- "hookrightarrow;": '\U000021AA',
- "hopf;": '\U0001D559',
- "horbar;": '\U00002015',
- "hscr;": '\U0001D4BD',
- "hslash;": '\U0000210F',
- "hstrok;": '\U00000127',
- "hybull;": '\U00002043',
- "hyphen;": '\U00002010',
- "iacute;": '\U000000ED',
- "ic;": '\U00002063',
- "icirc;": '\U000000EE',
- "icy;": '\U00000438',
- "iecy;": '\U00000435',
- "iexcl;": '\U000000A1',
- "iff;": '\U000021D4',
- "ifr;": '\U0001D526',
- "igrave;": '\U000000EC',
- "ii;": '\U00002148',
- "iiiint;": '\U00002A0C',
- "iiint;": '\U0000222D',
- "iinfin;": '\U000029DC',
- "iiota;": '\U00002129',
- "ijlig;": '\U00000133',
- "imacr;": '\U0000012B',
- "image;": '\U00002111',
- "imagline;": '\U00002110',
- "imagpart;": '\U00002111',
- "imath;": '\U00000131',
- "imof;": '\U000022B7',
- "imped;": '\U000001B5',
- "in;": '\U00002208',
- "incare;": '\U00002105',
- "infin;": '\U0000221E',
- "infintie;": '\U000029DD',
- "inodot;": '\U00000131',
- "int;": '\U0000222B',
- "intcal;": '\U000022BA',
- "integers;": '\U00002124',
- "intercal;": '\U000022BA',
- "intlarhk;": '\U00002A17',
- "intprod;": '\U00002A3C',
- "iocy;": '\U00000451',
- "iogon;": '\U0000012F',
- "iopf;": '\U0001D55A',
- "iota;": '\U000003B9',
- "iprod;": '\U00002A3C',
- "iquest;": '\U000000BF',
- "iscr;": '\U0001D4BE',
- "isin;": '\U00002208',
- "isinE;": '\U000022F9',
- "isindot;": '\U000022F5',
- "isins;": '\U000022F4',
- "isinsv;": '\U000022F3',
- "isinv;": '\U00002208',
- "it;": '\U00002062',
- "itilde;": '\U00000129',
- "iukcy;": '\U00000456',
- "iuml;": '\U000000EF',
- "jcirc;": '\U00000135',
- "jcy;": '\U00000439',
- "jfr;": '\U0001D527',
- "jmath;": '\U00000237',
- "jopf;": '\U0001D55B',
- "jscr;": '\U0001D4BF',
- "jsercy;": '\U00000458',
- "jukcy;": '\U00000454',
- "kappa;": '\U000003BA',
- "kappav;": '\U000003F0',
- "kcedil;": '\U00000137',
- "kcy;": '\U0000043A',
- "kfr;": '\U0001D528',
- "kgreen;": '\U00000138',
- "khcy;": '\U00000445',
- "kjcy;": '\U0000045C',
- "kopf;": '\U0001D55C',
- "kscr;": '\U0001D4C0',
- "lAarr;": '\U000021DA',
- "lArr;": '\U000021D0',
- "lAtail;": '\U0000291B',
- "lBarr;": '\U0000290E',
- "lE;": '\U00002266',
- "lEg;": '\U00002A8B',
- "lHar;": '\U00002962',
- "lacute;": '\U0000013A',
- "laemptyv;": '\U000029B4',
- "lagran;": '\U00002112',
- "lambda;": '\U000003BB',
- "lang;": '\U000027E8',
- "langd;": '\U00002991',
- "langle;": '\U000027E8',
- "lap;": '\U00002A85',
- "laquo;": '\U000000AB',
- "larr;": '\U00002190',
- "larrb;": '\U000021E4',
- "larrbfs;": '\U0000291F',
- "larrfs;": '\U0000291D',
- "larrhk;": '\U000021A9',
- "larrlp;": '\U000021AB',
- "larrpl;": '\U00002939',
- "larrsim;": '\U00002973',
- "larrtl;": '\U000021A2',
- "lat;": '\U00002AAB',
- "latail;": '\U00002919',
- "late;": '\U00002AAD',
- "lbarr;": '\U0000290C',
- "lbbrk;": '\U00002772',
- "lbrace;": '\U0000007B',
- "lbrack;": '\U0000005B',
- "lbrke;": '\U0000298B',
- "lbrksld;": '\U0000298F',
- "lbrkslu;": '\U0000298D',
- "lcaron;": '\U0000013E',
- "lcedil;": '\U0000013C',
- "lceil;": '\U00002308',
- "lcub;": '\U0000007B',
- "lcy;": '\U0000043B',
- "ldca;": '\U00002936',
- "ldquo;": '\U0000201C',
- "ldquor;": '\U0000201E',
- "ldrdhar;": '\U00002967',
- "ldrushar;": '\U0000294B',
- "ldsh;": '\U000021B2',
- "le;": '\U00002264',
- "leftarrow;": '\U00002190',
- "leftarrowtail;": '\U000021A2',
- "leftharpoondown;": '\U000021BD',
- "leftharpoonup;": '\U000021BC',
- "leftleftarrows;": '\U000021C7',
- "leftrightarrow;": '\U00002194',
- "leftrightarrows;": '\U000021C6',
- "leftrightharpoons;": '\U000021CB',
- "leftrightsquigarrow;": '\U000021AD',
- "leftthreetimes;": '\U000022CB',
- "leg;": '\U000022DA',
- "leq;": '\U00002264',
- "leqq;": '\U00002266',
- "leqslant;": '\U00002A7D',
- "les;": '\U00002A7D',
- "lescc;": '\U00002AA8',
- "lesdot;": '\U00002A7F',
- "lesdoto;": '\U00002A81',
- "lesdotor;": '\U00002A83',
- "lesges;": '\U00002A93',
- "lessapprox;": '\U00002A85',
- "lessdot;": '\U000022D6',
- "lesseqgtr;": '\U000022DA',
- "lesseqqgtr;": '\U00002A8B',
- "lessgtr;": '\U00002276',
- "lesssim;": '\U00002272',
- "lfisht;": '\U0000297C',
- "lfloor;": '\U0000230A',
- "lfr;": '\U0001D529',
- "lg;": '\U00002276',
- "lgE;": '\U00002A91',
- "lhard;": '\U000021BD',
- "lharu;": '\U000021BC',
- "lharul;": '\U0000296A',
- "lhblk;": '\U00002584',
- "ljcy;": '\U00000459',
- "ll;": '\U0000226A',
- "llarr;": '\U000021C7',
- "llcorner;": '\U0000231E',
- "llhard;": '\U0000296B',
- "lltri;": '\U000025FA',
- "lmidot;": '\U00000140',
- "lmoust;": '\U000023B0',
- "lmoustache;": '\U000023B0',
- "lnE;": '\U00002268',
- "lnap;": '\U00002A89',
- "lnapprox;": '\U00002A89',
- "lne;": '\U00002A87',
- "lneq;": '\U00002A87',
- "lneqq;": '\U00002268',
- "lnsim;": '\U000022E6',
- "loang;": '\U000027EC',
- "loarr;": '\U000021FD',
- "lobrk;": '\U000027E6',
- "longleftarrow;": '\U000027F5',
- "longleftrightarrow;": '\U000027F7',
- "longmapsto;": '\U000027FC',
- "longrightarrow;": '\U000027F6',
- "looparrowleft;": '\U000021AB',
- "looparrowright;": '\U000021AC',
- "lopar;": '\U00002985',
- "lopf;": '\U0001D55D',
- "loplus;": '\U00002A2D',
- "lotimes;": '\U00002A34',
- "lowast;": '\U00002217',
- "lowbar;": '\U0000005F',
- "loz;": '\U000025CA',
- "lozenge;": '\U000025CA',
- "lozf;": '\U000029EB',
- "lpar;": '\U00000028',
- "lparlt;": '\U00002993',
- "lrarr;": '\U000021C6',
- "lrcorner;": '\U0000231F',
- "lrhar;": '\U000021CB',
- "lrhard;": '\U0000296D',
- "lrm;": '\U0000200E',
- "lrtri;": '\U000022BF',
- "lsaquo;": '\U00002039',
- "lscr;": '\U0001D4C1',
- "lsh;": '\U000021B0',
- "lsim;": '\U00002272',
- "lsime;": '\U00002A8D',
- "lsimg;": '\U00002A8F',
- "lsqb;": '\U0000005B',
- "lsquo;": '\U00002018',
- "lsquor;": '\U0000201A',
- "lstrok;": '\U00000142',
- "lt;": '\U0000003C',
- "ltcc;": '\U00002AA6',
- "ltcir;": '\U00002A79',
- "ltdot;": '\U000022D6',
- "lthree;": '\U000022CB',
- "ltimes;": '\U000022C9',
- "ltlarr;": '\U00002976',
- "ltquest;": '\U00002A7B',
- "ltrPar;": '\U00002996',
- "ltri;": '\U000025C3',
- "ltrie;": '\U000022B4',
- "ltrif;": '\U000025C2',
- "lurdshar;": '\U0000294A',
- "luruhar;": '\U00002966',
- "mDDot;": '\U0000223A',
- "macr;": '\U000000AF',
- "male;": '\U00002642',
- "malt;": '\U00002720',
- "maltese;": '\U00002720',
- "map;": '\U000021A6',
- "mapsto;": '\U000021A6',
- "mapstodown;": '\U000021A7',
- "mapstoleft;": '\U000021A4',
- "mapstoup;": '\U000021A5',
- "marker;": '\U000025AE',
- "mcomma;": '\U00002A29',
- "mcy;": '\U0000043C',
- "mdash;": '\U00002014',
- "measuredangle;": '\U00002221',
- "mfr;": '\U0001D52A',
- "mho;": '\U00002127',
- "micro;": '\U000000B5',
- "mid;": '\U00002223',
- "midast;": '\U0000002A',
- "midcir;": '\U00002AF0',
- "middot;": '\U000000B7',
- "minus;": '\U00002212',
- "minusb;": '\U0000229F',
- "minusd;": '\U00002238',
- "minusdu;": '\U00002A2A',
- "mlcp;": '\U00002ADB',
- "mldr;": '\U00002026',
- "mnplus;": '\U00002213',
- "models;": '\U000022A7',
- "mopf;": '\U0001D55E',
- "mp;": '\U00002213',
- "mscr;": '\U0001D4C2',
- "mstpos;": '\U0000223E',
- "mu;": '\U000003BC',
- "multimap;": '\U000022B8',
- "mumap;": '\U000022B8',
- "nLeftarrow;": '\U000021CD',
- "nLeftrightarrow;": '\U000021CE',
- "nRightarrow;": '\U000021CF',
- "nVDash;": '\U000022AF',
- "nVdash;": '\U000022AE',
- "nabla;": '\U00002207',
- "nacute;": '\U00000144',
- "nap;": '\U00002249',
- "napos;": '\U00000149',
- "napprox;": '\U00002249',
- "natur;": '\U0000266E',
- "natural;": '\U0000266E',
- "naturals;": '\U00002115',
- "nbsp;": '\U000000A0',
- "ncap;": '\U00002A43',
- "ncaron;": '\U00000148',
- "ncedil;": '\U00000146',
- "ncong;": '\U00002247',
- "ncup;": '\U00002A42',
- "ncy;": '\U0000043D',
- "ndash;": '\U00002013',
- "ne;": '\U00002260',
- "neArr;": '\U000021D7',
- "nearhk;": '\U00002924',
- "nearr;": '\U00002197',
- "nearrow;": '\U00002197',
- "nequiv;": '\U00002262',
- "nesear;": '\U00002928',
- "nexist;": '\U00002204',
- "nexists;": '\U00002204',
- "nfr;": '\U0001D52B',
- "nge;": '\U00002271',
- "ngeq;": '\U00002271',
- "ngsim;": '\U00002275',
- "ngt;": '\U0000226F',
- "ngtr;": '\U0000226F',
- "nhArr;": '\U000021CE',
- "nharr;": '\U000021AE',
- "nhpar;": '\U00002AF2',
- "ni;": '\U0000220B',
- "nis;": '\U000022FC',
- "nisd;": '\U000022FA',
- "niv;": '\U0000220B',
- "njcy;": '\U0000045A',
- "nlArr;": '\U000021CD',
- "nlarr;": '\U0000219A',
- "nldr;": '\U00002025',
- "nle;": '\U00002270',
- "nleftarrow;": '\U0000219A',
- "nleftrightarrow;": '\U000021AE',
- "nleq;": '\U00002270',
- "nless;": '\U0000226E',
- "nlsim;": '\U00002274',
- "nlt;": '\U0000226E',
- "nltri;": '\U000022EA',
- "nltrie;": '\U000022EC',
- "nmid;": '\U00002224',
- "nopf;": '\U0001D55F',
- "not;": '\U000000AC',
- "notin;": '\U00002209',
- "notinva;": '\U00002209',
- "notinvb;": '\U000022F7',
- "notinvc;": '\U000022F6',
- "notni;": '\U0000220C',
- "notniva;": '\U0000220C',
- "notnivb;": '\U000022FE',
- "notnivc;": '\U000022FD',
- "npar;": '\U00002226',
- "nparallel;": '\U00002226',
- "npolint;": '\U00002A14',
- "npr;": '\U00002280',
- "nprcue;": '\U000022E0',
- "nprec;": '\U00002280',
- "nrArr;": '\U000021CF',
- "nrarr;": '\U0000219B',
- "nrightarrow;": '\U0000219B',
- "nrtri;": '\U000022EB',
- "nrtrie;": '\U000022ED',
- "nsc;": '\U00002281',
- "nsccue;": '\U000022E1',
- "nscr;": '\U0001D4C3',
- "nshortmid;": '\U00002224',
- "nshortparallel;": '\U00002226',
- "nsim;": '\U00002241',
- "nsime;": '\U00002244',
- "nsimeq;": '\U00002244',
- "nsmid;": '\U00002224',
- "nspar;": '\U00002226',
- "nsqsube;": '\U000022E2',
- "nsqsupe;": '\U000022E3',
- "nsub;": '\U00002284',
- "nsube;": '\U00002288',
- "nsubseteq;": '\U00002288',
- "nsucc;": '\U00002281',
- "nsup;": '\U00002285',
- "nsupe;": '\U00002289',
- "nsupseteq;": '\U00002289',
- "ntgl;": '\U00002279',
- "ntilde;": '\U000000F1',
- "ntlg;": '\U00002278',
- "ntriangleleft;": '\U000022EA',
- "ntrianglelefteq;": '\U000022EC',
- "ntriangleright;": '\U000022EB',
- "ntrianglerighteq;": '\U000022ED',
- "nu;": '\U000003BD',
- "num;": '\U00000023',
- "numero;": '\U00002116',
- "numsp;": '\U00002007',
- "nvDash;": '\U000022AD',
- "nvHarr;": '\U00002904',
- "nvdash;": '\U000022AC',
- "nvinfin;": '\U000029DE',
- "nvlArr;": '\U00002902',
- "nvrArr;": '\U00002903',
- "nwArr;": '\U000021D6',
- "nwarhk;": '\U00002923',
- "nwarr;": '\U00002196',
- "nwarrow;": '\U00002196',
- "nwnear;": '\U00002927',
- "oS;": '\U000024C8',
- "oacute;": '\U000000F3',
- "oast;": '\U0000229B',
- "ocir;": '\U0000229A',
- "ocirc;": '\U000000F4',
- "ocy;": '\U0000043E',
- "odash;": '\U0000229D',
- "odblac;": '\U00000151',
- "odiv;": '\U00002A38',
- "odot;": '\U00002299',
- "odsold;": '\U000029BC',
- "oelig;": '\U00000153',
- "ofcir;": '\U000029BF',
- "ofr;": '\U0001D52C',
- "ogon;": '\U000002DB',
- "ograve;": '\U000000F2',
- "ogt;": '\U000029C1',
- "ohbar;": '\U000029B5',
- "ohm;": '\U000003A9',
- "oint;": '\U0000222E',
- "olarr;": '\U000021BA',
- "olcir;": '\U000029BE',
- "olcross;": '\U000029BB',
- "oline;": '\U0000203E',
- "olt;": '\U000029C0',
- "omacr;": '\U0000014D',
- "omega;": '\U000003C9',
- "omicron;": '\U000003BF',
- "omid;": '\U000029B6',
- "ominus;": '\U00002296',
- "oopf;": '\U0001D560',
- "opar;": '\U000029B7',
- "operp;": '\U000029B9',
- "oplus;": '\U00002295',
- "or;": '\U00002228',
- "orarr;": '\U000021BB',
- "ord;": '\U00002A5D',
- "order;": '\U00002134',
- "orderof;": '\U00002134',
- "ordf;": '\U000000AA',
- "ordm;": '\U000000BA',
- "origof;": '\U000022B6',
- "oror;": '\U00002A56',
- "orslope;": '\U00002A57',
- "orv;": '\U00002A5B',
- "oscr;": '\U00002134',
- "oslash;": '\U000000F8',
- "osol;": '\U00002298',
- "otilde;": '\U000000F5',
- "otimes;": '\U00002297',
- "otimesas;": '\U00002A36',
- "ouml;": '\U000000F6',
- "ovbar;": '\U0000233D',
- "par;": '\U00002225',
- "para;": '\U000000B6',
- "parallel;": '\U00002225',
- "parsim;": '\U00002AF3',
- "parsl;": '\U00002AFD',
- "part;": '\U00002202',
- "pcy;": '\U0000043F',
- "percnt;": '\U00000025',
- "period;": '\U0000002E',
- "permil;": '\U00002030',
- "perp;": '\U000022A5',
- "pertenk;": '\U00002031',
- "pfr;": '\U0001D52D',
- "phi;": '\U000003C6',
- "phiv;": '\U000003D5',
- "phmmat;": '\U00002133',
- "phone;": '\U0000260E',
- "pi;": '\U000003C0',
- "pitchfork;": '\U000022D4',
- "piv;": '\U000003D6',
- "planck;": '\U0000210F',
- "planckh;": '\U0000210E',
- "plankv;": '\U0000210F',
- "plus;": '\U0000002B',
- "plusacir;": '\U00002A23',
- "plusb;": '\U0000229E',
- "pluscir;": '\U00002A22',
- "plusdo;": '\U00002214',
- "plusdu;": '\U00002A25',
- "pluse;": '\U00002A72',
- "plusmn;": '\U000000B1',
- "plussim;": '\U00002A26',
- "plustwo;": '\U00002A27',
- "pm;": '\U000000B1',
- "pointint;": '\U00002A15',
- "popf;": '\U0001D561',
- "pound;": '\U000000A3',
- "pr;": '\U0000227A',
- "prE;": '\U00002AB3',
- "prap;": '\U00002AB7',
- "prcue;": '\U0000227C',
- "pre;": '\U00002AAF',
- "prec;": '\U0000227A',
- "precapprox;": '\U00002AB7',
- "preccurlyeq;": '\U0000227C',
- "preceq;": '\U00002AAF',
- "precnapprox;": '\U00002AB9',
- "precneqq;": '\U00002AB5',
- "precnsim;": '\U000022E8',
- "precsim;": '\U0000227E',
- "prime;": '\U00002032',
- "primes;": '\U00002119',
- "prnE;": '\U00002AB5',
- "prnap;": '\U00002AB9',
- "prnsim;": '\U000022E8',
- "prod;": '\U0000220F',
- "profalar;": '\U0000232E',
- "profline;": '\U00002312',
- "profsurf;": '\U00002313',
- "prop;": '\U0000221D',
- "propto;": '\U0000221D',
- "prsim;": '\U0000227E',
- "prurel;": '\U000022B0',
- "pscr;": '\U0001D4C5',
- "psi;": '\U000003C8',
- "puncsp;": '\U00002008',
- "qfr;": '\U0001D52E',
- "qint;": '\U00002A0C',
- "qopf;": '\U0001D562',
- "qprime;": '\U00002057',
- "qscr;": '\U0001D4C6',
- "quaternions;": '\U0000210D',
- "quatint;": '\U00002A16',
- "quest;": '\U0000003F',
- "questeq;": '\U0000225F',
- "quot;": '\U00000022',
- "rAarr;": '\U000021DB',
- "rArr;": '\U000021D2',
- "rAtail;": '\U0000291C',
- "rBarr;": '\U0000290F',
- "rHar;": '\U00002964',
- "racute;": '\U00000155',
- "radic;": '\U0000221A',
- "raemptyv;": '\U000029B3',
- "rang;": '\U000027E9',
- "rangd;": '\U00002992',
- "range;": '\U000029A5',
- "rangle;": '\U000027E9',
- "raquo;": '\U000000BB',
- "rarr;": '\U00002192',
- "rarrap;": '\U00002975',
- "rarrb;": '\U000021E5',
- "rarrbfs;": '\U00002920',
- "rarrc;": '\U00002933',
- "rarrfs;": '\U0000291E',
- "rarrhk;": '\U000021AA',
- "rarrlp;": '\U000021AC',
- "rarrpl;": '\U00002945',
- "rarrsim;": '\U00002974',
- "rarrtl;": '\U000021A3',
- "rarrw;": '\U0000219D',
- "ratail;": '\U0000291A',
- "ratio;": '\U00002236',
- "rationals;": '\U0000211A',
- "rbarr;": '\U0000290D',
- "rbbrk;": '\U00002773',
- "rbrace;": '\U0000007D',
- "rbrack;": '\U0000005D',
- "rbrke;": '\U0000298C',
- "rbrksld;": '\U0000298E',
- "rbrkslu;": '\U00002990',
- "rcaron;": '\U00000159',
- "rcedil;": '\U00000157',
- "rceil;": '\U00002309',
- "rcub;": '\U0000007D',
- "rcy;": '\U00000440',
- "rdca;": '\U00002937',
- "rdldhar;": '\U00002969',
- "rdquo;": '\U0000201D',
- "rdquor;": '\U0000201D',
- "rdsh;": '\U000021B3',
- "real;": '\U0000211C',
- "realine;": '\U0000211B',
- "realpart;": '\U0000211C',
- "reals;": '\U0000211D',
- "rect;": '\U000025AD',
- "reg;": '\U000000AE',
- "rfisht;": '\U0000297D',
- "rfloor;": '\U0000230B',
- "rfr;": '\U0001D52F',
- "rhard;": '\U000021C1',
- "rharu;": '\U000021C0',
- "rharul;": '\U0000296C',
- "rho;": '\U000003C1',
- "rhov;": '\U000003F1',
- "rightarrow;": '\U00002192',
- "rightarrowtail;": '\U000021A3',
- "rightharpoondown;": '\U000021C1',
- "rightharpoonup;": '\U000021C0',
- "rightleftarrows;": '\U000021C4',
- "rightleftharpoons;": '\U000021CC',
- "rightrightarrows;": '\U000021C9',
- "rightsquigarrow;": '\U0000219D',
- "rightthreetimes;": '\U000022CC',
- "ring;": '\U000002DA',
- "risingdotseq;": '\U00002253',
- "rlarr;": '\U000021C4',
- "rlhar;": '\U000021CC',
- "rlm;": '\U0000200F',
- "rmoust;": '\U000023B1',
- "rmoustache;": '\U000023B1',
- "rnmid;": '\U00002AEE',
- "roang;": '\U000027ED',
- "roarr;": '\U000021FE',
- "robrk;": '\U000027E7',
- "ropar;": '\U00002986',
- "ropf;": '\U0001D563',
- "roplus;": '\U00002A2E',
- "rotimes;": '\U00002A35',
- "rpar;": '\U00000029',
- "rpargt;": '\U00002994',
- "rppolint;": '\U00002A12',
- "rrarr;": '\U000021C9',
- "rsaquo;": '\U0000203A',
- "rscr;": '\U0001D4C7',
- "rsh;": '\U000021B1',
- "rsqb;": '\U0000005D',
- "rsquo;": '\U00002019',
- "rsquor;": '\U00002019',
- "rthree;": '\U000022CC',
- "rtimes;": '\U000022CA',
- "rtri;": '\U000025B9',
- "rtrie;": '\U000022B5',
- "rtrif;": '\U000025B8',
- "rtriltri;": '\U000029CE',
- "ruluhar;": '\U00002968',
- "rx;": '\U0000211E',
- "sacute;": '\U0000015B',
- "sbquo;": '\U0000201A',
- "sc;": '\U0000227B',
- "scE;": '\U00002AB4',
- "scap;": '\U00002AB8',
- "scaron;": '\U00000161',
- "sccue;": '\U0000227D',
- "sce;": '\U00002AB0',
- "scedil;": '\U0000015F',
- "scirc;": '\U0000015D',
- "scnE;": '\U00002AB6',
- "scnap;": '\U00002ABA',
- "scnsim;": '\U000022E9',
- "scpolint;": '\U00002A13',
- "scsim;": '\U0000227F',
- "scy;": '\U00000441',
- "sdot;": '\U000022C5',
- "sdotb;": '\U000022A1',
- "sdote;": '\U00002A66',
- "seArr;": '\U000021D8',
- "searhk;": '\U00002925',
- "searr;": '\U00002198',
- "searrow;": '\U00002198',
- "sect;": '\U000000A7',
- "semi;": '\U0000003B',
- "seswar;": '\U00002929',
- "setminus;": '\U00002216',
- "setmn;": '\U00002216',
- "sext;": '\U00002736',
- "sfr;": '\U0001D530',
- "sfrown;": '\U00002322',
- "sharp;": '\U0000266F',
- "shchcy;": '\U00000449',
- "shcy;": '\U00000448',
- "shortmid;": '\U00002223',
- "shortparallel;": '\U00002225',
- "shy;": '\U000000AD',
- "sigma;": '\U000003C3',
- "sigmaf;": '\U000003C2',
- "sigmav;": '\U000003C2',
- "sim;": '\U0000223C',
- "simdot;": '\U00002A6A',
- "sime;": '\U00002243',
- "simeq;": '\U00002243',
- "simg;": '\U00002A9E',
- "simgE;": '\U00002AA0',
- "siml;": '\U00002A9D',
- "simlE;": '\U00002A9F',
- "simne;": '\U00002246',
- "simplus;": '\U00002A24',
- "simrarr;": '\U00002972',
- "slarr;": '\U00002190',
- "smallsetminus;": '\U00002216',
- "smashp;": '\U00002A33',
- "smeparsl;": '\U000029E4',
- "smid;": '\U00002223',
- "smile;": '\U00002323',
- "smt;": '\U00002AAA',
- "smte;": '\U00002AAC',
- "softcy;": '\U0000044C',
- "sol;": '\U0000002F',
- "solb;": '\U000029C4',
- "solbar;": '\U0000233F',
- "sopf;": '\U0001D564',
- "spades;": '\U00002660',
- "spadesuit;": '\U00002660',
- "spar;": '\U00002225',
- "sqcap;": '\U00002293',
- "sqcup;": '\U00002294',
- "sqsub;": '\U0000228F',
- "sqsube;": '\U00002291',
- "sqsubset;": '\U0000228F',
- "sqsubseteq;": '\U00002291',
- "sqsup;": '\U00002290',
- "sqsupe;": '\U00002292',
- "sqsupset;": '\U00002290',
- "sqsupseteq;": '\U00002292',
- "squ;": '\U000025A1',
- "square;": '\U000025A1',
- "squarf;": '\U000025AA',
- "squf;": '\U000025AA',
- "srarr;": '\U00002192',
- "sscr;": '\U0001D4C8',
- "ssetmn;": '\U00002216',
- "ssmile;": '\U00002323',
- "sstarf;": '\U000022C6',
- "star;": '\U00002606',
- "starf;": '\U00002605',
- "straightepsilon;": '\U000003F5',
- "straightphi;": '\U000003D5',
- "strns;": '\U000000AF',
- "sub;": '\U00002282',
- "subE;": '\U00002AC5',
- "subdot;": '\U00002ABD',
- "sube;": '\U00002286',
- "subedot;": '\U00002AC3',
- "submult;": '\U00002AC1',
- "subnE;": '\U00002ACB',
- "subne;": '\U0000228A',
- "subplus;": '\U00002ABF',
- "subrarr;": '\U00002979',
- "subset;": '\U00002282',
- "subseteq;": '\U00002286',
- "subseteqq;": '\U00002AC5',
- "subsetneq;": '\U0000228A',
- "subsetneqq;": '\U00002ACB',
- "subsim;": '\U00002AC7',
- "subsub;": '\U00002AD5',
- "subsup;": '\U00002AD3',
- "succ;": '\U0000227B',
- "succapprox;": '\U00002AB8',
- "succcurlyeq;": '\U0000227D',
- "succeq;": '\U00002AB0',
- "succnapprox;": '\U00002ABA',
- "succneqq;": '\U00002AB6',
- "succnsim;": '\U000022E9',
- "succsim;": '\U0000227F',
- "sum;": '\U00002211',
- "sung;": '\U0000266A',
- "sup;": '\U00002283',
- "sup1;": '\U000000B9',
- "sup2;": '\U000000B2',
- "sup3;": '\U000000B3',
- "supE;": '\U00002AC6',
- "supdot;": '\U00002ABE',
- "supdsub;": '\U00002AD8',
- "supe;": '\U00002287',
- "supedot;": '\U00002AC4',
- "suphsol;": '\U000027C9',
- "suphsub;": '\U00002AD7',
- "suplarr;": '\U0000297B',
- "supmult;": '\U00002AC2',
- "supnE;": '\U00002ACC',
- "supne;": '\U0000228B',
- "supplus;": '\U00002AC0',
- "supset;": '\U00002283',
- "supseteq;": '\U00002287',
- "supseteqq;": '\U00002AC6',
- "supsetneq;": '\U0000228B',
- "supsetneqq;": '\U00002ACC',
- "supsim;": '\U00002AC8',
- "supsub;": '\U00002AD4',
- "supsup;": '\U00002AD6',
- "swArr;": '\U000021D9',
- "swarhk;": '\U00002926',
- "swarr;": '\U00002199',
- "swarrow;": '\U00002199',
- "swnwar;": '\U0000292A',
- "szlig;": '\U000000DF',
- "target;": '\U00002316',
- "tau;": '\U000003C4',
- "tbrk;": '\U000023B4',
- "tcaron;": '\U00000165',
- "tcedil;": '\U00000163',
- "tcy;": '\U00000442',
- "tdot;": '\U000020DB',
- "telrec;": '\U00002315',
- "tfr;": '\U0001D531',
- "there4;": '\U00002234',
- "therefore;": '\U00002234',
- "theta;": '\U000003B8',
- "thetasym;": '\U000003D1',
- "thetav;": '\U000003D1',
- "thickapprox;": '\U00002248',
- "thicksim;": '\U0000223C',
- "thinsp;": '\U00002009',
- "thkap;": '\U00002248',
- "thksim;": '\U0000223C',
- "thorn;": '\U000000FE',
- "tilde;": '\U000002DC',
- "times;": '\U000000D7',
- "timesb;": '\U000022A0',
- "timesbar;": '\U00002A31',
- "timesd;": '\U00002A30',
- "tint;": '\U0000222D',
- "toea;": '\U00002928',
- "top;": '\U000022A4',
- "topbot;": '\U00002336',
- "topcir;": '\U00002AF1',
- "topf;": '\U0001D565',
- "topfork;": '\U00002ADA',
- "tosa;": '\U00002929',
- "tprime;": '\U00002034',
- "trade;": '\U00002122',
- "triangle;": '\U000025B5',
- "triangledown;": '\U000025BF',
- "triangleleft;": '\U000025C3',
- "trianglelefteq;": '\U000022B4',
- "triangleq;": '\U0000225C',
- "triangleright;": '\U000025B9',
- "trianglerighteq;": '\U000022B5',
- "tridot;": '\U000025EC',
- "trie;": '\U0000225C',
- "triminus;": '\U00002A3A',
- "triplus;": '\U00002A39',
- "trisb;": '\U000029CD',
- "tritime;": '\U00002A3B',
- "trpezium;": '\U000023E2',
- "tscr;": '\U0001D4C9',
- "tscy;": '\U00000446',
- "tshcy;": '\U0000045B',
- "tstrok;": '\U00000167',
- "twixt;": '\U0000226C',
- "twoheadleftarrow;": '\U0000219E',
- "twoheadrightarrow;": '\U000021A0',
- "uArr;": '\U000021D1',
- "uHar;": '\U00002963',
- "uacute;": '\U000000FA',
- "uarr;": '\U00002191',
- "ubrcy;": '\U0000045E',
- "ubreve;": '\U0000016D',
- "ucirc;": '\U000000FB',
- "ucy;": '\U00000443',
- "udarr;": '\U000021C5',
- "udblac;": '\U00000171',
- "udhar;": '\U0000296E',
- "ufisht;": '\U0000297E',
- "ufr;": '\U0001D532',
- "ugrave;": '\U000000F9',
- "uharl;": '\U000021BF',
- "uharr;": '\U000021BE',
- "uhblk;": '\U00002580',
- "ulcorn;": '\U0000231C',
- "ulcorner;": '\U0000231C',
- "ulcrop;": '\U0000230F',
- "ultri;": '\U000025F8',
- "umacr;": '\U0000016B',
- "uml;": '\U000000A8',
- "uogon;": '\U00000173',
- "uopf;": '\U0001D566',
- "uparrow;": '\U00002191',
- "updownarrow;": '\U00002195',
- "upharpoonleft;": '\U000021BF',
- "upharpoonright;": '\U000021BE',
- "uplus;": '\U0000228E',
- "upsi;": '\U000003C5',
- "upsih;": '\U000003D2',
- "upsilon;": '\U000003C5',
- "upuparrows;": '\U000021C8',
- "urcorn;": '\U0000231D',
- "urcorner;": '\U0000231D',
- "urcrop;": '\U0000230E',
- "uring;": '\U0000016F',
- "urtri;": '\U000025F9',
- "uscr;": '\U0001D4CA',
- "utdot;": '\U000022F0',
- "utilde;": '\U00000169',
- "utri;": '\U000025B5',
- "utrif;": '\U000025B4',
- "uuarr;": '\U000021C8',
- "uuml;": '\U000000FC',
- "uwangle;": '\U000029A7',
- "vArr;": '\U000021D5',
- "vBar;": '\U00002AE8',
- "vBarv;": '\U00002AE9',
- "vDash;": '\U000022A8',
- "vangrt;": '\U0000299C',
- "varepsilon;": '\U000003F5',
- "varkappa;": '\U000003F0',
- "varnothing;": '\U00002205',
- "varphi;": '\U000003D5',
- "varpi;": '\U000003D6',
- "varpropto;": '\U0000221D',
- "varr;": '\U00002195',
- "varrho;": '\U000003F1',
- "varsigma;": '\U000003C2',
- "vartheta;": '\U000003D1',
- "vartriangleleft;": '\U000022B2',
- "vartriangleright;": '\U000022B3',
- "vcy;": '\U00000432',
- "vdash;": '\U000022A2',
- "vee;": '\U00002228',
- "veebar;": '\U000022BB',
- "veeeq;": '\U0000225A',
- "vellip;": '\U000022EE',
- "verbar;": '\U0000007C',
- "vert;": '\U0000007C',
- "vfr;": '\U0001D533',
- "vltri;": '\U000022B2',
- "vopf;": '\U0001D567',
- "vprop;": '\U0000221D',
- "vrtri;": '\U000022B3',
- "vscr;": '\U0001D4CB',
- "vzigzag;": '\U0000299A',
- "wcirc;": '\U00000175',
- "wedbar;": '\U00002A5F',
- "wedge;": '\U00002227',
- "wedgeq;": '\U00002259',
- "weierp;": '\U00002118',
- "wfr;": '\U0001D534',
- "wopf;": '\U0001D568',
- "wp;": '\U00002118',
- "wr;": '\U00002240',
- "wreath;": '\U00002240',
- "wscr;": '\U0001D4CC',
- "xcap;": '\U000022C2',
- "xcirc;": '\U000025EF',
- "xcup;": '\U000022C3',
- "xdtri;": '\U000025BD',
- "xfr;": '\U0001D535',
- "xhArr;": '\U000027FA',
- "xharr;": '\U000027F7',
- "xi;": '\U000003BE',
- "xlArr;": '\U000027F8',
- "xlarr;": '\U000027F5',
- "xmap;": '\U000027FC',
- "xnis;": '\U000022FB',
- "xodot;": '\U00002A00',
- "xopf;": '\U0001D569',
- "xoplus;": '\U00002A01',
- "xotime;": '\U00002A02',
- "xrArr;": '\U000027F9',
- "xrarr;": '\U000027F6',
- "xscr;": '\U0001D4CD',
- "xsqcup;": '\U00002A06',
- "xuplus;": '\U00002A04',
- "xutri;": '\U000025B3',
- "xvee;": '\U000022C1',
- "xwedge;": '\U000022C0',
- "yacute;": '\U000000FD',
- "yacy;": '\U0000044F',
- "ycirc;": '\U00000177',
- "ycy;": '\U0000044B',
- "yen;": '\U000000A5',
- "yfr;": '\U0001D536',
- "yicy;": '\U00000457',
- "yopf;": '\U0001D56A',
- "yscr;": '\U0001D4CE',
- "yucy;": '\U0000044E',
- "yuml;": '\U000000FF',
- "zacute;": '\U0000017A',
- "zcaron;": '\U0000017E',
- "zcy;": '\U00000437',
- "zdot;": '\U0000017C',
- "zeetrf;": '\U00002128',
- "zeta;": '\U000003B6',
- "zfr;": '\U0001D537',
- "zhcy;": '\U00000436',
- "zigrarr;": '\U000021DD',
- "zopf;": '\U0001D56B',
- "zscr;": '\U0001D4CF',
- "zwj;": '\U0000200D',
- "zwnj;": '\U0000200C',
- "AElig": '\U000000C6',
- "AMP": '\U00000026',
- "Aacute": '\U000000C1',
- "Acirc": '\U000000C2',
- "Agrave": '\U000000C0',
- "Aring": '\U000000C5',
- "Atilde": '\U000000C3',
- "Auml": '\U000000C4',
- "COPY": '\U000000A9',
- "Ccedil": '\U000000C7',
- "ETH": '\U000000D0',
- "Eacute": '\U000000C9',
- "Ecirc": '\U000000CA',
- "Egrave": '\U000000C8',
- "Euml": '\U000000CB',
- "GT": '\U0000003E',
- "Iacute": '\U000000CD',
- "Icirc": '\U000000CE',
- "Igrave": '\U000000CC',
- "Iuml": '\U000000CF',
- "LT": '\U0000003C',
- "Ntilde": '\U000000D1',
- "Oacute": '\U000000D3',
- "Ocirc": '\U000000D4',
- "Ograve": '\U000000D2',
- "Oslash": '\U000000D8',
- "Otilde": '\U000000D5',
- "Ouml": '\U000000D6',
- "QUOT": '\U00000022',
- "REG": '\U000000AE',
- "THORN": '\U000000DE',
- "Uacute": '\U000000DA',
- "Ucirc": '\U000000DB',
- "Ugrave": '\U000000D9',
- "Uuml": '\U000000DC',
- "Yacute": '\U000000DD',
- "aacute": '\U000000E1',
- "acirc": '\U000000E2',
- "acute": '\U000000B4',
- "aelig": '\U000000E6',
- "agrave": '\U000000E0',
- "amp": '\U00000026',
- "aring": '\U000000E5',
- "atilde": '\U000000E3',
- "auml": '\U000000E4',
- "brvbar": '\U000000A6',
- "ccedil": '\U000000E7',
- "cedil": '\U000000B8',
- "cent": '\U000000A2',
- "copy": '\U000000A9',
- "curren": '\U000000A4',
- "deg": '\U000000B0',
- "divide": '\U000000F7',
- "eacute": '\U000000E9',
- "ecirc": '\U000000EA',
- "egrave": '\U000000E8',
- "eth": '\U000000F0',
- "euml": '\U000000EB',
- "frac12": '\U000000BD',
- "frac14": '\U000000BC',
- "frac34": '\U000000BE',
- "gt": '\U0000003E',
- "iacute": '\U000000ED',
- "icirc": '\U000000EE',
- "iexcl": '\U000000A1',
- "igrave": '\U000000EC',
- "iquest": '\U000000BF',
- "iuml": '\U000000EF',
- "laquo": '\U000000AB',
- "lt": '\U0000003C',
- "macr": '\U000000AF',
- "micro": '\U000000B5',
- "middot": '\U000000B7',
- "nbsp": '\U000000A0',
- "not": '\U000000AC',
- "ntilde": '\U000000F1',
- "oacute": '\U000000F3',
- "ocirc": '\U000000F4',
- "ograve": '\U000000F2',
- "ordf": '\U000000AA',
- "ordm": '\U000000BA',
- "oslash": '\U000000F8',
- "otilde": '\U000000F5',
- "ouml": '\U000000F6',
- "para": '\U000000B6',
- "plusmn": '\U000000B1',
- "pound": '\U000000A3',
- "quot": '\U00000022',
- "raquo": '\U000000BB',
- "reg": '\U000000AE',
- "sect": '\U000000A7',
- "shy": '\U000000AD',
- "sup1": '\U000000B9',
- "sup2": '\U000000B2',
- "sup3": '\U000000B3',
- "szlig": '\U000000DF',
- "thorn": '\U000000FE',
- "times": '\U000000D7',
- "uacute": '\U000000FA',
- "ucirc": '\U000000FB',
- "ugrave": '\U000000F9',
- "uml": '\U000000A8',
- "uuml": '\U000000FC',
- "yacute": '\U000000FD',
- "yen": '\U000000A5',
- "yuml": '\U000000FF',
+ "Cross;": '\U00002A2F',
+ "Cscr;": '\U0001D49E',
+ "Cup;": '\U000022D3',
+ "CupCap;": '\U0000224D',
+ "DD;": '\U00002145',
+ "DDotrahd;": '\U00002911',
+ "DJcy;": '\U00000402',
+ "DScy;": '\U00000405',
+ "DZcy;": '\U0000040F',
+ "Dagger;": '\U00002021',
+ "Darr;": '\U000021A1',
+ "Dashv;": '\U00002AE4',
+ "Dcaron;": '\U0000010E',
+ "Dcy;": '\U00000414',
+ "Del;": '\U00002207',
+ "Delta;": '\U00000394',
+ "Dfr;": '\U0001D507',
+ "DiacriticalAcute;": '\U000000B4',
+ "DiacriticalDot;": '\U000002D9',
+ "DiacriticalDoubleAcute;": '\U000002DD',
+ "DiacriticalGrave;": '\U00000060',
+ "DiacriticalTilde;": '\U000002DC',
+ "Diamond;": '\U000022C4',
+ "DifferentialD;": '\U00002146',
+ "Dopf;": '\U0001D53B',
+ "Dot;": '\U000000A8',
+ "DotDot;": '\U000020DC',
+ "DotEqual;": '\U00002250',
+ "DoubleContourIntegral;": '\U0000222F',
+ "DoubleDot;": '\U000000A8',
+ "DoubleDownArrow;": '\U000021D3',
+ "DoubleLeftArrow;": '\U000021D0',
+ "DoubleLeftRightArrow;": '\U000021D4',
+ "DoubleLeftTee;": '\U00002AE4',
+ "DoubleLongLeftArrow;": '\U000027F8',
+ "DoubleLongLeftRightArrow;": '\U000027FA',
+ "DoubleLongRightArrow;": '\U000027F9',
+ "DoubleRightArrow;": '\U000021D2',
+ "DoubleRightTee;": '\U000022A8',
+ "DoubleUpArrow;": '\U000021D1',
+ "DoubleUpDownArrow;": '\U000021D5',
+ "DoubleVerticalBar;": '\U00002225',
+ "DownArrow;": '\U00002193',
+ "DownArrowBar;": '\U00002913',
+ "DownArrowUpArrow;": '\U000021F5',
+ "DownBreve;": '\U00000311',
+ "DownLeftRightVector;": '\U00002950',
+ "DownLeftTeeVector;": '\U0000295E',
+ "DownLeftVector;": '\U000021BD',
+ "DownLeftVectorBar;": '\U00002956',
+ "DownRightTeeVector;": '\U0000295F',
+ "DownRightVector;": '\U000021C1',
+ "DownRightVectorBar;": '\U00002957',
+ "DownTee;": '\U000022A4',
+ "DownTeeArrow;": '\U000021A7',
+ "Downarrow;": '\U000021D3',
+ "Dscr;": '\U0001D49F',
+ "Dstrok;": '\U00000110',
+ "ENG;": '\U0000014A',
+ "ETH;": '\U000000D0',
+ "Eacute;": '\U000000C9',
+ "Ecaron;": '\U0000011A',
+ "Ecirc;": '\U000000CA',
+ "Ecy;": '\U0000042D',
+ "Edot;": '\U00000116',
+ "Efr;": '\U0001D508',
+ "Egrave;": '\U000000C8',
+ "Element;": '\U00002208',
+ "Emacr;": '\U00000112',
+ "EmptySmallSquare;": '\U000025FB',
+ "EmptyVerySmallSquare;": '\U000025AB',
+ "Eogon;": '\U00000118',
+ "Eopf;": '\U0001D53C',
+ "Epsilon;": '\U00000395',
+ "Equal;": '\U00002A75',
+ "EqualTilde;": '\U00002242',
+ "Equilibrium;": '\U000021CC',
+ "Escr;": '\U00002130',
+ "Esim;": '\U00002A73',
+ "Eta;": '\U00000397',
+ "Euml;": '\U000000CB',
+ "Exists;": '\U00002203',
+ "ExponentialE;": '\U00002147',
+ "Fcy;": '\U00000424',
+ "Ffr;": '\U0001D509',
+ "FilledSmallSquare;": '\U000025FC',
+ "FilledVerySmallSquare;": '\U000025AA',
+ "Fopf;": '\U0001D53D',
+ "ForAll;": '\U00002200',
+ "Fouriertrf;": '\U00002131',
+ "Fscr;": '\U00002131',
+ "GJcy;": '\U00000403',
+ "GT;": '\U0000003E',
+ "Gamma;": '\U00000393',
+ "Gammad;": '\U000003DC',
+ "Gbreve;": '\U0000011E',
+ "Gcedil;": '\U00000122',
+ "Gcirc;": '\U0000011C',
+ "Gcy;": '\U00000413',
+ "Gdot;": '\U00000120',
+ "Gfr;": '\U0001D50A',
+ "Gg;": '\U000022D9',
+ "Gopf;": '\U0001D53E',
+ "GreaterEqual;": '\U00002265',
+ "GreaterEqualLess;": '\U000022DB',
+ "GreaterFullEqual;": '\U00002267',
+ "GreaterGreater;": '\U00002AA2',
+ "GreaterLess;": '\U00002277',
+ "GreaterSlantEqual;": '\U00002A7E',
+ "GreaterTilde;": '\U00002273',
+ "Gscr;": '\U0001D4A2',
+ "Gt;": '\U0000226B',
+ "HARDcy;": '\U0000042A',
+ "Hacek;": '\U000002C7',
+ "Hat;": '\U0000005E',
+ "Hcirc;": '\U00000124',
+ "Hfr;": '\U0000210C',
+ "HilbertSpace;": '\U0000210B',
+ "Hopf;": '\U0000210D',
+ "HorizontalLine;": '\U00002500',
+ "Hscr;": '\U0000210B',
+ "Hstrok;": '\U00000126',
+ "HumpDownHump;": '\U0000224E',
+ "HumpEqual;": '\U0000224F',
+ "IEcy;": '\U00000415',
+ "IJlig;": '\U00000132',
+ "IOcy;": '\U00000401',
+ "Iacute;": '\U000000CD',
+ "Icirc;": '\U000000CE',
+ "Icy;": '\U00000418',
+ "Idot;": '\U00000130',
+ "Ifr;": '\U00002111',
+ "Igrave;": '\U000000CC',
+ "Im;": '\U00002111',
+ "Imacr;": '\U0000012A',
+ "ImaginaryI;": '\U00002148',
+ "Implies;": '\U000021D2',
+ "Int;": '\U0000222C',
+ "Integral;": '\U0000222B',
+ "Intersection;": '\U000022C2',
+ "InvisibleComma;": '\U00002063',
+ "InvisibleTimes;": '\U00002062',
+ "Iogon;": '\U0000012E',
+ "Iopf;": '\U0001D540',
+ "Iota;": '\U00000399',
+ "Iscr;": '\U00002110',
+ "Itilde;": '\U00000128',
+ "Iukcy;": '\U00000406',
+ "Iuml;": '\U000000CF',
+ "Jcirc;": '\U00000134',
+ "Jcy;": '\U00000419',
+ "Jfr;": '\U0001D50D',
+ "Jopf;": '\U0001D541',
+ "Jscr;": '\U0001D4A5',
+ "Jsercy;": '\U00000408',
+ "Jukcy;": '\U00000404',
+ "KHcy;": '\U00000425',
+ "KJcy;": '\U0000040C',
+ "Kappa;": '\U0000039A',
+ "Kcedil;": '\U00000136',
+ "Kcy;": '\U0000041A',
+ "Kfr;": '\U0001D50E',
+ "Kopf;": '\U0001D542',
+ "Kscr;": '\U0001D4A6',
+ "LJcy;": '\U00000409',
+ "LT;": '\U0000003C',
+ "Lacute;": '\U00000139',
+ "Lambda;": '\U0000039B',
+ "Lang;": '\U000027EA',
+ "Laplacetrf;": '\U00002112',
+ "Larr;": '\U0000219E',
+ "Lcaron;": '\U0000013D',
+ "Lcedil;": '\U0000013B',
+ "Lcy;": '\U0000041B',
+ "LeftAngleBracket;": '\U000027E8',
+ "LeftArrow;": '\U00002190',
+ "LeftArrowBar;": '\U000021E4',
+ "LeftArrowRightArrow;": '\U000021C6',
+ "LeftCeiling;": '\U00002308',
+ "LeftDoubleBracket;": '\U000027E6',
+ "LeftDownTeeVector;": '\U00002961',
+ "LeftDownVector;": '\U000021C3',
+ "LeftDownVectorBar;": '\U00002959',
+ "LeftFloor;": '\U0000230A',
+ "LeftRightArrow;": '\U00002194',
+ "LeftRightVector;": '\U0000294E',
+ "LeftTee;": '\U000022A3',
+ "LeftTeeArrow;": '\U000021A4',
+ "LeftTeeVector;": '\U0000295A',
+ "LeftTriangle;": '\U000022B2',
+ "LeftTriangleBar;": '\U000029CF',
+ "LeftTriangleEqual;": '\U000022B4',
+ "LeftUpDownVector;": '\U00002951',
+ "LeftUpTeeVector;": '\U00002960',
+ "LeftUpVector;": '\U000021BF',
+ "LeftUpVectorBar;": '\U00002958',
+ "LeftVector;": '\U000021BC',
+ "LeftVectorBar;": '\U00002952',
+ "Leftarrow;": '\U000021D0',
+ "Leftrightarrow;": '\U000021D4',
+ "LessEqualGreater;": '\U000022DA',
+ "LessFullEqual;": '\U00002266',
+ "LessGreater;": '\U00002276',
+ "LessLess;": '\U00002AA1',
+ "LessSlantEqual;": '\U00002A7D',
+ "LessTilde;": '\U00002272',
+ "Lfr;": '\U0001D50F',
+ "Ll;": '\U000022D8',
+ "Lleftarrow;": '\U000021DA',
+ "Lmidot;": '\U0000013F',
+ "LongLeftArrow;": '\U000027F5',
+ "LongLeftRightArrow;": '\U000027F7',
+ "LongRightArrow;": '\U000027F6',
+ "Longleftarrow;": '\U000027F8',
+ "Longleftrightarrow;": '\U000027FA',
+ "Longrightarrow;": '\U000027F9',
+ "Lopf;": '\U0001D543',
+ "LowerLeftArrow;": '\U00002199',
+ "LowerRightArrow;": '\U00002198',
+ "Lscr;": '\U00002112',
+ "Lsh;": '\U000021B0',
+ "Lstrok;": '\U00000141',
+ "Lt;": '\U0000226A',
+ "Map;": '\U00002905',
+ "Mcy;": '\U0000041C',
+ "MediumSpace;": '\U0000205F',
+ "Mellintrf;": '\U00002133',
+ "Mfr;": '\U0001D510',
+ "MinusPlus;": '\U00002213',
+ "Mopf;": '\U0001D544',
+ "Mscr;": '\U00002133',
+ "Mu;": '\U0000039C',
+ "NJcy;": '\U0000040A',
+ "Nacute;": '\U00000143',
+ "Ncaron;": '\U00000147',
+ "Ncedil;": '\U00000145',
+ "Ncy;": '\U0000041D',
+ "NegativeMediumSpace;": '\U0000200B',
+ "NegativeThickSpace;": '\U0000200B',
+ "NegativeThinSpace;": '\U0000200B',
+ "NegativeVeryThinSpace;": '\U0000200B',
+ "NestedGreaterGreater;": '\U0000226B',
+ "NestedLessLess;": '\U0000226A',
+ "NewLine;": '\U0000000A',
+ "Nfr;": '\U0001D511',
+ "NoBreak;": '\U00002060',
+ "NonBreakingSpace;": '\U000000A0',
+ "Nopf;": '\U00002115',
+ "Not;": '\U00002AEC',
+ "NotCongruent;": '\U00002262',
+ "NotCupCap;": '\U0000226D',
+ "NotDoubleVerticalBar;": '\U00002226',
+ "NotElement;": '\U00002209',
+ "NotEqual;": '\U00002260',
+ "NotExists;": '\U00002204',
+ "NotGreater;": '\U0000226F',
+ "NotGreaterEqual;": '\U00002271',
+ "NotGreaterLess;": '\U00002279',
+ "NotGreaterTilde;": '\U00002275',
+ "NotLeftTriangle;": '\U000022EA',
+ "NotLeftTriangleEqual;": '\U000022EC',
+ "NotLess;": '\U0000226E',
+ "NotLessEqual;": '\U00002270',
+ "NotLessGreater;": '\U00002278',
+ "NotLessTilde;": '\U00002274',
+ "NotPrecedes;": '\U00002280',
+ "NotPrecedesSlantEqual;": '\U000022E0',
+ "NotReverseElement;": '\U0000220C',
+ "NotRightTriangle;": '\U000022EB',
+ "NotRightTriangleEqual;": '\U000022ED',
+ "NotSquareSubsetEqual;": '\U000022E2',
+ "NotSquareSupersetEqual;": '\U000022E3',
+ "NotSubsetEqual;": '\U00002288',
+ "NotSucceeds;": '\U00002281',
+ "NotSucceedsSlantEqual;": '\U000022E1',
+ "NotSupersetEqual;": '\U00002289',
+ "NotTilde;": '\U00002241',
+ "NotTildeEqual;": '\U00002244',
+ "NotTildeFullEqual;": '\U00002247',
+ "NotTildeTilde;": '\U00002249',
+ "NotVerticalBar;": '\U00002224',
+ "Nscr;": '\U0001D4A9',
+ "Ntilde;": '\U000000D1',
+ "Nu;": '\U0000039D',
+ "OElig;": '\U00000152',
+ "Oacute;": '\U000000D3',
+ "Ocirc;": '\U000000D4',
+ "Ocy;": '\U0000041E',
+ "Odblac;": '\U00000150',
+ "Ofr;": '\U0001D512',
+ "Ograve;": '\U000000D2',
+ "Omacr;": '\U0000014C',
+ "Omega;": '\U000003A9',
+ "Omicron;": '\U0000039F',
+ "Oopf;": '\U0001D546',
+ "OpenCurlyDoubleQuote;": '\U0000201C',
+ "OpenCurlyQuote;": '\U00002018',
+ "Or;": '\U00002A54',
+ "Oscr;": '\U0001D4AA',
+ "Oslash;": '\U000000D8',
+ "Otilde;": '\U000000D5',
+ "Otimes;": '\U00002A37',
+ "Ouml;": '\U000000D6',
+ "OverBar;": '\U0000203E',
+ "OverBrace;": '\U000023DE',
+ "OverBracket;": '\U000023B4',
+ "OverParenthesis;": '\U000023DC',
+ "PartialD;": '\U00002202',
+ "Pcy;": '\U0000041F',
+ "Pfr;": '\U0001D513',
+ "Phi;": '\U000003A6',
+ "Pi;": '\U000003A0',
+ "PlusMinus;": '\U000000B1',
+ "Poincareplane;": '\U0000210C',
+ "Popf;": '\U00002119',
+ "Pr;": '\U00002ABB',
+ "Precedes;": '\U0000227A',
+ "PrecedesEqual;": '\U00002AAF',
+ "PrecedesSlantEqual;": '\U0000227C',
+ "PrecedesTilde;": '\U0000227E',
+ "Prime;": '\U00002033',
+ "Product;": '\U0000220F',
+ "Proportion;": '\U00002237',
+ "Proportional;": '\U0000221D',
+ "Pscr;": '\U0001D4AB',
+ "Psi;": '\U000003A8',
+ "QUOT;": '\U00000022',
+ "Qfr;": '\U0001D514',
+ "Qopf;": '\U0000211A',
+ "Qscr;": '\U0001D4AC',
+ "RBarr;": '\U00002910',
+ "REG;": '\U000000AE',
+ "Racute;": '\U00000154',
+ "Rang;": '\U000027EB',
+ "Rarr;": '\U000021A0',
+ "Rarrtl;": '\U00002916',
+ "Rcaron;": '\U00000158',
+ "Rcedil;": '\U00000156',
+ "Rcy;": '\U00000420',
+ "Re;": '\U0000211C',
+ "ReverseElement;": '\U0000220B',
+ "ReverseEquilibrium;": '\U000021CB',
+ "ReverseUpEquilibrium;": '\U0000296F',
+ "Rfr;": '\U0000211C',
+ "Rho;": '\U000003A1',
+ "RightAngleBracket;": '\U000027E9',
+ "RightArrow;": '\U00002192',
+ "RightArrowBar;": '\U000021E5',
+ "RightArrowLeftArrow;": '\U000021C4',
+ "RightCeiling;": '\U00002309',
+ "RightDoubleBracket;": '\U000027E7',
+ "RightDownTeeVector;": '\U0000295D',
+ "RightDownVector;": '\U000021C2',
+ "RightDownVectorBar;": '\U00002955',
+ "RightFloor;": '\U0000230B',
+ "RightTee;": '\U000022A2',
+ "RightTeeArrow;": '\U000021A6',
+ "RightTeeVector;": '\U0000295B',
+ "RightTriangle;": '\U000022B3',
+ "RightTriangleBar;": '\U000029D0',
+ "RightTriangleEqual;": '\U000022B5',
+ "RightUpDownVector;": '\U0000294F',
+ "RightUpTeeVector;": '\U0000295C',
+ "RightUpVector;": '\U000021BE',
+ "RightUpVectorBar;": '\U00002954',
+ "RightVector;": '\U000021C0',
+ "RightVectorBar;": '\U00002953',
+ "Rightarrow;": '\U000021D2',
+ "Ropf;": '\U0000211D',
+ "RoundImplies;": '\U00002970',
+ "Rrightarrow;": '\U000021DB',
+ "Rscr;": '\U0000211B',
+ "Rsh;": '\U000021B1',
+ "RuleDelayed;": '\U000029F4',
+ "SHCHcy;": '\U00000429',
+ "SHcy;": '\U00000428',
+ "SOFTcy;": '\U0000042C',
+ "Sacute;": '\U0000015A',
+ "Sc;": '\U00002ABC',
+ "Scaron;": '\U00000160',
+ "Scedil;": '\U0000015E',
+ "Scirc;": '\U0000015C',
+ "Scy;": '\U00000421',
+ "Sfr;": '\U0001D516',
+ "ShortDownArrow;": '\U00002193',
+ "ShortLeftArrow;": '\U00002190',
+ "ShortRightArrow;": '\U00002192',
+ "ShortUpArrow;": '\U00002191',
+ "Sigma;": '\U000003A3',
+ "SmallCircle;": '\U00002218',
+ "Sopf;": '\U0001D54A',
+ "Sqrt;": '\U0000221A',
+ "Square;": '\U000025A1',
+ "SquareIntersection;": '\U00002293',
+ "SquareSubset;": '\U0000228F',
+ "SquareSubsetEqual;": '\U00002291',
+ "SquareSuperset;": '\U00002290',
+ "SquareSupersetEqual;": '\U00002292',
+ "SquareUnion;": '\U00002294',
+ "Sscr;": '\U0001D4AE',
+ "Star;": '\U000022C6',
+ "Sub;": '\U000022D0',
+ "Subset;": '\U000022D0',
+ "SubsetEqual;": '\U00002286',
+ "Succeeds;": '\U0000227B',
+ "SucceedsEqual;": '\U00002AB0',
+ "SucceedsSlantEqual;": '\U0000227D',
+ "SucceedsTilde;": '\U0000227F',
+ "SuchThat;": '\U0000220B',
+ "Sum;": '\U00002211',
+ "Sup;": '\U000022D1',
+ "Superset;": '\U00002283',
+ "SupersetEqual;": '\U00002287',
+ "Supset;": '\U000022D1',
+ "THORN;": '\U000000DE',
+ "TRADE;": '\U00002122',
+ "TSHcy;": '\U0000040B',
+ "TScy;": '\U00000426',
+ "Tab;": '\U00000009',
+ "Tau;": '\U000003A4',
+ "Tcaron;": '\U00000164',
+ "Tcedil;": '\U00000162',
+ "Tcy;": '\U00000422',
+ "Tfr;": '\U0001D517',
+ "Therefore;": '\U00002234',
+ "Theta;": '\U00000398',
+ "ThinSpace;": '\U00002009',
+ "Tilde;": '\U0000223C',
+ "TildeEqual;": '\U00002243',
+ "TildeFullEqual;": '\U00002245',
+ "TildeTilde;": '\U00002248',
+ "Topf;": '\U0001D54B',
+ "TripleDot;": '\U000020DB',
+ "Tscr;": '\U0001D4AF',
+ "Tstrok;": '\U00000166',
+ "Uacute;": '\U000000DA',
+ "Uarr;": '\U0000219F',
+ "Uarrocir;": '\U00002949',
+ "Ubrcy;": '\U0000040E',
+ "Ubreve;": '\U0000016C',
+ "Ucirc;": '\U000000DB',
+ "Ucy;": '\U00000423',
+ "Udblac;": '\U00000170',
+ "Ufr;": '\U0001D518',
+ "Ugrave;": '\U000000D9',
+ "Umacr;": '\U0000016A',
+ "UnderBar;": '\U0000005F',
+ "UnderBrace;": '\U000023DF',
+ "UnderBracket;": '\U000023B5',
+ "UnderParenthesis;": '\U000023DD',
+ "Union;": '\U000022C3',
+ "UnionPlus;": '\U0000228E',
+ "Uogon;": '\U00000172',
+ "Uopf;": '\U0001D54C',
+ "UpArrow;": '\U00002191',
+ "UpArrowBar;": '\U00002912',
+ "UpArrowDownArrow;": '\U000021C5',
+ "UpDownArrow;": '\U00002195',
+ "UpEquilibrium;": '\U0000296E',
+ "UpTee;": '\U000022A5',
+ "UpTeeArrow;": '\U000021A5',
+ "Uparrow;": '\U000021D1',
+ "Updownarrow;": '\U000021D5',
+ "UpperLeftArrow;": '\U00002196',
+ "UpperRightArrow;": '\U00002197',
+ "Upsi;": '\U000003D2',
+ "Upsilon;": '\U000003A5',
+ "Uring;": '\U0000016E',
+ "Uscr;": '\U0001D4B0',
+ "Utilde;": '\U00000168',
+ "Uuml;": '\U000000DC',
+ "VDash;": '\U000022AB',
+ "Vbar;": '\U00002AEB',
+ "Vcy;": '\U00000412',
+ "Vdash;": '\U000022A9',
+ "Vdashl;": '\U00002AE6',
+ "Vee;": '\U000022C1',
+ "Verbar;": '\U00002016',
+ "Vert;": '\U00002016',
+ "VerticalBar;": '\U00002223',
+ "VerticalLine;": '\U0000007C',
+ "VerticalSeparator;": '\U00002758',
+ "VerticalTilde;": '\U00002240',
+ "VeryThinSpace;": '\U0000200A',
+ "Vfr;": '\U0001D519',
+ "Vopf;": '\U0001D54D',
+ "Vscr;": '\U0001D4B1',
+ "Vvdash;": '\U000022AA',
+ "Wcirc;": '\U00000174',
+ "Wedge;": '\U000022C0',
+ "Wfr;": '\U0001D51A',
+ "Wopf;": '\U0001D54E',
+ "Wscr;": '\U0001D4B2',
+ "Xfr;": '\U0001D51B',
+ "Xi;": '\U0000039E',
+ "Xopf;": '\U0001D54F',
+ "Xscr;": '\U0001D4B3',
+ "YAcy;": '\U0000042F',
+ "YIcy;": '\U00000407',
+ "YUcy;": '\U0000042E',
+ "Yacute;": '\U000000DD',
+ "Ycirc;": '\U00000176',
+ "Ycy;": '\U0000042B',
+ "Yfr;": '\U0001D51C',
+ "Yopf;": '\U0001D550',
+ "Yscr;": '\U0001D4B4',
+ "Yuml;": '\U00000178',
+ "ZHcy;": '\U00000416',
+ "Zacute;": '\U00000179',
+ "Zcaron;": '\U0000017D',
+ "Zcy;": '\U00000417',
+ "Zdot;": '\U0000017B',
+ "ZeroWidthSpace;": '\U0000200B',
+ "Zeta;": '\U00000396',
+ "Zfr;": '\U00002128',
+ "Zopf;": '\U00002124',
+ "Zscr;": '\U0001D4B5',
+ "aacute;": '\U000000E1',
+ "abreve;": '\U00000103',
+ "ac;": '\U0000223E',
+ "acd;": '\U0000223F',
+ "acirc;": '\U000000E2',
+ "acute;": '\U000000B4',
+ "acy;": '\U00000430',
+ "aelig;": '\U000000E6',
+ "af;": '\U00002061',
+ "afr;": '\U0001D51E',
+ "agrave;": '\U000000E0',
+ "alefsym;": '\U00002135',
+ "aleph;": '\U00002135',
+ "alpha;": '\U000003B1',
+ "amacr;": '\U00000101',
+ "amalg;": '\U00002A3F',
+ "amp;": '\U00000026',
+ "and;": '\U00002227',
+ "andand;": '\U00002A55',
+ "andd;": '\U00002A5C',
+ "andslope;": '\U00002A58',
+ "andv;": '\U00002A5A',
+ "ang;": '\U00002220',
+ "ange;": '\U000029A4',
+ "angle;": '\U00002220',
+ "angmsd;": '\U00002221',
+ "angmsdaa;": '\U000029A8',
+ "angmsdab;": '\U000029A9',
+ "angmsdac;": '\U000029AA',
+ "angmsdad;": '\U000029AB',
+ "angmsdae;": '\U000029AC',
+ "angmsdaf;": '\U000029AD',
+ "angmsdag;": '\U000029AE',
+ "angmsdah;": '\U000029AF',
+ "angrt;": '\U0000221F',
+ "angrtvb;": '\U000022BE',
+ "angrtvbd;": '\U0000299D',
+ "angsph;": '\U00002222',
+ "angst;": '\U000000C5',
+ "angzarr;": '\U0000237C',
+ "aogon;": '\U00000105',
+ "aopf;": '\U0001D552',
+ "ap;": '\U00002248',
+ "apE;": '\U00002A70',
+ "apacir;": '\U00002A6F',
+ "ape;": '\U0000224A',
+ "apid;": '\U0000224B',
+ "apos;": '\U00000027',
+ "approx;": '\U00002248',
+ "approxeq;": '\U0000224A',
+ "aring;": '\U000000E5',
+ "ascr;": '\U0001D4B6',
+ "ast;": '\U0000002A',
+ "asymp;": '\U00002248',
+ "asympeq;": '\U0000224D',
+ "atilde;": '\U000000E3',
+ "auml;": '\U000000E4',
+ "awconint;": '\U00002233',
+ "awint;": '\U00002A11',
+ "bNot;": '\U00002AED',
+ "backcong;": '\U0000224C',
+ "backepsilon;": '\U000003F6',
+ "backprime;": '\U00002035',
+ "backsim;": '\U0000223D',
+ "backsimeq;": '\U000022CD',
+ "barvee;": '\U000022BD',
+ "barwed;": '\U00002305',
+ "barwedge;": '\U00002305',
+ "bbrk;": '\U000023B5',
+ "bbrktbrk;": '\U000023B6',
+ "bcong;": '\U0000224C',
+ "bcy;": '\U00000431',
+ "bdquo;": '\U0000201E',
+ "becaus;": '\U00002235',
+ "because;": '\U00002235',
+ "bemptyv;": '\U000029B0',
+ "bepsi;": '\U000003F6',
+ "bernou;": '\U0000212C',
+ "beta;": '\U000003B2',
+ "beth;": '\U00002136',
+ "between;": '\U0000226C',
+ "bfr;": '\U0001D51F',
+ "bigcap;": '\U000022C2',
+ "bigcirc;": '\U000025EF',
+ "bigcup;": '\U000022C3',
+ "bigodot;": '\U00002A00',
+ "bigoplus;": '\U00002A01',
+ "bigotimes;": '\U00002A02',
+ "bigsqcup;": '\U00002A06',
+ "bigstar;": '\U00002605',
+ "bigtriangledown;": '\U000025BD',
+ "bigtriangleup;": '\U000025B3',
+ "biguplus;": '\U00002A04',
+ "bigvee;": '\U000022C1',
+ "bigwedge;": '\U000022C0',
+ "bkarow;": '\U0000290D',
+ "blacklozenge;": '\U000029EB',
+ "blacksquare;": '\U000025AA',
+ "blacktriangle;": '\U000025B4',
+ "blacktriangledown;": '\U000025BE',
+ "blacktriangleleft;": '\U000025C2',
+ "blacktriangleright;": '\U000025B8',
+ "blank;": '\U00002423',
+ "blk12;": '\U00002592',
+ "blk14;": '\U00002591',
+ "blk34;": '\U00002593',
+ "block;": '\U00002588',
+ "bnot;": '\U00002310',
+ "bopf;": '\U0001D553',
+ "bot;": '\U000022A5',
+ "bottom;": '\U000022A5',
+ "bowtie;": '\U000022C8',
+ "boxDL;": '\U00002557',
+ "boxDR;": '\U00002554',
+ "boxDl;": '\U00002556',
+ "boxDr;": '\U00002553',
+ "boxH;": '\U00002550',
+ "boxHD;": '\U00002566',
+ "boxHU;": '\U00002569',
+ "boxHd;": '\U00002564',
+ "boxHu;": '\U00002567',
+ "boxUL;": '\U0000255D',
+ "boxUR;": '\U0000255A',
+ "boxUl;": '\U0000255C',
+ "boxUr;": '\U00002559',
+ "boxV;": '\U00002551',
+ "boxVH;": '\U0000256C',
+ "boxVL;": '\U00002563',
+ "boxVR;": '\U00002560',
+ "boxVh;": '\U0000256B',
+ "boxVl;": '\U00002562',
+ "boxVr;": '\U0000255F',
+ "boxbox;": '\U000029C9',
+ "boxdL;": '\U00002555',
+ "boxdR;": '\U00002552',
+ "boxdl;": '\U00002510',
+ "boxdr;": '\U0000250C',
+ "boxh;": '\U00002500',
+ "boxhD;": '\U00002565',
+ "boxhU;": '\U00002568',
+ "boxhd;": '\U0000252C',
+ "boxhu;": '\U00002534',
+ "boxminus;": '\U0000229F',
+ "boxplus;": '\U0000229E',
+ "boxtimes;": '\U000022A0',
+ "boxuL;": '\U0000255B',
+ "boxuR;": '\U00002558',
+ "boxul;": '\U00002518',
+ "boxur;": '\U00002514',
+ "boxv;": '\U00002502',
+ "boxvH;": '\U0000256A',
+ "boxvL;": '\U00002561',
+ "boxvR;": '\U0000255E',
+ "boxvh;": '\U0000253C',
+ "boxvl;": '\U00002524',
+ "boxvr;": '\U0000251C',
+ "bprime;": '\U00002035',
+ "breve;": '\U000002D8',
+ "brvbar;": '\U000000A6',
+ "bscr;": '\U0001D4B7',
+ "bsemi;": '\U0000204F',
+ "bsim;": '\U0000223D',
+ "bsime;": '\U000022CD',
+ "bsol;": '\U0000005C',
+ "bsolb;": '\U000029C5',
+ "bsolhsub;": '\U000027C8',
+ "bull;": '\U00002022',
+ "bullet;": '\U00002022',
+ "bump;": '\U0000224E',
+ "bumpE;": '\U00002AAE',
+ "bumpe;": '\U0000224F',
+ "bumpeq;": '\U0000224F',
+ "cacute;": '\U00000107',
+ "cap;": '\U00002229',
+ "capand;": '\U00002A44',
+ "capbrcup;": '\U00002A49',
+ "capcap;": '\U00002A4B',
+ "capcup;": '\U00002A47',
+ "capdot;": '\U00002A40',
+ "caret;": '\U00002041',
+ "caron;": '\U000002C7',
+ "ccaps;": '\U00002A4D',
+ "ccaron;": '\U0000010D',
+ "ccedil;": '\U000000E7',
+ "ccirc;": '\U00000109',
+ "ccups;": '\U00002A4C',
+ "ccupssm;": '\U00002A50',
+ "cdot;": '\U0000010B',
+ "cedil;": '\U000000B8',
+ "cemptyv;": '\U000029B2',
+ "cent;": '\U000000A2',
+ "centerdot;": '\U000000B7',
+ "cfr;": '\U0001D520',
+ "chcy;": '\U00000447',
+ "check;": '\U00002713',
+ "checkmark;": '\U00002713',
+ "chi;": '\U000003C7',
+ "cir;": '\U000025CB',
+ "cirE;": '\U000029C3',
+ "circ;": '\U000002C6',
+ "circeq;": '\U00002257',
+ "circlearrowleft;": '\U000021BA',
+ "circlearrowright;": '\U000021BB',
+ "circledR;": '\U000000AE',
+ "circledS;": '\U000024C8',
+ "circledast;": '\U0000229B',
+ "circledcirc;": '\U0000229A',
+ "circleddash;": '\U0000229D',
+ "cire;": '\U00002257',
+ "cirfnint;": '\U00002A10',
+ "cirmid;": '\U00002AEF',
+ "cirscir;": '\U000029C2',
+ "clubs;": '\U00002663',
+ "clubsuit;": '\U00002663',
+ "colon;": '\U0000003A',
+ "colone;": '\U00002254',
+ "coloneq;": '\U00002254',
+ "comma;": '\U0000002C',
+ "commat;": '\U00000040',
+ "comp;": '\U00002201',
+ "compfn;": '\U00002218',
+ "complement;": '\U00002201',
+ "complexes;": '\U00002102',
+ "cong;": '\U00002245',
+ "congdot;": '\U00002A6D',
+ "conint;": '\U0000222E',
+ "copf;": '\U0001D554',
+ "coprod;": '\U00002210',
+ "copy;": '\U000000A9',
+ "copysr;": '\U00002117',
+ "crarr;": '\U000021B5',
+ "cross;": '\U00002717',
+ "cscr;": '\U0001D4B8',
+ "csub;": '\U00002ACF',
+ "csube;": '\U00002AD1',
+ "csup;": '\U00002AD0',
+ "csupe;": '\U00002AD2',
+ "ctdot;": '\U000022EF',
+ "cudarrl;": '\U00002938',
+ "cudarrr;": '\U00002935',
+ "cuepr;": '\U000022DE',
+ "cuesc;": '\U000022DF',
+ "cularr;": '\U000021B6',
+ "cularrp;": '\U0000293D',
+ "cup;": '\U0000222A',
+ "cupbrcap;": '\U00002A48',
+ "cupcap;": '\U00002A46',
+ "cupcup;": '\U00002A4A',
+ "cupdot;": '\U0000228D',
+ "cupor;": '\U00002A45',
+ "curarr;": '\U000021B7',
+ "curarrm;": '\U0000293C',
+ "curlyeqprec;": '\U000022DE',
+ "curlyeqsucc;": '\U000022DF',
+ "curlyvee;": '\U000022CE',
+ "curlywedge;": '\U000022CF',
+ "curren;": '\U000000A4',
+ "curvearrowleft;": '\U000021B6',
+ "curvearrowright;": '\U000021B7',
+ "cuvee;": '\U000022CE',
+ "cuwed;": '\U000022CF',
+ "cwconint;": '\U00002232',
+ "cwint;": '\U00002231',
+ "cylcty;": '\U0000232D',
+ "dArr;": '\U000021D3',
+ "dHar;": '\U00002965',
+ "dagger;": '\U00002020',
+ "daleth;": '\U00002138',
+ "darr;": '\U00002193',
+ "dash;": '\U00002010',
+ "dashv;": '\U000022A3',
+ "dbkarow;": '\U0000290F',
+ "dblac;": '\U000002DD',
+ "dcaron;": '\U0000010F',
+ "dcy;": '\U00000434',
+ "dd;": '\U00002146',
+ "ddagger;": '\U00002021',
+ "ddarr;": '\U000021CA',
+ "ddotseq;": '\U00002A77',
+ "deg;": '\U000000B0',
+ "delta;": '\U000003B4',
+ "demptyv;": '\U000029B1',
+ "dfisht;": '\U0000297F',
+ "dfr;": '\U0001D521',
+ "dharl;": '\U000021C3',
+ "dharr;": '\U000021C2',
+ "diam;": '\U000022C4',
+ "diamond;": '\U000022C4',
+ "diamondsuit;": '\U00002666',
+ "diams;": '\U00002666',
+ "die;": '\U000000A8',
+ "digamma;": '\U000003DD',
+ "disin;": '\U000022F2',
+ "div;": '\U000000F7',
+ "divide;": '\U000000F7',
+ "divideontimes;": '\U000022C7',
+ "divonx;": '\U000022C7',
+ "djcy;": '\U00000452',
+ "dlcorn;": '\U0000231E',
+ "dlcrop;": '\U0000230D',
+ "dollar;": '\U00000024',
+ "dopf;": '\U0001D555',
+ "dot;": '\U000002D9',
+ "doteq;": '\U00002250',
+ "doteqdot;": '\U00002251',
+ "dotminus;": '\U00002238',
+ "dotplus;": '\U00002214',
+ "dotsquare;": '\U000022A1',
+ "doublebarwedge;": '\U00002306',
+ "downarrow;": '\U00002193',
+ "downdownarrows;": '\U000021CA',
+ "downharpoonleft;": '\U000021C3',
+ "downharpoonright;": '\U000021C2',
+ "drbkarow;": '\U00002910',
+ "drcorn;": '\U0000231F',
+ "drcrop;": '\U0000230C',
+ "dscr;": '\U0001D4B9',
+ "dscy;": '\U00000455',
+ "dsol;": '\U000029F6',
+ "dstrok;": '\U00000111',
+ "dtdot;": '\U000022F1',
+ "dtri;": '\U000025BF',
+ "dtrif;": '\U000025BE',
+ "duarr;": '\U000021F5',
+ "duhar;": '\U0000296F',
+ "dwangle;": '\U000029A6',
+ "dzcy;": '\U0000045F',
+ "dzigrarr;": '\U000027FF',
+ "eDDot;": '\U00002A77',
+ "eDot;": '\U00002251',
+ "eacute;": '\U000000E9',
+ "easter;": '\U00002A6E',
+ "ecaron;": '\U0000011B',
+ "ecir;": '\U00002256',
+ "ecirc;": '\U000000EA',
+ "ecolon;": '\U00002255',
+ "ecy;": '\U0000044D',
+ "edot;": '\U00000117',
+ "ee;": '\U00002147',
+ "efDot;": '\U00002252',
+ "efr;": '\U0001D522',
+ "eg;": '\U00002A9A',
+ "egrave;": '\U000000E8',
+ "egs;": '\U00002A96',
+ "egsdot;": '\U00002A98',
+ "el;": '\U00002A99',
+ "elinters;": '\U000023E7',
+ "ell;": '\U00002113',
+ "els;": '\U00002A95',
+ "elsdot;": '\U00002A97',
+ "emacr;": '\U00000113',
+ "empty;": '\U00002205',
+ "emptyset;": '\U00002205',
+ "emptyv;": '\U00002205',
+ "emsp;": '\U00002003',
+ "emsp13;": '\U00002004',
+ "emsp14;": '\U00002005',
+ "eng;": '\U0000014B',
+ "ensp;": '\U00002002',
+ "eogon;": '\U00000119',
+ "eopf;": '\U0001D556',
+ "epar;": '\U000022D5',
+ "eparsl;": '\U000029E3',
+ "eplus;": '\U00002A71',
+ "epsi;": '\U000003B5',
+ "epsilon;": '\U000003B5',
+ "epsiv;": '\U000003F5',
+ "eqcirc;": '\U00002256',
+ "eqcolon;": '\U00002255',
+ "eqsim;": '\U00002242',
+ "eqslantgtr;": '\U00002A96',
+ "eqslantless;": '\U00002A95',
+ "equals;": '\U0000003D',
+ "equest;": '\U0000225F',
+ "equiv;": '\U00002261',
+ "equivDD;": '\U00002A78',
+ "eqvparsl;": '\U000029E5',
+ "erDot;": '\U00002253',
+ "erarr;": '\U00002971',
+ "escr;": '\U0000212F',
+ "esdot;": '\U00002250',
+ "esim;": '\U00002242',
+ "eta;": '\U000003B7',
+ "eth;": '\U000000F0',
+ "euml;": '\U000000EB',
+ "euro;": '\U000020AC',
+ "excl;": '\U00000021',
+ "exist;": '\U00002203',
+ "expectation;": '\U00002130',
+ "exponentiale;": '\U00002147',
+ "fallingdotseq;": '\U00002252',
+ "fcy;": '\U00000444',
+ "female;": '\U00002640',
+ "ffilig;": '\U0000FB03',
+ "fflig;": '\U0000FB00',
+ "ffllig;": '\U0000FB04',
+ "ffr;": '\U0001D523',
+ "filig;": '\U0000FB01',
+ "flat;": '\U0000266D',
+ "fllig;": '\U0000FB02',
+ "fltns;": '\U000025B1',
+ "fnof;": '\U00000192',
+ "fopf;": '\U0001D557',
+ "forall;": '\U00002200',
+ "fork;": '\U000022D4',
+ "forkv;": '\U00002AD9',
+ "fpartint;": '\U00002A0D',
+ "frac12;": '\U000000BD',
+ "frac13;": '\U00002153',
+ "frac14;": '\U000000BC',
+ "frac15;": '\U00002155',
+ "frac16;": '\U00002159',
+ "frac18;": '\U0000215B',
+ "frac23;": '\U00002154',
+ "frac25;": '\U00002156',
+ "frac34;": '\U000000BE',
+ "frac35;": '\U00002157',
+ "frac38;": '\U0000215C',
+ "frac45;": '\U00002158',
+ "frac56;": '\U0000215A',
+ "frac58;": '\U0000215D',
+ "frac78;": '\U0000215E',
+ "frasl;": '\U00002044',
+ "frown;": '\U00002322',
+ "fscr;": '\U0001D4BB',
+ "gE;": '\U00002267',
+ "gEl;": '\U00002A8C',
+ "gacute;": '\U000001F5',
+ "gamma;": '\U000003B3',
+ "gammad;": '\U000003DD',
+ "gap;": '\U00002A86',
+ "gbreve;": '\U0000011F',
+ "gcirc;": '\U0000011D',
+ "gcy;": '\U00000433',
+ "gdot;": '\U00000121',
+ "ge;": '\U00002265',
+ "gel;": '\U000022DB',
+ "geq;": '\U00002265',
+ "geqq;": '\U00002267',
+ "geqslant;": '\U00002A7E',
+ "ges;": '\U00002A7E',
+ "gescc;": '\U00002AA9',
+ "gesdot;": '\U00002A80',
+ "gesdoto;": '\U00002A82',
+ "gesdotol;": '\U00002A84',
+ "gesles;": '\U00002A94',
+ "gfr;": '\U0001D524',
+ "gg;": '\U0000226B',
+ "ggg;": '\U000022D9',
+ "gimel;": '\U00002137',
+ "gjcy;": '\U00000453',
+ "gl;": '\U00002277',
+ "glE;": '\U00002A92',
+ "gla;": '\U00002AA5',
+ "glj;": '\U00002AA4',
+ "gnE;": '\U00002269',
+ "gnap;": '\U00002A8A',
+ "gnapprox;": '\U00002A8A',
+ "gne;": '\U00002A88',
+ "gneq;": '\U00002A88',
+ "gneqq;": '\U00002269',
+ "gnsim;": '\U000022E7',
+ "gopf;": '\U0001D558',
+ "grave;": '\U00000060',
+ "gscr;": '\U0000210A',
+ "gsim;": '\U00002273',
+ "gsime;": '\U00002A8E',
+ "gsiml;": '\U00002A90',
+ "gt;": '\U0000003E',
+ "gtcc;": '\U00002AA7',
+ "gtcir;": '\U00002A7A',
+ "gtdot;": '\U000022D7',
+ "gtlPar;": '\U00002995',
+ "gtquest;": '\U00002A7C',
+ "gtrapprox;": '\U00002A86',
+ "gtrarr;": '\U00002978',
+ "gtrdot;": '\U000022D7',
+ "gtreqless;": '\U000022DB',
+ "gtreqqless;": '\U00002A8C',
+ "gtrless;": '\U00002277',
+ "gtrsim;": '\U00002273',
+ "hArr;": '\U000021D4',
+ "hairsp;": '\U0000200A',
+ "half;": '\U000000BD',
+ "hamilt;": '\U0000210B',
+ "hardcy;": '\U0000044A',
+ "harr;": '\U00002194',
+ "harrcir;": '\U00002948',
+ "harrw;": '\U000021AD',
+ "hbar;": '\U0000210F',
+ "hcirc;": '\U00000125',
+ "hearts;": '\U00002665',
+ "heartsuit;": '\U00002665',
+ "hellip;": '\U00002026',
+ "hercon;": '\U000022B9',
+ "hfr;": '\U0001D525',
+ "hksearow;": '\U00002925',
+ "hkswarow;": '\U00002926',
+ "hoarr;": '\U000021FF',
+ "homtht;": '\U0000223B',
+ "hookleftarrow;": '\U000021A9',
+ "hookrightarrow;": '\U000021AA',
+ "hopf;": '\U0001D559',
+ "horbar;": '\U00002015',
+ "hscr;": '\U0001D4BD',
+ "hslash;": '\U0000210F',
+ "hstrok;": '\U00000127',
+ "hybull;": '\U00002043',
+ "hyphen;": '\U00002010',
+ "iacute;": '\U000000ED',
+ "ic;": '\U00002063',
+ "icirc;": '\U000000EE',
+ "icy;": '\U00000438',
+ "iecy;": '\U00000435',
+ "iexcl;": '\U000000A1',
+ "iff;": '\U000021D4',
+ "ifr;": '\U0001D526',
+ "igrave;": '\U000000EC',
+ "ii;": '\U00002148',
+ "iiiint;": '\U00002A0C',
+ "iiint;": '\U0000222D',
+ "iinfin;": '\U000029DC',
+ "iiota;": '\U00002129',
+ "ijlig;": '\U00000133',
+ "imacr;": '\U0000012B',
+ "image;": '\U00002111',
+ "imagline;": '\U00002110',
+ "imagpart;": '\U00002111',
+ "imath;": '\U00000131',
+ "imof;": '\U000022B7',
+ "imped;": '\U000001B5',
+ "in;": '\U00002208',
+ "incare;": '\U00002105',
+ "infin;": '\U0000221E',
+ "infintie;": '\U000029DD',
+ "inodot;": '\U00000131',
+ "int;": '\U0000222B',
+ "intcal;": '\U000022BA',
+ "integers;": '\U00002124',
+ "intercal;": '\U000022BA',
+ "intlarhk;": '\U00002A17',
+ "intprod;": '\U00002A3C',
+ "iocy;": '\U00000451',
+ "iogon;": '\U0000012F',
+ "iopf;": '\U0001D55A',
+ "iota;": '\U000003B9',
+ "iprod;": '\U00002A3C',
+ "iquest;": '\U000000BF',
+ "iscr;": '\U0001D4BE',
+ "isin;": '\U00002208',
+ "isinE;": '\U000022F9',
+ "isindot;": '\U000022F5',
+ "isins;": '\U000022F4',
+ "isinsv;": '\U000022F3',
+ "isinv;": '\U00002208',
+ "it;": '\U00002062',
+ "itilde;": '\U00000129',
+ "iukcy;": '\U00000456',
+ "iuml;": '\U000000EF',
+ "jcirc;": '\U00000135',
+ "jcy;": '\U00000439',
+ "jfr;": '\U0001D527',
+ "jmath;": '\U00000237',
+ "jopf;": '\U0001D55B',
+ "jscr;": '\U0001D4BF',
+ "jsercy;": '\U00000458',
+ "jukcy;": '\U00000454',
+ "kappa;": '\U000003BA',
+ "kappav;": '\U000003F0',
+ "kcedil;": '\U00000137',
+ "kcy;": '\U0000043A',
+ "kfr;": '\U0001D528',
+ "kgreen;": '\U00000138',
+ "khcy;": '\U00000445',
+ "kjcy;": '\U0000045C',
+ "kopf;": '\U0001D55C',
+ "kscr;": '\U0001D4C0',
+ "lAarr;": '\U000021DA',
+ "lArr;": '\U000021D0',
+ "lAtail;": '\U0000291B',
+ "lBarr;": '\U0000290E',
+ "lE;": '\U00002266',
+ "lEg;": '\U00002A8B',
+ "lHar;": '\U00002962',
+ "lacute;": '\U0000013A',
+ "laemptyv;": '\U000029B4',
+ "lagran;": '\U00002112',
+ "lambda;": '\U000003BB',
+ "lang;": '\U000027E8',
+ "langd;": '\U00002991',
+ "langle;": '\U000027E8',
+ "lap;": '\U00002A85',
+ "laquo;": '\U000000AB',
+ "larr;": '\U00002190',
+ "larrb;": '\U000021E4',
+ "larrbfs;": '\U0000291F',
+ "larrfs;": '\U0000291D',
+ "larrhk;": '\U000021A9',
+ "larrlp;": '\U000021AB',
+ "larrpl;": '\U00002939',
+ "larrsim;": '\U00002973',
+ "larrtl;": '\U000021A2',
+ "lat;": '\U00002AAB',
+ "latail;": '\U00002919',
+ "late;": '\U00002AAD',
+ "lbarr;": '\U0000290C',
+ "lbbrk;": '\U00002772',
+ "lbrace;": '\U0000007B',
+ "lbrack;": '\U0000005B',
+ "lbrke;": '\U0000298B',
+ "lbrksld;": '\U0000298F',
+ "lbrkslu;": '\U0000298D',
+ "lcaron;": '\U0000013E',
+ "lcedil;": '\U0000013C',
+ "lceil;": '\U00002308',
+ "lcub;": '\U0000007B',
+ "lcy;": '\U0000043B',
+ "ldca;": '\U00002936',
+ "ldquo;": '\U0000201C',
+ "ldquor;": '\U0000201E',
+ "ldrdhar;": '\U00002967',
+ "ldrushar;": '\U0000294B',
+ "ldsh;": '\U000021B2',
+ "le;": '\U00002264',
+ "leftarrow;": '\U00002190',
+ "leftarrowtail;": '\U000021A2',
+ "leftharpoondown;": '\U000021BD',
+ "leftharpoonup;": '\U000021BC',
+ "leftleftarrows;": '\U000021C7',
+ "leftrightarrow;": '\U00002194',
+ "leftrightarrows;": '\U000021C6',
+ "leftrightharpoons;": '\U000021CB',
+ "leftrightsquigarrow;": '\U000021AD',
+ "leftthreetimes;": '\U000022CB',
+ "leg;": '\U000022DA',
+ "leq;": '\U00002264',
+ "leqq;": '\U00002266',
+ "leqslant;": '\U00002A7D',
+ "les;": '\U00002A7D',
+ "lescc;": '\U00002AA8',
+ "lesdot;": '\U00002A7F',
+ "lesdoto;": '\U00002A81',
+ "lesdotor;": '\U00002A83',
+ "lesges;": '\U00002A93',
+ "lessapprox;": '\U00002A85',
+ "lessdot;": '\U000022D6',
+ "lesseqgtr;": '\U000022DA',
+ "lesseqqgtr;": '\U00002A8B',
+ "lessgtr;": '\U00002276',
+ "lesssim;": '\U00002272',
+ "lfisht;": '\U0000297C',
+ "lfloor;": '\U0000230A',
+ "lfr;": '\U0001D529',
+ "lg;": '\U00002276',
+ "lgE;": '\U00002A91',
+ "lhard;": '\U000021BD',
+ "lharu;": '\U000021BC',
+ "lharul;": '\U0000296A',
+ "lhblk;": '\U00002584',
+ "ljcy;": '\U00000459',
+ "ll;": '\U0000226A',
+ "llarr;": '\U000021C7',
+ "llcorner;": '\U0000231E',
+ "llhard;": '\U0000296B',
+ "lltri;": '\U000025FA',
+ "lmidot;": '\U00000140',
+ "lmoust;": '\U000023B0',
+ "lmoustache;": '\U000023B0',
+ "lnE;": '\U00002268',
+ "lnap;": '\U00002A89',
+ "lnapprox;": '\U00002A89',
+ "lne;": '\U00002A87',
+ "lneq;": '\U00002A87',
+ "lneqq;": '\U00002268',
+ "lnsim;": '\U000022E6',
+ "loang;": '\U000027EC',
+ "loarr;": '\U000021FD',
+ "lobrk;": '\U000027E6',
+ "longleftarrow;": '\U000027F5',
+ "longleftrightarrow;": '\U000027F7',
+ "longmapsto;": '\U000027FC',
+ "longrightarrow;": '\U000027F6',
+ "looparrowleft;": '\U000021AB',
+ "looparrowright;": '\U000021AC',
+ "lopar;": '\U00002985',
+ "lopf;": '\U0001D55D',
+ "loplus;": '\U00002A2D',
+ "lotimes;": '\U00002A34',
+ "lowast;": '\U00002217',
+ "lowbar;": '\U0000005F',
+ "loz;": '\U000025CA',
+ "lozenge;": '\U000025CA',
+ "lozf;": '\U000029EB',
+ "lpar;": '\U00000028',
+ "lparlt;": '\U00002993',
+ "lrarr;": '\U000021C6',
+ "lrcorner;": '\U0000231F',
+ "lrhar;": '\U000021CB',
+ "lrhard;": '\U0000296D',
+ "lrm;": '\U0000200E',
+ "lrtri;": '\U000022BF',
+ "lsaquo;": '\U00002039',
+ "lscr;": '\U0001D4C1',
+ "lsh;": '\U000021B0',
+ "lsim;": '\U00002272',
+ "lsime;": '\U00002A8D',
+ "lsimg;": '\U00002A8F',
+ "lsqb;": '\U0000005B',
+ "lsquo;": '\U00002018',
+ "lsquor;": '\U0000201A',
+ "lstrok;": '\U00000142',
+ "lt;": '\U0000003C',
+ "ltcc;": '\U00002AA6',
+ "ltcir;": '\U00002A79',
+ "ltdot;": '\U000022D6',
+ "lthree;": '\U000022CB',
+ "ltimes;": '\U000022C9',
+ "ltlarr;": '\U00002976',
+ "ltquest;": '\U00002A7B',
+ "ltrPar;": '\U00002996',
+ "ltri;": '\U000025C3',
+ "ltrie;": '\U000022B4',
+ "ltrif;": '\U000025C2',
+ "lurdshar;": '\U0000294A',
+ "luruhar;": '\U00002966',
+ "mDDot;": '\U0000223A',
+ "macr;": '\U000000AF',
+ "male;": '\U00002642',
+ "malt;": '\U00002720',
+ "maltese;": '\U00002720',
+ "map;": '\U000021A6',
+ "mapsto;": '\U000021A6',
+ "mapstodown;": '\U000021A7',
+ "mapstoleft;": '\U000021A4',
+ "mapstoup;": '\U000021A5',
+ "marker;": '\U000025AE',
+ "mcomma;": '\U00002A29',
+ "mcy;": '\U0000043C',
+ "mdash;": '\U00002014',
+ "measuredangle;": '\U00002221',
+ "mfr;": '\U0001D52A',
+ "mho;": '\U00002127',
+ "micro;": '\U000000B5',
+ "mid;": '\U00002223',
+ "midast;": '\U0000002A',
+ "midcir;": '\U00002AF0',
+ "middot;": '\U000000B7',
+ "minus;": '\U00002212',
+ "minusb;": '\U0000229F',
+ "minusd;": '\U00002238',
+ "minusdu;": '\U00002A2A',
+ "mlcp;": '\U00002ADB',
+ "mldr;": '\U00002026',
+ "mnplus;": '\U00002213',
+ "models;": '\U000022A7',
+ "mopf;": '\U0001D55E',
+ "mp;": '\U00002213',
+ "mscr;": '\U0001D4C2',
+ "mstpos;": '\U0000223E',
+ "mu;": '\U000003BC',
+ "multimap;": '\U000022B8',
+ "mumap;": '\U000022B8',
+ "nLeftarrow;": '\U000021CD',
+ "nLeftrightarrow;": '\U000021CE',
+ "nRightarrow;": '\U000021CF',
+ "nVDash;": '\U000022AF',
+ "nVdash;": '\U000022AE',
+ "nabla;": '\U00002207',
+ "nacute;": '\U00000144',
+ "nap;": '\U00002249',
+ "napos;": '\U00000149',
+ "napprox;": '\U00002249',
+ "natur;": '\U0000266E',
+ "natural;": '\U0000266E',
+ "naturals;": '\U00002115',
+ "nbsp;": '\U000000A0',
+ "ncap;": '\U00002A43',
+ "ncaron;": '\U00000148',
+ "ncedil;": '\U00000146',
+ "ncong;": '\U00002247',
+ "ncup;": '\U00002A42',
+ "ncy;": '\U0000043D',
+ "ndash;": '\U00002013',
+ "ne;": '\U00002260',
+ "neArr;": '\U000021D7',
+ "nearhk;": '\U00002924',
+ "nearr;": '\U00002197',
+ "nearrow;": '\U00002197',
+ "nequiv;": '\U00002262',
+ "nesear;": '\U00002928',
+ "nexist;": '\U00002204',
+ "nexists;": '\U00002204',
+ "nfr;": '\U0001D52B',
+ "nge;": '\U00002271',
+ "ngeq;": '\U00002271',
+ "ngsim;": '\U00002275',
+ "ngt;": '\U0000226F',
+ "ngtr;": '\U0000226F',
+ "nhArr;": '\U000021CE',
+ "nharr;": '\U000021AE',
+ "nhpar;": '\U00002AF2',
+ "ni;": '\U0000220B',
+ "nis;": '\U000022FC',
+ "nisd;": '\U000022FA',
+ "niv;": '\U0000220B',
+ "njcy;": '\U0000045A',
+ "nlArr;": '\U000021CD',
+ "nlarr;": '\U0000219A',
+ "nldr;": '\U00002025',
+ "nle;": '\U00002270',
+ "nleftarrow;": '\U0000219A',
+ "nleftrightarrow;": '\U000021AE',
+ "nleq;": '\U00002270',
+ "nless;": '\U0000226E',
+ "nlsim;": '\U00002274',
+ "nlt;": '\U0000226E',
+ "nltri;": '\U000022EA',
+ "nltrie;": '\U000022EC',
+ "nmid;": '\U00002224',
+ "nopf;": '\U0001D55F',
+ "not;": '\U000000AC',
+ "notin;": '\U00002209',
+ "notinva;": '\U00002209',
+ "notinvb;": '\U000022F7',
+ "notinvc;": '\U000022F6',
+ "notni;": '\U0000220C',
+ "notniva;": '\U0000220C',
+ "notnivb;": '\U000022FE',
+ "notnivc;": '\U000022FD',
+ "npar;": '\U00002226',
+ "nparallel;": '\U00002226',
+ "npolint;": '\U00002A14',
+ "npr;": '\U00002280',
+ "nprcue;": '\U000022E0',
+ "nprec;": '\U00002280',
+ "nrArr;": '\U000021CF',
+ "nrarr;": '\U0000219B',
+ "nrightarrow;": '\U0000219B',
+ "nrtri;": '\U000022EB',
+ "nrtrie;": '\U000022ED',
+ "nsc;": '\U00002281',
+ "nsccue;": '\U000022E1',
+ "nscr;": '\U0001D4C3',
+ "nshortmid;": '\U00002224',
+ "nshortparallel;": '\U00002226',
+ "nsim;": '\U00002241',
+ "nsime;": '\U00002244',
+ "nsimeq;": '\U00002244',
+ "nsmid;": '\U00002224',
+ "nspar;": '\U00002226',
+ "nsqsube;": '\U000022E2',
+ "nsqsupe;": '\U000022E3',
+ "nsub;": '\U00002284',
+ "nsube;": '\U00002288',
+ "nsubseteq;": '\U00002288',
+ "nsucc;": '\U00002281',
+ "nsup;": '\U00002285',
+ "nsupe;": '\U00002289',
+ "nsupseteq;": '\U00002289',
+ "ntgl;": '\U00002279',
+ "ntilde;": '\U000000F1',
+ "ntlg;": '\U00002278',
+ "ntriangleleft;": '\U000022EA',
+ "ntrianglelefteq;": '\U000022EC',
+ "ntriangleright;": '\U000022EB',
+ "ntrianglerighteq;": '\U000022ED',
+ "nu;": '\U000003BD',
+ "num;": '\U00000023',
+ "numero;": '\U00002116',
+ "numsp;": '\U00002007',
+ "nvDash;": '\U000022AD',
+ "nvHarr;": '\U00002904',
+ "nvdash;": '\U000022AC',
+ "nvinfin;": '\U000029DE',
+ "nvlArr;": '\U00002902',
+ "nvrArr;": '\U00002903',
+ "nwArr;": '\U000021D6',
+ "nwarhk;": '\U00002923',
+ "nwarr;": '\U00002196',
+ "nwarrow;": '\U00002196',
+ "nwnear;": '\U00002927',
+ "oS;": '\U000024C8',
+ "oacute;": '\U000000F3',
+ "oast;": '\U0000229B',
+ "ocir;": '\U0000229A',
+ "ocirc;": '\U000000F4',
+ "ocy;": '\U0000043E',
+ "odash;": '\U0000229D',
+ "odblac;": '\U00000151',
+ "odiv;": '\U00002A38',
+ "odot;": '\U00002299',
+ "odsold;": '\U000029BC',
+ "oelig;": '\U00000153',
+ "ofcir;": '\U000029BF',
+ "ofr;": '\U0001D52C',
+ "ogon;": '\U000002DB',
+ "ograve;": '\U000000F2',
+ "ogt;": '\U000029C1',
+ "ohbar;": '\U000029B5',
+ "ohm;": '\U000003A9',
+ "oint;": '\U0000222E',
+ "olarr;": '\U000021BA',
+ "olcir;": '\U000029BE',
+ "olcross;": '\U000029BB',
+ "oline;": '\U0000203E',
+ "olt;": '\U000029C0',
+ "omacr;": '\U0000014D',
+ "omega;": '\U000003C9',
+ "omicron;": '\U000003BF',
+ "omid;": '\U000029B6',
+ "ominus;": '\U00002296',
+ "oopf;": '\U0001D560',
+ "opar;": '\U000029B7',
+ "operp;": '\U000029B9',
+ "oplus;": '\U00002295',
+ "or;": '\U00002228',
+ "orarr;": '\U000021BB',
+ "ord;": '\U00002A5D',
+ "order;": '\U00002134',
+ "orderof;": '\U00002134',
+ "ordf;": '\U000000AA',
+ "ordm;": '\U000000BA',
+ "origof;": '\U000022B6',
+ "oror;": '\U00002A56',
+ "orslope;": '\U00002A57',
+ "orv;": '\U00002A5B',
+ "oscr;": '\U00002134',
+ "oslash;": '\U000000F8',
+ "osol;": '\U00002298',
+ "otilde;": '\U000000F5',
+ "otimes;": '\U00002297',
+ "otimesas;": '\U00002A36',
+ "ouml;": '\U000000F6',
+ "ovbar;": '\U0000233D',
+ "par;": '\U00002225',
+ "para;": '\U000000B6',
+ "parallel;": '\U00002225',
+ "parsim;": '\U00002AF3',
+ "parsl;": '\U00002AFD',
+ "part;": '\U00002202',
+ "pcy;": '\U0000043F',
+ "percnt;": '\U00000025',
+ "period;": '\U0000002E',
+ "permil;": '\U00002030',
+ "perp;": '\U000022A5',
+ "pertenk;": '\U00002031',
+ "pfr;": '\U0001D52D',
+ "phi;": '\U000003C6',
+ "phiv;": '\U000003D5',
+ "phmmat;": '\U00002133',
+ "phone;": '\U0000260E',
+ "pi;": '\U000003C0',
+ "pitchfork;": '\U000022D4',
+ "piv;": '\U000003D6',
+ "planck;": '\U0000210F',
+ "planckh;": '\U0000210E',
+ "plankv;": '\U0000210F',
+ "plus;": '\U0000002B',
+ "plusacir;": '\U00002A23',
+ "plusb;": '\U0000229E',
+ "pluscir;": '\U00002A22',
+ "plusdo;": '\U00002214',
+ "plusdu;": '\U00002A25',
+ "pluse;": '\U00002A72',
+ "plusmn;": '\U000000B1',
+ "plussim;": '\U00002A26',
+ "plustwo;": '\U00002A27',
+ "pm;": '\U000000B1',
+ "pointint;": '\U00002A15',
+ "popf;": '\U0001D561',
+ "pound;": '\U000000A3',
+ "pr;": '\U0000227A',
+ "prE;": '\U00002AB3',
+ "prap;": '\U00002AB7',
+ "prcue;": '\U0000227C',
+ "pre;": '\U00002AAF',
+ "prec;": '\U0000227A',
+ "precapprox;": '\U00002AB7',
+ "preccurlyeq;": '\U0000227C',
+ "preceq;": '\U00002AAF',
+ "precnapprox;": '\U00002AB9',
+ "precneqq;": '\U00002AB5',
+ "precnsim;": '\U000022E8',
+ "precsim;": '\U0000227E',
+ "prime;": '\U00002032',
+ "primes;": '\U00002119',
+ "prnE;": '\U00002AB5',
+ "prnap;": '\U00002AB9',
+ "prnsim;": '\U000022E8',
+ "prod;": '\U0000220F',
+ "profalar;": '\U0000232E',
+ "profline;": '\U00002312',
+ "profsurf;": '\U00002313',
+ "prop;": '\U0000221D',
+ "propto;": '\U0000221D',
+ "prsim;": '\U0000227E',
+ "prurel;": '\U000022B0',
+ "pscr;": '\U0001D4C5',
+ "psi;": '\U000003C8',
+ "puncsp;": '\U00002008',
+ "qfr;": '\U0001D52E',
+ "qint;": '\U00002A0C',
+ "qopf;": '\U0001D562',
+ "qprime;": '\U00002057',
+ "qscr;": '\U0001D4C6',
+ "quaternions;": '\U0000210D',
+ "quatint;": '\U00002A16',
+ "quest;": '\U0000003F',
+ "questeq;": '\U0000225F',
+ "quot;": '\U00000022',
+ "rAarr;": '\U000021DB',
+ "rArr;": '\U000021D2',
+ "rAtail;": '\U0000291C',
+ "rBarr;": '\U0000290F',
+ "rHar;": '\U00002964',
+ "racute;": '\U00000155',
+ "radic;": '\U0000221A',
+ "raemptyv;": '\U000029B3',
+ "rang;": '\U000027E9',
+ "rangd;": '\U00002992',
+ "range;": '\U000029A5',
+ "rangle;": '\U000027E9',
+ "raquo;": '\U000000BB',
+ "rarr;": '\U00002192',
+ "rarrap;": '\U00002975',
+ "rarrb;": '\U000021E5',
+ "rarrbfs;": '\U00002920',
+ "rarrc;": '\U00002933',
+ "rarrfs;": '\U0000291E',
+ "rarrhk;": '\U000021AA',
+ "rarrlp;": '\U000021AC',
+ "rarrpl;": '\U00002945',
+ "rarrsim;": '\U00002974',
+ "rarrtl;": '\U000021A3',
+ "rarrw;": '\U0000219D',
+ "ratail;": '\U0000291A',
+ "ratio;": '\U00002236',
+ "rationals;": '\U0000211A',
+ "rbarr;": '\U0000290D',
+ "rbbrk;": '\U00002773',
+ "rbrace;": '\U0000007D',
+ "rbrack;": '\U0000005D',
+ "rbrke;": '\U0000298C',
+ "rbrksld;": '\U0000298E',
+ "rbrkslu;": '\U00002990',
+ "rcaron;": '\U00000159',
+ "rcedil;": '\U00000157',
+ "rceil;": '\U00002309',
+ "rcub;": '\U0000007D',
+ "rcy;": '\U00000440',
+ "rdca;": '\U00002937',
+ "rdldhar;": '\U00002969',
+ "rdquo;": '\U0000201D',
+ "rdquor;": '\U0000201D',
+ "rdsh;": '\U000021B3',
+ "real;": '\U0000211C',
+ "realine;": '\U0000211B',
+ "realpart;": '\U0000211C',
+ "reals;": '\U0000211D',
+ "rect;": '\U000025AD',
+ "reg;": '\U000000AE',
+ "rfisht;": '\U0000297D',
+ "rfloor;": '\U0000230B',
+ "rfr;": '\U0001D52F',
+ "rhard;": '\U000021C1',
+ "rharu;": '\U000021C0',
+ "rharul;": '\U0000296C',
+ "rho;": '\U000003C1',
+ "rhov;": '\U000003F1',
+ "rightarrow;": '\U00002192',
+ "rightarrowtail;": '\U000021A3',
+ "rightharpoondown;": '\U000021C1',
+ "rightharpoonup;": '\U000021C0',
+ "rightleftarrows;": '\U000021C4',
+ "rightleftharpoons;": '\U000021CC',
+ "rightrightarrows;": '\U000021C9',
+ "rightsquigarrow;": '\U0000219D',
+ "rightthreetimes;": '\U000022CC',
+ "ring;": '\U000002DA',
+ "risingdotseq;": '\U00002253',
+ "rlarr;": '\U000021C4',
+ "rlhar;": '\U000021CC',
+ "rlm;": '\U0000200F',
+ "rmoust;": '\U000023B1',
+ "rmoustache;": '\U000023B1',
+ "rnmid;": '\U00002AEE',
+ "roang;": '\U000027ED',
+ "roarr;": '\U000021FE',
+ "robrk;": '\U000027E7',
+ "ropar;": '\U00002986',
+ "ropf;": '\U0001D563',
+ "roplus;": '\U00002A2E',
+ "rotimes;": '\U00002A35',
+ "rpar;": '\U00000029',
+ "rpargt;": '\U00002994',
+ "rppolint;": '\U00002A12',
+ "rrarr;": '\U000021C9',
+ "rsaquo;": '\U0000203A',
+ "rscr;": '\U0001D4C7',
+ "rsh;": '\U000021B1',
+ "rsqb;": '\U0000005D',
+ "rsquo;": '\U00002019',
+ "rsquor;": '\U00002019',
+ "rthree;": '\U000022CC',
+ "rtimes;": '\U000022CA',
+ "rtri;": '\U000025B9',
+ "rtrie;": '\U000022B5',
+ "rtrif;": '\U000025B8',
+ "rtriltri;": '\U000029CE',
+ "ruluhar;": '\U00002968',
+ "rx;": '\U0000211E',
+ "sacute;": '\U0000015B',
+ "sbquo;": '\U0000201A',
+ "sc;": '\U0000227B',
+ "scE;": '\U00002AB4',
+ "scap;": '\U00002AB8',
+ "scaron;": '\U00000161',
+ "sccue;": '\U0000227D',
+ "sce;": '\U00002AB0',
+ "scedil;": '\U0000015F',
+ "scirc;": '\U0000015D',
+ "scnE;": '\U00002AB6',
+ "scnap;": '\U00002ABA',
+ "scnsim;": '\U000022E9',
+ "scpolint;": '\U00002A13',
+ "scsim;": '\U0000227F',
+ "scy;": '\U00000441',
+ "sdot;": '\U000022C5',
+ "sdotb;": '\U000022A1',
+ "sdote;": '\U00002A66',
+ "seArr;": '\U000021D8',
+ "searhk;": '\U00002925',
+ "searr;": '\U00002198',
+ "searrow;": '\U00002198',
+ "sect;": '\U000000A7',
+ "semi;": '\U0000003B',
+ "seswar;": '\U00002929',
+ "setminus;": '\U00002216',
+ "setmn;": '\U00002216',
+ "sext;": '\U00002736',
+ "sfr;": '\U0001D530',
+ "sfrown;": '\U00002322',
+ "sharp;": '\U0000266F',
+ "shchcy;": '\U00000449',
+ "shcy;": '\U00000448',
+ "shortmid;": '\U00002223',
+ "shortparallel;": '\U00002225',
+ "shy;": '\U000000AD',
+ "sigma;": '\U000003C3',
+ "sigmaf;": '\U000003C2',
+ "sigmav;": '\U000003C2',
+ "sim;": '\U0000223C',
+ "simdot;": '\U00002A6A',
+ "sime;": '\U00002243',
+ "simeq;": '\U00002243',
+ "simg;": '\U00002A9E',
+ "simgE;": '\U00002AA0',
+ "siml;": '\U00002A9D',
+ "simlE;": '\U00002A9F',
+ "simne;": '\U00002246',
+ "simplus;": '\U00002A24',
+ "simrarr;": '\U00002972',
+ "slarr;": '\U00002190',
+ "smallsetminus;": '\U00002216',
+ "smashp;": '\U00002A33',
+ "smeparsl;": '\U000029E4',
+ "smid;": '\U00002223',
+ "smile;": '\U00002323',
+ "smt;": '\U00002AAA',
+ "smte;": '\U00002AAC',
+ "softcy;": '\U0000044C',
+ "sol;": '\U0000002F',
+ "solb;": '\U000029C4',
+ "solbar;": '\U0000233F',
+ "sopf;": '\U0001D564',
+ "spades;": '\U00002660',
+ "spadesuit;": '\U00002660',
+ "spar;": '\U00002225',
+ "sqcap;": '\U00002293',
+ "sqcup;": '\U00002294',
+ "sqsub;": '\U0000228F',
+ "sqsube;": '\U00002291',
+ "sqsubset;": '\U0000228F',
+ "sqsubseteq;": '\U00002291',
+ "sqsup;": '\U00002290',
+ "sqsupe;": '\U00002292',
+ "sqsupset;": '\U00002290',
+ "sqsupseteq;": '\U00002292',
+ "squ;": '\U000025A1',
+ "square;": '\U000025A1',
+ "squarf;": '\U000025AA',
+ "squf;": '\U000025AA',
+ "srarr;": '\U00002192',
+ "sscr;": '\U0001D4C8',
+ "ssetmn;": '\U00002216',
+ "ssmile;": '\U00002323',
+ "sstarf;": '\U000022C6',
+ "star;": '\U00002606',
+ "starf;": '\U00002605',
+ "straightepsilon;": '\U000003F5',
+ "straightphi;": '\U000003D5',
+ "strns;": '\U000000AF',
+ "sub;": '\U00002282',
+ "subE;": '\U00002AC5',
+ "subdot;": '\U00002ABD',
+ "sube;": '\U00002286',
+ "subedot;": '\U00002AC3',
+ "submult;": '\U00002AC1',
+ "subnE;": '\U00002ACB',
+ "subne;": '\U0000228A',
+ "subplus;": '\U00002ABF',
+ "subrarr;": '\U00002979',
+ "subset;": '\U00002282',
+ "subseteq;": '\U00002286',
+ "subseteqq;": '\U00002AC5',
+ "subsetneq;": '\U0000228A',
+ "subsetneqq;": '\U00002ACB',
+ "subsim;": '\U00002AC7',
+ "subsub;": '\U00002AD5',
+ "subsup;": '\U00002AD3',
+ "succ;": '\U0000227B',
+ "succapprox;": '\U00002AB8',
+ "succcurlyeq;": '\U0000227D',
+ "succeq;": '\U00002AB0',
+ "succnapprox;": '\U00002ABA',
+ "succneqq;": '\U00002AB6',
+ "succnsim;": '\U000022E9',
+ "succsim;": '\U0000227F',
+ "sum;": '\U00002211',
+ "sung;": '\U0000266A',
+ "sup;": '\U00002283',
+ "sup1;": '\U000000B9',
+ "sup2;": '\U000000B2',
+ "sup3;": '\U000000B3',
+ "supE;": '\U00002AC6',
+ "supdot;": '\U00002ABE',
+ "supdsub;": '\U00002AD8',
+ "supe;": '\U00002287',
+ "supedot;": '\U00002AC4',
+ "suphsol;": '\U000027C9',
+ "suphsub;": '\U00002AD7',
+ "suplarr;": '\U0000297B',
+ "supmult;": '\U00002AC2',
+ "supnE;": '\U00002ACC',
+ "supne;": '\U0000228B',
+ "supplus;": '\U00002AC0',
+ "supset;": '\U00002283',
+ "supseteq;": '\U00002287',
+ "supseteqq;": '\U00002AC6',
+ "supsetneq;": '\U0000228B',
+ "supsetneqq;": '\U00002ACC',
+ "supsim;": '\U00002AC8',
+ "supsub;": '\U00002AD4',
+ "supsup;": '\U00002AD6',
+ "swArr;": '\U000021D9',
+ "swarhk;": '\U00002926',
+ "swarr;": '\U00002199',
+ "swarrow;": '\U00002199',
+ "swnwar;": '\U0000292A',
+ "szlig;": '\U000000DF',
+ "target;": '\U00002316',
+ "tau;": '\U000003C4',
+ "tbrk;": '\U000023B4',
+ "tcaron;": '\U00000165',
+ "tcedil;": '\U00000163',
+ "tcy;": '\U00000442',
+ "tdot;": '\U000020DB',
+ "telrec;": '\U00002315',
+ "tfr;": '\U0001D531',
+ "there4;": '\U00002234',
+ "therefore;": '\U00002234',
+ "theta;": '\U000003B8',
+ "thetasym;": '\U000003D1',
+ "thetav;": '\U000003D1',
+ "thickapprox;": '\U00002248',
+ "thicksim;": '\U0000223C',
+ "thinsp;": '\U00002009',
+ "thkap;": '\U00002248',
+ "thksim;": '\U0000223C',
+ "thorn;": '\U000000FE',
+ "tilde;": '\U000002DC',
+ "times;": '\U000000D7',
+ "timesb;": '\U000022A0',
+ "timesbar;": '\U00002A31',
+ "timesd;": '\U00002A30',
+ "tint;": '\U0000222D',
+ "toea;": '\U00002928',
+ "top;": '\U000022A4',
+ "topbot;": '\U00002336',
+ "topcir;": '\U00002AF1',
+ "topf;": '\U0001D565',
+ "topfork;": '\U00002ADA',
+ "tosa;": '\U00002929',
+ "tprime;": '\U00002034',
+ "trade;": '\U00002122',
+ "triangle;": '\U000025B5',
+ "triangledown;": '\U000025BF',
+ "triangleleft;": '\U000025C3',
+ "trianglelefteq;": '\U000022B4',
+ "triangleq;": '\U0000225C',
+ "triangleright;": '\U000025B9',
+ "trianglerighteq;": '\U000022B5',
+ "tridot;": '\U000025EC',
+ "trie;": '\U0000225C',
+ "triminus;": '\U00002A3A',
+ "triplus;": '\U00002A39',
+ "trisb;": '\U000029CD',
+ "tritime;": '\U00002A3B',
+ "trpezium;": '\U000023E2',
+ "tscr;": '\U0001D4C9',
+ "tscy;": '\U00000446',
+ "tshcy;": '\U0000045B',
+ "tstrok;": '\U00000167',
+ "twixt;": '\U0000226C',
+ "twoheadleftarrow;": '\U0000219E',
+ "twoheadrightarrow;": '\U000021A0',
+ "uArr;": '\U000021D1',
+ "uHar;": '\U00002963',
+ "uacute;": '\U000000FA',
+ "uarr;": '\U00002191',
+ "ubrcy;": '\U0000045E',
+ "ubreve;": '\U0000016D',
+ "ucirc;": '\U000000FB',
+ "ucy;": '\U00000443',
+ "udarr;": '\U000021C5',
+ "udblac;": '\U00000171',
+ "udhar;": '\U0000296E',
+ "ufisht;": '\U0000297E',
+ "ufr;": '\U0001D532',
+ "ugrave;": '\U000000F9',
+ "uharl;": '\U000021BF',
+ "uharr;": '\U000021BE',
+ "uhblk;": '\U00002580',
+ "ulcorn;": '\U0000231C',
+ "ulcorner;": '\U0000231C',
+ "ulcrop;": '\U0000230F',
+ "ultri;": '\U000025F8',
+ "umacr;": '\U0000016B',
+ "uml;": '\U000000A8',
+ "uogon;": '\U00000173',
+ "uopf;": '\U0001D566',
+ "uparrow;": '\U00002191',
+ "updownarrow;": '\U00002195',
+ "upharpoonleft;": '\U000021BF',
+ "upharpoonright;": '\U000021BE',
+ "uplus;": '\U0000228E',
+ "upsi;": '\U000003C5',
+ "upsih;": '\U000003D2',
+ "upsilon;": '\U000003C5',
+ "upuparrows;": '\U000021C8',
+ "urcorn;": '\U0000231D',
+ "urcorner;": '\U0000231D',
+ "urcrop;": '\U0000230E',
+ "uring;": '\U0000016F',
+ "urtri;": '\U000025F9',
+ "uscr;": '\U0001D4CA',
+ "utdot;": '\U000022F0',
+ "utilde;": '\U00000169',
+ "utri;": '\U000025B5',
+ "utrif;": '\U000025B4',
+ "uuarr;": '\U000021C8',
+ "uuml;": '\U000000FC',
+ "uwangle;": '\U000029A7',
+ "vArr;": '\U000021D5',
+ "vBar;": '\U00002AE8',
+ "vBarv;": '\U00002AE9',
+ "vDash;": '\U000022A8',
+ "vangrt;": '\U0000299C',
+ "varepsilon;": '\U000003F5',
+ "varkappa;": '\U000003F0',
+ "varnothing;": '\U00002205',
+ "varphi;": '\U000003D5',
+ "varpi;": '\U000003D6',
+ "varpropto;": '\U0000221D',
+ "varr;": '\U00002195',
+ "varrho;": '\U000003F1',
+ "varsigma;": '\U000003C2',
+ "vartheta;": '\U000003D1',
+ "vartriangleleft;": '\U000022B2',
+ "vartriangleright;": '\U000022B3',
+ "vcy;": '\U00000432',
+ "vdash;": '\U000022A2',
+ "vee;": '\U00002228',
+ "veebar;": '\U000022BB',
+ "veeeq;": '\U0000225A',
+ "vellip;": '\U000022EE',
+ "verbar;": '\U0000007C',
+ "vert;": '\U0000007C',
+ "vfr;": '\U0001D533',
+ "vltri;": '\U000022B2',
+ "vopf;": '\U0001D567',
+ "vprop;": '\U0000221D',
+ "vrtri;": '\U000022B3',
+ "vscr;": '\U0001D4CB',
+ "vzigzag;": '\U0000299A',
+ "wcirc;": '\U00000175',
+ "wedbar;": '\U00002A5F',
+ "wedge;": '\U00002227',
+ "wedgeq;": '\U00002259',
+ "weierp;": '\U00002118',
+ "wfr;": '\U0001D534',
+ "wopf;": '\U0001D568',
+ "wp;": '\U00002118',
+ "wr;": '\U00002240',
+ "wreath;": '\U00002240',
+ "wscr;": '\U0001D4CC',
+ "xcap;": '\U000022C2',
+ "xcirc;": '\U000025EF',
+ "xcup;": '\U000022C3',
+ "xdtri;": '\U000025BD',
+ "xfr;": '\U0001D535',
+ "xhArr;": '\U000027FA',
+ "xharr;": '\U000027F7',
+ "xi;": '\U000003BE',
+ "xlArr;": '\U000027F8',
+ "xlarr;": '\U000027F5',
+ "xmap;": '\U000027FC',
+ "xnis;": '\U000022FB',
+ "xodot;": '\U00002A00',
+ "xopf;": '\U0001D569',
+ "xoplus;": '\U00002A01',
+ "xotime;": '\U00002A02',
+ "xrArr;": '\U000027F9',
+ "xrarr;": '\U000027F6',
+ "xscr;": '\U0001D4CD',
+ "xsqcup;": '\U00002A06',
+ "xuplus;": '\U00002A04',
+ "xutri;": '\U000025B3',
+ "xvee;": '\U000022C1',
+ "xwedge;": '\U000022C0',
+ "yacute;": '\U000000FD',
+ "yacy;": '\U0000044F',
+ "ycirc;": '\U00000177',
+ "ycy;": '\U0000044B',
+ "yen;": '\U000000A5',
+ "yfr;": '\U0001D536',
+ "yicy;": '\U00000457',
+ "yopf;": '\U0001D56A',
+ "yscr;": '\U0001D4CE',
+ "yucy;": '\U0000044E',
+ "yuml;": '\U000000FF',
+ "zacute;": '\U0000017A',
+ "zcaron;": '\U0000017E',
+ "zcy;": '\U00000437',
+ "zdot;": '\U0000017C',
+ "zeetrf;": '\U00002128',
+ "zeta;": '\U000003B6',
+ "zfr;": '\U0001D537',
+ "zhcy;": '\U00000436',
+ "zigrarr;": '\U000021DD',
+ "zopf;": '\U0001D56B',
+ "zscr;": '\U0001D4CF',
+ "zwj;": '\U0000200D',
+ "zwnj;": '\U0000200C',
+ "AElig": '\U000000C6',
+ "AMP": '\U00000026',
+ "Aacute": '\U000000C1',
+ "Acirc": '\U000000C2',
+ "Agrave": '\U000000C0',
+ "Aring": '\U000000C5',
+ "Atilde": '\U000000C3',
+ "Auml": '\U000000C4',
+ "COPY": '\U000000A9',
+ "Ccedil": '\U000000C7',
+ "ETH": '\U000000D0',
+ "Eacute": '\U000000C9',
+ "Ecirc": '\U000000CA',
+ "Egrave": '\U000000C8',
+ "Euml": '\U000000CB',
+ "GT": '\U0000003E',
+ "Iacute": '\U000000CD',
+ "Icirc": '\U000000CE',
+ "Igrave": '\U000000CC',
+ "Iuml": '\U000000CF',
+ "LT": '\U0000003C',
+ "Ntilde": '\U000000D1',
+ "Oacute": '\U000000D3',
+ "Ocirc": '\U000000D4',
+ "Ograve": '\U000000D2',
+ "Oslash": '\U000000D8',
+ "Otilde": '\U000000D5',
+ "Ouml": '\U000000D6',
+ "QUOT": '\U00000022',
+ "REG": '\U000000AE',
+ "THORN": '\U000000DE',
+ "Uacute": '\U000000DA',
+ "Ucirc": '\U000000DB',
+ "Ugrave": '\U000000D9',
+ "Uuml": '\U000000DC',
+ "Yacute": '\U000000DD',
+ "aacute": '\U000000E1',
+ "acirc": '\U000000E2',
+ "acute": '\U000000B4',
+ "aelig": '\U000000E6',
+ "agrave": '\U000000E0',
+ "amp": '\U00000026',
+ "aring": '\U000000E5',
+ "atilde": '\U000000E3',
+ "auml": '\U000000E4',
+ "brvbar": '\U000000A6',
+ "ccedil": '\U000000E7',
+ "cedil": '\U000000B8',
+ "cent": '\U000000A2',
+ "copy": '\U000000A9',
+ "curren": '\U000000A4',
+ "deg": '\U000000B0',
+ "divide": '\U000000F7',
+ "eacute": '\U000000E9',
+ "ecirc": '\U000000EA',
+ "egrave": '\U000000E8',
+ "eth": '\U000000F0',
+ "euml": '\U000000EB',
+ "frac12": '\U000000BD',
+ "frac14": '\U000000BC',
+ "frac34": '\U000000BE',
+ "gt": '\U0000003E',
+ "iacute": '\U000000ED',
+ "icirc": '\U000000EE',
+ "iexcl": '\U000000A1',
+ "igrave": '\U000000EC',
+ "iquest": '\U000000BF',
+ "iuml": '\U000000EF',
+ "laquo": '\U000000AB',
+ "lt": '\U0000003C',
+ "macr": '\U000000AF',
+ "micro": '\U000000B5',
+ "middot": '\U000000B7',
+ "nbsp": '\U000000A0',
+ "not": '\U000000AC',
+ "ntilde": '\U000000F1',
+ "oacute": '\U000000F3',
+ "ocirc": '\U000000F4',
+ "ograve": '\U000000F2',
+ "ordf": '\U000000AA',
+ "ordm": '\U000000BA',
+ "oslash": '\U000000F8',
+ "otilde": '\U000000F5',
+ "ouml": '\U000000F6',
+ "para": '\U000000B6',
+ "plusmn": '\U000000B1',
+ "pound": '\U000000A3',
+ "quot": '\U00000022',
+ "raquo": '\U000000BB',
+ "reg": '\U000000AE',
+ "sect": '\U000000A7',
+ "shy": '\U000000AD',
+ "sup1": '\U000000B9',
+ "sup2": '\U000000B2',
+ "sup3": '\U000000B3',
+ "szlig": '\U000000DF',
+ "thorn": '\U000000FE',
+ "times": '\U000000D7',
+ "uacute": '\U000000FA',
+ "ucirc": '\U000000FB',
+ "ugrave": '\U000000F9',
+ "uml": '\U000000A8',
+ "uuml": '\U000000FC',
+ "yacute": '\U000000FD',
+ "yen": '\U000000A5',
+ "yuml": '\U000000FF',
}
// HTML entities that are two unicode codepoints.
diff --git a/libgo/go/html/template/escape.go b/libgo/go/html/template/escape.go
index 5f0e28e8c1c..ce11dedf6b9 100644
--- a/libgo/go/html/template/escape.go
+++ b/libgo/go/html/template/escape.go
@@ -242,10 +242,11 @@ func ensurePipelineContains(p *parse.PipeNode, s []string) {
copy(newCmds, p.Cmds)
// Merge existing identifier commands with the sanitizers needed.
for _, id := range idents {
+ pos := id.Args[0].Position()
i := indexOfStr((id.Args[0].(*parse.IdentifierNode)).Ident, s, escFnsEq)
if i != -1 {
for _, name := range s[:i] {
- newCmds = appendCmd(newCmds, newIdentCmd(name))
+ newCmds = appendCmd(newCmds, newIdentCmd(name, pos))
}
s = s[i+1:]
}
@@ -253,7 +254,7 @@ func ensurePipelineContains(p *parse.PipeNode, s []string) {
}
// Create any remaining sanitizers.
for _, name := range s {
- newCmds = appendCmd(newCmds, newIdentCmd(name))
+ newCmds = appendCmd(newCmds, newIdentCmd(name, p.Position()))
}
p.Cmds = newCmds
}
@@ -315,10 +316,10 @@ func escFnsEq(a, b string) bool {
}
// newIdentCmd produces a command containing a single identifier node.
-func newIdentCmd(identifier string) *parse.CommandNode {
+func newIdentCmd(identifier string, pos parse.Pos) *parse.CommandNode {
return &parse.CommandNode{
NodeType: parse.NodeCommand,
- Args: []parse.Node{parse.NewIdentifier(identifier)},
+ Args: []parse.Node{parse.NewIdentifier(identifier).SetPos(pos)},
}
}
diff --git a/libgo/go/html/template/escape_test.go b/libgo/go/html/template/escape_test.go
index ce12c1795c2..0d08101ecff 100644
--- a/libgo/go/html/template/escape_test.go
+++ b/libgo/go/html/template/escape_test.go
@@ -1539,6 +1539,11 @@ func TestEnsurePipelineContains(t *testing.T) {
".X | urlquery | html | print",
[]string{"urlquery", "html"},
},
+ {
+ "{{($).X | html | print}}",
+ "($).X | urlquery | html | print",
+ []string{"urlquery", "html"},
+ },
}
for i, test := range tests {
tmpl := template.Must(template.New("test").Parse(test.input))
diff --git a/libgo/go/image/jpeg/dct_test.go b/libgo/go/image/jpeg/dct_test.go
new file mode 100644
index 00000000000..770e274bac0
--- /dev/null
+++ b/libgo/go/image/jpeg/dct_test.go
@@ -0,0 +1,291 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jpeg
+
+import (
+ "bytes"
+ "fmt"
+ "math"
+ "math/rand"
+ "testing"
+)
+
+func benchmarkDCT(b *testing.B, f func(*block)) {
+ b.StopTimer()
+ blocks := make([]block, 0, b.N*len(testBlocks))
+ for i := 0; i < b.N; i++ {
+ blocks = append(blocks, testBlocks[:]...)
+ }
+ b.StartTimer()
+ for i := range blocks {
+ f(&blocks[i])
+ }
+}
+
+func BenchmarkFDCT(b *testing.B) {
+ benchmarkDCT(b, fdct)
+}
+
+func BenchmarkIDCT(b *testing.B) {
+ benchmarkDCT(b, idct)
+}
+
+func TestDCT(t *testing.T) {
+ blocks := make([]block, len(testBlocks))
+ copy(blocks, testBlocks[:])
+
+ // Append some randomly generated blocks of varying sparseness.
+ r := rand.New(rand.NewSource(123))
+ for i := 0; i < 100; i++ {
+ b := block{}
+ n := r.Int() % 64
+ for j := 0; j < n; j++ {
+ b[r.Int()%len(b)] = r.Int() % 256
+ }
+ blocks = append(blocks, b)
+ }
+
+ // Check that the FDCT and IDCT functions are inverses, after a scale and
+ // level shift. Scaling reduces the rounding errors in the conversion from
+ // floats to ints.
+ for i, b := range blocks {
+ got, want := b, b
+ for j := range got {
+ got[j] = (got[j] - 128) * 8
+ }
+ slowFDCT(&got)
+ slowIDCT(&got)
+ for j := range got {
+ got[j] = got[j]/8 + 128
+ }
+ if differ(&got, &want) {
+ t.Errorf("i=%d: IDCT(FDCT)\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
+ }
+ }
+
+ // Check that the optimized and slow FDCT implementations agree.
+ // The fdct function already does a scale and level shift.
+ for i, b := range blocks {
+ got, want := b, b
+ fdct(&got)
+ for j := range want {
+ want[j] = (want[j] - 128) * 8
+ }
+ slowFDCT(&want)
+ if differ(&got, &want) {
+ t.Errorf("i=%d: FDCT\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
+ }
+ }
+
+ // Check that the optimized and slow IDCT implementations agree.
+ for i, b := range blocks {
+ got, want := b, b
+ idct(&got)
+ slowIDCT(&want)
+ if differ(&got, &want) {
+ t.Errorf("i=%d: IDCT\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
+ }
+ }
+}
+
+// differ returns whether any pair-wise elements in b0 and b1 differ by 2 or
+// more. That tolerance is because there isn't a single definitive decoding of
+// a given JPEG image, even before the YCbCr to RGB conversion; implementations
+// can have different IDCT rounding errors.
+func differ(b0, b1 *block) bool {
+ for i := range b0 {
+ delta := b0[i] - b1[i]
+ if delta < -2 || +2 < delta {
+ return true
+ }
+ }
+ return false
+}
+
+// alpha returns 1 if i is 0 and returns √2 otherwise.
+func alpha(i int) float64 {
+ if i == 0 {
+ return 1
+ }
+ return math.Sqrt2
+}
+
+// slowFDCT performs the 8*8 2-dimensional forward discrete cosine transform:
+//
+// dst[u,v] = (1/8) * Σ_x Σ_y alpha(u) * alpha(v) * src[x,y] *
+// cos((π/2) * (2*x + 1) * u / 8) *
+// cos((π/2) * (2*y + 1) * v / 8)
+//
+// x and y are in pixel space, and u and v are in transform space.
+//
+// b acts as both dst and src.
+func slowFDCT(b *block) {
+ var dst [blockSize]float64
+ for v := 0; v < 8; v++ {
+ for u := 0; u < 8; u++ {
+ sum := 0.0
+ for y := 0; y < 8; y++ {
+ for x := 0; x < 8; x++ {
+ sum += alpha(u) * alpha(v) * float64(b[8*y+x]) *
+ math.Cos(math.Pi*float64((2*x+1)*u)/16) *
+ math.Cos(math.Pi*float64((2*y+1)*v)/16)
+ }
+ }
+ dst[8*v+u] = sum / 8
+ }
+ }
+ // Convert from float64 to int.
+ for i := range dst {
+ b[i] = int(dst[i] + 0.5)
+ }
+}
+
+// slowIDCT performs the 8*8 2-dimensional inverse discrete cosine transform:
+//
+// dst[x,y] = (1/8) * Σ_u Σ_v alpha(u) * alpha(v) * src[u,v] *
+// cos((π/2) * (2*x + 1) * u / 8) *
+// cos((π/2) * (2*y + 1) * v / 8)
+//
+// x and y are in pixel space, and u and v are in transform space.
+//
+// b acts as both dst and src.
+func slowIDCT(b *block) {
+ var dst [blockSize]float64
+ for y := 0; y < 8; y++ {
+ for x := 0; x < 8; x++ {
+ sum := 0.0
+ for v := 0; v < 8; v++ {
+ for u := 0; u < 8; u++ {
+ sum += alpha(u) * alpha(v) * float64(b[8*v+u]) *
+ math.Cos(math.Pi*float64((2*x+1)*u)/16) *
+ math.Cos(math.Pi*float64((2*y+1)*v)/16)
+ }
+ }
+ dst[8*y+x] = sum / 8
+ }
+ }
+ // Convert from float64 to int.
+ for i := range dst {
+ b[i] = int(dst[i] + 0.5)
+ }
+}
+
+func (b *block) String() string {
+ s := bytes.NewBuffer(nil)
+ fmt.Fprintf(s, "{\n")
+ for y := 0; y < 8; y++ {
+ fmt.Fprintf(s, "\t")
+ for x := 0; x < 8; x++ {
+ fmt.Fprintf(s, "0x%04x, ", uint16(b[8*y+x]))
+ }
+ fmt.Fprintln(s)
+ }
+ fmt.Fprintf(s, "}")
+ return s.String()
+}
+
+// testBlocks are the first 10 pre-IDCT blocks from ../testdata/video-001.jpeg.
+var testBlocks = [10]block{
+ {
+ 0x7f, 0xf6, 0x01, 0x07, 0xff, 0x00, 0x00, 0x00,
+ 0xf5, 0x01, 0xfa, 0x01, 0xfe, 0x00, 0x01, 0x00,
+ 0x05, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0xff, 0xf8, 0x00, 0x01, 0xff, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00,
+ 0xff, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x01, 0xff, 0x01, 0x00, 0xfe,
+ },
+ {
+ 0x29, 0x07, 0x00, 0xfc, 0x01, 0x01, 0x00, 0x00,
+ 0x07, 0x00, 0x03, 0x00, 0x01, 0x00, 0xff, 0xff,
+ 0xff, 0xfd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0xff, 0x01, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0xfa, 0x01, 0x00, 0x01, 0x00, 0x01, 0xff,
+ 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x02,
+ },
+ {
+ 0xc5, 0xfa, 0x01, 0x00, 0x00, 0x01, 0x00, 0xff,
+ 0x02, 0xff, 0x01, 0x00, 0x01, 0x00, 0xff, 0x00,
+ 0xff, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x86, 0x05, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00,
+ 0xf2, 0x06, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
+ 0xf6, 0xfa, 0xf9, 0x00, 0xff, 0x01, 0x00, 0x00,
+ 0xf9, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x01, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00,
+ },
+ {
+ 0x24, 0xfe, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
+ 0x08, 0xfd, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00,
+ 0x06, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0xff, 0x00, 0x01, 0x00, 0x00,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x01,
+ },
+ {
+ 0xcd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff,
+ },
+ {
+ 0x81, 0xfe, 0x05, 0xff, 0x01, 0xff, 0x01, 0x00,
+ 0xef, 0xf9, 0x00, 0xf9, 0x00, 0xff, 0x00, 0xff,
+ 0x05, 0xf9, 0x00, 0xf8, 0x01, 0xff, 0x01, 0xff,
+ 0x00, 0xff, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01,
+ 0xff, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
+ },
+ {
+ 0x28, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0b, 0x02, 0x01, 0x03, 0x00, 0xff, 0x00, 0x01,
+ 0xfe, 0x02, 0x01, 0x03, 0xff, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0xfd, 0x00, 0x01, 0x00, 0xff, 0x00,
+ 0x01, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x00, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01,
+ },
+ {
+ 0xdf, 0xf9, 0xfe, 0x00, 0x03, 0x01, 0xff, 0xff,
+ 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x01,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ },
+ {
+ 0x88, 0xfd, 0x00, 0x00, 0xff, 0x00, 0x01, 0xff,
+ 0xe1, 0x06, 0x06, 0x01, 0xff, 0x00, 0x01, 0x00,
+ 0x08, 0x00, 0xfa, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x08, 0x01, 0x00, 0xff, 0x01, 0xff, 0x00, 0x00,
+ 0xf5, 0xff, 0x00, 0x01, 0xff, 0x01, 0x01, 0x00,
+ 0xff, 0xff, 0x01, 0xff, 0x01, 0x00, 0x01, 0x00,
+ 0x00, 0x01, 0x01, 0xff, 0x00, 0xff, 0x00, 0x01,
+ 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
+ },
+}
diff --git a/libgo/go/image/jpeg/idct.go b/libgo/go/image/jpeg/idct.go
index b387dfdffd1..92ff1e4b41d 100644
--- a/libgo/go/image/jpeg/idct.go
+++ b/libgo/go/image/jpeg/idct.go
@@ -37,6 +37,10 @@ package jpeg
*
*/
+const blockSize = 64 // A DCT block is 8x8.
+
+type block [blockSize]int
+
const (
w1 = 2841 // 2048*sqrt(2)*cos(1*pi/16)
w2 = 2676 // 2048*sqrt(2)*cos(2*pi/16)
@@ -55,9 +59,7 @@ const (
r2 = 181 // 256/sqrt(2)
)
-// idct performs a 2-D Inverse Discrete Cosine Transformation, followed by a
-// +128 level shift and a clip to [0, 255], writing the results to dst.
-// stride is the number of elements between successive rows of dst.
+// idct performs a 2-D Inverse Discrete Cosine Transformation.
//
// The input coefficients should already have been multiplied by the
// appropriate quantization table. We use fixed-point computation, with the
@@ -67,33 +69,34 @@ const (
// For more on the actual algorithm, see Z. Wang, "Fast algorithms for the
// discrete W transform and for the discrete Fourier transform", IEEE Trans. on
// ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984.
-func idct(dst []byte, stride int, src *block) {
+func idct(src *block) {
// Horizontal 1-D IDCT.
for y := 0; y < 8; y++ {
+ y8 := y * 8
// If all the AC components are zero, then the IDCT is trivial.
- if src[y*8+1] == 0 && src[y*8+2] == 0 && src[y*8+3] == 0 &&
- src[y*8+4] == 0 && src[y*8+5] == 0 && src[y*8+6] == 0 && src[y*8+7] == 0 {
- dc := src[y*8+0] << 3
- src[y*8+0] = dc
- src[y*8+1] = dc
- src[y*8+2] = dc
- src[y*8+3] = dc
- src[y*8+4] = dc
- src[y*8+5] = dc
- src[y*8+6] = dc
- src[y*8+7] = dc
+ if src[y8+1] == 0 && src[y8+2] == 0 && src[y8+3] == 0 &&
+ src[y8+4] == 0 && src[y8+5] == 0 && src[y8+6] == 0 && src[y8+7] == 0 {
+ dc := src[y8+0] << 3
+ src[y8+0] = dc
+ src[y8+1] = dc
+ src[y8+2] = dc
+ src[y8+3] = dc
+ src[y8+4] = dc
+ src[y8+5] = dc
+ src[y8+6] = dc
+ src[y8+7] = dc
continue
}
// Prescale.
- x0 := (src[y*8+0] << 11) + 128
- x1 := src[y*8+4] << 11
- x2 := src[y*8+6]
- x3 := src[y*8+2]
- x4 := src[y*8+1]
- x5 := src[y*8+7]
- x6 := src[y*8+5]
- x7 := src[y*8+3]
+ x0 := (src[y8+0] << 11) + 128
+ x1 := src[y8+4] << 11
+ x2 := src[y8+6]
+ x3 := src[y8+2]
+ x4 := src[y8+1]
+ x5 := src[y8+7]
+ x6 := src[y8+5]
+ x7 := src[y8+3]
// Stage 1.
x8 := w7 * (x4 + x5)
@@ -123,14 +126,14 @@ func idct(dst []byte, stride int, src *block) {
x4 = (r2*(x4-x5) + 128) >> 8
// Stage 4.
- src[8*y+0] = (x7 + x1) >> 8
- src[8*y+1] = (x3 + x2) >> 8
- src[8*y+2] = (x0 + x4) >> 8
- src[8*y+3] = (x8 + x6) >> 8
- src[8*y+4] = (x8 - x6) >> 8
- src[8*y+5] = (x0 - x4) >> 8
- src[8*y+6] = (x3 - x2) >> 8
- src[8*y+7] = (x7 - x1) >> 8
+ src[y8+0] = (x7 + x1) >> 8
+ src[y8+1] = (x3 + x2) >> 8
+ src[y8+2] = (x0 + x4) >> 8
+ src[y8+3] = (x8 + x6) >> 8
+ src[y8+4] = (x8 - x6) >> 8
+ src[y8+5] = (x0 - x4) >> 8
+ src[y8+6] = (x3 - x2) >> 8
+ src[y8+7] = (x7 - x1) >> 8
}
// Vertical 1-D IDCT.
@@ -186,19 +189,4 @@ func idct(dst []byte, stride int, src *block) {
src[8*6+x] = (y3 - y2) >> 14
src[8*7+x] = (y7 - y1) >> 14
}
-
- // Level shift by +128, clip to [0, 255], and write to dst.
- for y := 0; y < 8; y++ {
- for x := 0; x < 8; x++ {
- c := src[y*8+x]
- if c < -128 {
- c = 0
- } else if c > 127 {
- c = 255
- } else {
- c += 128
- }
- dst[y*stride+x] = uint8(c)
- }
- }
}
diff --git a/libgo/go/image/jpeg/reader.go b/libgo/go/image/jpeg/reader.go
index 8da3611919e..415b093281d 100644
--- a/libgo/go/image/jpeg/reader.go
+++ b/libgo/go/image/jpeg/reader.go
@@ -35,11 +35,7 @@ type component struct {
tq uint8 // Quantization table destination selector.
}
-type block [blockSize]int
-
const (
- blockSize = 64 // A DCT block is 8x8.
-
dcTable = 0
acTable = 1
maxTc = 1
@@ -51,7 +47,7 @@ const (
// A color JPEG image has Y, Cb and Cr components.
nColorComponent = 3
- // We only support 4:4:4, 4:2:2 and 4:2:0 downsampling, and therefore the
+ // We only support 4:4:4, 4:4:0, 4:2:2 and 4:2:0 downsampling, and therefore the
// number of luma samples per chroma sample is at most 2 in the horizontal
// and 2 in the vertical direction.
maxH = 2
@@ -96,6 +92,7 @@ type Reader interface {
type decoder struct {
r Reader
+ b bits
width, height int
img1 *image.Gray
img3 *image.YCbCr
@@ -104,7 +101,6 @@ type decoder struct {
comp [nColorComponent]component
huff [maxTc + 1][maxTh + 1]huffman
quant [maxTq + 1]block // Quantization tables, in zig-zag order.
- b bits
tmp [1024]byte
}
@@ -156,12 +152,12 @@ func (d *decoder) processSOF(n int) error {
if d.nComp == nGrayComponent {
continue
}
- // For color images, we only support 4:4:4, 4:2:2 or 4:2:0 chroma
+ // For color images, we only support 4:4:4, 4:4:0, 4:2:2 or 4:2:0 chroma
// downsampling ratios. This implies that the (h, v) values for the Y
- // component are either (1, 1), (2, 1) or (2, 2), and the (h, v)
+ // component are either (1, 1), (1, 2), (2, 1) or (2, 2), and the (h, v)
// values for the Cr and Cb components must be (1, 1).
if i == 0 {
- if hv != 0x11 && hv != 0x21 && hv != 0x22 {
+ if hv != 0x11 && hv != 0x21 && hv != 0x22 && hv != 0x12 {
return UnsupportedError("luma downsample ratio")
}
} else if hv != 0x11 {
@@ -205,12 +201,14 @@ func (d *decoder) makeImg(h0, v0, mxx, myy int) {
return
}
var subsampleRatio image.YCbCrSubsampleRatio
- switch h0 * v0 {
- case 1:
+ switch {
+ case h0 == 1 && v0 == 1:
subsampleRatio = image.YCbCrSubsampleRatio444
- case 2:
+ case h0 == 1 && v0 == 2:
+ subsampleRatio = image.YCbCrSubsampleRatio440
+ case h0 == 2 && v0 == 1:
subsampleRatio = image.YCbCrSubsampleRatio422
- case 4:
+ case h0 == 2 && v0 == 2:
subsampleRatio = image.YCbCrSubsampleRatio420
default:
panic("unreachable")
@@ -311,18 +309,41 @@ func (d *decoder) processSOS(n int) error {
}
// Perform the inverse DCT and store the MCU component to the image.
+ idct(&b)
+ dst, stride := []byte(nil), 0
if d.nComp == nGrayComponent {
- idct(d.img1.Pix[8*(my*d.img1.Stride+mx):], d.img1.Stride, &b)
+ dst, stride = d.img1.Pix[8*(my*d.img1.Stride+mx):], d.img1.Stride
} else {
switch i {
case 0:
- mx0 := h0*mx + (j % 2)
- my0 := v0*my + (j / 2)
- idct(d.img3.Y[8*(my0*d.img3.YStride+mx0):], d.img3.YStride, &b)
+ mx0, my0 := h0*mx, v0*my
+ if h0 == 1 {
+ my0 += j
+ } else {
+ mx0 += j % 2
+ my0 += j / 2
+ }
+ dst, stride = d.img3.Y[8*(my0*d.img3.YStride+mx0):], d.img3.YStride
case 1:
- idct(d.img3.Cb[8*(my*d.img3.CStride+mx):], d.img3.CStride, &b)
+ dst, stride = d.img3.Cb[8*(my*d.img3.CStride+mx):], d.img3.CStride
case 2:
- idct(d.img3.Cr[8*(my*d.img3.CStride+mx):], d.img3.CStride, &b)
+ dst, stride = d.img3.Cr[8*(my*d.img3.CStride+mx):], d.img3.CStride
+ }
+ }
+ // Level shift by +128, clip to [0, 255], and write to dst.
+ for y := 0; y < 8; y++ {
+ y8 := y * 8
+ yStride := y * stride
+ for x := 0; x < 8; x++ {
+ c := b[y8+x]
+ if c < -128 {
+ c = 0
+ } else if c > 127 {
+ c = 255
+ } else {
+ c += 128
+ }
+ dst[yStride+x] = uint8(c)
}
}
} // for j
diff --git a/libgo/go/image/jpeg/writer_test.go b/libgo/go/image/jpeg/writer_test.go
index 8732df8459a..90b89a7b0f1 100644
--- a/libgo/go/image/jpeg/writer_test.go
+++ b/libgo/go/image/jpeg/writer_test.go
@@ -171,24 +171,38 @@ func TestWriter(t *testing.T) {
}
}
-func BenchmarkEncodeRGBOpaque(b *testing.B) {
+func BenchmarkDecode(b *testing.B) {
+ b.StopTimer()
+ data, err := ioutil.ReadFile("../testdata/video-001.jpeg")
+ if err != nil {
+ b.Fatal(err)
+ }
+ cfg, err := DecodeConfig(bytes.NewReader(data))
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.SetBytes(int64(cfg.Width * cfg.Height * 4))
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ Decode(bytes.NewReader(data))
+ }
+}
+
+func BenchmarkEncode(b *testing.B) {
b.StopTimer()
img := image.NewRGBA(image.Rect(0, 0, 640, 480))
- // Set all pixels to 0xFF alpha to force opaque mode.
bo := img.Bounds()
rnd := rand.New(rand.NewSource(123))
for y := bo.Min.Y; y < bo.Max.Y; y++ {
for x := bo.Min.X; x < bo.Max.X; x++ {
- img.Set(x, y, color.RGBA{
+ img.SetRGBA(x, y, color.RGBA{
uint8(rnd.Intn(256)),
uint8(rnd.Intn(256)),
uint8(rnd.Intn(256)),
- 255})
+ 255,
+ })
}
}
- if !img.Opaque() {
- b.Fatal("expected image to be opaque")
- }
b.SetBytes(640 * 480 * 4)
b.StartTimer()
options := &Options{Quality: 90}
diff --git a/libgo/go/image/png/paeth.go b/libgo/go/image/png/paeth.go
new file mode 100644
index 00000000000..37978aa662d
--- /dev/null
+++ b/libgo/go/image/png/paeth.go
@@ -0,0 +1,70 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package png
+
+// paeth implements the Paeth filter function, as per the PNG specification.
+func paeth(a, b, c uint8) uint8 {
+ // This is an optimized version of the sample code in the PNG spec.
+ // For example, the sample code starts with:
+ // p := int(a) + int(b) - int(c)
+ // pa := abs(p - int(a))
+ // but the optimized form uses fewer arithmetic operations:
+ // pa := int(b) - int(c)
+ // pa = abs(pa)
+ pc := int(c)
+ pa := int(b) - pc
+ pb := int(a) - pc
+ pc = pa + pb
+ if pa < 0 {
+ pa = -pa
+ }
+ if pb < 0 {
+ pb = -pb
+ }
+ if pc < 0 {
+ pc = -pc
+ }
+ if pa <= pb && pa <= pc {
+ return a
+ } else if pb <= pc {
+ return b
+ }
+ return c
+}
+
+// filterPaeth applies the Paeth filter to the cdat slice.
+// cdat is the current row's data, pdat is the previous row's data.
+func filterPaeth(cdat, pdat []byte, bytesPerPixel int) {
+ var a, b, c, pa, pb, pc int
+ for i := 0; i < bytesPerPixel; i++ {
+ a, c = 0, 0
+ for j := i; j < len(cdat); j += bytesPerPixel {
+ b = int(pdat[j])
+ pa = b - c
+ pb = a - c
+ pc = pa + pb
+ if pa < 0 {
+ pa = -pa
+ }
+ if pb < 0 {
+ pb = -pb
+ }
+ if pc < 0 {
+ pc = -pc
+ }
+ if pa <= pb && pa <= pc {
+ // No-op.
+ } else if pb <= pc {
+ a = b
+ } else {
+ a = c
+ }
+ a += int(cdat[j])
+ a &= 0xff
+ cdat[j] = uint8(a)
+ c = b
+ }
+ }
+}
diff --git a/libgo/go/image/png/paeth_test.go b/libgo/go/image/png/paeth_test.go
new file mode 100644
index 00000000000..bb084861ae9
--- /dev/null
+++ b/libgo/go/image/png/paeth_test.go
@@ -0,0 +1,91 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package png
+
+import (
+ "bytes"
+ "math/rand"
+ "testing"
+)
+
+func abs(x int) int {
+ if x < 0 {
+ return -x
+ }
+ return x
+}
+
+// slowPaeth is a slow but simple implementation of the Paeth function.
+// It is a straight port of the sample code in the PNG spec, section 9.4.
+func slowPaeth(a, b, c uint8) uint8 {
+ p := int(a) + int(b) - int(c)
+ pa := abs(p - int(a))
+ pb := abs(p - int(b))
+ pc := abs(p - int(c))
+ if pa <= pb && pa <= pc {
+ return a
+ } else if pb <= pc {
+ return b
+ }
+ return c
+}
+
+// slowFilterPaeth is a slow but simple implementation of func filterPaeth.
+func slowFilterPaeth(cdat, pdat []byte, bytesPerPixel int) {
+ for i := 0; i < bytesPerPixel; i++ {
+ cdat[i] += paeth(0, pdat[i], 0)
+ }
+ for i := bytesPerPixel; i < len(cdat); i++ {
+ cdat[i] += paeth(cdat[i-bytesPerPixel], pdat[i], pdat[i-bytesPerPixel])
+ }
+}
+
+func TestPaeth(t *testing.T) {
+ for a := 0; a < 256; a += 15 {
+ for b := 0; b < 256; b += 15 {
+ for c := 0; c < 256; c += 15 {
+ got := paeth(uint8(a), uint8(b), uint8(c))
+ want := slowPaeth(uint8(a), uint8(b), uint8(c))
+ if got != want {
+ t.Errorf("a, b, c = %d, %d, %d: got %d, want %d", a, b, c, got, want)
+ }
+ }
+ }
+ }
+}
+
+func BenchmarkPaeth(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ paeth(uint8(i>>16), uint8(i>>8), uint8(i))
+ }
+}
+
+func TestPaethDecode(t *testing.T) {
+ pdat0 := make([]byte, 32)
+ pdat1 := make([]byte, 32)
+ pdat2 := make([]byte, 32)
+ cdat0 := make([]byte, 32)
+ cdat1 := make([]byte, 32)
+ cdat2 := make([]byte, 32)
+ r := rand.New(rand.NewSource(1))
+ for bytesPerPixel := 1; bytesPerPixel <= 8; bytesPerPixel++ {
+ for i := 0; i < 100; i++ {
+ for j := range pdat0 {
+ pdat0[j] = uint8(r.Uint32())
+ cdat0[j] = uint8(r.Uint32())
+ }
+ copy(pdat1, pdat0)
+ copy(pdat2, pdat0)
+ copy(cdat1, cdat0)
+ copy(cdat2, cdat0)
+ filterPaeth(cdat1, pdat1, bytesPerPixel)
+ slowFilterPaeth(cdat2, pdat2, bytesPerPixel)
+ if !bytes.Equal(cdat1, cdat2) {
+ t.Errorf("bytesPerPixel: %d\npdat0: % x\ncdat0: % x\ngot: % x\nwant: % x", bytesPerPixel, pdat0, cdat0, cdat1, cdat2)
+ break
+ }
+ }
+ }
+}
diff --git a/libgo/go/image/png/reader.go b/libgo/go/image/png/reader.go
index fe07d60a91a..b3901b2adf9 100644
--- a/libgo/go/image/png/reader.go
+++ b/libgo/go/image/png/reader.go
@@ -98,13 +98,6 @@ type UnsupportedError string
func (e UnsupportedError) Error() string { return "png: unsupported feature: " + string(e) }
-func abs(x int) int {
- if x < 0 {
- return -x
- }
- return x
-}
-
func min(a, b int) int {
if a < b {
return a
@@ -233,7 +226,7 @@ func (d *decoder) parsetRNS(length uint32) error {
}
for i := 0; i < n; i++ {
rgba := d.palette[i].(color.RGBA)
- d.palette[i] = color.RGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
+ d.palette[i] = color.NRGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
}
case cbGA8, cbGA16, cbTCA8, cbTCA16:
return FormatError("tRNS, color type mismatch")
@@ -241,20 +234,6 @@ func (d *decoder) parsetRNS(length uint32) error {
return d.verifyChecksum()
}
-// The Paeth filter function, as per the PNG specification.
-func paeth(a, b, c uint8) uint8 {
- p := int(a) + int(b) - int(c)
- pa := abs(p - int(a))
- pb := abs(p - int(b))
- pc := abs(p - int(c))
- if pa <= pb && pa <= pc {
- return a
- } else if pb <= pc {
- return b
- }
- return c
-}
-
// Read presents one or more IDAT chunks as one continuous stream (minus the
// intermediate chunk headers and footers). If the PNG data looked like:
// ... len0 IDAT xxx crc0 len1 IDAT yy crc1 len2 IEND crc2
@@ -301,6 +280,7 @@ func (d *decoder) decode() (image.Image, error) {
defer r.Close()
bitsPerPixel := 0
maxPalette := uint8(0)
+ pixOffset := 0
var (
gray *image.Gray
rgba *image.RGBA
@@ -375,8 +355,8 @@ func (d *decoder) decode() (image.Image, error) {
cdat[i] += cdat[i-bytesPerPixel]
}
case ftUp:
- for i := 0; i < len(cdat); i++ {
- cdat[i] += pdat[i]
+ for i, p := range pdat {
+ cdat[i] += p
}
case ftAverage:
for i := 0; i < bytesPerPixel; i++ {
@@ -386,12 +366,7 @@ func (d *decoder) decode() (image.Image, error) {
cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2)
}
case ftPaeth:
- for i := 0; i < bytesPerPixel; i++ {
- cdat[i] += paeth(0, pdat[i], 0)
- }
- for i := bytesPerPixel; i < len(cdat); i++ {
- cdat[i] += paeth(cdat[i-bytesPerPixel], pdat[i], pdat[i-bytesPerPixel])
- }
+ filterPaeth(cdat, pdat, bytesPerPixel)
default:
return nil, FormatError("bad filter type")
}
@@ -423,18 +398,24 @@ func (d *decoder) decode() (image.Image, error) {
}
}
case cbG8:
- for x := 0; x < d.width; x++ {
- gray.SetGray(x, y, color.Gray{cdat[x]})
- }
+ copy(gray.Pix[pixOffset:], cdat)
+ pixOffset += gray.Stride
case cbGA8:
for x := 0; x < d.width; x++ {
ycol := cdat[2*x+0]
nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
}
case cbTC8:
+ pix, i, j := rgba.Pix, pixOffset, 0
for x := 0; x < d.width; x++ {
- rgba.SetRGBA(x, y, color.RGBA{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
+ pix[i+0] = cdat[j+0]
+ pix[i+1] = cdat[j+1]
+ pix[i+2] = cdat[j+2]
+ pix[i+3] = 0xff
+ i += 4
+ j += 3
}
+ pixOffset += rgba.Stride
case cbP1:
for x := 0; x < d.width; x += 8 {
b := cdat[x/8]
@@ -472,16 +453,18 @@ func (d *decoder) decode() (image.Image, error) {
}
}
case cbP8:
- for x := 0; x < d.width; x++ {
- if cdat[x] > maxPalette {
- return nil, FormatError("palette index out of range")
+ if maxPalette != 255 {
+ for x := 0; x < d.width; x++ {
+ if cdat[x] > maxPalette {
+ return nil, FormatError("palette index out of range")
+ }
}
- paletted.SetColorIndex(x, y, cdat[x])
}
+ copy(paletted.Pix[pixOffset:], cdat)
+ pixOffset += paletted.Stride
case cbTCA8:
- for x := 0; x < d.width; x++ {
- nrgba.SetNRGBA(x, y, color.NRGBA{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
- }
+ copy(nrgba.Pix[pixOffset:], cdat)
+ pixOffset += nrgba.Stride
case cbG16:
for x := 0; x < d.width; x++ {
ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
diff --git a/libgo/go/image/png/reader_test.go b/libgo/go/image/png/reader_test.go
index 24c4ea44808..8223f521cc3 100644
--- a/libgo/go/image/png/reader_test.go
+++ b/libgo/go/image/png/reader_test.go
@@ -10,6 +10,7 @@ import (
"image"
"image/color"
"io"
+ "io/ioutil"
"os"
"strings"
"testing"
@@ -106,13 +107,18 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
lastAlpha := -1
io.WriteString(w, "PLTE {\n")
for i, c := range cpm {
- r, g, b, a := c.RGBA()
- if a != 0xffff {
+ var r, g, b, a uint8
+ switch c := c.(type) {
+ case color.RGBA:
+ r, g, b, a = c.R, c.G, c.B, 0xff
+ case color.NRGBA:
+ r, g, b, a = c.R, c.G, c.B, c.A
+ default:
+ panic("unknown palette color type")
+ }
+ if a != 0xff {
lastAlpha = i
}
- r >>= 8
- g >>= 8
- b >>= 8
fmt.Fprintf(w, " (%3d,%3d,%3d) # rgb = (0x%02x,0x%02x,0x%02x)\n", r, g, b, r, g, b)
}
io.WriteString(w, "}\n")
@@ -267,3 +273,41 @@ func TestReaderError(t *testing.T) {
}
}
}
+
+func benchmarkDecode(b *testing.B, filename string, bytesPerPixel int) {
+ b.StopTimer()
+ data, err := ioutil.ReadFile(filename)
+ if err != nil {
+ b.Fatal(err)
+ }
+ s := string(data)
+ cfg, err := DecodeConfig(strings.NewReader(s))
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.SetBytes(int64(cfg.Width * cfg.Height * bytesPerPixel))
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ Decode(strings.NewReader(s))
+ }
+}
+
+func BenchmarkDecodeGray(b *testing.B) {
+ benchmarkDecode(b, "testdata/benchGray.png", 1)
+}
+
+func BenchmarkDecodeNRGBAGradient(b *testing.B) {
+ benchmarkDecode(b, "testdata/benchNRGBA-gradient.png", 4)
+}
+
+func BenchmarkDecodeNRGBAOpaque(b *testing.B) {
+ benchmarkDecode(b, "testdata/benchNRGBA-opaque.png", 4)
+}
+
+func BenchmarkDecodePaletted(b *testing.B) {
+ benchmarkDecode(b, "testdata/benchPaletted.png", 1)
+}
+
+func BenchmarkDecodeRGB(b *testing.B) {
+ benchmarkDecode(b, "testdata/benchRGB.png", 4)
+}
diff --git a/libgo/go/image/png/writer.go b/libgo/go/image/png/writer.go
index 57c03792b59..093d47193ba 100644
--- a/libgo/go/image/png/writer.go
+++ b/libgo/go/image/png/writer.go
@@ -21,7 +21,7 @@ type encoder struct {
err error
header [8]byte
footer [4]byte
- tmp [3 * 256]byte
+ tmp [4 * 256]byte
}
// Big-endian.
@@ -70,7 +70,7 @@ func (e *encoder) writeChunk(b []byte, name string) {
e.err = UnsupportedError(name + " chunk is too large: " + strconv.Itoa(len(b)))
return
}
- writeUint32(e.header[0:4], n)
+ writeUint32(e.header[:4], n)
e.header[4] = name[0]
e.header[5] = name[1]
e.header[6] = name[2]
@@ -78,9 +78,9 @@ func (e *encoder) writeChunk(b []byte, name string) {
crc := crc32.NewIEEE()
crc.Write(e.header[4:8])
crc.Write(b)
- writeUint32(e.footer[0:4], crc.Sum32())
+ writeUint32(e.footer[:4], crc.Sum32())
- _, e.err = e.w.Write(e.header[0:8])
+ _, e.err = e.w.Write(e.header[:8])
if e.err != nil {
return
}
@@ -88,7 +88,7 @@ func (e *encoder) writeChunk(b []byte, name string) {
if e.err != nil {
return
}
- _, e.err = e.w.Write(e.footer[0:4])
+ _, e.err = e.w.Write(e.footer[:4])
}
func (e *encoder) writeIHDR() {
@@ -122,36 +122,29 @@ func (e *encoder) writeIHDR() {
e.tmp[10] = 0 // default compression method
e.tmp[11] = 0 // default filter method
e.tmp[12] = 0 // non-interlaced
- e.writeChunk(e.tmp[0:13], "IHDR")
+ e.writeChunk(e.tmp[:13], "IHDR")
}
-func (e *encoder) writePLTE(p color.Palette) {
+func (e *encoder) writePLTEAndTRNS(p color.Palette) {
if len(p) < 1 || len(p) > 256 {
e.err = FormatError("bad palette length: " + strconv.Itoa(len(p)))
return
}
- for i, c := range p {
- r, g, b, _ := c.RGBA()
- e.tmp[3*i+0] = uint8(r >> 8)
- e.tmp[3*i+1] = uint8(g >> 8)
- e.tmp[3*i+2] = uint8(b >> 8)
- }
- e.writeChunk(e.tmp[0:3*len(p)], "PLTE")
-}
-
-func (e *encoder) maybeWritetRNS(p color.Palette) {
last := -1
for i, c := range p {
- _, _, _, a := c.RGBA()
- if a != 0xffff {
+ c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
+ e.tmp[3*i+0] = c1.R
+ e.tmp[3*i+1] = c1.G
+ e.tmp[3*i+2] = c1.B
+ if c1.A != 0xff {
last = i
}
- e.tmp[i] = uint8(a >> 8)
+ e.tmp[3*256+i] = c1.A
}
- if last == -1 {
- return
+ e.writeChunk(e.tmp[:3*len(p)], "PLTE")
+ if last != -1 {
+ e.writeChunk(e.tmp[3*256:3*256+1+last], "tRNS")
}
- e.writeChunk(e.tmp[:last+1], "tRNS")
}
// An encoder is an io.Writer that satisfies writes by writing PNG IDAT chunks,
@@ -297,26 +290,42 @@ func writeImage(w io.Writer, m image.Image, cb int) error {
}
pr := make([]uint8, 1+bpp*b.Dx())
+ gray, _ := m.(*image.Gray)
+ rgba, _ := m.(*image.RGBA)
+ paletted, _ := m.(*image.Paletted)
+ nrgba, _ := m.(*image.NRGBA)
+
for y := b.Min.Y; y < b.Max.Y; y++ {
// Convert from colors to bytes.
i := 1
switch cb {
case cbG8:
- for x := b.Min.X; x < b.Max.X; x++ {
- c := color.GrayModel.Convert(m.At(x, y)).(color.Gray)
- cr[0][i] = c.Y
- i++
+ if gray != nil {
+ offset := (y - b.Min.Y) * gray.Stride
+ copy(cr[0][1:], gray.Pix[offset:offset+b.Dx()])
+ } else {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ c := color.GrayModel.Convert(m.At(x, y)).(color.Gray)
+ cr[0][i] = c.Y
+ i++
+ }
}
case cbTC8:
// We have previously verified that the alpha value is fully opaque.
cr0 := cr[0]
- if rgba, _ := m.(*image.RGBA); rgba != nil {
- j0 := (y - b.Min.Y) * rgba.Stride
+ stride, pix := 0, []byte(nil)
+ if rgba != nil {
+ stride, pix = rgba.Stride, rgba.Pix
+ } else if nrgba != nil {
+ stride, pix = nrgba.Stride, nrgba.Pix
+ }
+ if stride != 0 {
+ j0 := (y - b.Min.Y) * stride
j1 := j0 + b.Dx()*4
for j := j0; j < j1; j += 4 {
- cr0[i+0] = rgba.Pix[j+0]
- cr0[i+1] = rgba.Pix[j+1]
- cr0[i+2] = rgba.Pix[j+2]
+ cr0[i+0] = pix[j+0]
+ cr0[i+1] = pix[j+1]
+ cr0[i+2] = pix[j+2]
i += 3
}
} else {
@@ -329,9 +338,9 @@ func writeImage(w io.Writer, m image.Image, cb int) error {
}
}
case cbP8:
- if p, _ := m.(*image.Paletted); p != nil {
- offset := (y - b.Min.Y) * p.Stride
- copy(cr[0][1:], p.Pix[offset:offset+b.Dx()])
+ if paletted != nil {
+ offset := (y - b.Min.Y) * paletted.Stride
+ copy(cr[0][1:], paletted.Pix[offset:offset+b.Dx()])
} else {
pi := m.(image.PalettedImage)
for x := b.Min.X; x < b.Max.X; x++ {
@@ -340,14 +349,19 @@ func writeImage(w io.Writer, m image.Image, cb int) error {
}
}
case cbTCA8:
- // Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
- for x := b.Min.X; x < b.Max.X; x++ {
- c := color.NRGBAModel.Convert(m.At(x, y)).(color.NRGBA)
- cr[0][i+0] = c.R
- cr[0][i+1] = c.G
- cr[0][i+2] = c.B
- cr[0][i+3] = c.A
- i += 4
+ if nrgba != nil {
+ offset := (y - b.Min.Y) * nrgba.Stride
+ copy(cr[0][1:], nrgba.Pix[offset:offset+b.Dx()*4])
+ } else {
+ // Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
+ for x := b.Min.X; x < b.Max.X; x++ {
+ c := color.NRGBAModel.Convert(m.At(x, y)).(color.NRGBA)
+ cr[0][i+0] = c.R
+ cr[0][i+1] = c.G
+ cr[0][i+2] = c.B
+ cr[0][i+3] = c.A
+ i += 4
+ }
}
case cbG16:
for x := b.Min.X; x < b.Max.X; x++ {
@@ -412,7 +426,7 @@ func (e *encoder) writeIDATs() {
e.err = bw.Flush()
}
-func (e *encoder) writeIEND() { e.writeChunk(e.tmp[0:0], "IEND") }
+func (e *encoder) writeIEND() { e.writeChunk(nil, "IEND") }
// Encode writes the Image m to w in PNG format. Any Image may be encoded, but
// images that are not image.NRGBA might be encoded lossily.
@@ -460,8 +474,7 @@ func Encode(w io.Writer, m image.Image) error {
_, e.err = io.WriteString(w, pngHeader)
e.writeIHDR()
if pal != nil {
- e.writePLTE(pal)
- e.maybeWritetRNS(pal)
+ e.writePLTEAndTRNS(pal)
}
e.writeIDATs()
e.writeIEND()
diff --git a/libgo/go/image/png/writer_test.go b/libgo/go/image/png/writer_test.go
index 644c4fb44b3..3116fc9ff94 100644
--- a/libgo/go/image/png/writer_test.go
+++ b/libgo/go/image/png/writer_test.go
@@ -101,6 +101,49 @@ func TestSubImage(t *testing.T) {
}
}
+func BenchmarkEncodeGray(b *testing.B) {
+ b.StopTimer()
+ img := image.NewGray(image.Rect(0, 0, 640, 480))
+ b.SetBytes(640 * 480 * 1)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ Encode(ioutil.Discard, img)
+ }
+}
+
+func BenchmarkEncodeNRGBOpaque(b *testing.B) {
+ b.StopTimer()
+ img := image.NewNRGBA(image.Rect(0, 0, 640, 480))
+ // Set all pixels to 0xFF alpha to force opaque mode.
+ bo := img.Bounds()
+ for y := bo.Min.Y; y < bo.Max.Y; y++ {
+ for x := bo.Min.X; x < bo.Max.X; x++ {
+ img.Set(x, y, color.NRGBA{0, 0, 0, 255})
+ }
+ }
+ if !img.Opaque() {
+ b.Fatal("expected image to be opaque")
+ }
+ b.SetBytes(640 * 480 * 4)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ Encode(ioutil.Discard, img)
+ }
+}
+
+func BenchmarkEncodeNRGBA(b *testing.B) {
+ b.StopTimer()
+ img := image.NewNRGBA(image.Rect(0, 0, 640, 480))
+ if img.Opaque() {
+ b.Fatal("expected image not to be opaque")
+ }
+ b.SetBytes(640 * 480 * 4)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ Encode(ioutil.Discard, img)
+ }
+}
+
func BenchmarkEncodePaletted(b *testing.B) {
b.StopTimer()
img := image.NewPaletted(image.Rect(0, 0, 640, 480), color.Palette{
@@ -138,7 +181,7 @@ func BenchmarkEncodeRGBA(b *testing.B) {
b.StopTimer()
img := image.NewRGBA(image.Rect(0, 0, 640, 480))
if img.Opaque() {
- b.Fatal("expected image to not be opaque")
+ b.Fatal("expected image not to be opaque")
}
b.SetBytes(640 * 480 * 4)
b.StartTimer()
diff --git a/libgo/go/image/ycbcr.go b/libgo/go/image/ycbcr.go
index c1a0b666f83..5b73bef7895 100644
--- a/libgo/go/image/ycbcr.go
+++ b/libgo/go/image/ycbcr.go
@@ -15,6 +15,7 @@ const (
YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
YCbCrSubsampleRatio422
YCbCrSubsampleRatio420
+ YCbCrSubsampleRatio440
)
func (s YCbCrSubsampleRatio) String() string {
@@ -25,6 +26,8 @@ func (s YCbCrSubsampleRatio) String() string {
return "YCbCrSubsampleRatio422"
case YCbCrSubsampleRatio420:
return "YCbCrSubsampleRatio420"
+ case YCbCrSubsampleRatio440:
+ return "YCbCrSubsampleRatio440"
}
return "YCbCrSubsampleRatioUnknown"
}
@@ -39,6 +42,7 @@ func (s YCbCrSubsampleRatio) String() string {
// For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1.
// For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2.
// For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4.
+// For 4:4:0, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/2.
type YCbCr struct {
Y, Cb, Cr []uint8
YStride int
@@ -82,6 +86,8 @@ func (p *YCbCr) COffset(x, y int) int {
return (y-p.Rect.Min.Y)*p.CStride + (x/2 - p.Rect.Min.X/2)
case YCbCrSubsampleRatio420:
return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2)
+ case YCbCrSubsampleRatio440:
+ return (y/2-p.Rect.Min.Y/2)*p.CStride + (x - p.Rect.Min.X)
}
// Default to 4:4:4 subsampling.
return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
@@ -126,6 +132,9 @@ func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
case YCbCrSubsampleRatio420:
cw = (r.Max.X+1)/2 - r.Min.X/2
ch = (r.Max.Y+1)/2 - r.Min.Y/2
+ case YCbCrSubsampleRatio440:
+ cw = w
+ ch = (r.Max.Y+1)/2 - r.Min.Y/2
default:
// Default to 4:4:4 subsampling.
cw = w
diff --git a/libgo/go/image/ycbcr_test.go b/libgo/go/image/ycbcr_test.go
index b2373f79ba3..7d1043dd395 100644
--- a/libgo/go/image/ycbcr_test.go
+++ b/libgo/go/image/ycbcr_test.go
@@ -37,6 +37,7 @@ func TestYCbCr(t *testing.T) {
YCbCrSubsampleRatio444,
YCbCrSubsampleRatio422,
YCbCrSubsampleRatio420,
+ YCbCrSubsampleRatio440,
}
deltas := []Point{
Pt(0, 0),
diff --git a/libgo/go/io/ioutil/blackhole.go b/libgo/go/io/ioutil/blackhole.go
new file mode 100644
index 00000000000..c127bdb71c0
--- /dev/null
+++ b/libgo/go/io/ioutil/blackhole.go
@@ -0,0 +1,13 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !race
+
+package ioutil
+
+var blackHoleBuf = make([]byte, 8192)
+
+func blackHole() []byte {
+ return blackHoleBuf
+}
diff --git a/libgo/go/io/ioutil/blackhole_race.go b/libgo/go/io/ioutil/blackhole_race.go
new file mode 100644
index 00000000000..eb640e05cfb
--- /dev/null
+++ b/libgo/go/io/ioutil/blackhole_race.go
@@ -0,0 +1,13 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build race
+
+package ioutil
+
+// Replaces the normal fast implementation with slower but formally correct one.
+
+func blackHole() []byte {
+ return make([]byte, 8192)
+}
diff --git a/libgo/go/io/ioutil/ioutil.go b/libgo/go/io/ioutil/ioutil.go
index f072b8c754a..31c77299eee 100644
--- a/libgo/go/io/ioutil/ioutil.go
+++ b/libgo/go/io/ioutil/ioutil.go
@@ -130,12 +130,11 @@ func (devNull) Write(p []byte) (int, error) {
return len(p), nil
}
-var blackHole = make([]byte, 8192)
-
func (devNull) ReadFrom(r io.Reader) (n int64, err error) {
+ buf := blackHole()
readSize := 0
for {
- readSize, err = r.Read(blackHole)
+ readSize, err = r.Read(buf)
n += int64(readSize)
if err != nil {
if err == io.EOF {
diff --git a/libgo/go/io/ioutil/tempfile.go b/libgo/go/io/ioutil/tempfile.go
index 42d2e675869..257e05d2152 100644
--- a/libgo/go/io/ioutil/tempfile.go
+++ b/libgo/go/io/ioutil/tempfile.go
@@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"strconv"
+ "sync"
"time"
)
@@ -16,18 +17,21 @@ import (
// chance the file doesn't exist yet - keeps the number of tries in
// TempFile to a minimum.
var rand uint32
+var randmu sync.Mutex
func reseed() uint32 {
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
}
func nextSuffix() string {
+ randmu.Lock()
r := rand
if r == 0 {
r = reseed()
}
r = r*1664525 + 1013904223 // constants from Numerical Recipes
rand = r
+ randmu.Unlock()
return strconv.Itoa(int(1e9 + r%1e9))[1:]
}
diff --git a/libgo/go/math/acosh.go b/libgo/go/math/acosh.go
index c6c8645e1ae..e394008b078 100644
--- a/libgo/go/math/acosh.go
+++ b/libgo/go/math/acosh.go
@@ -33,7 +33,7 @@ package math
// acosh(NaN) is NaN without signal.
//
-// Acosh(x) calculates the inverse hyperbolic cosine of x.
+// Acosh returns the inverse hyperbolic cosine of x.
//
// Special cases are:
// Acosh(+Inf) = +Inf
diff --git a/libgo/go/math/all_test.go b/libgo/go/math/all_test.go
index 35c33ce3859..cdea8035f9a 100644
--- a/libgo/go/math/all_test.go
+++ b/libgo/go/math/all_test.go
@@ -1128,11 +1128,11 @@ var vfgammaSC = []float64{
NaN(),
}
var gammaSC = []float64{
+ NaN(),
+ NaN(),
Inf(-1),
Inf(1),
Inf(1),
- Inf(1),
- Inf(1),
NaN(),
}
diff --git a/libgo/go/math/asinh.go b/libgo/go/math/asinh.go
index 0defbb9bef2..ff2de0215f5 100644
--- a/libgo/go/math/asinh.go
+++ b/libgo/go/math/asinh.go
@@ -30,7 +30,7 @@ package math
// := sign(x)*log1p(|x| + x**2/(1 + sqrt(1+x**2)))
//
-// Asinh(x) calculates the inverse hyperbolic sine of x.
+// Asinh returns the inverse hyperbolic sine of x.
//
// Special cases are:
// Asinh(±0) = ±0
diff --git a/libgo/go/math/atan.go b/libgo/go/math/atan.go
index b739721e81c..986ba068661 100644
--- a/libgo/go/math/atan.go
+++ b/libgo/go/math/atan.go
@@ -6,44 +6,85 @@ package math
/*
Floating-point arctangent.
-
- Atan returns the value of the arctangent of its
- argument in the range [-pi/2,pi/2].
- There are no error returns.
- Coefficients are #5077 from Hart & Cheney. (19.56D)
*/
-// xatan evaluates a series valid in the
-// range [-0.414...,+0.414...]. (tan(pi/8))
-func xatan(arg float64) float64 {
+// The original C code, the long comment, and the constants below were
+// from http://netlib.sandia.gov/cephes/cmath/atan.c, available from
+// http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a version of the original C.
+//
+// atan.c
+// Inverse circular tangent (arctangent)
+//
+// SYNOPSIS:
+// double x, y, atan();
+// y = atan( x );
+//
+// DESCRIPTION:
+// Returns radian angle between -pi/2 and +pi/2 whose tangent is x.
+//
+// Range reduction is from three intervals into the interval from zero to 0.66.
+// The approximant uses a rational function of degree 4/5 of the form
+// x + x**3 P(x)/Q(x).
+//
+// ACCURACY:
+// Relative error:
+// arithmetic domain # trials peak rms
+// DEC -10, 10 50000 2.4e-17 8.3e-18
+// IEEE -10, 10 10^6 1.8e-16 5.0e-17
+//
+// Cephes Math Library Release 2.8: June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+// Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+// The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+// Stephen L. Moshier
+// moshier@na-net.ornl.gov
+
+// xatan evaluates a series valid in the range [0, 0.66].
+func xatan(x float64) float64 {
const (
- P4 = .161536412982230228262e2
- P3 = .26842548195503973794141e3
- P2 = .11530293515404850115428136e4
- P1 = .178040631643319697105464587e4
- P0 = .89678597403663861959987488e3
- Q4 = .5895697050844462222791e2
- Q3 = .536265374031215315104235e3
- Q2 = .16667838148816337184521798e4
- Q1 = .207933497444540981287275926e4
- Q0 = .89678597403663861962481162e3
+ P0 = -8.750608600031904122785e-01
+ P1 = -1.615753718733365076637e+01
+ P2 = -7.500855792314704667340e+01
+ P3 = -1.228866684490136173410e+02
+ P4 = -6.485021904942025371773e+01
+ Q0 = +2.485846490142306297962e+01
+ Q1 = +1.650270098316988542046e+02
+ Q2 = +4.328810604912902668951e+02
+ Q3 = +4.853903996359136964868e+02
+ Q4 = +1.945506571482613964425e+02
)
- sq := arg * arg
- value := ((((P4*sq+P3)*sq+P2)*sq+P1)*sq + P0)
- value = value / (((((sq+Q4)*sq+Q3)*sq+Q2)*sq+Q1)*sq + Q0)
- return value * arg
+ z := x * x
+ z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4)
+ z = x*z + x
+ return z
}
// satan reduces its argument (known to be positive)
-// to the range [0,0.414...] and calls xatan.
-func satan(arg float64) float64 {
- if arg < Sqrt2-1 {
- return xatan(arg)
+// to the range [0, 0.66] and calls xatan.
+func satan(x float64) float64 {
+ const (
+ Morebits = 6.123233995736765886130e-17 // pi/2 = PIO2 + Morebits
+ Tan3pio8 = 2.41421356237309504880 // tan(3*pi/8)
+ )
+ if x <= 0.66 {
+ return xatan(x)
}
- if arg > Sqrt2+1 {
- return Pi/2 - xatan(1/arg)
+ if x > Tan3pio8 {
+ return Pi/2 - xatan(1/x) + Morebits
}
- return Pi/4 + xatan((arg-1)/(arg+1))
+ return Pi/4 + xatan((x-1)/(x+1)) + 0.5*Morebits
}
// Atan returns the arctangent of x.
diff --git a/libgo/go/math/atanh.go b/libgo/go/math/atanh.go
index 5b5d468559b..113d5c103c0 100644
--- a/libgo/go/math/atanh.go
+++ b/libgo/go/math/atanh.go
@@ -36,7 +36,7 @@ package math
// atanh(+-1) is +-INF with signal.
//
-// Atanh(x) calculates the inverse hyperbolic tangent of x.
+// Atanh returns the inverse hyperbolic tangent of x.
//
// Special cases are:
// Atanh(1) = +Inf
diff --git a/libgo/go/math/big/arith_test.go b/libgo/go/math/big/arith_test.go
index c7e3d284c2d..3615a659c3b 100644
--- a/libgo/go/math/big/arith_test.go
+++ b/libgo/go/math/big/arith_test.go
@@ -4,7 +4,10 @@
package big
-import "testing"
+import (
+ "math/rand"
+ "testing"
+)
type funWW func(x, y, c Word) (z1, z0 Word)
type argWW struct {
@@ -100,6 +103,43 @@ func TestFunVV(t *testing.T) {
}
}
+// Always the same seed for reproducible results.
+var rnd = rand.New(rand.NewSource(0))
+
+func rndW() Word {
+ return Word(rnd.Int63()<<1 | rnd.Int63n(2))
+}
+
+func rndV(n int) []Word {
+ v := make([]Word, n)
+ for i := range v {
+ v[i] = rndW()
+ }
+ return v
+}
+
+func benchmarkFunVV(b *testing.B, f funVV, n int) {
+ x := rndV(n)
+ y := rndV(n)
+ z := make([]Word, n)
+ b.SetBytes(int64(n * _W))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ f(z, x, y)
+ }
+}
+
+func BenchmarkAddVV_1(b *testing.B) { benchmarkFunVV(b, addVV, 1) }
+func BenchmarkAddVV_2(b *testing.B) { benchmarkFunVV(b, addVV, 2) }
+func BenchmarkAddVV_3(b *testing.B) { benchmarkFunVV(b, addVV, 3) }
+func BenchmarkAddVV_4(b *testing.B) { benchmarkFunVV(b, addVV, 4) }
+func BenchmarkAddVV_5(b *testing.B) { benchmarkFunVV(b, addVV, 5) }
+func BenchmarkAddVV_1e1(b *testing.B) { benchmarkFunVV(b, addVV, 1e1) }
+func BenchmarkAddVV_1e2(b *testing.B) { benchmarkFunVV(b, addVV, 1e2) }
+func BenchmarkAddVV_1e3(b *testing.B) { benchmarkFunVV(b, addVV, 1e3) }
+func BenchmarkAddVV_1e4(b *testing.B) { benchmarkFunVV(b, addVV, 1e4) }
+func BenchmarkAddVV_1e5(b *testing.B) { benchmarkFunVV(b, addVV, 1e5) }
+
type funVW func(z, x []Word, y Word) (c Word)
type argVW struct {
z, x nat
@@ -210,6 +250,28 @@ func TestFunVW(t *testing.T) {
}
}
+func benchmarkFunVW(b *testing.B, f funVW, n int) {
+ x := rndV(n)
+ y := rndW()
+ z := make([]Word, n)
+ b.SetBytes(int64(n * _W))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ f(z, x, y)
+ }
+}
+
+func BenchmarkAddVW_1(b *testing.B) { benchmarkFunVW(b, addVW, 1) }
+func BenchmarkAddVW_2(b *testing.B) { benchmarkFunVW(b, addVW, 2) }
+func BenchmarkAddVW_3(b *testing.B) { benchmarkFunVW(b, addVW, 3) }
+func BenchmarkAddVW_4(b *testing.B) { benchmarkFunVW(b, addVW, 4) }
+func BenchmarkAddVW_5(b *testing.B) { benchmarkFunVW(b, addVW, 5) }
+func BenchmarkAddVW_1e1(b *testing.B) { benchmarkFunVW(b, addVW, 1e1) }
+func BenchmarkAddVW_1e2(b *testing.B) { benchmarkFunVW(b, addVW, 1e2) }
+func BenchmarkAddVW_1e3(b *testing.B) { benchmarkFunVW(b, addVW, 1e3) }
+func BenchmarkAddVW_1e4(b *testing.B) { benchmarkFunVW(b, addVW, 1e4) }
+func BenchmarkAddVW_1e5(b *testing.B) { benchmarkFunVW(b, addVW, 1e5) }
+
type funVWW func(z, x []Word, y, r Word) (c Word)
type argVWW struct {
z, x nat
@@ -334,6 +396,28 @@ func TestMulAddWWW(t *testing.T) {
}
}
+func benchmarkAddMulVVW(b *testing.B, n int) {
+ x := rndV(n)
+ y := rndW()
+ z := make([]Word, n)
+ b.SetBytes(int64(n * _W))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ addMulVVW(z, x, y)
+ }
+}
+
+func BenchmarkAddMulVVW_1(b *testing.B) { benchmarkAddMulVVW(b, 1) }
+func BenchmarkAddMulVVW_2(b *testing.B) { benchmarkAddMulVVW(b, 2) }
+func BenchmarkAddMulVVW_3(b *testing.B) { benchmarkAddMulVVW(b, 3) }
+func BenchmarkAddMulVVW_4(b *testing.B) { benchmarkAddMulVVW(b, 4) }
+func BenchmarkAddMulVVW_5(b *testing.B) { benchmarkAddMulVVW(b, 5) }
+func BenchmarkAddMulVVW_1e1(b *testing.B) { benchmarkAddMulVVW(b, 1e1) }
+func BenchmarkAddMulVVW_1e2(b *testing.B) { benchmarkAddMulVVW(b, 1e2) }
+func BenchmarkAddMulVVW_1e3(b *testing.B) { benchmarkAddMulVVW(b, 1e3) }
+func BenchmarkAddMulVVW_1e4(b *testing.B) { benchmarkAddMulVVW(b, 1e4) }
+func BenchmarkAddMulVVW_1e5(b *testing.B) { benchmarkAddMulVVW(b, 1e5) }
+
func testWordBitLen(t *testing.T, fname string, f func(Word) int) {
for i := 0; i <= _W; i++ {
x := Word(1) << uint(i-1) // i == 0 => x == 0
diff --git a/libgo/go/math/big/calibrate_test.go b/libgo/go/math/big/calibrate_test.go
index efe1837bba3..f69ffbf5cf1 100644
--- a/libgo/go/math/big/calibrate_test.go
+++ b/libgo/go/math/big/calibrate_test.go
@@ -21,15 +21,17 @@ import (
var calibrate = flag.Bool("calibrate", false, "run calibration test")
-// measure returns the time to run f
-func measure(f func()) time.Duration {
- const N = 100
- start := time.Now()
- for i := N; i > 0; i-- {
- f()
- }
- stop := time.Now()
- return stop.Sub(start) / N
+func karatsubaLoad(b *testing.B) {
+ BenchmarkMul(b)
+}
+
+// measureKaratsuba returns the time to run a Karatsuba-relevant benchmark
+// given Karatsuba threshold th.
+func measureKaratsuba(th int) time.Duration {
+ th, karatsubaThreshold = karatsubaThreshold, th
+ res := testing.Benchmark(karatsubaLoad)
+ karatsubaThreshold = th
+ return time.Duration(res.NsPerOp())
}
func computeThresholds() {
@@ -37,35 +39,33 @@ func computeThresholds() {
fmt.Printf("(run repeatedly for good results)\n")
// determine Tk, the work load execution time using basic multiplication
- karatsubaThreshold = 1e9 // disable karatsuba
- Tb := measure(benchmarkMulLoad)
- fmt.Printf("Tb = %dns\n", Tb)
+ Tb := measureKaratsuba(1e9) // th == 1e9 => Karatsuba multiplication disabled
+ fmt.Printf("Tb = %10s\n", Tb)
// thresholds
- n := 8 // any lower values for the threshold lead to very slow multiplies
+ th := 4
th1 := -1
th2 := -1
var deltaOld time.Duration
- for count := -1; count != 0; count-- {
+ for count := -1; count != 0 && th < 128; count-- {
// determine Tk, the work load execution time using Karatsuba multiplication
- karatsubaThreshold = n // enable karatsuba
- Tk := measure(benchmarkMulLoad)
+ Tk := measureKaratsuba(th)
// improvement over Tb
delta := (Tb - Tk) * 100 / Tb
- fmt.Printf("n = %3d Tk = %8dns %4d%%", n, Tk, delta)
+ fmt.Printf("th = %3d Tk = %10s %4d%%", th, Tk, delta)
// determine break-even point
if Tk < Tb && th1 < 0 {
- th1 = n
+ th1 = th
fmt.Print(" break-even point")
}
// determine diminishing return
if 0 < delta && delta < deltaOld && th2 < 0 {
- th2 = n
+ th2 = th
fmt.Print(" diminishing return")
}
deltaOld = delta
@@ -74,10 +74,10 @@ func computeThresholds() {
// trigger counter
if th1 >= 0 && th2 >= 0 && count < 0 {
- count = 20 // this many extra measurements after we got both thresholds
+ count = 10 // this many extra measurements after we got both thresholds
}
- n++
+ th++
}
}
diff --git a/libgo/go/math/big/gcd_test.go b/libgo/go/math/big/gcd_test.go
new file mode 100644
index 00000000000..c0b9f583000
--- /dev/null
+++ b/libgo/go/math/big/gcd_test.go
@@ -0,0 +1,47 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements a GCD benchmark.
+// Usage: go test math/big -test.bench GCD
+
+package big
+
+import (
+ "math/rand"
+ "testing"
+)
+
+// randInt returns a pseudo-random Int in the range [1<<(size-1), (1<<size) - 1]
+func randInt(r *rand.Rand, size uint) *Int {
+ n := new(Int).Lsh(intOne, size-1)
+ x := new(Int).Rand(r, n)
+ return x.Add(x, n) // make sure result > 1<<(size-1)
+}
+
+func runGCD(b *testing.B, aSize, bSize uint) {
+ b.StopTimer()
+ var r = rand.New(rand.NewSource(1234))
+ aa := randInt(r, aSize)
+ bb := randInt(r, bSize)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ new(Int).GCD(nil, nil, aa, bb)
+ }
+}
+
+func BenchmarkGCD10x10(b *testing.B) { runGCD(b, 10, 10) }
+func BenchmarkGCD10x100(b *testing.B) { runGCD(b, 10, 100) }
+func BenchmarkGCD10x1000(b *testing.B) { runGCD(b, 10, 1000) }
+func BenchmarkGCD10x10000(b *testing.B) { runGCD(b, 10, 10000) }
+func BenchmarkGCD10x100000(b *testing.B) { runGCD(b, 10, 100000) }
+func BenchmarkGCD100x100(b *testing.B) { runGCD(b, 100, 100) }
+func BenchmarkGCD100x1000(b *testing.B) { runGCD(b, 100, 1000) }
+func BenchmarkGCD100x10000(b *testing.B) { runGCD(b, 100, 10000) }
+func BenchmarkGCD100x100000(b *testing.B) { runGCD(b, 100, 100000) }
+func BenchmarkGCD1000x1000(b *testing.B) { runGCD(b, 1000, 1000) }
+func BenchmarkGCD1000x10000(b *testing.B) { runGCD(b, 1000, 10000) }
+func BenchmarkGCD1000x100000(b *testing.B) { runGCD(b, 1000, 100000) }
+func BenchmarkGCD10000x10000(b *testing.B) { runGCD(b, 10000, 10000) }
+func BenchmarkGCD10000x100000(b *testing.B) { runGCD(b, 10000, 100000) }
+func BenchmarkGCD100000x100000(b *testing.B) { runGCD(b, 100000, 100000) }
diff --git a/libgo/go/math/big/int.go b/libgo/go/math/big/int.go
index cd2cd0e2da0..4bd7958ae50 100644
--- a/libgo/go/math/big/int.go
+++ b/libgo/go/math/big/int.go
@@ -581,12 +581,12 @@ func (z *Int) Exp(x, y, m *Int) *Int {
return z
}
-// GCD sets z to the greatest common divisor of a and b, which must be
-// positive numbers, and returns z.
+// GCD sets z to the greatest common divisor of a and b, which both must
+// be > 0, and returns z.
// If x and y are not nil, GCD sets x and y such that z = a*x + b*y.
-// If either a or b is not positive, GCD sets z = x = y = 0.
+// If either a or b is <= 0, GCD sets z = x = y = 0.
func (z *Int) GCD(x, y, a, b *Int) *Int {
- if a.neg || b.neg {
+ if a.Sign() <= 0 || b.Sign() <= 0 {
z.SetInt64(0)
if x != nil {
x.SetInt64(0)
@@ -596,6 +596,9 @@ func (z *Int) GCD(x, y, a, b *Int) *Int {
}
return z
}
+ if x == nil && y == nil {
+ return z.binaryGCD(a, b)
+ }
A := new(Int).Set(a)
B := new(Int).Set(b)
@@ -640,6 +643,63 @@ func (z *Int) GCD(x, y, a, b *Int) *Int {
return z
}
+// binaryGCD sets z to the greatest common divisor of a and b, which both must
+// be > 0, and returns z.
+// See Knuth, The Art of Computer Programming, Vol. 2, Section 4.5.2, Algorithm B.
+func (z *Int) binaryGCD(a, b *Int) *Int {
+ u := z
+ v := new(Int)
+
+ // use one Euclidean iteration to ensure that u and v are approx. the same size
+ switch {
+ case len(a.abs) > len(b.abs):
+ u.Set(b)
+ v.Rem(a, b)
+ case len(a.abs) < len(b.abs):
+ u.Set(a)
+ v.Rem(b, a)
+ default:
+ u.Set(a)
+ v.Set(b)
+ }
+
+ // v might be 0 now
+ if len(v.abs) == 0 {
+ return u
+ }
+ // u > 0 && v > 0
+
+ // determine largest k such that u = u' << k, v = v' << k
+ k := u.abs.trailingZeroBits()
+ if vk := v.abs.trailingZeroBits(); vk < k {
+ k = vk
+ }
+ u.Rsh(u, k)
+ v.Rsh(v, k)
+
+ // determine t (we know that u > 0)
+ t := new(Int)
+ if u.abs[0]&1 != 0 {
+ // u is odd
+ t.Neg(v)
+ } else {
+ t.Set(u)
+ }
+
+ for len(t.abs) > 0 {
+ // reduce t
+ t.Rsh(t, t.abs.trailingZeroBits())
+ if t.neg {
+ v.Neg(t)
+ } else {
+ u.Set(t)
+ }
+ t.Sub(u, v)
+ }
+
+ return u.Lsh(u, k)
+}
+
// ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
// If it returns true, x is prime with probability 1 - 1/4^n.
// If it returns false, x is not prime.
@@ -697,6 +757,13 @@ func (z *Int) Rsh(x *Int, n uint) *Int {
// Bit returns the value of the i'th bit of x. That is, it
// returns (x>>i)&1. The bit index i must be >= 0.
func (x *Int) Bit(i int) uint {
+ if i == 0 {
+ // optimization for common case: odd/even test of x
+ if len(x.abs) > 0 {
+ return uint(x.abs[0] & 1) // bit 0 is same for -x
+ }
+ return 0
+ }
if i < 0 {
panic("negative bit index")
}
@@ -894,3 +961,19 @@ func (z *Int) GobDecode(buf []byte) error {
z.abs = z.abs.setBytes(buf[1:])
return nil
}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (x *Int) MarshalJSON() ([]byte, error) {
+ // TODO(gri): get rid of the []byte/string conversions
+ return []byte(x.String()), nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (z *Int) UnmarshalJSON(x []byte) error {
+ // TODO(gri): get rid of the []byte/string conversions
+ _, ok := z.SetString(string(x), 0)
+ if !ok {
+ return fmt.Errorf("math/big: cannot unmarshal %s into a *big.Int", x)
+ }
+ return nil
+}
diff --git a/libgo/go/math/big/int_test.go b/libgo/go/math/big/int_test.go
index 9700a9b5a7c..27834cec6af 100644
--- a/libgo/go/math/big/int_test.go
+++ b/libgo/go/math/big/int_test.go
@@ -8,6 +8,7 @@ import (
"bytes"
"encoding/gob"
"encoding/hex"
+ "encoding/json"
"fmt"
"math/rand"
"testing"
@@ -817,14 +818,12 @@ func TestExp(t *testing.T) {
}
func checkGcd(aBytes, bBytes []byte) bool {
- a := new(Int).SetBytes(aBytes)
- b := new(Int).SetBytes(bBytes)
-
x := new(Int)
y := new(Int)
- d := new(Int)
+ a := new(Int).SetBytes(aBytes)
+ b := new(Int).SetBytes(bBytes)
- d.GCD(x, y, a, b)
+ d := new(Int).GCD(x, y, a, b)
x.Mul(x, a)
y.Mul(y, b)
x.Add(x, y)
@@ -833,32 +832,70 @@ func checkGcd(aBytes, bBytes []byte) bool {
}
var gcdTests = []struct {
- a, b int64
- d, x, y int64
+ d, x, y, a, b string
}{
- {120, 23, 1, -9, 47},
-}
-
-func TestGcd(t *testing.T) {
- for i, test := range gcdTests {
- a := NewInt(test.a)
- b := NewInt(test.b)
+ // a <= 0 || b <= 0
+ {"0", "0", "0", "0", "0"},
+ {"0", "0", "0", "0", "7"},
+ {"0", "0", "0", "11", "0"},
+ {"0", "0", "0", "-77", "35"},
+ {"0", "0", "0", "64515", "-24310"},
+ {"0", "0", "0", "-64515", "-24310"},
+
+ {"1", "-9", "47", "120", "23"},
+ {"7", "1", "-2", "77", "35"},
+ {"935", "-3", "8", "64515", "24310"},
+ {"935000000000000000", "-3", "8", "64515000000000000000", "24310000000000000000"},
+ {"1", "-221", "22059940471369027483332068679400581064239780177629666810348940098015901108344", "98920366548084643601728869055592650835572950932266967461790948584315647051443", "991"},
+
+ // test early exit (after one Euclidean iteration) in binaryGCD
+ {"1", "", "", "1", "98920366548084643601728869055592650835572950932266967461790948584315647051443"},
+}
+
+func testGcd(t *testing.T, d, x, y, a, b *Int) {
+ var X *Int
+ if x != nil {
+ X = new(Int)
+ }
+ var Y *Int
+ if y != nil {
+ Y = new(Int)
+ }
- x := new(Int)
- y := new(Int)
- d := new(Int)
+ D := new(Int).GCD(X, Y, a, b)
+ if D.Cmp(d) != 0 {
+ t.Errorf("GCD(%s, %s): got d = %s, want %s", a, b, D, d)
+ }
+ if x != nil && X.Cmp(x) != 0 {
+ t.Errorf("GCD(%s, %s): got x = %s, want %s", a, b, X, x)
+ }
+ if y != nil && Y.Cmp(y) != 0 {
+ t.Errorf("GCD(%s, %s): got y = %s, want %s", a, b, Y, y)
+ }
- expectedX := NewInt(test.x)
- expectedY := NewInt(test.y)
- expectedD := NewInt(test.d)
+ // binaryGCD requires a > 0 && b > 0
+ if a.Sign() <= 0 || b.Sign() <= 0 {
+ return
+ }
- d.GCD(x, y, a, b)
+ D.binaryGCD(a, b)
+ if D.Cmp(d) != 0 {
+ t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, D, d)
+ }
+}
- if expectedX.Cmp(x) != 0 ||
- expectedY.Cmp(y) != 0 ||
- expectedD.Cmp(d) != 0 {
- t.Errorf("#%d got (%s %s %s) want (%s %s %s)", i, x, y, d, expectedX, expectedY, expectedD)
- }
+func TestGcd(t *testing.T) {
+ for _, test := range gcdTests {
+ d, _ := new(Int).SetString(test.d, 0)
+ x, _ := new(Int).SetString(test.x, 0)
+ y, _ := new(Int).SetString(test.y, 0)
+ a, _ := new(Int).SetString(test.a, 0)
+ b, _ := new(Int).SetString(test.b, 0)
+
+ testGcd(t, d, nil, nil, a, b)
+ testGcd(t, d, x, nil, a, b)
+ testGcd(t, d, nil, y, a, b)
+ testGcd(t, d, x, y, a, b)
}
quick.Check(checkGcd, nil)
@@ -1368,8 +1405,12 @@ func TestModInverse(t *testing.T) {
}
}
-// used by TestIntGobEncoding and TestRatGobEncoding
-var gobEncodingTests = []string{
+var encodingTests = []string{
+ "-539345864568634858364538753846587364875430589374589",
+ "-678645873",
+ "-100",
+ "-2",
+ "-1",
"0",
"1",
"2",
@@ -1383,26 +1424,37 @@ func TestIntGobEncoding(t *testing.T) {
var medium bytes.Buffer
enc := gob.NewEncoder(&medium)
dec := gob.NewDecoder(&medium)
- for i, test := range gobEncodingTests {
- for j := 0; j < 2; j++ {
- medium.Reset() // empty buffer for each test case (in case of failures)
- stest := test
- if j != 0 {
- // negative numbers
- stest = "-" + test
- }
- var tx Int
- tx.SetString(stest, 10)
- if err := enc.Encode(&tx); err != nil {
- t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
- }
- var rx Int
- if err := dec.Decode(&rx); err != nil {
- t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
- }
- if rx.Cmp(&tx) != 0 {
- t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
- }
+ for _, test := range encodingTests {
+ medium.Reset() // empty buffer for each test case (in case of failures)
+ var tx Int
+ tx.SetString(test, 10)
+ if err := enc.Encode(&tx); err != nil {
+ t.Errorf("encoding of %s failed: %s", &tx, err)
+ }
+ var rx Int
+ if err := dec.Decode(&rx); err != nil {
+ t.Errorf("decoding of %s failed: %s", &tx, err)
+ }
+ if rx.Cmp(&tx) != 0 {
+ t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
+ }
+ }
+}
+
+func TestIntJSONEncoding(t *testing.T) {
+ for _, test := range encodingTests {
+ var tx Int
+ tx.SetString(test, 10)
+ b, err := json.Marshal(&tx)
+ if err != nil {
+ t.Errorf("marshaling of %s failed: %s", &tx, err)
+ }
+ var rx Int
+ if err := json.Unmarshal(b, &rx); err != nil {
+ t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+ }
+ if rx.Cmp(&tx) != 0 {
+ t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
}
}
}
diff --git a/libgo/go/math/big/nat.go b/libgo/go/math/big/nat.go
index 6d81823bb4a..2d5a5c9587d 100644
--- a/libgo/go/math/big/nat.go
+++ b/libgo/go/math/big/nat.go
@@ -236,7 +236,7 @@ func karatsubaSub(z, x nat, n int) {
// Operands that are shorter than karatsubaThreshold are multiplied using
// "grade school" multiplication; for longer operands the Karatsuba algorithm
// is used.
-var karatsubaThreshold int = 32 // computed by calibrate.go
+var karatsubaThreshold int = 40 // computed by calibrate.go
// karatsuba multiplies x and y and leaves the result in z.
// Both x and y must have the same length n and n must be a
@@ -342,7 +342,7 @@ func alias(x, y nat) bool {
return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
}
-// addAt implements z += x*(1<<(_W*i)); z must be long enough.
+// addAt implements z += x<<(_W*i); z must be long enough.
// (we don't use nat.add because we need z to stay the same
// slice, and we don't need to normalize z after each addition)
func addAt(z, x nat, i int) {
@@ -405,8 +405,8 @@ func (z nat) mul(x, y nat) nat {
// determine Karatsuba length k such that
//
- // x = x1*b + x0
- // y = y1*b + y0 (and k <= len(y), which implies k <= len(x))
+ // x = xh*b + x0 (0 <= x0 < b)
+ // y = yh*b + y0 (0 <= y0 < b)
// b = 1<<(_W*k) ("base" of digits xi, yi)
//
k := karatsubaLen(n)
@@ -417,27 +417,44 @@ func (z nat) mul(x, y nat) nat {
y0 := y[0:k] // y0 is not normalized
z = z.make(max(6*k, m+n)) // enough space for karatsuba of x0*y0 and full result of x*y
karatsuba(z, x0, y0)
- z = z[0 : m+n] // z has final length but may be incomplete, upper portion is garbage
-
- // If x1 and/or y1 are not 0, add missing terms to z explicitly:
- //
- // m+n 2*k 0
- // z = [ ... | x0*y0 ]
- // + [ x1*y1 ]
- // + [ x1*y0 ]
- // + [ x0*y1 ]
+ z = z[0 : m+n] // z has final length but may be incomplete
+ z[2*k:].clear() // upper portion of z is garbage (and 2*k <= m+n since k <= n <= m)
+
+ // If xh != 0 or yh != 0, add the missing terms to z. For
+ //
+ // xh = xi*b^i + ... + x2*b^2 + x1*b (0 <= xi < b)
+ // yh = y1*b (0 <= y1 < b)
+ //
+ // the missing terms are
+ //
+ // x0*y1*b and xi*y0*b^i, xi*y1*b^(i+1) for i > 0
+ //
+ // since all the yi for i > 1 are 0 by choice of k: If any of them
+ // were > 0, then yh >= b^2 and thus y >= b^2. Then k' = k*2 would
+ // be a larger valid threshold contradicting the assumption about k.
//
if k < n || m != n {
- x1 := x[k:] // x1 is normalized because x is
- y1 := y[k:] // y1 is normalized because y is
var t nat
- t = t.mul(x1, y1)
- copy(z[2*k:], t)
- z[2*k+len(t):].clear() // upper portion of z is garbage
- t = t.mul(x1, y0.norm())
- addAt(z, t, k)
- t = t.mul(x0.norm(), y1)
+
+ // add x0*y1*b
+ x0 := x0.norm()
+ y1 := y[k:] // y1 is normalized because y is
+ t = t.mul(x0, y1) // update t so we don't lose t's underlying array
addAt(z, t, k)
+
+ // add xi*y0<<i, xi*y1*b<<(i+k)
+ y0 := y0.norm()
+ for i := k; i < len(x); i += k {
+ xi := x[i:]
+ if len(xi) > k {
+ xi = xi[:k]
+ }
+ xi = xi.norm()
+ t = t.mul(xi, y0)
+ addAt(z, t, i)
+ t = t.mul(xi, y1)
+ addAt(z, t, i+k)
+ }
}
return z.norm()
@@ -493,14 +510,9 @@ func (z nat) div(z2, u, v nat) (q, r nat) {
}
if len(v) == 1 {
- var rprime Word
- q, rprime = z.divW(u, v[0])
- if rprime > 0 {
- r = z2.make(1)
- r[0] = rprime
- } else {
- r = z2.make(0)
- }
+ var r2 Word
+ q, r2 = z.divW(u, v[0])
+ r = z2.setWord(r2)
return
}
@@ -740,7 +752,7 @@ func (x nat) string(charset string) string {
// convert power of two and non power of two bases separately
if b == b&-b {
// shift is base-b digit size in bits
- shift := uint(trailingZeroBits(b)) // shift > 0 because b >= 2
+ shift := trailingZeroBits(b) // shift > 0 because b >= 2
mask := Word(1)<<shift - 1
w := x[0]
nbits := uint(_W) // number of unprocessed bits in w
@@ -993,10 +1005,9 @@ var deBruijn64Lookup = []byte{
54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
}
-// trailingZeroBits returns the number of consecutive zero bits on the right
-// side of the given Word.
-// See Knuth, volume 4, section 7.3.1
-func trailingZeroBits(x Word) int {
+// trailingZeroBits returns the number of consecutive least significant zero
+// bits of x.
+func trailingZeroBits(x Word) uint {
// x & -x leaves only the right-most bit set in the word. Let k be the
// index of that bit. Since only a single bit is set, the value is two
// to the power of k. Multiplying by a power of two is equivalent to
@@ -1005,18 +1016,33 @@ func trailingZeroBits(x Word) int {
// Therefore, if we have a left shifted version of this constant we can
// find by how many bits it was shifted by looking at which six bit
// substring ended up at the top of the word.
+ // (Knuth, volume 4, section 7.3.1)
switch _W {
case 32:
- return int(deBruijn32Lookup[((x&-x)*deBruijn32)>>27])
+ return uint(deBruijn32Lookup[((x&-x)*deBruijn32)>>27])
case 64:
- return int(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58])
+ return uint(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58])
default:
- panic("Unknown word size")
+ panic("unknown word size")
}
return 0
}
+// trailingZeroBits returns the number of consecutive least significant zero
+// bits of x.
+func (x nat) trailingZeroBits() uint {
+ if len(x) == 0 {
+ return 0
+ }
+ var i uint
+ for x[i] == 0 {
+ i++
+ }
+ // x[i] != 0
+ return i*_W + trailingZeroBits(x[i])
+}
+
// z = x << s
func (z nat) shl(x nat, s uint) nat {
m := len(x)
@@ -1169,29 +1195,6 @@ func (x nat) modW(d Word) (r Word) {
return divWVW(q, 0, x, d)
}
-// powersOfTwoDecompose finds q and k with x = q * 1<<k and q is odd, or q and k are 0.
-func (x nat) powersOfTwoDecompose() (q nat, k int) {
- if len(x) == 0 {
- return x, 0
- }
-
- // One of the words must be non-zero by definition,
- // so this loop will terminate with i < len(x), and
- // i is the number of 0 words.
- i := 0
- for x[i] == 0 {
- i++
- }
- n := trailingZeroBits(x[i]) // x[i] != 0
-
- q = make(nat, len(x)-i)
- shrVU(q, x[i:], uint(n))
-
- q = q.norm()
- k = i*_W + n
- return
-}
-
// random creates a random integer in [0..limit), using the space in z if
// possible. n is the bit length of limit.
func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
@@ -1207,17 +1210,19 @@ func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
mask := Word((1 << bitLengthOfMSW) - 1)
for {
- for i := range z {
- switch _W {
- case 32:
+ switch _W {
+ case 32:
+ for i := range z {
z[i] = Word(rand.Uint32())
- case 64:
+ }
+ case 64:
+ for i := range z {
z[i] = Word(rand.Uint32()) | Word(rand.Uint32())<<32
}
+ default:
+ panic("unknown word size")
}
-
z[len(limit)-1] &= mask
-
if z.cmp(limit) < 0 {
break
}
@@ -1230,7 +1235,7 @@ func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
// reuses the storage of z if possible.
func (z nat) expNN(x, y, m nat) nat {
if alias(z, x) || alias(z, y) {
- // We cannot allow in place modification of x or y.
+ // We cannot allow in-place modification of x or y.
z = nil
}
@@ -1259,15 +1264,21 @@ func (z nat) expNN(x, y, m nat) nat {
// we also multiply by x, thus adding one to the power.
w := _W - int(shift)
+ // zz and r are used to avoid allocating in mul and div as
+ // otherwise the arguments would alias.
+ var zz, r nat
for j := 0; j < w; j++ {
- z = z.mul(z, z)
+ zz = zz.mul(z, z)
+ zz, z = z, zz
if v&mask != 0 {
- z = z.mul(z, x)
+ zz = zz.mul(z, x)
+ zz, z = z, zz
}
if m != nil {
- q, z = q.div(z, z, m)
+ zz, r = zz.div(r, z, m)
+ zz, r, q, z = q, z, zz, r
}
v <<= 1
@@ -1277,14 +1288,17 @@ func (z nat) expNN(x, y, m nat) nat {
v = y[i]
for j := 0; j < _W; j++ {
- z = z.mul(z, z)
+ zz = zz.mul(z, z)
+ zz, z = z, zz
if v&mask != 0 {
- z = z.mul(z, x)
+ zz = zz.mul(z, x)
+ zz, z = z, zz
}
if m != nil {
- q, z = q.div(z, z, m)
+ zz, r = zz.div(r, z, m)
+ zz, r, q, z = q, z, zz, r
}
v <<= 1
@@ -1343,8 +1357,9 @@ func (n nat) probablyPrime(reps int) bool {
}
nm1 := nat(nil).sub(n, natOne)
- // 1<<k * q = nm1;
- q, k := nm1.powersOfTwoDecompose()
+ // determine q, k such that nm1 = q << k
+ k := nm1.trailingZeroBits()
+ q := nat(nil).shr(nm1, k)
nm3 := nat(nil).sub(nm1, natTwo)
rand := rand.New(rand.NewSource(int64(n[0])))
@@ -1360,7 +1375,7 @@ NextRandom:
if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 {
continue
}
- for j := 1; j < k; j++ {
+ for j := uint(1); j < k; j++ {
y = y.mul(y, y)
quotient, y = quotient.div(y, y, n)
if y.cmp(nm1) == 0 {
diff --git a/libgo/go/math/big/nat_test.go b/libgo/go/math/big/nat_test.go
index becde5d1719..68dd1a96d3c 100644
--- a/libgo/go/math/big/nat_test.go
+++ b/libgo/go/math/big/nat_test.go
@@ -6,6 +6,7 @@ package big
import (
"io"
+ "runtime"
"strings"
"testing"
)
@@ -62,6 +63,36 @@ var prodNN = []argNN{
{nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}},
{nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}},
{nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}},
+ // 3^100 * 3^28 = 3^128
+ {
+ natFromString("11790184577738583171520872861412518665678211592275841109096961"),
+ natFromString("515377520732011331036461129765621272702107522001"),
+ natFromString("22876792454961"),
+ },
+ // z = 111....1 (70000 digits)
+ // x = 10^(99*700) + ... + 10^1400 + 10^700 + 1
+ // y = 111....1 (700 digits, larger than Karatsuba threshold on 32-bit and 64-bit)
+ {
+ natFromString(strings.Repeat("1", 70000)),
+ natFromString("1" + strings.Repeat(strings.Repeat("0", 699)+"1", 99)),
+ natFromString(strings.Repeat("1", 700)),
+ },
+ // z = 111....1 (20000 digits)
+ // x = 10^10000 + 1
+ // y = 111....1 (10000 digits)
+ {
+ natFromString(strings.Repeat("1", 20000)),
+ natFromString("1" + strings.Repeat("0", 9999) + "1"),
+ natFromString(strings.Repeat("1", 10000)),
+ },
+}
+
+func natFromString(s string) nat {
+ x, _, err := nat(nil).scan(strings.NewReader(s), 0)
+ if err != nil {
+ panic(err)
+ }
+ return x
}
func TestSet(t *testing.T) {
@@ -135,26 +166,42 @@ func TestMulRangeN(t *testing.T) {
}
}
-var mulArg, mulTmp nat
-
-func init() {
- const n = 1000
- mulArg = make(nat, n)
- for i := 0; i < n; i++ {
- mulArg[i] = _M
+// allocBytes returns the number of bytes allocated by invoking f.
+func allocBytes(f func()) uint64 {
+ var stats runtime.MemStats
+ runtime.ReadMemStats(&stats)
+ t := stats.TotalAlloc
+ f()
+ runtime.ReadMemStats(&stats)
+ return stats.TotalAlloc - t
+}
+
+// TestMulUnbalanced tests that multiplying numbers of different lengths
+// does not cause deep recursion and in turn allocate too much memory.
+// Test case for issue 3807.
+func TestMulUnbalanced(t *testing.T) {
+ x := rndNat(50000)
+ y := rndNat(40)
+ allocSize := allocBytes(func() {
+ nat(nil).mul(x, y)
+ })
+ inputSize := uint64(len(x)+len(y)) * _S
+ if ratio := allocSize / uint64(inputSize); ratio > 10 {
+ t.Errorf("multiplication uses too much memory (%d > %d times the size of inputs)", allocSize, ratio)
}
}
-func benchmarkMulLoad() {
- for j := 1; j <= 10; j++ {
- x := mulArg[0 : j*100]
- mulTmp.mul(x, x)
- }
+func rndNat(n int) nat {
+ return nat(rndV(n)).norm()
}
func BenchmarkMul(b *testing.B) {
+ mulx := rndNat(1e4)
+ muly := rndNat(1e4)
+ b.ResetTimer()
for i := 0; i < b.N; i++ {
- benchmarkMulLoad()
+ var z nat
+ z.mul(mulx, muly)
}
}
@@ -616,14 +663,23 @@ func TestModW(t *testing.T) {
}
func TestTrailingZeroBits(t *testing.T) {
- var x Word
- x--
- for i := 0; i < _W; i++ {
- if trailingZeroBits(x) != i {
- t.Errorf("Failed at step %d: x: %x got: %d", i, x, trailingZeroBits(x))
+ x := Word(1)
+ for i := uint(0); i <= _W; i++ {
+ n := trailingZeroBits(x)
+ if n != i%_W {
+ t.Errorf("got trailingZeroBits(%#x) = %d; want %d", x, n, i%_W)
}
x <<= 1
}
+
+ y := nat(nil).set(natOne)
+ for i := uint(0); i <= 3*_W; i++ {
+ n := y.trailingZeroBits()
+ if n != i {
+ t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.string(lowercaseDigits[0:16]), n, i)
+ }
+ y = y.shl(y, 1)
+ }
}
var expNNTests = []struct {
diff --git a/libgo/go/math/big/rat.go b/libgo/go/math/big/rat.go
index 7bd83fc0fb2..eccf34e482f 100644
--- a/libgo/go/math/big/rat.go
+++ b/libgo/go/math/big/rat.go
@@ -16,8 +16,10 @@ import (
// A Rat represents a quotient a/b of arbitrary precision.
// The zero value for a Rat represents the value 0.
type Rat struct {
- a Int
- b nat // len(b) == 0 acts like b == 1
+ // To make zero values for Rat work w/o initialization,
+ // a zero value of b (len(b) == 0) acts like b == 1.
+ // a.neg determines the sign of the Rat, b.neg is ignored.
+ a, b Int
}
// NewRat creates a new Rat with numerator a and denominator b.
@@ -36,7 +38,7 @@ func (z *Rat) SetFrac(a, b *Int) *Rat {
babs = nat(nil).set(babs) // make a copy
}
z.a.abs = z.a.abs.set(a.abs)
- z.b = z.b.set(babs)
+ z.b.abs = z.b.abs.set(babs)
return z.norm()
}
@@ -50,21 +52,21 @@ func (z *Rat) SetFrac64(a, b int64) *Rat {
b = -b
z.a.neg = !z.a.neg
}
- z.b = z.b.setUint64(uint64(b))
+ z.b.abs = z.b.abs.setUint64(uint64(b))
return z.norm()
}
// SetInt sets z to x (by making a copy of x) and returns z.
func (z *Rat) SetInt(x *Int) *Rat {
z.a.Set(x)
- z.b = z.b.make(0)
+ z.b.abs = z.b.abs.make(0)
return z
}
// SetInt64 sets z to x and returns z.
func (z *Rat) SetInt64(x int64) *Rat {
z.a.SetInt64(x)
- z.b = z.b.make(0)
+ z.b.abs = z.b.abs.make(0)
return z
}
@@ -72,7 +74,7 @@ func (z *Rat) SetInt64(x int64) *Rat {
func (z *Rat) Set(x *Rat) *Rat {
if z != x {
z.a.Set(&x.a)
- z.b = z.b.set(x.b)
+ z.b.Set(&x.b)
}
return z
}
@@ -97,15 +99,15 @@ func (z *Rat) Inv(x *Rat) *Rat {
panic("division by zero")
}
z.Set(x)
- a := z.b
+ a := z.b.abs
if len(a) == 0 {
- a = a.setWord(1) // materialize numerator
+ a = a.set(natOne) // materialize numerator
}
b := z.a.abs
if b.cmp(natOne) == 0 {
b = b.make(0) // normalize denominator
}
- z.a.abs, z.b = a, b // sign doesn't change
+ z.a.abs, z.b.abs = a, b // sign doesn't change
return z
}
@@ -121,38 +123,26 @@ func (x *Rat) Sign() int {
// IsInt returns true if the denominator of x is 1.
func (x *Rat) IsInt() bool {
- return len(x.b) == 0 || x.b.cmp(natOne) == 0
+ return len(x.b.abs) == 0 || x.b.abs.cmp(natOne) == 0
}
// Num returns the numerator of x; it may be <= 0.
// The result is a reference to x's numerator; it
-// may change if a new value is assigned to x.
+// may change if a new value is assigned to x, and vice versa.
+// The sign of the numerator corresponds to the sign of x.
func (x *Rat) Num() *Int {
return &x.a
}
// Denom returns the denominator of x; it is always > 0.
// The result is a reference to x's denominator; it
-// may change if a new value is assigned to x.
+// may change if a new value is assigned to x, and vice versa.
func (x *Rat) Denom() *Int {
- if len(x.b) == 0 {
- return &Int{abs: nat{1}}
+ x.b.neg = false // the result is always >= 0
+ if len(x.b.abs) == 0 {
+ x.b.abs = x.b.abs.set(natOne) // materialize denominator
}
- return &Int{abs: x.b}
-}
-
-func gcd(x, y nat) nat {
- // Euclidean algorithm.
- var a, b nat
- a = a.set(x)
- b = b.set(y)
- for len(b) != 0 {
- var q, r nat
- _, r = q.div(r, a, b)
- a = b
- b = r
- }
- return a
+ return &x.b
}
func (z *Rat) norm() *Rat {
@@ -160,17 +150,25 @@ func (z *Rat) norm() *Rat {
case len(z.a.abs) == 0:
// z == 0 - normalize sign and denominator
z.a.neg = false
- z.b = z.b.make(0)
- case len(z.b) == 0:
+ z.b.abs = z.b.abs.make(0)
+ case len(z.b.abs) == 0:
// z is normalized int - nothing to do
- case z.b.cmp(natOne) == 0:
+ case z.b.abs.cmp(natOne) == 0:
// z is int - normalize denominator
- z.b = z.b.make(0)
+ z.b.abs = z.b.abs.make(0)
default:
- if f := gcd(z.a.abs, z.b); f.cmp(natOne) != 0 {
- z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f)
- z.b, _ = z.b.div(nil, z.b, f)
+ neg := z.a.neg
+ z.a.neg = false
+ z.b.neg = false
+ if f := NewInt(0).binaryGCD(&z.a, &z.b); f.Cmp(intOne) != 0 {
+ z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f.abs)
+ z.b.abs, _ = z.b.abs.div(nil, z.b.abs, f.abs)
+ if z.b.abs.cmp(natOne) == 0 {
+ // z is int - normalize denominator
+ z.b.abs = z.b.abs.make(0)
+ }
}
+ z.a.neg = neg
}
return z
}
@@ -207,31 +205,31 @@ func scaleDenom(x *Int, f nat) *Int {
// +1 if x > y
//
func (x *Rat) Cmp(y *Rat) int {
- return scaleDenom(&x.a, y.b).Cmp(scaleDenom(&y.a, x.b))
+ return scaleDenom(&x.a, y.b.abs).Cmp(scaleDenom(&y.a, x.b.abs))
}
// Add sets z to the sum x+y and returns z.
func (z *Rat) Add(x, y *Rat) *Rat {
- a1 := scaleDenom(&x.a, y.b)
- a2 := scaleDenom(&y.a, x.b)
+ a1 := scaleDenom(&x.a, y.b.abs)
+ a2 := scaleDenom(&y.a, x.b.abs)
z.a.Add(a1, a2)
- z.b = mulDenom(z.b, x.b, y.b)
+ z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
return z.norm()
}
// Sub sets z to the difference x-y and returns z.
func (z *Rat) Sub(x, y *Rat) *Rat {
- a1 := scaleDenom(&x.a, y.b)
- a2 := scaleDenom(&y.a, x.b)
+ a1 := scaleDenom(&x.a, y.b.abs)
+ a2 := scaleDenom(&y.a, x.b.abs)
z.a.Sub(a1, a2)
- z.b = mulDenom(z.b, x.b, y.b)
+ z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
return z.norm()
}
// Mul sets z to the product x*y and returns z.
func (z *Rat) Mul(x, y *Rat) *Rat {
z.a.Mul(&x.a, &y.a)
- z.b = mulDenom(z.b, x.b, y.b)
+ z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
return z.norm()
}
@@ -241,10 +239,10 @@ func (z *Rat) Quo(x, y *Rat) *Rat {
if len(y.a.abs) == 0 {
panic("division by zero")
}
- a := scaleDenom(&x.a, y.b)
- b := scaleDenom(&y.a, x.b)
+ a := scaleDenom(&x.a, y.b.abs)
+ b := scaleDenom(&y.a, x.b.abs)
z.a.abs = a.abs
- z.b = b.abs
+ z.b.abs = b.abs
z.a.neg = a.neg != b.neg
return z.norm()
}
@@ -286,7 +284,7 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
}
s = s[sep+1:]
var err error
- if z.b, _, err = z.b.scan(strings.NewReader(s), 10); err != nil {
+ if z.b.abs, _, err = z.b.abs.scan(strings.NewReader(s), 10); err != nil {
return nil, false
}
return z.norm(), true
@@ -317,11 +315,11 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
}
powTen := nat(nil).expNN(natTen, exp.abs, nil)
if exp.neg {
- z.b = powTen
+ z.b.abs = powTen
z.norm()
} else {
z.a.abs = z.a.abs.mul(z.a.abs, powTen)
- z.b = z.b.make(0)
+ z.b.abs = z.b.abs.make(0)
}
return z, true
@@ -330,8 +328,8 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
// String returns a string representation of z in the form "a/b" (even if b == 1).
func (x *Rat) String() string {
s := "/1"
- if len(x.b) != 0 {
- s = "/" + x.b.decimalString()
+ if len(x.b.abs) != 0 {
+ s = "/" + x.b.abs.decimalString()
}
return x.a.String() + s
}
@@ -355,9 +353,9 @@ func (x *Rat) FloatString(prec int) string {
}
return s
}
- // x.b != 0
+ // x.b.abs != 0
- q, r := nat(nil).div(nat(nil), x.a.abs, x.b)
+ q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
p := natOne
if prec > 0 {
@@ -365,11 +363,11 @@ func (x *Rat) FloatString(prec int) string {
}
r = r.mul(r, p)
- r, r2 := r.div(nat(nil), r, x.b)
+ r, r2 := r.div(nat(nil), r, x.b.abs)
// see if we need to round up
r2 = r2.add(r2, r2)
- if x.b.cmp(r2) <= 0 {
+ if x.b.abs.cmp(r2) <= 0 {
r = r.add(r, natOne)
if r.cmp(p) >= 0 {
q = nat(nil).add(q, natOne)
@@ -396,8 +394,8 @@ const ratGobVersion byte = 1
// GobEncode implements the gob.GobEncoder interface.
func (x *Rat) GobEncode() ([]byte, error) {
- buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
- i := x.b.bytes(buf)
+ buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
+ i := x.b.abs.bytes(buf)
j := x.a.abs.bytes(buf[0:i])
n := i - j
if int(uint32(n)) != n {
@@ -427,6 +425,6 @@ func (z *Rat) GobDecode(buf []byte) error {
i := j + binary.BigEndian.Uint32(buf[j-4:j])
z.a.neg = b&1 != 0
z.a.abs = z.a.abs.setBytes(buf[j:i])
- z.b = z.b.setBytes(buf[i:])
+ z.b.abs = z.b.abs.setBytes(buf[i:])
return nil
}
diff --git a/libgo/go/math/big/rat_test.go b/libgo/go/math/big/rat_test.go
index f7f31ae1a20..7c634233ff8 100644
--- a/libgo/go/math/big/rat_test.go
+++ b/libgo/go/math/big/rat_test.go
@@ -387,30 +387,19 @@ func TestRatGobEncoding(t *testing.T) {
var medium bytes.Buffer
enc := gob.NewEncoder(&medium)
dec := gob.NewDecoder(&medium)
- for i, test := range gobEncodingTests {
- for j := 0; j < 4; j++ {
- medium.Reset() // empty buffer for each test case (in case of failures)
- stest := test
- if j&1 != 0 {
- // negative numbers
- stest = "-" + test
- }
- if j%2 != 0 {
- // fractions
- stest = stest + "." + test
- }
- var tx Rat
- tx.SetString(stest)
- if err := enc.Encode(&tx); err != nil {
- t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
- }
- var rx Rat
- if err := dec.Decode(&rx); err != nil {
- t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
- }
- if rx.Cmp(&tx) != 0 {
- t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
- }
+ for _, test := range encodingTests {
+ medium.Reset() // empty buffer for each test case (in case of failures)
+ var tx Rat
+ tx.SetString(test + ".14159265")
+ if err := enc.Encode(&tx); err != nil {
+ t.Errorf("encoding of %s failed: %s", &tx, err)
+ }
+ var rx Rat
+ if err := dec.Decode(&rx); err != nil {
+ t.Errorf("decoding of %s failed: %s", &tx, err)
+ }
+ if rx.Cmp(&tx) != 0 {
+ t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
}
}
}
@@ -454,3 +443,56 @@ func TestIssue2379(t *testing.T) {
t.Errorf("5) got %s want %s", x, q)
}
}
+
+func TestIssue3521(t *testing.T) {
+ a := new(Int)
+ b := new(Int)
+ a.SetString("64375784358435883458348587", 0)
+ b.SetString("4789759874531", 0)
+
+ // 0) a raw zero value has 1 as denominator
+ zero := new(Rat)
+ one := NewInt(1)
+ if zero.Denom().Cmp(one) != 0 {
+ t.Errorf("0) got %s want %s", zero.Denom(), one)
+ }
+
+ // 1a) a zero value remains zero independent of denominator
+ x := new(Rat)
+ x.Denom().Set(new(Int).Neg(b))
+ if x.Cmp(zero) != 0 {
+ t.Errorf("1a) got %s want %s", x, zero)
+ }
+
+ // 1b) a zero value may have a denominator != 0 and != 1
+ x.Num().Set(a)
+ qab := new(Rat).SetFrac(a, b)
+ if x.Cmp(qab) != 0 {
+ t.Errorf("1b) got %s want %s", x, qab)
+ }
+
+ // 2a) an integral value becomes a fraction depending on denominator
+ x.SetFrac64(10, 2)
+ x.Denom().SetInt64(3)
+ q53 := NewRat(5, 3)
+ if x.Cmp(q53) != 0 {
+ t.Errorf("2a) got %s want %s", x, q53)
+ }
+
+ // 2b) an integral value becomes a fraction depending on denominator
+ x = NewRat(10, 2)
+ x.Denom().SetInt64(3)
+ if x.Cmp(q53) != 0 {
+ t.Errorf("2b) got %s want %s", x, q53)
+ }
+
+ // 3) changing the numerator/denominator of a Rat changes the Rat
+ x.SetFrac(a, b)
+ a = x.Num()
+ b = x.Denom()
+ a.SetInt64(5)
+ b.SetInt64(3)
+ if x.Cmp(q53) != 0 {
+ t.Errorf("3) got %s want %s", x, q53)
+ }
+}
diff --git a/libgo/go/math/cbrt.go b/libgo/go/math/cbrt.go
index 8c43f0afbc8..272e3092310 100644
--- a/libgo/go/math/cbrt.go
+++ b/libgo/go/math/cbrt.go
@@ -12,7 +12,7 @@ package math
(http://www.jstor.org/stable/2006387?seq=9, accessed 11-Feb-2010)
*/
-// Cbrt returns the cube root of its argument.
+// Cbrt returns the cube root of x.
//
// Special cases are:
// Cbrt(±0) = ±0
diff --git a/libgo/go/math/copysign.go b/libgo/go/math/copysign.go
index ee65456a1ce..719c64b9eba 100644
--- a/libgo/go/math/copysign.go
+++ b/libgo/go/math/copysign.go
@@ -4,7 +4,7 @@
package math
-// Copysign(x, y) returns a value with the magnitude
+// Copysign returns a value with the magnitude
// of x and the sign of y.
func Copysign(x, y float64) float64 {
const sign = 1 << 63
diff --git a/libgo/go/math/erf.go b/libgo/go/math/erf.go
index c6f32bdbe28..4cd80f80c3b 100644
--- a/libgo/go/math/erf.go
+++ b/libgo/go/math/erf.go
@@ -179,7 +179,7 @@ const (
sb7 = -2.24409524465858183362e+01 // 0xC03670E242712D62
)
-// Erf(x) returns the error function of x.
+// Erf returns the error function of x.
//
// Special cases are:
// Erf(+Inf) = 1
@@ -256,7 +256,7 @@ func Erf(x float64) float64 {
return 1 - r/x
}
-// Erfc(x) returns the complementary error function of x.
+// Erfc returns the complementary error function of x.
//
// Special cases are:
// Erfc(+Inf) = 0
diff --git a/libgo/go/math/gamma.go b/libgo/go/math/gamma.go
index 7c6f421bad1..164f54f332b 100644
--- a/libgo/go/math/gamma.go
+++ b/libgo/go/math/gamma.go
@@ -110,19 +110,26 @@ func stirling(x float64) float64 {
return y
}
-// Gamma(x) returns the Gamma function of x.
+// Gamma returns the Gamma function of x.
//
// Special cases are:
-// Gamma(±Inf) = ±Inf
+// Gamma(+Inf) = +Inf
+// Gamma(+0) = +Inf
+// Gamma(-0) = -Inf
+// Gamma(x) = NaN for integer x < 0
+// Gamma(-Inf) = NaN
// Gamma(NaN) = NaN
-// Large values overflow to +Inf.
-// Zero and negative integer arguments return ±Inf.
func Gamma(x float64) float64 {
const Euler = 0.57721566490153286060651209008240243104215933593992 // A001620
// special cases
switch {
- case IsInf(x, -1) || IsNaN(x):
- return x
+ case isNegInt(x) || IsInf(x, -1) || IsNaN(x):
+ return NaN()
+ case x == 0:
+ if Signbit(x) {
+ return Inf(-1)
+ }
+ return Inf(1)
case x < -170.5674972726612 || x > 171.61447887182298:
return Inf(1)
}
@@ -185,3 +192,11 @@ small:
}
return z / ((1 + Euler*x) * x)
}
+
+func isNegInt(x float64) bool {
+ if x < 0 {
+ _, xf := Modf(x)
+ return xf == 0
+ }
+ return false
+}
diff --git a/libgo/go/math/hypot.go b/libgo/go/math/hypot.go
index 57d8e343720..a6fa84c7655 100644
--- a/libgo/go/math/hypot.go
+++ b/libgo/go/math/hypot.go
@@ -8,7 +8,7 @@ package math
Hypot -- sqrt(p*p + q*q), but overflows only if the result does.
*/
-// Hypot computes Sqrt(p*p + q*q), taking care to avoid
+// Hypot returns Sqrt(p*p + q*q), taking care to avoid
// unnecessary overflow and underflow.
//
// Special cases are:
diff --git a/libgo/go/math/logb.go b/libgo/go/math/logb.go
index d32f9f1000c..f2769d4fd75 100644
--- a/libgo/go/math/logb.go
+++ b/libgo/go/math/logb.go
@@ -4,7 +4,7 @@
package math
-// Logb(x) returns the binary exponent of x.
+// Logb returns the binary exponent of x.
//
// Special cases are:
// Logb(±Inf) = +Inf
@@ -23,7 +23,7 @@ func Logb(x float64) float64 {
return float64(ilogb(x))
}
-// Ilogb(x) returns the binary exponent of x as an integer.
+// Ilogb returns the binary exponent of x as an integer.
//
// Special cases are:
// Ilogb(±Inf) = MaxInt32
diff --git a/libgo/go/math/rand/rand_test.go b/libgo/go/math/rand/rand_test.go
index bbd44e3f8b1..4d3abdb606c 100644
--- a/libgo/go/math/rand/rand_test.go
+++ b/libgo/go/math/rand/rand_test.go
@@ -57,16 +57,13 @@ func (this *statsResults) checkSimilarDistribution(expected *statsResults) error
func getStatsResults(samples []float64) *statsResults {
res := new(statsResults)
- var sum float64
- for i := range samples {
- sum += samples[i]
+ var sum, squaresum float64
+ for _, s := range samples {
+ sum += s
+ squaresum += s * s
}
res.mean = sum / float64(len(samples))
- var devsum float64
- for i := range samples {
- devsum += math.Pow(samples[i]-res.mean, 2)
- }
- res.stddev = math.Sqrt(devsum / float64(len(samples)))
+ res.stddev = math.Sqrt(squaresum/float64(len(samples)) - res.mean*res.mean)
return res
}
diff --git a/libgo/go/math/sincos.go b/libgo/go/math/sincos.go
index 75e6e7541e6..b3a2f8a8619 100644
--- a/libgo/go/math/sincos.go
+++ b/libgo/go/math/sincos.go
@@ -6,7 +6,7 @@ package math
// Coefficients _sin[] and _cos[] are found in pkg/math/sin.go.
-// Sincos(x) returns Sin(x), Cos(x).
+// Sincos returns Sin(x), Cos(x).
//
// Special cases are:
// Sincos(±0) = ±0, 1
diff --git a/libgo/go/math/tanh.go b/libgo/go/math/tanh.go
index 03a641b4da0..7305be66c7f 100644
--- a/libgo/go/math/tanh.go
+++ b/libgo/go/math/tanh.go
@@ -4,12 +4,66 @@
package math
-/*
- Floating-point hyperbolic tangent.
+// The original C code, the long comment, and the constants
+// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
+// available from http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a simplified version of the original C.
+// tanh.c
+//
+// Hyperbolic tangent
+//
+// SYNOPSIS:
+//
+// double x, y, tanh();
+//
+// y = tanh( x );
+//
+// DESCRIPTION:
+//
+// Returns hyperbolic tangent of argument in the range MINLOG to MAXLOG.
+// MAXLOG = 8.8029691931113054295988e+01 = log(2**127)
+// MINLOG = -8.872283911167299960540e+01 = log(2**-128)
+//
+// A rational function is used for |x| < 0.625. The form
+// x + x**3 P(x)/Q(x) of Cody & Waite is employed.
+// Otherwise,
+// tanh(x) = sinh(x)/cosh(x) = 1 - 2/(exp(2x) + 1).
+//
+// ACCURACY:
+//
+// Relative error:
+// arithmetic domain # trials peak rms
+// IEEE -2,2 30000 2.5e-16 5.8e-17
+//
+// Cephes Math Library Release 2.8: June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+// Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+// The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+// Stephen L. Moshier
+// moshier@na-net.ornl.gov
+//
- Sinh and Cosh are called except for large arguments, which
- would cause overflow improperly.
-*/
+var tanhP = [...]float64{
+ -9.64399179425052238628E-1,
+ -9.92877231001918586564E1,
+ -1.61468768441708447952E3,
+}
+var tanhQ = [...]float64{
+ 1.12811678491632931402E2,
+ 2.23548839060100448583E3,
+ 4.84406305325125486048E3,
+}
// Tanh computes the hyperbolic tangent of x.
//
@@ -18,15 +72,26 @@ package math
// Tanh(±Inf) = ±1
// Tanh(NaN) = NaN
func Tanh(x float64) float64 {
- if x < 0 {
- x = -x
- if x > 21 {
+ const MAXLOG = 8.8029691931113054295988e+01 // log(2**127)
+ z := Abs(x)
+ switch {
+ case z > 0.5*MAXLOG:
+ if x < 0 {
return -1
}
- return -Sinh(x) / Cosh(x)
- }
- if x > 21 {
return 1
+ case z >= 0.625:
+ s := Exp(2 * z)
+ z = 1 - 2/(s+1)
+ if x < 0 {
+ z = -z
+ }
+ default:
+ if x == 0 {
+ return x
+ }
+ s := x * x
+ z = x + x*s*((tanhP[0]*s+tanhP[1])*s+tanhP[2])/(((s+tanhQ[0])*s+tanhQ[1])*s+tanhQ[2])
}
- return Sinh(x) / Cosh(x)
+ return z
}
diff --git a/libgo/go/mime/type_windows.go b/libgo/go/mime/type_windows.go
index bc388893b48..857db5f41d7 100644
--- a/libgo/go/mime/type_windows.go
+++ b/libgo/go/mime/type_windows.go
@@ -11,7 +11,8 @@ import (
func initMime() {
var root syscall.Handle
- if syscall.RegOpenKeyEx(syscall.HKEY_CLASSES_ROOT, syscall.StringToUTF16Ptr(`\`),
+ rootpathp, _ := syscall.UTF16PtrFromString(`\`)
+ if syscall.RegOpenKeyEx(syscall.HKEY_CLASSES_ROOT, rootpathp,
0, syscall.KEY_READ, &root) != nil {
return
}
@@ -31,15 +32,17 @@ func initMime() {
continue
}
var h syscall.Handle
+ extpathp, _ := syscall.UTF16PtrFromString(`\` + ext)
if syscall.RegOpenKeyEx(
- syscall.HKEY_CLASSES_ROOT, syscall.StringToUTF16Ptr(`\`+ext),
+ syscall.HKEY_CLASSES_ROOT, extpathp,
0, syscall.KEY_READ, &h) != nil {
continue
}
var typ uint32
n = uint32(len(buf) * 2) // api expects array of bytes, not uint16
+ contenttypep, _ := syscall.UTF16PtrFromString("Content Type")
if syscall.RegQueryValueEx(
- h, syscall.StringToUTF16Ptr("Content Type"),
+ h, contenttypep,
nil, &typ, (*byte)(unsafe.Pointer(&buf[0])), &n) != nil {
syscall.RegCloseKey(h)
continue
diff --git a/libgo/go/net/cgo_bsd.go b/libgo/go/net/cgo_bsd.go
index b8c6ef974e4..27c3e9acb94 100644
--- a/libgo/go/net/cgo_bsd.go
+++ b/libgo/go/net/cgo_bsd.go
@@ -12,6 +12,6 @@ package net
import "syscall"
-func cgoAddrInfoMask() int {
- return syscall.AI_MASK
+func cgoAddrInfoFlags() int {
+ return (syscall.AI_CANONNAME | syscall.AI_V4MAPPED | syscall.AI_ALL) & syscall.AI_MASK
}
diff --git a/libgo/go/net/cgo_linux.go b/libgo/go/net/cgo_linux.go
index 482435221e0..650575cce6c 100644
--- a/libgo/go/net/cgo_linux.go
+++ b/libgo/go/net/cgo_linux.go
@@ -10,6 +10,12 @@ package net
import "syscall"
-func cgoAddrInfoMask() int {
+func cgoAddrInfoFlags() int {
+ // NOTE(rsc): In theory there are approximately balanced
+ // arguments for and against including AI_ADDRCONFIG
+ // in the flags (it includes IPv4 results only on IPv4 systems,
+ // and similarly for IPv6), but in practice setting it causes
+ // getaddrinfo to return the wrong canonical name on Linux.
+ // So definitely leave it out.
return syscall.AI_CANONNAME | syscall.AI_V4MAPPED | syscall.AI_ALL
}
diff --git a/libgo/go/net/cgo_netbsd.go b/libgo/go/net/cgo_netbsd.go
new file mode 100644
index 00000000000..27334af641a
--- /dev/null
+++ b/libgo/go/net/cgo_netbsd.go
@@ -0,0 +1,14 @@
+// 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 net
+
+/*
+#include <netdb.h>
+*/
+import "C"
+
+func cgoAddrInfoFlags() int {
+ return C.AI_CANONNAME
+}
diff --git a/libgo/go/net/cgo_unix.go b/libgo/go/net/cgo_unix.go
index 6751b8cc0e5..69daedcdf85 100644
--- a/libgo/go/net/cgo_unix.go
+++ b/libgo/go/net/cgo_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux
+// +build darwin freebsd linux netbsd
package net
@@ -102,13 +102,7 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, complet
var res *syscall.Addrinfo
var hints syscall.Addrinfo
- // NOTE(rsc): In theory there are approximately balanced
- // arguments for and against including AI_ADDRCONFIG
- // in the flags (it includes IPv4 results only on IPv4 systems,
- // and similarly for IPv6), but in practice setting it causes
- // getaddrinfo to return the wrong canonical name on Linux.
- // So definitely leave it out.
- hints.Ai_flags = int32((syscall.AI_ALL | syscall.AI_V4MAPPED | syscall.AI_CANONNAME) & cgoAddrInfoMask())
+ hints.Ai_flags = int32(cgoAddrInfoFlags())
h := syscall.StringBytePtr(name)
syscall.Entersyscall()
diff --git a/libgo/go/net/dial.go b/libgo/go/net/dial.go
index 51912397a46..752f81b618c 100644
--- a/libgo/go/net/dial.go
+++ b/libgo/go/net/dial.go
@@ -81,7 +81,7 @@ func resolveNetAddr(op, net, addr string) (afnet string, a Addr, err error) {
// Dial("tcp", "google.com:80")
// Dial("tcp", "[de:ad:be:ef::ca:fe]:80")
//
-// For IP networks, addr must be "ip", "ip4" or "ip6" followed
+// For IP networks, net must be "ip", "ip4" or "ip6" followed
// by a colon and a protocol number or name.
//
// Examples:
diff --git a/libgo/go/net/dial_test.go b/libgo/go/net/dial_test.go
index 63b91b37ead..abd6b7fe920 100644
--- a/libgo/go/net/dial_test.go
+++ b/libgo/go/net/dial_test.go
@@ -130,7 +130,7 @@ func TestSelfConnect(t *testing.T) {
n = 1000
}
switch runtime.GOOS {
- case "darwin", "freebsd", "openbsd", "solaris", "windows":
+ case "darwin", "freebsd", "netbsd", "openbsd", "plan9", "solaris", "windows":
// Non-Linux systems take a long time to figure
// out that there is nothing listening on localhost.
n = 100
diff --git a/libgo/go/net/dialgoogle_test.go b/libgo/go/net/dialgoogle_test.go
index 03c4499720f..426e2ffb001 100644
--- a/libgo/go/net/dialgoogle_test.go
+++ b/libgo/go/net/dialgoogle_test.go
@@ -41,17 +41,6 @@ func doDial(t *testing.T, network, addr string) {
fd.Close()
}
-func TestLookupCNAME(t *testing.T) {
- if testing.Short() || !*testExternal {
- t.Logf("skipping test to avoid external network")
- return
- }
- cname, err := LookupCNAME("www.google.com")
- if !strings.HasSuffix(cname, ".l.google.com.") || err != nil {
- t.Errorf(`LookupCNAME("www.google.com.") = %q, %v, want "*.l.google.com.", nil`, cname, err)
- }
-}
-
var googleaddrsipv4 = []string{
"%d.%d.%d.%d:80",
"www.google.com:80",
diff --git a/libgo/go/net/dnsclient_unix.go b/libgo/go/net/dnsclient_unix.go
index 18c39360e40..9e21bb4a0f6 100644
--- a/libgo/go/net/dnsclient_unix.go
+++ b/libgo/go/net/dnsclient_unix.go
@@ -237,24 +237,30 @@ func goLookupIP(name string) (addrs []IP, err error) {
}
var records []dnsRR
var cname string
- cname, records, err = lookup(name, dnsTypeA)
- if err != nil {
- return
- }
+ var err4, err6 error
+ cname, records, err4 = lookup(name, dnsTypeA)
addrs = convertRR_A(records)
if cname != "" {
name = cname
}
- _, records, err = lookup(name, dnsTypeAAAA)
- if err != nil && len(addrs) > 0 {
- // Ignore error because A lookup succeeded.
- err = nil
+ _, records, err6 = lookup(name, dnsTypeAAAA)
+ if err4 != nil && err6 == nil {
+ // Ignore A error because AAAA lookup succeeded.
+ err4 = nil
}
- if err != nil {
- return
+ if err6 != nil && len(addrs) > 0 {
+ // Ignore AAAA error because A lookup succeeded.
+ err6 = nil
}
+ if err4 != nil {
+ return nil, err4
+ }
+ if err6 != nil {
+ return nil, err6
+ }
+
addrs = append(addrs, convertRR_AAAA(records)...)
- return
+ return addrs, nil
}
// goLookupCNAME is the native Go implementation of LookupCNAME.
diff --git a/libgo/go/net/dnsconfig.go b/libgo/go/net/dnsconfig_unix.go
index bb46cc9007c..bb46cc9007c 100644
--- a/libgo/go/net/dnsconfig.go
+++ b/libgo/go/net/dnsconfig_unix.go
diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd_unix.go
index ff4f4f899e5..c55f3362f05 100644
--- a/libgo/go/net/fd.go
+++ b/libgo/go/net/fd_unix.go
@@ -10,6 +10,7 @@ import (
"errors"
"io"
"os"
+ "runtime"
"sync"
"syscall"
"time"
@@ -45,36 +46,16 @@ type netFD struct {
// owned by fd wait server
ncr, ncw int
+
+ // wait server
+ pollServer *pollServer
}
// A pollServer helps FDs determine when to retry a non-blocking
// read or write after they get EAGAIN. When an FD needs to wait,
-// send the fd on s.cr (for a read) or s.cw (for a write) to pass the
-// request to the poll server. Then receive on fd.cr/fd.cw.
+// call s.WaitRead() or s.WaitWrite() to pass the request to the poll server.
// When the pollServer finds that i/o on FD should be possible
-// again, it will send fd on fd.cr/fd.cw to wake any waiting processes.
-// This protocol is implemented as s.WaitRead() and s.WaitWrite().
-//
-// There is one subtlety: when sending on s.cr/s.cw, the
-// poll server is probably in a system call, waiting for an fd
-// to become ready. It's not looking at the request channels.
-// To resolve this, the poll server waits not just on the FDs it has
-// been given but also its own pipe. After sending on the
-// buffered channel s.cr/s.cw, WaitRead/WaitWrite writes a
-// byte to the pipe, causing the pollServer's poll system call to
-// return. In response to the pipe being readable, the pollServer
-// re-polls its request channels.
-//
-// Note that the ordering is "send request" and then "wake up server".
-// If the operations were reversed, there would be a race: the poll
-// server might wake up and look at the request channel, see that it
-// was empty, and go back to sleep, all before the requester managed
-// to send the request. Because the send must complete before the wakeup,
-// the request channel must be buffered. A buffer of size 1 is sufficient
-// for any request load. If many processes are trying to submit requests,
-// one will succeed, the pollServer will read the request, and then the
-// channel will be empty for the next process's request. A larger buffer
-// might help batch requests.
+// again, it will send on fd.cr/fd.cw to wake any waiting goroutines.
//
// To avoid races in closing, all fd operations are locked and
// refcounted. when netFD.Close() is called, it calls syscall.Shutdown
@@ -82,7 +63,6 @@ type netFD struct {
// will the fd be closed.
type pollServer struct {
- cr, cw chan *netFD // buffered >= 1
pr, pw *os.File
poll *pollster // low-level OS hooks
sync.Mutex // controls pending and deadline
@@ -279,21 +259,45 @@ func (s *pollServer) WaitWrite(fd *netFD) error {
}
// Network FD methods.
-// All the network FDs use a single pollServer.
+// Spread network FDs over several pollServers.
-var pollserver *pollServer
-var onceStartServer sync.Once
+var pollMaxN int
+var pollservers []*pollServer
+var startServersOnce []func()
+
+func init() {
+ pollMaxN = runtime.NumCPU()
+ if pollMaxN > 8 {
+ pollMaxN = 8 // No improvement then.
+ }
+ pollservers = make([]*pollServer, pollMaxN)
+ startServersOnce = make([]func(), pollMaxN)
+ for i := 0; i < pollMaxN; i++ {
+ k := i
+ once := new(sync.Once)
+ startServersOnce[i] = func() { once.Do(func() { startServer(k) }) }
+ }
+}
-func startServer() {
+func startServer(k int) {
p, err := newPollServer()
if err != nil {
- print("Start pollServer: ", err.Error(), "\n")
+ panic(err)
+ }
+ pollservers[k] = p
+}
+
+func server(fd int) *pollServer {
+ pollN := runtime.GOMAXPROCS(0)
+ if pollN > pollMaxN {
+ pollN = pollMaxN
}
- pollserver = p
+ k := fd % pollN
+ startServersOnce[k]()
+ return pollservers[k]
}
func newFD(fd, family, sotype int, net string) (*netFD, error) {
- onceStartServer.Do(startServer)
if err := syscall.SetNonblock(fd, true); err != nil {
return nil, err
}
@@ -305,6 +309,7 @@ func newFD(fd, family, sotype int, net string) (*netFD, error) {
}
netfd.cr = make(chan error, 1)
netfd.cw = make(chan error, 1)
+ netfd.pollServer = server(fd)
return netfd, nil
}
@@ -324,7 +329,7 @@ func (fd *netFD) setAddr(laddr, raddr Addr) {
func (fd *netFD) connect(ra syscall.Sockaddr) error {
err := syscall.Connect(fd.sysfd, ra)
if err == syscall.EINPROGRESS {
- if err = pollserver.WaitWrite(fd); err != nil {
+ if err = fd.pollServer.WaitWrite(fd); err != nil {
return err
}
var e int
@@ -378,8 +383,8 @@ func (fd *netFD) decref() {
}
func (fd *netFD) Close() error {
- pollserver.Lock() // needed for both fd.incref(true) and pollserver.Evict
- defer pollserver.Unlock()
+ fd.pollServer.Lock() // needed for both fd.incref(true) and pollserver.Evict
+ defer fd.pollServer.Unlock()
if err := fd.incref(true); err != nil {
return err
}
@@ -388,7 +393,7 @@ func (fd *netFD) Close() error {
// the final decref will close fd.sysfd. This should happen
// fairly quickly, since all the I/O is non-blocking, and any
// attempts to block in the pollserver will return errClosing.
- pollserver.Evict(fd)
+ fd.pollServer.Evict(fd)
fd.decref()
return nil
}
@@ -425,7 +430,7 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
if err == syscall.EAGAIN {
err = errTimeout
if fd.rdeadline >= 0 {
- if err = pollserver.WaitRead(fd); err == nil {
+ if err = fd.pollServer.WaitRead(fd); err == nil {
continue
}
}
@@ -455,7 +460,7 @@ func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
if err == syscall.EAGAIN {
err = errTimeout
if fd.rdeadline >= 0 {
- if err = pollserver.WaitRead(fd); err == nil {
+ if err = fd.pollServer.WaitRead(fd); err == nil {
continue
}
}
@@ -483,7 +488,7 @@ func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
if err == syscall.EAGAIN {
err = errTimeout
if fd.rdeadline >= 0 {
- if err = pollserver.WaitRead(fd); err == nil {
+ if err = fd.pollServer.WaitRead(fd); err == nil {
continue
}
}
@@ -525,7 +530,7 @@ func (fd *netFD) Write(p []byte) (int, error) {
if err == syscall.EAGAIN {
err = errTimeout
if fd.wdeadline >= 0 {
- if err = pollserver.WaitWrite(fd); err == nil {
+ if err = fd.pollServer.WaitWrite(fd); err == nil {
continue
}
}
@@ -557,7 +562,7 @@ func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
if err == syscall.EAGAIN {
err = errTimeout
if fd.wdeadline >= 0 {
- if err = pollserver.WaitWrite(fd); err == nil {
+ if err = fd.pollServer.WaitWrite(fd); err == nil {
continue
}
}
@@ -584,7 +589,7 @@ func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
if err == syscall.EAGAIN {
err = errTimeout
if fd.wdeadline >= 0 {
- if err = pollserver.WaitWrite(fd); err == nil {
+ if err = fd.pollServer.WaitWrite(fd); err == nil {
continue
}
}
@@ -606,7 +611,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err e
}
defer fd.decref()
- // See ../syscall/exec.go for description of ForkLock.
+ // See ../syscall/exec_unix.go for description of ForkLock.
// It is okay to hold the lock across syscall.Accept
// because we have put fd.sysfd into non-blocking mode.
var s int
@@ -619,7 +624,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err e
if err == syscall.EAGAIN {
err = errTimeout
if fd.rdeadline >= 0 {
- if err = pollserver.WaitRead(fd); err == nil {
+ if err = fd.pollServer.WaitRead(fd); err == nil {
continue
}
}
@@ -636,7 +641,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err e
syscall.ForkLock.RUnlock()
if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
- syscall.Close(s)
+ closesocket(s)
return nil, err
}
lsa, _ := syscall.Getsockname(netfd.sysfd)
diff --git a/libgo/go/net/fd_windows.go b/libgo/go/net/fd_windows.go
index 45f5c2d882f..4ae78397c33 100644
--- a/libgo/go/net/fd_windows.go
+++ b/libgo/go/net/fd_windows.go
@@ -524,7 +524,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
defer fd.decref()
// Get new socket.
- // See ../syscall/exec.go for description of ForkLock.
+ // See ../syscall/exec_unix.go for description of ForkLock.
syscall.ForkLock.RLock()
s, err := syscall.Socket(fd.family, fd.sotype, 0)
if err != nil {
diff --git a/libgo/go/net/file.go b/libgo/go/net/file_unix.go
index 837326e12e6..0a640801779 100644
--- a/libgo/go/net/file.go
+++ b/libgo/go/net/file_unix.go
@@ -29,8 +29,8 @@ func newFileFD(f *os.File) (*netFD, error) {
family := syscall.AF_UNSPEC
toAddr := sockaddrToTCP
- sa, _ := syscall.Getsockname(fd)
- switch sa.(type) {
+ lsa, _ := syscall.Getsockname(fd)
+ switch lsa.(type) {
default:
closesocket(fd)
return nil, syscall.EINVAL
@@ -57,9 +57,9 @@ func newFileFD(f *os.File) (*netFD, error) {
toAddr = sockaddrToUnixpacket
}
}
- laddr := toAddr(sa)
- sa, _ = syscall.Getpeername(fd)
- raddr := toAddr(sa)
+ laddr := toAddr(lsa)
+ rsa, _ := syscall.Getpeername(fd)
+ raddr := toAddr(rsa)
netfd, err := newFD(fd, family, sotype, laddr.Network())
if err != nil {
@@ -84,10 +84,10 @@ func FileConn(f *os.File) (c Conn, err error) {
return newTCPConn(fd), nil
case *UDPAddr:
return newUDPConn(fd), nil
- case *UnixAddr:
- return newUnixConn(fd), nil
case *IPAddr:
return newIPConn(fd), nil
+ case *UnixAddr:
+ return newUnixConn(fd), nil
}
fd.Close()
return nil, syscall.EINVAL
diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go
index 89441424e1d..02891db9adc 100644
--- a/libgo/go/net/http/client.go
+++ b/libgo/go/net/http/client.go
@@ -33,10 +33,11 @@ type Client struct {
// CheckRedirect specifies the policy for handling redirects.
// If CheckRedirect is not nil, the client calls it before
- // following an HTTP redirect. The arguments req and via
- // are the upcoming request and the requests made already,
- // oldest first. If CheckRedirect returns an error, the client
- // returns that error (wrapped in a url.Error) instead of
+ // following an HTTP redirect. The arguments req and via are
+ // the upcoming request and the requests made already, oldest
+ // first. If CheckRedirect returns an error, the Client's Get
+ // method returns both the previous Response and
+ // CheckRedirect's error (wrapped in a url.Error) instead of
// issuing the Request req.
//
// If CheckRedirect is nil, the Client uses its default policy,
@@ -95,7 +96,7 @@ type readClose struct {
//
// When err is nil, resp always contains a non-nil resp.Body.
//
-// Callers should close res.Body when done reading from it. If
+// Callers should close resp.Body when done reading from it. If
// resp.Body is not closed, the Client's underlying RoundTripper
// (typically Transport) may not be able to re-use a persistent TCP
// connection to the server for a subsequent "keep-alive" request.
@@ -221,6 +222,7 @@ func (c *Client) doFollowingRedirects(ireq *Request) (resp *Response, err error)
req := ireq
urlStr := "" // next relative or absolute URL to fetch (after first request)
+ redirectFailed := false
for redirect := 0; ; redirect++ {
if redirect != 0 {
req = new(Request)
@@ -239,6 +241,7 @@ func (c *Client) doFollowingRedirects(ireq *Request) (resp *Response, err error)
err = redirectChecker(req, via)
if err != nil {
+ redirectFailed = true
break
}
}
@@ -268,16 +271,24 @@ func (c *Client) doFollowingRedirects(ireq *Request) (resp *Response, err error)
return
}
- if resp != nil {
- resp.Body.Close()
- }
-
method := ireq.Method
- return nil, &url.Error{
+ urlErr := &url.Error{
Op: method[0:1] + strings.ToLower(method[1:]),
URL: urlStr,
Err: err,
}
+
+ if redirectFailed {
+ // Special case for Go 1 compatibility: return both the response
+ // and an error if the CheckRedirect function failed.
+ // See http://golang.org/issue/3795
+ return resp, urlErr
+ }
+
+ if resp != nil {
+ resp.Body.Close()
+ }
+ return nil, urlErr
}
func defaultCheckRedirect(req *Request, via []*Request) error {
diff --git a/libgo/go/net/http/client_test.go b/libgo/go/net/http/client_test.go
index 09fcc1c0b40..c61b17d289b 100644
--- a/libgo/go/net/http/client_test.go
+++ b/libgo/go/net/http/client_test.go
@@ -235,6 +235,12 @@ func TestRedirects(t *testing.T) {
if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr {
t.Errorf("with redirects forbidden, expected a *url.Error with our 'no redirects allowed' error inside; got %#v (%q)", err, err)
}
+ if res == nil {
+ t.Fatalf("Expected a non-nil Response on CheckRedirect failure (http://golang.org/issue/3795)")
+ }
+ if res.Header.Get("Location") == "" {
+ t.Errorf("no Location header in Response")
+ }
}
var expectedCookies = []*Cookie{
diff --git a/libgo/go/net/http/cookie.go b/libgo/go/net/http/cookie.go
index 2e30bbff177..43f519d1fba 100644
--- a/libgo/go/net/http/cookie.go
+++ b/libgo/go/net/http/cookie.go
@@ -258,10 +258,5 @@ func parseCookieValueUsing(raw string, validByte func(byte) bool) (string, bool)
}
func isCookieNameValid(raw string) bool {
- for _, c := range raw {
- if !isToken(byte(c)) {
- return false
- }
- }
- return true
+ return strings.IndexFunc(raw, isNotToken) < 0
}
diff --git a/libgo/go/net/http/fs.go b/libgo/go/net/http/fs.go
index 208d6cabb2c..b6bea0dfaad 100644
--- a/libgo/go/net/http/fs.go
+++ b/libgo/go/net/http/fs.go
@@ -100,6 +100,9 @@ func dirList(w ResponseWriter, f File) {
// The content's Seek method must work: ServeContent uses
// a seek to the end of the content to determine its size.
//
+// If the caller has set w's ETag header, ServeContent uses it to
+// handle requests using If-Range and If-None-Match.
+//
// Note that *os.File implements the io.ReadSeeker interface.
func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker) {
size, err := content.Seek(0, os.SEEK_END)
@@ -122,6 +125,10 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
if checkLastModified(w, r, modtime) {
return
}
+ rangeReq, done := checkETag(w, r)
+ if done {
+ return
+ }
code := StatusOK
@@ -148,7 +155,7 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
sendSize := size
var sendContent io.Reader = content
if size >= 0 {
- ranges, err := parseRange(r.Header.Get("Range"), size)
+ ranges, err := parseRange(rangeReq, size)
if err != nil {
Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
return
@@ -240,6 +247,9 @@ func checkLastModified(w ResponseWriter, r *Request, modtime time.Time) bool {
// The Date-Modified header truncates sub-second precision, so
// use mtime < t+1s instead of mtime <= t to check for unmodified.
if t, err := time.Parse(TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modtime.Before(t.Add(1*time.Second)) {
+ h := w.Header()
+ delete(h, "Content-Type")
+ delete(h, "Content-Length")
w.WriteHeader(StatusNotModified)
return true
}
@@ -247,6 +257,58 @@ func checkLastModified(w ResponseWriter, r *Request, modtime time.Time) bool {
return false
}
+// checkETag implements If-None-Match and If-Range checks.
+// The ETag must have been previously set in the ResponseWriter's headers.
+//
+// The return value is the effective request "Range" header to use and
+// whether this request is now considered done.
+func checkETag(w ResponseWriter, r *Request) (rangeReq string, done bool) {
+ etag := w.Header().get("Etag")
+ rangeReq = r.Header.get("Range")
+
+ // Invalidate the range request if the entity doesn't match the one
+ // the client was expecting.
+ // "If-Range: version" means "ignore the Range: header unless version matches the
+ // current file."
+ // We only support ETag versions.
+ // The caller must have set the ETag on the response already.
+ if ir := r.Header.get("If-Range"); ir != "" && ir != etag {
+ // TODO(bradfitz): handle If-Range requests with Last-Modified
+ // times instead of ETags? I'd rather not, at least for
+ // now. That seems like a bug/compromise in the RFC 2616, and
+ // I've never heard of anybody caring about that (yet).
+ rangeReq = ""
+ }
+
+ if inm := r.Header.get("If-None-Match"); inm != "" {
+ // Must know ETag.
+ if etag == "" {
+ return rangeReq, false
+ }
+
+ // TODO(bradfitz): non-GET/HEAD requests require more work:
+ // sending a different status code on matches, and
+ // also can't use weak cache validators (those with a "W/
+ // prefix). But most users of ServeContent will be using
+ // it on GET or HEAD, so only support those for now.
+ if r.Method != "GET" && r.Method != "HEAD" {
+ return rangeReq, false
+ }
+
+ // TODO(bradfitz): deal with comma-separated or multiple-valued
+ // list of If-None-match values. For now just handle the common
+ // case of a single item.
+ if inm == etag || inm == "*" {
+ h := w.Header()
+ delete(h, "Content-Type")
+ delete(h, "Content-Length")
+ w.WriteHeader(StatusNotModified)
+ return "", true
+ }
+ }
+ return rangeReq, false
+}
+
// name is '/'-separated, not filepath.Separator.
func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {
const indexPage = "/index.html"
diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go
index 17329fbd59a..09d5cfaf2d4 100644
--- a/libgo/go/net/http/fs_test.go
+++ b/libgo/go/net/http/fs_test.go
@@ -81,6 +81,7 @@ func TestServeFile(t *testing.T) {
}
// Range tests
+Cases:
for _, rt := range ServeFileRangeTests {
if rt.r != "" {
req.Header.Set("Range", rt.r)
@@ -109,7 +110,7 @@ func TestServeFile(t *testing.T) {
t.Errorf("range=%q: body = %q, want %q", rt.r, body, wantBody)
}
if strings.HasPrefix(ct, "multipart/byteranges") {
- t.Errorf("range=%q content-type = %q; unexpected multipart/byteranges", rt.r)
+ t.Errorf("range=%q content-type = %q; unexpected multipart/byteranges", rt.r, ct)
}
}
if len(rt.ranges) > 1 {
@@ -119,37 +120,41 @@ func TestServeFile(t *testing.T) {
continue
}
if typ != "multipart/byteranges" {
- t.Errorf("range=%q content-type = %q; want multipart/byteranges", rt.r)
+ t.Errorf("range=%q content-type = %q; want multipart/byteranges", rt.r, typ)
continue
}
if params["boundary"] == "" {
t.Errorf("range=%q content-type = %q; lacks boundary", rt.r, ct)
+ continue
}
if g, w := resp.ContentLength, int64(len(body)); g != w {
t.Errorf("range=%q Content-Length = %d; want %d", rt.r, g, w)
+ continue
}
mr := multipart.NewReader(bytes.NewReader(body), params["boundary"])
for ri, rng := range rt.ranges {
part, err := mr.NextPart()
if err != nil {
- t.Fatalf("range=%q, reading part index %d: %v", rt.r, ri, err)
+ t.Errorf("range=%q, reading part index %d: %v", rt.r, ri, err)
+ continue Cases
+ }
+ wantContentRange = fmt.Sprintf("bytes %d-%d/%d", rng.start, rng.end-1, testFileLen)
+ if g, w := part.Header.Get("Content-Range"), wantContentRange; g != w {
+ t.Errorf("range=%q: part Content-Range = %q; want %q", rt.r, g, w)
}
body, err := ioutil.ReadAll(part)
if err != nil {
- t.Fatalf("range=%q, reading part index %d body: %v", rt.r, ri, err)
+ t.Errorf("range=%q, reading part index %d body: %v", rt.r, ri, err)
+ continue Cases
}
- wantContentRange = fmt.Sprintf("bytes %d-%d/%d", rng.start, rng.end-1, testFileLen)
wantBody := file[rng.start:rng.end]
if !bytes.Equal(body, wantBody) {
t.Errorf("range=%q: body = %q, want %q", rt.r, body, wantBody)
}
- if g, w := part.Header.Get("Content-Range"), wantContentRange; g != w {
- t.Errorf("range=%q: part Content-Range = %q; want %q", rt.r, g, w)
- }
}
_, err = mr.NextPart()
if err != io.EOF {
- t.Errorf("range=%q; expected final error io.EOF; got %v", err)
+ t.Errorf("range=%q; expected final error io.EOF; got %v", rt.r, err)
}
}
}
@@ -335,11 +340,6 @@ func TestServeFileMimeType(t *testing.T) {
}
func TestServeFileFromCWD(t *testing.T) {
- if runtime.GOOS == "windows" {
- // TODO(brainman): find out why this test is broken
- t.Logf("Temporarily skipping test on Windows; see http://golang.org/issue/3917")
- return
- }
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
ServeFile(w, r, "fs_test.go")
}))
@@ -348,6 +348,7 @@ func TestServeFileFromCWD(t *testing.T) {
if err != nil {
t.Fatal(err)
}
+ r.Body.Close()
if r.StatusCode != 200 {
t.Fatalf("expected 200 OK, got %s", r.Status)
}
@@ -522,51 +523,140 @@ func TestDirectoryIfNotModified(t *testing.T) {
res.Body.Close()
}
-func TestServeContent(t *testing.T) {
- type req struct {
- name string
- modtime time.Time
- content io.ReadSeeker
+func mustStat(t *testing.T, fileName string) os.FileInfo {
+ fi, err := os.Stat(fileName)
+ if err != nil {
+ t.Fatal(err)
}
- ch := make(chan req, 1)
+ return fi
+}
+
+func TestServeContent(t *testing.T) {
+ type serveParam struct {
+ name string
+ modtime time.Time
+ content io.ReadSeeker
+ contentType string
+ etag string
+ }
+ servec := make(chan serveParam, 1)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
- p := <-ch
+ p := <-servec
+ if p.etag != "" {
+ w.Header().Set("ETag", p.etag)
+ }
+ if p.contentType != "" {
+ w.Header().Set("Content-Type", p.contentType)
+ }
ServeContent(w, r, p.name, p.modtime, p.content)
}))
defer ts.Close()
- css, err := os.Open("testdata/style.css")
- if err != nil {
- t.Fatal(err)
- }
- defer css.Close()
-
- ch <- req{"style.css", time.Time{}, css}
- res, err := Get(ts.URL)
- if err != nil {
- t.Fatal(err)
- }
- if g, e := res.Header.Get("Content-Type"), "text/css; charset=utf-8"; g != e {
- t.Errorf("style.css: content type = %q, want %q", g, e)
- }
- if g := res.Header.Get("Last-Modified"); g != "" {
- t.Errorf("want empty Last-Modified; got %q", g)
+ type testCase struct {
+ file string
+ modtime time.Time
+ serveETag string // optional
+ serveContentType string // optional
+ reqHeader map[string]string
+ wantLastMod string
+ wantContentType string
+ wantStatus int
+ }
+ htmlModTime := mustStat(t, "testdata/index.html").ModTime()
+ tests := map[string]testCase{
+ "no_last_modified": {
+ file: "testdata/style.css",
+ wantContentType: "text/css; charset=utf-8",
+ wantStatus: 200,
+ },
+ "with_last_modified": {
+ file: "testdata/index.html",
+ wantContentType: "text/html; charset=utf-8",
+ modtime: htmlModTime,
+ wantLastMod: htmlModTime.UTC().Format(TimeFormat),
+ wantStatus: 200,
+ },
+ "not_modified_modtime": {
+ file: "testdata/style.css",
+ modtime: htmlModTime,
+ reqHeader: map[string]string{
+ "If-Modified-Since": htmlModTime.UTC().Format(TimeFormat),
+ },
+ wantStatus: 304,
+ },
+ "not_modified_modtime_with_contenttype": {
+ file: "testdata/style.css",
+ serveContentType: "text/css", // explicit content type
+ modtime: htmlModTime,
+ reqHeader: map[string]string{
+ "If-Modified-Since": htmlModTime.UTC().Format(TimeFormat),
+ },
+ wantStatus: 304,
+ },
+ "not_modified_etag": {
+ file: "testdata/style.css",
+ serveETag: `"foo"`,
+ reqHeader: map[string]string{
+ "If-None-Match": `"foo"`,
+ },
+ wantStatus: 304,
+ },
+ "range_good": {
+ file: "testdata/style.css",
+ serveETag: `"A"`,
+ reqHeader: map[string]string{
+ "Range": "bytes=0-4",
+ },
+ wantStatus: StatusPartialContent,
+ wantContentType: "text/css; charset=utf-8",
+ },
+ // An If-Range resource for entity "A", but entity "B" is now current.
+ // The Range request should be ignored.
+ "range_no_match": {
+ file: "testdata/style.css",
+ serveETag: `"A"`,
+ reqHeader: map[string]string{
+ "Range": "bytes=0-4",
+ "If-Range": `"B"`,
+ },
+ wantStatus: 200,
+ wantContentType: "text/css; charset=utf-8",
+ },
}
+ for testName, tt := range tests {
+ f, err := os.Open(tt.file)
+ if err != nil {
+ t.Fatalf("test %q: %v", testName, err)
+ }
+ defer f.Close()
- fi, err := css.Stat()
- if err != nil {
- t.Fatal(err)
- }
- ch <- req{"style.html", fi.ModTime(), css}
- res, err = Get(ts.URL)
- if err != nil {
- t.Fatal(err)
- }
- if g, e := res.Header.Get("Content-Type"), "text/html; charset=utf-8"; g != e {
- t.Errorf("style.html: content type = %q, want %q", g, e)
- }
- if g := res.Header.Get("Last-Modified"); g == "" {
- t.Errorf("want non-empty last-modified")
+ servec <- serveParam{
+ name: filepath.Base(tt.file),
+ content: f,
+ modtime: tt.modtime,
+ etag: tt.serveETag,
+ contentType: tt.serveContentType,
+ }
+ req, err := NewRequest("GET", ts.URL, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for k, v := range tt.reqHeader {
+ req.Header.Set(k, v)
+ }
+ res, err := DefaultClient.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if res.StatusCode != tt.wantStatus {
+ t.Errorf("test %q: status = %d; want %d", testName, res.StatusCode, tt.wantStatus)
+ }
+ if g, e := res.Header.Get("Content-Type"), tt.wantContentType; g != e {
+ t.Errorf("test %q: content-type = %q, want %q", testName, g, e)
+ }
+ if g, e := res.Header.Get("Last-Modified"), tt.wantLastMod; g != e {
+ t.Errorf("test %q: last-modified = %q, want %q", testName, g, e)
+ }
}
}
diff --git a/libgo/go/net/http/header.go b/libgo/go/net/http/header.go
index 6be94f98e74..91417366ae8 100644
--- a/libgo/go/net/http/header.go
+++ b/libgo/go/net/http/header.go
@@ -5,11 +5,11 @@
package http
import (
- "fmt"
"io"
"net/textproto"
"sort"
"strings"
+ "time"
)
// A Header represents the key-value pairs in an HTTP header.
@@ -36,6 +36,14 @@ func (h Header) Get(key string) string {
return textproto.MIMEHeader(h).Get(key)
}
+// get is like Get, but key must already be in CanonicalHeaderKey form.
+func (h Header) get(key string) string {
+ if v := h[key]; len(v) > 0 {
+ return v[0]
+ }
+ return ""
+}
+
// Del deletes the values associated with key.
func (h Header) Del(key string) {
textproto.MIMEHeader(h).Del(key)
@@ -46,24 +54,77 @@ func (h Header) Write(w io.Writer) error {
return h.WriteSubset(w, nil)
}
+var timeFormats = []string{
+ TimeFormat,
+ time.RFC850,
+ time.ANSIC,
+}
+
+// ParseTime parses a time header (such as the Date: header),
+// trying each of the three formats allowed by HTTP/1.1:
+// TimeFormat, time.RFC850, and time.ANSIC.
+func ParseTime(text string) (t time.Time, err error) {
+ for _, layout := range timeFormats {
+ t, err = time.Parse(layout, text)
+ if err == nil {
+ return
+ }
+ }
+ return
+}
+
var headerNewlineToSpace = strings.NewReplacer("\n", " ", "\r", " ")
+type writeStringer interface {
+ WriteString(string) (int, error)
+}
+
+// stringWriter implements WriteString on a Writer.
+type stringWriter struct {
+ w io.Writer
+}
+
+func (w stringWriter) WriteString(s string) (n int, err error) {
+ return w.w.Write([]byte(s))
+}
+
+type keyValues struct {
+ key string
+ values []string
+}
+
+type byKey []keyValues
+
+func (s byKey) Len() int { return len(s) }
+func (s byKey) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s byKey) Less(i, j int) bool { return s[i].key < s[j].key }
+
+func (h Header) sortedKeyValues(exclude map[string]bool) []keyValues {
+ kvs := make([]keyValues, 0, len(h))
+ for k, vv := range h {
+ if !exclude[k] {
+ kvs = append(kvs, keyValues{k, vv})
+ }
+ }
+ sort.Sort(byKey(kvs))
+ return kvs
+}
+
// WriteSubset writes a header in wire format.
// If exclude is not nil, keys where exclude[key] == true are not written.
func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
- keys := make([]string, 0, len(h))
- for k := range h {
- if exclude == nil || !exclude[k] {
- keys = append(keys, k)
- }
+ ws, ok := w.(writeStringer)
+ if !ok {
+ ws = stringWriter{w}
}
- sort.Strings(keys)
- for _, k := range keys {
- for _, v := range h[k] {
+ for _, kv := range h.sortedKeyValues(exclude) {
+ for _, v := range kv.values {
v = headerNewlineToSpace.Replace(v)
- v = strings.TrimSpace(v)
- if _, err := fmt.Fprintf(w, "%s: %s\r\n", k, v); err != nil {
- return err
+ v = textproto.TrimString(v)
+ for _, s := range []string{kv.key, ": ", v, "\r\n"} {
+ if _, err := ws.WriteString(s); err != nil {
+ return err
+ }
}
}
}
diff --git a/libgo/go/net/http/header_test.go b/libgo/go/net/http/header_test.go
index ccdee8a97bd..fd971a61d05 100644
--- a/libgo/go/net/http/header_test.go
+++ b/libgo/go/net/http/header_test.go
@@ -6,7 +6,9 @@ package http
import (
"bytes"
+ "runtime"
"testing"
+ "time"
)
var headerWriteTests = []struct {
@@ -67,6 +69,24 @@ var headerWriteTests = []struct {
nil,
"Blank: \r\nDouble-Blank: \r\nDouble-Blank: \r\n",
},
+ // Tests header sorting when over the insertion sort threshold side:
+ {
+ Header{
+ "k1": {"1a", "1b"},
+ "k2": {"2a", "2b"},
+ "k3": {"3a", "3b"},
+ "k4": {"4a", "4b"},
+ "k5": {"5a", "5b"},
+ "k6": {"6a", "6b"},
+ "k7": {"7a", "7b"},
+ "k8": {"8a", "8b"},
+ "k9": {"9a", "9b"},
+ },
+ map[string]bool{"k5": true},
+ "k1: 1a\r\nk1: 1b\r\nk2: 2a\r\nk2: 2b\r\nk3: 3a\r\nk3: 3b\r\n" +
+ "k4: 4a\r\nk4: 4b\r\nk6: 6a\r\nk6: 6b\r\n" +
+ "k7: 7a\r\nk7: 7b\r\nk8: 8a\r\nk8: 8b\r\nk9: 9a\r\nk9: 9b\r\n",
+ },
}
func TestHeaderWrite(t *testing.T) {
@@ -79,3 +99,113 @@ func TestHeaderWrite(t *testing.T) {
buf.Reset()
}
}
+
+var parseTimeTests = []struct {
+ h Header
+ err bool
+}{
+ {Header{"Date": {""}}, true},
+ {Header{"Date": {"invalid"}}, true},
+ {Header{"Date": {"1994-11-06T08:49:37Z00:00"}}, true},
+ {Header{"Date": {"Sun, 06 Nov 1994 08:49:37 GMT"}}, false},
+ {Header{"Date": {"Sunday, 06-Nov-94 08:49:37 GMT"}}, false},
+ {Header{"Date": {"Sun Nov 6 08:49:37 1994"}}, false},
+}
+
+func TestParseTime(t *testing.T) {
+ expect := time.Date(1994, 11, 6, 8, 49, 37, 0, time.UTC)
+ for i, test := range parseTimeTests {
+ d, err := ParseTime(test.h.Get("Date"))
+ if err != nil {
+ if !test.err {
+ t.Errorf("#%d:\n got err: %v", i, err)
+ }
+ continue
+ }
+ if test.err {
+ t.Errorf("#%d:\n should err", i)
+ continue
+ }
+ if !expect.Equal(d) {
+ t.Errorf("#%d:\n got: %v\nwant: %v", i, d, expect)
+ }
+ }
+}
+
+type hasTokenTest struct {
+ header string
+ token string
+ want bool
+}
+
+var hasTokenTests = []hasTokenTest{
+ {"", "", false},
+ {"", "foo", false},
+ {"foo", "foo", true},
+ {"foo ", "foo", true},
+ {" foo", "foo", true},
+ {" foo ", "foo", true},
+ {"foo,bar", "foo", true},
+ {"bar,foo", "foo", true},
+ {"bar, foo", "foo", true},
+ {"bar,foo, baz", "foo", true},
+ {"bar, foo,baz", "foo", true},
+ {"bar,foo, baz", "foo", true},
+ {"bar, foo, baz", "foo", true},
+ {"FOO", "foo", true},
+ {"FOO ", "foo", true},
+ {" FOO", "foo", true},
+ {" FOO ", "foo", true},
+ {"FOO,BAR", "foo", true},
+ {"BAR,FOO", "foo", true},
+ {"BAR, FOO", "foo", true},
+ {"BAR,FOO, baz", "foo", true},
+ {"BAR, FOO,BAZ", "foo", true},
+ {"BAR,FOO, BAZ", "foo", true},
+ {"BAR, FOO, BAZ", "foo", true},
+ {"foobar", "foo", false},
+ {"barfoo ", "foo", false},
+}
+
+func TestHasToken(t *testing.T) {
+ for _, tt := range hasTokenTests {
+ if hasToken(tt.header, tt.token) != tt.want {
+ t.Errorf("hasToken(%q, %q) = %v; want %v", tt.header, tt.token, !tt.want, tt.want)
+ }
+ }
+}
+
+func BenchmarkHeaderWriteSubset(b *testing.B) {
+ doHeaderWriteSubset(b.N, b)
+}
+
+func TestHeaderWriteSubsetMallocs(t *testing.T) {
+ doHeaderWriteSubset(100, t)
+}
+
+type errorfer interface {
+ Errorf(string, ...interface{})
+}
+
+func doHeaderWriteSubset(n int, t errorfer) {
+ h := Header(map[string][]string{
+ "Content-Length": {"123"},
+ "Content-Type": {"text/plain"},
+ "Date": {"some date at some time Z"},
+ "Server": {"Go http package"},
+ })
+ var buf bytes.Buffer
+ var m0 runtime.MemStats
+ runtime.ReadMemStats(&m0)
+ for i := 0; i < n; i++ {
+ buf.Reset()
+ h.WriteSubset(&buf, nil)
+ }
+ var m1 runtime.MemStats
+ runtime.ReadMemStats(&m1)
+ if mallocs := m1.Mallocs - m0.Mallocs; n >= 100 && mallocs >= uint64(n) {
+ // TODO(bradfitz,rsc): once we can sort with allocating,
+ // make this an error. See http://golang.org/issue/3761
+ // t.Errorf("did %d mallocs (>= %d iterations); should have avoided mallocs", mallocs, n)
+ }
+}
diff --git a/libgo/go/net/http/httptest/recorder.go b/libgo/go/net/http/httptest/recorder.go
index 9aa0d510bd4..5451f54234c 100644
--- a/libgo/go/net/http/httptest/recorder.go
+++ b/libgo/go/net/http/httptest/recorder.go
@@ -17,6 +17,8 @@ type ResponseRecorder struct {
HeaderMap http.Header // the HTTP response headers
Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
Flushed bool
+
+ wroteHeader bool
}
// NewRecorder returns an initialized ResponseRecorder.
@@ -24,6 +26,7 @@ func NewRecorder() *ResponseRecorder {
return &ResponseRecorder{
HeaderMap: make(http.Header),
Body: new(bytes.Buffer),
+ Code: 200,
}
}
@@ -33,26 +36,37 @@ const DefaultRemoteAddr = "1.2.3.4"
// Header returns the response headers.
func (rw *ResponseRecorder) Header() http.Header {
- return rw.HeaderMap
+ m := rw.HeaderMap
+ if m == nil {
+ m = make(http.Header)
+ rw.HeaderMap = m
+ }
+ return m
}
// Write always succeeds and writes to rw.Body, if not nil.
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
+ if !rw.wroteHeader {
+ rw.WriteHeader(200)
+ }
if rw.Body != nil {
rw.Body.Write(buf)
}
- if rw.Code == 0 {
- rw.Code = http.StatusOK
- }
return len(buf), nil
}
// WriteHeader sets rw.Code.
func (rw *ResponseRecorder) WriteHeader(code int) {
- rw.Code = code
+ if !rw.wroteHeader {
+ rw.Code = code
+ }
+ rw.wroteHeader = true
}
// Flush sets rw.Flushed to true.
func (rw *ResponseRecorder) Flush() {
+ if !rw.wroteHeader {
+ rw.WriteHeader(200)
+ }
rw.Flushed = true
}
diff --git a/libgo/go/net/http/httptest/recorder_test.go b/libgo/go/net/http/httptest/recorder_test.go
new file mode 100644
index 00000000000..2b563260c76
--- /dev/null
+++ b/libgo/go/net/http/httptest/recorder_test.go
@@ -0,0 +1,90 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package httptest
+
+import (
+ "fmt"
+ "net/http"
+ "testing"
+)
+
+func TestRecorder(t *testing.T) {
+ type checkFunc func(*ResponseRecorder) error
+ check := func(fns ...checkFunc) []checkFunc { return fns }
+
+ hasStatus := func(wantCode int) checkFunc {
+ return func(rec *ResponseRecorder) error {
+ if rec.Code != wantCode {
+ return fmt.Errorf("Status = %d; want %d", rec.Code, wantCode)
+ }
+ return nil
+ }
+ }
+ hasContents := func(want string) checkFunc {
+ return func(rec *ResponseRecorder) error {
+ if rec.Body.String() != want {
+ return fmt.Errorf("wrote = %q; want %q", rec.Body.String(), want)
+ }
+ return nil
+ }
+ }
+ hasFlush := func(want bool) checkFunc {
+ return func(rec *ResponseRecorder) error {
+ if rec.Flushed != want {
+ return fmt.Errorf("Flushed = %v; want %v", rec.Flushed, want)
+ }
+ return nil
+ }
+ }
+
+ tests := []struct {
+ name string
+ h func(w http.ResponseWriter, r *http.Request)
+ checks []checkFunc
+ }{
+ {
+ "200 default",
+ func(w http.ResponseWriter, r *http.Request) {},
+ check(hasStatus(200), hasContents("")),
+ },
+ {
+ "first code only",
+ func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(201)
+ w.WriteHeader(202)
+ w.Write([]byte("hi"))
+ },
+ check(hasStatus(201), hasContents("hi")),
+ },
+ {
+ "write sends 200",
+ func(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte("hi first"))
+ w.WriteHeader(201)
+ w.WriteHeader(202)
+ },
+ check(hasStatus(200), hasContents("hi first"), hasFlush(false)),
+ },
+ {
+ "flush",
+ func(w http.ResponseWriter, r *http.Request) {
+ w.(http.Flusher).Flush() // also sends a 200
+ w.WriteHeader(201)
+ },
+ check(hasStatus(200), hasFlush(true)),
+ },
+ }
+ r, _ := http.NewRequest("GET", "http://foo.com/", nil)
+ for _, tt := range tests {
+ h := http.HandlerFunc(tt.h)
+ rec := NewRecorder()
+ h.ServeHTTP(rec, r)
+ for _, check := range tt.checks {
+ if err := check(rec); err != nil {
+ t.Errorf("%s: %v", tt.name, err)
+ }
+ }
+ }
+}
diff --git a/libgo/go/net/http/httputil/dump.go b/libgo/go/net/http/httputil/dump.go
index 0fb2eeb8c00..0b003566165 100644
--- a/libgo/go/net/http/httputil/dump.go
+++ b/libgo/go/net/http/httputil/dump.go
@@ -75,7 +75,7 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
// Use the actual Transport code to record what we would send
// on the wire, but not using TCP. Use a Transport with a
- // customer dialer that returns a fake net.Conn that waits
+ // custom dialer that returns a fake net.Conn that waits
// for the full input (and recording it), and then responds
// with a dummy response.
var buf bytes.Buffer // records the output
diff --git a/libgo/go/net/http/httputil/reverseproxy.go b/libgo/go/net/http/httputil/reverseproxy.go
index 9c4bd6e09a5..134c452999d 100644
--- a/libgo/go/net/http/httputil/reverseproxy.go
+++ b/libgo/go/net/http/httputil/reverseproxy.go
@@ -17,6 +17,10 @@ import (
"time"
)
+// onExitFlushLoop is a callback set by tests to detect the state of the
+// flushLoop() goroutine.
+var onExitFlushLoop func()
+
// ReverseProxy is an HTTP Handler that takes an incoming request and
// sends it to another server, proxying the response back to the
// client.
@@ -102,8 +106,14 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
outreq.Header.Del("Connection")
}
- if clientIp, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
- outreq.Header.Set("X-Forwarded-For", clientIp)
+ if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
+ // If we aren't the first proxy retain prior
+ // X-Forwarded-For information as a comma+space
+ // separated list and fold multiple headers into one.
+ if prior, ok := outreq.Header["X-Forwarded-For"]; ok {
+ clientIP = strings.Join(prior, ", ") + ", " + clientIP
+ }
+ outreq.Header.Set("X-Forwarded-For", clientIP)
}
res, err := transport.RoundTrip(outreq)
@@ -112,20 +122,29 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusInternalServerError)
return
}
+ defer res.Body.Close()
copyHeader(rw.Header(), res.Header)
rw.WriteHeader(res.StatusCode)
+ p.copyResponse(rw, res.Body)
+}
- if res.Body != nil {
- var dst io.Writer = rw
- if p.FlushInterval != 0 {
- if wf, ok := rw.(writeFlusher); ok {
- dst = &maxLatencyWriter{dst: wf, latency: p.FlushInterval}
+func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader) {
+ if p.FlushInterval != 0 {
+ if wf, ok := dst.(writeFlusher); ok {
+ mlw := &maxLatencyWriter{
+ dst: wf,
+ latency: p.FlushInterval,
+ done: make(chan bool),
}
+ go mlw.flushLoop()
+ defer mlw.stop()
+ dst = mlw
}
- io.Copy(dst, res.Body)
}
+
+ io.Copy(dst, src)
}
type writeFlusher interface {
@@ -137,22 +156,14 @@ type maxLatencyWriter struct {
dst writeFlusher
latency time.Duration
- lk sync.Mutex // protects init of done, as well Write + Flush
+ lk sync.Mutex // protects Write + Flush
done chan bool
}
-func (m *maxLatencyWriter) Write(p []byte) (n int, err error) {
+func (m *maxLatencyWriter) Write(p []byte) (int, error) {
m.lk.Lock()
defer m.lk.Unlock()
- if m.done == nil {
- m.done = make(chan bool)
- go m.flushLoop()
- }
- n, err = m.dst.Write(p)
- if err != nil {
- m.done <- true
- }
- return
+ return m.dst.Write(p)
}
func (m *maxLatencyWriter) flushLoop() {
@@ -160,13 +171,18 @@ func (m *maxLatencyWriter) flushLoop() {
defer t.Stop()
for {
select {
+ case <-m.done:
+ if onExitFlushLoop != nil {
+ onExitFlushLoop()
+ }
+ return
case <-t.C:
m.lk.Lock()
m.dst.Flush()
m.lk.Unlock()
- case <-m.done:
- return
}
}
panic("unreached")
}
+
+func (m *maxLatencyWriter) stop() { m.done <- true }
diff --git a/libgo/go/net/http/httputil/reverseproxy_test.go b/libgo/go/net/http/httputil/reverseproxy_test.go
index 28e9c90ad36..8639271626f 100644
--- a/libgo/go/net/http/httputil/reverseproxy_test.go
+++ b/libgo/go/net/http/httputil/reverseproxy_test.go
@@ -11,7 +11,9 @@ import (
"net/http"
"net/http/httptest"
"net/url"
+ "strings"
"testing"
+ "time"
)
func TestReverseProxy(t *testing.T) {
@@ -70,6 +72,47 @@ func TestReverseProxy(t *testing.T) {
}
}
+func TestXForwardedFor(t *testing.T) {
+ const prevForwardedFor = "client ip"
+ const backendResponse = "I am the backend"
+ const backendStatus = 404
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Header.Get("X-Forwarded-For") == "" {
+ t.Errorf("didn't get X-Forwarded-For header")
+ }
+ if !strings.Contains(r.Header.Get("X-Forwarded-For"), prevForwardedFor) {
+ t.Errorf("X-Forwarded-For didn't contain prior data")
+ }
+ w.WriteHeader(backendStatus)
+ w.Write([]byte(backendResponse))
+ }))
+ defer backend.Close()
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ frontend := httptest.NewServer(proxyHandler)
+ defer frontend.Close()
+
+ getReq, _ := http.NewRequest("GET", frontend.URL, nil)
+ getReq.Host = "some-name"
+ getReq.Header.Set("Connection", "close")
+ getReq.Header.Set("X-Forwarded-For", prevForwardedFor)
+ getReq.Close = true
+ res, err := http.DefaultClient.Do(getReq)
+ if err != nil {
+ t.Fatalf("Get: %v", err)
+ }
+ if g, e := res.StatusCode, backendStatus; g != e {
+ t.Errorf("got res.StatusCode %d; expected %d", g, e)
+ }
+ bodyBytes, _ := ioutil.ReadAll(res.Body)
+ if g, e := string(bodyBytes), backendResponse; g != e {
+ t.Errorf("got body %q; expected %q", g, e)
+ }
+}
+
var proxyQueryTests = []struct {
baseSuffix string // suffix to add to backend URL
reqSuffix string // suffix to add to frontend's request URL
@@ -107,3 +150,44 @@ func TestReverseProxyQuery(t *testing.T) {
frontend.Close()
}
}
+
+func TestReverseProxyFlushInterval(t *testing.T) {
+ const expected = "hi"
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte(expected))
+ }))
+ defer backend.Close()
+
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ proxyHandler.FlushInterval = time.Microsecond
+
+ done := make(chan bool)
+ onExitFlushLoop = func() { done <- true }
+ defer func() { onExitFlushLoop = nil }()
+
+ frontend := httptest.NewServer(proxyHandler)
+ defer frontend.Close()
+
+ req, _ := http.NewRequest("GET", frontend.URL, nil)
+ req.Close = true
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ t.Fatalf("Get: %v", err)
+ }
+ defer res.Body.Close()
+ if bodyBytes, _ := ioutil.ReadAll(res.Body); string(bodyBytes) != expected {
+ t.Errorf("got body %q; expected %q", bodyBytes, expected)
+ }
+
+ select {
+ case <-done:
+ // OK
+ case <-time.After(5 * time.Second):
+ t.Error("maxLatencyWriter flushLoop() never exited")
+ }
+}
diff --git a/libgo/go/net/http/lex.go b/libgo/go/net/http/lex.go
index ffb393ccf6a..cb33318f49b 100644
--- a/libgo/go/net/http/lex.go
+++ b/libgo/go/net/http/lex.go
@@ -6,131 +6,91 @@ package http
// This file deals with lexical matters of HTTP
-func isSeparator(c byte) bool {
- switch c {
- case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
- return true
- }
- return false
+var isTokenTable = [127]bool{
+ '!': true,
+ '#': true,
+ '$': true,
+ '%': true,
+ '&': true,
+ '\'': true,
+ '*': true,
+ '+': true,
+ '-': true,
+ '.': true,
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ 'A': true,
+ 'B': true,
+ 'C': true,
+ 'D': true,
+ 'E': true,
+ 'F': true,
+ 'G': true,
+ 'H': true,
+ 'I': true,
+ 'J': true,
+ 'K': true,
+ 'L': true,
+ 'M': true,
+ 'N': true,
+ 'O': true,
+ 'P': true,
+ 'Q': true,
+ 'R': true,
+ 'S': true,
+ 'T': true,
+ 'U': true,
+ 'W': true,
+ 'V': true,
+ 'X': true,
+ 'Y': true,
+ 'Z': true,
+ '^': true,
+ '_': true,
+ '`': true,
+ 'a': true,
+ 'b': true,
+ 'c': true,
+ 'd': true,
+ 'e': true,
+ 'f': true,
+ 'g': true,
+ 'h': true,
+ 'i': true,
+ 'j': true,
+ 'k': true,
+ 'l': true,
+ 'm': true,
+ 'n': true,
+ 'o': true,
+ 'p': true,
+ 'q': true,
+ 'r': true,
+ 's': true,
+ 't': true,
+ 'u': true,
+ 'v': true,
+ 'w': true,
+ 'x': true,
+ 'y': true,
+ 'z': true,
+ '|': true,
+ '~': true,
}
-func isCtl(c byte) bool { return (0 <= c && c <= 31) || c == 127 }
-
-func isChar(c byte) bool { return 0 <= c && c <= 127 }
-
-func isAnyText(c byte) bool { return !isCtl(c) }
-
-func isQdText(c byte) bool { return isAnyText(c) && c != '"' }
-
-func isToken(c byte) bool { return isChar(c) && !isCtl(c) && !isSeparator(c) }
-
-// Valid escaped sequences are not specified in RFC 2616, so for now, we assume
-// that they coincide with the common sense ones used by GO. Malformed
-// characters should probably not be treated as errors by a robust (forgiving)
-// parser, so we replace them with the '?' character.
-func httpUnquotePair(b byte) byte {
- // skip the first byte, which should always be '\'
- switch b {
- case 'a':
- return '\a'
- case 'b':
- return '\b'
- case 'f':
- return '\f'
- case 'n':
- return '\n'
- case 'r':
- return '\r'
- case 't':
- return '\t'
- case 'v':
- return '\v'
- case '\\':
- return '\\'
- case '\'':
- return '\''
- case '"':
- return '"'
- }
- return '?'
-}
-
-// raw must begin with a valid quoted string. Only the first quoted string is
-// parsed and is unquoted in result. eaten is the number of bytes parsed, or -1
-// upon failure.
-func httpUnquote(raw []byte) (eaten int, result string) {
- buf := make([]byte, len(raw))
- if raw[0] != '"' {
- return -1, ""
- }
- eaten = 1
- j := 0 // # of bytes written in buf
- for i := 1; i < len(raw); i++ {
- switch b := raw[i]; b {
- case '"':
- eaten++
- buf = buf[0:j]
- return i + 1, string(buf)
- case '\\':
- if len(raw) < i+2 {
- return -1, ""
- }
- buf[j] = httpUnquotePair(raw[i+1])
- eaten += 2
- j++
- i++
- default:
- if isQdText(b) {
- buf[j] = b
- } else {
- buf[j] = '?'
- }
- eaten++
- j++
- }
- }
- return -1, ""
+func isToken(r rune) bool {
+ i := int(r)
+ return i < len(isTokenTable) && isTokenTable[i]
}
-// This is a best effort parse, so errors are not returned, instead not all of
-// the input string might be parsed. result is always non-nil.
-func httpSplitFieldValue(fv string) (eaten int, result []string) {
- result = make([]string, 0, len(fv))
- raw := []byte(fv)
- i := 0
- chunk := ""
- for i < len(raw) {
- b := raw[i]
- switch {
- case b == '"':
- eaten, unq := httpUnquote(raw[i:len(raw)])
- if eaten < 0 {
- return i, result
- } else {
- i += eaten
- chunk += unq
- }
- case isSeparator(b):
- if chunk != "" {
- result = result[0 : len(result)+1]
- result[len(result)-1] = chunk
- chunk = ""
- }
- i++
- case isToken(b):
- chunk += string(b)
- i++
- case b == '\n' || b == '\r':
- i++
- default:
- chunk += "?"
- i++
- }
- }
- if chunk != "" {
- result = result[0 : len(result)+1]
- result[len(result)-1] = chunk
- chunk = ""
- }
- return i, result
+func isNotToken(r rune) bool {
+ return !isToken(r)
}
diff --git a/libgo/go/net/http/lex_test.go b/libgo/go/net/http/lex_test.go
index 5386f7534db..6d9d294f703 100644
--- a/libgo/go/net/http/lex_test.go
+++ b/libgo/go/net/http/lex_test.go
@@ -8,63 +8,24 @@ import (
"testing"
)
-type lexTest struct {
- Raw string
- Parsed int // # of parsed characters
- Result []string
-}
+func isChar(c rune) bool { return c <= 127 }
-var lexTests = []lexTest{
- {
- Raw: `"abc"def,:ghi`,
- Parsed: 13,
- Result: []string{"abcdef", "ghi"},
- },
- // My understanding of the RFC is that escape sequences outside of
- // quotes are not interpreted?
- {
- Raw: `"\t"\t"\t"`,
- Parsed: 10,
- Result: []string{"\t", "t\t"},
- },
- {
- Raw: `"\yab"\r\n`,
- Parsed: 10,
- Result: []string{"?ab", "r", "n"},
- },
- {
- Raw: "ab\f",
- Parsed: 3,
- Result: []string{"ab?"},
- },
- {
- Raw: "\"ab \" c,de f, gh, ij\n\t\r",
- Parsed: 23,
- Result: []string{"ab ", "c", "de", "f", "gh", "ij"},
- },
-}
+func isCtl(c rune) bool { return c <= 31 || c == 127 }
-func min(x, y int) int {
- if x <= y {
- return x
+func isSeparator(c rune) bool {
+ switch c {
+ case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
+ return true
}
- return y
+ return false
}
-func TestSplitFieldValue(t *testing.T) {
- for k, l := range lexTests {
- parsed, result := httpSplitFieldValue(l.Raw)
- if parsed != l.Parsed {
- t.Errorf("#%d: Parsed %d, expected %d", k, parsed, l.Parsed)
- }
- if len(result) != len(l.Result) {
- t.Errorf("#%d: Result len %d, expected %d", k, len(result), len(l.Result))
- }
- for i := 0; i < min(len(result), len(l.Result)); i++ {
- if result[i] != l.Result[i] {
- t.Errorf("#%d: %d-th entry mismatch. Have {%s}, expect {%s}",
- k, i, result[i], l.Result[i])
- }
+func TestIsToken(t *testing.T) {
+ for i := 0; i <= 130; i++ {
+ r := rune(i)
+ expected := isChar(r) && !isCtl(r) && !isSeparator(r)
+ if isToken(r) != expected {
+ t.Errorf("isToken(0x%x) = %v", r, !expected)
}
}
}
diff --git a/libgo/go/net/http/pprof/pprof.go b/libgo/go/net/http/pprof/pprof.go
index 7a9f465c477..d70bf4ed9d3 100644
--- a/libgo/go/net/http/pprof/pprof.go
+++ b/libgo/go/net/http/pprof/pprof.go
@@ -30,6 +30,10 @@
//
// go tool pprof http://localhost:6060/debug/pprof/profile
//
+// Or to look at the goroutine blocking profile:
+//
+// go tool pprof http://localhost:6060/debug/pprof/block
+//
// Or to view all available profiles:
//
// go tool pprof http://localhost:6060/debug/pprof/
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index f5bc6eb9100..61557ff8302 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -19,6 +19,7 @@ import (
"mime/multipart"
"net/textproto"
"net/url"
+ "strconv"
"strings"
)
@@ -131,6 +132,12 @@ type Request struct {
// The HTTP client ignores Form and uses Body instead.
Form url.Values
+ // PostForm contains the parsed form data from POST or PUT
+ // body parameters.
+ // This field is only available after ParseForm is called.
+ // The HTTP client ignores PostForm and uses Body instead.
+ PostForm url.Values
+
// MultipartForm is the parsed multipart form, including file uploads.
// This field is only available after ParseMultipartForm is called.
// The HTTP client ignores MultipartForm and uses Body instead.
@@ -369,36 +376,29 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
return bw.Flush()
}
-// Convert decimal at s[i:len(s)] to integer,
-// returning value, string position where the digits stopped,
-// and whether there was a valid number (digits, not too big).
-func atoi(s string, i int) (n, i1 int, ok bool) {
- const Big = 1000000
- if i >= len(s) || s[i] < '0' || s[i] > '9' {
- return 0, 0, false
- }
- n = 0
- for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
- n = n*10 + int(s[i]-'0')
- if n > Big {
- return 0, 0, false
- }
- }
- return n, i, true
-}
-
// ParseHTTPVersion parses a HTTP version string.
// "HTTP/1.0" returns (1, 0, true).
func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
- if len(vers) < 5 || vers[0:5] != "HTTP/" {
+ const Big = 1000000 // arbitrary upper bound
+ switch vers {
+ case "HTTP/1.1":
+ return 1, 1, true
+ case "HTTP/1.0":
+ return 1, 0, true
+ }
+ if !strings.HasPrefix(vers, "HTTP/") {
+ return 0, 0, false
+ }
+ dot := strings.Index(vers, ".")
+ if dot < 0 {
return 0, 0, false
}
- major, i, ok := atoi(vers, 5)
- if !ok || i >= len(vers) || vers[i] != '.' {
+ major, err := strconv.Atoi(vers[5:dot])
+ if err != nil || major < 0 || major > Big {
return 0, 0, false
}
- minor, i, ok = atoi(vers, i+1)
- if !ok || i != len(vers) {
+ minor, err = strconv.Atoi(vers[dot+1:])
+ if err != nil || minor < 0 || minor > Big {
return 0, 0, false
}
return major, minor, true
@@ -513,9 +513,9 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) {
// the same. In the second case, any Host line is ignored.
req.Host = req.URL.Host
if req.Host == "" {
- req.Host = req.Header.Get("Host")
+ req.Host = req.Header.get("Host")
}
- req.Header.Del("Host")
+ delete(req.Header, "Host")
fixPragmaCacheControl(req.Header)
@@ -594,66 +594,93 @@ func (l *maxBytesReader) Close() error {
return l.r.Close()
}
+func copyValues(dst, src url.Values) {
+ for k, vs := range src {
+ for _, value := range vs {
+ dst.Add(k, value)
+ }
+ }
+}
+
+func parsePostForm(r *Request) (vs url.Values, err error) {
+ if r.Body == nil {
+ err = errors.New("missing form body")
+ return
+ }
+ ct := r.Header.Get("Content-Type")
+ ct, _, err = mime.ParseMediaType(ct)
+ switch {
+ case ct == "application/x-www-form-urlencoded":
+ var reader io.Reader = r.Body
+ maxFormSize := int64(1<<63 - 1)
+ if _, ok := r.Body.(*maxBytesReader); !ok {
+ maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
+ reader = io.LimitReader(r.Body, maxFormSize+1)
+ }
+ b, e := ioutil.ReadAll(reader)
+ if e != nil {
+ if err == nil {
+ err = e
+ }
+ break
+ }
+ if int64(len(b)) > maxFormSize {
+ err = errors.New("http: POST too large")
+ return
+ }
+ vs, e = url.ParseQuery(string(b))
+ if err == nil {
+ err = e
+ }
+ case ct == "multipart/form-data":
+ // handled by ParseMultipartForm (which is calling us, or should be)
+ // TODO(bradfitz): there are too many possible
+ // orders to call too many functions here.
+ // Clean this up and write more tests.
+ // request_test.go contains the start of this,
+ // in TestRequestMultipartCallOrder.
+ }
+ return
+}
+
// ParseForm parses the raw query from the URL.
//
// For POST or PUT requests, it also parses the request body as a form.
+// POST and PUT body parameters take precedence over URL query string values.
// If the request Body's size has not already been limited by MaxBytesReader,
// the size is capped at 10MB.
//
// ParseMultipartForm calls ParseForm automatically.
// It is idempotent.
func (r *Request) ParseForm() (err error) {
- if r.Form != nil {
- return
- }
- if r.URL != nil {
- r.Form, err = url.ParseQuery(r.URL.RawQuery)
+ if r.PostForm == nil {
+ if r.Method == "POST" || r.Method == "PUT" {
+ r.PostForm, err = parsePostForm(r)
+ }
+ if r.PostForm == nil {
+ r.PostForm = make(url.Values)
+ }
}
- if r.Method == "POST" || r.Method == "PUT" {
- if r.Body == nil {
- return errors.New("missing form body")
+ if r.Form == nil {
+ if len(r.PostForm) > 0 {
+ r.Form = make(url.Values)
+ copyValues(r.Form, r.PostForm)
}
- ct := r.Header.Get("Content-Type")
- ct, _, err = mime.ParseMediaType(ct)
- switch {
- case ct == "application/x-www-form-urlencoded":
- var reader io.Reader = r.Body
- maxFormSize := int64(1<<63 - 1)
- if _, ok := r.Body.(*maxBytesReader); !ok {
- maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
- reader = io.LimitReader(r.Body, maxFormSize+1)
- }
- b, e := ioutil.ReadAll(reader)
- if e != nil {
- if err == nil {
- err = e
- }
- break
- }
- if int64(len(b)) > maxFormSize {
- return errors.New("http: POST too large")
- }
- var newValues url.Values
- newValues, e = url.ParseQuery(string(b))
+ var newValues url.Values
+ if r.URL != nil {
+ var e error
+ newValues, e = url.ParseQuery(r.URL.RawQuery)
if err == nil {
err = e
}
- if r.Form == nil {
- r.Form = make(url.Values)
- }
- // Copy values into r.Form. TODO: make this smoother.
- for k, vs := range newValues {
- for _, value := range vs {
- r.Form.Add(k, value)
- }
- }
- case ct == "multipart/form-data":
- // handled by ParseMultipartForm (which is calling us, or should be)
- // TODO(bradfitz): there are too many possible
- // orders to call too many functions here.
- // Clean this up and write more tests.
- // request_test.go contains the start of this,
- // in TestRequestMultipartCallOrder.
+ }
+ if newValues == nil {
+ newValues = make(url.Values)
+ }
+ if r.Form == nil {
+ r.Form = newValues
+ } else {
+ copyValues(r.Form, newValues)
}
}
return err
@@ -699,6 +726,7 @@ func (r *Request) ParseMultipartForm(maxMemory int64) error {
}
// FormValue returns the first value for the named component of the query.
+// POST and PUT body parameters take precedence over URL query string values.
// FormValue calls ParseMultipartForm and ParseForm if necessary.
func (r *Request) FormValue(key string) string {
if r.Form == nil {
@@ -710,6 +738,19 @@ func (r *Request) FormValue(key string) string {
return ""
}
+// PostFormValue returns the first value for the named component of the POST
+// or PUT request body. URL query parameters are ignored.
+// PostFormValue calls ParseMultipartForm and ParseForm if necessary.
+func (r *Request) PostFormValue(key string) string {
+ if r.PostForm == nil {
+ r.ParseMultipartForm(defaultMaxMemory)
+ }
+ if vs := r.PostForm[key]; len(vs) > 0 {
+ return vs[0]
+ }
+ return ""
+}
+
// FormFile returns the first file for the provided form key.
// FormFile calls ParseMultipartForm and ParseForm if necessary.
func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error) {
@@ -732,12 +773,16 @@ func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, e
}
func (r *Request) expectsContinue() bool {
- return strings.ToLower(r.Header.Get("Expect")) == "100-continue"
+ return hasToken(r.Header.get("Expect"), "100-continue")
}
func (r *Request) wantsHttp10KeepAlive() bool {
if r.ProtoMajor != 1 || r.ProtoMinor != 0 {
return false
}
- return strings.Contains(strings.ToLower(r.Header.Get("Connection")), "keep-alive")
+ return hasToken(r.Header.get("Connection"), "keep-alive")
+}
+
+func (r *Request) wantsClose() bool {
+ return hasToken(r.Header.get("Connection"), "close")
}
diff --git a/libgo/go/net/http/request_test.go b/libgo/go/net/http/request_test.go
index 6e00b9bfd39..db7419b26fe 100644
--- a/libgo/go/net/http/request_test.go
+++ b/libgo/go/net/http/request_test.go
@@ -30,8 +30,8 @@ func TestQuery(t *testing.T) {
}
func TestPostQuery(t *testing.T) {
- req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x",
- strings.NewReader("z=post&both=y"))
+ req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&empty=not",
+ strings.NewReader("z=post&both=y&prio=2&empty="))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
if q := req.FormValue("q"); q != "foo" {
@@ -40,8 +40,23 @@ func TestPostQuery(t *testing.T) {
if z := req.FormValue("z"); z != "post" {
t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
}
- if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"x", "y"}) {
- t.Errorf(`req.FormValue("both") = %q, want ["x", "y"]`, both)
+ if bq, found := req.PostForm["q"]; found {
+ t.Errorf(`req.PostForm["q"] = %q, want no entry in map`, bq)
+ }
+ if bz := req.PostFormValue("z"); bz != "post" {
+ t.Errorf(`req.PostFormValue("z") = %q, want "post"`, bz)
+ }
+ if qs := req.Form["q"]; !reflect.DeepEqual(qs, []string{"foo", "bar"}) {
+ t.Errorf(`req.Form["q"] = %q, want ["foo", "bar"]`, qs)
+ }
+ if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"y", "x"}) {
+ t.Errorf(`req.Form["both"] = %q, want ["y", "x"]`, both)
+ }
+ if prio := req.FormValue("prio"); prio != "2" {
+ t.Errorf(`req.FormValue("prio") = %q, want "2" (from body)`, prio)
+ }
+ if empty := req.FormValue("empty"); empty != "" {
+ t.Errorf(`req.FormValue("empty") = %q, want "" (from body)`, empty)
}
}
@@ -76,6 +91,23 @@ func TestParseFormUnknownContentType(t *testing.T) {
}
}
+func TestParseFormInitializeOnError(t *testing.T) {
+ nilBody, _ := NewRequest("POST", "http://www.google.com/search?q=foo", nil)
+ tests := []*Request{
+ nilBody,
+ {Method: "GET", URL: nil},
+ }
+ for i, req := range tests {
+ err := req.ParseForm()
+ if req.Form == nil {
+ t.Errorf("%d. Form not initialized, error %v", i, err)
+ }
+ if req.PostForm == nil {
+ t.Errorf("%d. PostForm not initialized, error %v", i, err)
+ }
+ }
+}
+
func TestMultipartReader(t *testing.T) {
req := &Request{
Method: "POST",
diff --git a/libgo/go/net/http/response.go b/libgo/go/net/http/response.go
index 945ecd8a4b0..92d2f499839 100644
--- a/libgo/go/net/http/response.go
+++ b/libgo/go/net/http/response.go
@@ -107,7 +107,6 @@ func ReadResponse(r *bufio.Reader, req *Request) (resp *Response, err error) {
resp = new(Response)
resp.Request = req
- resp.Request.Method = strings.ToUpper(resp.Request.Method)
// Parse the first line of the response.
line, err := tp.ReadLine()
@@ -188,11 +187,6 @@ func (r *Response) ProtoAtLeast(major, minor int) bool {
//
func (r *Response) Write(w io.Writer) error {
- // RequestMethod should be upper-case
- if r.Request != nil {
- r.Request.Method = strings.ToUpper(r.Request.Method)
- }
-
// Status line
text := r.Status
if text == "" {
diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go
index c9d73932bb9..71b7b3fb6b7 100644
--- a/libgo/go/net/http/serve_test.go
+++ b/libgo/go/net/http/serve_test.go
@@ -20,8 +20,13 @@ import (
"net/http/httputil"
"net/url"
"os"
+ "os/exec"
"reflect"
+ "runtime"
+ "strconv"
"strings"
+ "sync"
+ "sync/atomic"
"syscall"
"testing"
"time"
@@ -168,6 +173,9 @@ var vtests = []struct {
{"http://someHost.com/someDir/apage", "someHost.com/someDir"},
{"http://otherHost.com/someDir/apage", "someDir"},
{"http://otherHost.com/aDir/apage", "Default"},
+ // redirections for trees
+ {"http://localhost/someDir", "/someDir/"},
+ {"http://someHost.com/someDir", "/someDir/"},
}
func TestHostHandlers(t *testing.T) {
@@ -199,9 +207,19 @@ func TestHostHandlers(t *testing.T) {
t.Errorf("reading response: %v", err)
continue
}
- s := r.Header.Get("Result")
- if s != vt.expected {
- t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
+ switch r.StatusCode {
+ case StatusOK:
+ s := r.Header.Get("Result")
+ if s != vt.expected {
+ t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
+ }
+ case StatusMovedPermanently:
+ s := r.Header.Get("Location")
+ if s != vt.expected {
+ t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
+ }
+ default:
+ t.Errorf("Get(%q) unhandled status code %d", vt.url, r.StatusCode)
}
}
}
@@ -370,7 +388,7 @@ func TestIdentityResponse(t *testing.T) {
})
}
-func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
+func testTCPConnectionCloses(t *testing.T, req string, h Handler) {
s := httptest.NewServer(h)
defer s.Close()
@@ -414,21 +432,28 @@ func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
// TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive.
func TestServeHTTP10Close(t *testing.T) {
- testTcpConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+ testTCPConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
ServeFile(w, r, "testdata/file")
}))
}
+// TestClientCanClose verifies that clients can also force a connection to close.
+func TestClientCanClose(t *testing.T) {
+ testTCPConnectionCloses(t, "GET / HTTP/1.1\r\nConnection: close\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+ // Nothing.
+ }))
+}
+
// TestHandlersCanSetConnectionClose verifies that handlers can force a connection to close,
// even for HTTP/1.1 requests.
func TestHandlersCanSetConnectionClose11(t *testing.T) {
- testTcpConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+ testTCPConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Connection", "close")
}))
}
func TestHandlersCanSetConnectionClose10(t *testing.T) {
- testTcpConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+ testTCPConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Connection", "close")
}))
}
@@ -665,30 +690,51 @@ func TestServerExpect(t *testing.T) {
t.Fatalf("Dial: %v", err)
}
defer conn.Close()
- sendf := func(format string, args ...interface{}) {
- _, err := fmt.Fprintf(conn, format, args...)
- if err != nil {
- t.Fatalf("On test %#v, error writing %q: %v", test, format, err)
- }
- }
+
+ // Only send the body immediately if we're acting like an HTTP client
+ // that doesn't send 100-continue expectations.
+ writeBody := test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue"
+
go func() {
- sendf("POST /?readbody=%v HTTP/1.1\r\n"+
+ _, err := fmt.Fprintf(conn, "POST /?readbody=%v HTTP/1.1\r\n"+
"Connection: close\r\n"+
"Content-Length: %d\r\n"+
"Expect: %s\r\nHost: foo\r\n\r\n",
test.readBody, test.contentLength, test.expectation)
- if test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue" {
+ if err != nil {
+ t.Errorf("On test %#v, error writing request headers: %v", test, err)
+ return
+ }
+ if writeBody {
body := strings.Repeat("A", test.contentLength)
- sendf(body)
+ _, err = fmt.Fprint(conn, body)
+ if err != nil {
+ if !test.readBody {
+ // Server likely already hung up on us.
+ // See larger comment below.
+ t.Logf("On test %#v, acceptable error writing request body: %v", test, err)
+ return
+ }
+ t.Errorf("On test %#v, error writing request body: %v", test, err)
+ }
}
}()
bufr := bufio.NewReader(conn)
line, err := bufr.ReadString('\n')
if err != nil {
- t.Fatalf("ReadString: %v", err)
+ if writeBody && !test.readBody {
+ // This is an acceptable failure due to a possible TCP race:
+ // We were still writing data and the server hung up on us. A TCP
+ // implementation may send a RST if our request body data was known
+ // to be lost, which may trigger our reads to fail.
+ // See RFC 1122 page 88.
+ t.Logf("On test %#v, acceptable error from ReadString: %v", test, err)
+ return
+ }
+ t.Fatalf("On test %#v, ReadString: %v", test, err)
}
if !strings.Contains(line, test.expectedResponse) {
- t.Errorf("for test %#v got first line=%q", test, line)
+ t.Errorf("On test %#v, got first line = %q; want %q", test, line, test.expectedResponse)
}
}
@@ -1112,6 +1158,68 @@ func TestServerBufferedChunking(t *testing.T) {
}
}
+// Tests that the server flushes its response headers out when it's
+// ignoring the response body and waits a bit before forcefully
+// closing the TCP connection, causing the client to get a RST.
+// See http://golang.org/issue/3595
+func TestServerGracefulClose(t *testing.T) {
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ Error(w, "bye", StatusUnauthorized)
+ }))
+ defer ts.Close()
+
+ conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer conn.Close()
+ const bodySize = 5 << 20
+ req := []byte(fmt.Sprintf("POST / HTTP/1.1\r\nHost: foo.com\r\nContent-Length: %d\r\n\r\n", bodySize))
+ for i := 0; i < bodySize; i++ {
+ req = append(req, 'x')
+ }
+ writeErr := make(chan error)
+ go func() {
+ _, err := conn.Write(req)
+ writeErr <- err
+ }()
+ br := bufio.NewReader(conn)
+ lineNum := 0
+ for {
+ line, err := br.ReadString('\n')
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ t.Fatalf("ReadLine: %v", err)
+ }
+ lineNum++
+ if lineNum == 1 && !strings.Contains(line, "401 Unauthorized") {
+ t.Errorf("Response line = %q; want a 401", line)
+ }
+ }
+ // Wait for write to finish. This is a broken pipe on both
+ // Darwin and Linux, but checking this isn't the point of
+ // the test.
+ <-writeErr
+}
+
+func TestCaseSensitiveMethod(t *testing.T) {
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ if r.Method != "get" {
+ t.Errorf(`Got method %q; want "get"`, r.Method)
+ }
+ }))
+ defer ts.Close()
+ req, _ := NewRequest("get", ts.URL, nil)
+ res, err := DefaultClient.Do(req)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ res.Body.Close()
+}
+
// TestContentLengthZero tests that for both an HTTP/1.0 and HTTP/1.1
// request (both keep-alive), when a Handler never writes any
// response, the net/http package adds a "Content-Length: 0" response
@@ -1220,3 +1328,100 @@ func BenchmarkClientServer(b *testing.B) {
b.StopTimer()
}
+
+func BenchmarkClientServerParallel4(b *testing.B) {
+ benchmarkClientServerParallel(b, 4)
+}
+
+func BenchmarkClientServerParallel64(b *testing.B) {
+ benchmarkClientServerParallel(b, 64)
+}
+
+func benchmarkClientServerParallel(b *testing.B, conc int) {
+ b.StopTimer()
+ ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+ fmt.Fprintf(rw, "Hello world.\n")
+ }))
+ defer ts.Close()
+ b.StartTimer()
+
+ numProcs := runtime.GOMAXPROCS(-1) * conc
+ var wg sync.WaitGroup
+ wg.Add(numProcs)
+ n := int32(b.N)
+ for p := 0; p < numProcs; p++ {
+ go func() {
+ for atomic.AddInt32(&n, -1) >= 0 {
+ res, err := Get(ts.URL)
+ if err != nil {
+ b.Logf("Get: %v", err)
+ continue
+ }
+ all, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ b.Logf("ReadAll: %v", err)
+ continue
+ }
+ body := string(all)
+ if body != "Hello world.\n" {
+ panic("Got body: " + body)
+ }
+ }
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+}
+
+// A benchmark for profiling the server without the HTTP client code.
+// The client code runs in a subprocess.
+//
+// For use like:
+// $ go test -c
+// $ ./http.test -test.run=XX -test.bench=BenchmarkServer -test.benchtime=15s -test.cpuprofile=http.prof
+// $ go tool pprof http.test http.prof
+// (pprof) web
+func BenchmarkServer(b *testing.B) {
+ // Child process mode;
+ if url := os.Getenv("TEST_BENCH_SERVER_URL"); url != "" {
+ n, err := strconv.Atoi(os.Getenv("TEST_BENCH_CLIENT_N"))
+ if err != nil {
+ panic(err)
+ }
+ for i := 0; i < n; i++ {
+ res, err := Get(url)
+ if err != nil {
+ log.Panicf("Get: %v", err)
+ }
+ all, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ log.Panicf("ReadAll: %v", err)
+ }
+ body := string(all)
+ if body != "Hello world.\n" {
+ log.Panicf("Got body: %q", body)
+ }
+ }
+ os.Exit(0)
+ return
+ }
+
+ var res = []byte("Hello world.\n")
+ b.StopTimer()
+ ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+ rw.Header().Set("Content-Type", "text/html; charset=utf-8")
+ rw.Write(res)
+ }))
+ defer ts.Close()
+ b.StartTimer()
+
+ cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkServer")
+ cmd.Env = append([]string{
+ fmt.Sprintf("TEST_BENCH_CLIENT_N=%d", b.N),
+ fmt.Sprintf("TEST_BENCH_SERVER_URL=%s", ts.URL),
+ }, os.Environ()...)
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ b.Errorf("Test failure: %v, with output: %s", err, out)
+ }
+}
diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go
index b74b7629809..ee57e01276d 100644
--- a/libgo/go/net/http/server.go
+++ b/libgo/go/net/http/server.go
@@ -129,7 +129,7 @@ type response struct {
// maxBytesReader hits its max size. It is checked in
// WriteHeader, to make sure we don't consume the the
// remaining request body to try to advance to the next HTTP
- // request. Instead, when this is set, we stop doing
+ // request. Instead, when this is set, we stop reading
// subsequent requests on this connection and stop reading
// input from it.
requestBodyLimitHit bool
@@ -287,7 +287,7 @@ func (w *response) WriteHeader(code int) {
// Check for a explicit (and valid) Content-Length header.
var hasCL bool
var contentLength int64
- if clenStr := w.header.Get("Content-Length"); clenStr != "" {
+ if clenStr := w.header.get("Content-Length"); clenStr != "" {
var err error
contentLength, err = strconv.ParseInt(clenStr, 10, 64)
if err == nil {
@@ -303,12 +303,11 @@ func (w *response) WriteHeader(code int) {
if !connectionHeaderSet {
w.header.Set("Connection", "keep-alive")
}
- } else if !w.req.ProtoAtLeast(1, 1) {
- // Client did not ask to keep connection alive.
+ } else if !w.req.ProtoAtLeast(1, 1) || w.req.wantsClose() {
w.closeAfterReply = true
}
- if w.header.Get("Connection") == "close" {
+ if w.header.get("Connection") == "close" {
w.closeAfterReply = true
}
@@ -332,7 +331,7 @@ func (w *response) WriteHeader(code int) {
if code == StatusNotModified {
// Must not have body.
for _, header := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} {
- if w.header.Get(header) != "" {
+ if w.header.get(header) != "" {
// TODO: return an error if WriteHeader gets a return parameter
// or set a flag on w to make future Writes() write an error page?
// for now just log and drop the header.
@@ -342,7 +341,7 @@ func (w *response) WriteHeader(code int) {
}
} else {
// If no content type, apply sniffing algorithm to body.
- if w.header.Get("Content-Type") == "" && w.req.Method != "HEAD" {
+ if w.header.get("Content-Type") == "" && w.req.Method != "HEAD" {
w.needSniff = true
}
}
@@ -351,7 +350,7 @@ func (w *response) WriteHeader(code int) {
w.Header().Set("Date", time.Now().UTC().Format(TimeFormat))
}
- te := w.header.Get("Transfer-Encoding")
+ te := w.header.get("Transfer-Encoding")
hasTE := te != ""
if hasCL && hasTE && te != "identity" {
// TODO: return an error if WriteHeader gets a return parameter
@@ -391,7 +390,7 @@ func (w *response) WriteHeader(code int) {
return
}
- if w.closeAfterReply && !hasToken(w.header.Get("Connection"), "close") {
+ if w.closeAfterReply && !hasToken(w.header.get("Connection"), "close") {
w.header.Set("Connection", "close")
}
@@ -518,14 +517,14 @@ func (w *response) finishRequest() {
// HTTP/1.0 clients keep their "keep-alive" connections alive, and for
// HTTP/1.1 clients is just as good as the alternative: sending a
// chunked response and immediately sending the zero-length EOF chunk.
- if w.written == 0 && w.header.Get("Content-Length") == "" {
+ if w.written == 0 && w.header.get("Content-Length") == "" {
w.header.Set("Content-Length", "0")
}
// If this was an HTTP/1.0 request with keep-alive and we sent a
// Content-Length back, we can make this a keep-alive response ...
if w.req.wantsHttp10KeepAlive() {
- sentLength := w.header.Get("Content-Length") != ""
- if sentLength && w.header.Get("Connection") == "keep-alive" {
+ sentLength := w.header.get("Content-Length") != ""
+ if sentLength && w.header.get("Connection") == "keep-alive" {
w.closeAfterReply = false
}
}
@@ -564,18 +563,31 @@ func (w *response) Flush() {
w.conn.buf.Flush()
}
-// Close the connection.
-func (c *conn) close() {
+func (c *conn) finalFlush() {
if c.buf != nil {
c.buf.Flush()
c.buf = nil
}
+}
+
+// Close the connection.
+func (c *conn) close() {
+ c.finalFlush()
if c.rwc != nil {
c.rwc.Close()
c.rwc = nil
}
}
+// closeWrite flushes any outstanding data and sends a FIN packet (if client
+// is connected via TCP), signalling that we're done.
+func (c *conn) closeWrite() {
+ c.finalFlush()
+ if tcp, ok := c.rwc.(*net.TCPConn); ok {
+ tcp.CloseWrite()
+ }
+}
+
// Serve a new connection.
func (c *conn) serve() {
defer func() {
@@ -637,7 +649,7 @@ func (c *conn) serve() {
break
}
req.Header.Del("Expect")
- } else if req.Header.Get("Expect") != "" {
+ } else if req.Header.get("Expect") != "" {
// TODO(bradfitz): let ServeHTTP handlers handle
// requests with non-standard expectation[s]? Seems
// theoretical at best, and doesn't fit into the
@@ -672,6 +684,20 @@ func (c *conn) serve() {
}
w.finishRequest()
if w.closeAfterReply {
+ if w.requestBodyLimitHit {
+ // Flush our response and send a FIN packet and wait a bit
+ // before closing the connection, so the client has a chance
+ // to read our response before they possibly get a RST from
+ // our TCP stack from ignoring their unread body.
+ // See http://golang.org/issue/3595
+ c.closeWrite()
+ // Now wait a bit for our machine to send the FIN and the client's
+ // machine's HTTP client to read the request before we close
+ // the connection, which might send a RST (on BSDs, at least).
+ // 250ms is somewhat arbitrary (~latency around half the planet),
+ // but this doesn't need to be a full second probably.
+ time.Sleep(250 * time.Millisecond)
+ }
break
}
}
@@ -849,13 +875,15 @@ func RedirectHandler(url string, code int) Handler {
// redirecting any request containing . or .. elements to an
// equivalent .- and ..-free URL.
type ServeMux struct {
- mu sync.RWMutex
- m map[string]muxEntry
+ mu sync.RWMutex
+ m map[string]muxEntry
+ hosts bool // whether any patterns contain hostnames
}
type muxEntry struct {
explicit bool
h Handler
+ pattern string
}
// NewServeMux allocates and returns a new ServeMux.
@@ -896,8 +924,7 @@ func cleanPath(p string) string {
// Find a handler on a handler map given a path string
// Most-specific (longest) pattern wins
-func (mux *ServeMux) match(path string) Handler {
- var h Handler
+func (mux *ServeMux) match(path string) (h Handler, pattern string) {
var n = 0
for k, v := range mux.m {
if !pathMatch(k, path) {
@@ -906,39 +933,59 @@ func (mux *ServeMux) match(path string) Handler {
if h == nil || len(k) > n {
n = len(k)
h = v.h
+ pattern = v.pattern
+ }
+ }
+ return
+}
+
+// Handler returns the handler to use for the given request,
+// consulting r.Method, r.Host, and r.URL.Path. It always returns
+// a non-nil handler. If the path is not in its canonical form, the
+// handler will be an internally-generated handler that redirects
+// to the canonical path.
+//
+// Handler also returns the registered pattern that matches the
+// request or, in the case of internally-generated redirects,
+// the pattern that will match after following the redirect.
+//
+// If there is no registered handler that applies to the request,
+// Handler returns a ``page not found'' handler and an empty pattern.
+func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
+ if r.Method != "CONNECT" {
+ if p := cleanPath(r.URL.Path); p != r.URL.Path {
+ _, pattern = mux.handler(r.Host, p)
+ return RedirectHandler(p, StatusMovedPermanently), pattern
}
}
- return h
+
+ return mux.handler(r.Host, r.URL.Path)
}
-// handler returns the handler to use for the request r.
-func (mux *ServeMux) handler(r *Request) Handler {
+// handler is the main implementation of Handler.
+// The path is known to be in canonical form, except for CONNECT methods.
+func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
mux.mu.RLock()
defer mux.mu.RUnlock()
// Host-specific pattern takes precedence over generic ones
- h := mux.match(r.Host + r.URL.Path)
+ if mux.hosts {
+ h, pattern = mux.match(host + path)
+ }
if h == nil {
- h = mux.match(r.URL.Path)
+ h, pattern = mux.match(path)
}
if h == nil {
- h = NotFoundHandler()
+ h, pattern = NotFoundHandler(), ""
}
- return h
+ return
}
// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
- if r.Method != "CONNECT" {
- // Clean path to canonical form and redirect.
- if p := cleanPath(r.URL.Path); p != r.URL.Path {
- w.Header().Set("Location", p)
- w.WriteHeader(StatusMovedPermanently)
- return
- }
- }
- mux.handler(r).ServeHTTP(w, r)
+ h, _ := mux.Handler(r)
+ h.ServeHTTP(w, r)
}
// Handle registers the handler for the given pattern.
@@ -957,14 +1004,26 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
panic("http: multiple registrations for " + pattern)
}
- mux.m[pattern] = muxEntry{explicit: true, h: handler}
+ mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}
+
+ if pattern[0] != '/' {
+ mux.hosts = true
+ }
// Helpful behavior:
// If pattern is /tree/, insert an implicit permanent redirect for /tree.
// It can be overridden by an explicit registration.
n := len(pattern)
if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {
- mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(pattern, StatusMovedPermanently)}
+ // If pattern contains a host name, strip it and use remaining
+ // path for redirect.
+ path := pattern
+ if pattern[0] != '/' {
+ // In pattern, at least the last character is a '/', so
+ // strings.Index can't be -1.
+ path = pattern[strings.Index(pattern, "/"):]
+ }
+ mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(path, StatusMovedPermanently), pattern: pattern}
}
}
diff --git a/libgo/go/net/http/server_test.go b/libgo/go/net/http/server_test.go
new file mode 100644
index 00000000000..8b4e8c6d6f6
--- /dev/null
+++ b/libgo/go/net/http/server_test.go
@@ -0,0 +1,95 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http
+
+import (
+ "net/url"
+ "testing"
+)
+
+var serveMuxRegister = []struct {
+ pattern string
+ h Handler
+}{
+ {"/dir/", serve(200)},
+ {"/search", serve(201)},
+ {"codesearch.google.com/search", serve(202)},
+ {"codesearch.google.com/", serve(203)},
+}
+
+// serve returns a handler that sends a response with the given code.
+func serve(code int) HandlerFunc {
+ return func(w ResponseWriter, r *Request) {
+ w.WriteHeader(code)
+ }
+}
+
+var serveMuxTests = []struct {
+ method string
+ host string
+ path string
+ code int
+ pattern string
+}{
+ {"GET", "google.com", "/", 404, ""},
+ {"GET", "google.com", "/dir", 301, "/dir/"},
+ {"GET", "google.com", "/dir/", 200, "/dir/"},
+ {"GET", "google.com", "/dir/file", 200, "/dir/"},
+ {"GET", "google.com", "/search", 201, "/search"},
+ {"GET", "google.com", "/search/", 404, ""},
+ {"GET", "google.com", "/search/foo", 404, ""},
+ {"GET", "codesearch.google.com", "/search", 202, "codesearch.google.com/search"},
+ {"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"},
+ {"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"},
+ {"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"},
+ {"GET", "images.google.com", "/search", 201, "/search"},
+ {"GET", "images.google.com", "/search/", 404, ""},
+ {"GET", "images.google.com", "/search/foo", 404, ""},
+ {"GET", "google.com", "/../search", 301, "/search"},
+ {"GET", "google.com", "/dir/..", 301, ""},
+ {"GET", "google.com", "/dir/..", 301, ""},
+ {"GET", "google.com", "/dir/./file", 301, "/dir/"},
+
+ // The /foo -> /foo/ redirect applies to CONNECT requests
+ // but the path canonicalization does not.
+ {"CONNECT", "google.com", "/dir", 301, "/dir/"},
+ {"CONNECT", "google.com", "/../search", 404, ""},
+ {"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
+ {"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
+ {"CONNECT", "google.com", "/dir/./file", 200, "/dir/"},
+}
+
+func TestServeMuxHandler(t *testing.T) {
+ mux := NewServeMux()
+ for _, e := range serveMuxRegister {
+ mux.Handle(e.pattern, e.h)
+ }
+
+ for _, tt := range serveMuxTests {
+ r := &Request{
+ Method: tt.method,
+ Host: tt.host,
+ URL: &url.URL{
+ Path: tt.path,
+ },
+ }
+ h, pattern := mux.Handler(r)
+ cs := &codeSaver{h: Header{}}
+ h.ServeHTTP(cs, r)
+ if pattern != tt.pattern || cs.code != tt.code {
+ t.Errorf("%s %s %s = %d, %q, want %d, %q", tt.method, tt.host, tt.path, cs.code, pattern, tt.code, tt.pattern)
+ }
+ }
+}
+
+// A codeSaver is a ResponseWriter that saves the code passed to WriteHeader.
+type codeSaver struct {
+ h Header
+ code int
+}
+
+func (cs *codeSaver) Header() Header { return cs.h }
+func (cs *codeSaver) Write(p []byte) (int, error) { return len(p), nil }
+func (cs *codeSaver) WriteHeader(code int) { cs.code = code }
diff --git a/libgo/go/net/http/transfer.go b/libgo/go/net/http/transfer.go
index 9e9d84172d0..1fc1e63a960 100644
--- a/libgo/go/net/http/transfer.go
+++ b/libgo/go/net/http/transfer.go
@@ -432,7 +432,7 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
}
// Logic based on Content-Length
- cl := strings.TrimSpace(header.Get("Content-Length"))
+ cl := strings.TrimSpace(header.get("Content-Length"))
if cl != "" {
n, err := strconv.ParseInt(cl, 10, 64)
if err != nil || n < 0 {
@@ -454,7 +454,7 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
// Logic based on media type. The purpose of the following code is just
// to detect whether the unsupported "multipart/byteranges" is being
// used. A proper Content-Type parser is needed in the future.
- if strings.Contains(strings.ToLower(header.Get("Content-Type")), "multipart/byteranges") {
+ if strings.Contains(strings.ToLower(header.get("Content-Type")), "multipart/byteranges") {
return -1, ErrNotSupported
}
@@ -469,14 +469,14 @@ func shouldClose(major, minor int, header Header) bool {
if major < 1 {
return true
} else if major == 1 && minor == 0 {
- if !strings.Contains(strings.ToLower(header.Get("Connection")), "keep-alive") {
+ if !strings.Contains(strings.ToLower(header.get("Connection")), "keep-alive") {
return true
}
return false
} else {
// TODO: Should split on commas, toss surrounding white space,
// and check each field.
- if strings.ToLower(header.Get("Connection")) == "close" {
+ if strings.ToLower(header.get("Connection")) == "close" {
header.Del("Connection")
return true
}
@@ -486,7 +486,7 @@ func shouldClose(major, minor int, header Header) bool {
// Parse the trailer header
func fixTrailer(header Header, te []string) (Header, error) {
- raw := header.Get("Trailer")
+ raw := header.get("Trailer")
if raw == "" {
return nil, nil
}
diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go
index 6131d0d1ee1..651f3ce0081 100644
--- a/libgo/go/net/http/transport.go
+++ b/libgo/go/net/http/transport.go
@@ -24,6 +24,7 @@ import (
"os"
"strings"
"sync"
+ "time"
)
// DefaultTransport is the default implementation of Transport and is
@@ -265,6 +266,11 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
pconn.close()
return false
}
+ for _, exist := range t.idleConn[key] {
+ if exist == pconn {
+ log.Fatalf("dup idle pconn %p in freelist", pconn)
+ }
+ }
t.idleConn[key] = append(t.idleConn[key], pconn)
t.idleLk.Unlock()
return true
@@ -295,7 +301,7 @@ func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
return
}
}
- return
+ panic("unreachable")
}
func (t *Transport) dial(network, addr string) (c net.Conn, err error) {
@@ -329,6 +335,8 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
cacheKey: cm.String(),
conn: conn,
reqch: make(chan requestAndChan, 50),
+ writech: make(chan writeRequest, 50),
+ closech: make(chan struct{}),
}
switch {
@@ -373,7 +381,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
// Initiate TLS and check remote host name against certificate.
cfg := t.TLSClientConfig
if cfg == nil || cfg.ServerName == "" {
- host, _, _ := net.SplitHostPort(cm.addr())
+ host := cm.tlsHost()
if cfg == nil {
cfg = &tls.Config{ServerName: host}
} else {
@@ -397,6 +405,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
pconn.br = bufio.NewReader(pconn.conn)
pconn.bw = bufio.NewWriter(pconn.conn)
go pconn.readLoop()
+ go pconn.writeLoop()
return pconn, nil
}
@@ -504,7 +513,9 @@ type persistConn struct {
closed bool // whether conn has been closed
br *bufio.Reader // from conn
bw *bufio.Writer // to conn
- reqch chan requestAndChan // written by roundTrip(); read by readLoop()
+ reqch chan requestAndChan // written by roundTrip; read by readLoop
+ writech chan writeRequest // written by roundTrip; read by writeLoop
+ closech chan struct{} // broadcast close when readLoop (TCP connection) closes
isProxy bool
// mutateHeaderFunc is an optional func to modify extra
@@ -537,6 +548,7 @@ func remoteSideClosed(err error) bool {
}
func (pc *persistConn) readLoop() {
+ defer close(pc.closech)
alive := true
var lastbody io.ReadCloser // last response body, if any, read on this connection
@@ -563,7 +575,11 @@ func (pc *persistConn) readLoop() {
lastbody.Close() // assumed idempotent
lastbody = nil
}
- resp, err := ReadResponse(pc.br, rc.req)
+
+ var resp *Response
+ if err == nil {
+ resp, err = ReadResponse(pc.br, rc.req)
+ }
if err != nil {
pc.close()
@@ -592,12 +608,12 @@ func (pc *persistConn) readLoop() {
var waitForBodyRead chan bool
if hasBody {
lastbody = resp.Body
- waitForBodyRead = make(chan bool)
+ waitForBodyRead = make(chan bool, 1)
resp.Body.(*bodyEOFSignal).fn = func() {
if alive && !pc.t.putIdleConn(pc) {
alive = false
}
- if !alive {
+ if !alive || pc.isBroken() {
pc.close()
}
waitForBodyRead <- true
@@ -633,6 +649,28 @@ func (pc *persistConn) readLoop() {
}
}
+func (pc *persistConn) writeLoop() {
+ for {
+ select {
+ case wr := <-pc.writech:
+ if pc.isBroken() {
+ wr.ch <- errors.New("http: can't write HTTP request on broken connection")
+ continue
+ }
+ err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra)
+ if err == nil {
+ err = pc.bw.Flush()
+ }
+ if err != nil {
+ pc.markBroken()
+ }
+ wr.ch <- err
+ case <-pc.closech:
+ return
+ }
+ }
+}
+
type responseAndError struct {
res *Response
err error
@@ -648,6 +686,15 @@ type requestAndChan struct {
addedGzip bool
}
+// A writeRequest is sent by the readLoop's goroutine to the
+// writeLoop's goroutine to write a request while the read loop
+// concurrently waits on both the write response and the server's
+// reply.
+type writeRequest struct {
+ req *transportRequest
+ ch chan<- error
+}
+
func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) {
if pc.mutateHeaderFunc != nil {
pc.mutateHeaderFunc(req.extraHeaders())
@@ -670,16 +717,49 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
pc.numExpectedResponses++
pc.lk.Unlock()
- err = req.Request.write(pc.bw, pc.isProxy, req.extra)
- if err != nil {
- pc.close()
- return
+ // Write the request concurrently with waiting for a response,
+ // in case the server decides to reply before reading our full
+ // request body.
+ writeErrCh := make(chan error, 1)
+ pc.writech <- writeRequest{req, writeErrCh}
+
+ resc := make(chan responseAndError, 1)
+ pc.reqch <- requestAndChan{req.Request, resc, requestedGzip}
+
+ var re responseAndError
+ var pconnDeadCh = pc.closech
+ var failTicker <-chan time.Time
+WaitResponse:
+ for {
+ select {
+ case err := <-writeErrCh:
+ if err != nil {
+ re = responseAndError{nil, err}
+ break WaitResponse
+ }
+ case <-pconnDeadCh:
+ // The persist connection is dead. This shouldn't
+ // usually happen (only with Connection: close responses
+ // with no response bodies), but if it does happen it
+ // means either a) the remote server hung up on us
+ // prematurely, or b) the readLoop sent us a response &
+ // closed its closech at roughly the same time, and we
+ // selected this case first, in which case a response
+ // might still be coming soon.
+ //
+ // We can't avoid the select race in b) by using a unbuffered
+ // resc channel instead, because then goroutines can
+ // leak if we exit due to other errors.
+ pconnDeadCh = nil // avoid spinning
+ failTicker = time.After(100 * time.Millisecond) // arbitrary time to wait for resc
+ case <-failTicker:
+ re = responseAndError{nil, errors.New("net/http: transport closed before response was received")}
+ break WaitResponse
+ case re = <-resc:
+ break WaitResponse
+ }
}
- pc.bw.Flush()
- ch := make(chan responseAndError, 1)
- pc.reqch <- requestAndChan{req.Request, ch, requestedGzip}
- re := <-ch
pc.lk.Lock()
pc.numExpectedResponses--
pc.lk.Unlock()
@@ -687,6 +767,15 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
return re.res, re.err
}
+// markBroken marks a connection as broken (so it's not reused).
+// It differs from close in that it doesn't close the underlying
+// connection for use when it's still being read.
+func (pc *persistConn) markBroken() {
+ pc.lk.Lock()
+ defer pc.lk.Unlock()
+ pc.broken = true
+}
+
func (pc *persistConn) close() {
pc.lk.Lock()
defer pc.lk.Unlock()
@@ -728,6 +817,7 @@ type bodyEOFSignal struct {
body io.ReadCloser
fn func()
isClosed bool
+ once sync.Once
}
func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
@@ -735,9 +825,8 @@ func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
if es.isClosed && n > 0 {
panic("http: unexpected bodyEOFSignal Read after Close; see issue 1725")
}
- if err == io.EOF && es.fn != nil {
- es.fn()
- es.fn = nil
+ if err == io.EOF {
+ es.condfn()
}
return
}
@@ -748,13 +837,18 @@ func (es *bodyEOFSignal) Close() (err error) {
}
es.isClosed = true
err = es.body.Close()
- if err == nil && es.fn != nil {
- es.fn()
- es.fn = nil
+ if err == nil {
+ es.condfn()
}
return
}
+func (es *bodyEOFSignal) condfn() {
+ if es.fn != nil {
+ es.once.Do(es.fn)
+ }
+}
+
type readFirstCloseBoth struct {
io.ReadCloser
io.Closer
diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go
index e676bf6db39..e4072e88fed 100644
--- a/libgo/go/net/http/transport_test.go
+++ b/libgo/go/net/http/transport_test.go
@@ -833,6 +833,74 @@ func TestIssue3644(t *testing.T) {
}
}
+// Test that a client receives a server's reply, even if the server doesn't read
+// the entire request body.
+func TestIssue3595(t *testing.T) {
+ const deniedMsg = "sorry, denied."
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ Error(w, deniedMsg, StatusUnauthorized)
+ }))
+ defer ts.Close()
+ tr := &Transport{}
+ c := &Client{Transport: tr}
+ res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a'))
+ if err != nil {
+ t.Errorf("Post: %v", err)
+ return
+ }
+ got, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatalf("Body ReadAll: %v", err)
+ }
+ if !strings.Contains(string(got), deniedMsg) {
+ t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg)
+ }
+}
+
+func TestTransportConcurrency(t *testing.T) {
+ const maxProcs = 16
+ const numReqs = 500
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ fmt.Fprintf(w, "%v", r.FormValue("echo"))
+ }))
+ defer ts.Close()
+ tr := &Transport{}
+ c := &Client{Transport: tr}
+ reqs := make(chan string)
+ defer close(reqs)
+
+ var wg sync.WaitGroup
+ wg.Add(numReqs)
+ for i := 0; i < maxProcs*2; i++ {
+ go func() {
+ for req := range reqs {
+ res, err := c.Get(ts.URL + "/?echo=" + req)
+ if err != nil {
+ t.Errorf("error on req %s: %v", req, err)
+ wg.Done()
+ continue
+ }
+ all, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Errorf("read error on req %s: %v", req, err)
+ wg.Done()
+ continue
+ }
+ if string(all) != req {
+ t.Errorf("body of req %s = %q; want %q", req, all, req)
+ }
+ wg.Done()
+ res.Body.Close()
+ }
+ }()
+ }
+ for i := 0; i < numReqs; i++ {
+ reqs <- fmt.Sprintf("request-%d", i)
+ }
+ wg.Wait()
+}
+
type fooProto struct{}
func (fooProto) RoundTrip(req *Request) (*Response, error) {
diff --git a/libgo/go/net/interface_test.go b/libgo/go/net/interface_test.go
index 0a33bfdb517..2fe0f60caea 100644
--- a/libgo/go/net/interface_test.go
+++ b/libgo/go/net/interface_test.go
@@ -24,7 +24,7 @@ func TestInterfaces(t *testing.T) {
if err != nil {
t.Fatalf("Interfaces failed: %v", err)
}
- t.Logf("table: len/cap = %v/%v\n", len(ift), cap(ift))
+ t.Logf("table: len/cap = %v/%v", len(ift), cap(ift))
for _, ifi := range ift {
ifxi, err := InterfaceByIndex(ifi.Index)
@@ -41,7 +41,7 @@ func TestInterfaces(t *testing.T) {
if !sameInterface(ifxn, &ifi) {
t.Fatalf("InterfaceByName(%q) = %v, want %v", ifi.Name, *ifxn, ifi)
}
- t.Logf("%q: flags %q, ifindex %v, mtu %v\n", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
+ t.Logf("%q: flags %q, ifindex %v, mtu %v", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
t.Logf("\thardware address %q", ifi.HardwareAddr.String())
testInterfaceAddrs(t, &ifi)
testInterfaceMulticastAddrs(t, &ifi)
@@ -53,7 +53,7 @@ func TestInterfaceAddrs(t *testing.T) {
if err != nil {
t.Fatalf("InterfaceAddrs failed: %v", err)
}
- t.Logf("table: len/cap = %v/%v\n", len(ifat), cap(ifat))
+ t.Logf("table: len/cap = %v/%v", len(ifat), cap(ifat))
testAddrs(t, ifat)
}
@@ -77,7 +77,7 @@ func testAddrs(t *testing.T, ifat []Addr) {
for _, ifa := range ifat {
switch ifa.(type) {
case *IPAddr, *IPNet:
- t.Logf("\tinterface address %q\n", ifa.String())
+ t.Logf("\tinterface address %q", ifa.String())
default:
t.Errorf("\tunexpected type: %T", ifa)
}
@@ -88,7 +88,7 @@ func testMulticastAddrs(t *testing.T, ifmat []Addr) {
for _, ifma := range ifmat {
switch ifma.(type) {
case *IPAddr:
- t.Logf("\tjoined group address %q\n", ifma.String())
+ t.Logf("\tjoined group address %q", ifma.String())
default:
t.Errorf("\tunexpected type: %T", ifma)
}
diff --git a/libgo/go/net/ipraw_test.go b/libgo/go/net/ipraw_test.go
index 6136202727c..d37272c1062 100644
--- a/libgo/go/net/ipraw_test.go
+++ b/libgo/go/net/ipraw_test.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 !plan9
+
package net
import (
@@ -24,7 +26,7 @@ var icmpTests = []struct {
func TestICMP(t *testing.T) {
if os.Getuid() != 0 {
- t.Logf("test disabled; must be root")
+ t.Logf("skipping test; must be root")
return
}
diff --git a/libgo/go/net/iprawsock_plan9.go b/libgo/go/net/iprawsock_plan9.go
index ea3321b7e2f..6de2ee33d84 100644
--- a/libgo/go/net/iprawsock_plan9.go
+++ b/libgo/go/net/iprawsock_plan9.go
@@ -7,14 +7,37 @@
package net
import (
+ "os"
"syscall"
"time"
)
-// IPConn is the implementation of the Conn and PacketConn
-// interfaces for IP network connections.
+// IPConn is the implementation of the Conn and PacketConn interfaces
+// for IP network connections.
type IPConn bool
+// Implementation of the Conn interface - see Conn for documentation.
+
+// Read implements the Conn Read method.
+func (c *IPConn) Read(b []byte) (int, error) {
+ return 0, syscall.EPLAN9
+}
+
+// Write implements the Conn Write method.
+func (c *IPConn) Write(b []byte) (int, error) {
+ return 0, syscall.EPLAN9
+}
+
+// LocalAddr returns the local network address.
+func (c *IPConn) LocalAddr() Addr {
+ return nil
+}
+
+// RemoteAddr returns the remote network address.
+func (c *IPConn) RemoteAddr() Addr {
+ return nil
+}
+
// SetDeadline implements the Conn SetDeadline method.
func (c *IPConn) SetDeadline(t time.Time) error {
return syscall.EPLAN9
@@ -30,16 +53,23 @@ func (c *IPConn) SetWriteDeadline(t time.Time) error {
return syscall.EPLAN9
}
-// Implementation of the Conn interface - see Conn for documentation.
+// SetReadBuffer sets the size of the operating system's receive
+// buffer associated with the connection.
+func (c *IPConn) SetReadBuffer(bytes int) error {
+ return syscall.EPLAN9
+}
-// Read implements the Conn Read method.
-func (c *IPConn) Read(b []byte) (int, error) {
- return 0, syscall.EPLAN9
+// SetWriteBuffer sets the size of the operating system's transmit
+// buffer associated with the connection.
+func (c *IPConn) SetWriteBuffer(bytes int) error {
+ return syscall.EPLAN9
}
-// Write implements the Conn Write method.
-func (c *IPConn) Write(b []byte) (int, error) {
- return 0, syscall.EPLAN9
+// File returns a copy of the underlying os.File, set to blocking
+// mode. It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (c *IPConn) File() (f *os.File, err error) {
+ return nil, syscall.EPLAN9
}
// Close closes the IP connection.
@@ -47,16 +77,6 @@ func (c *IPConn) Close() error {
return syscall.EPLAN9
}
-// LocalAddr returns the local network address.
-func (c *IPConn) LocalAddr() Addr {
- return nil
-}
-
-// RemoteAddr returns the remote network address, a *IPAddr.
-func (c *IPConn) RemoteAddr() Addr {
- return nil
-}
-
// IP-specific methods.
// ReadFromIP reads an IP packet from c, copying the payload into b.
@@ -75,12 +95,21 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
return 0, nil, syscall.EPLAN9
}
-// WriteToIP writes an IP packet to addr via c, copying the payload from b.
+// ReadMsgIP reads a packet from c, copying the payload into b and the
+// associdated out-of-band data into oob. It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet and the source address of the packet.
+func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
+ return 0, 0, 0, nil, syscall.EPLAN9
+}
+
+// WriteToIP writes an IP packet to addr via c, copying the payload
+// from b.
//
-// WriteToIP can be made to time out and return
-// an error with Timeout() == true after a fixed time limit;
-// see SetDeadline and SetWriteDeadline.
-// On packet-oriented connections, write timeouts are rare.
+// WriteToIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline. On packet-oriented connections, write timeouts
+// are rare.
func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
return 0, syscall.EPLAN9
}
@@ -90,16 +119,24 @@ func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
return 0, syscall.EPLAN9
}
-// DialIP connects to the remote address raddr on the network protocol netProto,
-// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
+// WriteMsgIP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob. It returns the
+// number of payload and out-of-band bytes written.
+func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
+ return 0, 0, syscall.EPLAN9
+}
+
+// DialIP connects to the remote address raddr on the network protocol
+// netProto, which must be "ip", "ip4", or "ip6" followed by a colon
+// and a protocol number or name.
func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
return nil, syscall.EPLAN9
}
-// ListenIP listens for incoming IP packets addressed to the
-// local address laddr. The returned connection c's ReadFrom
-// and WriteTo methods can be used to receive and send IP
-// packets with per-packet addressing.
+// ListenIP listens for incoming IP packets addressed to the local
+// address laddr. The returned connection c's ReadFrom and WriteTo
+// methods can be used to receive and send IP packets with per-packet
+// addressing.
func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
return nil, syscall.EPLAN9
}
diff --git a/libgo/go/net/iprawsock_posix.go b/libgo/go/net/iprawsock_posix.go
index dda81ddf881..d0f0b567ac8 100644
--- a/libgo/go/net/iprawsock_posix.go
+++ b/libgo/go/net/iprawsock_posix.go
@@ -9,9 +9,7 @@
package net
import (
- "os"
"syscall"
- "time"
)
func sockaddrToIP(sa syscall.Sockaddr) Addr {
@@ -55,94 +53,10 @@ func (a *IPAddr) toAddr() sockaddr {
// IPConn is the implementation of the Conn and PacketConn
// interfaces for IP network connections.
type IPConn struct {
- fd *netFD
+ conn
}
-func newIPConn(fd *netFD) *IPConn { return &IPConn{fd} }
-
-func (c *IPConn) ok() bool { return c != nil && c.fd != nil }
-
-// Implementation of the Conn interface - see Conn for documentation.
-
-// Read implements the Conn Read method.
-func (c *IPConn) Read(b []byte) (int, error) {
- n, _, err := c.ReadFrom(b)
- return n, err
-}
-
-// Write implements the Conn Write method.
-func (c *IPConn) Write(b []byte) (int, error) {
- if !c.ok() {
- return 0, syscall.EINVAL
- }
- return c.fd.Write(b)
-}
-
-// Close closes the IP connection.
-func (c *IPConn) Close() error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return c.fd.Close()
-}
-
-// LocalAddr returns the local network address.
-func (c *IPConn) LocalAddr() Addr {
- if !c.ok() {
- return nil
- }
- return c.fd.laddr
-}
-
-// RemoteAddr returns the remote network address, a *IPAddr.
-func (c *IPConn) RemoteAddr() Addr {
- if !c.ok() {
- return nil
- }
- return c.fd.raddr
-}
-
-// SetDeadline implements the Conn SetDeadline method.
-func (c *IPConn) SetDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setDeadline(c.fd, t)
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *IPConn) SetReadDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setReadDeadline(c.fd, t)
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *IPConn) SetWriteDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setWriteDeadline(c.fd, t)
-}
-
-// SetReadBuffer sets the size of the operating system's
-// receive buffer associated with the connection.
-func (c *IPConn) SetReadBuffer(bytes int) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setReadBuffer(c.fd, bytes)
-}
-
-// SetWriteBuffer sets the size of the operating system's
-// transmit buffer associated with the connection.
-func (c *IPConn) SetWriteBuffer(bytes int) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setWriteBuffer(c.fd, bytes)
-}
+func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
// IP-specific methods.
@@ -184,6 +98,25 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
return n, uaddr.toAddr(), err
}
+// ReadMsgIP reads a packet from c, copying the payload into b and the
+// associdated out-of-band data into oob. It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet and the source address of the packet.
+func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
+ if !c.ok() {
+ return 0, 0, 0, nil, syscall.EINVAL
+ }
+ var sa syscall.Sockaddr
+ n, oobn, flags, sa, err = c.fd.ReadMsg(b, oob)
+ switch sa := sa.(type) {
+ case *syscall.SockaddrInet4:
+ addr = &IPAddr{sa.Addr[0:]}
+ case *syscall.SockaddrInet6:
+ addr = &IPAddr{sa.Addr[0:]}
+ }
+ return
+}
+
// WriteToIP writes an IP packet to addr via c, copying the payload from b.
//
// WriteToIP can be made to time out and return
@@ -213,6 +146,20 @@ func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
return c.WriteToIP(b, a)
}
+// WriteMsgIP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob. It returns the
+// number of payload and out-of-band bytes written.
+func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
+ if !c.ok() {
+ return 0, 0, syscall.EINVAL
+ }
+ sa, err := addr.sockaddr(c.fd.family)
+ if err != nil {
+ return 0, 0, &OpError{"write", c.fd.net, addr, err}
+ }
+ return c.fd.WriteMsg(b, oob, sa)
+}
+
// DialIP connects to the remote address raddr on the network protocol netProto,
// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
@@ -255,8 +202,3 @@ func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
}
return newIPConn(fd), nil
}
-
-// File returns a copy of the underlying os.File, set to blocking mode.
-// It is the caller's responsibility to close f when finished.
-// Closing c does not affect f, and closing f does not affect c.
-func (c *IPConn) File() (f *os.File, err error) { return c.fd.dup() }
diff --git a/libgo/go/net/ipsock.go b/libgo/go/net/ipsock.go
index bfbce18a414..84547c7a6a8 100644
--- a/libgo/go/net/ipsock.go
+++ b/libgo/go/net/ipsock.go
@@ -129,17 +129,10 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err error) {
}
}
- p, i, ok := dtoi(port, 0)
- if !ok || i != len(port) {
- p, err = LookupPort(net, port)
- if err != nil {
- return nil, 0, err
- }
- }
- if p < 0 || p > 0xFFFF {
- return nil, 0, &AddrError{"invalid port", port}
+ p, err := parsePort(net, port)
+ if err != nil {
+ return nil, 0, err
}
return addr, p, nil
-
}
diff --git a/libgo/go/net/ipsock_plan9.go b/libgo/go/net/ipsock_plan9.go
index eab0bf3e899..7cc2d714d8a 100644
--- a/libgo/go/net/ipsock_plan9.go
+++ b/libgo/go/net/ipsock_plan9.go
@@ -14,9 +14,12 @@ import (
"time"
)
-// probeIPv6Stack returns two boolean values. If the first boolean value is
-// true, kernel supports basic IPv6 functionality. If the second
-// boolean value is true, kernel supports IPv6 IPv4-mapping.
+// /sys/include/ape/sys/socket.h:/SOMAXCONN
+var listenerBacklog = 5
+
+// probeIPv6Stack returns two boolean values. If the first boolean
+// value is true, kernel supports basic IPv6 functionality. If the
+// second boolean value is true, kernel supports IPv6 IPv4-mapping.
func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
return false, false
}
@@ -48,6 +51,7 @@ func readPlan9Addr(proto, filename string) (addr Addr, err error) {
if err != nil {
return
}
+ defer f.Close()
n, err := f.Read(buf[:])
if err != nil {
return
@@ -162,6 +166,25 @@ func (c *plan9Conn) SetWriteDeadline(t time.Time) error {
return syscall.EPLAN9
}
+// SetReadBuffer sets the size of the operating system's receive
+// buffer associated with the connection.
+func (c *plan9Conn) SetReadBuffer(bytes int) error {
+ return syscall.EPLAN9
+}
+
+// SetWriteBuffer sets the size of the operating system's transmit
+// buffer associated with the connection.
+func (c *plan9Conn) SetWriteBuffer(bytes int) error {
+ return syscall.EPLAN9
+}
+
+// File returns a copy of the underlying os.File, set to blocking
+// mode. It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (c *plan9Conn) File() (f *os.File, err error) {
+ return nil, syscall.EPLAN9
+}
+
func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err error) {
var (
ip IP
@@ -192,6 +215,7 @@ func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string,
var buf [16]byte
n, err := f.Read(buf[:])
if err != nil {
+ f.Close()
return
}
return f, dest, proto, string(buf[:n]), nil
@@ -204,14 +228,17 @@ func dialPlan9(net string, laddr, raddr Addr) (c *plan9Conn, err error) {
}
_, err = f.WriteString("connect " + dest)
if err != nil {
+ f.Close()
return
}
laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
if err != nil {
+ f.Close()
return
}
raddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/remote")
if err != nil {
+ f.Close()
return
}
return newPlan9Conn(proto, name, f, laddr, raddr), nil
@@ -230,10 +257,12 @@ func listenPlan9(net string, laddr Addr) (l *plan9Listener, err error) {
}
_, err = f.WriteString("announce " + dest)
if err != nil {
+ f.Close()
return
}
laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
if err != nil {
+ f.Close()
return
}
l = new(plan9Listener)
@@ -257,15 +286,18 @@ func (l *plan9Listener) acceptPlan9() (c *plan9Conn, err error) {
var buf [16]byte
n, err := f.Read(buf[:])
if err != nil {
+ f.Close()
return
}
name := string(buf[:n])
laddr, err := readPlan9Addr(l.proto, l.dir+"/local")
if err != nil {
+ f.Close()
return
}
raddr, err := readPlan9Addr(l.proto, l.dir+"/remote")
if err != nil {
+ f.Close()
return
}
return newPlan9Conn(l.proto, name, f, laddr, raddr), nil
@@ -287,3 +319,16 @@ func (l *plan9Listener) Close() error {
}
func (l *plan9Listener) Addr() Addr { return l.laddr }
+
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *plan9Listener) SetDeadline(t time.Time) error {
+ return syscall.EPLAN9
+}
+
+// File returns a copy of the underlying os.File, set to blocking
+// mode. It is the caller's responsibility to close f when finished.
+// Closing l does not affect f, and closing f does not affect l.
+func (l *plan9Listener) File() (f *os.File, err error) {
+ return nil, syscall.EPLAN9
+}
diff --git a/libgo/go/net/ipsock_posix.go b/libgo/go/net/ipsock_posix.go
index ed313195c97..171889207d7 100644
--- a/libgo/go/net/ipsock_posix.go
+++ b/libgo/go/net/ipsock_posix.go
@@ -97,10 +97,13 @@ func favoriteAddrFamily(net string, laddr, raddr sockaddr, mode string) (family
return syscall.AF_INET6, true
}
- if mode == "listen" && laddr.isWildcard() {
+ if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
if supportsIPv4map {
return syscall.AF_INET6, false
}
+ if laddr == nil {
+ return syscall.AF_INET, false
+ }
return laddr.family(), false
}
diff --git a/libgo/go/net/doc.go b/libgo/go/net/lookup.go
index 3a44e528eb2..3a44e528eb2 100644
--- a/libgo/go/net/doc.go
+++ b/libgo/go/net/lookup.go
diff --git a/libgo/go/net/lookup_test.go b/libgo/go/net/lookup_test.go
index 3a61dfb29c2..84f089e8697 100644
--- a/libgo/go/net/lookup_test.go
+++ b/libgo/go/net/lookup_test.go
@@ -9,6 +9,7 @@ package net
import (
"flag"
+ "strings"
"testing"
)
@@ -79,6 +80,17 @@ func TestGoogleDNSAddr(t *testing.T) {
}
}
+func TestLookupIANACNAME(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Logf("skipping test to avoid external network")
+ return
+ }
+ cname, err := LookupCNAME("www.iana.org")
+ if !strings.HasSuffix(cname, ".icann.org.") || err != nil {
+ t.Errorf(`LookupCNAME("www.iana.org.") = %q, %v, want "*.icann.org.", nil`, cname, err)
+ }
+}
+
var revAddrTests = []struct {
Addr string
Reverse string
diff --git a/libgo/go/net/mail/message.go b/libgo/go/net/mail/message.go
index 93cc4d1edd4..96c796e7804 100644
--- a/libgo/go/net/mail/message.go
+++ b/libgo/go/net/mail/message.go
@@ -127,7 +127,7 @@ func (h Header) AddressList(key string) ([]*Address, error) {
if hdr == "" {
return nil, ErrHeaderNotPresent
}
- return newAddrParser(hdr).parseAddressList()
+ return ParseAddressList(hdr)
}
// Address represents a single mail address.
@@ -138,6 +138,16 @@ type Address struct {
Address string // user@domain
}
+// Parses a single RFC 5322 address, e.g. "Barry Gibbs <bg@example.com>"
+func ParseAddress(address string) (*Address, error) {
+ return newAddrParser(address).parseAddress()
+}
+
+// ParseAddressList parses the given string as a list of addresses.
+func ParseAddressList(list string) ([]*Address, error) {
+ return newAddrParser(list).parseAddressList()
+}
+
// String formats the address as a valid RFC 5322 address.
// If the address's name contains non-ASCII characters
// the name will be rendered according to RFC 2047.
diff --git a/libgo/go/net/mail/message_test.go b/libgo/go/net/mail/message_test.go
index fd17eb414a7..2e746f4a722 100644
--- a/libgo/go/net/mail/message_test.go
+++ b/libgo/go/net/mail/message_test.go
@@ -227,13 +227,24 @@ func TestAddressParsing(t *testing.T) {
},
}
for _, test := range tests {
- addrs, err := newAddrParser(test.addrsStr).parseAddressList()
+ if len(test.exp) == 1 {
+ addr, err := ParseAddress(test.addrsStr)
+ if err != nil {
+ t.Errorf("Failed parsing (single) %q: %v", test.addrsStr, err)
+ continue
+ }
+ if !reflect.DeepEqual([]*Address{addr}, test.exp) {
+ t.Errorf("Parse (single) of %q: got %+v, want %+v", test.addrsStr, addr, test.exp)
+ }
+ }
+
+ addrs, err := ParseAddressList(test.addrsStr)
if err != nil {
- t.Errorf("Failed parsing %q: %v", test.addrsStr, err)
+ t.Errorf("Failed parsing (list) %q: %v", test.addrsStr, err)
continue
}
if !reflect.DeepEqual(addrs, test.exp) {
- t.Errorf("Parse of %q: got %+v, want %+v", test.addrsStr, addrs, test.exp)
+ t.Errorf("Parse (list) of %q: got %+v, want %+v", test.addrsStr, addrs, test.exp)
}
}
}
diff --git a/libgo/go/net/multicast_test.go b/libgo/go/net/multicast_posix_test.go
index 50c0f0a82c9..3767a6bc178 100644
--- a/libgo/go/net/multicast_test.go
+++ b/libgo/go/net/multicast_posix_test.go
@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build !plan9
+
package net
import (
"errors"
"os"
"runtime"
- "syscall"
"testing"
)
@@ -46,7 +47,7 @@ var multicastListenerTests = []struct {
// listener with same address family, same group address and same port.
func TestMulticastListener(t *testing.T) {
switch runtime.GOOS {
- case "netbsd", "openbsd", "plan9", "solaris", "windows":
+ case "netbsd", "openbsd", "plan9", "windows":
t.Logf("skipping test on %q", runtime.GOOS)
return
case "linux":
@@ -57,7 +58,7 @@ func TestMulticastListener(t *testing.T) {
}
for _, tt := range multicastListenerTests {
- if tt.ipv6 && (!supportsIPv6 || os.Getuid() != 0) {
+ if tt.ipv6 && (!*testIPv6 || !supportsIPv6 || os.Getuid() != 0) {
continue
}
ifi, err := availMulticastInterface(t, tt.flags)
@@ -75,12 +76,6 @@ func TestMulticastListener(t *testing.T) {
}
checkMulticastListener(t, err, c2, tt.gaddr)
c2.Close()
- switch c1.fd.family {
- case syscall.AF_INET:
- testIPv4MulticastSocketOptions(t, c1.fd, ifi)
- case syscall.AF_INET6:
- testIPv6MulticastSocketOptions(t, c1.fd, ifi)
- }
c1.Close()
}
}
@@ -174,61 +169,3 @@ func multicastRIBContains(t *testing.T, ip IP) bool {
}
return false
}
-
-func testIPv4MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
- _, err := ipv4MulticastInterface(fd)
- if err != nil {
- t.Fatalf("ipv4MulticastInterface failed: %v", err)
- }
- if ifi != nil {
- err = setIPv4MulticastInterface(fd, ifi)
- if err != nil {
- t.Fatalf("setIPv4MulticastInterface failed: %v", err)
- }
- }
- _, err = ipv4MulticastTTL(fd)
- if err != nil {
- t.Fatalf("ipv4MulticastTTL failed: %v", err)
- }
- err = setIPv4MulticastTTL(fd, 1)
- if err != nil {
- t.Fatalf("setIPv4MulticastTTL failed: %v", err)
- }
- _, err = ipv4MulticastLoopback(fd)
- if err != nil {
- t.Fatalf("ipv4MulticastLoopback failed: %v", err)
- }
- err = setIPv4MulticastLoopback(fd, false)
- if err != nil {
- t.Fatalf("setIPv4MulticastLoopback failed: %v", err)
- }
-}
-
-func testIPv6MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
- _, err := ipv6MulticastInterface(fd)
- if err != nil {
- t.Fatalf("ipv6MulticastInterface failed: %v", err)
- }
- if ifi != nil {
- err = setIPv6MulticastInterface(fd, ifi)
- if err != nil {
- t.Fatalf("setIPv6MulticastInterface failed: %v", err)
- }
- }
- _, err = ipv6MulticastHopLimit(fd)
- if err != nil {
- t.Fatalf("ipv6MulticastHopLimit failed: %v", err)
- }
- err = setIPv6MulticastHopLimit(fd, 1)
- if err != nil {
- t.Fatalf("setIPv6MulticastHopLimit failed: %v", err)
- }
- _, err = ipv6MulticastLoopback(fd)
- if err != nil {
- t.Fatalf("ipv6MulticastLoopback failed: %v", err)
- }
- err = setIPv6MulticastLoopback(fd, false)
- if err != nil {
- t.Fatalf("setIPv6MulticastLoopback failed: %v", err)
- }
-}
diff --git a/libgo/go/net/net_test.go b/libgo/go/net/net_test.go
index fd145e1d70f..623a788f9ab 100644
--- a/libgo/go/net/net_test.go
+++ b/libgo/go/net/net_test.go
@@ -6,6 +6,8 @@ package net
import (
"io"
+ "io/ioutil"
+ "os"
"runtime"
"testing"
"time"
@@ -16,15 +18,15 @@ func TestShutdown(t *testing.T) {
t.Logf("skipping test on %q", runtime.GOOS)
return
}
- l, err := Listen("tcp", "127.0.0.1:0")
+ ln, err := Listen("tcp", "127.0.0.1:0")
if err != nil {
- if l, err = Listen("tcp6", "[::1]:0"); err != nil {
+ if ln, err = Listen("tcp6", "[::1]:0"); err != nil {
t.Fatalf("ListenTCP on :0: %v", err)
}
}
go func() {
- c, err := l.Accept()
+ c, err := ln.Accept()
if err != nil {
t.Fatalf("Accept: %v", err)
}
@@ -37,7 +39,7 @@ func TestShutdown(t *testing.T) {
c.Close()
}()
- c, err := Dial("tcp", l.Addr().String())
+ c, err := Dial("tcp", ln.Addr().String())
if err != nil {
t.Fatalf("Dial: %v", err)
}
@@ -58,8 +60,62 @@ func TestShutdown(t *testing.T) {
}
}
+func TestShutdownUnix(t *testing.T) {
+ switch runtime.GOOS {
+ case "windows", "plan9":
+ t.Logf("skipping test on %q", runtime.GOOS)
+ return
+ }
+ f, err := ioutil.TempFile("", "go_net_unixtest")
+ if err != nil {
+ t.Fatalf("TempFile: %s", err)
+ }
+ f.Close()
+ tmpname := f.Name()
+ os.Remove(tmpname)
+ ln, err := Listen("unix", tmpname)
+ if err != nil {
+ t.Fatalf("ListenUnix on %s: %s", tmpname, err)
+ }
+ defer os.Remove(tmpname)
+
+ go func() {
+ c, err := ln.Accept()
+ if err != nil {
+ t.Fatalf("Accept: %v", err)
+ }
+ var buf [10]byte
+ n, err := c.Read(buf[:])
+ if n != 0 || err != io.EOF {
+ t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
+ }
+ c.Write([]byte("response"))
+ c.Close()
+ }()
+
+ c, err := Dial("unix", tmpname)
+ if err != nil {
+ t.Fatalf("Dial: %v", err)
+ }
+ defer c.Close()
+
+ err = c.(*UnixConn).CloseWrite()
+ if err != nil {
+ t.Fatalf("CloseWrite: %v", err)
+ }
+ var buf [10]byte
+ n, err := c.Read(buf[:])
+ if err != nil {
+ t.Fatalf("client Read: %d, %v", n, err)
+ }
+ got := string(buf[:n])
+ if got != "response" {
+ t.Errorf("read = %q, want \"response\"", got)
+ }
+}
+
func TestTCPListenClose(t *testing.T) {
- l, err := Listen("tcp", "127.0.0.1:0")
+ ln, err := Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Listen failed: %v", err)
}
@@ -67,11 +123,12 @@ func TestTCPListenClose(t *testing.T) {
done := make(chan bool, 1)
go func() {
time.Sleep(100 * time.Millisecond)
- l.Close()
+ ln.Close()
}()
go func() {
- _, err = l.Accept()
+ c, err := ln.Accept()
if err == nil {
+ c.Close()
t.Error("Accept succeeded")
} else {
t.Logf("Accept timeout error: %s (any error is fine)", err)
@@ -86,7 +143,12 @@ func TestTCPListenClose(t *testing.T) {
}
func TestUDPListenClose(t *testing.T) {
- l, err := ListenPacket("udp", "127.0.0.1:0")
+ switch runtime.GOOS {
+ case "plan9":
+ t.Logf("skipping test on %q", runtime.GOOS)
+ return
+ }
+ ln, err := ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Listen failed: %v", err)
}
@@ -95,10 +157,10 @@ func TestUDPListenClose(t *testing.T) {
done := make(chan bool, 1)
go func() {
time.Sleep(100 * time.Millisecond)
- l.Close()
+ ln.Close()
}()
go func() {
- _, _, err = l.ReadFrom(buf)
+ _, _, err = ln.ReadFrom(buf)
if err == nil {
t.Error("ReadFrom succeeded")
} else {
diff --git a/libgo/go/net/newpollserver.go b/libgo/go/net/newpollserver_unix.go
index d34bb511f7f..618b5b10ba4 100644
--- a/libgo/go/net/newpollserver.go
+++ b/libgo/go/net/newpollserver_unix.go
@@ -13,8 +13,6 @@ import (
func newPollServer() (s *pollServer, err error) {
s = new(pollServer)
- s.cr = make(chan *netFD, 1)
- s.cw = make(chan *netFD, 1)
if s.pr, s.pw, err = os.Pipe(); err != nil {
return nil, err
}
diff --git a/libgo/go/net/port.go b/libgo/go/net/port.go
index 16780da1160..c24f4ed5b17 100644
--- a/libgo/go/net/port.go
+++ b/libgo/go/net/port.go
@@ -1,69 +1,24 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
-
-// Read system port mappings from /etc/services
+// Network service port manipulations
package net
-import "sync"
-
-var services map[string]map[string]int
-var servicesError error
-var onceReadServices sync.Once
-
-func readServices() {
- services = make(map[string]map[string]int)
- var file *file
- if file, servicesError = open("/etc/services"); servicesError != nil {
- return
- }
- for line, ok := file.readLine(); ok; line, ok = file.readLine() {
- // "http 80/tcp www www-http # World Wide Web HTTP"
- if i := byteIndex(line, '#'); i >= 0 {
- line = line[0:i]
- }
- f := getFields(line)
- if len(f) < 2 {
- continue
- }
- portnet := f[1] // "tcp/80"
- port, j, ok := dtoi(portnet, 0)
- if !ok || port <= 0 || j >= len(portnet) || portnet[j] != '/' {
- continue
- }
- netw := portnet[j+1:] // "tcp"
- m, ok1 := services[netw]
- if !ok1 {
- m = make(map[string]int)
- services[netw] = m
- }
- for i := 0; i < len(f); i++ {
- if i != 1 { // f[1] was port/net
- m[f[i]] = port
- }
+// parsePort parses port as a network service port number for both
+// TCP and UDP.
+func parsePort(net, port string) (int, error) {
+ p, i, ok := dtoi(port, 0)
+ if !ok || i != len(port) {
+ var err error
+ p, err = LookupPort(net, port)
+ if err != nil {
+ return 0, err
}
}
- file.close()
-}
-
-// goLookupPort is the native Go implementation of LookupPort.
-func goLookupPort(network, service string) (port int, err error) {
- onceReadServices.Do(readServices)
-
- switch network {
- case "tcp4", "tcp6":
- network = "tcp"
- case "udp4", "udp6":
- network = "udp"
- }
-
- if m, ok := services[network]; ok {
- if port, ok = m[service]; ok {
- return
- }
+ if p < 0 || p > 0xFFFF {
+ return 0, &AddrError{"invalid port", port}
}
- return 0, &AddrError{"unknown port", network + "/" + service}
+ return p, nil
}
diff --git a/libgo/go/net/port_unix.go b/libgo/go/net/port_unix.go
new file mode 100644
index 00000000000..16780da1160
--- /dev/null
+++ b/libgo/go/net/port_unix.go
@@ -0,0 +1,69 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd
+
+// Read system port mappings from /etc/services
+
+package net
+
+import "sync"
+
+var services map[string]map[string]int
+var servicesError error
+var onceReadServices sync.Once
+
+func readServices() {
+ services = make(map[string]map[string]int)
+ var file *file
+ if file, servicesError = open("/etc/services"); servicesError != nil {
+ return
+ }
+ for line, ok := file.readLine(); ok; line, ok = file.readLine() {
+ // "http 80/tcp www www-http # World Wide Web HTTP"
+ if i := byteIndex(line, '#'); i >= 0 {
+ line = line[0:i]
+ }
+ f := getFields(line)
+ if len(f) < 2 {
+ continue
+ }
+ portnet := f[1] // "tcp/80"
+ port, j, ok := dtoi(portnet, 0)
+ if !ok || port <= 0 || j >= len(portnet) || portnet[j] != '/' {
+ continue
+ }
+ netw := portnet[j+1:] // "tcp"
+ m, ok1 := services[netw]
+ if !ok1 {
+ m = make(map[string]int)
+ services[netw] = m
+ }
+ for i := 0; i < len(f); i++ {
+ if i != 1 { // f[1] was port/net
+ m[f[i]] = port
+ }
+ }
+ }
+ file.close()
+}
+
+// goLookupPort is the native Go implementation of LookupPort.
+func goLookupPort(network, service string) (port int, err error) {
+ onceReadServices.Do(readServices)
+
+ switch network {
+ case "tcp4", "tcp6":
+ network = "tcp"
+ case "udp4", "udp6":
+ network = "udp"
+ }
+
+ if m, ok := services[network]; ok {
+ if port, ok = m[service]; ok {
+ return
+ }
+ }
+ return 0, &AddrError{"unknown port", network + "/" + service}
+}
diff --git a/libgo/go/net/rpc/client.go b/libgo/go/net/rpc/client.go
index db2da8e4418..7d3d0bb9b87 100644
--- a/libgo/go/net/rpc/client.go
+++ b/libgo/go/net/rpc/client.go
@@ -88,10 +88,13 @@ func (client *Client) send(call *Call) {
err := client.codec.WriteRequest(&client.request, call.Args)
if err != nil {
client.mutex.Lock()
+ call = client.pending[seq]
delete(client.pending, seq)
client.mutex.Unlock()
- call.Error = err
- call.done()
+ if call != nil {
+ call.Error = err
+ call.done()
+ }
}
}
@@ -113,12 +116,18 @@ func (client *Client) input() {
delete(client.pending, seq)
client.mutex.Unlock()
- if response.Error == "" {
- err = client.codec.ReadResponseBody(call.Reply)
+ switch {
+ case call == nil:
+ // We've got no pending call. That usually means that
+ // WriteRequest partially failed, and call was already
+ // removed; response is a server telling us about an
+ // error reading request body. We should still attempt
+ // to read error body, but there's no one to give it to.
+ err = client.codec.ReadResponseBody(nil)
if err != nil {
- call.Error = errors.New("reading body " + err.Error())
+ err = errors.New("reading error body: " + err.Error())
}
- } else {
+ case response.Error != "":
// We've got an error response. Give this to the request;
// any subsequent requests will get the ReadResponseBody
// error if there is one.
@@ -127,8 +136,14 @@ func (client *Client) input() {
if err != nil {
err = errors.New("reading error body: " + err.Error())
}
+ call.done()
+ default:
+ err = client.codec.ReadResponseBody(call.Reply)
+ if err != nil {
+ call.Error = errors.New("reading body " + err.Error())
+ }
+ call.done()
}
- call.done()
}
// Terminate pending calls.
client.sending.Lock()
diff --git a/libgo/go/net/rpc/jsonrpc/all_test.go b/libgo/go/net/rpc/jsonrpc/all_test.go
index adc29d5a1b3..3c7c4d48fa6 100644
--- a/libgo/go/net/rpc/jsonrpc/all_test.go
+++ b/libgo/go/net/rpc/jsonrpc/all_test.go
@@ -24,6 +24,12 @@ type Reply struct {
type Arith int
+type ArithAddResp struct {
+ Id interface{} `json:"id"`
+ Result Reply `json:"result"`
+ Error interface{} `json:"error"`
+}
+
func (t *Arith) Add(args *Args, reply *Reply) error {
reply.C = args.A + args.B
return nil
@@ -50,13 +56,39 @@ func init() {
rpc.Register(new(Arith))
}
-func TestServer(t *testing.T) {
- type addResp struct {
- Id interface{} `json:"id"`
- Result Reply `json:"result"`
- Error interface{} `json:"error"`
+func TestServerNoParams(t *testing.T) {
+ cli, srv := net.Pipe()
+ defer cli.Close()
+ go ServeConn(srv)
+ dec := json.NewDecoder(cli)
+
+ fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "123"}`)
+ var resp ArithAddResp
+ if err := dec.Decode(&resp); err != nil {
+ t.Fatalf("Decode after no params: %s", err)
+ }
+ if resp.Error == nil {
+ t.Fatalf("Expected error, got nil")
+ }
+}
+
+func TestServerEmptyMessage(t *testing.T) {
+ cli, srv := net.Pipe()
+ defer cli.Close()
+ go ServeConn(srv)
+ dec := json.NewDecoder(cli)
+
+ fmt.Fprintf(cli, "{}")
+ var resp ArithAddResp
+ if err := dec.Decode(&resp); err != nil {
+ t.Fatalf("Decode after empty: %s", err)
}
+ if resp.Error == nil {
+ t.Fatalf("Expected error, got nil")
+ }
+}
+func TestServer(t *testing.T) {
cli, srv := net.Pipe()
defer cli.Close()
go ServeConn(srv)
@@ -65,7 +97,7 @@ func TestServer(t *testing.T) {
// Send hand-coded requests to server, parse responses.
for i := 0; i < 10; i++ {
fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "\u%04d", "params": [{"A": %d, "B": %d}]}`, i, i, i+1)
- var resp addResp
+ var resp ArithAddResp
err := dec.Decode(&resp)
if err != nil {
t.Fatalf("Decode: %s", err)
@@ -80,15 +112,6 @@ func TestServer(t *testing.T) {
t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C)
}
}
-
- fmt.Fprintf(cli, "{}\n")
- var resp addResp
- if err := dec.Decode(&resp); err != nil {
- t.Fatalf("Decode after empty: %s", err)
- }
- if resp.Error == nil {
- t.Fatalf("Expected error, got nil")
- }
}
func TestClient(t *testing.T) {
diff --git a/libgo/go/net/rpc/jsonrpc/server.go b/libgo/go/net/rpc/jsonrpc/server.go
index 4c54553a723..5bc05fd0a71 100644
--- a/libgo/go/net/rpc/jsonrpc/server.go
+++ b/libgo/go/net/rpc/jsonrpc/server.go
@@ -12,6 +12,8 @@ import (
"sync"
)
+var errMissingParams = errors.New("jsonrpc: request body missing params")
+
type serverCodec struct {
dec *json.Decoder // for reading JSON values
enc *json.Encoder // for writing JSON values
@@ -50,12 +52,8 @@ type serverRequest struct {
func (r *serverRequest) reset() {
r.Method = ""
- if r.Params != nil {
- *r.Params = (*r.Params)[0:0]
- }
- if r.Id != nil {
- *r.Id = (*r.Id)[0:0]
- }
+ r.Params = nil
+ r.Id = nil
}
type serverResponse struct {
@@ -88,6 +86,9 @@ func (c *serverCodec) ReadRequestBody(x interface{}) error {
if x == nil {
return nil
}
+ if c.req.Params == nil {
+ return errMissingParams
+ }
// JSON params is array value.
// RPC params is struct.
// Unmarshal into array containing struct for now.
diff --git a/libgo/go/net/sendfile_freebsd.go b/libgo/go/net/sendfile_freebsd.go
new file mode 100644
index 00000000000..85000061040
--- /dev/null
+++ b/libgo/go/net/sendfile_freebsd.go
@@ -0,0 +1,105 @@
+// 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 net
+
+import (
+ "io"
+ "os"
+ "syscall"
+)
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// sendFile copies the contents of r to c using the sendfile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
+ // FreeBSD uses 0 as the "until EOF" value. If you pass in more bytes than the
+ // file contains, it will loop back to the beginning ad nauseum until it's sent
+ // exactly the number of bytes told to. As such, we need to know exactly how many
+ // bytes to send.
+ var remain int64 = 0
+
+ lr, ok := r.(*io.LimitedReader)
+ if ok {
+ remain, r = lr.N, lr.R
+ if remain <= 0 {
+ return 0, nil, true
+ }
+ }
+ f, ok := r.(*os.File)
+ if !ok {
+ return 0, nil, false
+ }
+
+ if remain == 0 {
+ fi, err := f.Stat()
+ if err != nil {
+ return 0, err, false
+ }
+
+ remain = fi.Size()
+ }
+
+ // The other quirk with FreeBSD's sendfile implementation is that it doesn't
+ // use the current position of the file -- if you pass it offset 0, it starts
+ // from offset 0. There's no way to tell it "start from current position", so
+ // we have to manage that explicitly.
+ pos, err := f.Seek(0, os.SEEK_CUR)
+ if err != nil {
+ return 0, err, false
+ }
+
+ c.wio.Lock()
+ defer c.wio.Unlock()
+ if err := c.incref(false); err != nil {
+ return 0, err, true
+ }
+ defer c.decref()
+
+ dst := c.sysfd
+ src := int(f.Fd())
+ for remain > 0 {
+ n := maxSendfileSize
+ if int64(n) > remain {
+ n = int(remain)
+ }
+ pos1 := pos
+ n, err1 := syscall.Sendfile(dst, src, &pos1, n)
+ if n > 0 {
+ pos += int64(n)
+ written += int64(n)
+ remain -= int64(n)
+ }
+ if n == 0 && err1 == nil {
+ break
+ }
+ if err1 == syscall.EAGAIN && c.wdeadline >= 0 {
+ if err1 = c.pollServer.WaitWrite(c); err1 == nil {
+ continue
+ }
+ }
+ if err1 == syscall.EINTR {
+ continue
+ }
+ if err1 != nil {
+ // This includes syscall.ENOSYS (no kernel
+ // support) and syscall.EINVAL (fd types which
+ // don't implement sendfile together)
+ err = &OpError{"sendfile", c.net, c.raddr, err1}
+ break
+ }
+ }
+ if lr != nil {
+ lr.N = remain
+ }
+ return written, err, written > 0
+}
diff --git a/libgo/go/net/sendfile_linux.go b/libgo/go/net/sendfile_linux.go
index a0d53036263..5ee18f9cccd 100644
--- a/libgo/go/net/sendfile_linux.go
+++ b/libgo/go/net/sendfile_linux.go
@@ -59,7 +59,7 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
break
}
if err1 == syscall.EAGAIN && c.wdeadline >= 0 {
- if err1 = pollserver.WaitWrite(c); err1 == nil {
+ if err1 = c.pollServer.WaitWrite(c); err1 == nil {
continue
}
}
diff --git a/libgo/go/net/sendfile_stub.go b/libgo/go/net/sendfile_stub.go
index ff76ab9cf0e..3660849c182 100644
--- a/libgo/go/net/sendfile_stub.go
+++ b/libgo/go/net/sendfile_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd netbsd openbsd
+// +build darwin netbsd openbsd
package net
diff --git a/libgo/go/net/sock.go b/libgo/go/net/sock_posix.go
index 3ae16054e47..dc5247a7f38 100644
--- a/libgo/go/net/sock.go
+++ b/libgo/go/net/sock_posix.go
@@ -16,8 +16,8 @@ import (
var listenerBacklog = maxListenerBacklog()
// Generic socket creation.
-func socket(net string, f, t, p int, ipv6only bool, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
- // See ../syscall/exec.go for description of ForkLock.
+func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
+ // See ../syscall/exec_unix.go for description of ForkLock.
syscall.ForkLock.RLock()
s, err := syscall.Socket(f, t, p)
if err != nil {
@@ -27,21 +27,18 @@ func socket(net string, f, t, p int, ipv6only bool, la, ra syscall.Sockaddr, toA
syscall.CloseOnExec(s)
syscall.ForkLock.RUnlock()
- err = setDefaultSockopts(s, f, t, ipv6only)
- if err != nil {
+ if err = setDefaultSockopts(s, f, t, ipv6only); err != nil {
closesocket(s)
return nil, err
}
- var bla syscall.Sockaddr
- if la != nil {
- bla, err = listenerSockaddr(s, f, la, toAddr)
- if err != nil {
+ var blsa syscall.Sockaddr
+ if ulsa != nil {
+ if blsa, err = listenerSockaddr(s, f, ulsa, toAddr); err != nil {
closesocket(s)
return nil, err
}
- err = syscall.Bind(s, bla)
- if err != nil {
+ if err = syscall.Bind(s, blsa); err != nil {
closesocket(s)
return nil, err
}
@@ -52,8 +49,8 @@ func socket(net string, f, t, p int, ipv6only bool, la, ra syscall.Sockaddr, toA
return nil, err
}
- if ra != nil {
- if err = fd.connect(ra); err != nil {
+ if ursa != nil {
+ if err = fd.connect(ursa); err != nil {
closesocket(s)
fd.Close()
return nil, err
@@ -61,16 +58,15 @@ func socket(net string, f, t, p int, ipv6only bool, la, ra syscall.Sockaddr, toA
fd.isConnected = true
}
- sa, _ := syscall.Getsockname(s)
+ lsa, _ := syscall.Getsockname(s)
var laddr Addr
- if la != nil && bla != la {
- laddr = toAddr(la)
+ if ulsa != nil && blsa != ulsa {
+ laddr = toAddr(ulsa)
} else {
- laddr = toAddr(sa)
+ laddr = toAddr(lsa)
}
- sa, _ = syscall.Getpeername(s)
- raddr := toAddr(sa)
-
+ rsa, _ := syscall.Getpeername(s)
+ raddr := toAddr(rsa)
fd.setAddr(laddr, raddr)
return fd, nil
}
diff --git a/libgo/go/net/sockopt.go b/libgo/go/net/sockopt_posix.go
index b139c427654..b139c427654 100644
--- a/libgo/go/net/sockopt.go
+++ b/libgo/go/net/sockopt_posix.go
diff --git a/libgo/go/net/sockoptip.go b/libgo/go/net/sockoptip.go
deleted file mode 100644
index 1fcad4018cc..00000000000
--- a/libgo/go/net/sockoptip.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// 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.
-
-// +build darwin freebsd linux netbsd openbsd windows
-
-// IP-level socket options
-
-package net
-
-import (
- "os"
- "syscall"
-)
-
-func ipv4TOS(fd *netFD) (int, error) {
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS)
- if err != nil {
- return 0, os.NewSyscallError("getsockopt", err)
- }
- return v, nil
-}
-
-func setIPv4TOS(fd *netFD, v int) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS, v)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv4TTL(fd *netFD) (int, error) {
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL)
- if err != nil {
- return 0, os.NewSyscallError("getsockopt", err)
- }
- return v, nil
-}
-
-func setIPv4TTL(fd *netFD, v int) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL, v)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
- mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
- if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
- return err
- }
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
-}
-
-func leaveIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
- mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
- if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
- return err
- }
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
-}
-
-func ipv6HopLimit(fd *netFD) (int, error) {
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS)
- if err != nil {
- return 0, os.NewSyscallError("getsockopt", err)
- }
- return v, nil
-}
-
-func setIPv6HopLimit(fd *netFD, v int) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, v)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv6MulticastInterface(fd *netFD) (*Interface, error) {
- if err := fd.incref(false); err != nil {
- return nil, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF)
- if err != nil {
- return nil, os.NewSyscallError("getsockopt", err)
- }
- if v == 0 {
- return nil, nil
- }
- ifi, err := InterfaceByIndex(v)
- if err != nil {
- return nil, err
- }
- return ifi, nil
-}
-
-func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
- var v int
- if ifi != nil {
- v = ifi.Index
- }
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv6MulticastHopLimit(fd *netFD) (int, error) {
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS)
- if err != nil {
- return 0, os.NewSyscallError("getsockopt", err)
- }
- return v, nil
-}
-
-func setIPv6MulticastHopLimit(fd *netFD, v int) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS, v)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv6MulticastLoopback(fd *netFD) (bool, error) {
- if err := fd.incref(false); err != nil {
- return false, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP)
- if err != nil {
- return false, os.NewSyscallError("getsockopt", err)
- }
- return v == 1, nil
-}
-
-func setIPv6MulticastLoopback(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
- mreq := &syscall.IPv6Mreq{}
- copy(mreq.Multiaddr[:], ip)
- if ifi != nil {
- mreq.Interface = uint32(ifi.Index)
- }
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq))
-}
-
-func leaveIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
- mreq := &syscall.IPv6Mreq{}
- copy(mreq.Multiaddr[:], ip)
- if ifi != nil {
- mreq.Interface = uint32(ifi.Index)
- }
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_LEAVE_GROUP, mreq))
-}
diff --git a/libgo/go/net/sockoptip_bsd.go b/libgo/go/net/sockoptip_bsd.go
index 19e2b142e92..263f8552176 100644
--- a/libgo/go/net/sockoptip_bsd.go
+++ b/libgo/go/net/sockoptip_bsd.go
@@ -4,8 +4,6 @@
// +build darwin freebsd netbsd openbsd
-// IP-level socket options for BSD variants
-
package net
import (
@@ -13,48 +11,30 @@ import (
"syscall"
)
-func ipv4MulticastTTL(fd *netFD) (int, error) {
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+ ip, err := interfaceToIPv4Addr(ifi)
if err != nil {
- return 0, os.NewSyscallError("getsockopt", err)
+ return os.NewSyscallError("setsockopt", err)
}
- return int(v), nil
-}
-
-func setIPv4MulticastTTL(fd *netFD, v int) error {
+ var a [4]byte
+ copy(a[:], ip.To4())
if err := fd.incref(false); err != nil {
return err
}
defer fd.decref()
- err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, byte(v))
+ err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, a)
if err != nil {
return os.NewSyscallError("setsockopt", err)
}
return nil
}
-func ipv6TrafficClass(fd *netFD) (int, error) {
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
- if err != nil {
- return 0, os.NewSyscallError("getsockopt", err)
- }
- return v, nil
-}
-
-func setIPv6TrafficClass(fd *netFD, v int) error {
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
if err := fd.incref(false); err != nil {
return err
}
defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
+ err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
if err != nil {
return os.NewSyscallError("setsockopt", err)
}
diff --git a/libgo/go/net/sockoptip_darwin.go b/libgo/go/net/sockoptip_darwin.go
deleted file mode 100644
index 52b237c4b8d..00000000000
--- a/libgo/go/net/sockoptip_darwin.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// 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.
-
-// IP-level socket options for Darwin
-
-package net
-
-import (
- "os"
- "syscall"
-)
-
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
- if err := fd.incref(false); err != nil {
- return nil, err
- }
- defer fd.decref()
- a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
- if err != nil {
- return nil, os.NewSyscallError("getsockopt", err)
- }
- return ipv4AddrToInterface(IPv4(a[0], a[1], a[2], a[3]))
-}
-
-func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
- ip, err := interfaceToIPv4Addr(ifi)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- var x [4]byte
- copy(x[:], ip.To4())
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
- if err := fd.incref(false); err != nil {
- return false, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
- if err != nil {
- return false, os.NewSyscallError("getsockopt", err)
- }
- return v == 1, nil
-}
-
-func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
- if err := fd.incref(false); err != nil {
- return false, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
- if err != nil {
- return false, os.NewSyscallError("getsockopt", err)
- }
- return v == 1, nil
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
diff --git a/libgo/go/net/sockoptip_freebsd.go b/libgo/go/net/sockoptip_freebsd.go
deleted file mode 100644
index 4a3bc2e82c8..00000000000
--- a/libgo/go/net/sockoptip_freebsd.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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.
-
-// IP-level socket options for FreeBSD
-
-package net
-
-import (
- "os"
- "syscall"
-)
-
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
- if err := fd.incref(false); err != nil {
- return nil, err
- }
- defer fd.decref()
- mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
- if err != nil {
- return nil, os.NewSyscallError("getsockopt", err)
- }
- if int(mreq.Ifindex) == 0 {
- return nil, nil
- }
- return InterfaceByIndex(int(mreq.Ifindex))
-}
-
-func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
- var v int32
- if ifi != nil {
- v = int32(ifi.Index)
- }
- mreq := &syscall.IPMreqn{Ifindex: v}
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
- if err := fd.incref(false); err != nil {
- return false, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
- if err != nil {
- return false, os.NewSyscallError("getsockopt", err)
- }
- return v == 1, nil
-}
-
-func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
- if err := fd.incref(false); err != nil {
- return false, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
- if err != nil {
- return false, os.NewSyscallError("getsockopt", err)
- }
- return v == 1, nil
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
diff --git a/libgo/go/net/sockoptip_linux.go b/libgo/go/net/sockoptip_linux.go
index 169718f14aa..225fb0c4c6c 100644
--- a/libgo/go/net/sockoptip_linux.go
+++ b/libgo/go/net/sockoptip_linux.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// IP-level socket options for Linux
-
package net
import (
@@ -11,21 +9,6 @@ import (
"syscall"
)
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
- if err := fd.incref(false); err != nil {
- return nil, err
- }
- defer fd.decref()
- mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
- if err != nil {
- return nil, os.NewSyscallError("getsockopt", err)
- }
- if int(mreq.Ifindex) == 0 {
- return nil, nil
- }
- return InterfaceByIndex(int(mreq.Ifindex))
-}
-
func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
var v int32
if ifi != nil {
@@ -43,42 +26,6 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
return nil
}
-func ipv4MulticastTTL(fd *netFD) (int, error) {
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
- if err != nil {
- return -1, os.NewSyscallError("getsockopt", err)
- }
- return v, nil
-}
-
-func setIPv4MulticastTTL(fd *netFD, v int) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
- if err := fd.incref(false); err != nil {
- return false, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
- if err != nil {
- return false, os.NewSyscallError("getsockopt", err)
- }
- return v == 1, nil
-}
-
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
if err := fd.incref(false); err != nil {
return err
@@ -90,51 +37,3 @@ func setIPv4MulticastLoopback(fd *netFD, v bool) error {
}
return nil
}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
- if err := fd.incref(false); err != nil {
- return false, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO)
- if err != nil {
- return false, os.NewSyscallError("getsockopt", err)
- }
- return v == 1, nil
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO, boolint(v))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv6TrafficClass(fd *netFD) (int, error) {
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
- if err != nil {
- return 0, os.NewSyscallError("getsockopt", err)
- }
- return v, nil
-}
-
-func setIPv6TrafficClass(fd *netFD, v int) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
diff --git a/libgo/go/net/sockoptip_netbsd.go b/libgo/go/net/sockoptip_netbsd.go
deleted file mode 100644
index 446d92aa343..00000000000
--- a/libgo/go/net/sockoptip_netbsd.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// IP-level socket options for NetBSD
-
-package net
-
-import "syscall"
-
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
- // TODO: Implement this
- return nil, syscall.EAFNOSUPPORT
-}
-
-func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
- // TODO: Implement this
- return syscall.EAFNOSUPPORT
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
- // TODO: Implement this
- return false, syscall.EAFNOSUPPORT
-}
-
-func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- // TODO: Implement this
- return syscall.EAFNOSUPPORT
-}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
- // TODO: Implement this
- return false, syscall.EAFNOSUPPORT
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
- // TODO: Implement this
- return syscall.EAFNOSUPPORT
-}
diff --git a/libgo/go/net/sockoptip_openbsd.go b/libgo/go/net/sockoptip_openbsd.go
deleted file mode 100644
index f3e42f1a9bc..00000000000
--- a/libgo/go/net/sockoptip_openbsd.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// 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.
-
-// IP-level socket options for OpenBSD
-
-package net
-
-import (
- "os"
- "syscall"
-)
-
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
- if err := fd.incref(false); err != nil {
- return nil, err
- }
- defer fd.decref()
- a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
- if err != nil {
- return nil, os.NewSyscallError("getsockopt", err)
- }
- return ipv4AddrToInterface(IPv4(a[0], a[1], a[2], a[3]))
-}
-
-func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
- ip, err := interfaceToIPv4Addr(ifi)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- var x [4]byte
- copy(x[:], ip.To4())
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
- if err := fd.incref(false); err != nil {
- return false, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
- if err != nil {
- return false, os.NewSyscallError("getsockopt", err)
- }
- return v == 1, nil
-}
-
-func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
- if err := fd.incref(false); err != nil {
- return false, err
- }
- defer fd.decref()
- v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
- if err != nil {
- return false, os.NewSyscallError("getsockopt", err)
- }
- return v == 1, nil
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
diff --git a/libgo/go/net/sockoptip_posix.go b/libgo/go/net/sockoptip_posix.go
new file mode 100644
index 00000000000..e4c56a0e4b2
--- /dev/null
+++ b/libgo/go/net/sockoptip_posix.go
@@ -0,0 +1,73 @@
+// 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.
+
+// +build darwin freebsd linux netbsd openbsd windows
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
+ mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+ if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
+ return err
+ }
+ if err := fd.incref(false); err != nil {
+ return err
+ }
+ defer fd.decref()
+ err := syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
+ var v int
+ if ifi != nil {
+ v = ifi.Index
+ }
+ if err := fd.incref(false); err != nil {
+ return err
+ }
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func setIPv6MulticastLoopback(fd *netFD, v bool) error {
+ if err := fd.incref(false); err != nil {
+ return err
+ }
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
+ mreq := &syscall.IPv6Mreq{}
+ copy(mreq.Multiaddr[:], ip)
+ if ifi != nil {
+ mreq.Interface = uint32(ifi.Index)
+ }
+ if err := fd.incref(false); err != nil {
+ return err
+ }
+ defer fd.decref()
+ err := syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
diff --git a/libgo/go/net/sockoptip_windows.go b/libgo/go/net/sockoptip_windows.go
index b9db3334d5f..3e248441ab3 100644
--- a/libgo/go/net/sockoptip_windows.go
+++ b/libgo/go/net/sockoptip_windows.go
@@ -2,90 +2,41 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// IP-level socket options for Windows
-
package net
import (
"os"
"syscall"
+ "unsafe"
)
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
- // TODO: Implement this
- return nil, syscall.EWINDOWS
-}
-
func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
ip, err := interfaceToIPv4Addr(ifi)
if err != nil {
return os.NewSyscallError("setsockopt", err)
}
- var x [4]byte
- copy(x[:], ip.To4())
+ var a [4]byte
+ copy(a[:], ip.To4())
if err := fd.incref(false); err != nil {
return err
}
defer fd.decref()
- err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
+ err = syscall.Setsockopt(fd.sysfd, int32(syscall.IPPROTO_IP), int32(syscall.IP_MULTICAST_IF), (*byte)(unsafe.Pointer(&a[0])), 4)
if err != nil {
return os.NewSyscallError("setsockopt", err)
}
return nil
}
-func ipv4MulticastTTL(fd *netFD) (int, error) {
- // TODO: Implement this
- return -1, syscall.EWINDOWS
-}
-
-func setIPv4MulticastTTL(fd *netFD, v int) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
- // TODO: Implement this
- return false, syscall.EWINDOWS
-}
-
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
if err := fd.incref(false); err != nil {
return err
}
defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
+ vv := int32(boolint(v))
+ err := syscall.Setsockopt(fd.sysfd, int32(syscall.IPPROTO_IP), int32(syscall.IP_MULTICAST_LOOP), (*byte)(unsafe.Pointer(&vv)), 4)
if err != nil {
return os.NewSyscallError("setsockopt", err)
}
return nil
-
-}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
- // TODO: Implement this
- return false, syscall.EWINDOWS
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
- // TODO: Implement this
- return syscall.EWINDOWS
-}
-
-func ipv6TrafficClass(fd *netFD) (int, error) {
- // TODO: Implement this
- return 0, syscall.EWINDOWS
-}
-
-func setIPv6TrafficClass(fd *netFD, v int) error {
- // TODO: Implement this
- return syscall.EWINDOWS
}
diff --git a/libgo/go/net/tcp_test.go b/libgo/go/net/tcp_test.go
new file mode 100644
index 00000000000..53daf5b0999
--- /dev/null
+++ b/libgo/go/net/tcp_test.go
@@ -0,0 +1,118 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "runtime"
+ "testing"
+ "time"
+)
+
+func BenchmarkTCPOneShot(b *testing.B) {
+ benchmarkTCP(b, false, false)
+}
+
+func BenchmarkTCPOneShotTimeout(b *testing.B) {
+ benchmarkTCP(b, false, true)
+}
+
+func BenchmarkTCPPersistent(b *testing.B) {
+ benchmarkTCP(b, true, false)
+}
+
+func BenchmarkTCPPersistentTimeout(b *testing.B) {
+ benchmarkTCP(b, true, true)
+}
+
+func benchmarkTCP(b *testing.B, persistent, timeout bool) {
+ const msgLen = 512
+ conns := b.N
+ numConcurrent := runtime.GOMAXPROCS(-1) * 16
+ msgs := 1
+ if persistent {
+ conns = numConcurrent
+ msgs = b.N / conns
+ if msgs == 0 {
+ msgs = 1
+ }
+ if conns > b.N {
+ conns = b.N
+ }
+ }
+ sendMsg := func(c Conn, buf []byte) bool {
+ n, err := c.Write(buf)
+ if n != len(buf) || err != nil {
+ b.Logf("Write failed: %v", err)
+ return false
+ }
+ return true
+ }
+ recvMsg := func(c Conn, buf []byte) bool {
+ for read := 0; read != len(buf); {
+ n, err := c.Read(buf)
+ read += n
+ if err != nil {
+ b.Logf("Read failed: %v", err)
+ return false
+ }
+ }
+ return true
+ }
+ ln, err := Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ b.Fatalf("Listen failed: %v", err)
+ }
+ defer ln.Close()
+ // Acceptor.
+ go func() {
+ for {
+ c, err := ln.Accept()
+ if err != nil {
+ break
+ }
+ // Server connection.
+ go func(c Conn) {
+ defer c.Close()
+ if timeout {
+ c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
+ }
+ var buf [msgLen]byte
+ for m := 0; m < msgs; m++ {
+ if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
+ break
+ }
+ }
+ }(c)
+ }
+ }()
+ sem := make(chan bool, numConcurrent)
+ for i := 0; i < conns; i++ {
+ sem <- true
+ // Client connection.
+ go func() {
+ defer func() {
+ <-sem
+ }()
+ c, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ b.Logf("Dial failed: %v", err)
+ return
+ }
+ defer c.Close()
+ if timeout {
+ c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
+ }
+ var buf [msgLen]byte
+ for m := 0; m < msgs; m++ {
+ if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
+ break
+ }
+ }
+ }()
+ }
+ for i := 0; i < cap(sem); i++ {
+ sem <- true
+ }
+}
diff --git a/libgo/go/net/tcpsock_plan9.go b/libgo/go/net/tcpsock_plan9.go
index 35f56966eae..4121dd89e9a 100644
--- a/libgo/go/net/tcpsock_plan9.go
+++ b/libgo/go/net/tcpsock_plan9.go
@@ -2,36 +2,18 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// TCP for Plan 9
+// TCP sockets for Plan 9
package net
-import (
- "syscall"
- "time"
-)
+import "syscall"
-// TCPConn is an implementation of the Conn interface
-// for TCP network connections.
+// TCPConn is an implementation of the Conn interface for TCP network
+// connections.
type TCPConn struct {
plan9Conn
}
-// SetDeadline implements the Conn SetDeadline method.
-func (c *TCPConn) SetDeadline(t time.Time) error {
- return syscall.EPLAN9
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *TCPConn) SetReadDeadline(t time.Time) error {
- return syscall.EPLAN9
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *TCPConn) SetWriteDeadline(t time.Time) error {
- return syscall.EPLAN9
-}
-
// CloseRead shuts down the reading side of the TCP connection.
// Most callers should just use Close.
func (c *TCPConn) CloseRead() error {
@@ -51,8 +33,8 @@ func (c *TCPConn) CloseWrite() error {
}
// DialTCP connects to the remote address raddr on the network net,
-// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
-// as the local address for the connection.
+// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is
+// used as the local address for the connection.
func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) {
switch net {
case "tcp", "tcp4", "tcp6":
@@ -69,17 +51,27 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) {
return &TCPConn{*c1}, nil
}
-// TCPListener is a TCP network listener.
-// Clients should typically use variables of type Listener
-// instead of assuming TCP.
+// TCPListener is a TCP network listener. Clients should typically
+// use variables of type Listener instead of assuming TCP.
type TCPListener struct {
plan9Listener
}
-// ListenTCP announces on the TCP address laddr and returns a TCP listener.
-// Net must be "tcp", "tcp4", or "tcp6".
-// If laddr has a port of 0, it means to listen on some available port.
-// The caller can use l.Addr() to retrieve the chosen address.
+func (l *TCPListener) Close() error {
+ if l == nil || l.ctl == nil {
+ return syscall.EINVAL
+ }
+ if _, err := l.ctl.WriteString("hangup"); err != nil {
+ l.ctl.Close()
+ return err
+ }
+ return l.ctl.Close()
+}
+
+// ListenTCP announces on the TCP address laddr and returns a TCP
+// listener. Net must be "tcp", "tcp4", or "tcp6". If laddr has a
+// port of 0, it means to listen on some available port. The caller
+// can use l.Addr() to retrieve the chosen address.
func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) {
switch net {
case "tcp", "tcp4", "tcp6":
diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go
index e6b1937fb2c..2c34d2fda7d 100644
--- a/libgo/go/net/tcpsock_posix.go
+++ b/libgo/go/net/tcpsock_posix.go
@@ -66,27 +66,15 @@ func (a *TCPAddr) toAddr() sockaddr {
// TCPConn is an implementation of the Conn interface
// for TCP network connections.
type TCPConn struct {
- fd *netFD
+ conn
}
func newTCPConn(fd *netFD) *TCPConn {
- c := &TCPConn{fd}
+ c := &TCPConn{conn{fd}}
c.SetNoDelay(true)
return c
}
-func (c *TCPConn) ok() bool { return c != nil && c.fd != nil }
-
-// Implementation of the Conn interface - see Conn for documentation.
-
-// Read implements the Conn Read method.
-func (c *TCPConn) Read(b []byte) (n int, err error) {
- if !c.ok() {
- return 0, syscall.EINVAL
- }
- return c.fd.Read(b)
-}
-
// ReadFrom implements the io.ReaderFrom ReadFrom method.
func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
if n, err, handled := sendFile(c.fd, r); handled {
@@ -95,22 +83,6 @@ func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
return genericReadFrom(c, r)
}
-// Write implements the Conn Write method.
-func (c *TCPConn) Write(b []byte) (n int, err error) {
- if !c.ok() {
- return 0, syscall.EINVAL
- }
- return c.fd.Write(b)
-}
-
-// Close closes the TCP connection.
-func (c *TCPConn) Close() error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return c.fd.Close()
-}
-
// CloseRead shuts down the reading side of the TCP connection.
// Most callers should just use Close.
func (c *TCPConn) CloseRead() error {
@@ -129,64 +101,6 @@ func (c *TCPConn) CloseWrite() error {
return c.fd.CloseWrite()
}
-// LocalAddr returns the local network address, a *TCPAddr.
-func (c *TCPConn) LocalAddr() Addr {
- if !c.ok() {
- return nil
- }
- return c.fd.laddr
-}
-
-// RemoteAddr returns the remote network address, a *TCPAddr.
-func (c *TCPConn) RemoteAddr() Addr {
- if !c.ok() {
- return nil
- }
- return c.fd.raddr
-}
-
-// SetDeadline implements the Conn SetDeadline method.
-func (c *TCPConn) SetDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setDeadline(c.fd, t)
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *TCPConn) SetReadDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setReadDeadline(c.fd, t)
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *TCPConn) SetWriteDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setWriteDeadline(c.fd, t)
-}
-
-// SetReadBuffer sets the size of the operating system's
-// receive buffer associated with the connection.
-func (c *TCPConn) SetReadBuffer(bytes int) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setReadBuffer(c.fd, bytes)
-}
-
-// SetWriteBuffer sets the size of the operating system's
-// transmit buffer associated with the connection.
-func (c *TCPConn) SetWriteBuffer(bytes int) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setWriteBuffer(c.fd, bytes)
-}
-
// SetLinger sets the behavior of Close() on a connection
// which still has data waiting to be sent or to be acknowledged.
//
@@ -225,11 +139,6 @@ func (c *TCPConn) SetNoDelay(noDelay bool) error {
return setNoDelay(c.fd, noDelay)
}
-// File returns a copy of the underlying os.File, set to blocking mode.
-// It is the caller's responsibility to close f when finished.
-// Closing c does not affect f, and closing f does not affect c.
-func (c *TCPConn) File() (f *os.File, err error) { return c.fd.dup() }
-
// DialTCP connects to the remote address raddr on the network net,
// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
// as the local address for the connection.
@@ -257,8 +166,17 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
// use the result. See also:
// http://golang.org/issue/2690
// http://stackoverflow.com/questions/4949858/
- for i := 0; i < 2 && err == nil && laddr == nil && selfConnect(fd); i++ {
- fd.Close()
+ //
+ // The opposite can also happen: if we ask the kernel to pick an appropriate
+ // originating local address, sometimes it picks one that is already in use.
+ // So if the error is EADDRNOTAVAIL, we have to try again too, just for
+ // a different reason.
+ //
+ // The kernel socket code is no doubt enjoying watching us squirm.
+ for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(fd, err) || spuriousENOTAVAIL(err)); i++ {
+ if err == nil {
+ fd.Close()
+ }
fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
}
@@ -268,7 +186,12 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
return newTCPConn(fd), nil
}
-func selfConnect(fd *netFD) bool {
+func selfConnect(fd *netFD, err error) bool {
+ // If the connect failed, we clearly didn't connect to ourselves.
+ if err != nil {
+ return false
+ }
+
// The socket constructor can return an fd with raddr nil under certain
// unknown conditions. The errors in the calls there to Getpeername
// are discarded, but we can't catch the problem there because those
@@ -285,6 +208,11 @@ func selfConnect(fd *netFD) bool {
return l.Port == r.Port && l.IP.Equal(r.IP)
}
+func spuriousENOTAVAIL(err error) bool {
+ e, ok := err.(*OpError)
+ return ok && e.Err == syscall.EADDRNOTAVAIL
+}
+
// TCPListener is a TCP network listener.
// Clients should typically use variables of type Listener
// instead of assuming TCP.
diff --git a/libgo/go/net/textproto/reader.go b/libgo/go/net/textproto/reader.go
index 125feb3e885..3777424534d 100644
--- a/libgo/go/net/textproto/reader.go
+++ b/libgo/go/net/textproto/reader.go
@@ -452,16 +452,18 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
return m, err
}
- // Key ends at first colon; must not have spaces.
+ // Key ends at first colon; should not have spaces but
+ // they appear in the wild, violating specs, so we
+ // remove them if present.
i := bytes.IndexByte(kv, ':')
if i < 0 {
return m, ProtocolError("malformed MIME header line: " + string(kv))
}
- key := string(kv[0:i])
- if strings.Index(key, " ") >= 0 {
- key = strings.TrimRight(key, " ")
+ endKey := i
+ for endKey > 0 && kv[endKey-1] == ' ' {
+ endKey--
}
- key = CanonicalMIMEHeaderKey(key)
+ key := canonicalMIMEHeaderKey(kv[:endKey])
// Skip initial spaces in value.
i++ // skip colon
@@ -486,25 +488,28 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
// canonical key for "accept-encoding" is "Accept-Encoding".
func CanonicalMIMEHeaderKey(s string) string {
// Quick check for canonical encoding.
- needUpper := true
+ upper := true
for i := 0; i < len(s); i++ {
c := s[i]
- if needUpper && 'a' <= c && c <= 'z' {
- goto MustRewrite
+ if upper && 'a' <= c && c <= 'z' {
+ return canonicalMIMEHeaderKey([]byte(s))
}
- if !needUpper && 'A' <= c && c <= 'Z' {
- goto MustRewrite
+ if !upper && 'A' <= c && c <= 'Z' {
+ return canonicalMIMEHeaderKey([]byte(s))
}
- needUpper = c == '-'
+ upper = c == '-'
}
return s
+}
-MustRewrite:
+// canonicalMIMEHeaderKey is like CanonicalMIMEHeaderKey but is
+// allowed to mutate the provided byte slice before returning the
+// string.
+func canonicalMIMEHeaderKey(a []byte) string {
// Canonicalize: first letter upper case
// and upper case after each dash.
// (Host, User-Agent, If-Modified-Since).
// MIME headers are ASCII only, so no Unicode issues.
- a := []byte(s)
upper := true
for i, v := range a {
if v == ' ' {
diff --git a/libgo/go/net/textproto/reader_test.go b/libgo/go/net/textproto/reader_test.go
index 7c5d16227ff..9b6c76a0d08 100644
--- a/libgo/go/net/textproto/reader_test.go
+++ b/libgo/go/net/textproto/reader_test.go
@@ -6,6 +6,7 @@ package textproto
import (
"bufio"
+ "bytes"
"io"
"reflect"
"strings"
@@ -239,3 +240,19 @@ func TestRFC959Lines(t *testing.T) {
}
}
}
+
+func BenchmarkReadMIMEHeader(b *testing.B) {
+ var buf bytes.Buffer
+ br := bufio.NewReader(&buf)
+ r := NewReader(br)
+ for i := 0; i < b.N; i++ {
+ buf.WriteString("User-Agent: not mozilla\r\nContent-Length: 23452\r\nContent-Type: text/html; charset-utf8\r\nFoo-Bar: foobar\r\nfoo-bar: some more string\r\n\r\n")
+ h, err := r.ReadMIMEHeader()
+ if err != nil {
+ b.Fatal(err)
+ }
+ if len(h) != 4 {
+ b.Fatalf("want 4")
+ }
+ }
+}
diff --git a/libgo/go/net/textproto/textproto.go b/libgo/go/net/textproto/textproto.go
index ad5840cf7da..e7ad8773dc6 100644
--- a/libgo/go/net/textproto/textproto.go
+++ b/libgo/go/net/textproto/textproto.go
@@ -121,3 +121,29 @@ func (c *Conn) Cmd(format string, args ...interface{}) (id uint, err error) {
}
return id, nil
}
+
+// TrimString returns s without leading and trailing ASCII space.
+func TrimString(s string) string {
+ for len(s) > 0 && isASCIISpace(s[0]) {
+ s = s[1:]
+ }
+ for len(s) > 0 && isASCIISpace(s[len(s)-1]) {
+ s = s[:len(s)-1]
+ }
+ return s
+}
+
+// TrimBytes returns b without leading and trailing ASCII space.
+func TrimBytes(b []byte) []byte {
+ for len(b) > 0 && isASCIISpace(b[0]) {
+ b = b[1:]
+ }
+ for len(b) > 0 && isASCIISpace(b[len(b)-1]) {
+ b = b[:len(b)-1]
+ }
+ return b
+}
+
+func isASCIISpace(b byte) bool {
+ return b == ' ' || b == '\t' || b == '\n' || b == '\r'
+}
diff --git a/libgo/go/net/udpsock.go b/libgo/go/net/udpsock.go
index b3520cf09f3..62b27d95e9c 100644
--- a/libgo/go/net/udpsock.go
+++ b/libgo/go/net/udpsock.go
@@ -6,6 +6,10 @@
package net
+import "errors"
+
+var ErrWriteToConnected = errors.New("use of WriteTo with pre-connected UDP")
+
// UDPAddr represents the address of a UDP end point.
type UDPAddr struct {
IP IP
diff --git a/libgo/go/net/udpsock_plan9.go b/libgo/go/net/udpsock_plan9.go
index 4f298a42f87..aaa7e5b28cb 100644
--- a/libgo/go/net/udpsock_plan9.go
+++ b/libgo/go/net/udpsock_plan9.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// UDP for Plan 9
+// UDP sockets for Plan 9
package net
@@ -10,7 +10,6 @@ import (
"errors"
"os"
"syscall"
- "time"
)
// UDPConn is the implementation of the Conn and PacketConn
@@ -19,29 +18,15 @@ type UDPConn struct {
plan9Conn
}
-// SetDeadline implements the Conn SetDeadline method.
-func (c *UDPConn) SetDeadline(t time.Time) error {
- return syscall.EPLAN9
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *UDPConn) SetReadDeadline(t time.Time) error {
- return syscall.EPLAN9
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *UDPConn) SetWriteDeadline(t time.Time) error {
- return syscall.EPLAN9
-}
-
// UDP-specific methods.
// ReadFromUDP reads a UDP packet from c, copying the payload into b.
// It returns the number of bytes copied into b and the return address
// that was on the packet.
//
-// ReadFromUDP can be made to time out and return an error with Timeout() == true
-// after a fixed time limit; see SetDeadline and SetReadDeadline.
+// ReadFromUDP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
if !c.ok() {
return 0, nil, syscall.EINVAL
@@ -75,12 +60,22 @@ func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
return c.ReadFromUDP(b)
}
-// WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
+// ReadMsgUDP reads a packet from c, copying the payload into b and
+// the associdated out-of-band data into oob. It returns the number
+// of bytes copied into b, the number of bytes copied into oob, the
+// flags that were set on the packet and the source address of the
+// packet.
+func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
+ return 0, 0, 0, nil, syscall.EPLAN9
+}
+
+// WriteToUDP writes a UDP packet to addr via c, copying the payload
+// from b.
//
-// WriteToUDP can be made to time out and return
-// an error with Timeout() == true after a fixed time limit;
-// see SetDeadline and SetWriteDeadline.
-// On packet-oriented connections, write timeouts are rare.
+// WriteToUDP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline. On packet-oriented connections, write timeouts
+// are rare.
func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) {
if !c.ok() {
return 0, syscall.EINVAL
@@ -116,9 +111,16 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
return c.WriteToUDP(b, a)
}
+// WriteMsgUDP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob. It returns the
+// number of payload and out-of-band bytes written.
+func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
+ return 0, 0, syscall.EPLAN9
+}
+
// DialUDP connects to the remote address raddr on the network net,
-// which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used
-// as the local address for the connection.
+// which must be "udp", "udp4", or "udp6". If laddr is not nil, it is
+// used as the local address for the connection.
func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
switch net {
case "udp", "udp4", "udp6":
@@ -163,10 +165,10 @@ func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {
return h, b
}
-// ListenUDP listens for incoming UDP packets addressed to the
-// local address laddr. The returned connection c's ReadFrom
-// and WriteTo methods can be used to receive and send UDP
-// packets with per-packet addressing.
+// ListenUDP listens for incoming UDP packets addressed to the local
+// address laddr. The returned connection c's ReadFrom and WriteTo
+// methods can be used to receive and send UDP packets with per-packet
+// addressing.
func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
switch net {
case "udp", "udp4", "udp6":
@@ -188,9 +190,9 @@ func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
}
// ListenMulticastUDP listens for incoming multicast UDP packets
-// addressed to the group address gaddr on ifi, which specifies
-// the interface to join. ListenMulticastUDP uses default
-// multicast interface if ifi is nil.
+// addressed to the group address gaddr on ifi, which specifies the
+// interface to join. ListenMulticastUDP uses default multicast
+// interface if ifi is nil.
func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
return nil, syscall.EPLAN9
}
diff --git a/libgo/go/net/udpsock_posix.go b/libgo/go/net/udpsock_posix.go
index 9c6b6d39336..e075380c8e3 100644
--- a/libgo/go/net/udpsock_posix.go
+++ b/libgo/go/net/udpsock_posix.go
@@ -8,14 +8,7 @@
package net
-import (
- "errors"
- "os"
- "syscall"
- "time"
-)
-
-var ErrWriteToConnected = errors.New("use of WriteTo with pre-connected UDP")
+import "syscall"
func sockaddrToUDP(sa syscall.Sockaddr) Addr {
switch sa := sa.(type) {
@@ -58,96 +51,10 @@ func (a *UDPAddr) toAddr() sockaddr {
// UDPConn is the implementation of the Conn and PacketConn
// interfaces for UDP network connections.
type UDPConn struct {
- fd *netFD
-}
-
-func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{fd} }
-
-func (c *UDPConn) ok() bool { return c != nil && c.fd != nil }
-
-// Implementation of the Conn interface - see Conn for documentation.
-
-// Read implements the Conn Read method.
-func (c *UDPConn) Read(b []byte) (int, error) {
- if !c.ok() {
- return 0, syscall.EINVAL
- }
- return c.fd.Read(b)
-}
-
-// Write implements the Conn Write method.
-func (c *UDPConn) Write(b []byte) (int, error) {
- if !c.ok() {
- return 0, syscall.EINVAL
- }
- return c.fd.Write(b)
-}
-
-// Close closes the UDP connection.
-func (c *UDPConn) Close() error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return c.fd.Close()
-}
-
-// LocalAddr returns the local network address.
-func (c *UDPConn) LocalAddr() Addr {
- if !c.ok() {
- return nil
- }
- return c.fd.laddr
-}
-
-// RemoteAddr returns the remote network address, a *UDPAddr.
-func (c *UDPConn) RemoteAddr() Addr {
- if !c.ok() {
- return nil
- }
- return c.fd.raddr
-}
-
-// SetDeadline implements the Conn SetDeadline method.
-func (c *UDPConn) SetDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setDeadline(c.fd, t)
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *UDPConn) SetReadDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setReadDeadline(c.fd, t)
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *UDPConn) SetWriteDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setWriteDeadline(c.fd, t)
-}
-
-// SetReadBuffer sets the size of the operating system's
-// receive buffer associated with the connection.
-func (c *UDPConn) SetReadBuffer(bytes int) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setReadBuffer(c.fd, bytes)
+ conn
}
-// SetWriteBuffer sets the size of the operating system's
-// transmit buffer associated with the connection.
-func (c *UDPConn) SetWriteBuffer(bytes int) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setWriteBuffer(c.fd, bytes)
-}
+func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
// UDP-specific methods.
@@ -180,6 +87,26 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
return n, uaddr.toAddr(), err
}
+// ReadMsgUDP reads a packet from c, copying the payload into b and
+// the associdated out-of-band data into oob. It returns the number
+// of bytes copied into b, the number of bytes copied into oob, the
+// flags that were set on the packet and the source address of the
+// packet.
+func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
+ if !c.ok() {
+ return 0, 0, 0, nil, syscall.EINVAL
+ }
+ var sa syscall.Sockaddr
+ n, oobn, flags, sa, err = c.fd.ReadMsg(b, oob)
+ switch sa := sa.(type) {
+ case *syscall.SockaddrInet4:
+ addr = &UDPAddr{sa.Addr[0:], sa.Port}
+ case *syscall.SockaddrInet6:
+ addr = &UDPAddr{sa.Addr[0:], sa.Port}
+ }
+ return
+}
+
// WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
//
// WriteToUDP can be made to time out and return
@@ -212,10 +139,22 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
return c.WriteToUDP(b, a)
}
-// File returns a copy of the underlying os.File, set to blocking mode.
-// It is the caller's responsibility to close f when finished.
-// Closing c does not affect f, and closing f does not affect c.
-func (c *UDPConn) File() (f *os.File, err error) { return c.fd.dup() }
+// WriteMsgUDP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob. It returns the
+// number of payload and out-of-band bytes written.
+func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
+ if !c.ok() {
+ return 0, 0, syscall.EINVAL
+ }
+ if c.fd.isConnected {
+ return 0, 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
+ }
+ sa, err := addr.sockaddr(c.fd.family)
+ if err != nil {
+ return 0, 0, &OpError{"write", c.fd.net, addr, err}
+ }
+ return c.fd.WriteMsg(b, oob, sa)
+}
// DialUDP connects to the remote address raddr on the network net,
// which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used
@@ -335,14 +274,6 @@ func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
return nil
}
-func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
- err := leaveIPv4Group(c.fd, ifi, ip)
- if err != nil {
- return &OpError{"leaveipv4group", c.fd.net, &IPAddr{ip}, err}
- }
- return nil
-}
-
func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
err := joinIPv6Group(c.fd, ifi, ip)
if err != nil {
@@ -350,11 +281,3 @@ func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
}
return nil
}
-
-func leaveIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
- err := leaveIPv6Group(c.fd, ifi, ip)
- if err != nil {
- return &OpError{"leaveipv6group", c.fd.net, &IPAddr{ip}, err}
- }
- return nil
-}
diff --git a/libgo/go/net/unicast_test.go b/libgo/go/net/unicast_posix_test.go
index e5dd013db67..5b39e25acbf 100644
--- a/libgo/go/net/unicast_test.go
+++ b/libgo/go/net/unicast_posix_test.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 !plan9
+
package net
import (
@@ -59,13 +61,6 @@ func TestTCPListener(t *testing.T) {
checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
l2, err := Listen(tt.net, tt.laddr+":"+port)
checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
- fd := l1.(*TCPListener).fd
- switch fd.family {
- case syscall.AF_INET:
- testIPv4UnicastSocketOptions(t, fd)
- case syscall.AF_INET6:
- testIPv6UnicastSocketOptions(t, fd)
- }
l1.Close()
}
}
@@ -104,13 +99,6 @@ func TestUDPListener(t *testing.T) {
checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
- fd := l1.(*UDPConn).fd
- switch fd.family {
- case syscall.AF_INET:
- testIPv4UnicastSocketOptions(t, fd)
- case syscall.AF_INET6:
- testIPv6UnicastSocketOptions(t, fd)
- }
l1.Close()
}
}
@@ -468,44 +456,6 @@ func checkDualStackAddrFamily(t *testing.T, net, laddr string, fd *netFD) {
}
}
-func testIPv4UnicastSocketOptions(t *testing.T, fd *netFD) {
- _, err := ipv4TOS(fd)
- if err != nil {
- t.Fatalf("ipv4TOS failed: %v", err)
- }
- err = setIPv4TOS(fd, 1)
- if err != nil {
- t.Fatalf("setIPv4TOS failed: %v", err)
- }
- _, err = ipv4TTL(fd)
- if err != nil {
- t.Fatalf("ipv4TTL failed: %v", err)
- }
- err = setIPv4TTL(fd, 1)
- if err != nil {
- t.Fatalf("setIPv4TTL failed: %v", err)
- }
-}
-
-func testIPv6UnicastSocketOptions(t *testing.T, fd *netFD) {
- _, err := ipv6TrafficClass(fd)
- if err != nil {
- t.Fatalf("ipv6TrafficClass failed: %v", err)
- }
- err = setIPv6TrafficClass(fd, 1)
- if err != nil {
- t.Fatalf("setIPv6TrafficClass failed: %v", err)
- }
- _, err = ipv6HopLimit(fd)
- if err != nil {
- t.Fatalf("ipv6HopLimit failed: %v", err)
- }
- err = setIPv6HopLimit(fd, 1)
- if err != nil {
- t.Fatalf("setIPv6HopLimit failed: %v", err)
- }
-}
-
var prohibitionaryDialArgTests = []struct {
net string
addr string
@@ -536,3 +486,38 @@ func TestProhibitionaryDialArgs(t *testing.T) {
}
}
}
+
+func TestWildWildcardListener(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9":
+ t.Logf("skipping test on %q", runtime.GOOS)
+ return
+ }
+
+ if testing.Short() || !*testExternal {
+ t.Logf("skipping test to avoid external network")
+ return
+ }
+
+ defer func() {
+ if recover() != nil {
+ t.Fatalf("panicked")
+ }
+ }()
+
+ if ln, err := Listen("tcp", ""); err == nil {
+ ln.Close()
+ }
+ if ln, err := ListenPacket("udp", ""); err == nil {
+ ln.Close()
+ }
+ if ln, err := ListenTCP("tcp", nil); err == nil {
+ ln.Close()
+ }
+ if ln, err := ListenUDP("udp", nil); err == nil {
+ ln.Close()
+ }
+ if ln, err := ListenIP("ip:icmp", nil); err == nil {
+ ln.Close()
+ }
+}
diff --git a/libgo/go/net/unixsock_plan9.go b/libgo/go/net/unixsock_plan9.go
index 7b4ae6bd116..21403754a7a 100644
--- a/libgo/go/net/unixsock_plan9.go
+++ b/libgo/go/net/unixsock_plan9.go
@@ -7,40 +7,33 @@
package net
import (
+ "os"
"syscall"
"time"
)
-// UnixConn is an implementation of the Conn interface
-// for connections to Unix domain sockets.
+// UnixConn is an implementation of the Conn interface for connections
+// to Unix domain sockets.
type UnixConn bool
// Implementation of the Conn interface - see Conn for documentation.
// Read implements the Conn Read method.
-func (c *UnixConn) Read(b []byte) (n int, err error) {
+func (c *UnixConn) Read(b []byte) (int, error) {
return 0, syscall.EPLAN9
}
// Write implements the Conn Write method.
-func (c *UnixConn) Write(b []byte) (n int, err error) {
+func (c *UnixConn) Write(b []byte) (int, error) {
return 0, syscall.EPLAN9
}
-// Close closes the Unix domain connection.
-func (c *UnixConn) Close() error {
- return syscall.EPLAN9
-}
-
-// LocalAddr returns the local network address, a *UnixAddr.
-// Unlike in other protocols, LocalAddr is usually nil for dialed connections.
+// LocalAddr returns the local network address.
func (c *UnixConn) LocalAddr() Addr {
return nil
}
-// RemoteAddr returns the remote network address, a *UnixAddr.
-// Unlike in other protocols, RemoteAddr is usually nil for connections
-// accepted by a listener.
+// RemoteAddr returns the remote network address.
func (c *UnixConn) RemoteAddr() Addr {
return nil
}
@@ -60,47 +53,144 @@ func (c *UnixConn) SetWriteDeadline(t time.Time) error {
return syscall.EPLAN9
}
+// SetReadBuffer sets the size of the operating system's receive
+// buffer associated with the connection.
+func (c *UnixConn) SetReadBuffer(bytes int) error {
+ return syscall.EPLAN9
+}
+
+// SetWriteBuffer sets the size of the operating system's transmit
+// buffer associated with the connection.
+func (c *UnixConn) SetWriteBuffer(bytes int) error {
+ return syscall.EPLAN9
+}
+
+// File returns a copy of the underlying os.File, set to blocking
+// mode. It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (c *UnixConn) File() (f *os.File, err error) {
+ return nil, syscall.EPLAN9
+}
+
+// Close closes the Unix domain connection.
+func (c *UnixConn) Close() error {
+ return syscall.EPLAN9
+}
+
+// ReadFromUnix reads a packet from c, copying the payload into b. It
+// returns the number of bytes copied into b and the source address of
+// the packet.
+//
+// ReadFromUnix can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
+ return 0, nil, syscall.EPLAN9
+}
+
// ReadFrom implements the PacketConn ReadFrom method.
-func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
- err = syscall.EPLAN9
- return
+func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
+ return 0, nil, syscall.EPLAN9
+}
+
+// ReadMsgUnix reads a packet from c, copying the payload into b and
+// the associated out-of-band data into oob. It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet, and the source address of the packet.
+func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
+ return 0, 0, 0, nil, syscall.EPLAN9
+}
+
+// WriteToUnix writes a packet to addr via c, copying the payload from b.
+//
+// WriteToUnix can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline. On packet-oriented connections, write timeouts
+// are rare.
+func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
+ return 0, syscall.EPLAN9
}
// WriteTo implements the PacketConn WriteTo method.
-func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
- err = syscall.EPLAN9
- return
+func (c *UnixConn) WriteTo(b []byte, addr Addr) (int, error) {
+ return 0, syscall.EPLAN9
+}
+
+// WriteMsgUnix writes a packet to addr via c, copying the payload
+// from b and the associated out-of-band data from oob. It returns
+// the number of payload and out-of-band bytes written.
+func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
+ return 0, 0, syscall.EPLAN9
+}
+
+// CloseRead shuts down the reading side of the Unix domain
+// connection. Most callers should just use Close.
+func (c *UnixConn) CloseRead() error {
+ return syscall.EPLAN9
+}
+
+// CloseWrite shuts down the writing side of the Unix domain
+// connection. Most callers should just use Close.
+func (c *UnixConn) CloseWrite() error {
+ return syscall.EPLAN9
}
// DialUnix connects to the remote address raddr on the network net,
-// which must be "unix" or "unixgram". If laddr is not nil, it is used
-// as the local address for the connection.
-func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err error) {
+// which must be "unix" or "unixgram". If laddr is not nil, it is
+// used as the local address for the connection.
+func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
return nil, syscall.EPLAN9
}
-// UnixListener is a Unix domain socket listener.
-// Clients should typically use variables of type Listener
-// instead of assuming Unix domain sockets.
+// UnixListener is a Unix domain socket listener. Clients should
+// typically use variables of type Listener instead of assuming Unix
+// domain sockets.
type UnixListener bool
-// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
-// Net must be "unix" (stream sockets).
-func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err error) {
+// ListenUnix announces on the Unix domain socket laddr and returns a
+// Unix listener. Net must be "unix" (stream sockets).
+func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
return nil, syscall.EPLAN9
}
-// Accept implements the Accept method in the Listener interface;
-// it waits for the next call and returns a generic Conn.
-func (l *UnixListener) Accept() (c Conn, err error) {
+// AcceptUnix accepts the next incoming call and returns the new
+// connection and the remote address.
+func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
return nil, syscall.EPLAN9
}
-// Close stops listening on the Unix address.
-// Already accepted connections are not closed.
+// Accept implements the Accept method in the Listener interface; it
+// waits for the next call and returns a generic Conn.
+func (l *UnixListener) Accept() (Conn, error) {
+ return nil, syscall.EPLAN9
+}
+
+// Close stops listening on the Unix address. Already accepted
+// connections are not closed.
func (l *UnixListener) Close() error {
return syscall.EPLAN9
}
// Addr returns the listener's network address.
func (l *UnixListener) Addr() Addr { return nil }
+
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *UnixListener) SetDeadline(t time.Time) error {
+ return syscall.EPLAN9
+}
+
+// File returns a copy of the underlying os.File, set to blocking
+// mode. It is the caller's responsibility to close f when finished.
+// Closing l does not affect f, and closing f does not affect l.
+func (l *UnixListener) File() (*os.File, error) {
+ return nil, syscall.EPLAN9
+}
+
+// ListenUnixgram listens for incoming Unix datagram packets addressed
+// to the local address laddr. The returned connection c's ReadFrom
+// and WriteTo methods can be used to receive and send UDP packets
+// with per-packet addressing. The network net must be "unixgram".
+func ListenUnixgram(net string, laddr *UnixAddr) (*UDPConn, error) {
+ return nil, syscall.EPLAN9
+}
diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go
index 57d784c71cf..2bef5eaaf12 100644
--- a/libgo/go/net/unixsock_posix.go
+++ b/libgo/go/net/unixsock_posix.go
@@ -111,99 +111,10 @@ func sotypeToNet(sotype int) string {
// UnixConn is an implementation of the Conn interface
// for connections to Unix domain sockets.
type UnixConn struct {
- fd *netFD
+ conn
}
-func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{fd} }
-
-func (c *UnixConn) ok() bool { return c != nil && c.fd != nil }
-
-// Implementation of the Conn interface - see Conn for documentation.
-
-// Read implements the Conn Read method.
-func (c *UnixConn) Read(b []byte) (n int, err error) {
- if !c.ok() {
- return 0, syscall.EINVAL
- }
- return c.fd.Read(b)
-}
-
-// Write implements the Conn Write method.
-func (c *UnixConn) Write(b []byte) (n int, err error) {
- if !c.ok() {
- return 0, syscall.EINVAL
- }
- return c.fd.Write(b)
-}
-
-// Close closes the Unix domain connection.
-func (c *UnixConn) Close() error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return c.fd.Close()
-}
-
-// LocalAddr returns the local network address, a *UnixAddr.
-// Unlike in other protocols, LocalAddr is usually nil for dialed connections.
-func (c *UnixConn) LocalAddr() Addr {
- if !c.ok() {
- return nil
- }
- return c.fd.laddr
-}
-
-// RemoteAddr returns the remote network address, a *UnixAddr.
-// Unlike in other protocols, RemoteAddr is usually nil for connections
-// accepted by a listener.
-func (c *UnixConn) RemoteAddr() Addr {
- if !c.ok() {
- return nil
- }
- return c.fd.raddr
-}
-
-// SetDeadline implements the Conn SetDeadline method.
-func (c *UnixConn) SetDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setDeadline(c.fd, t)
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *UnixConn) SetReadDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setReadDeadline(c.fd, t)
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *UnixConn) SetWriteDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setWriteDeadline(c.fd, t)
-}
-
-// SetReadBuffer sets the size of the operating system's
-// receive buffer associated with the connection.
-func (c *UnixConn) SetReadBuffer(bytes int) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setReadBuffer(c.fd, bytes)
-}
-
-// SetWriteBuffer sets the size of the operating system's
-// transmit buffer associated with the connection.
-func (c *UnixConn) SetWriteBuffer(bytes int) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return setWriteBuffer(c.fd, bytes)
-}
+func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
// ReadFromUnix reads a packet from c, copying the payload into b.
// It returns the number of bytes copied into b and the source address
@@ -296,10 +207,23 @@ func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err
return c.fd.WriteMsg(b, oob, nil)
}
-// File returns a copy of the underlying os.File, set to blocking mode.
-// It is the caller's responsibility to close f when finished.
-// Closing c does not affect f, and closing f does not affect c.
-func (c *UnixConn) File() (f *os.File, err error) { return c.fd.dup() }
+// CloseRead shuts down the reading side of the Unix domain connection.
+// Most callers should just use Close.
+func (c *UnixConn) CloseRead() error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return c.fd.CloseRead()
+}
+
+// CloseWrite shuts down the writing side of the Unix domain connection.
+// Most callers should just use Close.
+func (c *UnixConn) CloseWrite() error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return c.fd.CloseWrite()
+}
// DialUnix connects to the remote address raddr on the network net,
// which must be "unix" or "unixgram". If laddr is not nil, it is used
diff --git a/libgo/go/net/url/url.go b/libgo/go/net/url/url.go
index 17bf0d3a342..d1fff89da79 100644
--- a/libgo/go/net/url/url.go
+++ b/libgo/go/net/url/url.go
@@ -7,7 +7,9 @@
package url
import (
+ "bytes"
"errors"
+ "sort"
"strconv"
"strings"
)
@@ -519,12 +521,16 @@ func parseQuery(m Values, query string) (err error) {
}
key, err1 := QueryUnescape(key)
if err1 != nil {
- err = err1
+ if err == nil {
+ err = err1
+ }
continue
}
value, err1 = QueryUnescape(value)
if err1 != nil {
- err = err1
+ if err == nil {
+ err = err1
+ }
continue
}
m[key] = append(m[key], value)
@@ -538,14 +544,24 @@ func (v Values) Encode() string {
if v == nil {
return ""
}
- parts := make([]string, 0, len(v)) // will be large enough for most uses
- for k, vs := range v {
+ var buf bytes.Buffer
+ keys := make([]string, 0, len(v))
+ for k := range v {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ for _, k := range keys {
+ vs := v[k]
prefix := QueryEscape(k) + "="
for _, v := range vs {
- parts = append(parts, prefix+QueryEscape(v))
+ if buf.Len() > 0 {
+ buf.WriteByte('&')
+ }
+ buf.WriteString(prefix)
+ buf.WriteString(QueryEscape(v))
}
}
- return strings.Join(parts, "&")
+ return buf.String()
}
// resolvePath applies special path segments from refs and applies
diff --git a/libgo/go/net/url/url_test.go b/libgo/go/net/url/url_test.go
index 75e8abe4eb3..64f11700278 100644
--- a/libgo/go/net/url/url_test.go
+++ b/libgo/go/net/url/url_test.go
@@ -7,6 +7,7 @@ package url
import (
"fmt"
"reflect"
+ "strings"
"testing"
)
@@ -453,20 +454,24 @@ func TestEscape(t *testing.T) {
//}
type EncodeQueryTest struct {
- m Values
- expected string
- expected1 string
+ m Values
+ expected string
}
var encodeQueryTests = []EncodeQueryTest{
- {nil, "", ""},
- {Values{"q": {"puppies"}, "oe": {"utf8"}}, "q=puppies&oe=utf8", "oe=utf8&q=puppies"},
- {Values{"q": {"dogs", "&", "7"}}, "q=dogs&q=%26&q=7", "q=dogs&q=%26&q=7"},
+ {nil, ""},
+ {Values{"q": {"puppies"}, "oe": {"utf8"}}, "oe=utf8&q=puppies"},
+ {Values{"q": {"dogs", "&", "7"}}, "q=dogs&q=%26&q=7"},
+ {Values{
+ "a": {"a1", "a2", "a3"},
+ "b": {"b1", "b2", "b3"},
+ "c": {"c1", "c2", "c3"},
+ }, "a=a1&a=a2&a=a3&b=b1&b=b2&b=b3&c=c1&c=c2&c=c3"},
}
func TestEncodeQuery(t *testing.T) {
for _, tt := range encodeQueryTests {
- if q := tt.m.Encode(); q != tt.expected && q != tt.expected1 {
+ if q := tt.m.Encode(); q != tt.expected {
t.Errorf(`EncodeQuery(%+v) = %q, want %q`, tt.m, q, tt.expected)
}
}
@@ -775,3 +780,13 @@ func TestRequestURI(t *testing.T) {
}
}
}
+
+func TestParseFailure(t *testing.T) {
+ // Test that the first parse error is returned.
+ const url = "%gh&%ij"
+ _, err := ParseQuery(url)
+ errStr := fmt.Sprint(err)
+ if !strings.Contains(errStr, "%gh") {
+ t.Errorf(`ParseQuery(%q) returned error %q, want something containing %q"`, url, errStr, "%gh")
+ }
+}
diff --git a/libgo/go/os/dir.go b/libgo/go/os/dir.go
index c77560fc08c..a35d525319a 100644
--- a/libgo/go/os/dir.go
+++ b/libgo/go/os/dir.go
@@ -52,7 +52,7 @@ func (file *File) readdirnames(n int) (names []string, err error) {
entry_dirent := (*syscall.Dirent)(unsafe.Pointer(&file.dirinfo.buf[0]))
size := n
- if size < 0 {
+ if size <= 0 {
size = 100
n = -1
}
diff --git a/libgo/go/os/dir_plan9.go b/libgo/go/os/dir_plan9.go
index 7fa4c7f4449..ebce6d83d82 100644
--- a/libgo/go/os/dir_plan9.go
+++ b/libgo/go/os/dir_plan9.go
@@ -48,7 +48,7 @@ func (file *File) readdir(n int) (fi []FileInfo, err error) {
if m < syscall.STATFIXLEN {
return result, &PathError{"readdir", file.name, errShortStat}
}
- dir, e := UnmarshalDir(d.buf[d.bufp : d.bufp+int(m)])
+ dir, e := unmarshalDir(d.buf[d.bufp : d.bufp+int(m)])
if e != nil {
return result, &PathError{"readdir", file.name, e}
}
@@ -73,12 +73,12 @@ func (file *File) readdirnames(n int) (names []string, err error) {
return
}
-type Dir struct {
+type dir struct {
// system-modified data
Type uint16 // server type
Dev uint32 // server subtype
// file data
- Qid Qid // unique id from server
+ Qid qid // unique id from server
Mode uint32 // permissions
Atime uint32 // last read time
Mtime uint32 // last write time
@@ -89,16 +89,16 @@ type Dir struct {
Muid string // last modifier name
}
-type Qid struct {
+type qid struct {
Path uint64 // the file server's unique identification for the file
Vers uint32 // version number for given Path
Type uint8 // the type of the file (syscall.QTDIR for example)
}
-var nullDir = Dir{
+var nullDir = dir{
^uint16(0),
^uint32(0),
- Qid{^uint64(0), ^uint32(0), ^uint8(0)},
+ qid{^uint64(0), ^uint32(0), ^uint8(0)},
^uint32(0),
^uint32(0),
^uint32(0),
@@ -111,12 +111,12 @@ var nullDir = Dir{
// Null assigns members of d with special "don't care" values indicating
// they should not be written by syscall.Wstat.
-func (d *Dir) Null() {
+func (d *dir) Null() {
*d = nullDir
}
// pdir appends a 9P Stat message based on the contents of Dir d to a byte slice b.
-func pdir(b []byte, d *Dir) []byte {
+func pdir(b []byte, d *dir) []byte {
n := len(b)
b = pbit16(b, 0) // length, filled in later
b = pbit16(b, d.Type)
@@ -134,9 +134,9 @@ func pdir(b []byte, d *Dir) []byte {
return b
}
-// UnmarshalDir reads a 9P Stat message from a 9P protocol message stored in b,
-// returning the corresponding Dir struct.
-func UnmarshalDir(b []byte) (d *Dir, err error) {
+// unmarshalDir reads a 9P Stat message from a 9P protocol message stored in b,
+// returning the corresponding dir struct.
+func unmarshalDir(b []byte) (d *dir, err error) {
n := uint16(0)
n, b = gbit16(b)
@@ -144,7 +144,7 @@ func UnmarshalDir(b []byte) (d *Dir, err error) {
return nil, errBadStat
}
- d = new(Dir)
+ d = new(dir)
d.Type, b = gbit16(b)
d.Dev, b = gbit32(b)
d.Qid, b = gqid(b)
@@ -165,17 +165,17 @@ func UnmarshalDir(b []byte) (d *Dir, err error) {
}
// gqid reads the qid part of a 9P Stat message from a 9P protocol message stored in b,
-// returning the corresponding Qid struct and the remaining slice of b.
-func gqid(b []byte) (Qid, []byte) {
- var q Qid
+// returning the corresponding qid struct and the remaining slice of b.
+func gqid(b []byte) (qid, []byte) {
+ var q qid
q.Path, b = gbit64(b)
q.Vers, b = gbit32(b)
q.Type, b = gbit8(b)
return q, b
}
-// pqid appends a Qid struct q to a 9P message b.
-func pqid(b []byte, q Qid) []byte {
+// pqid appends a qid struct q to a 9P message b.
+func pqid(b []byte, q qid) []byte {
b = pbit64(b, q.Path)
b = pbit32(b, q.Vers)
b = pbit8(b, q.Type)
diff --git a/libgo/go/os/error_test.go b/libgo/go/os/error_test.go
index 054bb3fcbcc..02ed2351c5c 100644
--- a/libgo/go/os/error_test.go
+++ b/libgo/go/os/error_test.go
@@ -106,3 +106,27 @@ func TestIsExist(t *testing.T) {
}
}
}
+
+func TestErrPathNUL(t *testing.T) {
+ f, err := ioutil.TempFile("", "_Go_ErrPathNUL\x00")
+ if err == nil {
+ f.Close()
+ t.Fatal("TempFile should have failed")
+ }
+ f, err = ioutil.TempFile("", "_Go_ErrPathNUL")
+ if err != nil {
+ t.Fatalf("open ErrPathNUL tempfile: %s", err)
+ }
+ defer os.Remove(f.Name())
+ defer f.Close()
+ f2, err := os.OpenFile(f.Name(), os.O_RDWR, 0600)
+ if err != nil {
+ t.Fatalf("open ErrPathNUL: %s", err)
+ }
+ f2.Close()
+ f2, err = os.OpenFile(f.Name()+"\x00", os.O_RDWR, 0600)
+ if err == nil {
+ f2.Close()
+ t.Fatal("Open should have failed")
+ }
+}
diff --git a/libgo/go/os/exec.go b/libgo/go/os/exec.go
index 6681acfd43b..5aea3098b54 100644
--- a/libgo/go/os/exec.go
+++ b/libgo/go/os/exec.go
@@ -63,14 +63,6 @@ type Signal interface {
Signal() // to distinguish from other Stringers
}
-// The only signal values guaranteed to be present on all systems
-// are Interrupt (send the process an interrupt) and
-// Kill (force the process to exit).
-var (
- Interrupt Signal = syscall.SIGINT
- Kill Signal = syscall.SIGKILL
-)
-
// Getpid returns the process id of the caller.
func Getpid() int { return syscall.Getpid() }
diff --git a/libgo/go/os/exec/exec_test.go b/libgo/go/os/exec/exec_test.go
index 27ebb60d3d0..af07452b464 100644
--- a/libgo/go/os/exec/exec_test.go
+++ b/libgo/go/os/exec/exec_test.go
@@ -349,6 +349,11 @@ func TestHelperProcess(*testing.T) {
// TODO(bradfitz): broken? Sometimes.
// http://golang.org/issue/2603
// Skip this additional part of the test for now.
+ case "netbsd":
+ // TODO(jsing): This currently fails on NetBSD due to
+ // the cloned file descriptors that result from opening
+ // /dev/urandom.
+ // http://golang.org/issue/3955
default:
// Now verify that there are no other open fds.
var files []*os.File
diff --git a/libgo/go/os/exec_plan9.go b/libgo/go/os/exec_plan9.go
index 01f06e2cf93..2a7a5976373 100644
--- a/libgo/go/os/exec_plan9.go
+++ b/libgo/go/os/exec_plan9.go
@@ -11,6 +11,14 @@ import (
"time"
)
+// The only signal values guaranteed to be present on all systems
+// are Interrupt (send the process an interrupt) and Kill (force
+// the process to exit).
+var (
+ Interrupt Signal = syscall.Note("interrupt")
+ Kill Signal = syscall.Note("kill")
+)
+
func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
sysattr := &syscall.ProcAttr{
Dir: attr.Dir,
@@ -30,35 +38,35 @@ func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e
return newProcess(pid, h), nil
}
-// Plan9Note implements the Signal interface on Plan 9.
-type Plan9Note string
-
-func (note Plan9Note) String() string {
- return string(note)
+func (p *Process) writeProcFile(file string, data string) error {
+ f, e := OpenFile("/proc/"+itoa(p.Pid)+"/"+file, O_WRONLY, 0)
+ if e != nil {
+ return e
+ }
+ defer f.Close()
+ _, e = f.Write([]byte(data))
+ return e
}
func (p *Process) signal(sig Signal) error {
if p.done() {
return errors.New("os: process already finished")
}
-
- f, e := OpenFile("/proc/"+itoa(p.Pid)+"/note", O_WRONLY, 0)
- if e != nil {
+ if sig == Kill {
+ // Special-case the kill signal since it doesn't use /proc/$pid/note.
+ return p.Kill()
+ }
+ if e := p.writeProcFile("note", sig.String()); e != nil {
return NewSyscallError("signal", e)
}
- defer f.Close()
- _, e = f.Write([]byte(sig.String()))
- return e
+ return nil
}
func (p *Process) kill() error {
- f, e := OpenFile("/proc/"+itoa(p.Pid)+"/ctl", O_WRONLY, 0)
- if e != nil {
+ if e := p.writeProcFile("ctl", "kill"); e != nil {
return NewSyscallError("kill", e)
}
- defer f.Close()
- _, e = f.Write([]byte("kill"))
- return e
+ return nil
}
func (p *Process) wait() (ps *ProcessState, err error) {
diff --git a/libgo/go/os/exec_posix.go b/libgo/go/os/exec_posix.go
index 40fd0fd0ee6..2ced4d673b8 100644
--- a/libgo/go/os/exec_posix.go
+++ b/libgo/go/os/exec_posix.go
@@ -10,6 +10,14 @@ import (
"syscall"
)
+// The only signal values guaranteed to be present on all systems
+// are Interrupt (send the process an interrupt) and Kill (force
+// the process to exit).
+var (
+ Interrupt Signal = syscall.SIGINT
+ Kill Signal = syscall.SIGKILL
+)
+
func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
// If there is no SysProcAttr (ie. no Chroot or changed
// UID/GID), double-check existence of the directory we want
diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go
index cb0e9ef9289..db366a07cc9 100644
--- a/libgo/go/os/file_plan9.go
+++ b/libgo/go/os/file_plan9.go
@@ -5,14 +5,11 @@
package os
import (
- "errors"
"runtime"
"syscall"
"time"
)
-var ErrPlan9 = errors.New("unimplemented on Plan 9")
-
// File represents an open file descriptor.
type File struct {
*file
@@ -137,8 +134,8 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
-func (file *File) Close() error {
- return file.file.close()
+func (f *File) Close() error {
+ return f.file.close()
}
func (file *file) close() error {
@@ -159,8 +156,8 @@ func (file *file) close() error {
}
// Stat returns the FileInfo structure describing file.
-// It returns the FileInfo and an error, if any.
-func (f *File) Stat() (FileInfo, error) {
+// If there is an error, it will be of type *PathError.
+func (f *File) Stat() (fi FileInfo, err error) {
d, err := dirstat(f)
if err != nil {
return nil, err
@@ -170,8 +167,9 @@ func (f *File) Stat() (FileInfo, error) {
// Truncate changes the size of the file.
// It does not change the I/O offset.
+// If there is an error, it will be of type *PathError.
func (f *File) Truncate(size int64) error {
- var d Dir
+ var d dir
d.Null()
d.Length = uint64(size)
@@ -187,7 +185,7 @@ const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | Mod
// Chmod changes the mode of the file to mode.
// If there is an error, it will be of type *PathError.
func (f *File) Chmod(mode FileMode) error {
- var d Dir
+ var d dir
odir, e := dirstat(f)
if e != nil {
@@ -209,7 +207,7 @@ func (f *File) Sync() (err error) {
return ErrInvalid
}
- var d Dir
+ var d dir
d.Null()
if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil {
@@ -255,7 +253,7 @@ func (f *File) seek(offset int64, whence int) (ret int64, err error) {
// If the file is a symbolic link, it changes the size of the link's target.
// If there is an error, it will be of type *PathError.
func Truncate(name string, size int64) error {
- var d Dir
+ var d dir
d.Null()
d.Length = uint64(size)
@@ -277,7 +275,7 @@ func Remove(name string) error {
// Rename renames a file.
func Rename(oldname, newname string) error {
- var d Dir
+ var d dir
d.Null()
d.Name = newname
@@ -289,9 +287,10 @@ func Rename(oldname, newname string) error {
}
// Chmod changes the mode of the named file to mode.
+// If the file is a symbolic link, it changes the mode of the link's target.
// If there is an error, it will be of type *PathError.
func Chmod(name string, mode FileMode) error {
- var d Dir
+ var d dir
odir, e := dirstat(name)
if e != nil {
@@ -310,8 +309,9 @@ func Chmod(name string, mode FileMode) error {
//
// The underlying filesystem may truncate or round the values to a
// less precise time unit.
+// If there is an error, it will be of type *PathError.
func Chtimes(name string, atime time.Time, mtime time.Time) error {
- var d Dir
+ var d dir
d.Null()
d.Atime = uint32(atime.Unix())
@@ -323,6 +323,8 @@ func Chtimes(name string, atime time.Time, mtime time.Time) error {
return nil
}
+// Pipe returns a connected pair of Files; reads from r return bytes
+// written to w. It returns the files and an error, if any.
func Pipe() (r *File, w *File, err error) {
var p [2]int
@@ -338,32 +340,42 @@ func Pipe() (r *File, w *File, err error) {
// not supported on Plan 9
-// Link creates a hard link.
+// Link creates newname as a hard link to the oldname file.
// If there is an error, it will be of type *LinkError.
func Link(oldname, newname string) error {
- return &LinkError{"link", oldname, newname, ErrPlan9}
+ return &LinkError{"link", oldname, newname, syscall.EPLAN9}
}
// Symlink creates newname as a symbolic link to oldname.
// If there is an error, it will be of type *LinkError.
func Symlink(oldname, newname string) error {
- return &LinkError{"symlink", oldname, newname, ErrPlan9}
+ return &LinkError{"symlink", oldname, newname, syscall.EPLAN9}
}
+// Readlink returns the destination of the named symbolic link.
+// If there is an error, it will be of type *PathError.
func Readlink(name string) (string, error) {
- return "", ErrPlan9
+ return "", &PathError{"readlink", name, syscall.EPLAN9}
}
+// Chown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link's target.
+// If there is an error, it will be of type *PathError.
func Chown(name string, uid, gid int) error {
- return ErrPlan9
+ return &PathError{"chown", name, syscall.EPLAN9}
}
+// Lchown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link itself.
+// If there is an error, it will be of type *PathError.
func Lchown(name string, uid, gid int) error {
- return ErrPlan9
+ return &PathError{"lchown", name, syscall.EPLAN9}
}
+// Chown changes the numeric uid and gid of the named file.
+// If there is an error, it will be of type *PathError.
func (f *File) Chown(uid, gid int) error {
- return ErrPlan9
+ return &PathError{"chown", f.name, syscall.EPLAN9}
}
// TempDir returns the default directory to use for temporary files.
diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go
index 5046e60af43..671c301f048 100644
--- a/libgo/go/os/os_test.go
+++ b/libgo/go/os/os_test.go
@@ -6,6 +6,7 @@ package os_test
import (
"bytes"
+ "flag"
"fmt"
"io"
"io/ioutil"
@@ -1064,3 +1065,31 @@ func TestDevNullFile(t *testing.T) {
t.Fatalf("wrong file size have %d want 0", fi.Size())
}
}
+
+var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
+
+func TestLargeWriteToConsole(t *testing.T) {
+ if !*testLargeWrite {
+ t.Logf("skipping console-flooding test; enable with -large_write")
+ return
+ }
+ b := make([]byte, 32000)
+ for i := range b {
+ b[i] = '.'
+ }
+ b[len(b)-1] = '\n'
+ n, err := Stdout.Write(b)
+ if err != nil {
+ t.Fatalf("Write to os.Stdout failed: %v", err)
+ }
+ if n != len(b) {
+ t.Errorf("Write to os.Stdout should return %d; got %d", len(b), n)
+ }
+ n, err = Stderr.Write(b)
+ if err != nil {
+ t.Fatalf("Write to os.Stderr failed: %v", err)
+ }
+ if n != len(b) {
+ t.Errorf("Write to os.Stderr should return %d; got %d", len(b), n)
+ }
+}
diff --git a/libgo/go/os/path_plan9.go b/libgo/go/os/path_plan9.go
index 3121b7bc712..64bad500a67 100644
--- a/libgo/go/os/path_plan9.go
+++ b/libgo/go/os/path_plan9.go
@@ -5,8 +5,8 @@
package os
const (
- PathSeparator = '/' // OS-specific path separator
- PathListSeparator = 0 // OS-specific path list separator
+ PathSeparator = '/' // OS-specific path separator
+ PathListSeparator = '\000' // OS-specific path list separator
)
// IsPathSeparator returns true if c is a directory separator character.
diff --git a/libgo/go/os/path_test.go b/libgo/go/os/path_test.go
index c1e3fb35436..96f0f41e639 100644
--- a/libgo/go/os/path_test.go
+++ b/libgo/go/os/path_test.go
@@ -5,6 +5,7 @@
package os_test
import (
+ "io/ioutil"
. "os"
"path/filepath"
"runtime"
@@ -171,20 +172,23 @@ func TestMkdirAllWithSymlink(t *testing.T) {
return
}
- tmpDir := TempDir()
+ tmpDir, err := ioutil.TempDir("", "TestMkdirAllWithSymlink-")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer RemoveAll(tmpDir)
+
dir := tmpDir + "/dir"
- err := Mkdir(dir, 0755)
+ err = Mkdir(dir, 0755)
if err != nil {
t.Fatalf("Mkdir %s: %s", dir, err)
}
- defer RemoveAll(dir)
link := tmpDir + "/link"
err = Symlink("dir", link)
if err != nil {
t.Fatalf("Symlink %s: %s", link, err)
}
- defer RemoveAll(link)
path := link + "/foo"
err = MkdirAll(path, 0755)
diff --git a/libgo/go/os/stat_plan9.go b/libgo/go/os/stat_plan9.go
index a7990a359ec..1bc9dd0524a 100644
--- a/libgo/go/os/stat_plan9.go
+++ b/libgo/go/os/stat_plan9.go
@@ -10,12 +10,12 @@ import (
)
func sameFile(sys1, sys2 interface{}) bool {
- a := sys1.(*Dir)
- b := sys2.(*Dir)
+ a := sys1.(*dir)
+ b := sys2.(*dir)
return a.Qid.Path == b.Qid.Path && a.Type == b.Type && a.Dev == b.Dev
}
-func fileInfoFromStat(d *Dir) FileInfo {
+func fileInfoFromStat(d *dir) FileInfo {
fs := &fileStat{
name: d.Name,
size: int64(d.Length),
@@ -39,7 +39,7 @@ func fileInfoFromStat(d *Dir) FileInfo {
}
// arg is an open *File or a path string.
-func dirstat(arg interface{}) (d *Dir, err error) {
+func dirstat(arg interface{}) (d *dir, err error) {
var name string
// This is big enough for most stat messages
@@ -72,7 +72,7 @@ func dirstat(arg interface{}) (d *Dir, err error) {
// If the stat message is larger than our buffer we will
// go around the loop and allocate one that is big enough.
if size <= n {
- d, err = UnmarshalDir(buf[:n])
+ d, err = unmarshalDir(buf[:n])
if err != nil {
return nil, &PathError{"stat", name, err}
}
@@ -82,9 +82,9 @@ func dirstat(arg interface{}) (d *Dir, err error) {
return nil, &PathError{"stat", name, errBadStat}
}
-// Stat returns a FileInfo structure describing the named file.
+// Stat returns a FileInfo describing the named file.
// If there is an error, it will be of type *PathError.
-func Stat(name string) (FileInfo, error) {
+func Stat(name string) (fi FileInfo, err error) {
d, err := dirstat(name)
if err != nil {
return nil, err
@@ -92,15 +92,15 @@ func Stat(name string) (FileInfo, error) {
return fileInfoFromStat(d), nil
}
-// Lstat returns the FileInfo structure describing the named file.
-// If the file is a symbolic link (though Plan 9 does not have symbolic links),
-// the returned FileInfo describes the symbolic link. Lstat makes no attempt to follow the link.
+// Lstat returns a FileInfo describing the named file.
+// If the file is a symbolic link, the returned FileInfo
+// describes the symbolic link. Lstat makes no attempt to follow the link.
// If there is an error, it will be of type *PathError.
-func Lstat(name string) (FileInfo, error) {
+func Lstat(name string) (fi FileInfo, err error) {
return Stat(name)
}
// For testing.
func atime(fi FileInfo) time.Time {
- return time.Unix(int64(fi.Sys().(*Dir).Atime), 0)
+ return time.Unix(int64(fi.Sys().(*dir).Atime), 0)
}
diff --git a/libgo/go/os/user/lookup_unix.go b/libgo/go/os/user/lookup_unix.go
index ebc8684825d..5c964082010 100644
--- a/libgo/go/os/user/lookup_unix.go
+++ b/libgo/go/os/user/lookup_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux
+// +build darwin freebsd linux netbsd
// +build cgo
package user
diff --git a/libgo/go/os/user/lookup_windows.go b/libgo/go/os/user/lookup_windows.go
index 99368711594..3626a4e9f05 100644
--- a/libgo/go/os/user/lookup_windows.go
+++ b/libgo/go/os/user/lookup_windows.go
@@ -16,13 +16,21 @@ func lookupFullName(domain, username, domainAndUser string) (string, error) {
syscall.NameSamCompatible, syscall.NameDisplay, 50)
if e != nil {
// domain lookup failed, perhaps this pc is not part of domain
- d := syscall.StringToUTF16Ptr(domain)
- u := syscall.StringToUTF16Ptr(username)
- var p *byte
- e := syscall.NetUserGetInfo(d, u, 10, &p)
+ d, e := syscall.UTF16PtrFromString(domain)
+ if e != nil {
+ return "", e
+ }
+ u, e := syscall.UTF16PtrFromString(username)
if e != nil {
return "", e
}
+ var p *byte
+ e = syscall.NetUserGetInfo(d, u, 10, &p)
+ if e != nil {
+ // path executed when a domain user is disconnected from the domain
+ // pretend username is fullname
+ return username, nil
+ }
defer syscall.NetApiBufferFree(p)
i := (*syscall.UserInfo10)(unsafe.Pointer(p))
if i.FullName == nil {
diff --git a/libgo/go/os/user/user_test.go b/libgo/go/os/user/user_test.go
index b812ebce79a..1486fb84751 100644
--- a/libgo/go/os/user/user_test.go
+++ b/libgo/go/os/user/user_test.go
@@ -5,7 +5,6 @@
package user
import (
- "os"
"runtime"
"testing"
)
@@ -34,12 +33,11 @@ func TestCurrent(t *testing.T) {
if err != nil {
t.Fatalf("Current: %v", err)
}
- fi, err := os.Stat(u.HomeDir)
- if err != nil || !fi.IsDir() {
- t.Errorf("expected a valid HomeDir; stat(%q): err=%v", u.HomeDir, err)
+ if u.HomeDir == "" {
+ t.Errorf("didn't get a HomeDir")
}
if u.Username == "" {
- t.Fatalf("didn't get a username")
+ t.Errorf("didn't get a username")
}
}
diff --git a/libgo/go/path/filepath/path.go b/libgo/go/path/filepath/path.go
index 815021bd040..bb27f1c851a 100644
--- a/libgo/go/path/filepath/path.go
+++ b/libgo/go/path/filepath/path.go
@@ -13,6 +13,45 @@ import (
"strings"
)
+// A lazybuf is a lazily constructed path buffer.
+// It supports append, reading previously appended bytes,
+// and retrieving the final string. It does not allocate a buffer
+// to hold the output until that output diverges from s.
+type lazybuf struct {
+ path string
+ buf []byte
+ w int
+ volAndPath string
+ volLen int
+}
+
+func (b *lazybuf) index(i int) byte {
+ if b.buf != nil {
+ return b.buf[i]
+ }
+ return b.path[i]
+}
+
+func (b *lazybuf) append(c byte) {
+ if b.buf == nil {
+ if b.w < len(b.path) && b.path[b.w] == c {
+ b.w++
+ return
+ }
+ b.buf = make([]byte, len(b.path))
+ copy(b.buf, b.path[:b.w])
+ }
+ b.buf[b.w] = c
+ b.w++
+}
+
+func (b *lazybuf) string() string {
+ if b.buf == nil {
+ return b.volAndPath[:b.volLen+b.w]
+ }
+ return b.volAndPath[:b.volLen] + string(b.buf[:b.w])
+}
+
const (
Separator = os.PathSeparator
ListSeparator = os.PathListSeparator
@@ -40,14 +79,15 @@ const (
// Getting Dot-Dot Right,''
// http://plan9.bell-labs.com/sys/doc/lexnames.html
func Clean(path string) string {
- vol := VolumeName(path)
- path = path[len(vol):]
+ originalPath := path
+ volLen := volumeNameLen(path)
+ path = path[volLen:]
if path == "" {
- if len(vol) > 1 && vol[1] != ':' {
+ if volLen > 1 && originalPath[1] != ':' {
// should be UNC
- return FromSlash(vol)
+ return FromSlash(originalPath)
}
- return vol + "."
+ return originalPath + "."
}
rooted := os.IsPathSeparator(path[0])
@@ -57,11 +97,11 @@ func Clean(path string) string {
// dotdot is index in buf where .. must stop, either because
// it is the leading slash or it is a leading ../../.. prefix.
n := len(path)
- buf := []byte(path)
- r, w, dotdot := 0, 0, 0
+ out := lazybuf{path: path, volAndPath: originalPath, volLen: volLen}
+ r, dotdot := 0, 0
if rooted {
- buf[0] = Separator
- r, w, dotdot = 1, 1, 1
+ out.append(Separator)
+ r, dotdot = 1, 1
}
for r < n {
@@ -76,46 +116,40 @@ func Clean(path string) string {
// .. element: remove to last separator
r += 2
switch {
- case w > dotdot:
+ case out.w > dotdot:
// can backtrack
- w--
- for w > dotdot && !os.IsPathSeparator(buf[w]) {
- w--
+ out.w--
+ for out.w > dotdot && !os.IsPathSeparator(out.index(out.w)) {
+ out.w--
}
case !rooted:
// cannot backtrack, but not rooted, so append .. element.
- if w > 0 {
- buf[w] = Separator
- w++
+ if out.w > 0 {
+ out.append(Separator)
}
- buf[w] = '.'
- w++
- buf[w] = '.'
- w++
- dotdot = w
+ out.append('.')
+ out.append('.')
+ dotdot = out.w
}
default:
// real path element.
// add slash if needed
- if rooted && w != 1 || !rooted && w != 0 {
- buf[w] = Separator
- w++
+ if rooted && out.w != 1 || !rooted && out.w != 0 {
+ out.append(Separator)
}
// copy element
for ; r < n && !os.IsPathSeparator(path[r]); r++ {
- buf[w] = path[r]
- w++
+ out.append(path[r])
}
}
}
// Turn empty string into "."
- if w == 0 {
- buf[w] = '.'
- w++
+ if out.w == 0 {
+ out.append('.')
}
- return FromSlash(vol + string(buf[0:w]))
+ return FromSlash(out.string())
}
// ToSlash returns the result of replacing each separator character
@@ -417,3 +451,11 @@ func Dir(path string) string {
}
return vol + dir
}
+
+// VolumeName returns leading volume name.
+// Given "C:\foo\bar" it returns "C:" under windows.
+// Given "\\host\share\foo" it returns "\\host\share".
+// On other platforms it returns "".
+func VolumeName(path string) (v string) {
+ return path[:volumeNameLen(path)]
+}
diff --git a/libgo/go/path/filepath/path_plan9.go b/libgo/go/path/filepath/path_plan9.go
index 59a5812dd0b..0c938d89da1 100644
--- a/libgo/go/path/filepath/path_plan9.go
+++ b/libgo/go/path/filepath/path_plan9.go
@@ -11,10 +11,10 @@ func IsAbs(path string) bool {
return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "#")
}
-// VolumeName returns the leading volume name on Windows.
-// It returns "" elsewhere.
-func VolumeName(path string) string {
- return ""
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
+ return 0
}
// HasPrefix exists for historical compatibility and should not be used.
diff --git a/libgo/go/path/filepath/path_test.go b/libgo/go/path/filepath/path_test.go
index 097b0d9dc82..577b0a3e125 100644
--- a/libgo/go/path/filepath/path_test.go
+++ b/libgo/go/path/filepath/path_test.go
@@ -20,7 +20,6 @@ type PathTest struct {
var cleantests = []PathTest{
// Already clean
- {"", "."},
{"abc", "abc"},
{"abc/def", "abc/def"},
{"a/b/c", "a/b/c"},
@@ -31,6 +30,9 @@ var cleantests = []PathTest{
{"/abc", "/abc"},
{"/", "/"},
+ // Empty is current dir
+ {"", "."},
+
// Remove trailing slash
{"abc/", "abc"},
{"abc/def/", "abc/def"},
@@ -61,6 +63,7 @@ var cleantests = []PathTest{
{"abc/def/../../..", ".."},
{"/abc/def/../../..", "/"},
{"abc/def/../../../ghi/jkl/../../../mno", "../../mno"},
+ {"/../abc", "/abc"},
// Combinations
{"abc/./../def", "def"},
@@ -99,7 +102,27 @@ func TestClean(t *testing.T) {
if s := filepath.Clean(test.path); s != test.result {
t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.result)
}
+ if s := filepath.Clean(test.result); s != test.result {
+ t.Errorf("Clean(%q) = %q, want %q", test.result, s, test.result)
+ }
+ }
+
+ var ms runtime.MemStats
+ runtime.ReadMemStats(&ms)
+ allocs := -ms.Mallocs
+ const rounds = 100
+ for i := 0; i < rounds; i++ {
+ for _, test := range tests {
+ filepath.Clean(test.result)
+ }
+ }
+ runtime.ReadMemStats(&ms)
+ allocs += ms.Mallocs
+ /* Fails with gccgo, which has no escape analysis.
+ if allocs >= rounds {
+ t.Errorf("Clean cleaned paths: %d allocations per test round, want zero", allocs/rounds)
}
+ */
}
const sep = filepath.Separator
@@ -684,10 +707,15 @@ func TestAbs(t *testing.T) {
}
defer os.RemoveAll(root)
+ wd, err := os.Getwd()
+ if err != nil {
+ t.Fatal("getwd failed: ", err)
+ }
err = os.Chdir(root)
if err != nil {
t.Fatal("chdir failed: ", err)
}
+ defer os.Chdir(wd)
for _, dir := range absTestDirs {
err = os.Mkdir(dir, 0777)
diff --git a/libgo/go/path/filepath/path_unix.go b/libgo/go/path/filepath/path_unix.go
index 305e307272f..3b48d14e083 100644
--- a/libgo/go/path/filepath/path_unix.go
+++ b/libgo/go/path/filepath/path_unix.go
@@ -13,10 +13,10 @@ func IsAbs(path string) bool {
return strings.HasPrefix(path, "/")
}
-// VolumeName returns the leading volume name on Windows.
-// It returns "" elsewhere.
-func VolumeName(path string) string {
- return ""
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
+ return 0
}
// HasPrefix exists for historical compatibility and should not be used.
diff --git a/libgo/go/path/filepath/path_windows.go b/libgo/go/path/filepath/path_windows.go
index 3dcd0302195..db2b57ec00a 100644
--- a/libgo/go/path/filepath/path_windows.go
+++ b/libgo/go/path/filepath/path_windows.go
@@ -14,29 +14,27 @@ func isSlash(c uint8) bool {
// IsAbs returns true if the path is absolute.
func IsAbs(path string) (b bool) {
- v := VolumeName(path)
- if v == "" {
+ l := volumeNameLen(path)
+ if l == 0 {
return false
}
- path = path[len(v):]
+ path = path[l:]
if path == "" {
return false
}
return isSlash(path[0])
}
-// VolumeName returns leading volume name.
-// Given "C:\foo\bar" it returns "C:" under windows.
-// Given "\\host\share\foo" it returns "\\host\share".
-// On other platforms it returns "".
-func VolumeName(path string) (v string) {
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
if len(path) < 2 {
- return ""
+ return 0
}
// with drive letter
c := path[0]
if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
- return path[:2]
+ return 2
}
// is it UNC
if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&
@@ -56,13 +54,13 @@ func VolumeName(path string) (v string) {
break
}
}
- return path[:n]
+ return n
}
break
}
}
}
- return ""
+ return 0
}
// HasPrefix exists for historical compatibility and should not be used.
diff --git a/libgo/go/path/filepath/symlink_windows.go b/libgo/go/path/filepath/symlink_windows.go
index 1ee939928e9..9adc8a48af0 100644
--- a/libgo/go/path/filepath/symlink_windows.go
+++ b/libgo/go/path/filepath/symlink_windows.go
@@ -9,7 +9,10 @@ import (
)
func toShort(path string) (string, error) {
- p := syscall.StringToUTF16(path)
+ p, err := syscall.UTF16FromString(path)
+ if err != nil {
+ return "", err
+ }
b := p // GetShortPathName says we can reuse buffer
n, err := syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
if err != nil {
@@ -26,7 +29,10 @@ func toShort(path string) (string, error) {
}
func toLong(path string) (string, error) {
- p := syscall.StringToUTF16(path)
+ p, err := syscall.UTF16FromString(path)
+ if err != nil {
+ return "", err
+ }
b := p // GetLongPathName says we can reuse buffer
n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b)))
if err != nil {
diff --git a/libgo/go/path/path.go b/libgo/go/path/path.go
index b07534b36f4..bdb85c6b92a 100644
--- a/libgo/go/path/path.go
+++ b/libgo/go/path/path.go
@@ -10,6 +10,43 @@ import (
"strings"
)
+// A lazybuf is a lazily constructed path buffer.
+// It supports append, reading previously appended bytes,
+// and retrieving the final string. It does not allocate a buffer
+// to hold the output until that output diverges from s.
+type lazybuf struct {
+ s string
+ buf []byte
+ w int
+}
+
+func (b *lazybuf) index(i int) byte {
+ if b.buf != nil {
+ return b.buf[i]
+ }
+ return b.s[i]
+}
+
+func (b *lazybuf) append(c byte) {
+ if b.buf == nil {
+ if b.w < len(b.s) && b.s[b.w] == c {
+ b.w++
+ return
+ }
+ b.buf = make([]byte, len(b.s))
+ copy(b.buf, b.s[:b.w])
+ }
+ b.buf[b.w] = c
+ b.w++
+}
+
+func (b *lazybuf) string() string {
+ if b.buf == nil {
+ return b.s[:b.w]
+ }
+ return string(b.buf[:b.w])
+}
+
// Clean returns the shortest path name equivalent to path
// by purely lexical processing. It applies the following rules
// iteratively until no further processing can be done:
@@ -42,10 +79,11 @@ func Clean(path string) string {
// writing to buf; w is index of next byte to write.
// dotdot is index in buf where .. must stop, either because
// it is the leading slash or it is a leading ../../.. prefix.
- buf := []byte(path)
- r, w, dotdot := 0, 0, 0
+ out := lazybuf{s: path}
+ r, dotdot := 0, 0
if rooted {
- r, w, dotdot = 1, 1, 1
+ out.append('/')
+ r, dotdot = 1, 1
}
for r < n {
@@ -60,46 +98,40 @@ func Clean(path string) string {
// .. element: remove to last /
r += 2
switch {
- case w > dotdot:
+ case out.w > dotdot:
// can backtrack
- w--
- for w > dotdot && buf[w] != '/' {
- w--
+ out.w--
+ for out.w > dotdot && out.index(out.w) != '/' {
+ out.w--
}
case !rooted:
// cannot backtrack, but not rooted, so append .. element.
- if w > 0 {
- buf[w] = '/'
- w++
+ if out.w > 0 {
+ out.append('/')
}
- buf[w] = '.'
- w++
- buf[w] = '.'
- w++
- dotdot = w
+ out.append('.')
+ out.append('.')
+ dotdot = out.w
}
default:
// real path element.
// add slash if needed
- if rooted && w != 1 || !rooted && w != 0 {
- buf[w] = '/'
- w++
+ if rooted && out.w != 1 || !rooted && out.w != 0 {
+ out.append('/')
}
// copy element
for ; r < n && path[r] != '/'; r++ {
- buf[w] = path[r]
- w++
+ out.append(path[r])
}
}
}
// Turn empty string into "."
- if w == 0 {
- buf[w] = '.'
- w++
+ if out.w == 0 {
+ return "."
}
- return string(buf[0:w])
+ return out.string()
}
// Split splits path immediately following the final slash.
diff --git a/libgo/go/path/path_test.go b/libgo/go/path/path_test.go
index 65be5506042..69096494e2a 100644
--- a/libgo/go/path/path_test.go
+++ b/libgo/go/path/path_test.go
@@ -5,6 +5,7 @@
package path
import (
+ "runtime"
"testing"
)
@@ -67,7 +68,27 @@ func TestClean(t *testing.T) {
if s := Clean(test.path); s != test.result {
t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.result)
}
+ if s := Clean(test.result); s != test.result {
+ t.Errorf("Clean(%q) = %q, want %q", test.result, s, test.result)
+ }
+ }
+
+ var ms runtime.MemStats
+ runtime.ReadMemStats(&ms)
+ allocs := -ms.Mallocs
+ const rounds = 100
+ for i := 0; i < rounds; i++ {
+ for _, test := range cleantests {
+ Clean(test.result)
+ }
+ }
+ runtime.ReadMemStats(&ms)
+ allocs += ms.Mallocs
+ /* Fails with gccgo, which has no escape analysis.
+ if allocs >= rounds {
+ t.Errorf("Clean cleaned paths: %d allocations per test round, want zero", allocs/rounds)
}
+ */
}
type SplitTest struct {
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index 56ba8a824c2..10f995eaf13 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -7,12 +7,16 @@ package reflect_test
import (
"bytes"
"encoding/base64"
+ "flag"
"fmt"
"io"
+ "math/rand"
"os"
. "reflect"
/* "runtime" */
+ "sync"
"testing"
+ "time"
"unsafe"
)
@@ -1053,29 +1057,402 @@ func TestChan(t *testing.T) {
if l, m := cv.Len(), cv.Cap(); l != len(c) || m != cap(c) {
t.Errorf("Len/Cap = %d/%d want %d/%d", l, m, len(c), cap(c))
}
+}
+
+// caseInfo describes a single case in a select test.
+type caseInfo struct {
+ desc string
+ canSelect bool
+ recv Value
+ closed bool
+ helper func()
+ panic bool
+}
+
+var allselect = flag.Bool("allselect", false, "exhaustive select test")
+
+func TestSelect(t *testing.T) {
+ selectWatch.once.Do(func() { go selectWatcher() })
+
+ var x exhaustive
+ nch := 0
+ newop := func(n int, cap int) (ch, val Value) {
+ nch++
+ if nch%101%2 == 1 {
+ c := make(chan int, cap)
+ ch = ValueOf(c)
+ val = ValueOf(n)
+ } else {
+ c := make(chan string, cap)
+ ch = ValueOf(c)
+ val = ValueOf(fmt.Sprint(n))
+ }
+ return
+ }
+
+ for n := 0; x.Next(); n++ {
+ if testing.Short() && n >= 1000 {
+ break
+ }
+ if n >= 100000 && !*allselect {
+ break
+ }
+ if n%100000 == 0 && testing.Verbose() {
+ println("TestSelect", n)
+ }
+ var cases []SelectCase
+ var info []caseInfo
+
+ // Ready send.
+ if x.Maybe() {
+ ch, val := newop(len(cases), 1)
+ cases = append(cases, SelectCase{
+ Dir: SelectSend,
+ Chan: ch,
+ Send: val,
+ })
+ info = append(info, caseInfo{desc: "ready send", canSelect: true})
+ }
+
+ // Ready recv.
+ if x.Maybe() {
+ ch, val := newop(len(cases), 1)
+ ch.Send(val)
+ cases = append(cases, SelectCase{
+ Dir: SelectRecv,
+ Chan: ch,
+ })
+ info = append(info, caseInfo{desc: "ready recv", canSelect: true, recv: val})
+ }
+
+ // Blocking send.
+ if x.Maybe() {
+ ch, val := newop(len(cases), 0)
+ cases = append(cases, SelectCase{
+ Dir: SelectSend,
+ Chan: ch,
+ Send: val,
+ })
+ // Let it execute?
+ if x.Maybe() {
+ f := func() { ch.Recv() }
+ info = append(info, caseInfo{desc: "blocking send", helper: f})
+ } else {
+ info = append(info, caseInfo{desc: "blocking send"})
+ }
+ }
+
+ // Blocking recv.
+ if x.Maybe() {
+ ch, val := newop(len(cases), 0)
+ cases = append(cases, SelectCase{
+ Dir: SelectRecv,
+ Chan: ch,
+ })
+ // Let it execute?
+ if x.Maybe() {
+ f := func() { ch.Send(val) }
+ info = append(info, caseInfo{desc: "blocking recv", recv: val, helper: f})
+ } else {
+ info = append(info, caseInfo{desc: "blocking recv"})
+ }
+ }
+
+ // Zero Chan send.
+ if x.Maybe() {
+ // Maybe include value to send.
+ var val Value
+ if x.Maybe() {
+ val = ValueOf(100)
+ }
+ cases = append(cases, SelectCase{
+ Dir: SelectSend,
+ Send: val,
+ })
+ info = append(info, caseInfo{desc: "zero Chan send"})
+ }
+
+ // Zero Chan receive.
+ if x.Maybe() {
+ cases = append(cases, SelectCase{
+ Dir: SelectRecv,
+ })
+ info = append(info, caseInfo{desc: "zero Chan recv"})
+ }
+
+ // nil Chan send.
+ if x.Maybe() {
+ cases = append(cases, SelectCase{
+ Dir: SelectSend,
+ Chan: ValueOf((chan int)(nil)),
+ Send: ValueOf(101),
+ })
+ info = append(info, caseInfo{desc: "nil Chan send"})
+ }
+
+ // nil Chan recv.
+ if x.Maybe() {
+ cases = append(cases, SelectCase{
+ Dir: SelectRecv,
+ Chan: ValueOf((chan int)(nil)),
+ })
+ info = append(info, caseInfo{desc: "nil Chan recv"})
+ }
+
+ // closed Chan send.
+ if x.Maybe() {
+ ch := make(chan int)
+ close(ch)
+ cases = append(cases, SelectCase{
+ Dir: SelectSend,
+ Chan: ValueOf(ch),
+ Send: ValueOf(101),
+ })
+ info = append(info, caseInfo{desc: "closed Chan send", canSelect: true, panic: true})
+ }
+
+ // closed Chan recv.
+ if x.Maybe() {
+ ch, val := newop(len(cases), 0)
+ ch.Close()
+ val = Zero(val.Type())
+ cases = append(cases, SelectCase{
+ Dir: SelectRecv,
+ Chan: ch,
+ })
+ info = append(info, caseInfo{desc: "closed Chan recv", canSelect: true, closed: true, recv: val})
+ }
+
+ var helper func() // goroutine to help the select complete
+
+ // Add default? Must be last case here, but will permute.
+ // Add the default if the select would otherwise
+ // block forever, and maybe add it anyway.
+ numCanSelect := 0
+ canProceed := false
+ canBlock := true
+ canPanic := false
+ helpers := []int{}
+ for i, c := range info {
+ if c.canSelect {
+ canProceed = true
+ canBlock = false
+ numCanSelect++
+ if c.panic {
+ canPanic = true
+ }
+ } else if c.helper != nil {
+ canProceed = true
+ helpers = append(helpers, i)
+ }
+ }
+ if !canProceed || x.Maybe() {
+ cases = append(cases, SelectCase{
+ Dir: SelectDefault,
+ })
+ info = append(info, caseInfo{desc: "default", canSelect: canBlock})
+ numCanSelect++
+ } else if canBlock {
+ // Select needs to communicate with another goroutine.
+ cas := &info[helpers[x.Choose(len(helpers))]]
+ helper = cas.helper
+ cas.canSelect = true
+ numCanSelect++
+ }
+
+ // Permute cases and case info.
+ // Doing too much here makes the exhaustive loop
+ // too exhausting, so just do two swaps.
+ for loop := 0; loop < 2; loop++ {
+ i := x.Choose(len(cases))
+ j := x.Choose(len(cases))
+ cases[i], cases[j] = cases[j], cases[i]
+ info[i], info[j] = info[j], info[i]
+ }
+
+ if helper != nil {
+ // We wait before kicking off a goroutine to satisfy a blocked select.
+ // The pause needs to be big enough to let the select block before
+ // we run the helper, but if we lose that race once in a while it's okay: the
+ // select will just proceed immediately. Not a big deal.
+ // For short tests we can grow [sic] the timeout a bit without fear of taking too long
+ pause := 10 * time.Microsecond
+ if testing.Short() {
+ pause = 100 * time.Microsecond
+ }
+ time.AfterFunc(pause, helper)
+ }
+
+ // Run select.
+ i, recv, recvOK, panicErr := runSelect(cases, info)
+ if panicErr != nil && !canPanic {
+ t.Fatalf("%s\npanicked unexpectedly: %v", fmtSelect(info), panicErr)
+ }
+ if panicErr == nil && canPanic && numCanSelect == 1 {
+ t.Fatalf("%s\nselected #%d incorrectly (should panic)", fmtSelect(info), i)
+ }
+ if panicErr != nil {
+ continue
+ }
+
+ cas := info[i]
+ if !cas.canSelect {
+ recvStr := ""
+ if recv.IsValid() {
+ recvStr = fmt.Sprintf(", received %v, %v", recv.Interface(), recvOK)
+ }
+ t.Fatalf("%s\nselected #%d incorrectly%s", fmtSelect(info), i, recvStr)
+ continue
+ }
+ if cas.panic {
+ t.Fatalf("%s\nselected #%d incorrectly (case should panic)", fmtSelect(info), i)
+ continue
+ }
+
+ if cases[i].Dir == SelectRecv {
+ if !recv.IsValid() {
+ t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, cas.recv.Interface(), !cas.closed)
+ }
+ if !cas.recv.IsValid() {
+ t.Fatalf("%s\nselected #%d but internal error: missing recv value", fmtSelect(info), i)
+ }
+ if recv.Interface() != cas.recv.Interface() || recvOK != !cas.closed {
+ if recv.Interface() == cas.recv.Interface() && recvOK == !cas.closed {
+ t.Fatalf("%s\nselected #%d, got %#v, %v, and DeepEqual is broken on %T", fmtSelect(info), i, recv.Interface(), recvOK, recv.Interface())
+ }
+ t.Fatalf("%s\nselected #%d but got %#v, %v, want %#v, %v", fmtSelect(info), i, recv.Interface(), recvOK, cas.recv.Interface(), !cas.closed)
+ }
+ } else {
+ if recv.IsValid() || recvOK {
+ t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, Value{}, false)
+ }
+ }
+ }
+}
+
+// selectWatch and the selectWatcher are a watchdog mechanism for running Select.
+// If the selectWatcher notices that the select has been blocked for >1 second, it prints
+// an error describing the select and panics the entire test binary.
+var selectWatch struct {
+ sync.Mutex
+ once sync.Once
+ now time.Time
+ info []caseInfo
+}
+
+func selectWatcher() {
+ for {
+ time.Sleep(1 * time.Second)
+ selectWatch.Lock()
+ if selectWatch.info != nil && time.Since(selectWatch.now) > 1*time.Second {
+ fmt.Fprintf(os.Stderr, "TestSelect:\n%s blocked indefinitely\n", fmtSelect(selectWatch.info))
+ panic("select stuck")
+ }
+ selectWatch.Unlock()
+ }
+}
+
+// runSelect runs a single select test.
+// It returns the values returned by Select but also returns
+// a panic value if the Select panics.
+func runSelect(cases []SelectCase, info []caseInfo) (chosen int, recv Value, recvOK bool, panicErr interface{}) {
+ defer func() {
+ panicErr = recover()
+
+ selectWatch.Lock()
+ selectWatch.info = nil
+ selectWatch.Unlock()
+ }()
+
+ selectWatch.Lock()
+ selectWatch.now = time.Now()
+ selectWatch.info = info
+ selectWatch.Unlock()
+ chosen, recv, recvOK = Select(cases)
+ return
}
+// fmtSelect formats the information about a single select test.
+func fmtSelect(info []caseInfo) string {
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "\nselect {\n")
+ for i, cas := range info {
+ fmt.Fprintf(&buf, "%d: %s", i, cas.desc)
+ if cas.recv.IsValid() {
+ fmt.Fprintf(&buf, " val=%#v", cas.recv.Interface())
+ }
+ if cas.canSelect {
+ fmt.Fprintf(&buf, " canselect")
+ }
+ if cas.panic {
+ fmt.Fprintf(&buf, " panic")
+ }
+ fmt.Fprintf(&buf, "\n")
+ }
+ fmt.Fprintf(&buf, "}")
+ return buf.String()
+}
+
+type two [2]uintptr
+
// Difficult test for function call because of
// implicit padding between arguments.
-func dummy(b byte, c int, d byte) (i byte, j int, k byte) {
- return b, c, d
+func dummy(b byte, c int, d byte, e two, f byte, g float32, h byte) (i byte, j int, k byte, l two, m byte, n float32, o byte) {
+ return b, c, d, e, f, g, h
}
func TestFunc(t *testing.T) {
- ret := ValueOf(dummy).Call([]Value{ValueOf(byte(10)), ValueOf(20), ValueOf(byte(30))})
- if len(ret) != 3 {
- t.Fatalf("Call returned %d values, want 3", len(ret))
+ ret := ValueOf(dummy).Call([]Value{
+ ValueOf(byte(10)),
+ ValueOf(20),
+ ValueOf(byte(30)),
+ ValueOf(two{40, 50}),
+ ValueOf(byte(60)),
+ ValueOf(float32(70)),
+ ValueOf(byte(80)),
+ })
+ if len(ret) != 7 {
+ t.Fatalf("Call returned %d values, want 7", len(ret))
}
i := byte(ret[0].Uint())
j := int(ret[1].Int())
k := byte(ret[2].Uint())
- if i != 10 || j != 20 || k != 30 {
- t.Errorf("Call returned %d, %d, %d; want 10, 20, 30", i, j, k)
+ l := ret[3].Interface().(two)
+ m := byte(ret[4].Uint())
+ n := float32(ret[5].Float())
+ o := byte(ret[6].Uint())
+
+ if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
+ t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
}
}
+/*
+
+Not yet implemented for gccgo.
+
+func TestMakeFunc(t *testing.T) {
+ f := dummy
+ fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })
+ ValueOf(&f).Elem().Set(fv)
+
+ // Call g with small arguments so that there is
+ // something predictable (and different from the
+ // correct results) in those positions on the stack.
+ g := dummy
+ g(1, 2, 3, two{4, 5}, 6, 7, 8)
+
+ // Call constructed function f.
+ i, j, k, l, m, n, o := f(10, 20, 30, two{40, 50}, 60, 70, 80)
+ if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
+ t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
+ }
+}
+
+*/
+
type Point struct {
x, y int
}
@@ -1123,7 +1500,7 @@ func TestMethod(t *testing.T) {
}
// Curried method of value.
- tfunc := TypeOf(func(int) int(nil))
+ tfunc := TypeOf((func(int) int)(nil))
v := ValueOf(p).Method(1)
if tt := v.Type(); tt != tfunc {
t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
@@ -1225,7 +1602,7 @@ func TestAnonymousFields(t *testing.T) {
var t1 T1
type1 := TypeOf(t1)
if field, ok = type1.FieldByName("int"); !ok {
- t.Error("no field 'int'")
+ t.Fatal("no field 'int'")
}
if field.Index[0] != 1 {
t.Error("field index should be 1; is", field.Index)
@@ -1282,6 +1659,47 @@ type S4 struct {
A int
}
+// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
+type S5 struct {
+ S6
+ S7
+ S8
+}
+
+type S6 struct {
+ X int
+}
+
+type S7 S6
+
+type S8 struct {
+ S9
+}
+
+type S9 struct {
+ X int
+ Y int
+}
+
+// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
+type S10 struct {
+ S11
+ S12
+ S13
+}
+
+type S11 struct {
+ S6
+}
+
+type S12 struct {
+ S6
+}
+
+type S13 struct {
+ S8
+}
+
var fieldTests = []FTest{
{struct{}{}, "", nil, 0},
{struct{}{}, "Foo", nil, 0},
@@ -1303,6 +1721,10 @@ var fieldTests = []FTest{
{S3{E: 'e'}, "E", []int{3}, 'e'},
{S4{A: 'a'}, "A", []int{1}, 'a'},
{S4{}, "B", nil, 0},
+ {S5{}, "X", nil, 0},
+ {S5{}, "Y", []int{2, 0, 1}, 0},
+ {S10{}, "X", nil, 0},
+ {S10{}, "Y", []int{2, 0, 0, 1}, 0},
}
func TestFieldByIndex(t *testing.T) {
@@ -1346,7 +1768,7 @@ func TestFieldByName(t *testing.T) {
if test.index != nil {
// Verify field depth and index.
if len(f.Index) != len(test.index) {
- t.Errorf("%s.%s depth %d; want %d", s.Name(), test.name, len(f.Index), len(test.index))
+ t.Errorf("%s.%s depth %d; want %d: %v vs %v", s.Name(), test.name, len(f.Index), len(test.index), f.Index, test.index)
} else {
for i, x := range f.Index {
if x != test.index[i] {
@@ -1594,9 +2016,10 @@ func noAlloc(t *testing.T, n int, f func(int)) {
}
// A few allocs may happen in the testing package when GOMAXPROCS > 1, so don't
// require zero mallocs.
+ // A new thread, one of which will be created if GOMAXPROCS>1, does 6 allocations.
runtime.ReadMemStats(memstats)
mallocs := memstats.Mallocs - oldmallocs
- if mallocs > 5 {
+ if mallocs > 10 {
t.Fatalf("%d mallocs after %d iterations", mallocs, n)
}
}
@@ -1787,3 +2210,640 @@ func TestAlias(t *testing.T) {
t.Errorf("aliasing: old=%q new=%q, want hello, world", oldvalue, newvalue)
}
}
+
+var V = ValueOf
+
+func EmptyInterfaceV(x interface{}) Value {
+ return ValueOf(&x).Elem()
+}
+
+func ReaderV(x io.Reader) Value {
+ return ValueOf(&x).Elem()
+}
+
+func ReadWriterV(x io.ReadWriter) Value {
+ return ValueOf(&x).Elem()
+}
+
+type Empty struct{}
+type MyString string
+type MyBytes []byte
+type MyRunes []int32
+type MyFunc func()
+type MyByte byte
+
+var convertTests = []struct {
+ in Value
+ out Value
+}{
+ // numbers
+ /*
+ Edit .+1,/\*\//-1>cat >/tmp/x.go && go run /tmp/x.go
+
+ package main
+
+ import "fmt"
+
+ var numbers = []string{
+ "int8", "uint8", "int16", "uint16",
+ "int32", "uint32", "int64", "uint64",
+ "int", "uint", "uintptr",
+ "float32", "float64",
+ }
+
+ func main() {
+ // all pairs but in an unusual order,
+ // to emit all the int8, uint8 cases
+ // before n grows too big.
+ n := 1
+ for i, f := range numbers {
+ for _, g := range numbers[i:] {
+ fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", f, n, g, n)
+ n++
+ if f != g {
+ fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", g, n, f, n)
+ n++
+ }
+ }
+ }
+ }
+ */
+ {V(int8(1)), V(int8(1))},
+ {V(int8(2)), V(uint8(2))},
+ {V(uint8(3)), V(int8(3))},
+ {V(int8(4)), V(int16(4))},
+ {V(int16(5)), V(int8(5))},
+ {V(int8(6)), V(uint16(6))},
+ {V(uint16(7)), V(int8(7))},
+ {V(int8(8)), V(int32(8))},
+ {V(int32(9)), V(int8(9))},
+ {V(int8(10)), V(uint32(10))},
+ {V(uint32(11)), V(int8(11))},
+ {V(int8(12)), V(int64(12))},
+ {V(int64(13)), V(int8(13))},
+ {V(int8(14)), V(uint64(14))},
+ {V(uint64(15)), V(int8(15))},
+ {V(int8(16)), V(int(16))},
+ {V(int(17)), V(int8(17))},
+ {V(int8(18)), V(uint(18))},
+ {V(uint(19)), V(int8(19))},
+ {V(int8(20)), V(uintptr(20))},
+ {V(uintptr(21)), V(int8(21))},
+ {V(int8(22)), V(float32(22))},
+ {V(float32(23)), V(int8(23))},
+ {V(int8(24)), V(float64(24))},
+ {V(float64(25)), V(int8(25))},
+ {V(uint8(26)), V(uint8(26))},
+ {V(uint8(27)), V(int16(27))},
+ {V(int16(28)), V(uint8(28))},
+ {V(uint8(29)), V(uint16(29))},
+ {V(uint16(30)), V(uint8(30))},
+ {V(uint8(31)), V(int32(31))},
+ {V(int32(32)), V(uint8(32))},
+ {V(uint8(33)), V(uint32(33))},
+ {V(uint32(34)), V(uint8(34))},
+ {V(uint8(35)), V(int64(35))},
+ {V(int64(36)), V(uint8(36))},
+ {V(uint8(37)), V(uint64(37))},
+ {V(uint64(38)), V(uint8(38))},
+ {V(uint8(39)), V(int(39))},
+ {V(int(40)), V(uint8(40))},
+ {V(uint8(41)), V(uint(41))},
+ {V(uint(42)), V(uint8(42))},
+ {V(uint8(43)), V(uintptr(43))},
+ {V(uintptr(44)), V(uint8(44))},
+ {V(uint8(45)), V(float32(45))},
+ {V(float32(46)), V(uint8(46))},
+ {V(uint8(47)), V(float64(47))},
+ {V(float64(48)), V(uint8(48))},
+ {V(int16(49)), V(int16(49))},
+ {V(int16(50)), V(uint16(50))},
+ {V(uint16(51)), V(int16(51))},
+ {V(int16(52)), V(int32(52))},
+ {V(int32(53)), V(int16(53))},
+ {V(int16(54)), V(uint32(54))},
+ {V(uint32(55)), V(int16(55))},
+ {V(int16(56)), V(int64(56))},
+ {V(int64(57)), V(int16(57))},
+ {V(int16(58)), V(uint64(58))},
+ {V(uint64(59)), V(int16(59))},
+ {V(int16(60)), V(int(60))},
+ {V(int(61)), V(int16(61))},
+ {V(int16(62)), V(uint(62))},
+ {V(uint(63)), V(int16(63))},
+ {V(int16(64)), V(uintptr(64))},
+ {V(uintptr(65)), V(int16(65))},
+ {V(int16(66)), V(float32(66))},
+ {V(float32(67)), V(int16(67))},
+ {V(int16(68)), V(float64(68))},
+ {V(float64(69)), V(int16(69))},
+ {V(uint16(70)), V(uint16(70))},
+ {V(uint16(71)), V(int32(71))},
+ {V(int32(72)), V(uint16(72))},
+ {V(uint16(73)), V(uint32(73))},
+ {V(uint32(74)), V(uint16(74))},
+ {V(uint16(75)), V(int64(75))},
+ {V(int64(76)), V(uint16(76))},
+ {V(uint16(77)), V(uint64(77))},
+ {V(uint64(78)), V(uint16(78))},
+ {V(uint16(79)), V(int(79))},
+ {V(int(80)), V(uint16(80))},
+ {V(uint16(81)), V(uint(81))},
+ {V(uint(82)), V(uint16(82))},
+ {V(uint16(83)), V(uintptr(83))},
+ {V(uintptr(84)), V(uint16(84))},
+ {V(uint16(85)), V(float32(85))},
+ {V(float32(86)), V(uint16(86))},
+ {V(uint16(87)), V(float64(87))},
+ {V(float64(88)), V(uint16(88))},
+ {V(int32(89)), V(int32(89))},
+ {V(int32(90)), V(uint32(90))},
+ {V(uint32(91)), V(int32(91))},
+ {V(int32(92)), V(int64(92))},
+ {V(int64(93)), V(int32(93))},
+ {V(int32(94)), V(uint64(94))},
+ {V(uint64(95)), V(int32(95))},
+ {V(int32(96)), V(int(96))},
+ {V(int(97)), V(int32(97))},
+ {V(int32(98)), V(uint(98))},
+ {V(uint(99)), V(int32(99))},
+ {V(int32(100)), V(uintptr(100))},
+ {V(uintptr(101)), V(int32(101))},
+ {V(int32(102)), V(float32(102))},
+ {V(float32(103)), V(int32(103))},
+ {V(int32(104)), V(float64(104))},
+ {V(float64(105)), V(int32(105))},
+ {V(uint32(106)), V(uint32(106))},
+ {V(uint32(107)), V(int64(107))},
+ {V(int64(108)), V(uint32(108))},
+ {V(uint32(109)), V(uint64(109))},
+ {V(uint64(110)), V(uint32(110))},
+ {V(uint32(111)), V(int(111))},
+ {V(int(112)), V(uint32(112))},
+ {V(uint32(113)), V(uint(113))},
+ {V(uint(114)), V(uint32(114))},
+ {V(uint32(115)), V(uintptr(115))},
+ {V(uintptr(116)), V(uint32(116))},
+ {V(uint32(117)), V(float32(117))},
+ {V(float32(118)), V(uint32(118))},
+ {V(uint32(119)), V(float64(119))},
+ {V(float64(120)), V(uint32(120))},
+ {V(int64(121)), V(int64(121))},
+ {V(int64(122)), V(uint64(122))},
+ {V(uint64(123)), V(int64(123))},
+ {V(int64(124)), V(int(124))},
+ {V(int(125)), V(int64(125))},
+ {V(int64(126)), V(uint(126))},
+ {V(uint(127)), V(int64(127))},
+ {V(int64(128)), V(uintptr(128))},
+ {V(uintptr(129)), V(int64(129))},
+ {V(int64(130)), V(float32(130))},
+ {V(float32(131)), V(int64(131))},
+ {V(int64(132)), V(float64(132))},
+ {V(float64(133)), V(int64(133))},
+ {V(uint64(134)), V(uint64(134))},
+ {V(uint64(135)), V(int(135))},
+ {V(int(136)), V(uint64(136))},
+ {V(uint64(137)), V(uint(137))},
+ {V(uint(138)), V(uint64(138))},
+ {V(uint64(139)), V(uintptr(139))},
+ {V(uintptr(140)), V(uint64(140))},
+ {V(uint64(141)), V(float32(141))},
+ {V(float32(142)), V(uint64(142))},
+ {V(uint64(143)), V(float64(143))},
+ {V(float64(144)), V(uint64(144))},
+ {V(int(145)), V(int(145))},
+ {V(int(146)), V(uint(146))},
+ {V(uint(147)), V(int(147))},
+ {V(int(148)), V(uintptr(148))},
+ {V(uintptr(149)), V(int(149))},
+ {V(int(150)), V(float32(150))},
+ {V(float32(151)), V(int(151))},
+ {V(int(152)), V(float64(152))},
+ {V(float64(153)), V(int(153))},
+ {V(uint(154)), V(uint(154))},
+ {V(uint(155)), V(uintptr(155))},
+ {V(uintptr(156)), V(uint(156))},
+ {V(uint(157)), V(float32(157))},
+ {V(float32(158)), V(uint(158))},
+ {V(uint(159)), V(float64(159))},
+ {V(float64(160)), V(uint(160))},
+ {V(uintptr(161)), V(uintptr(161))},
+ {V(uintptr(162)), V(float32(162))},
+ {V(float32(163)), V(uintptr(163))},
+ {V(uintptr(164)), V(float64(164))},
+ {V(float64(165)), V(uintptr(165))},
+ {V(float32(166)), V(float32(166))},
+ {V(float32(167)), V(float64(167))},
+ {V(float64(168)), V(float32(168))},
+ {V(float64(169)), V(float64(169))},
+
+ // truncation
+ {V(float64(1.5)), V(int(1))},
+
+ // complex
+ {V(complex64(1i)), V(complex64(1i))},
+ {V(complex64(2i)), V(complex128(2i))},
+ {V(complex128(3i)), V(complex64(3i))},
+ {V(complex128(4i)), V(complex128(4i))},
+
+ // string
+ {V(string("hello")), V(string("hello"))},
+ {V(string("bytes1")), V([]byte("bytes1"))},
+ {V([]byte("bytes2")), V(string("bytes2"))},
+ {V([]byte("bytes3")), V([]byte("bytes3"))},
+ {V(string("runes♝")), V([]rune("runes♝"))},
+ {V([]rune("runes♕")), V(string("runes♕"))},
+ {V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
+ {V(int('a')), V(string("a"))},
+ {V(int8('a')), V(string("a"))},
+ {V(int16('a')), V(string("a"))},
+ {V(int32('a')), V(string("a"))},
+ {V(int64('a')), V(string("a"))},
+ {V(uint('a')), V(string("a"))},
+ {V(uint8('a')), V(string("a"))},
+ {V(uint16('a')), V(string("a"))},
+ {V(uint32('a')), V(string("a"))},
+ {V(uint64('a')), V(string("a"))},
+ {V(uintptr('a')), V(string("a"))},
+ {V(int(-1)), V(string("\uFFFD"))},
+ {V(int8(-2)), V(string("\uFFFD"))},
+ {V(int16(-3)), V(string("\uFFFD"))},
+ {V(int32(-4)), V(string("\uFFFD"))},
+ {V(int64(-5)), V(string("\uFFFD"))},
+ {V(uint(0x110001)), V(string("\uFFFD"))},
+ {V(uint32(0x110002)), V(string("\uFFFD"))},
+ {V(uint64(0x110003)), V(string("\uFFFD"))},
+ {V(uintptr(0x110004)), V(string("\uFFFD"))},
+
+ // named string
+ {V(MyString("hello")), V(string("hello"))},
+ {V(string("hello")), V(MyString("hello"))},
+ {V(string("hello")), V(string("hello"))},
+ {V(MyString("hello")), V(MyString("hello"))},
+ {V(MyString("bytes1")), V([]byte("bytes1"))},
+ {V([]byte("bytes2")), V(MyString("bytes2"))},
+ {V([]byte("bytes3")), V([]byte("bytes3"))},
+ {V(MyString("runes♝")), V([]rune("runes♝"))},
+ {V([]rune("runes♕")), V(MyString("runes♕"))},
+ {V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
+ {V([]rune("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
+ {V(MyRunes("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
+ {V(int('a')), V(MyString("a"))},
+ {V(int8('a')), V(MyString("a"))},
+ {V(int16('a')), V(MyString("a"))},
+ {V(int32('a')), V(MyString("a"))},
+ {V(int64('a')), V(MyString("a"))},
+ {V(uint('a')), V(MyString("a"))},
+ {V(uint8('a')), V(MyString("a"))},
+ {V(uint16('a')), V(MyString("a"))},
+ {V(uint32('a')), V(MyString("a"))},
+ {V(uint64('a')), V(MyString("a"))},
+ {V(uintptr('a')), V(MyString("a"))},
+ {V(int(-1)), V(MyString("\uFFFD"))},
+ {V(int8(-2)), V(MyString("\uFFFD"))},
+ {V(int16(-3)), V(MyString("\uFFFD"))},
+ {V(int32(-4)), V(MyString("\uFFFD"))},
+ {V(int64(-5)), V(MyString("\uFFFD"))},
+ {V(uint(0x110001)), V(MyString("\uFFFD"))},
+ {V(uint32(0x110002)), V(MyString("\uFFFD"))},
+ {V(uint64(0x110003)), V(MyString("\uFFFD"))},
+ {V(uintptr(0x110004)), V(MyString("\uFFFD"))},
+
+ // named []byte
+ {V(string("bytes1")), V(MyBytes("bytes1"))},
+ {V(MyBytes("bytes2")), V(string("bytes2"))},
+ {V(MyBytes("bytes3")), V(MyBytes("bytes3"))},
+ {V(MyString("bytes1")), V(MyBytes("bytes1"))},
+ {V(MyBytes("bytes2")), V(MyString("bytes2"))},
+
+ // named []rune
+ {V(string("runes♝")), V(MyRunes("runes♝"))},
+ {V(MyRunes("runes♕")), V(string("runes♕"))},
+ {V(MyRunes("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
+ {V(MyString("runes♝")), V(MyRunes("runes♝"))},
+ {V(MyRunes("runes♕")), V(MyString("runes♕"))},
+
+ // named types and equal underlying types
+ {V(new(int)), V(new(integer))},
+ {V(new(integer)), V(new(int))},
+ {V(Empty{}), V(struct{}{})},
+ {V(new(Empty)), V(new(struct{}))},
+ {V(struct{}{}), V(Empty{})},
+ {V(new(struct{})), V(new(Empty))},
+ {V(Empty{}), V(Empty{})},
+ {V(MyBytes{}), V([]byte{})},
+ {V([]byte{}), V(MyBytes{})},
+ {V((func())(nil)), V(MyFunc(nil))},
+ {V((MyFunc)(nil)), V((func())(nil))},
+
+ // can convert *byte and *MyByte
+ {V((*byte)(nil)), V((*MyByte)(nil))},
+ {V((*MyByte)(nil)), V((*byte)(nil))},
+
+ // cannot convert mismatched array sizes
+ {V([2]byte{}), V([2]byte{})},
+ {V([3]byte{}), V([3]byte{})},
+
+ // cannot convert other instances
+ {V((**byte)(nil)), V((**byte)(nil))},
+ {V((**MyByte)(nil)), V((**MyByte)(nil))},
+ {V((chan byte)(nil)), V((chan byte)(nil))},
+ {V((chan MyByte)(nil)), V((chan MyByte)(nil))},
+ {V(([]byte)(nil)), V(([]byte)(nil))},
+ {V(([]MyByte)(nil)), V(([]MyByte)(nil))},
+ {V((map[int]byte)(nil)), V((map[int]byte)(nil))},
+ {V((map[int]MyByte)(nil)), V((map[int]MyByte)(nil))},
+ {V((map[byte]int)(nil)), V((map[byte]int)(nil))},
+ {V((map[MyByte]int)(nil)), V((map[MyByte]int)(nil))},
+ {V([2]byte{}), V([2]byte{})},
+ {V([2]MyByte{}), V([2]MyByte{})},
+
+ // other
+ {V((***int)(nil)), V((***int)(nil))},
+ {V((***byte)(nil)), V((***byte)(nil))},
+ {V((***int32)(nil)), V((***int32)(nil))},
+ {V((***int64)(nil)), V((***int64)(nil))},
+ {V((chan int)(nil)), V((<-chan int)(nil))},
+ {V((chan int)(nil)), V((chan<- int)(nil))},
+ {V((chan string)(nil)), V((<-chan string)(nil))},
+ {V((chan string)(nil)), V((chan<- string)(nil))},
+ {V((chan byte)(nil)), V((chan byte)(nil))},
+ {V((chan MyByte)(nil)), V((chan MyByte)(nil))},
+ {V((map[int]bool)(nil)), V((map[int]bool)(nil))},
+ {V((map[int]byte)(nil)), V((map[int]byte)(nil))},
+ {V((map[uint]bool)(nil)), V((map[uint]bool)(nil))},
+ {V([]uint(nil)), V([]uint(nil))},
+ {V([]int(nil)), V([]int(nil))},
+ {V(new(interface{})), V(new(interface{}))},
+ {V(new(io.Reader)), V(new(io.Reader))},
+ {V(new(io.Writer)), V(new(io.Writer))},
+
+ // interfaces
+ {V(int(1)), EmptyInterfaceV(int(1))},
+ {V(string("hello")), EmptyInterfaceV(string("hello"))},
+ {V(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))},
+ {ReadWriterV(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))},
+ {V(new(bytes.Buffer)), ReadWriterV(new(bytes.Buffer))},
+}
+
+func TestConvert(t *testing.T) {
+ canConvert := map[[2]Type]bool{}
+ all := map[Type]bool{}
+
+ for _, tt := range convertTests {
+ t1 := tt.in.Type()
+ if !t1.ConvertibleTo(t1) {
+ t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t1)
+ continue
+ }
+
+ t2 := tt.out.Type()
+ if !t1.ConvertibleTo(t2) {
+ t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t2)
+ continue
+ }
+
+ all[t1] = true
+ all[t2] = true
+ canConvert[[2]Type{t1, t2}] = true
+
+ v1 := tt.in
+ vout1 := v1.Convert(t1)
+ out1 := vout1.Interface()
+ if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
+ t.Errorf("ValueOf(%T(%v)).Convert(%s) = %T(%v), want %T(%v)", tt.in.Interface(), tt.in.Interface(), t1, out1, out1, tt.in.Interface(), tt.in.Interface())
+ }
+
+ vout := v1.Convert(t2)
+ out := vout.Interface()
+ if vout.Type() != tt.out.Type() || !DeepEqual(out, tt.out.Interface()) {
+ t.Errorf("ValueOf(%T(%v)).Convert(%s) = %T(%v), want %T(%v)", tt.in.Interface(), tt.in.Interface(), t2, out, out, tt.out.Interface(), tt.out.Interface())
+ }
+
+ if IsRO(v1) {
+ t.Errorf("table entry %v is RO, should not be", v1)
+ }
+ if IsRO(vout1) {
+ t.Errorf("self-conversion output %v is RO, should not be", vout1)
+ }
+ if IsRO(vout) {
+ t.Errorf("conversion output %v is RO, should not be", vout)
+ }
+ if !IsRO(MakeRO(v1).Convert(t1)) {
+ t.Errorf("RO self-conversion output %v is not RO, should be", v1)
+ }
+ if !IsRO(MakeRO(v1).Convert(t2)) {
+ t.Errorf("RO conversion output %v is not RO, should be", v1)
+ }
+ }
+
+ // Assume that of all the types we saw during the tests,
+ // if there wasn't an explicit entry for a conversion between
+ // a pair of types, then it's not to be allowed. This checks for
+ // things like 'int64' converting to '*int'.
+ for t1 := range all {
+ for t2 := range all {
+ expectOK := t1 == t2 || canConvert[[2]Type{t1, t2}] || t2.Kind() == Interface && t2.NumMethod() == 0
+ if ok := t1.ConvertibleTo(t2); ok != expectOK {
+ t.Errorf("(%s).ConvertibleTo(%s) = %v, want %v", t1, t2, ok, expectOK)
+ }
+ }
+ }
+}
+
+type B1 struct {
+ X int
+ Y int
+ Z int
+}
+
+func BenchmarkFieldByName1(b *testing.B) {
+ t := TypeOf(B1{})
+ for i := 0; i < b.N; i++ {
+ t.FieldByName("Z")
+ }
+}
+
+func BenchmarkFieldByName2(b *testing.B) {
+ t := TypeOf(S3{})
+ for i := 0; i < b.N; i++ {
+ t.FieldByName("B")
+ }
+}
+
+type R0 struct {
+ *R1
+ *R2
+ *R3
+ *R4
+}
+
+type R1 struct {
+ *R5
+ *R6
+ *R7
+ *R8
+}
+
+type R2 R1
+type R3 R1
+type R4 R1
+
+type R5 struct {
+ *R9
+ *R10
+ *R11
+ *R12
+}
+
+type R6 R5
+type R7 R5
+type R8 R5
+
+type R9 struct {
+ *R13
+ *R14
+ *R15
+ *R16
+}
+
+type R10 R9
+type R11 R9
+type R12 R9
+
+type R13 struct {
+ *R17
+ *R18
+ *R19
+ *R20
+}
+
+type R14 R13
+type R15 R13
+type R16 R13
+
+type R17 struct {
+ *R21
+ *R22
+ *R23
+ *R24
+}
+
+type R18 R17
+type R19 R17
+type R20 R17
+
+type R21 struct {
+ X int
+}
+
+type R22 R21
+type R23 R21
+type R24 R21
+
+func TestEmbed(t *testing.T) {
+ typ := TypeOf(R0{})
+ f, ok := typ.FieldByName("X")
+ if ok {
+ t.Fatalf(`FieldByName("X") should fail, returned %v`, f.Index)
+ }
+}
+
+func BenchmarkFieldByName3(b *testing.B) {
+ t := TypeOf(R0{})
+ for i := 0; i < b.N; i++ {
+ t.FieldByName("X")
+ }
+}
+
+// An exhaustive is a mechanism for writing exhaustive or stochastic tests.
+// The basic usage is:
+//
+// for x.Next() {
+// ... code using x.Maybe() or x.Choice(n) to create test cases ...
+// }
+//
+// Each iteration of the loop returns a different set of results, until all
+// possible result sets have been explored. It is okay for different code paths
+// to make different method call sequences on x, but there must be no
+// other source of non-determinism in the call sequences.
+//
+// When faced with a new decision, x chooses randomly. Future explorations
+// of that path will choose successive values for the result. Thus, stopping
+// the loop after a fixed number of iterations gives somewhat stochastic
+// testing.
+//
+// Example:
+//
+// for x.Next() {
+// v := make([]bool, x.Choose(4))
+// for i := range v {
+// v[i] = x.Maybe()
+// }
+// fmt.Println(v)
+// }
+//
+// prints (in some order):
+//
+// []
+// [false]
+// [true]
+// [false false]
+// [false true]
+// ...
+// [true true]
+// [false false false]
+// ...
+// [true true true]
+// [false false false false]
+// ...
+// [true true true true]
+//
+type exhaustive struct {
+ r *rand.Rand
+ pos int
+ last []choice
+}
+
+type choice struct {
+ off int
+ n int
+ max int
+}
+
+func (x *exhaustive) Next() bool {
+ if x.r == nil {
+ x.r = rand.New(rand.NewSource(time.Now().UnixNano()))
+ }
+ x.pos = 0
+ if x.last == nil {
+ x.last = []choice{}
+ return true
+ }
+ for i := len(x.last) - 1; i >= 0; i-- {
+ c := &x.last[i]
+ if c.n+1 < c.max {
+ c.n++
+ x.last = x.last[:i+1]
+ return true
+ }
+ }
+ return false
+}
+
+func (x *exhaustive) Choose(max int) int {
+ if x.pos >= len(x.last) {
+ x.last = append(x.last, choice{x.r.Intn(max), 0, max})
+ }
+ c := &x.last[x.pos]
+ x.pos++
+ if c.max != max {
+ panic("inconsistent use of exhaustive tester")
+ }
+ return (c.n + c.off) % max
+}
+
+func (x *exhaustive) Maybe() bool {
+ return x.Choose(2) == 1
+}
diff --git a/libgo/go/reflect/deepequal.go b/libgo/go/reflect/deepequal.go
index c12e90f36cc..cd364dd9fd9 100644
--- a/libgo/go/reflect/deepequal.go
+++ b/libgo/go/reflect/deepequal.go
@@ -125,6 +125,7 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
// DeepEqual tests for deep equality. It uses normal == equality where possible
// but will scan members of arrays, slices, maps, and fields of structs. It correctly
// handles recursive types. Functions are equal only if they are both nil.
+// An empty slice is not equal to a nil slice.
func DeepEqual(a1, a2 interface{}) bool {
if a1 == nil || a2 == nil {
return a1 == a2
diff --git a/libgo/go/reflect/example_test.go b/libgo/go/reflect/example_test.go
new file mode 100644
index 00000000000..62455c00ad9
--- /dev/null
+++ b/libgo/go/reflect/example_test.go
@@ -0,0 +1,52 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package reflect_test
+
+import (
+ "fmt"
+ "reflect"
+)
+
+func ExampleMakeFunc() {
+ // swap is the implementation passed to MakeFunc.
+ // It must work in terms of reflect.Values so that it is possible
+ // to write code without knowing beforehand what the types
+ // will be.
+ swap := func(in []reflect.Value) []reflect.Value {
+ return []reflect.Value{in[1], in[0]}
+ }
+
+ // makeSwap expects fptr to be a pointer to a nil function.
+ // It sets that pointer to a new function created with MakeFunc.
+ // When the function is invoked, reflect turns the arguments
+ // into Values, calls swap, and then turns swap's result slice
+ // into the values returned by the new function.
+ makeSwap := func(fptr interface{}) {
+ // fptr is a pointer to a function.
+ // Obtain the function value itself (likely nil) as a reflect.Value
+ // so that we can query its type and then set the value.
+ fn := reflect.ValueOf(fptr).Elem()
+
+ // Make a function of the right type.
+ v := reflect.MakeFunc(fn.Type(), swap)
+
+ // Assign it to the value fn represents.
+ fn.Set(v)
+ }
+
+ // Make and call a swap function for ints.
+ var intSwap func(int, int) (int, int)
+ makeSwap(&intSwap)
+ fmt.Println(intSwap(0, 1))
+
+ // Make and call a swap function for float64s.
+ var floatSwap func(float64, float64) (float64, float64)
+ makeSwap(&floatSwap)
+ fmt.Println(floatSwap(2.72, 3.14))
+
+ // Output:
+ // 1 0
+ // 3.14 2.72
+}
diff --git a/libgo/go/reflect/export_test.go b/libgo/go/reflect/export_test.go
new file mode 100644
index 00000000000..6e0d8a3e0bc
--- /dev/null
+++ b/libgo/go/reflect/export_test.go
@@ -0,0 +1,16 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package reflect
+
+// MakeRO returns a copy of v with the read-only flag set.
+func MakeRO(v Value) Value {
+ v.flag |= flagRO
+ return v
+}
+
+// IsRO reports whether v's read-only flag is set.
+func IsRO(v Value) bool {
+ return v.flag&flagRO != 0
+}
diff --git a/libgo/go/reflect/makefunc.go b/libgo/go/reflect/makefunc.go
new file mode 100644
index 00000000000..d30bf63aae3
--- /dev/null
+++ b/libgo/go/reflect/makefunc.go
@@ -0,0 +1,81 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// MakeFunc implementation.
+
+package reflect
+
+import (
+ "unsafe"
+)
+
+// MakeFunc returns a new function of the given Type
+// that wraps the function fn. When called, that new function
+// does the following:
+//
+// - converts its arguments to a list of Values args.
+// - runs results := fn(args).
+// - returns the results as a slice of Values, one per formal result.
+//
+// The implementation fn can assume that the argument Value slice
+// has the number and type of arguments given by typ.
+// If typ describes a variadic function, the final Value is itself
+// a slice representing the variadic arguments, as in the
+// body of a variadic function. The result Value slice returned by fn
+// must have the number and type of results given by typ.
+//
+// The Value.Call method allows the caller to invoke a typed function
+// in terms of Values; in contrast, MakeFunc allows the caller to implement
+// a typed function in terms of Values.
+//
+// The Examples section of the documentation includes an illustration
+// of how to use MakeFunc to build a swap function for different types.
+//
+func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
+ if typ.Kind() != Func {
+ panic("reflect: call of MakeFunc with non-Func type")
+ }
+
+ ft := (*funcType)(unsafe.Pointer(typ.common()))
+
+ // We will build a function that uses the C stdarg routines to
+ // pull out the arguments. Since the stdarg routines require
+ // the first parameter to be available, we need to switch on
+ // the possible first parameter types. Note that this assumes
+ // that the calling ABI for a stdarg function is the same as
+ // that for a non-stdarg function. The C standard does not
+ // require this, but it is true for most implementations in
+ // practice.
+
+ // Handling result types is a different problem. There are a
+ // few cases to handle:
+ // * No results.
+ // * One result.
+ // * More than one result, which is returned in a struct.
+ // + Struct returned in registers.
+ // + Struct returned in memory.
+
+ var result Kind
+ var resultSize uintptr
+ switch len(ft.out) {
+ case 0:
+ result = Invalid
+ case 1:
+ result = Kind(ft.out[0].kind)
+ resultSize = ft.out[0].size
+ default:
+ result = Struct
+ }
+
+ panic("reflect MakeFunc not implemented")
+
+ // stub := func(i int) {
+ // var args __gnuc_va_list
+ // __builtin_va_start(args, i)
+ // v := makeInt(0, uint64(i), ft.in[0])
+ // return callReflect(ft, fn, v, args)
+ // }
+
+ // return Value{t, unsafe.Pointer(&impl.code[0]), flag(Func) << flagKindShift}
+}
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index 93021bae263..b5f27d0b446 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -95,6 +95,9 @@ type Type interface {
// AssignableTo returns true if a value of the type is assignable to type u.
AssignableTo(u Type) bool
+ // ConvertibleTo returns true if a value of the type is convertible to type u.
+ ConvertibleTo(u Type) bool
+
// Methods applicable only to some types, depending on Kind.
// The methods allowed for each kind are:
//
@@ -189,6 +192,12 @@ type Type interface {
uncommon() *uncommonType
}
+/*
+ * These data structures are known to the compiler (../../cmd/gc/reflect.c).
+ * A few are known to ../runtime/type.go to convey to debuggers.
+ * They are also known to ../runtime/type.h.
+ */
+
// A Kind represents the specific kind of type that a Type represents.
// The zero Kind is not a valid kind.
type Kind uint
@@ -223,11 +232,6 @@ const (
UnsafePointer
)
-/*
- * These data structures are known to the compiler (../../cmd/gc/reflect.c).
- * A few are known to ../runtime/type.go to convey to debuggers.
- */
-
type runtimeType commonType
// commonType is the common implementation of most values.
@@ -854,92 +858,140 @@ func (t *structType) FieldByIndex(index []int) (f StructField) {
return
}
-const inf = 1 << 30 // infinity - no struct has that many nesting levels
-
-func (t *structType) fieldByNameFunc(match func(string) bool, mark map[*structType]bool, depth int) (ff StructField, fd int) {
- fd = inf // field depth
+// A fieldScan represents an item on the fieldByNameFunc scan work list.
+type fieldScan struct {
+ typ *structType
+ index []int
+}
- if mark[t] {
- // Struct already seen.
- return
- }
- mark[t] = true
-
- var fi int // field index
- n := 0 // number of matching fields at depth fd
-L:
- for i := range t.fields {
- f := t.Field(i)
- d := inf
- switch {
- case match(f.Name):
- // Matching top-level field.
- d = depth
- case f.Anonymous:
- ft := f.Type
- if ft.Kind() == Ptr {
- ft = ft.Elem()
+// FieldByNameFunc returns the struct field with a name that satisfies the
+// match function and a boolean to indicate if the field was found.
+func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
+ // This uses the same condition that the Go language does: there must be a unique instance
+ // of the match at a given depth level. If there are multiple instances of a match at the
+ // same depth, they annihilate each other and inhibit any possible match at a lower level.
+ // The algorithm is breadth first search, one depth level at a time.
+
+ // The current and next slices are work queues:
+ // current lists the fields to visit on this depth level,
+ // and next lists the fields on the next lower level.
+ current := []fieldScan{}
+ next := []fieldScan{{typ: t}}
+
+ // nextCount records the number of times an embedded type has been
+ // encountered and considered for queueing in the 'next' slice.
+ // We only queue the first one, but we increment the count on each.
+ // If a struct type T can be reached more than once at a given depth level,
+ // then it annihilates itself and need not be considered at all when we
+ // process that next depth level.
+ var nextCount map[*structType]int
+
+ // visited records the structs that have been considered already.
+ // Embedded pointer fields can create cycles in the graph of
+ // reachable embedded types; visited avoids following those cycles.
+ // It also avoids duplicated effort: if we didn't find the field in an
+ // embedded type T at level 2, we won't find it in one at level 4 either.
+ visited := map[*structType]bool{}
+
+ for len(next) > 0 {
+ current, next = next, current[:0]
+ count := nextCount
+ nextCount = nil
+
+ // Process all the fields at this depth, now listed in 'current'.
+ // The loop queues embedded fields found in 'next', for processing during the next
+ // iteration. The multiplicity of the 'current' field counts is recorded
+ // in 'count'; the multiplicity of the 'next' field counts is recorded in 'nextCount'.
+ for _, scan := range current {
+ t := scan.typ
+ if visited[t] {
+ // We've looked through this type before, at a higher level.
+ // That higher level would shadow the lower level we're now at,
+ // so this one can't be useful to us. Ignore it.
+ continue
}
- switch {
- case match(ft.Name()):
- // Matching anonymous top-level field.
- d = depth
- case fd > depth:
- // No top-level field yet; look inside nested structs.
- if ft.Kind() == Struct {
- st := (*structType)(unsafe.Pointer(ft.(*commonType)))
- f, d = st.fieldByNameFunc(match, mark, depth+1)
+ visited[t] = true
+ for i := range t.fields {
+ f := &t.fields[i]
+ // Find name and type for field f.
+ var fname string
+ var ntyp *commonType
+ if f.name != nil {
+ fname = *f.name
+ } else {
+ // Anonymous field of type T or *T.
+ // Name taken from type.
+ ntyp = toCommonType(f.typ)
+ if ntyp.Kind() == Ptr {
+ ntyp = ntyp.Elem().common()
+ }
+ fname = ntyp.Name()
}
- }
- }
- switch {
- case d < fd:
- // Found field at shallower depth.
- ff, fi, fd = f, i, d
- n = 1
- case d == fd:
- // More than one matching field at the same depth (or d, fd == inf).
- // Same as no field found at this depth.
- n++
- if d == depth {
- // Impossible to find a field at lower depth.
- break L
- }
- }
- }
+ // Does it match?
+ if match(fname) {
+ // Potential match
+ if count[t] > 1 || ok {
+ // Name appeared multiple times at this level: annihilate.
+ return StructField{}, false
+ }
+ result = t.Field(i)
+ result.Index = nil
+ result.Index = append(result.Index, scan.index...)
+ result.Index = append(result.Index, i)
+ ok = true
+ continue
+ }
- if n == 1 {
- // Found matching field.
- if depth >= len(ff.Index) {
- ff.Index = make([]int, depth+1)
+ // Queue embedded struct fields for processing with next level,
+ // but only if we haven't seen a match yet at this level and only
+ // if the embedded types haven't alredy been queued.
+ if ok || ntyp == nil || ntyp.Kind() != Struct {
+ continue
+ }
+ styp := (*structType)(unsafe.Pointer(ntyp))
+ if nextCount[styp] > 0 {
+ nextCount[styp]++
+ continue
+ }
+ if nextCount == nil {
+ nextCount = map[*structType]int{}
+ }
+ nextCount[styp] = 1
+ var index []int
+ index = append(index, scan.index...)
+ index = append(index, i)
+ next = append(next, fieldScan{styp, index})
+ }
}
- if len(ff.Index) > 1 {
- ff.Index[depth] = fi
+ if ok {
+ break
}
- } else {
- // None or more than one matching field found.
- fd = inf
}
-
- delete(mark, t)
return
}
// FieldByName returns the struct field with the given name
// and a boolean to indicate if the field was found.
func (t *structType) FieldByName(name string) (f StructField, present bool) {
- return t.FieldByNameFunc(func(s string) bool { return s == name })
-}
-
-// FieldByNameFunc returns the struct field with a name that satisfies the
-// match function and a boolean to indicate if the field was found.
-func (t *structType) FieldByNameFunc(match func(string) bool) (f StructField, present bool) {
- if ff, fd := t.fieldByNameFunc(match, make(map[*structType]bool), 0); fd < inf {
- ff.Index = ff.Index[0 : fd+1]
- f, present = ff, true
+ // Quick check for top-level name, or struct without anonymous fields.
+ hasAnon := false
+ if name != "" {
+ for i := range t.fields {
+ tf := &t.fields[i]
+ if tf.name == nil {
+ hasAnon = true
+ continue
+ }
+ if *tf.name == name {
+ return t.Field(i), true
+ }
+ }
}
- return
+ if !hasAnon {
+ return
+ }
+ return t.FieldByNameFunc(func(s string) bool { return s == name })
}
// Convert runtime type to reflect type.
@@ -1073,7 +1125,8 @@ func (ct *commonType) ptrTo() *commonType {
p.ptrToThis = nil
p.elem = (*runtimeType)(unsafe.Pointer(ct))
- p = canonicalize(p).(*ptrType)
+ q := canonicalize(&p.commonType)
+ p = (*ptrType)(unsafe.Pointer(q.(*commonType)))
ptrMap.m[ct] = p
ptrMap.Unlock()
@@ -1098,6 +1151,14 @@ func (t *commonType) AssignableTo(u Type) bool {
return directlyAssignable(uu, t) || implements(uu, t)
}
+func (t *commonType) ConvertibleTo(u Type) bool {
+ if u == nil {
+ panic("reflect: nil type passed to Type.ConvertibleTo")
+ }
+ uu := u.(*commonType)
+ return convertOp(uu, t) != nil
+}
+
// implements returns true if the type V implements the interface type T.
func implements(T, V *commonType) bool {
if T.Kind() != Interface {
@@ -1169,10 +1230,28 @@ func directlyAssignable(T, V *commonType) bool {
return false
}
- // x's type T and V have identical underlying types.
- // Since at least one is unnamed, only the composite types
- // need to be considered.
- switch T.Kind() {
+ // x's type T and V must have identical underlying types.
+ return haveIdenticalUnderlyingType(T, V)
+}
+
+func haveIdenticalUnderlyingType(T, V *commonType) bool {
+ if T == V {
+ return true
+ }
+
+ kind := T.Kind()
+ if kind != V.Kind() {
+ return false
+ }
+
+ // Non-composite types of equal kind have same underlying type
+ // (the predefined instance of the type).
+ if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
+ return true
+ }
+
+ // Composite types.
+ switch kind {
case Array:
return T.Elem() == V.Elem() && T.Len() == V.Len()
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index b25e5c73d1a..6d3ddd836c2 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -298,6 +298,17 @@ func (v Value) Bytes() []byte {
return *(*[]byte)(v.val)
}
+// runes returns v's underlying value.
+// It panics if v's underlying value is not a slice of runes (int32s).
+func (v Value) runes() []rune {
+ v.mustBe(Slice)
+ if v.typ.Elem().Kind() != Int32 {
+ panic("reflect.Value.Bytes of non-rune slice")
+ }
+ // Slice is always bigger than a word; assume flagIndir.
+ return *(*[]rune)(v.val)
+}
+
// CanAddr returns true if the value's address can be obtained with Addr.
// Such values are called addressable. A value is addressable if it is
// an element of a slice, an element of an addressable array,
@@ -528,6 +539,82 @@ func isMethod(t *commonType) bool {
return params > 2
}
+// callReflect is the call implementation used by a function
+// returned by MakeFunc. In many ways it is the opposite of the
+// method Value.call above. The method above converts a call using Values
+// into a call of a function with a concrete argument frame, while
+// callReflect converts a call of a function with a concrete argument
+// frame into a call using Values.
+// It is in this file so that it can be next to the call method above.
+// The remainder of the MakeFunc implementation is in makefunc.go.
+func callReflect(ftyp *funcType, f func([]Value) []Value, frame unsafe.Pointer) {
+ // Copy argument frame into Values.
+ ptr := frame
+ off := uintptr(0)
+ in := make([]Value, 0, len(ftyp.in))
+ for _, arg := range ftyp.in {
+ typ := toCommonType(arg)
+ off += -off & uintptr(typ.align-1)
+ v := Value{typ, nil, flag(typ.Kind()) << flagKindShift}
+ if typ.size <= ptrSize {
+ // value fits in word.
+ v.val = unsafe.Pointer(loadIword(unsafe.Pointer(uintptr(ptr)+off), typ.size))
+ } else {
+ // value does not fit in word.
+ // Must make a copy, because f might keep a reference to it,
+ // and we cannot let f keep a reference to the stack frame
+ // after this function returns, not even a read-only reference.
+ v.val = unsafe_New(typ)
+ memmove(v.val, unsafe.Pointer(uintptr(ptr)+off), typ.size)
+ v.flag |= flagIndir
+ }
+ in = append(in, v)
+ off += typ.size
+ }
+
+ // Call underlying function.
+ out := f(in)
+ if len(out) != len(ftyp.out) {
+ panic("reflect: wrong return count from function created by MakeFunc")
+ }
+
+ // Copy results back into argument frame.
+ if len(ftyp.out) > 0 {
+ off += -off & (ptrSize - 1)
+ for i, arg := range ftyp.out {
+ typ := toCommonType(arg)
+ v := out[i]
+ if v.typ != typ {
+ panic("reflect: function created by MakeFunc using " + funcName(f) +
+ " returned wrong type: have " +
+ out[i].typ.String() + " for " + typ.String())
+ }
+ if v.flag&flagRO != 0 {
+ panic("reflect: function created by MakeFunc using " + funcName(f) +
+ " returned value obtained from unexported field")
+ }
+ off += -off & uintptr(typ.align-1)
+ addr := unsafe.Pointer(uintptr(ptr) + off)
+ if v.flag&flagIndir == 0 {
+ storeIword(addr, iword(v.val), typ.size)
+ } else {
+ memmove(addr, v.val, typ.size)
+ }
+ off += typ.size
+ }
+ }
+}
+
+// funcName returns the name of f, for use in error messages.
+func funcName(f func([]Value) []Value) string {
+ pc := *(*uintptr)(unsafe.Pointer(&f))
+ rf := runtime.FuncForPC(pc)
+ if rf != nil {
+ return rf.Name()
+ }
+ return "closure"
+}
+
// Cap returns v's capacity.
// It panics if v's Kind is not Array, Chan, or Slice.
func (v Value) Cap() int {
@@ -911,9 +998,9 @@ func (v Value) Len() int {
tt := (*arrayType)(unsafe.Pointer(v.typ))
return int(tt.len)
case Chan:
- return int(chanlen(*(*iword)(v.iword())))
+ return chanlen(*(*iword)(v.iword()))
case Map:
- return int(maplen(*(*iword)(v.iword())))
+ return maplen(*(*iword)(v.iword()))
case Slice:
// Slice is bigger than a word; assume flagIndir.
return (*SliceHeader)(v.val).Len
@@ -970,7 +1057,7 @@ func (v Value) MapKeys() []Value {
}
m := *(*iword)(v.iword())
- mlen := int32(0)
+ mlen := int(0)
if m != nil {
mlen = maplen(m)
}
@@ -1213,6 +1300,17 @@ func (v Value) SetBytes(x []byte) {
*(*[]byte)(v.val) = x
}
+// setRunes sets v's underlying value.
+// It panics if v's underlying value is not a slice of runes (int32s).
+func (v Value) setRunes(x []rune) {
+ v.mustBeAssignable()
+ v.mustBe(Slice)
+ if v.typ.Elem().Kind() != Int32 {
+ panic("reflect.Value.setRunes of non-rune slice")
+ }
+ *(*[]rune)(v.val) = x
+}
+
// SetComplex sets v's underlying value to x.
// It panics if v's Kind is not Complex64 or Complex128, or if CanSet() is false.
func (v Value) SetComplex(x complex128) {
@@ -1610,6 +1708,140 @@ func Copy(dst, src Value) int {
return n
}
+// A runtimeSelect is a single case passed to rselect.
+// This must match ../runtime/chan.c:/runtimeSelect
+type runtimeSelect struct {
+ dir uintptr // 0, SendDir, or RecvDir
+ typ *runtimeType // channel type
+ ch iword // interface word for channel
+ val iword // interface word for value (for SendDir)
+}
+
+// rselect runs a select. It returns the index of the chosen case,
+// and if the case was a receive, the interface word of the received
+// value and the conventional OK bool to indicate whether the receive
+// corresponds to a sent value.
+func rselect([]runtimeSelect) (chosen int, recv iword, recvOK bool)
+
+// A SelectDir describes the communication direction of a select case.
+type SelectDir int
+
+// NOTE: These values must match ../runtime/chan.c:/SelectDir.
+
+const (
+ _ SelectDir = iota
+ SelectSend // case Chan <- Send
+ SelectRecv // case <-Chan:
+ SelectDefault // default
+)
+
+// A SelectCase describes a single case in a select operation.
+// The kind of case depends on Dir, the communication direction.
+//
+// If Dir is SelectDefault, the case represents a default case.
+// Chan and Send must be zero Values.
+//
+// If Dir is SelectSend, the case represents a send operation.
+// Normally Chan's underlying value must be a channel, and Send's underlying value must be
+// assignable to the channel's element type. As a special case, if Chan is a zero Value,
+// then the case is ignored, and the field Send will also be ignored and may be either zero
+// or non-zero.
+//
+// If Dir is SelectRecv, the case represents a receive operation.
+// Normally Chan's underlying value must be a channel and Send must be a zero Value.
+// If Chan is a zero Value, then the case is ignored, but Send must still be a zero Value.
+// When a receive operation is selected, the received Value is returned by Select.
+//
+type SelectCase struct {
+ Dir SelectDir // direction of case
+ Chan Value // channel to use (for send or receive)
+ Send Value // value to send (for send)
+}
+
+// Select executes a select operation described by the list of cases.
+// Like the Go select statement, it blocks until one of the cases can
+// proceed and then executes that case. It returns the index of the chosen case
+// and, if that case was a receive operation, the value received and a
+// boolean indicating whether the value corresponds to a send on the channel
+// (as opposed to a zero value received because the channel is closed).
+func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
+ // NOTE: Do not trust that caller is not modifying cases data underfoot.
+ // The range is safe because the caller cannot modify our copy of the len
+ // and each iteration makes its own copy of the value c.
+ runcases := make([]runtimeSelect, len(cases))
+ haveDefault := false
+ for i, c := range cases {
+ rc := &runcases[i]
+ rc.dir = uintptr(c.Dir)
+ switch c.Dir {
+ default:
+ panic("reflect.Select: invalid Dir")
+
+ case SelectDefault: // default
+ if haveDefault {
+ panic("reflect.Select: multiple default cases")
+ }
+ haveDefault = true
+ if c.Chan.IsValid() {
+ panic("reflect.Select: default case has Chan value")
+ }
+ if c.Send.IsValid() {
+ panic("reflect.Select: default case has Send value")
+ }
+
+ case SelectSend:
+ ch := c.Chan
+ if !ch.IsValid() {
+ break
+ }
+ ch.mustBe(Chan)
+ ch.mustBeExported()
+ tt := (*chanType)(unsafe.Pointer(ch.typ))
+ if ChanDir(tt.dir)&SendDir == 0 {
+ panic("reflect.Select: SendDir case using recv-only channel")
+ }
+ rc.ch = *(*iword)(ch.iword())
+ rc.typ = tt.runtimeType()
+ v := c.Send
+ if !v.IsValid() {
+ panic("reflect.Select: SendDir case missing Send value")
+ }
+ v.mustBeExported()
+ v = v.assignTo("reflect.Select", toCommonType(tt.elem), nil)
+ rc.val = v.iword()
+
+ case SelectRecv:
+ if c.Send.IsValid() {
+ panic("reflect.Select: RecvDir case has Send value")
+ }
+ ch := c.Chan
+ if !ch.IsValid() {
+ break
+ }
+ ch.mustBe(Chan)
+ ch.mustBeExported()
+ tt := (*chanType)(unsafe.Pointer(ch.typ))
+ rc.typ = tt.runtimeType()
+ if ChanDir(tt.dir)&RecvDir == 0 {
+ panic("reflect.Select: RecvDir case using send-only channel")
+ }
+ rc.ch = *(*iword)(ch.iword())
+ }
+ }
+
+ chosen, word, recvOK := rselect(runcases)
+ if runcases[chosen].dir == uintptr(SelectRecv) {
+ tt := (*chanType)(unsafe.Pointer(toCommonType(runcases[chosen].typ)))
+ typ := toCommonType(tt.elem)
+ fl := flag(typ.Kind()) << flagKindShift
+ if typ.Kind() != Ptr && typ.Kind() != UnsafePointer {
+ fl |= flagIndir
+ }
+ recv = Value{typ, unsafe.Pointer(word), fl}
+ }
+ return chosen, recv, recvOK
+}
+
/*
* constructors
*/
@@ -1657,7 +1889,7 @@ func MakeChan(typ Type, buffer int) Value {
if typ.ChanDir() != BothDir {
panic("reflect.MakeChan: unidirectional channel type")
}
- ch := makechan(typ.runtimeType(), uint32(buffer))
+ ch := makechan(typ.runtimeType(), uint64(buffer))
return Value{typ.common(), unsafe.Pointer(ch), flagIndir | (flag(Chan) << flagKindShift)}
}
@@ -1774,21 +2006,317 @@ func (v Value) assignTo(context string, dst *commonType, target *interface{}) Va
panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
}
+// Convert returns the value v converted to type t.
+// If the usual Go conversion rules do not allow conversion
+// of the value v to type t, Convert panics.
+func (v Value) Convert(t Type) Value {
+ if v.flag&flagMethod != 0 {
+ panic("reflect.Value.Convert: cannot convert method values")
+ }
+ op := convertOp(t.common(), v.typ)
+ if op == nil {
+ panic("reflect.Value.Convert: value of type " + v.typ.String() + " cannot be converted to type " + t.String())
+ }
+ return op(v, t)
+}
+
+// convertOp returns the function to convert a value of type src
+// to a value of type dst. If the conversion is illegal, convertOp returns nil.
+func convertOp(dst, src *commonType) func(Value, Type) Value {
+ switch src.Kind() {
+ case Int, Int8, Int16, Int32, Int64:
+ switch dst.Kind() {
+ case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+ return cvtInt
+ case Float32, Float64:
+ return cvtIntFloat
+ case String:
+ return cvtIntString
+ }
+
+ case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+ switch dst.Kind() {
+ case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+ return cvtUint
+ case Float32, Float64:
+ return cvtUintFloat
+ case String:
+ return cvtUintString
+ }
+
+ case Float32, Float64:
+ switch dst.Kind() {
+ case Int, Int8, Int16, Int32, Int64:
+ return cvtFloatInt
+ case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+ return cvtFloatUint
+ case Float32, Float64:
+ return cvtFloat
+ }
+
+ case Complex64, Complex128:
+ switch dst.Kind() {
+ case Complex64, Complex128:
+ return cvtComplex
+ }
+
+ case String:
+ if dst.Kind() == Slice && dst.Elem().PkgPath() == "" {
+ switch dst.Elem().Kind() {
+ case Uint8:
+ return cvtStringBytes
+ case Int32:
+ return cvtStringRunes
+ }
+ }
+
+ case Slice:
+ if dst.Kind() == String && src.Elem().PkgPath() == "" {
+ switch src.Elem().Kind() {
+ case Uint8:
+ return cvtBytesString
+ case Int32:
+ return cvtRunesString
+ }
+ }
+ }
+
+ // dst and src have same underlying type.
+ if haveIdenticalUnderlyingType(dst, src) {
+ return cvtDirect
+ }
+
+ // dst and src are unnamed pointer types with same underlying base type.
+ if dst.Kind() == Ptr && dst.Name() == "" &&
+ src.Kind() == Ptr && src.Name() == "" &&
+ haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common()) {
+ return cvtDirect
+ }
+
+ if implements(dst, src) {
+ if src.Kind() == Interface {
+ return cvtI2I
+ }
+ return cvtT2I
+ }
+
+ return nil
+}
+
+// makeInt returns a Value of type t equal to bits (possibly truncated),
+// where t is a signed or unsigned int type.
+func makeInt(f flag, bits uint64, t Type) Value {
+ typ := t.common()
+ if typ.size > ptrSize {
+ // Assume ptrSize >= 4, so this must be uint64.
+ ptr := unsafe_New(t)
+ *(*uint64)(unsafe.Pointer(ptr)) = bits
+ return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift}
+ }
+ var w iword
+ switch typ.size {
+ case 1:
+ *(*uint8)(unsafe.Pointer(&w)) = uint8(bits)
+ case 2:
+ *(*uint16)(unsafe.Pointer(&w)) = uint16(bits)
+ case 4:
+ *(*uint32)(unsafe.Pointer(&w)) = uint32(bits)
+ case 8:
+ *(*uint64)(unsafe.Pointer(&w)) = uint64(bits)
+ }
+ return Value{typ, unsafe.Pointer(&w), f | flag(typ.Kind())<<flagKindShift | flagIndir}
+}
+
+// makeFloat returns a Value of type t equal to v (possibly truncated to float32),
+// where t is a float32 or float64 type.
+func makeFloat(f flag, v float64, t Type) Value {
+ typ := t.common()
+ if typ.size > ptrSize {
+ // Assume ptrSize >= 4, so this must be float64.
+ ptr := unsafe_New(t)
+ *(*float64)(unsafe.Pointer(ptr)) = v
+ return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift}
+ }
+
+ var w iword
+ switch typ.size {
+ case 4:
+ *(*float32)(unsafe.Pointer(&w)) = float32(v)
+ case 8:
+ *(*float64)(unsafe.Pointer(&w)) = v
+ }
+ return Value{typ, unsafe.Pointer(&w), f | flag(typ.Kind())<<flagKindShift | flagIndir}
+}
+
+// makeComplex returns a Value of type t equal to v (possibly truncated to complex64),
+// where t is a complex64 or complex128 type.
+func makeComplex(f flag, v complex128, t Type) Value {
+ typ := t.common()
+ if typ.size > ptrSize {
+ ptr := unsafe_New(t)
+ switch typ.size {
+ case 8:
+ *(*complex64)(unsafe.Pointer(ptr)) = complex64(v)
+ case 16:
+ *(*complex128)(unsafe.Pointer(ptr)) = v
+ }
+ return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift}
+ }
+
+ // Assume ptrSize <= 8 so this must be complex64.
+ var w iword
+ *(*complex64)(unsafe.Pointer(&w)) = complex64(v)
+ return Value{typ, unsafe.Pointer(&w), f | flag(typ.Kind())<<flagKindShift | flagIndir}
+}
+
+func makeString(f flag, v string, t Type) Value {
+ ret := New(t).Elem()
+ ret.SetString(v)
+ ret.flag = ret.flag&^flagAddr | f
+ return ret
+}
+
+func makeBytes(f flag, v []byte, t Type) Value {
+ ret := New(t).Elem()
+ ret.SetBytes(v)
+ ret.flag = ret.flag&^flagAddr | f
+ return ret
+}
+
+func makeRunes(f flag, v []rune, t Type) Value {
+ ret := New(t).Elem()
+ ret.setRunes(v)
+ ret.flag = ret.flag&^flagAddr | f
+ return ret
+}
+
+// These conversion functions are returned by convertOp
+// for classes of conversions. For example, the first function, cvtInt,
+// takes any value v of signed int type and returns the value converted
+// to type t, where t is any signed or unsigned int type.
+
+// convertOp: intXX -> [u]intXX
+func cvtInt(v Value, t Type) Value {
+ return makeInt(v.flag&flagRO, uint64(v.Int()), t)
+}
+
+// convertOp: uintXX -> [u]intXX
+func cvtUint(v Value, t Type) Value {
+ return makeInt(v.flag&flagRO, v.Uint(), t)
+}
+
+// convertOp: floatXX -> intXX
+func cvtFloatInt(v Value, t Type) Value {
+ return makeInt(v.flag&flagRO, uint64(int64(v.Float())), t)
+}
+
+// convertOp: floatXX -> uintXX
+func cvtFloatUint(v Value, t Type) Value {
+ return makeInt(v.flag&flagRO, uint64(v.Float()), t)
+}
+
+// convertOp: intXX -> floatXX
+func cvtIntFloat(v Value, t Type) Value {
+ return makeFloat(v.flag&flagRO, float64(v.Int()), t)
+}
+
+// convertOp: uintXX -> floatXX
+func cvtUintFloat(v Value, t Type) Value {
+ return makeFloat(v.flag&flagRO, float64(v.Uint()), t)
+}
+
+// convertOp: floatXX -> floatXX
+func cvtFloat(v Value, t Type) Value {
+ return makeFloat(v.flag&flagRO, v.Float(), t)
+}
+
+// convertOp: complexXX -> complexXX
+func cvtComplex(v Value, t Type) Value {
+ return makeComplex(v.flag&flagRO, v.Complex(), t)
+}
+
+// convertOp: intXX -> string
+func cvtIntString(v Value, t Type) Value {
+ return makeString(v.flag&flagRO, string(v.Int()), t)
+}
+
+// convertOp: uintXX -> string
+func cvtUintString(v Value, t Type) Value {
+ return makeString(v.flag&flagRO, string(v.Uint()), t)
+}
+
+// convertOp: []byte -> string
+func cvtBytesString(v Value, t Type) Value {
+ return makeString(v.flag&flagRO, string(v.Bytes()), t)
+}
+
+// convertOp: string -> []byte
+func cvtStringBytes(v Value, t Type) Value {
+ return makeBytes(v.flag&flagRO, []byte(v.String()), t)
+}
+
+// convertOp: []rune -> string
+func cvtRunesString(v Value, t Type) Value {
+ return makeString(v.flag&flagRO, string(v.runes()), t)
+}
+
+// convertOp: string -> []rune
+func cvtStringRunes(v Value, t Type) Value {
+ return makeRunes(v.flag&flagRO, []rune(v.String()), t)
+}
+
+// convertOp: direct copy
+func cvtDirect(v Value, typ Type) Value {
+ f := v.flag
+ t := typ.common()
+ val := v.val
+ if f&flagAddr != 0 {
+ // indirect, mutable word - make a copy
+ ptr := unsafe_New(t)
+ memmove(ptr, val, t.size)
+ val = ptr
+ f &^= flagAddr
+ }
+ return Value{t, val, v.flag&flagRO | f}
+}
+
+// convertOp: concrete -> interface
+func cvtT2I(v Value, typ Type) Value {
+ target := new(interface{})
+ x := valueInterface(v, false)
+ if typ.NumMethod() == 0 {
+ *target = x
+ } else {
+ ifaceE2I(typ.runtimeType(), x, unsafe.Pointer(target))
+ }
+ return Value{typ.common(), unsafe.Pointer(target), v.flag&flagRO | flagIndir | flag(Interface)<<flagKindShift}
+}
+
+// convertOp: interface -> interface
+func cvtI2I(v Value, typ Type) Value {
+ if v.IsNil() {
+ ret := Zero(typ)
+ ret.flag |= v.flag & flagRO
+ return ret
+ }
+ return cvtT2I(v.Elem(), typ)
+}
+
// implemented in ../pkg/runtime
-func chancap(ch iword) int32
+func chancap(ch iword) int
func chanclose(ch iword)
-func chanlen(ch iword) int32
+func chanlen(ch iword) int
func chanrecv(t *runtimeType, ch iword, nb bool) (val iword, selected, received bool)
func chansend(t *runtimeType, ch iword, val iword, nb bool) bool
-func makechan(typ *runtimeType, size uint32) (ch iword)
+func makechan(typ *runtimeType, size uint64) (ch iword)
func makemap(t *runtimeType) (m iword)
func mapaccess(t *runtimeType, m iword, key iword) (val iword, ok bool)
func mapassign(t *runtimeType, m iword, key, val iword, ok bool)
func mapiterinit(t *runtimeType, m iword) *byte
func mapiterkey(it *byte) (key iword, ok bool)
func mapiternext(it *byte)
-func maplen(m iword) int32
+func maplen(m iword) int
func call(typ *commonType, fnaddr unsafe.Pointer, isInterface bool, isMethod bool, params *unsafe.Pointer, results *unsafe.Pointer)
func ifaceE2I(t *runtimeType, src interface{}, dst unsafe.Pointer)
diff --git a/libgo/go/regexp/syntax/doc.go b/libgo/go/regexp/syntax/doc.go
new file mode 100644
index 00000000000..843a6f6a424
--- /dev/null
+++ b/libgo/go/regexp/syntax/doc.go
@@ -0,0 +1,127 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// DO NOT EDIT. This file is generated by mksyntaxgo from the RE2 distribution.
+
+/*
+Package syntax parses regular expressions into parse trees and compiles
+parse trees into programs. Most clients of regular expressions will use the
+facilities of package regexp (such as Compile and Match) instead of this package.
+
+Syntax
+
+The regular expression syntax understood by this package when parsing with the Perl flag is as follows.
+Parts of the syntax can be disabled by passing alternate flags to Parse.
+
+
+Single characters:
+ . any character, possibly including newline (flag s=true)
+ [xyz] character class
+ [^xyz] negated character class
+ \d Perl character class
+ \D negated Perl character class
+ [:alpha:] ASCII character class
+ [:^alpha:] negated ASCII character class
+ \pN Unicode character class (one-letter name)
+ \p{Greek} Unicode character class
+ \PN negated Unicode character class (one-letter name)
+ \P{Greek} negated Unicode character class
+
+Composites:
+ xy x followed by y
+ x|y x or y (prefer x)
+
+Repetitions:
+ x* zero or more x, prefer more
+ x+ one or more x, prefer more
+ x? zero or one x, prefer one
+ x{n,m} n or n+1 or ... or m x, prefer more
+ x{n,} n or more x, prefer more
+ x{n} exactly n x
+ x*? zero or more x, prefer fewer
+ x+? one or more x, prefer fewer
+ x?? zero or one x, prefer zero
+ x{n,m}? n or n+1 or ... or m x, prefer fewer
+ x{n,}? n or more x, prefer fewer
+ x{n}? exactly n x
+
+Grouping:
+ (re) numbered capturing group
+ (?P<name>re) named & numbered capturing group
+ (?:re) non-capturing group
+ (?flags) set flags within current group; non-capturing
+ (?flags:re) set flags during re; non-capturing
+
+ Flag syntax is xyz (set) or -xyz (clear) or xy-z (set xy, clear z). The flags are:
+
+ i case-insensitive (default false)
+ m multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false)
+ s let . match \n (default false)
+ U ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false)
+
+Empty strings:
+ ^ at beginning of text or line (flag m=true)
+ $ at end of text (like \z not \Z) or line (flag m=true)
+ \A at beginning of text
+ \b at word boundary (\w on one side and \W, \A, or \z on the other)
+ \B not a word boundary
+ \z at end of text
+
+Escape sequences:
+ \a bell (== \007)
+ \f form feed (== \014)
+ \t horizontal tab (== \011)
+ \n newline (== \012)
+ \r carriage return (== \015)
+ \v vertical tab character (== \013)
+ \* literal *, for any punctuation character *
+ \123 octal character code (up to three digits)
+ \x7F hex character code (exactly two digits)
+ \x{10FFFF} hex character code
+ \Q...\E literal text ... even if ... has punctuation
+
+Character class elements:
+ x single character
+ A-Z character range (inclusive)
+ \d Perl character class
+ [:foo:] ASCII character class foo
+ \p{Foo} Unicode character class Foo
+ \pF Unicode character class F (one-letter name)
+
+Named character classes as character class elements:
+ [\d] digits (== \d)
+ [^\d] not digits (== \D)
+ [\D] not digits (== \D)
+ [^\D] not not digits (== \d)
+ [[:name:]] named ASCII class inside character class (== [:name:])
+ [^[:name:]] named ASCII class inside negated character class (== [:^name:])
+ [\p{Name}] named Unicode property inside character class (== \p{Name})
+ [^\p{Name}] named Unicode property inside negated character class (== \P{Name})
+
+Perl character classes:
+ \d digits (== [0-9])
+ \D not digits (== [^0-9])
+ \s whitespace (== [\t\n\f\r ])
+ \S not whitespace (== [^\t\n\f\r ])
+ \w word characters (== [0-9A-Za-z_])
+ \W not word characters (== [^0-9A-Za-z_])
+
+ASCII character classes:
+ [:alnum:] alphanumeric (== [0-9A-Za-z])
+ [:alpha:] alphabetic (== [A-Za-z])
+ [:ascii:] ASCII (== [\x00-\x7F])
+ [:blank:] blank (== [\t ])
+ [:cntrl:] control (== [\x00-\x1F\x7F])
+ [:digit:] digits (== [0-9])
+ [:graph:] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
+ [:lower:] lower case (== [a-z])
+ [:print:] printable (== [ -~] == [ [:graph:]])
+ [:punct:] punctuation (== [!-/:-@[-`{-~])
+ [:space:] whitespace (== [\t\n\v\f\r ])
+ [:upper:] upper case (== [A-Z])
+ [:word:] word characters (== [0-9A-Za-z_])
+ [:xdigit:] hex digit (== [0-9A-Fa-f])
+
+*/
+package syntax
diff --git a/libgo/go/regexp/syntax/parse.go b/libgo/go/regexp/syntax/parse.go
index 4c61cb3a064..4088dba9784 100644
--- a/libgo/go/regexp/syntax/parse.go
+++ b/libgo/go/regexp/syntax/parse.go
@@ -2,10 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package syntax parses regular expressions into parse trees and compiles
-// parse trees into programs. Most clients of regular expressions will use
-// the facilities of package regexp (such as Compile and Match) instead of
-// this package.
package syntax
import (
diff --git a/libgo/go/runtime/complex_test.go b/libgo/go/runtime/complex_test.go
new file mode 100644
index 00000000000..f41e6a35701
--- /dev/null
+++ b/libgo/go/runtime/complex_test.go
@@ -0,0 +1,67 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ "math/cmplx"
+ "testing"
+)
+
+var result complex128
+
+func BenchmarkComplex128DivNormal(b *testing.B) {
+ d := 15 + 2i
+ n := 32 + 3i
+ res := 0i
+ for i := 0; i < b.N; i++ {
+ n += 0.1i
+ res += n / d
+ }
+ result = res
+}
+
+func BenchmarkComplex128DivNisNaN(b *testing.B) {
+ d := cmplx.NaN()
+ n := 32 + 3i
+ res := 0i
+ for i := 0; i < b.N; i++ {
+ n += 0.1i
+ res += n / d
+ }
+ result = res
+}
+
+func BenchmarkComplex128DivDisNaN(b *testing.B) {
+ d := 15 + 2i
+ n := cmplx.NaN()
+ res := 0i
+ for i := 0; i < b.N; i++ {
+ d += 0.1i
+ res += n / d
+ }
+ result = res
+}
+
+func BenchmarkComplex128DivNisInf(b *testing.B) {
+ d := 15 + 2i
+ n := cmplx.Inf()
+ res := 0i
+ for i := 0; i < b.N; i++ {
+ d += 0.1i
+ res += n / d
+ }
+ result = res
+}
+
+func BenchmarkComplex128DivDisInf(b *testing.B) {
+ d := cmplx.Inf()
+ n := 32 + 3i
+ res := 0i
+ for i := 0; i < b.N; i++ {
+ n += 0.1i
+ res += n / d
+ }
+ result = res
+}
diff --git a/libgo/go/runtime/crash_cgo_test.go b/libgo/go/runtime/crash_cgo_test.go
new file mode 100644
index 00000000000..91c4bdb0358
--- /dev/null
+++ b/libgo/go/runtime/crash_cgo_test.go
@@ -0,0 +1,15 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build cgo
+
+package runtime_test
+
+import (
+ "testing"
+)
+
+func TestCgoCrashHandler(t *testing.T) {
+ testCrashHandler(t, &crashTest{Cgo: true})
+}
diff --git a/libgo/go/runtime/crash_test.go b/libgo/go/runtime/crash_test.go
new file mode 100644
index 00000000000..465b2d70964
--- /dev/null
+++ b/libgo/go/runtime/crash_test.go
@@ -0,0 +1,109 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "testing"
+ "text/template"
+)
+
+type crashTest struct {
+ Cgo bool
+}
+
+// This test is a separate program, because it is testing
+// both main (m0) and non-main threads (m).
+
+func testCrashHandler(t *testing.T, ct *crashTest) {
+ if runtime.GOOS == "freebsd" || runtime.GOOS == "netbsd" {
+ // TODO(brainman): do not know why this test fails on freebsd
+ // TODO(jsing): figure out why this causes delayed failures
+ // on NetBSD - http://golang.org/issue/3954
+ t.Logf("skipping test on %q", runtime.GOOS)
+ return
+ }
+
+ st := template.Must(template.New("crashSource").Parse(crashSource))
+
+ dir, err := ioutil.TempDir("", "go-build")
+ if err != nil {
+ t.Fatalf("failed to create temp directory: %v", err)
+ }
+ defer os.RemoveAll(dir)
+
+ src := filepath.Join(dir, "main.go")
+ f, err := os.Create(src)
+ if err != nil {
+ t.Fatalf("failed to create %v: %v", src, err)
+ }
+ err = st.Execute(f, ct)
+ if err != nil {
+ f.Close()
+ t.Fatalf("failed to execute template: %v", err)
+ }
+ f.Close()
+
+ got, err := exec.Command("go", "run", src).CombinedOutput()
+ if err != nil {
+ t.Fatalf("program exited with error: %v\n%v", err, string(got))
+ }
+ want := "main: recovered done\nnew-thread: recovered done\nsecond-new-thread: recovered done\nmain-again: recovered done\n"
+ if string(got) != string(want) {
+ t.Fatalf("expected %q, but got %q", string(want), string(got))
+ }
+}
+
+func TestCrashHandler(t *testing.T) {
+ testCrashHandler(t, &crashTest{Cgo: false})
+}
+
+const crashSource = `
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+{{if .Cgo}}
+import "C"
+{{end}}
+
+func test(name string) {
+ defer func() {
+ if x := recover(); x != nil {
+ fmt.Printf(" recovered")
+ }
+ fmt.Printf(" done\n")
+ }()
+ fmt.Printf("%s:", name)
+ var s *string
+ _ = *s
+ fmt.Print("SHOULD NOT BE HERE")
+}
+
+func testInNewThread(name string) {
+ c := make(chan bool)
+ go func() {
+ runtime.LockOSThread()
+ test(name)
+ c <- true
+ }()
+ <-c
+}
+
+func main() {
+ runtime.LockOSThread()
+ test("main")
+ testInNewThread("new-thread")
+ testInNewThread("second-new-thread")
+ test("main-again")
+}
+`
diff --git a/libgo/go/runtime/debug.go b/libgo/go/runtime/debug.go
index b802fc63f71..e9d7601710c 100644
--- a/libgo/go/runtime/debug.go
+++ b/libgo/go/runtime/debug.go
@@ -138,6 +138,31 @@ func CPUProfile() []byte
// SetCPUProfileRate directly.
func SetCPUProfileRate(hz int)
+// SetBlockProfileRate controls the fraction of goroutine blocking events
+// that are reported in the blocking profile. The profiler aims to sample
+// an average of one blocking event per rate nanoseconds spent blocked.
+//
+// To include every blocking event in the profile, pass rate = 1.
+// To turn off profiling entirely, pass rate <= 0.
+func SetBlockProfileRate(rate int)
+
+// BlockProfileRecord describes blocking events originated
+// at a particular call sequence (stack trace).
+type BlockProfileRecord struct {
+ Count int64
+ Cycles int64
+ StackRecord
+}
+
+// BlockProfile returns n, the number of records in the current blocking profile.
+// If len(p) >= n, BlockProfile copies the profile into p and returns n, true.
+// If len(p) < n, BlockProfile does not change p and returns n, false.
+//
+// Most clients should use the runtime/pprof package or
+// the testing package's -test.blockprofile flag instead
+// of calling BlockProfile directly.
+func BlockProfile(p []BlockProfileRecord) (n int, ok bool)
+
// Stack formats a stack trace of the calling goroutine into buf
// and returns the number of bytes written to buf.
// If all is true, Stack formats stack traces of all other goroutines
diff --git a/libgo/go/runtime/debug/stack_test.go b/libgo/go/runtime/debug/stack_test.go
index f33f5072b40..bbd662618fd 100644
--- a/libgo/go/runtime/debug/stack_test.go
+++ b/libgo/go/runtime/debug/stack_test.go
@@ -36,7 +36,7 @@ func (t T) method() []byte {
func TestStack(t *testing.T) {
b := T(0).method()
lines := strings.Split(string(b), "\n")
- if len(lines) <= 6 {
+ if len(lines) < 6 {
t.Fatal("too few lines")
}
n := 0
diff --git a/libgo/go/runtime/error.go b/libgo/go/runtime/error.go
index d3913ec27b8..f7f81e95d3e 100644
--- a/libgo/go/runtime/error.go
+++ b/libgo/go/runtime/error.go
@@ -57,9 +57,41 @@ func NewTypeAssertionError(ps1, ps2, ps3 *string, pmeth *string, ret *interface{
if pmeth != nil {
meth = *pmeth
}
+
+ // For gccgo, strip out quoted strings.
+ s1 = unquote(s1)
+ s2 = unquote(s2)
+ s3 = unquote(s3)
+
*ret = &TypeAssertionError{s1, s2, s3, meth}
}
+// Remove quoted strings from gccgo reflection strings.
+func unquote(s string) string {
+ ls := len(s)
+ var i int
+ for i = 0; i < ls; i++ {
+ if s[i] == '\t' {
+ break
+ }
+ }
+ if i == ls {
+ return s
+ }
+ var q bool
+ r := make([]byte, len(s))
+ j := 0
+ for i = 0; i < ls; i++ {
+ if s[i] == '\t' {
+ q = !q
+ } else if !q {
+ r[j] = s[i]
+ j++
+ }
+ }
+ return string(r[:j])
+}
+
// An errorString represents a runtime error described by a single string.
type errorString string
diff --git a/libgo/go/runtime/export_test.go b/libgo/go/runtime/export_test.go
index c603e1b0d79..7551ab802ca 100644
--- a/libgo/go/runtime/export_test.go
+++ b/libgo/go/runtime/export_test.go
@@ -23,3 +23,39 @@ func golockedOSThread() bool
var Entersyscall = entersyscall
var Exitsyscall = exitsyscall
var LockedOSThread = golockedOSThread
+
+type LFNode struct {
+ Next *LFNode
+ Pushcnt uintptr
+}
+
+func lfstackpush(head *uint64, node *LFNode)
+func lfstackpop2(head *uint64) *LFNode
+
+var LFStackPush = lfstackpush
+var LFStackPop = lfstackpop2
+
+type ParFor struct {
+ body *byte
+ done uint32
+ Nthr uint32
+ nthrmax uint32
+ thrseq uint32
+ Cnt uint32
+ Ctx *byte
+ wait bool
+}
+
+func parforalloc2(nthrmax uint32) *ParFor
+func parforsetup2(desc *ParFor, nthr, n uint32, ctx *byte, wait bool, body func(*ParFor, uint32))
+func parfordo(desc *ParFor)
+func parforiters(desc *ParFor, tid uintptr) (uintptr, uintptr)
+
+var NewParFor = parforalloc2
+var ParForSetup = parforsetup2
+var ParForDo = parfordo
+
+func ParForIters(desc *ParFor, tid uint32) (uint32, uint32) {
+ begin, end := parforiters(desc, uintptr(tid))
+ return uint32(begin), uint32(end)
+}
diff --git a/libgo/go/runtime/gc_test.go b/libgo/go/runtime/gc_test.go
index 7770e499ad3..56dd93819e1 100644
--- a/libgo/go/runtime/gc_test.go
+++ b/libgo/go/runtime/gc_test.go
@@ -26,6 +26,7 @@ func TestGcSys(t *testing.T) {
}
// Should only be using a few MB.
+ // We allocated 100 MB or (if not short) 1 GB.
runtime.ReadMemStats(memstats)
if sys > memstats.Sys {
sys = 0
@@ -33,7 +34,7 @@ func TestGcSys(t *testing.T) {
sys = memstats.Sys - sys
}
t.Logf("used %d extra bytes", sys)
- if sys > 4<<20 {
+ if sys > 16<<20 {
t.Fatalf("using too much memory: %d bytes", sys)
}
}
@@ -41,3 +42,19 @@ func TestGcSys(t *testing.T) {
func workthegc() []byte {
return make([]byte, 1029)
}
+
+func TestGcDeepNesting(t *testing.T) {
+ type T [2][2][2][2][2][2][2][2][2][2]*int
+ a := new(T)
+
+ // Prevent the compiler from applying escape analysis.
+ // This makes sure new(T) is allocated on heap, not on the stack.
+ t.Logf("%p", a)
+
+ a[0][0][0][0][0][0][0][0][0][0] = new(int)
+ *a[0][0][0][0][0][0][0][0][0][0] = 13
+ runtime.GC()
+ if *a[0][0][0][0][0][0][0][0][0][0] != 13 {
+ t.Fail()
+ }
+}
diff --git a/libgo/go/runtime/iface_test.go b/libgo/go/runtime/iface_test.go
new file mode 100644
index 00000000000..bca0ea0ee75
--- /dev/null
+++ b/libgo/go/runtime/iface_test.go
@@ -0,0 +1,138 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ "testing"
+)
+
+type I1 interface {
+ Method1()
+}
+
+type I2 interface {
+ Method1()
+ Method2()
+}
+
+type TS uint16
+type TM uintptr
+type TL [2]uintptr
+
+func (TS) Method1() {}
+func (TS) Method2() {}
+func (TM) Method1() {}
+func (TM) Method2() {}
+func (TL) Method1() {}
+func (TL) Method2() {}
+
+var (
+ e interface{}
+ e_ interface{}
+ i1 I1
+ i2 I2
+ ts TS
+ tm TM
+ tl TL
+)
+
+func BenchmarkConvT2ESmall(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ e = ts
+ }
+}
+
+func BenchmarkConvT2EUintptr(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ e = tm
+ }
+}
+
+func BenchmarkConvT2ELarge(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ e = tl
+ }
+}
+
+func BenchmarkConvT2ISmall(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ i1 = ts
+ }
+}
+
+func BenchmarkConvT2IUintptr(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ i1 = tm
+ }
+}
+
+func BenchmarkConvT2ILarge(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ i1 = tl
+ }
+}
+
+func BenchmarkConvI2E(b *testing.B) {
+ i2 = tm
+ for i := 0; i < b.N; i++ {
+ e = i2
+ }
+}
+
+func BenchmarkConvI2I(b *testing.B) {
+ i2 = tm
+ for i := 0; i < b.N; i++ {
+ i1 = i2
+ }
+}
+
+func BenchmarkAssertE2T(b *testing.B) {
+ e = tm
+ for i := 0; i < b.N; i++ {
+ tm = e.(TM)
+ }
+}
+
+func BenchmarkAssertE2TLarge(b *testing.B) {
+ e = tl
+ for i := 0; i < b.N; i++ {
+ tl = e.(TL)
+ }
+}
+
+func BenchmarkAssertE2I(b *testing.B) {
+ e = tm
+ for i := 0; i < b.N; i++ {
+ i1 = e.(I1)
+ }
+}
+
+func BenchmarkAssertI2T(b *testing.B) {
+ i1 = tm
+ for i := 0; i < b.N; i++ {
+ tm = i1.(TM)
+ }
+}
+
+func BenchmarkAssertI2I(b *testing.B) {
+ i1 = tm
+ for i := 0; i < b.N; i++ {
+ i2 = i1.(I2)
+ }
+}
+
+func BenchmarkAssertI2E(b *testing.B) {
+ i1 = tm
+ for i := 0; i < b.N; i++ {
+ e = i1.(interface{})
+ }
+}
+
+func BenchmarkAssertE2E(b *testing.B) {
+ e = tm
+ for i := 0; i < b.N; i++ {
+ e_ = e
+ }
+}
diff --git a/libgo/go/runtime/lfstack_test.go b/libgo/go/runtime/lfstack_test.go
new file mode 100644
index 00000000000..505aae60551
--- /dev/null
+++ b/libgo/go/runtime/lfstack_test.go
@@ -0,0 +1,130 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ "math/rand"
+ . "runtime"
+ "testing"
+ "unsafe"
+)
+
+type MyNode struct {
+ LFNode
+ data int
+}
+
+func fromMyNode(node *MyNode) *LFNode {
+ return (*LFNode)(unsafe.Pointer(node))
+}
+
+func toMyNode(node *LFNode) *MyNode {
+ return (*MyNode)(unsafe.Pointer(node))
+}
+
+func TestLFStack(t *testing.T) {
+ stack := new(uint64)
+ // Need to keep additional referenfces to nodes, the stack is not all that type-safe.
+ var nodes []*MyNode
+
+ // Check the stack is initially empty.
+ if LFStackPop(stack) != nil {
+ t.Fatalf("stack is not empty")
+ }
+
+ // Push one element.
+ node := &MyNode{data: 42}
+ nodes = append(nodes, node)
+ LFStackPush(stack, fromMyNode(node))
+
+ // Push another.
+ node = &MyNode{data: 43}
+ nodes = append(nodes, node)
+ LFStackPush(stack, fromMyNode(node))
+
+ // Pop one element.
+ node = toMyNode(LFStackPop(stack))
+ if node == nil {
+ t.Fatalf("stack is empty")
+ }
+ if node.data != 43 {
+ t.Fatalf("no lifo")
+ }
+
+ // Pop another.
+ node = toMyNode(LFStackPop(stack))
+ if node == nil {
+ t.Fatalf("stack is empty")
+ }
+ if node.data != 42 {
+ t.Fatalf("no lifo")
+ }
+
+ // Check the stack is empty again.
+ if LFStackPop(stack) != nil {
+ t.Fatalf("stack is not empty")
+ }
+ if *stack != 0 {
+ t.Fatalf("stack is not empty")
+ }
+}
+
+func TestLFStackStress(t *testing.T) {
+ const K = 100
+ P := 4 * GOMAXPROCS(-1)
+ N := 100000
+ if testing.Short() {
+ N /= 10
+ }
+ // Create 2 stacks.
+ stacks := [2]*uint64{new(uint64), new(uint64)}
+ // Need to keep additional referenfces to nodes, the stack is not all that type-safe.
+ var nodes []*MyNode
+ // Push K elements randomly onto the stacks.
+ sum := 0
+ for i := 0; i < K; i++ {
+ sum += i
+ node := &MyNode{data: i}
+ nodes = append(nodes, node)
+ LFStackPush(stacks[i%2], fromMyNode(node))
+ }
+ c := make(chan bool, P)
+ for p := 0; p < P; p++ {
+ go func() {
+ r := rand.New(rand.NewSource(rand.Int63()))
+ // Pop a node from a random stack, then push it onto a random stack.
+ for i := 0; i < N; i++ {
+ node := toMyNode(LFStackPop(stacks[r.Intn(2)]))
+ if node != nil {
+ LFStackPush(stacks[r.Intn(2)], fromMyNode(node))
+ }
+ }
+ c <- true
+ }()
+ }
+ for i := 0; i < P; i++ {
+ <-c
+ }
+ // Pop all elements from both stacks, and verify that nothing lost.
+ sum2 := 0
+ cnt := 0
+ for i := 0; i < 2; i++ {
+ for {
+ node := toMyNode(LFStackPop(stacks[i]))
+ if node == nil {
+ break
+ }
+ cnt++
+ sum2 += node.data
+ node.Next = nil
+ }
+ }
+ if cnt != K {
+ t.Fatalf("Wrong number of nodes %d/%d", cnt, K)
+ }
+ if sum2 != sum {
+ t.Fatalf("Wrong sum %d/%d", sum2, sum)
+ }
+}
diff --git a/libgo/go/runtime/parfor_test.go b/libgo/go/runtime/parfor_test.go
new file mode 100644
index 00000000000..0547db02096
--- /dev/null
+++ b/libgo/go/runtime/parfor_test.go
@@ -0,0 +1,125 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ . "runtime"
+ "testing"
+ "unsafe"
+)
+
+// Simple serial sanity test for parallelfor.
+func TestParFor(t *testing.T) {
+ const P = 1
+ const N = 20
+ data := make([]uint64, N)
+ for i := uint64(0); i < N; i++ {
+ data[i] = i
+ }
+ desc := NewParFor(P)
+ ParForSetup(desc, P, N, nil, true, func(desc *ParFor, i uint32) {
+ data[i] = data[i]*data[i] + 1
+ })
+ ParForDo(desc)
+ for i := uint64(0); i < N; i++ {
+ if data[i] != i*i+1 {
+ t.Fatalf("Wrong element %d: %d", i, data[i])
+ }
+ }
+}
+
+// Test that nonblocking parallelfor does not block.
+func TestParFor2(t *testing.T) {
+ const P = 7
+ const N = 1003
+ data := make([]uint64, N)
+ for i := uint64(0); i < N; i++ {
+ data[i] = i
+ }
+ desc := NewParFor(P)
+ ParForSetup(desc, P, N, (*byte)(unsafe.Pointer(&data)), false, func(desc *ParFor, i uint32) {
+ d := *(*[]uint64)(unsafe.Pointer(desc.Ctx))
+ d[i] = d[i]*d[i] + 1
+ })
+ for p := 0; p < P; p++ {
+ ParForDo(desc)
+ }
+ for i := uint64(0); i < N; i++ {
+ if data[i] != i*i+1 {
+ t.Fatalf("Wrong element %d: %d", i, data[i])
+ }
+ }
+}
+
+// Test that iterations are properly distributed.
+func TestParForSetup(t *testing.T) {
+ const P = 11
+ const N = 101
+ desc := NewParFor(P)
+ for n := uint32(0); n < N; n++ {
+ for p := uint32(1); p <= P; p++ {
+ ParForSetup(desc, p, n, nil, true, func(desc *ParFor, i uint32) {})
+ sum := uint32(0)
+ size0 := uint32(0)
+ end0 := uint32(0)
+ for i := uint32(0); i < p; i++ {
+ begin, end := ParForIters(desc, i)
+ size := end - begin
+ sum += size
+ if i == 0 {
+ size0 = size
+ if begin != 0 {
+ t.Fatalf("incorrect begin: %d (n=%d, p=%d)", begin, n, p)
+ }
+ } else {
+ if size != size0 && size != size0+1 {
+ t.Fatalf("incorrect size: %d/%d (n=%d, p=%d)", size, size0, n, p)
+ }
+ if begin != end0 {
+ t.Fatalf("incorrect begin/end: %d/%d (n=%d, p=%d)", begin, end0, n, p)
+ }
+ }
+ end0 = end
+ }
+ if sum != n {
+ t.Fatalf("incorrect sum: %d/%d (p=%d)", sum, n, p)
+ }
+ }
+ }
+}
+
+// Test parallel parallelfor.
+func TestParForParallel(t *testing.T) {
+ if GOARCH != "amd64" {
+ t.Log("temporarily disabled, see http://golang.org/issue/4155")
+ return
+ }
+
+ N := uint64(1e7)
+ if testing.Short() {
+ N /= 10
+ }
+ data := make([]uint64, N)
+ for i := uint64(0); i < N; i++ {
+ data[i] = i
+ }
+ P := GOMAXPROCS(-1)
+ desc := NewParFor(uint32(P))
+ ParForSetup(desc, uint32(P), uint32(N), nil, true, func(desc *ParFor, i uint32) {
+ data[i] = data[i]*data[i] + 1
+ })
+ for p := 1; p < P; p++ {
+ go ParForDo(desc)
+ }
+ ParForDo(desc)
+ for i := uint64(0); i < N; i++ {
+ if data[i] != i*i+1 {
+ t.Fatalf("Wrong element %d: %d", i, data[i])
+ }
+ }
+
+ data, desc = nil, nil
+ GC()
+}
diff --git a/libgo/go/runtime/pprof/pprof.go b/libgo/go/runtime/pprof/pprof.go
index 8cc15390c14..952ccf6d898 100644
--- a/libgo/go/runtime/pprof/pprof.go
+++ b/libgo/go/runtime/pprof/pprof.go
@@ -36,6 +36,7 @@ import (
// goroutine - stack traces of all current goroutines
// heap - a sampling of all heap allocations
// threadcreate - stack traces that led to the creation of new OS threads
+// block - stack traces that led to blocking on synchronization primitives
//
// These predefine profiles maintain themselves and panic on an explicit
// Add or Remove method call.
@@ -76,6 +77,12 @@ var heapProfile = &Profile{
write: writeHeap,
}
+var blockProfile = &Profile{
+ name: "block",
+ count: countBlock,
+ write: writeBlock,
+}
+
func lockProfiles() {
profiles.mu.Lock()
if profiles.m == nil {
@@ -84,6 +91,7 @@ func lockProfiles() {
"goroutine": goroutineProfile,
"threadcreate": threadcreateProfile,
"heap": heapProfile,
+ "block": blockProfile,
}
}
}
@@ -352,26 +360,26 @@ func WriteHeapProfile(w io.Writer) error {
// countHeap returns the number of records in the heap profile.
func countHeap() int {
- n, _ := runtime.MemProfile(nil, false)
+ n, _ := runtime.MemProfile(nil, true)
return n
}
// writeHeap writes the current runtime heap profile to w.
func writeHeap(w io.Writer, debug int) error {
- // Find out how many records there are (MemProfile(nil, false)),
+ // Find out how many records there are (MemProfile(nil, true)),
// allocate that many records, and get the data.
// There's a race—more records might be added between
// the two calls—so allocate a few extra records for safety
// and also try again if we're very unlucky.
// The loop should only execute one iteration in the common case.
var p []runtime.MemProfileRecord
- n, ok := runtime.MemProfile(nil, false)
+ n, ok := runtime.MemProfile(nil, true)
for {
// Allocate room for a slightly bigger profile,
// in case a few more entries have been added
// since the call to MemProfile.
p = make([]runtime.MemProfileRecord, n+50)
- n, ok = runtime.MemProfile(p, false)
+ n, ok = runtime.MemProfile(p, true)
if ok {
p = p[0:n]
break
@@ -431,11 +439,14 @@ func writeHeap(w io.Writer, debug int) error {
fmt.Fprintf(w, "# Sys = %d\n", s.Sys)
fmt.Fprintf(w, "# Lookups = %d\n", s.Lookups)
fmt.Fprintf(w, "# Mallocs = %d\n", s.Mallocs)
+ fmt.Fprintf(w, "# Frees = %d\n", s.Frees)
fmt.Fprintf(w, "# HeapAlloc = %d\n", s.HeapAlloc)
fmt.Fprintf(w, "# HeapSys = %d\n", s.HeapSys)
fmt.Fprintf(w, "# HeapIdle = %d\n", s.HeapIdle)
fmt.Fprintf(w, "# HeapInuse = %d\n", s.HeapInuse)
+ fmt.Fprintf(w, "# HeapReleased = %d\n", s.HeapReleased)
+ fmt.Fprintf(w, "# HeapObjects = %d\n", s.HeapObjects)
fmt.Fprintf(w, "# Stack = %d / %d\n", s.StackInuse, s.StackSys)
fmt.Fprintf(w, "# MSpan = %d / %d\n", s.MSpanInuse, s.MSpanSys)
@@ -597,3 +608,60 @@ func StopCPUProfile() {
runtime.SetCPUProfileRate(0)
<-cpu.done
}
+
+type byCycles []runtime.BlockProfileRecord
+
+func (x byCycles) Len() int { return len(x) }
+func (x byCycles) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x byCycles) Less(i, j int) bool { return x[i].Cycles > x[j].Cycles }
+
+// countBlock returns the number of records in the blocking profile.
+func countBlock() int {
+ n, _ := runtime.BlockProfile(nil)
+ return n
+}
+
+// writeBlock writes the current blocking profile to w.
+func writeBlock(w io.Writer, debug int) error {
+ var p []runtime.BlockProfileRecord
+ n, ok := runtime.BlockProfile(nil)
+ for {
+ p = make([]runtime.BlockProfileRecord, n+50)
+ n, ok = runtime.BlockProfile(p)
+ if ok {
+ p = p[:n]
+ break
+ }
+ }
+
+ sort.Sort(byCycles(p))
+
+ b := bufio.NewWriter(w)
+ var tw *tabwriter.Writer
+ w = b
+ if debug > 0 {
+ tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
+ w = tw
+ }
+
+ fmt.Fprintf(w, "--- contention:\n")
+ fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
+ for i := range p {
+ r := &p[i]
+ fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
+ for _, pc := range r.Stack() {
+ fmt.Fprintf(w, " %#x", pc)
+ }
+ fmt.Fprint(w, "\n")
+ if debug > 0 {
+ printStackRecord(w, r.Stack(), false)
+ }
+ }
+
+ if tw != nil {
+ tw.Flush()
+ }
+ return b.Flush()
+}
+
+func runtime_cyclesPerSecond() int64
diff --git a/libgo/go/runtime/proc_test.go b/libgo/go/runtime/proc_test.go
index 32111080a54..1d51c5271e3 100644
--- a/libgo/go/runtime/proc_test.go
+++ b/libgo/go/runtime/proc_test.go
@@ -123,3 +123,29 @@ func BenchmarkSyscallWork(b *testing.B) {
<-c
}
}
+
+func BenchmarkCreateGoroutines(b *testing.B) {
+ benchmarkCreateGoroutines(b, 1)
+}
+
+func BenchmarkCreateGoroutinesParallel(b *testing.B) {
+ benchmarkCreateGoroutines(b, runtime.GOMAXPROCS(-1))
+}
+
+func benchmarkCreateGoroutines(b *testing.B, procs int) {
+ c := make(chan bool)
+ var f func(n int)
+ f = func(n int) {
+ if n == 0 {
+ c <- true
+ return
+ }
+ go f(n - 1)
+ }
+ for i := 0; i < procs; i++ {
+ go f(b.N / procs)
+ }
+ for i := 0; i < procs; i++ {
+ <-c
+ }
+}
diff --git a/libgo/go/runtime/string_test.go b/libgo/go/runtime/string_test.go
new file mode 100644
index 00000000000..8f13f0f428b
--- /dev/null
+++ b/libgo/go/runtime/string_test.go
@@ -0,0 +1,45 @@
+package runtime_test
+
+import (
+ "testing"
+)
+
+func BenchmarkCompareStringEqual(b *testing.B) {
+ bytes := []byte("Hello Gophers!")
+ s1, s2 := string(bytes), string(bytes)
+ for i := 0; i < b.N; i++ {
+ if s1 != s2 {
+ b.Fatal("s1 != s2")
+ }
+ }
+}
+
+func BenchmarkCompareStringIdentical(b *testing.B) {
+ s1 := "Hello Gophers!"
+ s2 := s1
+ for i := 0; i < b.N; i++ {
+ if s1 != s2 {
+ b.Fatal("s1 != s2")
+ }
+ }
+}
+
+func BenchmarkCompareStringSameLength(b *testing.B) {
+ s1 := "Hello Gophers!"
+ s2 := "Hello, Gophers"
+ for i := 0; i < b.N; i++ {
+ if s1 == s2 {
+ b.Fatal("s1 == s2")
+ }
+ }
+}
+
+func BenchmarkCompareStringDifferentLength(b *testing.B) {
+ s1 := "Hello Gophers!"
+ s2 := "Hello, Gophers!"
+ for i := 0; i < b.N; i++ {
+ if s1 == s2 {
+ b.Fatal("s1 == s2")
+ }
+ }
+}
diff --git a/libgo/go/runtime/vlop_arm_test.go b/libgo/go/runtime/vlop_arm_test.go
new file mode 100644
index 00000000000..f672f1a0de3
--- /dev/null
+++ b/libgo/go/runtime/vlop_arm_test.go
@@ -0,0 +1,70 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import "testing"
+
+// arm soft division benchmarks adapted from
+// http://ridiculousfish.com/files/division_benchmarks.tar.gz
+
+const numeratorsSize = 1 << 21
+
+var numerators = randomNumerators()
+
+type randstate struct {
+ hi, lo uint32
+}
+
+func (r *randstate) rand() uint32 {
+ r.hi = r.hi<<16 + r.hi>>16
+ r.hi += r.lo
+ r.lo += r.hi
+ return r.hi
+}
+
+func randomNumerators() []uint32 {
+ numerators := make([]uint32, numeratorsSize)
+ random := &randstate{2147483563, 2147483563 ^ 0x49616E42}
+ for i := range numerators {
+ numerators[i] = random.rand()
+ }
+ return numerators
+}
+
+func bmUint32Div(divisor uint32, b *testing.B) {
+ var sum uint32
+ for i := 0; i < b.N; i++ {
+ sum += numerators[i&(numeratorsSize-1)] / divisor
+ }
+}
+
+func BenchmarkUint32Div7(b *testing.B) { bmUint32Div(7, b) }
+func BenchmarkUint32Div37(b *testing.B) { bmUint32Div(37, b) }
+func BenchmarkUint32Div123(b *testing.B) { bmUint32Div(123, b) }
+func BenchmarkUint32Div763(b *testing.B) { bmUint32Div(763, b) }
+func BenchmarkUint32Div1247(b *testing.B) { bmUint32Div(1247, b) }
+func BenchmarkUint32Div9305(b *testing.B) { bmUint32Div(9305, b) }
+func BenchmarkUint32Div13307(b *testing.B) { bmUint32Div(13307, b) }
+func BenchmarkUint32Div52513(b *testing.B) { bmUint32Div(52513, b) }
+func BenchmarkUint32Div60978747(b *testing.B) { bmUint32Div(60978747, b) }
+func BenchmarkUint32Div106956295(b *testing.B) { bmUint32Div(106956295, b) }
+
+func bmUint32Mod(divisor uint32, b *testing.B) {
+ var sum uint32
+ for i := 0; i < b.N; i++ {
+ sum += numerators[i&(numeratorsSize-1)] % divisor
+ }
+}
+
+func BenchmarkUint32Mod7(b *testing.B) { bmUint32Mod(7, b) }
+func BenchmarkUint32Mod37(b *testing.B) { bmUint32Mod(37, b) }
+func BenchmarkUint32Mod123(b *testing.B) { bmUint32Mod(123, b) }
+func BenchmarkUint32Mod763(b *testing.B) { bmUint32Mod(763, b) }
+func BenchmarkUint32Mod1247(b *testing.B) { bmUint32Mod(1247, b) }
+func BenchmarkUint32Mod9305(b *testing.B) { bmUint32Mod(9305, b) }
+func BenchmarkUint32Mod13307(b *testing.B) { bmUint32Mod(13307, b) }
+func BenchmarkUint32Mod52513(b *testing.B) { bmUint32Mod(52513, b) }
+func BenchmarkUint32Mod60978747(b *testing.B) { bmUint32Mod(60978747, b) }
+func BenchmarkUint32Mod106956295(b *testing.B) { bmUint32Mod(106956295, b) }
diff --git a/libgo/go/strconv/atof.go b/libgo/go/strconv/atof.go
index d99117bed1d..c9e243aa06d 100644
--- a/libgo/go/strconv/atof.go
+++ b/libgo/go/strconv/atof.go
@@ -38,17 +38,28 @@ func equalIgnoreCase(s1, s2 string) bool {
}
func special(s string) (f float64, ok bool) {
- switch {
- case equalIgnoreCase(s, "nan"):
- return math.NaN(), true
- case equalIgnoreCase(s, "-inf"),
- equalIgnoreCase(s, "-infinity"):
- return math.Inf(-1), true
- case equalIgnoreCase(s, "+inf"),
- equalIgnoreCase(s, "+infinity"),
- equalIgnoreCase(s, "inf"),
- equalIgnoreCase(s, "infinity"):
- return math.Inf(1), true
+ if len(s) == 0 {
+ return
+ }
+ switch s[0] {
+ default:
+ return
+ case '+':
+ if equalIgnoreCase(s, "+inf") || equalIgnoreCase(s, "+infinity") {
+ return math.Inf(1), true
+ }
+ case '-':
+ if equalIgnoreCase(s, "-inf") || equalIgnoreCase(s, "-infinity") {
+ return math.Inf(-1), true
+ }
+ case 'n', 'N':
+ if equalIgnoreCase(s, "nan") {
+ return math.NaN(), true
+ }
+ case 'i', 'I':
+ if equalIgnoreCase(s, "inf") || equalIgnoreCase(s, "infinity") {
+ return math.Inf(1), true
+ }
}
return
}
@@ -143,6 +154,105 @@ func (b *decimal) set(s string) (ok bool) {
return
}
+// readFloat reads a decimal mantissa and exponent from a float
+// string representation. It sets ok to false if the number could
+// not fit return types or is invalid.
+func readFloat(s string) (mantissa uint64, exp int, neg, trunc, ok bool) {
+ const uint64digits = 19
+ i := 0
+
+ // optional sign
+ if i >= len(s) {
+ return
+ }
+ switch {
+ case s[i] == '+':
+ i++
+ case s[i] == '-':
+ neg = true
+ i++
+ }
+
+ // digits
+ sawdot := false
+ sawdigits := false
+ nd := 0
+ ndMant := 0
+ dp := 0
+ for ; i < len(s); i++ {
+ switch c := s[i]; true {
+ case c == '.':
+ if sawdot {
+ return
+ }
+ sawdot = true
+ dp = nd
+ continue
+
+ case '0' <= c && c <= '9':
+ sawdigits = true
+ if c == '0' && nd == 0 { // ignore leading zeros
+ dp--
+ continue
+ }
+ nd++
+ if ndMant < uint64digits {
+ mantissa *= 10
+ mantissa += uint64(c - '0')
+ ndMant++
+ } else if s[i] != '0' {
+ trunc = true
+ }
+ continue
+ }
+ break
+ }
+ if !sawdigits {
+ return
+ }
+ if !sawdot {
+ dp = nd
+ }
+
+ // optional exponent moves decimal point.
+ // if we read a very large, very long number,
+ // just be sure to move the decimal point by
+ // a lot (say, 100000). it doesn't matter if it's
+ // not the exact number.
+ if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
+ i++
+ if i >= len(s) {
+ return
+ }
+ esign := 1
+ if s[i] == '+' {
+ i++
+ } else if s[i] == '-' {
+ i++
+ esign = -1
+ }
+ if i >= len(s) || s[i] < '0' || s[i] > '9' {
+ return
+ }
+ e := 0
+ for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
+ if e < 10000 {
+ e = e*10 + int(s[i]) - '0'
+ }
+ }
+ dp += e * esign
+ }
+
+ if i != len(s) {
+ return
+ }
+
+ exp = dp - ndMant
+ ok = true
+ return
+
+}
+
// decimal power of ten to binary power of two.
var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26}
@@ -244,19 +354,6 @@ out:
return bits, overflow
}
-// Compute exact floating-point integer from d's digits.
-// Caller is responsible for avoiding overflow.
-func (d *decimal) atof64int() float64 {
- f := 0.0
- for i := 0; i < d.nd; i++ {
- f = f*10 + float64(d.d[i]-'0')
- }
- if d.neg {
- f = -f
- }
- return f
-}
-
func (d *decimal) atof32int() float32 {
f := float32(0)
for i := 0; i < d.nd; i++ {
@@ -268,18 +365,6 @@ func (d *decimal) atof32int() float32 {
return f
}
-// Reads a uint64 decimal mantissa, which might be truncated.
-func (d *decimal) atou64() (mant uint64, digits int) {
- const uint64digits = 19
- for i, c := range d.d[:d.nd] {
- if i == uint64digits {
- return mant, i
- }
- mant = 10*mant + uint64(c-'0')
- }
- return mant, d.nd
-}
-
// Exact powers of 10.
var float64pow10 = []float64{
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
@@ -288,17 +373,15 @@ var float64pow10 = []float64{
}
var float32pow10 = []float32{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10}
-// If possible to convert decimal d to 64-bit float f exactly,
+// If possible to convert decimal representation to 64-bit float f exactly,
// entirely in floating-point math, do so, avoiding the expense of decimalToFloatBits.
// Three common cases:
// value is exact integer
// value is exact integer * exact power of ten
// value is exact integer / exact power of ten
// These all produce potentially inexact but correctly rounded answers.
-func (d *decimal) atof64() (f float64, ok bool) {
- // Exact integers are <= 10^15.
- // Exact powers of ten are <= 10^22.
- if d.nd > 15 {
+func atof64exact(mantissa uint64, exp int, neg bool) (f float64, ok bool) {
+ if mantissa>>float64info.mantbits != 0 {
return
}
// gccgo gets this wrong on 32-bit i386 when not using -msse.
@@ -306,56 +389,63 @@ func (d *decimal) atof64() (f float64, ok bool) {
if runtime.GOARCH == "386" {
return
}
+ f = float64(mantissa)
+ if neg {
+ f = -f
+ }
switch {
- case d.dp == d.nd: // int
- f := d.atof64int()
+ case exp == 0:
+ // an integer.
return f, true
-
- case d.dp > d.nd && d.dp <= 15+22: // int * 10^k
- f := d.atof64int()
- k := d.dp - d.nd
+ // Exact integers are <= 10^15.
+ // Exact powers of ten are <= 10^22.
+ case exp > 0 && exp <= 15+22: // int * 10^k
// If exponent is big but number of digits is not,
// can move a few zeros into the integer part.
- if k > 22 {
- f *= float64pow10[k-22]
- k = 22
+ if exp > 22 {
+ f *= float64pow10[exp-22]
+ exp = 22
}
- return f * float64pow10[k], true
-
- case d.dp < d.nd && d.nd-d.dp <= 22: // int / 10^k
- f := d.atof64int()
- return f / float64pow10[d.nd-d.dp], true
+ if f > 1e15 || f < -1e15 {
+ // the exponent was really too large.
+ return
+ }
+ return f * float64pow10[exp], true
+ case exp < 0 && exp >= -22: // int / 10^k
+ return f / float64pow10[-exp], true
}
return
}
-// If possible to convert decimal d to 32-bit float f exactly,
+// If possible to compute mantissa*10^exp to 32-bit float f exactly,
// entirely in floating-point math, do so, avoiding the machinery above.
-func (d *decimal) atof32() (f float32, ok bool) {
- // Exact integers are <= 10^7.
- // Exact powers of ten are <= 10^10.
- if d.nd > 7 {
+func atof32exact(mantissa uint64, exp int, neg bool) (f float32, ok bool) {
+ if mantissa>>float32info.mantbits != 0 {
return
}
+ f = float32(mantissa)
+ if neg {
+ f = -f
+ }
switch {
- case d.dp == d.nd: // int
- f := d.atof32int()
+ case exp == 0:
return f, true
-
- case d.dp > d.nd && d.dp <= 7+10: // int * 10^k
- f := d.atof32int()
- k := d.dp - d.nd
+ // Exact integers are <= 10^7.
+ // Exact powers of ten are <= 10^10.
+ case exp > 0 && exp <= 7+10: // int * 10^k
// If exponent is big but number of digits is not,
// can move a few zeros into the integer part.
- if k > 10 {
- f *= float32pow10[k-10]
- k = 10
+ if exp > 10 {
+ f *= float32pow10[exp-10]
+ exp = 10
}
- return f * float32pow10[k], true
-
- case d.dp < d.nd && d.nd-d.dp <= 10: // int / 10^k
- f := d.atof32int()
- return f / float32pow10[d.nd-d.dp], true
+ if f > 1e7 || f < -1e7 {
+ // the exponent was really too large.
+ return
+ }
+ return f * float32pow10[exp], true
+ case exp < 0 && exp >= -10: // int / 10^k
+ return f / float32pow10[-exp], true
}
return
}
@@ -367,15 +457,32 @@ func atof32(s string) (f float32, err error) {
return float32(val), nil
}
+ if optimize {
+ // Parse mantissa and exponent.
+ mantissa, exp, neg, trunc, ok := readFloat(s)
+ if ok {
+ // Try pure floating-point arithmetic conversion.
+ if !trunc {
+ if f, ok := atof32exact(mantissa, exp, neg); ok {
+ return f, nil
+ }
+ }
+ // Try another fast path.
+ ext := new(extFloat)
+ if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float32info); ok {
+ b, ovf := ext.floatBits(&float32info)
+ f = math.Float32frombits(uint32(b))
+ if ovf {
+ err = rangeError(fnParseFloat, s)
+ }
+ return f, err
+ }
+ }
+ }
var d decimal
if !d.set(s) {
return 0, syntaxError(fnParseFloat, s)
}
- if optimize {
- if f, ok := d.atof32(); ok {
- return f, nil
- }
- }
b, ovf := d.floatBits(&float32info)
f = math.Float32frombits(uint32(b))
if ovf {
@@ -389,26 +496,32 @@ func atof64(s string) (f float64, err error) {
return val, nil
}
- var d decimal
- if !d.set(s) {
- return 0, syntaxError(fnParseFloat, s)
- }
if optimize {
- if f, ok := d.atof64(); ok {
- return f, nil
- }
-
- // Try another fast path.
- ext := new(extFloat)
- if ok := ext.AssignDecimal(&d); ok {
- b, ovf := ext.floatBits()
- f = math.Float64frombits(b)
- if ovf {
- err = rangeError(fnParseFloat, s)
+ // Parse mantissa and exponent.
+ mantissa, exp, neg, trunc, ok := readFloat(s)
+ if ok {
+ // Try pure floating-point arithmetic conversion.
+ if !trunc {
+ if f, ok := atof64exact(mantissa, exp, neg); ok {
+ return f, nil
+ }
+ }
+ // Try another fast path.
+ ext := new(extFloat)
+ if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float64info); ok {
+ b, ovf := ext.floatBits(&float64info)
+ f = math.Float64frombits(b)
+ if ovf {
+ err = rangeError(fnParseFloat, s)
+ }
+ return f, err
}
- return f, err
}
}
+ var d decimal
+ if !d.set(s) {
+ return 0, syntaxError(fnParseFloat, s)
+ }
b, ovf := d.floatBits(&float64info)
f = math.Float64frombits(b)
if ovf {
diff --git a/libgo/go/strconv/atof_test.go b/libgo/go/strconv/atof_test.go
index 59950238230..b4f3a6f08f9 100644
--- a/libgo/go/strconv/atof_test.go
+++ b/libgo/go/strconv/atof_test.go
@@ -134,6 +134,54 @@ var atoftests = []atofTest{
{"1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1", "1.0000000000000002", nil},
}
+var atof32tests = []atofTest{
+ // Exactly halfway between 1 and the next float32.
+ // Round to even (down).
+ {"1.000000059604644775390625", "1", nil},
+ // Slightly lower.
+ {"1.000000059604644775390624", "1", nil},
+ // Slightly higher.
+ {"1.000000059604644775390626", "1.0000001", nil},
+ // Slightly higher, but you have to read all the way to the end.
+ {"1.000000059604644775390625" + strings.Repeat("0", 10000) + "1", "1.0000001", nil},
+
+ // largest float32: (1<<128) * (1 - 2^-24)
+ {"340282346638528859811704183484516925440", "3.4028235e+38", nil},
+ {"-340282346638528859811704183484516925440", "-3.4028235e+38", nil},
+ // next float32 - too large
+ {"3.4028236e38", "+Inf", ErrRange},
+ {"-3.4028236e38", "-Inf", ErrRange},
+ // the border is 3.40282356779...e+38
+ // borderline - okay
+ {"3.402823567e38", "3.4028235e+38", nil},
+ {"-3.402823567e38", "-3.4028235e+38", nil},
+ // borderline - too large
+ {"3.4028235678e38", "+Inf", ErrRange},
+ {"-3.4028235678e38", "-Inf", ErrRange},
+
+ // Denormals: less than 2^-126
+ {"1e-38", "1e-38", nil},
+ {"1e-39", "1e-39", nil},
+ {"1e-40", "1e-40", nil},
+ {"1e-41", "1e-41", nil},
+ {"1e-42", "1e-42", nil},
+ {"1e-43", "1e-43", nil},
+ {"1e-44", "1e-44", nil},
+ {"6e-45", "6e-45", nil}, // 4p-149 = 5.6e-45
+ {"5e-45", "6e-45", nil},
+ // Smallest denormal
+ {"1e-45", "1e-45", nil}, // 1p-149 = 1.4e-45
+ {"2e-45", "1e-45", nil},
+
+ // 2^92 = 8388608p+69 = 4951760157141521099596496896 (4.9517602e27)
+ // is an exact power of two that needs 8 decimal digits to be correctly
+ // parsed back.
+ // The float32 before is 16777215p+68 = 4.95175986e+27
+ // The halfway is 4.951760009. A bad algorithm that thinks the previous
+ // float32 is 8388607p+69 will shorten incorrectly to 4.95176e+27.
+ {"4951760157141521099596496896", "4.9517602e+27", nil},
+}
+
type atofSimpleTest struct {
x float64
s string
@@ -154,6 +202,12 @@ func init() {
test.err = &NumError{"ParseFloat", test.in, test.err}
}
}
+ for i := range atof32tests {
+ test := &atof32tests[i]
+ if test.err != nil {
+ test.err = &NumError{"ParseFloat", test.in, test.err}
+ }
+ }
// Generate random inputs for tests and benchmarks
rand.Seed(time.Now().UnixNano())
@@ -206,6 +260,19 @@ func testAtof(t *testing.T, opt bool) {
}
}
}
+ for _, test := range atof32tests {
+ out, err := ParseFloat(test.in, 32)
+ out32 := float32(out)
+ if float64(out32) != out {
+ t.Errorf("ParseFloat(%v, 32) = %v, not a float32 (closest is %v)", test.in, out, float64(out32))
+ continue
+ }
+ outs := FormatFloat(float64(out32), 'g', -1, 32)
+ if outs != test.out || !reflect.DeepEqual(err, test.err) {
+ t.Errorf("ParseFloat(%v, 32) = %v, %v want %v, %v # %v",
+ test.in, out32, err, test.out, test.err, out)
+ }
+ }
SetOptimize(oldopt)
}
@@ -264,6 +331,35 @@ func TestRoundTrip(t *testing.T) {
}
}
+// TestRoundTrip32 tries a fraction of all finite positive float32 values.
+func TestRoundTrip32(t *testing.T) {
+ step := uint32(997)
+ if testing.Short() {
+ step = 99991
+ }
+ count := 0
+ for i := uint32(0); i < 0xff<<23; i += step {
+ f := math.Float32frombits(i)
+ if i&1 == 1 {
+ f = -f // negative
+ }
+ s := FormatFloat(float64(f), 'g', -1, 32)
+
+ parsed, err := ParseFloat(s, 32)
+ parsed32 := float32(parsed)
+ switch {
+ case err != nil:
+ t.Errorf("ParseFloat(%q, 32) gave error %s", s, err)
+ case float64(parsed32) != parsed:
+ t.Errorf("ParseFloat(%q, 32) = %v, not a float32 (nearest is %v)", s, parsed, parsed32)
+ case parsed32 != f:
+ t.Errorf("ParseFloat(%q, 32) = %b (expected %b)", s, parsed32, f)
+ }
+ count++
+ }
+ t.Logf("tested %d float32's", count)
+}
+
func BenchmarkAtof64Decimal(b *testing.B) {
for i := 0; i < b.N; i++ {
ParseFloat("33909", 64)
@@ -299,3 +395,35 @@ func BenchmarkAtof64RandomFloats(b *testing.B) {
ParseFloat(benchmarksRandomNormal[i%1024], 64)
}
}
+
+func BenchmarkAtof32Decimal(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ParseFloat("33909", 32)
+ }
+}
+
+func BenchmarkAtof32Float(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ParseFloat("339.778", 32)
+ }
+}
+
+func BenchmarkAtof32FloatExp(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ParseFloat("12.3456e32", 32)
+ }
+}
+
+var float32strings [4096]string
+
+func BenchmarkAtof32Random(b *testing.B) {
+ n := uint32(997)
+ for i := range float32strings {
+ n = (99991*n + 42) % (0xff << 23)
+ float32strings[i] = FormatFloat(float64(math.Float32frombits(n)), 'g', -1, 32)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ ParseFloat(float32strings[i%4096], 32)
+ }
+}
diff --git a/libgo/go/strconv/decimal.go b/libgo/go/strconv/decimal.go
index a75071dcc46..42601283d23 100644
--- a/libgo/go/strconv/decimal.go
+++ b/libgo/go/strconv/decimal.go
@@ -79,7 +79,7 @@ func trim(a *decimal) {
// Assign v to a.
func (a *decimal) Assign(v uint64) {
- var buf [50]byte
+ var buf [24]byte
// Write reversed decimal in buf.
n := 0
diff --git a/libgo/go/strconv/extfloat.go b/libgo/go/strconv/extfloat.go
index aa5e5607ca0..6c352019401 100644
--- a/libgo/go/strconv/extfloat.go
+++ b/libgo/go/strconv/extfloat.go
@@ -4,8 +4,6 @@
package strconv
-import "math"
-
// An extFloat represents an extended floating-point number, with more
// precision than a float64. It does not try to save bits: the
// number represented by the structure is mant*(2^exp), with a negative
@@ -127,8 +125,7 @@ var powersOfTen = [...]extFloat{
// floatBits returns the bits of the float64 that best approximates
// the extFloat passed as receiver. Overflow is set to true if
// the resulting float64 is ±Inf.
-func (f *extFloat) floatBits() (bits uint64, overflow bool) {
- flt := &float64info
+func (f *extFloat) floatBits(flt *floatInfo) (bits uint64, overflow bool) {
f.Normalize()
exp := f.exp + 63
@@ -140,7 +137,7 @@ func (f *extFloat) floatBits() (bits uint64, overflow bool) {
exp += n
}
- // Extract 1+flt.mantbits bits.
+ // Extract 1+flt.mantbits bits from the 64-bit mantissa.
mant := f.mant >> (63 - flt.mantbits)
if f.mant&(1<<(62-flt.mantbits)) != 0 {
// Round up.
@@ -180,40 +177,24 @@ out:
return
}
-// Assign sets f to the value of x.
-func (f *extFloat) Assign(x float64) {
- if x < 0 {
- x = -x
- f.neg = true
- }
- x, f.exp = math.Frexp(x)
- f.mant = uint64(x * float64(1<<64))
- f.exp -= 64
-}
-
-// AssignComputeBounds sets f to the value of x and returns
+// AssignComputeBounds sets f to the floating point value
+// defined by mant, exp and precision given by flt. It returns
// lower, upper such that any number in the closed interval
-// [lower, upper] is converted back to x.
-func (f *extFloat) AssignComputeBounds(x float64) (lower, upper extFloat) {
- // Special cases.
- bits := math.Float64bits(x)
- flt := &float64info
- neg := bits>>(flt.expbits+flt.mantbits) != 0
- expBiased := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
- mant := bits & (uint64(1)<<flt.mantbits - 1)
-
- if expBiased == 0 {
- // denormalized.
- f.mant = mant
- f.exp = 1 + flt.bias - int(flt.mantbits)
- } else {
- f.mant = mant | 1<<flt.mantbits
- f.exp = expBiased + flt.bias - int(flt.mantbits)
- }
+// [lower, upper] is converted back to the same floating point number.
+func (f *extFloat) AssignComputeBounds(mant uint64, exp int, neg bool, flt *floatInfo) (lower, upper extFloat) {
+ f.mant = mant
+ f.exp = exp - int(flt.mantbits)
f.neg = neg
+ if f.exp <= 0 && mant == (mant>>uint(-f.exp))<<uint(-f.exp) {
+ // An exact integer
+ f.mant >>= uint(-f.exp)
+ f.exp = 0
+ return *f, *f
+ }
+ expBiased := exp - flt.bias
upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg}
- if mant != 0 || expBiased == 1 {
+ if mant != 1<<flt.mantbits || expBiased == 1 {
lower = extFloat{mant: 2*f.mant - 1, exp: f.exp - 1, neg: f.neg}
} else {
lower = extFloat{mant: 4*f.mant - 1, exp: f.exp - 2, neg: f.neg}
@@ -223,20 +204,38 @@ func (f *extFloat) AssignComputeBounds(x float64) (lower, upper extFloat) {
// Normalize normalizes f so that the highest bit of the mantissa is
// set, and returns the number by which the mantissa was left-shifted.
-func (f *extFloat) Normalize() uint {
- if f.mant == 0 {
+func (f *extFloat) Normalize() (shift uint) {
+ mant, exp := f.mant, f.exp
+ if mant == 0 {
return 0
}
- exp_before := f.exp
- for f.mant < (1 << 55) {
- f.mant <<= 8
- f.exp -= 8
+ if mant>>(64-32) == 0 {
+ mant <<= 32
+ exp -= 32
}
- for f.mant < (1 << 63) {
- f.mant <<= 1
- f.exp -= 1
+ if mant>>(64-16) == 0 {
+ mant <<= 16
+ exp -= 16
}
- return uint(exp_before - f.exp)
+ if mant>>(64-8) == 0 {
+ mant <<= 8
+ exp -= 8
+ }
+ if mant>>(64-4) == 0 {
+ mant <<= 4
+ exp -= 4
+ }
+ if mant>>(64-2) == 0 {
+ mant <<= 2
+ exp -= 2
+ }
+ if mant>>(64-1) == 0 {
+ mant <<= 1
+ exp -= 1
+ }
+ shift = uint(f.exp - exp)
+ f.mant, f.exp = mant, exp
+ return
}
// Multiply sets f to the product f*g: the result is correctly rounded,
@@ -264,24 +263,22 @@ var uint64pow10 = [...]uint64{
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
}
-// AssignDecimal sets f to an approximate value of the decimal d. It
+// AssignDecimal sets f to an approximate value mantissa*10^exp. It
// returns true if the value represented by f is guaranteed to be the
-// best approximation of d after being rounded to a float64.
-func (f *extFloat) AssignDecimal(d *decimal) (ok bool) {
+// best approximation of d after being rounded to a float64 or
+// float32 depending on flt.
+func (f *extFloat) AssignDecimal(mantissa uint64, exp10 int, neg bool, trunc bool, flt *floatInfo) (ok bool) {
const uint64digits = 19
const errorscale = 8
- mant10, digits := d.atou64()
- exp10 := d.dp - digits
errors := 0 // An upper bound for error, computed in errorscale*ulp.
-
- if digits < d.nd {
+ if trunc {
// the decimal number was truncated.
errors += errorscale / 2
}
- f.mant = mant10
+ f.mant = mantissa
f.exp = 0
- f.neg = d.neg
+ f.neg = neg
// Multiply by powers of ten.
i := (exp10 - firstPowerOfTen) / stepPowerOfTen
@@ -291,9 +288,9 @@ func (f *extFloat) AssignDecimal(d *decimal) (ok bool) {
adjExp := (exp10 - firstPowerOfTen) % stepPowerOfTen
// We multiply by exp%step
- if digits+adjExp <= uint64digits {
- // We can multiply the mantissa
- f.mant *= uint64(float64pow10[adjExp])
+ if adjExp < uint64digits && mantissa < uint64pow10[uint64digits-adjExp] {
+ // We can multiply the mantissa exactly.
+ f.mant *= uint64pow10[adjExp]
f.Normalize()
} else {
f.Normalize()
@@ -318,10 +315,10 @@ func (f *extFloat) AssignDecimal(d *decimal) (ok bool) {
// The 64 bits mantissa is 1 + 52 bits for float64 + 11 extra bits.
//
// In many cases the approximation will be good enough.
- const denormalExp = -1023 - 63
- flt := &float64info
+ denormalExp := flt.bias - 63
var extrabits uint
if f.exp <= denormalExp {
+ // f.mant * 2^f.exp is smaller than 2^(flt.bias+1).
extrabits = uint(63 - flt.mantbits + 1 + uint(denormalExp-f.exp))
} else {
extrabits = uint(63 - flt.mantbits)
@@ -344,16 +341,17 @@ func (f *extFloat) AssignDecimal(d *decimal) (ok bool) {
// f by an approximate power of ten 10^-exp, and returns exp10, so
// that f*10^exp10 has the same value as the old f, up to an ulp,
// as well as the index of 10^-exp in the powersOfTen table.
-// The arguments expMin and expMax constrain the final value of the
-// binary exponent of f.
-func (f *extFloat) frexp10(expMin, expMax int) (exp10, index int) {
- // it is illegal to call this function with a too restrictive exponent range.
- if expMax-expMin <= 25 {
- panic("strconv: invalid exponent range")
- }
+func (f *extFloat) frexp10() (exp10, index int) {
+ // The constants expMin and expMax constrain the final value of the
+ // binary exponent of f. We want a small integral part in the result
+ // because finding digits of an integer requires divisions, whereas
+ // digits of the fractional part can be found by repeatedly multiplying
+ // by 10.
+ const expMin = -60
+ const expMax = -32
// Find power of ten such that x * 10^n has a binary exponent
- // between expMin and expMax
- approxExp10 := -(f.exp + 100) * 28 / 93 // log(10)/log(2) is close to 93/28.
+ // between expMin and expMax.
+ approxExp10 := ((expMin+expMax)/2 - f.exp) * 28 / 93 // log(10)/log(2) is close to 93/28.
i := (approxExp10 - firstPowerOfTen) / stepPowerOfTen
Loop:
for {
@@ -375,26 +373,202 @@ Loop:
}
// frexp10Many applies a common shift by a power of ten to a, b, c.
-func frexp10Many(expMin, expMax int, a, b, c *extFloat) (exp10 int) {
- exp10, i := c.frexp10(expMin, expMax)
+func frexp10Many(a, b, c *extFloat) (exp10 int) {
+ exp10, i := c.frexp10()
a.Multiply(powersOfTen[i])
b.Multiply(powersOfTen[i])
return
}
+// FixedDecimal stores in d the first n significant digits
+// of the decimal representation of f. It returns false
+// if it cannot be sure of the answer.
+func (f *extFloat) FixedDecimal(d *decimalSlice, n int) bool {
+ if f.mant == 0 {
+ d.nd = 0
+ d.dp = 0
+ d.neg = f.neg
+ return true
+ }
+ if n == 0 {
+ panic("strconv: internal error: extFloat.FixedDecimal called with n == 0")
+ }
+ // Multiply by an appropriate power of ten to have a reasonable
+ // number to process.
+ f.Normalize()
+ exp10, _ := f.frexp10()
+
+ shift := uint(-f.exp)
+ integer := uint32(f.mant >> shift)
+ fraction := f.mant - (uint64(integer) << shift)
+ ε := uint64(1) // ε is the uncertainty we have on the mantissa of f.
+
+ // Write exactly n digits to d.
+ needed := n // how many digits are left to write.
+ integerDigits := 0 // the number of decimal digits of integer.
+ pow10 := uint64(1) // the power of ten by which f was scaled.
+ for i, pow := 0, uint64(1); i < 20; i++ {
+ if pow > uint64(integer) {
+ integerDigits = i
+ break
+ }
+ pow *= 10
+ }
+ rest := integer
+ if integerDigits > needed {
+ // the integral part is already large, trim the last digits.
+ pow10 = uint64pow10[integerDigits-needed]
+ integer /= uint32(pow10)
+ rest -= integer * uint32(pow10)
+ } else {
+ rest = 0
+ }
+
+ // Write the digits of integer: the digits of rest are omitted.
+ var buf [32]byte
+ pos := len(buf)
+ for v := integer; v > 0; {
+ v1 := v / 10
+ v -= 10 * v1
+ pos--
+ buf[pos] = byte(v + '0')
+ v = v1
+ }
+ for i := pos; i < len(buf); i++ {
+ d.d[i-pos] = buf[i]
+ }
+ nd := len(buf) - pos
+ d.nd = nd
+ d.dp = integerDigits + exp10
+ needed -= nd
+
+ if needed > 0 {
+ if rest != 0 || pow10 != 1 {
+ panic("strconv: internal error, rest != 0 but needed > 0")
+ }
+ // Emit digits for the fractional part. Each time, 10*fraction
+ // fits in a uint64 without overflow.
+ for needed > 0 {
+ fraction *= 10
+ ε *= 10 // the uncertainty scales as we multiply by ten.
+ if 2*ε > 1<<shift {
+ // the error is so large it could modify which digit to write, abort.
+ return false
+ }
+ digit := fraction >> shift
+ d.d[nd] = byte(digit + '0')
+ fraction -= digit << shift
+ nd++
+ needed--
+ }
+ d.nd = nd
+ }
+
+ // We have written a truncation of f (a numerator / 10^d.dp). The remaining part
+ // can be interpreted as a small number (< 1) to be added to the last digit of the
+ // numerator.
+ //
+ // If rest > 0, the amount is:
+ // (rest<<shift | fraction) / (pow10 << shift)
+ // fraction being known with a ±ε uncertainty.
+ // The fact that n > 0 guarantees that pow10 << shift does not overflow a uint64.
+ //
+ // If rest = 0, pow10 == 1 and the amount is
+ // fraction / (1 << shift)
+ // fraction being known with a ±ε uncertainty.
+ //
+ // We pass this information to the rounding routine for adjustment.
+
+ ok := adjustLastDigitFixed(d, uint64(rest)<<shift|fraction, pow10, shift, ε)
+ if !ok {
+ return false
+ }
+ // Trim trailing zeros.
+ for i := d.nd - 1; i >= 0; i-- {
+ if d.d[i] != '0' {
+ d.nd = i + 1
+ break
+ }
+ }
+ return true
+}
+
+// adjustLastDigitFixed assumes d contains the representation of the integral part
+// of some number, whose fractional part is num / (den << shift). The numerator
+// num is only known up to an uncertainty of size ε, assumed to be less than
+// (den << shift)/2.
+//
+// It will increase the last digit by one to account for correct rounding, typically
+// when the fractional part is greater than 1/2, and will return false if ε is such
+// that no correct answer can be given.
+func adjustLastDigitFixed(d *decimalSlice, num, den uint64, shift uint, ε uint64) bool {
+ if num > den<<shift {
+ panic("strconv: num > den<<shift in adjustLastDigitFixed")
+ }
+ if 2*ε > den<<shift {
+ panic("strconv: ε > (den<<shift)/2")
+ }
+ if 2*(num+ε) < den<<shift {
+ return true
+ }
+ if 2*(num-ε) > den<<shift {
+ // increment d by 1.
+ i := d.nd - 1
+ for ; i >= 0; i-- {
+ if d.d[i] == '9' {
+ d.nd--
+ } else {
+ break
+ }
+ }
+ if i < 0 {
+ d.d[0] = '1'
+ d.nd = 1
+ d.dp++
+ } else {
+ d.d[i]++
+ }
+ return true
+ }
+ return false
+}
+
// ShortestDecimal stores in d the shortest decimal representation of f
// which belongs to the open interval (lower, upper), where f is supposed
// to lie. It returns false whenever the result is unsure. The implementation
// uses the Grisu3 algorithm.
-func (f *extFloat) ShortestDecimal(d *decimal, lower, upper *extFloat) bool {
+func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool {
if f.mant == 0 {
- d.d[0] = '0'
- d.nd = 1
+ d.nd = 0
d.dp = 0
d.neg = f.neg
+ return true
+ }
+ if f.exp == 0 && *lower == *f && *lower == *upper {
+ // an exact integer.
+ var buf [24]byte
+ n := len(buf) - 1
+ for v := f.mant; v > 0; {
+ v1 := v / 10
+ v -= 10 * v1
+ buf[n] = byte(v + '0')
+ n--
+ v = v1
+ }
+ nd := len(buf) - n - 1
+ for i := 0; i < nd; i++ {
+ d.d[i] = buf[n+1+i]
+ }
+ d.nd, d.dp = nd, nd
+ for d.nd > 0 && d.d[d.nd-1] == '0' {
+ d.nd--
+ }
+ if d.nd == 0 {
+ d.dp = 0
+ }
+ d.neg = f.neg
+ return true
}
- const minExp = -60
- const maxExp = -32
upper.Normalize()
// Uniformize exponents.
if f.exp > upper.exp {
@@ -406,7 +580,7 @@ func (f *extFloat) ShortestDecimal(d *decimal, lower, upper *extFloat) bool {
lower.exp = upper.exp
}
- exp10 := frexp10Many(minExp, maxExp, lower, f, upper)
+ exp10 := frexp10Many(lower, f, upper)
// Take a safety margin due to rounding in frexp10Many, but we lose precision.
upper.mant++
lower.mant--
@@ -424,10 +598,12 @@ func (f *extFloat) ShortestDecimal(d *decimal, lower, upper *extFloat) bool {
// Count integral digits: there are at most 10.
var integerDigits int
- for i, pow := range uint64pow10 {
- if uint64(integer) >= pow {
- integerDigits = i + 1
+ for i, pow := 0, uint64(1); i < 20; i++ {
+ if pow > uint64(integer) {
+ integerDigits = i
+ break
}
+ pow *= 10
}
for i := 0; i < integerDigits; i++ {
pow := uint64pow10[integerDigits-i-1]
@@ -475,7 +651,7 @@ func (f *extFloat) ShortestDecimal(d *decimal, lower, upper *extFloat) bool {
// d = x-targetDiff*ε, without becoming smaller than x-maxDiff*ε.
// It assumes that a decimal digit is worth ulpDecimal*ε, and that
// all data is known with a error estimate of ulpBinary*ε.
-func adjustLastDigit(d *decimal, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool {
+func adjustLastDigit(d *decimalSlice, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool {
if ulpDecimal < 2*ulpBinary {
// Approximation is too wide.
return false
diff --git a/libgo/go/strconv/ftoa.go b/libgo/go/strconv/ftoa.go
index 8eefbee79f2..8067881e0d1 100644
--- a/libgo/go/strconv/ftoa.go
+++ b/libgo/go/strconv/ftoa.go
@@ -98,42 +98,79 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
return fmtB(dst, neg, mant, exp, flt)
}
+ if !optimize {
+ return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
+ }
+
+ var digs decimalSlice
+ ok := false
// Negative precision means "only as much as needed to be exact."
shortest := prec < 0
-
- d := new(decimal)
if shortest {
- ok := false
- if optimize && bitSize == 64 {
- // Try Grisu3 algorithm.
- f := new(extFloat)
- lower, upper := f.AssignComputeBounds(val)
- ok = f.ShortestDecimal(d, &lower, &upper)
- }
+ // Try Grisu3 algorithm.
+ f := new(extFloat)
+ lower, upper := f.AssignComputeBounds(mant, exp, neg, flt)
+ var buf [32]byte
+ digs.d = buf[:]
+ ok = f.ShortestDecimal(&digs, &lower, &upper)
if !ok {
- // Create exact decimal representation.
- // The shift is exp - flt.mantbits because mant is a 1-bit integer
- // followed by a flt.mantbits fraction, and we are treating it as
- // a 1+flt.mantbits-bit integer.
- d.Assign(mant)
- d.Shift(exp - int(flt.mantbits))
- roundShortest(d, mant, exp, flt)
+ return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
}
// Precision for shortest representation mode.
- if prec < 0 {
- switch fmt {
- case 'e', 'E':
- prec = d.nd - 1
- case 'f':
- prec = max(d.nd-d.dp, 0)
- case 'g', 'G':
- prec = d.nd
+ switch fmt {
+ case 'e', 'E':
+ prec = digs.nd - 1
+ case 'f':
+ prec = max(digs.nd-digs.dp, 0)
+ case 'g', 'G':
+ prec = digs.nd
+ }
+ } else if fmt != 'f' {
+ // Fixed number of digits.
+ digits := prec
+ switch fmt {
+ case 'e', 'E':
+ digits++
+ case 'g', 'G':
+ if prec == 0 {
+ prec = 1
}
+ digits = prec
+ }
+ if digits <= 15 {
+ // try fast algorithm when the number of digits is reasonable.
+ var buf [24]byte
+ digs.d = buf[:]
+ f := extFloat{mant, exp - int(flt.mantbits), neg}
+ ok = f.FixedDecimal(&digs, digits)
+ }
+ }
+ if !ok {
+ return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
+ }
+ return formatDigits(dst, shortest, neg, digs, prec, fmt)
+}
+
+// bigFtoa uses multiprecision computations to format a float.
+func bigFtoa(dst []byte, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {
+ d := new(decimal)
+ d.Assign(mant)
+ d.Shift(exp - int(flt.mantbits))
+ var digs decimalSlice
+ shortest := prec < 0
+ if shortest {
+ roundShortest(d, mant, exp, flt)
+ digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
+ // Precision for shortest representation mode.
+ switch fmt {
+ case 'e', 'E':
+ prec = digs.nd - 1
+ case 'f':
+ prec = max(digs.nd-digs.dp, 0)
+ case 'g', 'G':
+ prec = digs.nd
}
} else {
- // Create exact decimal representation.
- d.Assign(mant)
- d.Shift(exp - int(flt.mantbits))
// Round appropriately.
switch fmt {
case 'e', 'E':
@@ -146,18 +183,22 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
}
d.Round(prec)
}
+ digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
}
+ return formatDigits(dst, shortest, neg, digs, prec, fmt)
+}
+func formatDigits(dst []byte, shortest bool, neg bool, digs decimalSlice, prec int, fmt byte) []byte {
switch fmt {
case 'e', 'E':
- return fmtE(dst, neg, d, prec, fmt)
+ return fmtE(dst, neg, digs, prec, fmt)
case 'f':
- return fmtF(dst, neg, d, prec)
+ return fmtF(dst, neg, digs, prec)
case 'g', 'G':
// trailing fractional zeros in 'e' form will be trimmed.
eprec := prec
- if eprec > d.nd && d.nd >= d.dp {
- eprec = d.nd
+ if eprec > digs.nd && digs.nd >= digs.dp {
+ eprec = digs.nd
}
// %e is used if the exponent from the conversion
// is less than -4 or greater than or equal to the precision.
@@ -165,17 +206,17 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
if shortest {
eprec = 6
}
- exp := d.dp - 1
+ exp := digs.dp - 1
if exp < -4 || exp >= eprec {
- if prec > d.nd {
- prec = d.nd
+ if prec > digs.nd {
+ prec = digs.nd
}
- return fmtE(dst, neg, d, prec-1, fmt+'e'-'g')
+ return fmtE(dst, neg, digs, prec-1, fmt+'e'-'g')
}
- if prec > d.dp {
- prec = d.nd
+ if prec > digs.dp {
+ prec = digs.nd
}
- return fmtF(dst, neg, d, max(prec-d.dp, 0))
+ return fmtF(dst, neg, digs, max(prec-digs.dp, 0))
}
// unknown format
@@ -283,8 +324,14 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
}
}
+type decimalSlice struct {
+ d []byte
+ nd, dp int
+ neg bool
+}
+
// %e: -d.ddddde±dd
-func fmtE(dst []byte, neg bool, d *decimal, prec int, fmt byte) []byte {
+func fmtE(dst []byte, neg bool, d decimalSlice, prec int, fmt byte) []byte {
// sign
if neg {
dst = append(dst, '-')
@@ -300,12 +347,15 @@ func fmtE(dst []byte, neg bool, d *decimal, prec int, fmt byte) []byte {
// .moredigits
if prec > 0 {
dst = append(dst, '.')
- for i := 1; i <= prec; i++ {
- ch = '0'
- if i < d.nd {
- ch = d.d[i]
- }
- dst = append(dst, ch)
+ i := 1
+ m := d.nd + prec + 1 - max(d.nd, prec+1)
+ for i < m {
+ dst = append(dst, d.d[i])
+ i++
+ }
+ for i <= prec {
+ dst = append(dst, '0')
+ i++
}
}
@@ -335,17 +385,20 @@ func fmtE(dst []byte, neg bool, d *decimal, prec int, fmt byte) []byte {
i--
buf[i] = byte(exp + '0')
- // leading zeroes
- if i > len(buf)-2 {
- i--
- buf[i] = '0'
+ switch i {
+ case 0:
+ dst = append(dst, buf[0], buf[1], buf[2])
+ case 1:
+ dst = append(dst, buf[1], buf[2])
+ case 2:
+ // leading zeroes
+ dst = append(dst, '0', buf[2])
}
-
- return append(dst, buf[i:]...)
+ return dst
}
// %f: -ddddddd.ddddd
-func fmtF(dst []byte, neg bool, d *decimal, prec int) []byte {
+func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte {
// sign
if neg {
dst = append(dst, '-')
diff --git a/libgo/go/strconv/ftoa_test.go b/libgo/go/strconv/ftoa_test.go
index ee7b7c431e7..39b861547ea 100644
--- a/libgo/go/strconv/ftoa_test.go
+++ b/libgo/go/strconv/ftoa_test.go
@@ -163,6 +163,7 @@ func TestFtoaRandom(t *testing.T) {
for i := 0; i < N; i++ {
bits := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
x := math.Float64frombits(bits)
+
shortFast := FormatFloat(x, 'g', -1, 64)
SetOptimize(false)
shortSlow := FormatFloat(x, 'g', -1, 64)
@@ -170,30 +171,18 @@ func TestFtoaRandom(t *testing.T) {
if shortSlow != shortFast {
t.Errorf("%b printed as %s, want %s", x, shortFast, shortSlow)
}
- }
-}
-
-/* This test relies on escape analysis which gccgo does not yet do.
-func TestAppendFloatDoesntAllocate(t *testing.T) {
- n := numAllocations(func() {
- var buf [64]byte
- AppendFloat(buf[:0], 1.23, 'g', 5, 64)
- })
- want := 1 // TODO(bradfitz): this might be 0, once escape analysis is better
- if n != want {
- t.Errorf("with local buffer, did %d allocations, want %d", n, want)
- }
- n = numAllocations(func() {
- AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64)
- })
- if n != 0 {
- t.Errorf("with reused buffer, did %d allocations, want 0", n)
+ prec := rand.Intn(12) + 5
+ shortFast = FormatFloat(x, 'e', prec, 64)
+ SetOptimize(false)
+ shortSlow = FormatFloat(x, 'e', prec, 64)
+ SetOptimize(true)
+ if shortSlow != shortFast {
+ t.Errorf("%b printed as %s, want %s", x, shortFast, shortSlow)
+ }
}
}
-*/
-
func BenchmarkFormatFloatDecimal(b *testing.B) {
for i := 0; i < b.N; i++ {
FormatFloat(33909, 'g', -1, 64)
@@ -224,37 +213,28 @@ func BenchmarkFormatFloatBig(b *testing.B) {
}
}
-func BenchmarkAppendFloatDecimal(b *testing.B) {
- dst := make([]byte, 0, 30)
+func benchmarkAppendFloat(b *testing.B, f float64, fmt byte, prec, bitSize int) {
+ dst := make([]byte, 30)
for i := 0; i < b.N; i++ {
- AppendFloat(dst, 33909, 'g', -1, 64)
+ AppendFloat(dst[:0], f, fmt, prec, bitSize)
}
}
-func BenchmarkAppendFloat(b *testing.B) {
- dst := make([]byte, 0, 30)
- for i := 0; i < b.N; i++ {
- AppendFloat(dst, 339.7784, 'g', -1, 64)
- }
-}
-
-func BenchmarkAppendFloatExp(b *testing.B) {
- dst := make([]byte, 0, 30)
- for i := 0; i < b.N; i++ {
- AppendFloat(dst, -5.09e75, 'g', -1, 64)
- }
+func BenchmarkAppendFloatDecimal(b *testing.B) { benchmarkAppendFloat(b, 33909, 'g', -1, 64) }
+func BenchmarkAppendFloat(b *testing.B) { benchmarkAppendFloat(b, 339.7784, 'g', -1, 64) }
+func BenchmarkAppendFloatExp(b *testing.B) { benchmarkAppendFloat(b, -5.09e75, 'g', -1, 64) }
+func BenchmarkAppendFloatNegExp(b *testing.B) { benchmarkAppendFloat(b, -5.11e-95, 'g', -1, 64) }
+func BenchmarkAppendFloatBig(b *testing.B) {
+ benchmarkAppendFloat(b, 123456789123456789123456789, 'g', -1, 64)
}
-func BenchmarkAppendFloatNegExp(b *testing.B) {
- dst := make([]byte, 0, 30)
- for i := 0; i < b.N; i++ {
- AppendFloat(dst, -5.11e-95, 'g', -1, 64)
- }
-}
+func BenchmarkAppendFloat32Integer(b *testing.B) { benchmarkAppendFloat(b, 33909, 'g', -1, 32) }
+func BenchmarkAppendFloat32ExactFraction(b *testing.B) { benchmarkAppendFloat(b, 3.375, 'g', -1, 32) }
+func BenchmarkAppendFloat32Point(b *testing.B) { benchmarkAppendFloat(b, 339.7784, 'g', -1, 32) }
+func BenchmarkAppendFloat32Exp(b *testing.B) { benchmarkAppendFloat(b, -5.09e25, 'g', -1, 32) }
+func BenchmarkAppendFloat32NegExp(b *testing.B) { benchmarkAppendFloat(b, -5.11e-25, 'g', -1, 32) }
-func BenchmarkAppendFloatBig(b *testing.B) {
- dst := make([]byte, 0, 30)
- for i := 0; i < b.N; i++ {
- AppendFloat(dst, 123456789123456789123456789, 'g', -1, 64)
- }
-}
+func BenchmarkAppendFloat64Fixed1(b *testing.B) { benchmarkAppendFloat(b, 123456, 'e', 3, 64) }
+func BenchmarkAppendFloat64Fixed2(b *testing.B) { benchmarkAppendFloat(b, 123.456, 'e', 3, 64) }
+func BenchmarkAppendFloat64Fixed3(b *testing.B) { benchmarkAppendFloat(b, 1.23456e+78, 'e', 3, 64) }
+func BenchmarkAppendFloat64Fixed4(b *testing.B) { benchmarkAppendFloat(b, 1.23456e-78, 'e', 3, 64) }
diff --git a/libgo/go/strconv/itoa_test.go b/libgo/go/strconv/itoa_test.go
index 63d2fa44e02..e0213ae9afe 100644
--- a/libgo/go/strconv/itoa_test.go
+++ b/libgo/go/strconv/itoa_test.go
@@ -5,7 +5,6 @@
package strconv_test
import (
- "runtime"
. "strconv"
"testing"
)
@@ -126,39 +125,6 @@ func TestUitoa(t *testing.T) {
}
}
-func numAllocations(f func()) int {
- runtime.GC()
- memstats := new(runtime.MemStats)
- runtime.ReadMemStats(memstats)
- n0 := memstats.Mallocs
- f()
- runtime.ReadMemStats(memstats)
- return int(memstats.Mallocs - n0)
-}
-
-/* This test relies on escape analysis which gccgo does not yet do.
-
-var globalBuf [64]byte
-
-func TestAppendUintDoesntAllocate(t *testing.T) {
- n := numAllocations(func() {
- var buf [64]byte
- AppendInt(buf[:0], 123, 10)
- })
- want := 1 // TODO(bradfitz): this might be 0, once escape analysis is better
- if n != want {
- t.Errorf("with local buffer, did %d allocations, want %d", n, want)
- }
- n = numAllocations(func() {
- AppendInt(globalBuf[:0], 123, 10)
- })
- if n != 0 {
- t.Errorf("with reused buffer, did %d allocations, want 0", n)
- }
-}
-
-*/
-
func BenchmarkFormatInt(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range itob64tests {
diff --git a/libgo/go/strconv/strconv_test.go b/libgo/go/strconv/strconv_test.go
new file mode 100644
index 00000000000..5a3beae61d0
--- /dev/null
+++ b/libgo/go/strconv/strconv_test.go
@@ -0,0 +1,67 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strconv_test
+
+/*
+
+gccgo does not pass this.
+
+import (
+ "runtime"
+ . "strconv"
+ "strings"
+ "testing"
+)
+
+var (
+ globalBuf [64]byte
+ nextToOne = "1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1"
+
+ mallocTest = []struct {
+ count int
+ desc string
+ fn func()
+ }{
+ // TODO(bradfitz): this might be 0, once escape analysis is better
+ {1, `AppendInt(localBuf[:0], 123, 10)`, func() {
+ var localBuf [64]byte
+ AppendInt(localBuf[:0], 123, 10)
+ }},
+ {0, `AppendInt(globalBuf[:0], 123, 10)`, func() { AppendInt(globalBuf[:0], 123, 10) }},
+ // TODO(bradfitz): this might be 0, once escape analysis is better
+ {1, `AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)`, func() {
+ var localBuf [64]byte
+ AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)
+ }},
+ {0, `AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64)`, func() { AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64) }},
+ {0, `ParseFloat("123.45", 64)`, func() { ParseFloat("123.45", 64) }},
+ {0, `ParseFloat("123.456789123456789", 64)`, func() { ParseFloat("123.456789123456789", 64) }},
+ {0, `ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64)`, func() {
+ ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64)
+ }},
+ {0, `ParseFloat("1.0000000000000001110223024625156540423631668090820312500...001", 64)`, func() {
+ ParseFloat(nextToOne, 64)
+ }},
+ }
+)
+
+func TestCountMallocs(t *testing.T) {
+ for _, mt := range mallocTest {
+ const N = 100
+ memstats := new(runtime.MemStats)
+ runtime.ReadMemStats(memstats)
+ mallocs := 0 - memstats.Mallocs
+ for i := 0; i < N; i++ {
+ mt.fn()
+ }
+ runtime.ReadMemStats(memstats)
+ mallocs += memstats.Mallocs
+ if mallocs/N > uint64(mt.count) {
+ t.Errorf("%s: expected %d mallocs, got %d", mt.desc, mt.count, mallocs/N)
+ }
+ }
+}
+
+*/
diff --git a/libgo/go/strings/export_test.go b/libgo/go/strings/export_test.go
index dcfec513ccf..17c806aa563 100644
--- a/libgo/go/strings/export_test.go
+++ b/libgo/go/strings/export_test.go
@@ -7,3 +7,39 @@ package strings
func (r *Replacer) Replacer() interface{} {
return r.r
}
+
+func (r *Replacer) PrintTrie() string {
+ gen := r.r.(*genericReplacer)
+ return gen.printNode(&gen.root, 0)
+}
+
+func (r *genericReplacer) printNode(t *trieNode, depth int) (s string) {
+ if t.priority > 0 {
+ s += "+"
+ } else {
+ s += "-"
+ }
+ s += "\n"
+
+ if t.prefix != "" {
+ s += Repeat(".", depth) + t.prefix
+ s += r.printNode(t.next, depth+len(t.prefix))
+ } else if t.table != nil {
+ for b, m := range r.mapping {
+ if int(m) != r.tableSize && t.table[m] != nil {
+ s += Repeat(".", depth) + string([]byte{byte(b)})
+ s += r.printNode(t.table[m], depth+1)
+ }
+ }
+ }
+ return
+}
+
+func StringFind(pattern, text string) int {
+ return makeStringFinder(pattern).next(text)
+}
+
+func DumpTables(pattern string) ([]int, []int) {
+ finder := makeStringFinder(pattern)
+ return finder.badCharSkip[:], finder.goodSuffixSkip
+}
diff --git a/libgo/go/strings/replace.go b/libgo/go/strings/replace.go
index f53a96ee0f9..f63b1792c56 100644
--- a/libgo/go/strings/replace.go
+++ b/libgo/go/strings/replace.go
@@ -33,47 +33,45 @@ func NewReplacer(oldnew ...string) *Replacer {
panic("strings.NewReplacer: odd argument count")
}
- // Possible implementations.
- var (
- bb byteReplacer
- bs byteStringReplacer
- gen genericReplacer
- )
-
- allOldBytes, allNewBytes := true, true
- for len(oldnew) > 0 {
- old, new := oldnew[0], oldnew[1]
- oldnew = oldnew[2:]
- if len(old) != 1 {
- allOldBytes = false
+ if len(oldnew) == 2 && len(oldnew[0]) > 1 {
+ return &Replacer{r: makeSingleStringReplacer(oldnew[0], oldnew[1])}
+ }
+
+ allNewBytes := true
+ for i := 0; i < len(oldnew); i += 2 {
+ if len(oldnew[i]) != 1 {
+ return &Replacer{r: makeGenericReplacer(oldnew)}
}
- if len(new) != 1 {
+ if len(oldnew[i+1]) != 1 {
allNewBytes = false
}
+ }
- // generic
- gen.p = append(gen.p, pair{old, new})
-
- // byte -> string
- if allOldBytes {
- bs.old.set(old[0])
- bs.new[old[0]] = []byte(new)
- }
-
- // byte -> byte
- if allOldBytes && allNewBytes {
- bb.old.set(old[0])
- bb.new[old[0]] = new[0]
+ if allNewBytes {
+ bb := &byteReplacer{}
+ for i := 0; i < len(oldnew); i += 2 {
+ o, n := oldnew[i][0], oldnew[i+1][0]
+ if bb.old[o>>5]&uint32(1<<(o&31)) != 0 {
+ // Later old->new maps do not override previous ones with the same old string.
+ continue
+ }
+ bb.old.set(o)
+ bb.new[o] = n
}
+ return &Replacer{r: bb}
}
- if allOldBytes && allNewBytes {
- return &Replacer{r: &bb}
- }
- if allOldBytes {
- return &Replacer{r: &bs}
+ bs := &byteStringReplacer{}
+ for i := 0; i < len(oldnew); i += 2 {
+ o, new := oldnew[i][0], oldnew[i+1]
+ if bs.old[o>>5]&uint32(1<<(o&31)) != 0 {
+ // Later old->new maps do not override previous ones with the same old string.
+ continue
+ }
+ bs.old.set(o)
+ bs.new[o] = []byte(new)
}
- return &Replacer{r: &gen}
+ return &Replacer{r: bs}
}
// Replace returns a copy of s with all replacements performed.
@@ -86,79 +84,326 @@ func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error) {
return r.r.WriteString(w, s)
}
-// genericReplacer is the fully generic (and least optimized) algorithm.
+// trieNode is a node in a lookup trie for prioritized key/value pairs. Keys
+// and values may be empty. For example, the trie containing keys "ax", "ay",
+// "bcbc", "x" and "xy" could have eight nodes:
+//
+// n0 -
+// n1 a-
+// n2 .x+
+// n3 .y+
+// n4 b-
+// n5 .cbc+
+// n6 x+
+// n7 .y+
+//
+// n0 is the root node, and its children are n1, n4 and n6; n1's children are
+// n2 and n3; n4's child is n5; n6's child is n7. Nodes n0, n1 and n4 (marked
+// with a trailing "-") are partial keys, and nodes n2, n3, n5, n6 and n7
+// (marked with a trailing "+") are complete keys.
+type trieNode struct {
+ // value is the value of the trie node's key/value pair. It is empty if
+ // this node is not a complete key.
+ value string
+ // priority is the priority (higher is more important) of the trie node's
+ // key/value pair; keys are not necessarily matched shortest- or longest-
+ // first. Priority is positive if this node is a complete key, and zero
+ // otherwise. In the example above, positive/zero priorities are marked
+ // with a trailing "+" or "-".
+ priority int
+
+ // A trie node may have zero, one or more child nodes:
+ // * if the remaining fields are zero, there are no children.
+ // * if prefix and next are non-zero, there is one child in next.
+ // * if table is non-zero, it defines all the children.
+ //
+ // Prefixes are preferred over tables when there is one child, but the
+ // root node always uses a table for lookup efficiency.
+
+ // prefix is the difference in keys between this trie node and the next.
+ // In the example above, node n4 has prefix "cbc" and n4's next node is n5.
+ // Node n5 has no children and so has zero prefix, next and table fields.
+ prefix string
+ next *trieNode
+
+ // table is a lookup table indexed by the next byte in the key, after
+ // remapping that byte through genericReplacer.mapping to create a dense
+ // index. In the example above, the keys only use 'a', 'b', 'c', 'x' and
+ // 'y', which remap to 0, 1, 2, 3 and 4. All other bytes remap to 5, and
+ // genericReplacer.tableSize will be 5. Node n0's table will be
+ // []*trieNode{ 0:n1, 1:n4, 3:n6 }, where the 0, 1 and 3 are the remapped
+ // 'a', 'b' and 'x'.
+ table []*trieNode
+}
+
+func (t *trieNode) add(key, val string, priority int, r *genericReplacer) {
+ if key == "" {
+ if t.priority == 0 {
+ t.value = val
+ t.priority = priority
+ }
+ return
+ }
+
+ if t.prefix != "" {
+ // Need to split the prefix among multiple nodes.
+ var n int // length of the longest common prefix
+ for ; n < len(t.prefix) && n < len(key); n++ {
+ if t.prefix[n] != key[n] {
+ break
+ }
+ }
+ if n == len(t.prefix) {
+ t.next.add(key[n:], val, priority, r)
+ } else if n == 0 {
+ // First byte differs, start a new lookup table here. Looking up
+ // what is currently t.prefix[0] will lead to prefixNode, and
+ // looking up key[0] will lead to keyNode.
+ var prefixNode *trieNode
+ if len(t.prefix) == 1 {
+ prefixNode = t.next
+ } else {
+ prefixNode = &trieNode{
+ prefix: t.prefix[1:],
+ next: t.next,
+ }
+ }
+ keyNode := new(trieNode)
+ t.table = make([]*trieNode, r.tableSize)
+ t.table[r.mapping[t.prefix[0]]] = prefixNode
+ t.table[r.mapping[key[0]]] = keyNode
+ t.prefix = ""
+ t.next = nil
+ keyNode.add(key[1:], val, priority, r)
+ } else {
+ // Insert new node after the common section of the prefix.
+ next := &trieNode{
+ prefix: t.prefix[n:],
+ next: t.next,
+ }
+ t.prefix = t.prefix[:n]
+ t.next = next
+ next.add(key[n:], val, priority, r)
+ }
+ } else if t.table != nil {
+ // Insert into existing table.
+ m := r.mapping[key[0]]
+ if t.table[m] == nil {
+ t.table[m] = new(trieNode)
+ }
+ t.table[m].add(key[1:], val, priority, r)
+ } else {
+ t.prefix = key
+ t.next = new(trieNode)
+ t.next.add("", val, priority, r)
+ }
+}
+
+func (r *genericReplacer) lookup(s string, ignoreRoot bool) (val string, keylen int, found bool) {
+ // Iterate down the trie to the end, and grab the value and keylen with
+ // the highest priority.
+ bestPriority := 0
+ node := &r.root
+ n := 0
+ for node != nil {
+ if node.priority > bestPriority && !(ignoreRoot && node == &r.root) {
+ bestPriority = node.priority
+ val = node.value
+ keylen = n
+ found = true
+ }
+
+ if s == "" {
+ break
+ }
+ if node.table != nil {
+ index := r.mapping[s[0]]
+ if int(index) == r.tableSize {
+ break
+ }
+ node = node.table[index]
+ s = s[1:]
+ n++
+ } else if node.prefix != "" && HasPrefix(s, node.prefix) {
+ n += len(node.prefix)
+ s = s[len(node.prefix):]
+ node = node.next
+ } else {
+ break
+ }
+ }
+ return
+}
+
+// genericReplacer is the fully generic algorithm.
// It's used as a fallback when nothing faster can be used.
type genericReplacer struct {
- p []pair
+ root trieNode
+ // tableSize is the size of a trie node's lookup table. It is the number
+ // of unique key bytes.
+ tableSize int
+ // mapping maps from key bytes to a dense index for trieNode.table.
+ mapping [256]byte
}
-type pair struct{ old, new string }
+func makeGenericReplacer(oldnew []string) *genericReplacer {
+ r := new(genericReplacer)
+ // Find each byte used, then assign them each an index.
+ for i := 0; i < len(oldnew); i += 2 {
+ key := oldnew[i]
+ for j := 0; j < len(key); j++ {
+ r.mapping[key[j]] = 1
+ }
+ }
+
+ for _, b := range r.mapping {
+ r.tableSize += int(b)
+ }
+
+ var index byte
+ for i, b := range r.mapping {
+ if b == 0 {
+ r.mapping[i] = byte(r.tableSize)
+ } else {
+ r.mapping[i] = index
+ index++
+ }
+ }
+ // Ensure root node uses a lookup table (for performance).
+ r.root.table = make([]*trieNode, r.tableSize)
-type appendSliceWriter struct {
- b []byte
+ for i := 0; i < len(oldnew); i += 2 {
+ r.root.add(oldnew[i], oldnew[i+1], len(oldnew)-i, r)
+ }
+ return r
}
+type appendSliceWriter []byte
+
+// Write writes to the buffer to satisfy io.Writer.
func (w *appendSliceWriter) Write(p []byte) (int, error) {
- w.b = append(w.b, p...)
+ *w = append(*w, p...)
return len(p), nil
}
+// WriteString writes to the buffer without string->[]byte->string allocations.
+func (w *appendSliceWriter) WriteString(s string) (int, error) {
+ *w = append(*w, s...)
+ return len(s), nil
+}
+
+type stringWriterIface interface {
+ WriteString(string) (int, error)
+}
+
+type stringWriter struct {
+ w io.Writer
+}
+
+func (w stringWriter) WriteString(s string) (int, error) {
+ return w.w.Write([]byte(s))
+}
+
+func getStringWriter(w io.Writer) stringWriterIface {
+ sw, ok := w.(stringWriterIface)
+ if !ok {
+ sw = stringWriter{w}
+ }
+ return sw
+}
+
func (r *genericReplacer) Replace(s string) string {
- // TODO(bradfitz): optimized version
- n, _ := r.WriteString(discard, s)
- w := appendSliceWriter{make([]byte, 0, n)}
- r.WriteString(&w, s)
- return string(w.b)
+ buf := make(appendSliceWriter, 0, len(s))
+ r.WriteString(&buf, s)
+ return string(buf)
}
func (r *genericReplacer) WriteString(w io.Writer, s string) (n int, err error) {
- lastEmpty := false // the last replacement was of the empty string
-Input:
- // TODO(bradfitz): optimized version
- for i := 0; i < len(s); {
- for _, p := range r.p {
- if p.old == "" && lastEmpty {
- // Don't let old match twice in a row.
- // (it doesn't advance the input and
- // would otherwise loop forever)
- continue
+ sw := getStringWriter(w)
+ var last, wn int
+ var prevMatchEmpty bool
+ for i := 0; i <= len(s); {
+ // Ignore the empty match iff the previous loop found the empty match.
+ val, keylen, match := r.lookup(s[i:], prevMatchEmpty)
+ prevMatchEmpty = match && keylen == 0
+ if match {
+ wn, err = sw.WriteString(s[last:i])
+ n += wn
+ if err != nil {
+ return
}
- if HasPrefix(s[i:], p.old) {
- if p.new != "" {
- wn, err := w.Write([]byte(p.new))
- n += wn
- if err != nil {
- return n, err
- }
- }
- i += len(p.old)
- lastEmpty = p.old == ""
- continue Input
+ wn, err = sw.WriteString(val)
+ n += wn
+ if err != nil {
+ return
}
- }
- wn, err := w.Write([]byte{s[i]})
- n += wn
- if err != nil {
- return n, err
+ i += keylen
+ last = i
+ continue
}
i++
}
+ if last != len(s) {
+ wn, err = sw.WriteString(s[last:])
+ n += wn
+ }
+ return
+}
- // Final empty match at end.
- for _, p := range r.p {
- if p.old == "" {
- if p.new != "" {
- wn, err := w.Write([]byte(p.new))
- n += wn
- if err != nil {
- return n, err
- }
- }
+// singleStringReplacer is the implementation that's used when there is only
+// one string to replace (and that string has more than one byte).
+type singleStringReplacer struct {
+ finder *stringFinder
+ // value is the new string that replaces that pattern when it's found.
+ value string
+}
+
+func makeSingleStringReplacer(pattern string, value string) *singleStringReplacer {
+ return &singleStringReplacer{finder: makeStringFinder(pattern), value: value}
+}
+
+func (r *singleStringReplacer) Replace(s string) string {
+ var buf []byte
+ i := 0
+ for {
+ match := r.finder.next(s[i:])
+ if match == -1 {
break
}
+ buf = append(buf, s[i:i+match]...)
+ buf = append(buf, r.value...)
+ i += match + len(r.finder.pattern)
+ }
+ if buf == nil {
+ return s
}
+ buf = append(buf, s[i:]...)
+ return string(buf)
+}
- return n, nil
+func (r *singleStringReplacer) WriteString(w io.Writer, s string) (n int, err error) {
+ sw := getStringWriter(w)
+ var i, wn int
+ for {
+ match := r.finder.next(s[i:])
+ if match == -1 {
+ break
+ }
+ wn, err = sw.WriteString(s[i : i+match])
+ n += wn
+ if err != nil {
+ return
+ }
+ wn, err = sw.WriteString(r.value)
+ n += wn
+ if err != nil {
+ return
+ }
+ i += match + len(r.finder.pattern)
+ }
+ wn, err = sw.WriteString(s[i:])
+ n += wn
+ return
}
// byteReplacer is the implementation that's used when all the "old"
@@ -301,12 +546,3 @@ func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err erro
}
return n, nil
}
-
-// strings is too low-level to import io/ioutil
-var discard io.Writer = devNull(0)
-
-type devNull int
-
-func (devNull) Write(p []byte) (int, error) {
- return len(p), nil
-}
diff --git a/libgo/go/strings/replace_test.go b/libgo/go/strings/replace_test.go
index 23c7e2e5334..d33dea95b09 100644
--- a/libgo/go/strings/replace_test.go
+++ b/libgo/go/strings/replace_test.go
@@ -7,105 +7,390 @@ package strings_test
import (
"bytes"
"fmt"
- "log"
. "strings"
"testing"
)
-var _ = log.Printf
-
-type ReplacerTest struct {
- r *Replacer
- in string
- out string
-}
+var htmlEscaper = NewReplacer(
+ "&", "&amp;",
+ "<", "&lt;",
+ ">", "&gt;",
+ `"`, "&quot;",
+ "'", "&apos;",
+)
-var htmlEscaper = NewReplacer("&", "&amp;", "<", "&lt;", ">", "&gt;", "\"", "&quot;")
+var htmlUnescaper = NewReplacer(
+ "&amp;", "&",
+ "&lt;", "<",
+ "&gt;", ">",
+ "&quot;", `"`,
+ "&apos;", "'",
+)
// The http package's old HTML escaping function.
-func oldhtmlEscape(s string) string {
+func oldHTMLEscape(s string) string {
s = Replace(s, "&", "&amp;", -1)
s = Replace(s, "<", "&lt;", -1)
s = Replace(s, ">", "&gt;", -1)
- s = Replace(s, "\"", "&quot;", -1)
+ s = Replace(s, `"`, "&quot;", -1)
s = Replace(s, "'", "&apos;", -1)
return s
}
-var replacer = NewReplacer("aaa", "3[aaa]", "aa", "2[aa]", "a", "1[a]", "i", "i",
- "longerst", "most long", "longer", "medium", "long", "short",
- "X", "Y", "Y", "Z")
-
var capitalLetters = NewReplacer("a", "A", "b", "B")
-var blankToXReplacer = NewReplacer("", "X", "o", "O")
+// TestReplacer tests the replacer implementations.
+func TestReplacer(t *testing.T) {
+ type testCase struct {
+ r *Replacer
+ in, out string
+ }
+ var testCases []testCase
-var ReplacerTests = []ReplacerTest{
- // byte->string
- {htmlEscaper, "No changes", "No changes"},
- {htmlEscaper, "I <3 escaping & stuff", "I &lt;3 escaping &amp; stuff"},
- {htmlEscaper, "&&&", "&amp;&amp;&amp;"},
+ // str converts 0xff to "\xff". This isn't just string(b) since that converts to UTF-8.
+ str := func(b byte) string {
+ return string([]byte{b})
+ }
+ var s []string
- // generic
- {replacer, "fooaaabar", "foo3[aaa]b1[a]r"},
- {replacer, "long, longerst, longer", "short, most long, medium"},
- {replacer, "XiX", "YiY"},
+ // inc maps "\x00"->"\x01", ..., "a"->"b", "b"->"c", ..., "\xff"->"\x00".
+ s = nil
+ for i := 0; i < 256; i++ {
+ s = append(s, str(byte(i)), str(byte(i+1)))
+ }
+ inc := NewReplacer(s...)
- // byte->byte
- {capitalLetters, "brad", "BrAd"},
- {capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)},
+ // Test cases with 1-byte old strings, 1-byte new strings.
+ testCases = append(testCases,
+ testCase{capitalLetters, "brad", "BrAd"},
+ testCase{capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)},
+ testCase{capitalLetters, "", ""},
- // hitting "" special case
- {blankToXReplacer, "oo", "XOXOX"},
-}
+ testCase{inc, "brad", "csbe"},
+ testCase{inc, "\x00\xff", "\x01\x00"},
+ testCase{inc, "", ""},
-func TestReplacer(t *testing.T) {
- for i, tt := range ReplacerTests {
- if s := tt.r.Replace(tt.in); s != tt.out {
- t.Errorf("%d. Replace(%q) = %q, want %q", i, tt.in, s, tt.out)
+ testCase{NewReplacer("a", "1", "a", "2"), "brad", "br1d"},
+ )
+
+ // repeat maps "a"->"a", "b"->"bb", "c"->"ccc", ...
+ s = nil
+ for i := 0; i < 256; i++ {
+ n := i + 1 - 'a'
+ if n < 1 {
+ n = 1
+ }
+ s = append(s, str(byte(i)), Repeat(str(byte(i)), n))
+ }
+ repeat := NewReplacer(s...)
+
+ // Test cases with 1-byte old strings, variable length new strings.
+ testCases = append(testCases,
+ testCase{htmlEscaper, "No changes", "No changes"},
+ testCase{htmlEscaper, "I <3 escaping & stuff", "I &lt;3 escaping &amp; stuff"},
+ testCase{htmlEscaper, "&&&", "&amp;&amp;&amp;"},
+ testCase{htmlEscaper, "", ""},
+
+ testCase{repeat, "brad", "bbrrrrrrrrrrrrrrrrrradddd"},
+ testCase{repeat, "abba", "abbbba"},
+ testCase{repeat, "", ""},
+
+ testCase{NewReplacer("a", "11", "a", "22"), "brad", "br11d"},
+ )
+
+ // The remaining test cases have variable length old strings.
+
+ testCases = append(testCases,
+ testCase{htmlUnescaper, "&amp;amp;", "&amp;"},
+ testCase{htmlUnescaper, "&lt;b&gt;HTML&apos;s neat&lt;/b&gt;", "<b>HTML's neat</b>"},
+ testCase{htmlUnescaper, "", ""},
+
+ testCase{NewReplacer("a", "1", "a", "2", "xxx", "xxx"), "brad", "br1d"},
+
+ testCase{NewReplacer("a", "1", "aa", "2", "aaa", "3"), "aaaa", "1111"},
+
+ testCase{NewReplacer("aaa", "3", "aa", "2", "a", "1"), "aaaa", "31"},
+ )
+
+ // gen1 has multiple old strings of variable length. There is no
+ // overall non-empty common prefix, but some pairwise common prefixes.
+ gen1 := NewReplacer(
+ "aaa", "3[aaa]",
+ "aa", "2[aa]",
+ "a", "1[a]",
+ "i", "i",
+ "longerst", "most long",
+ "longer", "medium",
+ "long", "short",
+ "xx", "xx",
+ "x", "X",
+ "X", "Y",
+ "Y", "Z",
+ )
+ testCases = append(testCases,
+ testCase{gen1, "fooaaabar", "foo3[aaa]b1[a]r"},
+ testCase{gen1, "long, longerst, longer", "short, most long, medium"},
+ testCase{gen1, "xxxxx", "xxxxX"},
+ testCase{gen1, "XiX", "YiY"},
+ testCase{gen1, "", ""},
+ )
+
+ // gen2 has multiple old strings with no pairwise common prefix.
+ gen2 := NewReplacer(
+ "roses", "red",
+ "violets", "blue",
+ "sugar", "sweet",
+ )
+ testCases = append(testCases,
+ testCase{gen2, "roses are red, violets are blue...", "red are red, blue are blue..."},
+ testCase{gen2, "", ""},
+ )
+
+ // gen3 has multiple old strings with an overall common prefix.
+ gen3 := NewReplacer(
+ "abracadabra", "poof",
+ "abracadabrakazam", "splat",
+ "abraham", "lincoln",
+ "abrasion", "scrape",
+ "abraham", "isaac",
+ )
+ testCases = append(testCases,
+ testCase{gen3, "abracadabrakazam abraham", "poofkazam lincoln"},
+ testCase{gen3, "abrasion abracad", "scrape abracad"},
+ testCase{gen3, "abba abram abrasive", "abba abram abrasive"},
+ testCase{gen3, "", ""},
+ )
+
+ // foo{1,2,3,4} have multiple old strings with an overall common prefix
+ // and 1- or 2- byte extensions from the common prefix.
+ foo1 := NewReplacer(
+ "foo1", "A",
+ "foo2", "B",
+ "foo3", "C",
+ )
+ foo2 := NewReplacer(
+ "foo1", "A",
+ "foo2", "B",
+ "foo31", "C",
+ "foo32", "D",
+ )
+ foo3 := NewReplacer(
+ "foo11", "A",
+ "foo12", "B",
+ "foo31", "C",
+ "foo32", "D",
+ )
+ foo4 := NewReplacer(
+ "foo12", "B",
+ "foo32", "D",
+ )
+ testCases = append(testCases,
+ testCase{foo1, "fofoofoo12foo32oo", "fofooA2C2oo"},
+ testCase{foo1, "", ""},
+
+ testCase{foo2, "fofoofoo12foo32oo", "fofooA2Doo"},
+ testCase{foo2, "", ""},
+
+ testCase{foo3, "fofoofoo12foo32oo", "fofooBDoo"},
+ testCase{foo3, "", ""},
+
+ testCase{foo4, "fofoofoo12foo32oo", "fofooBDoo"},
+ testCase{foo4, "", ""},
+ )
+
+ // genAll maps "\x00\x01\x02...\xfe\xff" to "[all]", amongst other things.
+ allBytes := make([]byte, 256)
+ for i := range allBytes {
+ allBytes[i] = byte(i)
+ }
+ allString := string(allBytes)
+ genAll := NewReplacer(
+ allString, "[all]",
+ "\xff", "[ff]",
+ "\x00", "[00]",
+ )
+ testCases = append(testCases,
+ testCase{genAll, allString, "[all]"},
+ testCase{genAll, "a\xff" + allString + "\x00", "a[ff][all][00]"},
+ testCase{genAll, "", ""},
+ )
+
+ // Test cases with empty old strings.
+
+ blankToX1 := NewReplacer("", "X")
+ blankToX2 := NewReplacer("", "X", "", "")
+ blankHighPriority := NewReplacer("", "X", "o", "O")
+ blankLowPriority := NewReplacer("o", "O", "", "X")
+ blankNoOp1 := NewReplacer("", "")
+ blankNoOp2 := NewReplacer("", "", "", "A")
+ blankFoo := NewReplacer("", "X", "foobar", "R", "foobaz", "Z")
+ testCases = append(testCases,
+ testCase{blankToX1, "foo", "XfXoXoX"},
+ testCase{blankToX1, "", "X"},
+
+ testCase{blankToX2, "foo", "XfXoXoX"},
+ testCase{blankToX2, "", "X"},
+
+ testCase{blankHighPriority, "oo", "XOXOX"},
+ testCase{blankHighPriority, "ii", "XiXiX"},
+ testCase{blankHighPriority, "oiio", "XOXiXiXOX"},
+ testCase{blankHighPriority, "iooi", "XiXOXOXiX"},
+ testCase{blankHighPriority, "", "X"},
+
+ testCase{blankLowPriority, "oo", "OOX"},
+ testCase{blankLowPriority, "ii", "XiXiX"},
+ testCase{blankLowPriority, "oiio", "OXiXiOX"},
+ testCase{blankLowPriority, "iooi", "XiOOXiX"},
+ testCase{blankLowPriority, "", "X"},
+
+ testCase{blankNoOp1, "foo", "foo"},
+ testCase{blankNoOp1, "", ""},
+
+ testCase{blankNoOp2, "foo", "foo"},
+ testCase{blankNoOp2, "", ""},
+
+ testCase{blankFoo, "foobarfoobaz", "XRXZX"},
+ testCase{blankFoo, "foobar-foobaz", "XRX-XZX"},
+ testCase{blankFoo, "", "X"},
+ )
+
+ // single string replacer
+
+ abcMatcher := NewReplacer("abc", "[match]")
+
+ testCases = append(testCases,
+ testCase{abcMatcher, "", ""},
+ testCase{abcMatcher, "ab", "ab"},
+ testCase{abcMatcher, "abcd", "[match]d"},
+ testCase{abcMatcher, "cabcabcdabca", "c[match][match]d[match]a"},
+ )
+
+ // No-arg test cases.
+
+ nop := NewReplacer()
+ testCases = append(testCases,
+ testCase{nop, "abc", "abc"},
+ testCase{nop, "", ""},
+ )
+
+ // Run the test cases.
+
+ for i, tc := range testCases {
+ if s := tc.r.Replace(tc.in); s != tc.out {
+ t.Errorf("%d. Replace(%q) = %q, want %q", i, tc.in, s, tc.out)
}
var buf bytes.Buffer
- n, err := tt.r.WriteString(&buf, tt.in)
+ n, err := tc.r.WriteString(&buf, tc.in)
if err != nil {
t.Errorf("%d. WriteString: %v", i, err)
continue
}
got := buf.String()
- if got != tt.out {
- t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tt.in, got, tt.out)
+ if got != tc.out {
+ t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tc.in, got, tc.out)
continue
}
- if n != len(tt.out) {
+ if n != len(tc.out) {
t.Errorf("%d. WriteString(%q) wrote correct string but reported %d bytes; want %d (%q)",
- i, tt.in, n, len(tt.out), tt.out)
+ i, tc.in, n, len(tc.out), tc.out)
}
}
}
-// pickAlgorithmTest is a test that verifies that given input for a
-// Replacer that we pick the correct algorithm.
-type pickAlgorithmTest struct {
- r *Replacer
- want string // name of algorithm
+// TestPickAlgorithm tests that NewReplacer picks the correct algorithm.
+func TestPickAlgorithm(t *testing.T) {
+ testCases := []struct {
+ r *Replacer
+ want string
+ }{
+ {capitalLetters, "*strings.byteReplacer"},
+ {htmlEscaper, "*strings.byteStringReplacer"},
+ {NewReplacer("12", "123"), "*strings.singleStringReplacer"},
+ {NewReplacer("1", "12"), "*strings.byteStringReplacer"},
+ {NewReplacer("", "X"), "*strings.genericReplacer"},
+ {NewReplacer("a", "1", "b", "12", "cde", "123"), "*strings.genericReplacer"},
+ }
+ for i, tc := range testCases {
+ got := fmt.Sprintf("%T", tc.r.Replacer())
+ if got != tc.want {
+ t.Errorf("%d. algorithm = %s, want %s", i, got, tc.want)
+ }
+ }
}
-var pickAlgorithmTests = []pickAlgorithmTest{
- {capitalLetters, "*strings.byteReplacer"},
- {NewReplacer("12", "123"), "*strings.genericReplacer"},
- {NewReplacer("1", "12"), "*strings.byteStringReplacer"},
- {htmlEscaper, "*strings.byteStringReplacer"},
-}
+// TestGenericTrieBuilding verifies the structure of the generated trie. There
+// is one node per line, and the key ending with the current line is in the
+// trie if it ends with a "+".
+func TestGenericTrieBuilding(t *testing.T) {
+ testCases := []struct{ in, out string }{
+ {"abc;abdef;abdefgh;xx;xy;z", `-
+ a-
+ .b-
+ ..c+
+ ..d-
+ ...ef+
+ .....gh+
+ x-
+ .x+
+ .y+
+ z+
+ `},
+ {"abracadabra;abracadabrakazam;abraham;abrasion", `-
+ a-
+ .bra-
+ ....c-
+ .....adabra+
+ ...........kazam+
+ ....h-
+ .....am+
+ ....s-
+ .....ion+
+ `},
+ {"aaa;aa;a;i;longerst;longer;long;xx;x;X;Y", `-
+ X+
+ Y+
+ a+
+ .a+
+ ..a+
+ i+
+ l-
+ .ong+
+ ....er+
+ ......st+
+ x+
+ .x+
+ `},
+ {"foo;;foo;foo1", `+
+ f-
+ .oo+
+ ...1+
+ `},
+ }
-func TestPickAlgorithm(t *testing.T) {
- for i, tt := range pickAlgorithmTests {
- got := fmt.Sprintf("%T", tt.r.Replacer())
- if got != tt.want {
- t.Errorf("%d. algorithm = %s, want %s", i, got, tt.want)
+ for _, tc := range testCases {
+ keys := Split(tc.in, ";")
+ args := make([]string, len(keys)*2)
+ for i, key := range keys {
+ args[i*2] = key
+ }
+
+ got := NewReplacer(args...).PrintTrie()
+ // Remove tabs from tc.out
+ wantbuf := make([]byte, 0, len(tc.out))
+ for i := 0; i < len(tc.out); i++ {
+ if tc.out[i] != '\t' {
+ wantbuf = append(wantbuf, tc.out[i])
+ }
+ }
+ want := string(wantbuf)
+
+ if got != want {
+ t.Errorf("PrintTrie(%q)\ngot\n%swant\n%s", tc.in, got, want)
}
}
}
-func BenchmarkGenericMatch(b *testing.B) {
+func BenchmarkGenericNoMatch(b *testing.B) {
str := Repeat("A", 100) + Repeat("B", 100)
generic := NewReplacer("a", "A", "b", "B", "12", "123") // varying lengths forces generic
for i := 0; i < b.N; i++ {
@@ -113,6 +398,42 @@ func BenchmarkGenericMatch(b *testing.B) {
}
}
+func BenchmarkGenericMatch1(b *testing.B) {
+ str := Repeat("a", 100) + Repeat("b", 100)
+ generic := NewReplacer("a", "A", "b", "B", "12", "123")
+ for i := 0; i < b.N; i++ {
+ generic.Replace(str)
+ }
+}
+
+func BenchmarkGenericMatch2(b *testing.B) {
+ str := Repeat("It&apos;s &lt;b&gt;HTML&lt;/b&gt;!", 100)
+ for i := 0; i < b.N; i++ {
+ htmlUnescaper.Replace(str)
+ }
+}
+
+func benchmarkSingleString(b *testing.B, pattern, text string) {
+ r := NewReplacer(pattern, "[match]")
+ b.SetBytes(int64(len(text)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ r.Replace(text)
+ }
+}
+
+func BenchmarkSingleMaxSkipping(b *testing.B) {
+ benchmarkSingleString(b, Repeat("b", 25), Repeat("a", 10000))
+}
+
+func BenchmarkSingleLongSuffixFail(b *testing.B) {
+ benchmarkSingleString(b, "b"+Repeat("a", 500), Repeat("a", 1002))
+}
+
+func BenchmarkSingleMatch(b *testing.B) {
+ benchmarkSingleString(b, "abcdef", Repeat("abcdefghijklmno", 1000))
+}
+
func BenchmarkByteByteNoMatch(b *testing.B) {
str := Repeat("A", 100) + Repeat("B", 100)
for i := 0; i < b.N; i++ {
@@ -144,7 +465,7 @@ func BenchmarkHTMLEscapeNew(b *testing.B) {
func BenchmarkHTMLEscapeOld(b *testing.B) {
str := "I <3 to escape HTML & other text too."
for i := 0; i < b.N; i++ {
- oldhtmlEscape(str)
+ oldHTMLEscape(str)
}
}
diff --git a/libgo/go/strings/search.go b/libgo/go/strings/search.go
new file mode 100644
index 00000000000..f77c879c572
--- /dev/null
+++ b/libgo/go/strings/search.go
@@ -0,0 +1,124 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strings
+
+// stringFinder efficiently finds strings in a source text. It's implemented
+// using the Boyer-Moore string search algorithm:
+// http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm
+// http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf (note: this aged
+// document uses 1-based indexing)
+type stringFinder struct {
+ // pattern is the string that we are searching for in the text.
+ pattern string
+
+ // badCharSkip[b] contains the distance between the last byte of pattern
+ // and the rightmost occurrence of b in pattern. If b is not in pattern,
+ // badCharSkip[b] is len(pattern).
+ //
+ // Whenever a mismatch is found with byte b in the text, we can safely
+ // shift the matching frame at least badCharSkip[b] until the next time
+ // the matching char could be in alignment.
+ badCharSkip [256]int
+
+ // goodSuffixSkip[i] defines how far we can shift the matching frame given
+ // that the suffix pattern[i+1:] matches, but the byte pattern[i] does
+ // not. There are two cases to consider:
+ //
+ // 1. The matched suffix occurs elsewhere in pattern (with a different
+ // byte preceding it that we might possibly match). In this case, we can
+ // shift the matching frame to align with the next suffix chunk. For
+ // example, the pattern "mississi" has the suffix "issi" next occurring
+ // (in right-to-left order) at index 1, so goodSuffixSkip[3] ==
+ // shift+len(suffix) == 3+4 == 7.
+ //
+ // 2. If the matched suffix does not occur elsewhere in pattern, then the
+ // matching frame may share part of its prefix with the end of the
+ // matching suffix. In this case, goodSuffixSkip[i] will contain how far
+ // to shift the frame to align this portion of the prefix to the
+ // suffix. For example, in the pattern "abcxxxabc", when the first
+ // mismatch from the back is found to be in position 3, the matching
+ // suffix "xxabc" is not found elsewhere in the pattern. However, its
+ // rightmost "abc" (at position 6) is a prefix of the whole pattern, so
+ // goodSuffixSkip[3] == shift+len(suffix) == 6+5 == 11.
+ goodSuffixSkip []int
+}
+
+func makeStringFinder(pattern string) *stringFinder {
+ f := &stringFinder{
+ pattern: pattern,
+ goodSuffixSkip: make([]int, len(pattern)),
+ }
+ // last is the index of the last character in the pattern.
+ last := len(pattern) - 1
+
+ // Build bad character table.
+ // Bytes not in the pattern can skip one pattern's length.
+ for i := range f.badCharSkip {
+ f.badCharSkip[i] = len(pattern)
+ }
+ // The loop condition is < instead of <= so that the last byte does not
+ // have a zero distance to itself. Finding this byte out of place implies
+ // that it is not in the last position.
+ for i := 0; i < last; i++ {
+ f.badCharSkip[pattern[i]] = last - i
+ }
+
+ // Build good suffix table.
+ // First pass: set each value to the next index which starts a prefix of
+ // pattern.
+ lastPrefix := last
+ for i := last; i >= 0; i-- {
+ if HasPrefix(pattern, pattern[i+1:]) {
+ lastPrefix = i + 1
+ }
+ // lastPrefix is the shift, and (last-i) is len(suffix).
+ f.goodSuffixSkip[i] = lastPrefix + last - i
+ }
+ // Second pass: find repeats of pattern's suffix starting from the front.
+ for i := 0; i < last; i++ {
+ lenSuffix := longestCommonSuffix(pattern, pattern[1:i+1])
+ if pattern[i-lenSuffix] != pattern[last-lenSuffix] {
+ // (last-i) is the shift, and lenSuffix is len(suffix).
+ f.goodSuffixSkip[last-lenSuffix] = lenSuffix + last - i
+ }
+ }
+
+ return f
+}
+
+func longestCommonSuffix(a, b string) (i int) {
+ for ; i < len(a) && i < len(b); i++ {
+ if a[len(a)-1-i] != b[len(b)-1-i] {
+ break
+ }
+ }
+ return
+}
+
+// next returns the index in text of the first occurrence of the pattern. If
+// the pattern is not found, it returns -1.
+func (f *stringFinder) next(text string) int {
+ i := len(f.pattern) - 1
+ for i < len(text) {
+ // Compare backwards from the end until the first unmatching character.
+ j := len(f.pattern) - 1
+ for j >= 0 && text[i] == f.pattern[j] {
+ i--
+ j--
+ }
+ if j < 0 {
+ return i + 1 // match
+ }
+ i += max(f.badCharSkip[text[i]], f.goodSuffixSkip[j])
+ }
+ return -1
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
diff --git a/libgo/go/strings/search_test.go b/libgo/go/strings/search_test.go
new file mode 100644
index 00000000000..966c05e65ad
--- /dev/null
+++ b/libgo/go/strings/search_test.go
@@ -0,0 +1,90 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strings_test
+
+import (
+ "reflect"
+ . "strings"
+ "testing"
+)
+
+func TestFinderNext(t *testing.T) {
+ testCases := []struct {
+ pat, text string
+ index int
+ }{
+ {"", "", 0},
+ {"", "abc", 0},
+ {"abc", "", -1},
+ {"abc", "abc", 0},
+ {"d", "abcdefg", 3},
+ {"nan", "banana", 2},
+ {"pan", "anpanman", 2},
+ {"nnaaman", "anpanmanam", -1},
+ {"abcd", "abc", -1},
+ {"abcd", "bcd", -1},
+ {"bcd", "abcd", 1},
+ {"abc", "acca", -1},
+ {"aa", "aaa", 0},
+ {"baa", "aaaaa", -1},
+ {"at that", "which finally halts. at that point", 22},
+ }
+
+ for _, tc := range testCases {
+ got := StringFind(tc.pat, tc.text)
+ want := tc.index
+ if got != want {
+ t.Errorf("stringFind(%q, %q) got %d, want %d\n", tc.pat, tc.text, got, want)
+ }
+ }
+}
+
+func TestFinderCreation(t *testing.T) {
+ testCases := []struct {
+ pattern string
+ bad [256]int
+ suf []int
+ }{
+ {
+ "abc",
+ [256]int{'a': 2, 'b': 1, 'c': 3},
+ []int{5, 4, 1},
+ },
+ {
+ "mississi",
+ [256]int{'i': 3, 'm': 7, 's': 1},
+ []int{15, 14, 13, 7, 11, 10, 7, 1},
+ },
+ // From http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf
+ {
+ "abcxxxabc",
+ [256]int{'a': 2, 'b': 1, 'c': 6, 'x': 3},
+ []int{14, 13, 12, 11, 10, 9, 11, 10, 1},
+ },
+ {
+ "abyxcdeyx",
+ [256]int{'a': 8, 'b': 7, 'c': 4, 'd': 3, 'e': 2, 'y': 1, 'x': 5},
+ []int{17, 16, 15, 14, 13, 12, 7, 10, 1},
+ },
+ }
+
+ for _, tc := range testCases {
+ bad, good := DumpTables(tc.pattern)
+
+ for i, got := range bad {
+ want := tc.bad[i]
+ if want == 0 {
+ want = len(tc.pattern)
+ }
+ if got != want {
+ t.Errorf("boyerMoore(%q) bad['%c']: got %d want %d", tc.pattern, i, got, want)
+ }
+ }
+
+ if !reflect.DeepEqual(good, tc.suf) {
+ t.Errorf("boyerMoore(%q) got %v want %v", tc.pattern, good, tc.suf)
+ }
+ }
+}
diff --git a/libgo/go/strings/strings_test.go b/libgo/go/strings/strings_test.go
index 54046d68aa0..c271e48ab24 100644
--- a/libgo/go/strings/strings_test.go
+++ b/libgo/go/strings/strings_test.go
@@ -7,6 +7,7 @@ package strings_test
import (
"bytes"
"io"
+ "math/rand"
"reflect"
. "strings"
"testing"
@@ -311,6 +312,13 @@ var FieldsFuncTests = []FieldsTest{
}
func TestFieldsFunc(t *testing.T) {
+ for _, tt := range fieldstests {
+ a := FieldsFunc(tt.s, unicode.IsSpace)
+ if !eq(a, tt.a) {
+ t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a)
+ continue
+ }
+ }
pred := func(c rune) bool { return c == 'X' }
for _, tt := range FieldsFuncTests {
a := FieldsFunc(tt.s, pred)
@@ -984,3 +992,39 @@ func TestEqualFold(t *testing.T) {
}
}
}
+
+var makeFieldsInput = func() string {
+ x := make([]byte, 1<<20)
+ // Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
+ for i := range x {
+ switch rand.Intn(10) {
+ case 0:
+ x[i] = ' '
+ case 1:
+ if i > 0 && x[i-1] == 'x' {
+ copy(x[i-1:], "χ")
+ break
+ }
+ fallthrough
+ default:
+ x[i] = 'x'
+ }
+ }
+ return string(x)
+}
+
+var fieldsInput = makeFieldsInput()
+
+func BenchmarkFields(b *testing.B) {
+ b.SetBytes(int64(len(fieldsInput)))
+ for i := 0; i < b.N; i++ {
+ Fields(fieldsInput)
+ }
+}
+
+func BenchmarkFieldsFunc(b *testing.B) {
+ b.SetBytes(int64(len(fieldsInput)))
+ for i := 0; i < b.N; i++ {
+ FieldsFunc(fieldsInput, unicode.IsSpace)
+ }
+}
diff --git a/libgo/go/sync/atomic/64bit_linux_arm.go b/libgo/go/sync/atomic/64bit_linux_arm.go
new file mode 100644
index 00000000000..f070e78bd3c
--- /dev/null
+++ b/libgo/go/sync/atomic/64bit_linux_arm.go
@@ -0,0 +1,36 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package atomic
+
+func loadUint64(addr *uint64) (val uint64) {
+ for {
+ val = *addr
+ if CompareAndSwapUint64(addr, val, val) {
+ break
+ }
+ }
+ return
+}
+
+func storeUint64(addr *uint64, val uint64) {
+ for {
+ old := *addr
+ if CompareAndSwapUint64(addr, old, val) {
+ break
+ }
+ }
+ return
+}
+
+func addUint64(val *uint64, delta uint64) (new uint64) {
+ for {
+ old := *val
+ new = old + delta
+ if CompareAndSwapUint64(val, old, new) {
+ break
+ }
+ }
+ return
+}
diff --git a/libgo/go/sync/atomic/atomic_test.go b/libgo/go/sync/atomic/atomic_test.go
index f60d997ce83..53dfdbf40ad 100644
--- a/libgo/go/sync/atomic/atomic_test.go
+++ b/libgo/go/sync/atomic/atomic_test.go
@@ -640,73 +640,73 @@ func init() {
}
}
-func hammerAddInt32(uval *uint32, count int) {
- val := (*int32)(unsafe.Pointer(uval))
+func hammerAddInt32(uaddr *uint32, count int) {
+ addr := (*int32)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
- AddInt32(val, 1)
+ AddInt32(addr, 1)
}
}
-func hammerAddUint32(val *uint32, count int) {
+func hammerAddUint32(addr *uint32, count int) {
for i := 0; i < count; i++ {
- AddUint32(val, 1)
+ AddUint32(addr, 1)
}
}
-func hammerAddUintptr32(uval *uint32, count int) {
+func hammerAddUintptr32(uaddr *uint32, count int) {
// only safe when uintptr is 32-bit.
// not called on 64-bit systems.
- val := (*uintptr)(unsafe.Pointer(uval))
+ addr := (*uintptr)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
- AddUintptr(val, 1)
+ AddUintptr(addr, 1)
}
}
-func hammerCompareAndSwapInt32(uval *uint32, count int) {
- val := (*int32)(unsafe.Pointer(uval))
+func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
+ addr := (*int32)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *val
- if CompareAndSwapInt32(val, v, v+1) {
+ v := *addr
+ if CompareAndSwapInt32(addr, v, v+1) {
break
}
}
}
}
-func hammerCompareAndSwapUint32(val *uint32, count int) {
+func hammerCompareAndSwapUint32(addr *uint32, count int) {
for i := 0; i < count; i++ {
for {
- v := *val
- if CompareAndSwapUint32(val, v, v+1) {
+ v := *addr
+ if CompareAndSwapUint32(addr, v, v+1) {
break
}
}
}
}
-func hammerCompareAndSwapUintptr32(uval *uint32, count int) {
+func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
// only safe when uintptr is 32-bit.
// not called on 64-bit systems.
- val := (*uintptr)(unsafe.Pointer(uval))
+ addr := (*uintptr)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *val
- if CompareAndSwapUintptr(val, v, v+1) {
+ v := *addr
+ if CompareAndSwapUintptr(addr, v, v+1) {
break
}
}
}
}
-func hammerCompareAndSwapPointer32(uval *uint32, count int) {
+func hammerCompareAndSwapPointer32(uaddr *uint32, count int) {
// only safe when uintptr is 32-bit.
// not called on 64-bit systems.
- val := (*unsafe.Pointer)(unsafe.Pointer(uval))
+ addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *val
- if CompareAndSwapPointer(val, v, unsafe.Pointer(uintptr(v)+1)) {
+ v := *addr
+ if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
break
}
}
@@ -765,73 +765,73 @@ func init() {
}
}
-func hammerAddInt64(uval *uint64, count int) {
- val := (*int64)(unsafe.Pointer(uval))
+func hammerAddInt64(uaddr *uint64, count int) {
+ addr := (*int64)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
- AddInt64(val, 1)
+ AddInt64(addr, 1)
}
}
-func hammerAddUint64(val *uint64, count int) {
+func hammerAddUint64(addr *uint64, count int) {
for i := 0; i < count; i++ {
- AddUint64(val, 1)
+ AddUint64(addr, 1)
}
}
-func hammerAddUintptr64(uval *uint64, count int) {
+func hammerAddUintptr64(uaddr *uint64, count int) {
// only safe when uintptr is 64-bit.
// not called on 32-bit systems.
- val := (*uintptr)(unsafe.Pointer(uval))
+ addr := (*uintptr)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
- AddUintptr(val, 1)
+ AddUintptr(addr, 1)
}
}
-func hammerCompareAndSwapInt64(uval *uint64, count int) {
- val := (*int64)(unsafe.Pointer(uval))
+func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
+ addr := (*int64)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *val
- if CompareAndSwapInt64(val, v, v+1) {
+ v := *addr
+ if CompareAndSwapInt64(addr, v, v+1) {
break
}
}
}
}
-func hammerCompareAndSwapUint64(val *uint64, count int) {
+func hammerCompareAndSwapUint64(addr *uint64, count int) {
for i := 0; i < count; i++ {
for {
- v := *val
- if CompareAndSwapUint64(val, v, v+1) {
+ v := *addr
+ if CompareAndSwapUint64(addr, v, v+1) {
break
}
}
}
}
-func hammerCompareAndSwapUintptr64(uval *uint64, count int) {
+func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
// only safe when uintptr is 64-bit.
// not called on 32-bit systems.
- val := (*uintptr)(unsafe.Pointer(uval))
+ addr := (*uintptr)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *val
- if CompareAndSwapUintptr(val, v, v+1) {
+ v := *addr
+ if CompareAndSwapUintptr(addr, v, v+1) {
break
}
}
}
}
-func hammerCompareAndSwapPointer64(uval *uint64, count int) {
+func hammerCompareAndSwapPointer64(uaddr *uint64, count int) {
// only safe when uintptr is 64-bit.
// not called on 32-bit systems.
- val := (*unsafe.Pointer)(unsafe.Pointer(uval))
+ addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *val
- if CompareAndSwapPointer(val, v, unsafe.Pointer(uintptr(v)+1)) {
+ v := *addr
+ if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
break
}
}
@@ -871,9 +871,9 @@ func TestHammer64(t *testing.T) {
}
}
-func hammerStoreLoadInt32(t *testing.T, valp unsafe.Pointer) {
- val := (*int32)(valp)
- v := LoadInt32(val)
+func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
+ addr := (*int32)(paddr)
+ v := LoadInt32(addr)
vlo := v & ((1 << 16) - 1)
vhi := v >> 16
if vlo != vhi {
@@ -883,12 +883,12 @@ func hammerStoreLoadInt32(t *testing.T, valp unsafe.Pointer) {
if vlo == 1e4 {
new = 0
}
- StoreInt32(val, new)
+ StoreInt32(addr, new)
}
-func hammerStoreLoadUint32(t *testing.T, valp unsafe.Pointer) {
- val := (*uint32)(valp)
- v := LoadUint32(val)
+func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
+ addr := (*uint32)(paddr)
+ v := LoadUint32(addr)
vlo := v & ((1 << 16) - 1)
vhi := v >> 16
if vlo != vhi {
@@ -898,38 +898,38 @@ func hammerStoreLoadUint32(t *testing.T, valp unsafe.Pointer) {
if vlo == 1e4 {
new = 0
}
- StoreUint32(val, new)
+ StoreUint32(addr, new)
}
-func hammerStoreLoadInt64(t *testing.T, valp unsafe.Pointer) {
- val := (*int64)(valp)
- v := LoadInt64(val)
+func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
+ addr := (*int64)(paddr)
+ v := LoadInt64(addr)
vlo := v & ((1 << 32) - 1)
vhi := v >> 32
if vlo != vhi {
t.Fatalf("Int64: %#x != %#x", vlo, vhi)
}
new := v + 1 + 1<<32
- StoreInt64(val, new)
+ StoreInt64(addr, new)
}
-func hammerStoreLoadUint64(t *testing.T, valp unsafe.Pointer) {
- val := (*uint64)(valp)
- v := LoadUint64(val)
+func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
+ addr := (*uint64)(paddr)
+ v := LoadUint64(addr)
vlo := v & ((1 << 32) - 1)
vhi := v >> 32
if vlo != vhi {
t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
}
new := v + 1 + 1<<32
- StoreUint64(val, new)
+ StoreUint64(addr, new)
}
-func hammerStoreLoadUintptr(t *testing.T, valp unsafe.Pointer) {
- val := (*uintptr)(valp)
+func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
+ addr := (*uintptr)(paddr)
var test64 uint64 = 1 << 50
arch32 := uintptr(test64) == 0
- v := LoadUintptr(val)
+ v := LoadUintptr(addr)
new := v
if arch32 {
vlo := v & ((1 << 16) - 1)
@@ -950,14 +950,14 @@ func hammerStoreLoadUintptr(t *testing.T, valp unsafe.Pointer) {
inc := uint64(1 + 1<<32)
new = v + uintptr(inc)
}
- StoreUintptr(val, new)
+ StoreUintptr(addr, new)
}
-func hammerStoreLoadPointer(t *testing.T, valp unsafe.Pointer) {
- val := (*unsafe.Pointer)(valp)
+func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
+ addr := (*unsafe.Pointer)(paddr)
var test64 uint64 = 1 << 50
arch32 := uintptr(test64) == 0
- v := uintptr(LoadPointer(val))
+ v := uintptr(LoadPointer(addr))
new := v
if arch32 {
vlo := v & ((1 << 16) - 1)
@@ -978,7 +978,7 @@ func hammerStoreLoadPointer(t *testing.T, valp unsafe.Pointer) {
inc := uint64(1 + 1<<32)
new = v + uintptr(inc)
}
- StorePointer(val, unsafe.Pointer(new))
+ StorePointer(addr, unsafe.Pointer(new))
}
func TestHammerStoreLoad(t *testing.T) {
diff --git a/libgo/go/sync/atomic/doc.go b/libgo/go/sync/atomic/doc.go
index ecb4808ce58..33e1bcf0aec 100644
--- a/libgo/go/sync/atomic/doc.go
+++ b/libgo/go/sync/atomic/doc.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 !race
+
// Package atomic provides low-level atomic memory primitives
// useful for implementing synchronization algorithms.
//
@@ -14,12 +16,22 @@
// The compare-and-swap operation, implemented by the CompareAndSwapT
// functions, is the atomic equivalent of:
//
-// if *val == old {
-// *val = new
+// if *addr == old {
+// *addr = new
// return true
// }
// return false
//
+// The add operation, implemented by the AddT functions, is the atomic
+// equivalent of:
+//
+// *addr += delta
+// return *addr
+//
+// The load and store operations, implemented by the LoadT and StoreT
+// functions, are the atomic equivalents of "return *addr" and
+// "*addr = val".
+//
package atomic
import (
@@ -31,37 +43,37 @@ import (
// On x86-32, the 64-bit functions use instructions unavailable before the Pentium MMX.
// CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value.
-func CompareAndSwapInt32(val *int32, old, new int32) (swapped bool)
+func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
// CompareAndSwapInt64 executes the compare-and-swap operation for an int64 value.
-func CompareAndSwapInt64(val *int64, old, new int64) (swapped bool)
+func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
// CompareAndSwapUint32 executes the compare-and-swap operation for a uint32 value.
-func CompareAndSwapUint32(val *uint32, old, new uint32) (swapped bool)
+func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)
// CompareAndSwapUint64 executes the compare-and-swap operation for a uint64 value.
-func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool)
+func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool)
// CompareAndSwapUintptr executes the compare-and-swap operation for a uintptr value.
-func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool)
+func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool)
// CompareAndSwapPointer executes the compare-and-swap operation for a unsafe.Pointer value.
-func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
+func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
-// AddInt32 atomically adds delta to *val and returns the new value.
-func AddInt32(val *int32, delta int32) (new int32)
+// AddInt32 atomically adds delta to *addr and returns the new value.
+func AddInt32(addr *int32, delta int32) (new int32)
-// AddUint32 atomically adds delta to *val and returns the new value.
-func AddUint32(val *uint32, delta uint32) (new uint32)
+// AddUint32 atomically adds delta to *addr and returns the new value.
+func AddUint32(addr *uint32, delta uint32) (new uint32)
-// AddInt64 atomically adds delta to *val and returns the new value.
-func AddInt64(val *int64, delta int64) (new int64)
+// AddInt64 atomically adds delta to *addr and returns the new value.
+func AddInt64(addr *int64, delta int64) (new int64)
-// AddUint64 atomically adds delta to *val and returns the new value.
-func AddUint64(val *uint64, delta uint64) (new uint64)
+// AddUint64 atomically adds delta to *addr and returns the new value.
+func AddUint64(addr *uint64, delta uint64) (new uint64)
-// AddUintptr atomically adds delta to *val and returns the new value.
-func AddUintptr(val *uintptr, delta uintptr) (new uintptr)
+// AddUintptr atomically adds delta to *addr and returns the new value.
+func AddUintptr(addr *uintptr, delta uintptr) (new uintptr)
// LoadInt32 atomically loads *addr.
func LoadInt32(addr *int32) (val int32)
diff --git a/libgo/go/sync/atomic/race.go b/libgo/go/sync/atomic/race.go
new file mode 100644
index 00000000000..c3627654deb
--- /dev/null
+++ b/libgo/go/sync/atomic/race.go
@@ -0,0 +1,191 @@
+// 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.
+
+// +build race
+
+package atomic
+
+import (
+ "runtime"
+ "unsafe"
+)
+
+var mtx uint32 = 1 // same for all
+
+func CompareAndSwapInt32(val *int32, old, new int32) bool {
+ return CompareAndSwapUint32((*uint32)(unsafe.Pointer(val)), uint32(old), uint32(new))
+}
+
+func CompareAndSwapUint32(val *uint32, old, new uint32) (swapped bool) {
+ swapped = false
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(val))
+ if *val == old {
+ *val = new
+ swapped = true
+ runtime.RaceReleaseMerge(unsafe.Pointer(val))
+ }
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
+func CompareAndSwapInt64(val *int64, old, new int64) bool {
+ return CompareAndSwapUint64((*uint64)(unsafe.Pointer(val)), uint64(old), uint64(new))
+}
+
+func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool) {
+ swapped = false
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(val))
+ if *val == old {
+ *val = new
+ swapped = true
+ runtime.RaceReleaseMerge(unsafe.Pointer(val))
+ }
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
+func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) {
+ swapped = false
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(val))
+ if *val == old {
+ *val = new
+ swapped = true
+ runtime.RaceReleaseMerge(unsafe.Pointer(val))
+ }
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
+func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool) {
+ swapped = false
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(val))
+ if *val == old {
+ *val = new
+ swapped = true
+ runtime.RaceReleaseMerge(unsafe.Pointer(val))
+ }
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
+func AddInt32(val *int32, delta int32) int32 {
+ return int32(AddUint32((*uint32)(unsafe.Pointer(val)), uint32(delta)))
+}
+
+func AddUint32(val *uint32, delta uint32) (new uint32) {
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(val))
+ *val = *val + delta
+ new = *val
+ runtime.RaceReleaseMerge(unsafe.Pointer(val))
+ runtime.RaceSemrelease(&mtx)
+
+ return
+}
+
+func AddInt64(val *int64, delta int64) int64 {
+ return int64(AddUint64((*uint64)(unsafe.Pointer(val)), uint64(delta)))
+}
+
+func AddUint64(val *uint64, delta uint64) (new uint64) {
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(val))
+ *val = *val + delta
+ new = *val
+ runtime.RaceReleaseMerge(unsafe.Pointer(val))
+ runtime.RaceSemrelease(&mtx)
+
+ return
+}
+
+func AddUintptr(val *uintptr, delta uintptr) (new uintptr) {
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(val))
+ *val = *val + delta
+ new = *val
+ runtime.RaceReleaseMerge(unsafe.Pointer(val))
+ runtime.RaceSemrelease(&mtx)
+
+ return
+}
+
+func LoadInt32(addr *int32) int32 {
+ return int32(LoadUint32((*uint32)(unsafe.Pointer(addr))))
+}
+
+func LoadUint32(addr *uint32) (val uint32) {
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(addr))
+ val = *addr
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
+func LoadInt64(addr *int64) int64 {
+ return int64(LoadUint64((*uint64)(unsafe.Pointer(addr))))
+}
+
+func LoadUint64(addr *uint64) (val uint64) {
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(addr))
+ val = *addr
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
+func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) {
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(addr))
+ val = *addr
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
+func LoadUintptr(addr *uintptr) (val uintptr) {
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceAcquire(unsafe.Pointer(addr))
+ val = *addr
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
+func StoreInt32(addr *int32, val int32) {
+ StoreUint32((*uint32)(unsafe.Pointer(addr)), uint32(val))
+}
+
+func StoreUint32(addr *uint32, val uint32) {
+ runtime.RaceSemacquire(&mtx)
+ *addr = val
+ runtime.RaceRelease(unsafe.Pointer(addr))
+ runtime.RaceSemrelease(&mtx)
+}
+
+func StoreInt64(addr *int64, val int64) {
+ StoreUint64((*uint64)(unsafe.Pointer(addr)), uint64(val))
+}
+
+func StoreUint64(addr *uint64, val uint64) {
+ runtime.RaceSemacquire(&mtx)
+ *addr = val
+ runtime.RaceRelease(unsafe.Pointer(addr))
+ runtime.RaceSemrelease(&mtx)
+}
+
+func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) {
+ runtime.RaceSemacquire(&mtx)
+ *addr = val
+ runtime.RaceRelease(unsafe.Pointer(addr))
+ runtime.RaceSemrelease(&mtx)
+}
+
+func StoreUintptr(addr *uintptr, val uintptr) {
+ runtime.RaceSemacquire(&mtx)
+ *addr = val
+ runtime.RaceRelease(unsafe.Pointer(addr))
+ runtime.RaceSemrelease(&mtx)
+}
diff --git a/libgo/go/sync/cond.go b/libgo/go/sync/cond.go
index 1fc3deaf1e0..491b9856919 100644
--- a/libgo/go/sync/cond.go
+++ b/libgo/go/sync/cond.go
@@ -56,6 +56,9 @@ func NewCond(l Locker) *Cond {
// c.L.Unlock()
//
func (c *Cond) Wait() {
+ if raceenabled {
+ raceDisable()
+ }
c.m.Lock()
if c.newSema == nil {
c.newSema = new(uint32)
@@ -63,6 +66,9 @@ func (c *Cond) Wait() {
s := c.newSema
c.newWaiters++
c.m.Unlock()
+ if raceenabled {
+ raceEnable()
+ }
c.L.Unlock()
runtime_Semacquire(s)
c.L.Lock()
@@ -73,6 +79,9 @@ func (c *Cond) Wait() {
// It is allowed but not required for the caller to hold c.L
// during the call.
func (c *Cond) Signal() {
+ if raceenabled {
+ raceDisable()
+ }
c.m.Lock()
if c.oldWaiters == 0 && c.newWaiters > 0 {
// Retire old generation; rename new to old.
@@ -86,6 +95,9 @@ func (c *Cond) Signal() {
runtime_Semrelease(c.oldSema)
}
c.m.Unlock()
+ if raceenabled {
+ raceEnable()
+ }
}
// Broadcast wakes all goroutines waiting on c.
@@ -93,6 +105,9 @@ func (c *Cond) Signal() {
// It is allowed but not required for the caller to hold c.L
// during the call.
func (c *Cond) Broadcast() {
+ if raceenabled {
+ raceDisable()
+ }
c.m.Lock()
// Wake both generations.
if c.oldWaiters > 0 {
@@ -109,4 +124,7 @@ func (c *Cond) Broadcast() {
c.newSema = nil
}
c.m.Unlock()
+ if raceenabled {
+ raceEnable()
+ }
}
diff --git a/libgo/go/sync/mutex.go b/libgo/go/sync/mutex.go
index 9494cc3f826..b4629ebca53 100644
--- a/libgo/go/sync/mutex.go
+++ b/libgo/go/sync/mutex.go
@@ -10,7 +10,10 @@
// Values containing the types defined in this package should not be copied.
package sync
-import "sync/atomic"
+import (
+ "sync/atomic"
+ "unsafe"
+)
// A Mutex is a mutual exclusion lock.
// Mutexes can be created as part of other structures;
@@ -38,6 +41,9 @@ const (
func (m *Mutex) Lock() {
// Fast path: grab unlocked mutex.
if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {
+ if raceenabled {
+ raceAcquire(unsafe.Pointer(m))
+ }
return
}
@@ -61,6 +67,10 @@ func (m *Mutex) Lock() {
awoke = true
}
}
+
+ if raceenabled {
+ raceAcquire(unsafe.Pointer(m))
+ }
}
// Unlock unlocks m.
@@ -70,6 +80,10 @@ func (m *Mutex) Lock() {
// It is allowed for one goroutine to lock a Mutex and then
// arrange for another goroutine to unlock it.
func (m *Mutex) Unlock() {
+ if raceenabled {
+ raceRelease(unsafe.Pointer(m))
+ }
+
// Fast path: drop lock bit.
new := atomic.AddInt32(&m.state, -mutexLocked)
if (new+mutexLocked)&mutexLocked == 0 {
diff --git a/libgo/go/sync/once.go b/libgo/go/sync/once.go
index 04b714a3e74..1699e86a9eb 100644
--- a/libgo/go/sync/once.go
+++ b/libgo/go/sync/once.go
@@ -38,6 +38,6 @@ func (o *Once) Do(f func()) {
defer o.m.Unlock()
if o.done == 0 {
f()
- atomic.CompareAndSwapUint32(&o.done, 0, 1)
+ atomic.StoreUint32(&o.done, 1)
}
}
diff --git a/libgo/go/sync/once_test.go b/libgo/go/sync/once_test.go
index 37075af171b..183069a1a23 100644
--- a/libgo/go/sync/once_test.go
+++ b/libgo/go/sync/once_test.go
@@ -17,8 +17,11 @@ func (o *one) Increment() {
*o++
}
-func run(once *Once, o *one, c chan bool) {
+func run(t *testing.T, once *Once, o *one, c chan bool) {
once.Do(func() { o.Increment() })
+ if v := *o; v != 1 {
+ t.Errorf("once failed inside run: %d is not 1", v)
+ }
c <- true
}
@@ -28,14 +31,34 @@ func TestOnce(t *testing.T) {
c := make(chan bool)
const N = 10
for i := 0; i < N; i++ {
- go run(once, o, c)
+ go run(t, once, o, c)
}
for i := 0; i < N; i++ {
<-c
}
if *o != 1 {
- t.Errorf("once failed: %d is not 1", *o)
+ t.Errorf("once failed outside run: %d is not 1", *o)
+ }
+}
+
+func TestOncePanic(t *testing.T) {
+ once := new(Once)
+ for i := 0; i < 2; i++ {
+ func() {
+ defer func() {
+ if recover() == nil {
+ t.Fatalf("Once.Do() has not panic'ed")
+ }
+ }()
+ once.Do(func() {
+ panic("failed")
+ })
+ }()
}
+ once.Do(func() {})
+ once.Do(func() {
+ t.Fatalf("Once called twice")
+ })
}
func BenchmarkOnce(b *testing.B) {
diff --git a/libgo/go/sync/race.go b/libgo/go/sync/race.go
new file mode 100644
index 00000000000..d9431af6ffb
--- /dev/null
+++ b/libgo/go/sync/race.go
@@ -0,0 +1,34 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build race
+
+package sync
+
+import (
+ "runtime"
+ "unsafe"
+)
+
+const raceenabled = true
+
+func raceAcquire(addr unsafe.Pointer) {
+ runtime.RaceAcquire(addr)
+}
+
+func raceRelease(addr unsafe.Pointer) {
+ runtime.RaceRelease(addr)
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+ runtime.RaceReleaseMerge(addr)
+}
+
+func raceDisable() {
+ runtime.RaceDisable()
+}
+
+func raceEnable() {
+ runtime.RaceEnable()
+}
diff --git a/libgo/go/sync/race0.go b/libgo/go/sync/race0.go
new file mode 100644
index 00000000000..bef14f974f1
--- /dev/null
+++ b/libgo/go/sync/race0.go
@@ -0,0 +1,28 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !race
+
+package sync
+
+import (
+ "unsafe"
+)
+
+const raceenabled = false
+
+func raceAcquire(addr unsafe.Pointer) {
+}
+
+func raceRelease(addr unsafe.Pointer) {
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+}
+
+func raceDisable() {
+}
+
+func raceEnable() {
+}
diff --git a/libgo/go/sync/rwmutex.go b/libgo/go/sync/rwmutex.go
index 782a9c31968..b494c64355e 100644
--- a/libgo/go/sync/rwmutex.go
+++ b/libgo/go/sync/rwmutex.go
@@ -4,7 +4,10 @@
package sync
-import "sync/atomic"
+import (
+ "sync/atomic"
+ "unsafe"
+)
// An RWMutex is a reader/writer mutual exclusion lock.
// The lock can be held by an arbitrary number of readers
@@ -24,10 +27,17 @@ const rwmutexMaxReaders = 1 << 30
// RLock locks rw for reading.
func (rw *RWMutex) RLock() {
+ if raceenabled {
+ raceDisable()
+ }
if atomic.AddInt32(&rw.readerCount, 1) < 0 {
// A writer is pending, wait for it.
runtime_Semacquire(&rw.readerSem)
}
+ if raceenabled {
+ raceEnable()
+ raceAcquire(unsafe.Pointer(&rw.readerSem))
+ }
}
// RUnlock undoes a single RLock call;
@@ -35,6 +45,10 @@ func (rw *RWMutex) RLock() {
// It is a run-time error if rw is not locked for reading
// on entry to RUnlock.
func (rw *RWMutex) RUnlock() {
+ if raceenabled {
+ raceReleaseMerge(unsafe.Pointer(&rw.writerSem))
+ raceDisable()
+ }
if atomic.AddInt32(&rw.readerCount, -1) < 0 {
// A writer is pending.
if atomic.AddInt32(&rw.readerWait, -1) == 0 {
@@ -42,6 +56,9 @@ func (rw *RWMutex) RUnlock() {
runtime_Semrelease(&rw.writerSem)
}
}
+ if raceenabled {
+ raceEnable()
+ }
}
// Lock locks rw for writing.
@@ -51,6 +68,9 @@ func (rw *RWMutex) RUnlock() {
// a blocked Lock call excludes new readers from acquiring
// the lock.
func (rw *RWMutex) Lock() {
+ if raceenabled {
+ raceDisable()
+ }
// First, resolve competition with other writers.
rw.w.Lock()
// Announce to readers there is a pending writer.
@@ -59,6 +79,11 @@ func (rw *RWMutex) Lock() {
if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
runtime_Semacquire(&rw.writerSem)
}
+ if raceenabled {
+ raceEnable()
+ raceAcquire(unsafe.Pointer(&rw.readerSem))
+ raceAcquire(unsafe.Pointer(&rw.writerSem))
+ }
}
// Unlock unlocks rw for writing. It is a run-time error if rw is
@@ -68,6 +93,12 @@ func (rw *RWMutex) Lock() {
// goroutine. One goroutine may RLock (Lock) an RWMutex and then
// arrange for another goroutine to RUnlock (Unlock) it.
func (rw *RWMutex) Unlock() {
+ if raceenabled {
+ raceRelease(unsafe.Pointer(&rw.readerSem))
+ raceRelease(unsafe.Pointer(&rw.writerSem))
+ raceDisable()
+ }
+
// Announce to readers there is no active writer.
r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
// Unblock blocked readers, if any.
@@ -76,6 +107,9 @@ func (rw *RWMutex) Unlock() {
}
// Allow other writers to proceed.
rw.w.Unlock()
+ if raceenabled {
+ raceEnable()
+ }
}
// RLocker returns a Locker interface that implements
diff --git a/libgo/go/sync/waitgroup.go b/libgo/go/sync/waitgroup.go
index bc9e738e784..9b0ffec58b3 100644
--- a/libgo/go/sync/waitgroup.go
+++ b/libgo/go/sync/waitgroup.go
@@ -4,7 +4,10 @@
package sync
-import "sync/atomic"
+import (
+ "sync/atomic"
+ "unsafe"
+)
// A WaitGroup waits for a collection of goroutines to finish.
// The main goroutine calls Add to set the number of
@@ -34,6 +37,11 @@ type WaitGroup struct {
// If the counter becomes zero, all goroutines blocked on Wait() are released.
// If the counter goes negative, Add panics.
func (wg *WaitGroup) Add(delta int) {
+ if raceenabled {
+ raceReleaseMerge(unsafe.Pointer(wg))
+ raceDisable()
+ defer raceEnable()
+ }
v := atomic.AddInt32(&wg.counter, int32(delta))
if v < 0 {
panic("sync: negative WaitGroup counter")
@@ -57,7 +65,14 @@ func (wg *WaitGroup) Done() {
// Wait blocks until the WaitGroup counter is zero.
func (wg *WaitGroup) Wait() {
+ if raceenabled {
+ raceDisable()
+ }
if atomic.LoadInt32(&wg.counter) == 0 {
+ if raceenabled {
+ raceEnable()
+ raceAcquire(unsafe.Pointer(wg))
+ }
return
}
wg.m.Lock()
@@ -68,7 +83,15 @@ func (wg *WaitGroup) Wait() {
// to avoid missing an Add.
if atomic.LoadInt32(&wg.counter) == 0 {
atomic.AddInt32(&wg.waiters, -1)
+ if raceenabled {
+ raceEnable()
+ raceAcquire(unsafe.Pointer(wg))
+ raceDisable()
+ }
wg.m.Unlock()
+ if raceenabled {
+ raceEnable()
+ }
return
}
if wg.sema == nil {
@@ -77,4 +100,8 @@ func (wg *WaitGroup) Wait() {
s := wg.sema
wg.m.Unlock()
runtime_Semacquire(s)
+ if raceenabled {
+ raceEnable()
+ raceAcquire(unsafe.Pointer(wg))
+ }
}
diff --git a/libgo/go/syscall/creds_test.go b/libgo/go/syscall/creds_test.go
new file mode 100644
index 00000000000..6eaa97e57b8
--- /dev/null
+++ b/libgo/go/syscall/creds_test.go
@@ -0,0 +1,109 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+
+package syscall_test
+
+import (
+ "bytes"
+ "net"
+ "os"
+ "syscall"
+ "testing"
+)
+
+// TestSCMCredentials tests the sending and receiving of credentials
+// (PID, UID, GID) in an ancillary message between two UNIX
+// sockets. The SO_PASSCRED socket option is enabled on the sending
+// socket for this to work.
+func TestSCMCredentials(t *testing.T) {
+ fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
+ if err != nil {
+ t.Fatalf("Socketpair: %v", err)
+ }
+ defer syscall.Close(fds[0])
+ defer syscall.Close(fds[1])
+
+ err = syscall.SetsockoptInt(fds[0], syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1)
+ if err != nil {
+ t.Fatalf("SetsockoptInt: %v", err)
+ }
+
+ srv, err := net.FileConn(os.NewFile(uintptr(fds[0]), ""))
+ if err != nil {
+ t.Errorf("FileConn: %v", err)
+ return
+ }
+ defer srv.Close()
+
+ cli, err := net.FileConn(os.NewFile(uintptr(fds[1]), ""))
+ if err != nil {
+ t.Errorf("FileConn: %v", err)
+ return
+ }
+ defer cli.Close()
+
+ var ucred syscall.Ucred
+ if os.Getuid() != 0 {
+ ucred.Pid = int32(os.Getpid())
+ ucred.Uid = 0
+ ucred.Gid = 0
+ oob := syscall.UnixCredentials(&ucred)
+ _, _, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+ if err.(*net.OpError).Err != syscall.EPERM {
+ t.Fatalf("WriteMsgUnix failed with %v, want EPERM", err)
+ }
+ }
+
+ ucred.Pid = int32(os.Getpid())
+ ucred.Uid = uint32(os.Getuid())
+ ucred.Gid = uint32(os.Getgid())
+ oob := syscall.UnixCredentials(&ucred)
+
+ // this is going to send a dummy byte
+ n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+ if err != nil {
+ t.Fatalf("WriteMsgUnix: %v", err)
+ }
+ if n != 0 {
+ t.Fatalf("WriteMsgUnix n = %d, want 0", n)
+ }
+ if oobn != len(oob) {
+ t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob))
+ }
+
+ oob2 := make([]byte, 10*len(oob))
+ n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2)
+ if err != nil {
+ t.Fatalf("ReadMsgUnix: %v", err)
+ }
+ if flags != 0 {
+ t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
+ }
+ if n != 1 {
+ t.Fatalf("ReadMsgUnix n = %d, want 1 (dummy byte)", n)
+ }
+ if oobn2 != oobn {
+ // without SO_PASSCRED set on the socket, ReadMsgUnix will
+ // return zero oob bytes
+ t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn)
+ }
+ oob2 = oob2[:oobn2]
+ if !bytes.Equal(oob, oob2) {
+ t.Fatal("ReadMsgUnix oob bytes don't match")
+ }
+
+ scm, err := syscall.ParseSocketControlMessage(oob2)
+ if err != nil {
+ t.Fatalf("ParseSocketControlMessage: %v", err)
+ }
+ newUcred, err := syscall.ParseUnixCredentials(&scm[0])
+ if err != nil {
+ t.Fatalf("ParseUnixCredentials: %v", err)
+ }
+ if *newUcred != ucred {
+ t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
+ }
+}
diff --git a/libgo/go/syscall/env_windows.go b/libgo/go/syscall/env_windows.go
index 3107ae5f415..39bd5022efd 100644
--- a/libgo/go/syscall/env_windows.go
+++ b/libgo/go/syscall/env_windows.go
@@ -12,7 +12,7 @@ import (
)
func Getenv(key string) (value string, found bool) {
- keyp, err := utf16PtrFromString(key)
+ keyp, err := UTF16PtrFromString(key)
if err != nil {
return "", false
}
@@ -38,12 +38,12 @@ func Setenv(key, value string) error {
var v *uint16
var err error
if len(value) > 0 {
- v, err = utf16PtrFromString(value)
+ v, err = UTF16PtrFromString(value)
if err != nil {
return err
}
}
- keyp, err := utf16PtrFromString(key)
+ keyp, err := UTF16PtrFromString(key)
if err != nil {
return err
}
diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go
index b34ee1bf882..813627bf2fe 100644
--- a/libgo/go/syscall/exec_unix.go
+++ b/libgo/go/syscall/exec_unix.go
@@ -50,10 +50,6 @@ import (
//sysnb raw_dup2(oldfd int, newfd int) (err Errno)
//dup2(oldfd int, newfd int) int
-// Note: not raw, returns error rather than Errno.
-//sys read(fd int, p *byte, np int) (n int, err error)
-//read(fd int, buf *byte, count Size_t) Ssize_t
-
// Lock synchronizing creation of new file descriptors with fork.
//
// We want the child in a fork/exec sequence to inherit only the
@@ -103,7 +99,7 @@ import (
var ForkLock sync.RWMutex
-// Convert array of string to array of NUL-terminated byte pointer.
+// StringSlicePtr is deprecated. Use SlicePtrFromStrings instead.
// If any string contains a NUL byte this function panics instead
// of returning an error.
func StringSlicePtr(ss []string) []*byte {
@@ -115,14 +111,14 @@ func StringSlicePtr(ss []string) []*byte {
return bb
}
-// slicePtrFromStrings converts a slice of strings to a slice of
+// SlicePtrFromStrings converts a slice of strings to a slice of
// pointers to NUL-terminated byte slices. If any string contains
// a NUL byte, it returns (nil, EINVAL).
-func slicePtrFromStrings(ss []string) ([]*byte, error) {
+func SlicePtrFromStrings(ss []string) ([]*byte, error) {
var err error
bb := make([]*byte, len(ss)+1)
for i := 0; i < len(ss); i++ {
- bb[i], err = bytePtrFromString(ss[i])
+ bb[i], err = BytePtrFromString(ss[i])
if err != nil {
return nil, err
}
@@ -185,15 +181,15 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
p[1] = -1
// Convert args to C form.
- argv0p, err := bytePtrFromString(argv0)
+ argv0p, err := BytePtrFromString(argv0)
if err != nil {
return 0, err
}
- argvp, err := slicePtrFromStrings(argv)
+ argvp, err := SlicePtrFromStrings(argv)
if err != nil {
return 0, err
}
- envvp, err := slicePtrFromStrings(attr.Env)
+ envvp, err := SlicePtrFromStrings(attr.Env)
if err != nil {
return 0, err
}
@@ -204,14 +200,14 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
var chroot *byte
if sys.Chroot != "" {
- chroot, err = bytePtrFromString(sys.Chroot)
+ chroot, err = BytePtrFromString(sys.Chroot)
if err != nil {
return 0, err
}
}
var dir *byte
if attr.Dir != "" {
- dir, err = bytePtrFromString(attr.Dir)
+ dir, err = BytePtrFromString(attr.Dir)
if err != nil {
return 0, err
}
@@ -242,7 +238,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
// Read child error status from pipe.
Close(p[1])
- n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+ n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
Close(p[0])
if err != nil || n != 0 {
if n == int(unsafe.Sizeof(err1)) {
@@ -286,15 +282,15 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
// Ordinary exec.
func Exec(argv0 string, argv []string, envv []string) (err error) {
- argv0p, err := bytePtrFromString(argv0)
+ argv0p, err := BytePtrFromString(argv0)
if err != nil {
return err
}
- argvp, err := slicePtrFromStrings(argv)
+ argvp, err := SlicePtrFromStrings(argv)
if err != nil {
return err
}
- envvp, err := slicePtrFromStrings(envv)
+ envvp, err := SlicePtrFromStrings(envv)
if err != nil {
return err
}
diff --git a/libgo/go/syscall/exec_windows.go b/libgo/go/syscall/exec_windows.go
index 68779c461a0..82abc0715e5 100644
--- a/libgo/go/syscall/exec_windows.go
+++ b/libgo/go/syscall/exec_windows.go
@@ -132,7 +132,7 @@ func SetNonblock(fd Handle, nonblocking bool) (err error) {
// getFullPath retrieves the full path of the specified file.
// Just a wrapper for Windows GetFullPathName api.
func getFullPath(name string) (path string, err error) {
- p, err := utf16PtrFromString(name)
+ p, err := UTF16PtrFromString(name)
if err != nil {
return "", err
}
@@ -228,8 +228,9 @@ type ProcAttr struct {
}
type SysProcAttr struct {
- HideWindow bool
- CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
+ HideWindow bool
+ CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
+ CreationFlags uint32
}
var zeroProcAttr ProcAttr
@@ -264,7 +265,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
return 0, 0, err
}
}
- argv0p, err := utf16PtrFromString(argv0)
+ argv0p, err := UTF16PtrFromString(argv0)
if err != nil {
return 0, 0, err
}
@@ -281,7 +282,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
var argvp *uint16
if len(cmdline) != 0 {
- argvp, err = utf16PtrFromString(cmdline)
+ argvp, err = UTF16PtrFromString(cmdline)
if err != nil {
return 0, 0, err
}
@@ -289,7 +290,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
var dirp *uint16
if len(attr.Dir) != 0 {
- dirp, err = utf16PtrFromString(attr.Dir)
+ dirp, err = UTF16PtrFromString(attr.Dir)
if err != nil {
return 0, 0, err
}
@@ -325,7 +326,8 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
pi := new(ProcessInformation)
- err = CreateProcess(argv0p, argvp, nil, nil, true, CREATE_UNICODE_ENVIRONMENT, createEnvBlock(attr.Env), dirp, si, pi)
+ flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT
+ err = CreateProcess(argv0p, argvp, nil, nil, true, flags, createEnvBlock(attr.Env), dirp, si, pi)
if err != nil {
return 0, 0, err
}
diff --git a/libgo/go/syscall/libcall_posix.go b/libgo/go/syscall/libcall_posix.go
index 4f25b82649a..9623103243e 100644
--- a/libgo/go/syscall/libcall_posix.go
+++ b/libgo/go/syscall/libcall_posix.go
@@ -277,7 +277,10 @@ func Gettimeofday(tv *Timeval) (err error) {
//sys Pause() (err error)
//pause() int
-//sys Read(fd int, p []byte) (n int, err error)
+//sys read(fd int, p []byte) (n int, err error)
+//read(fd int, buf *byte, count Size_t) Ssize_t
+
+//sys readlen(fd int, p *byte, np int) (n int, err error)
//read(fd int, buf *byte, count Size_t) Ssize_t
//sys Readlink(path string, buf []byte) (n int, err error)
@@ -344,7 +347,10 @@ func Settimeofday(tv *Timeval) (err error) {
//sys Utime(path string, buf *Utimbuf) (err error)
//utime(path *byte, buf *Utimbuf) int
-//sys Write(fd int, p []byte) (n int, err error)
+//sys write(fd int, p []byte) (n int, err error)
+//write(fd int, buf *byte, count Size_t) Ssize_t
+
+//sys writelen(fd int, p *byte, np int) (n int, err error)
//write(fd int, buf *byte, count Size_t) Ssize_t
//sys munmap(addr uintptr, length uintptr) (err error)
diff --git a/libgo/go/syscall/mksyscall.awk b/libgo/go/syscall/mksyscall.awk
index b81796031ca..74f0e28af4d 100644
--- a/libgo/go/syscall/mksyscall.awk
+++ b/libgo/go/syscall/mksyscall.awk
@@ -104,6 +104,19 @@ BEGIN {
loc = gofnname "/" cfnname ":"
+ haserr = 0
+ if (gofnresults != "") {
+ fields = split(gofnresults, goresults, ", *")
+ for (goresult = 1; goresults[goresult] != ""; goresult++) {
+ if (split(goresults[goresult], goparam) == 2) {
+ if (goparam[1] == "err") {
+ haserr = 1
+ break
+ }
+ }
+ }
+ }
+
split(gofnparams, goargs, ", *")
split(cfnparams, cargs, ", *")
args = ""
@@ -147,7 +160,14 @@ BEGIN {
status = 1
next
}
- printf("\t_p%d := StringBytePtr(%s)\n", goarg, goname)
+ printf("\tvar _p%d *byte\n", goarg)
+ if (haserr) {
+ printf("\t_p%d, err = BytePtrFromString(%s)\n", goarg, goname)
+ printf("\tif err != nil {\n\t\treturn\n\t}\n")
+ } else {
+ print loc, "uses string arguments but has no error return" | "cat 1>&2"
+ printf("\t_p%d, _ = BytePtrFromString(%s)\n", goarg, goname)
+ }
args = sprintf("%s_p%d", args, goarg)
} else if (gotype ~ /^\[\](.*)/) {
if (ctype !~ /^\*/ || cargs[carg + 1] == "") {
diff --git a/libgo/go/syscall/passfd_test.go b/libgo/go/syscall/passfd_test.go
new file mode 100644
index 00000000000..20ef39ecaab
--- /dev/null
+++ b/libgo/go/syscall/passfd_test.go
@@ -0,0 +1,151 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux darwin
+
+package syscall_test
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "os"
+ "os/exec"
+ "syscall"
+ "testing"
+ "time"
+)
+
+// TestPassFD tests passing a file descriptor over a Unix socket.
+//
+// This test involved both a parent and child process. The parent
+// process is invoked as a normal test, with "go test", which then
+// runs the child process by running the current test binary with args
+// "-test.run=^TestPassFD$" and an environment variable used to signal
+// that the test should become the child process instead.
+func TestPassFD(t *testing.T) {
+ if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
+ passFDChild()
+ return
+ }
+
+ tempDir, err := ioutil.TempDir("", "TestPassFD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tempDir)
+
+ fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
+ if err != nil {
+ t.Fatalf("Socketpair: %v", err)
+ }
+ defer syscall.Close(fds[0])
+ defer syscall.Close(fds[1])
+ writeFile := os.NewFile(uintptr(fds[0]), "child-writes")
+ readFile := os.NewFile(uintptr(fds[1]), "parent-reads")
+ defer writeFile.Close()
+ defer readFile.Close()
+
+ cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir)
+ cmd.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
+ cmd.ExtraFiles = []*os.File{writeFile}
+
+ out, err := cmd.CombinedOutput()
+ if len(out) > 0 || err != nil {
+ t.Fatalf("child process: %q, %v", out, err)
+ }
+
+ c, err := net.FileConn(readFile)
+ if err != nil {
+ t.Fatalf("FileConn: %v", err)
+ }
+ defer c.Close()
+
+ uc, ok := c.(*net.UnixConn)
+ if !ok {
+ t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c)
+ }
+
+ buf := make([]byte, 32) // expect 1 byte
+ oob := make([]byte, 32) // expect 24 bytes
+ closeUnix := time.AfterFunc(5*time.Second, func() {
+ t.Logf("timeout reading from unix socket")
+ uc.Close()
+ })
+ _, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
+ closeUnix.Stop()
+
+ scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
+ if err != nil {
+ t.Fatalf("ParseSocketControlMessage: %v", err)
+ }
+ if len(scms) != 1 {
+ t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms)
+ }
+ scm := scms[0]
+ gotFds, err := syscall.ParseUnixRights(&scm)
+ if err != nil {
+ t.Fatalf("syscall.ParseUnixRights: %v", err)
+ }
+ if len(gotFds) != 1 {
+ t.Fatalf("wanted 1 fd; got %#v", gotFds)
+ }
+
+ f := os.NewFile(uintptr(gotFds[0]), "fd-from-child")
+ defer f.Close()
+
+ got, err := ioutil.ReadAll(f)
+ want := "Hello from child process!\n"
+ if string(got) != want {
+ t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want)
+ }
+}
+
+// passFDChild is the child process used by TestPassFD.
+func passFDChild() {
+ defer os.Exit(0)
+
+ // Look for our fd. It should be fd 3, but we work around an fd leak
+ // bug here (http://golang.org/issue/2603) to let it be elsewhere.
+ var uc *net.UnixConn
+ for fd := uintptr(3); fd <= 10; fd++ {
+ f := os.NewFile(fd, "unix-conn")
+ var ok bool
+ netc, _ := net.FileConn(f)
+ uc, ok = netc.(*net.UnixConn)
+ if ok {
+ break
+ }
+ }
+ if uc == nil {
+ fmt.Println("failed to find unix fd")
+ return
+ }
+
+ // Make a file f to send to our parent process on uc.
+ // We make it in tempDir, which our parent will clean up.
+ flag.Parse()
+ tempDir := flag.Arg(0)
+ f, err := ioutil.TempFile(tempDir, "")
+ if err != nil {
+ fmt.Printf("TempFile: %v", err)
+ return
+ }
+
+ f.Write([]byte("Hello from child process!\n"))
+ f.Seek(0, 0)
+
+ rights := syscall.UnixRights(int(f.Fd()))
+ dummyByte := []byte("x")
+ n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil)
+ if err != nil {
+ fmt.Printf("WriteMsgUnix: %v", err)
+ return
+ }
+ if n != 1 || oobn != len(rights) {
+ fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights))
+ return
+ }
+}
diff --git a/libgo/go/syscall/race0.go b/libgo/go/syscall/race0.go
new file mode 100644
index 00000000000..e94fb47afbe
--- /dev/null
+++ b/libgo/go/syscall/race0.go
@@ -0,0 +1,19 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !race
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+const raceenabled = false
+
+func raceAcquire(addr unsafe.Pointer) {
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+}
diff --git a/libgo/go/syscall/security_windows.go b/libgo/go/syscall/security_windows.go
index 4353af4fb90..71aef2fcafe 100644
--- a/libgo/go/syscall/security_windows.go
+++ b/libgo/go/syscall/security_windows.go
@@ -37,7 +37,7 @@ const (
// TranslateAccountName converts a directory service
// object name from one format to another.
func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
- u, e := utf16PtrFromString(username)
+ u, e := UTF16PtrFromString(username)
if e != nil {
return "", e
}
@@ -97,7 +97,7 @@ type SID struct{}
// sid into a valid, functional sid.
func StringToSid(s string) (*SID, error) {
var sid *SID
- p, e := utf16PtrFromString(s)
+ p, e := UTF16PtrFromString(s)
if e != nil {
return nil, e
}
@@ -116,13 +116,13 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32,
if len(account) == 0 {
return nil, "", 0, EINVAL
}
- acc, e := utf16PtrFromString(account)
+ acc, e := UTF16PtrFromString(account)
if e != nil {
return nil, "", 0, e
}
var sys *uint16
if len(system) > 0 {
- sys, e = utf16PtrFromString(system)
+ sys, e = UTF16PtrFromString(system)
if e != nil {
return nil, "", 0, e
}
@@ -183,7 +183,7 @@ func (sid *SID) Copy() (*SID, error) {
func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
var sys *uint16
if len(system) > 0 {
- sys, err = utf16PtrFromString(system)
+ sys, err = UTF16PtrFromString(system)
if err != nil {
return "", "", 0, err
}
diff --git a/libgo/go/syscall/syscall.go b/libgo/go/syscall/syscall.go
index 3090a5ec697..56296c84bf6 100644
--- a/libgo/go/syscall/syscall.go
+++ b/libgo/go/syscall/syscall.go
@@ -16,21 +16,21 @@ package syscall
import "unsafe"
-// StringByteSlice returns a NUL-terminated slice of bytes containing the text of s.
+// StringByteSlice is deprecated. Use ByteSliceFromString instead.
// If s contains a NUL byte this function panics instead of
// returning an error.
func StringByteSlice(s string) []byte {
- a, err := byteSliceFromString(s)
+ a, err := ByteSliceFromString(s)
if err != nil {
panic("syscall: string with NUL passed to StringByteSlice")
}
return a
}
-// byteSliceFromString returns a NUL-terminated slice of bytes
+// ByteSliceFromString returns a NUL-terminated slice of bytes
// containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, EINVAL).
-func byteSliceFromString(s string) ([]byte, error) {
+func ByteSliceFromString(s string) ([]byte, error) {
for i := 0; i < len(s); i++ {
if s[i] == 0 {
return nil, EINVAL
@@ -41,16 +41,16 @@ func byteSliceFromString(s string) ([]byte, error) {
return a, nil
}
-// StringBytePtr returns a pointer to a NUL-terminated array of bytes containing the text of s.
+// StringBytePtr is deprecated. Use BytePtrFromString instead.
// If s contains a NUL byte this function panics instead of
// returning an error.
func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }
-// bytePtrFromString returns a pointer to a NUL-terminated array of
+// BytePtrFromString returns a pointer to a NUL-terminated array of
// bytes containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, EINVAL).
-func bytePtrFromString(s string) (*byte, error) {
- a, err := byteSliceFromString(s)
+func BytePtrFromString(s string) (*byte, error) {
+ a, err := ByteSliceFromString(s)
if err != nil {
return nil, err
}
diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go
index d4bff9efc9c..fb62681a9e1 100644
--- a/libgo/go/syscall/syscall_unix.go
+++ b/libgo/go/syscall/syscall_unix.go
@@ -179,3 +179,20 @@ func Signame(s Signal) string
func (s Signal) String() string {
return Signame(s)
}
+
+func Read(fd int, p []byte) (n int, err error) {
+ n, err = read(fd, p)
+ if raceenabled && err == nil {
+ raceAcquire(unsafe.Pointer(&ioSync))
+ }
+ return
+}
+
+func Write(fd int, p []byte) (n int, err error) {
+ if raceenabled {
+ raceReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ return write(fd, p)
+}
+
+var ioSync int64
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index 41290594ee2..cb92fab50ad 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -9,11 +9,19 @@ import (
"fmt"
"os"
"runtime"
+ "sync"
"time"
)
var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
-var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
+var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
+var benchmarkMemory = flag.Bool("test.benchmem", false, "print memory allocations for benchmarks")
+
+// Global lock to ensure only one benchmark runs at a time.
+var benchmarkLock sync.Mutex
+
+// Used for every benchmark for measuring memory.
+var memStats runtime.MemStats
// An internal type but exported because it is cross-package; part of the implementation
// of the "go test" command.
@@ -31,6 +39,12 @@ type B struct {
bytes int64
timerOn bool
result BenchmarkResult
+ // The initial states of memStats.Mallocs and memStats.TotalAlloc.
+ startAllocs uint64
+ startBytes uint64
+ // The net total of this test after being run.
+ netAllocs uint64
+ netBytes uint64
}
// StartTimer starts timing a test. This function is called automatically
@@ -38,6 +52,9 @@ type B struct {
// a call to StopTimer.
func (b *B) StartTimer() {
if !b.timerOn {
+ runtime.ReadMemStats(&memStats)
+ b.startAllocs = memStats.Mallocs
+ b.startBytes = memStats.TotalAlloc
b.start = time.Now()
b.timerOn = true
}
@@ -49,6 +66,9 @@ func (b *B) StartTimer() {
func (b *B) StopTimer() {
if b.timerOn {
b.duration += time.Now().Sub(b.start)
+ runtime.ReadMemStats(&memStats)
+ b.netAllocs += memStats.Mallocs - b.startAllocs
+ b.netBytes += memStats.TotalAlloc - b.startBytes
b.timerOn = false
}
}
@@ -57,9 +77,14 @@ func (b *B) StopTimer() {
// It does not affect whether the timer is running.
func (b *B) ResetTimer() {
if b.timerOn {
+ runtime.ReadMemStats(&memStats)
+ b.startAllocs = memStats.Mallocs
+ b.startBytes = memStats.TotalAlloc
b.start = time.Now()
}
b.duration = 0
+ b.netAllocs = 0
+ b.netBytes = 0
}
// SetBytes records the number of bytes processed in a single operation.
@@ -75,6 +100,8 @@ func (b *B) nsPerOp() int64 {
// runN runs a single benchmark for the specified number of iterations.
func (b *B) runN(n int) {
+ benchmarkLock.Lock()
+ defer benchmarkLock.Unlock()
// Try to get a comparable environment for each run
// by clearing garbage from previous runs.
runtime.GC()
@@ -151,7 +178,7 @@ func (b *B) launch() {
b.runN(n)
// Run the benchmark for at least the specified amount of time.
- d := time.Duration(*benchTime * float64(time.Second))
+ d := *benchTime
for !b.failed && b.duration < d && n < 1e9 {
last := n
// Predict iterations/sec.
@@ -168,14 +195,16 @@ func (b *B) launch() {
n = roundUp(n)
b.runN(n)
}
- b.result = BenchmarkResult{b.N, b.duration, b.bytes}
+ b.result = BenchmarkResult{b.N, b.duration, b.bytes, b.netAllocs, b.netBytes}
}
// The results of a benchmark run.
type BenchmarkResult struct {
- N int // The number of iterations.
- T time.Duration // The total time taken.
- Bytes int64 // Bytes processed in one iteration.
+ N int // The number of iterations.
+ T time.Duration // The total time taken.
+ Bytes int64 // Bytes processed in one iteration.
+ MemAllocs uint64 // The total number of memory allocations.
+ MemBytes uint64 // The total number of bytes allocated.
}
func (r BenchmarkResult) NsPerOp() int64 {
@@ -192,6 +221,20 @@ func (r BenchmarkResult) mbPerSec() float64 {
return (float64(r.Bytes) * float64(r.N) / 1e6) / r.T.Seconds()
}
+func (r BenchmarkResult) AllocsPerOp() int64 {
+ if r.N <= 0 {
+ return 0
+ }
+ return int64(r.MemAllocs) / int64(r.N)
+}
+
+func (r BenchmarkResult) AllocedBytesPerOp() int64 {
+ if r.N <= 0 {
+ return 0
+ }
+ return int64(r.MemBytes) / int64(r.N)
+}
+
func (r BenchmarkResult) String() string {
mbs := r.mbPerSec()
mb := ""
@@ -212,6 +255,11 @@ func (r BenchmarkResult) String() string {
return fmt.Sprintf("%8d\t%s%s", r.N, ns, mb)
}
+func (r BenchmarkResult) MemString() string {
+ return fmt.Sprintf("%8d B/op\t%8d allocs/op",
+ r.AllocedBytesPerOp(), r.AllocsPerOp())
+}
+
// An internal function but exported because it is cross-package; part of the implementation
// of the "go test" command.
func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
@@ -249,7 +297,11 @@ func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks [
fmt.Printf("--- FAIL: %s\n%s", benchName, b.output)
continue
}
- fmt.Printf("%v\n", r)
+ results := r.String()
+ if *benchmarkMemory {
+ results += "\t" + r.MemString()
+ }
+ fmt.Println(results)
// Unlike with tests, we ignore the -chatty flag and always print output for
// benchmarks since the output generation time will skew the results.
if len(b.output) > 0 {
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index e56b77c9c77..60edbd55ebd 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -13,7 +13,10 @@
// Functions of the form
// func BenchmarkXxx(*testing.B)
// are considered benchmarks, and are executed by the "go test" command when
-// the -test.bench flag is provided.
+// the -test.bench flag is provided. Benchmarks are run sequentially.
+//
+// For a description of the testing flags, see
+// http://golang.org/cmd/go/#Description_of_testing_flags.
//
// A sample benchmark function looks like this:
// func BenchmarkHello(b *testing.B) {
@@ -24,15 +27,14 @@
//
// The benchmark package will vary b.N until the benchmark function lasts
// long enough to be timed reliably. The output
-// testing.BenchmarkHello 10000000 282 ns/op
+// BenchmarkHello 10000000 282 ns/op
// means that the loop ran 10000000 times at a speed of 282 ns per loop.
//
// If a benchmark needs some expensive setup before running, the timer
-// may be stopped:
+// may be reset:
// func BenchmarkBigLen(b *testing.B) {
-// b.StopTimer()
// big := NewBig()
-// b.StartTimer()
+// b.ResetTimer()
// for i := 0; i < b.N; i++ {
// big.Len()
// }
@@ -100,14 +102,16 @@ var (
short = flag.Bool("test.short", false, "run smaller test suite to save time")
// Report as tests are run; default is silent for success.
- chatty = flag.Bool("test.v", false, "verbose: print additional output")
- match = flag.String("test.run", "", "regular expression to select tests and examples to run")
- memProfile = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
- memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
- cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
- timeout = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
- cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
- parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+ chatty = flag.Bool("test.v", false, "verbose: print additional output")
+ match = flag.String("test.run", "", "regular expression to select tests and examples to run")
+ memProfile = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
+ memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
+ cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
+ blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to the named file after execution")
+ blockProfileRate = flag.Int("test.blockprofilerate", 1, "if >= 0, calls runtime.SetBlockProfileRate()")
+ timeout = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
+ cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+ parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
haveExamples bool // are there examples?
@@ -132,6 +136,11 @@ func Short() bool {
return *short
}
+// Verbose reports whether the -test.v flag is set.
+func Verbose() bool {
+ return *chatty
+}
+
// decorate prefixes the string with the file and line of the call site
// and inserts the final newline if needed and indentation tabs for formatting.
func decorate(s string) string {
@@ -151,6 +160,9 @@ func decorate(s string) string {
fmt.Fprintf(buf, "%s:%d: ", file, line)
lines := strings.Split(s, "\n")
+ if l := len(lines); l > 1 && lines[l-1] == "" {
+ lines = lines[:l-1]
+ }
for i, line := range lines {
if i > 0 {
buf.WriteByte('\n')
@@ -163,10 +175,7 @@ func decorate(s string) string {
}
buf.WriteString(line)
}
- if l := len(s); l > 0 && s[len(s)-1] != '\n' {
- // Add final new line if needed.
- buf.WriteByte('\n')
- }
+ buf.WriteByte('\n')
return buf.String()
}
@@ -413,7 +422,9 @@ func before() {
}
// Could save f so after can call f.Close; not worth the effort.
}
-
+ if *blockProfile != "" && *blockProfileRate >= 0 {
+ runtime.SetBlockProfileRate(*blockProfileRate)
+ }
}
// after runs after all testing.
@@ -432,6 +443,17 @@ func after() {
}
f.Close()
}
+ if *blockProfile != "" && *blockProfileRate >= 0 {
+ f, err := os.Create(*blockProfile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "testing: %s", err)
+ return
+ }
+ if err = pprof.Lookup("block").WriteTo(f, 0); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *blockProfile, err)
+ }
+ f.Close()
+ }
}
var timer *time.Timer
diff --git a/libgo/go/text/scanner/scanner.go b/libgo/go/text/scanner/scanner.go
index 565650edf9c..e0d86e343da 100644
--- a/libgo/go/text/scanner/scanner.go
+++ b/libgo/go/text/scanner/scanner.go
@@ -5,7 +5,8 @@
// Package scanner provides a scanner and tokenizer for UTF-8-encoded text.
// It takes an io.Reader providing the source, which then can be tokenized
// through repeated calls to the Scan function. For compatibility with
-// existing tools, the NUL character is not allowed.
+// existing tools, the NUL character is not allowed. If the first character
+// in the source is a UTF-8 encoded byte order mark (BOM), it is discarded.
//
// By default, a Scanner skips white space and Go comments and recognizes all
// literals as defined by the Go language specification. It may be
@@ -208,11 +209,6 @@ func (s *Scanner) Init(src io.Reader) *Scanner {
return s
}
-// TODO(gri): The code for next() and the internal scanner state could benefit
-// from a rethink. While next() is optimized for the common ASCII
-// case, the "corrections" needed for proper position tracking undo
-// some of the attempts for fast-path optimization.
-
// next reads and returns the next Unicode character. It is designed such
// that only a minimal amount of work needs to be done in the common ASCII
// case (one test to check for both ASCII and end-of-buffer, and one test
@@ -316,7 +312,11 @@ func (s *Scanner) Next() rune {
// character of the source.
func (s *Scanner) Peek() rune {
if s.ch < 0 {
+ // this code is only run for the very first character
s.ch = s.next()
+ if s.ch == '\uFEFF' {
+ s.ch = s.next() // ignore BOM
+ }
}
return s.ch
}
@@ -389,15 +389,20 @@ func (s *Scanner) scanNumber(ch rune) (rune, rune) {
if ch == 'x' || ch == 'X' {
// hexadecimal int
ch = s.next()
+ hasMantissa := false
for digitVal(ch) < 16 {
ch = s.next()
+ hasMantissa = true
+ }
+ if !hasMantissa {
+ s.error("illegal hexadecimal number")
}
} else {
// octal int or float
- seenDecimalDigit := false
+ has8or9 := false
for isDecimal(ch) {
if ch > '7' {
- seenDecimalDigit = true
+ has8or9 = true
}
ch = s.next()
}
@@ -408,7 +413,7 @@ func (s *Scanner) scanNumber(ch rune) (rune, rune) {
return Float, ch
}
// octal int
- if seenDecimalDigit {
+ if has8or9 {
s.error("illegal octal number")
}
}
diff --git a/libgo/go/text/scanner/scanner_test.go b/libgo/go/text/scanner/scanner_test.go
index bb3adb55a77..496eed4a31d 100644
--- a/libgo/go/text/scanner/scanner_test.go
+++ b/libgo/go/text/scanner/scanner_test.go
@@ -358,8 +358,10 @@ func TestScanSelectedMask(t *testing.T) {
}
func TestScanNext(t *testing.T) {
- s := new(Scanner).Init(bytes.NewBufferString("if a == bcd /* comment */ {\n\ta += c\n} // line comment ending in eof"))
- checkTok(t, s, 1, s.Scan(), Ident, "if")
+ const BOM = '\uFEFF'
+ BOMs := string(BOM)
+ s := new(Scanner).Init(bytes.NewBufferString(BOMs + "if a == bcd /* com" + BOMs + "ment */ {\n\ta += c\n}" + BOMs + "// line comment ending in eof"))
+ checkTok(t, s, 1, s.Scan(), Ident, "if") // the first BOM is ignored
checkTok(t, s, 1, s.Scan(), Ident, "a")
checkTok(t, s, 1, s.Scan(), '=', "=")
checkTok(t, s, 0, s.Next(), '=', "")
@@ -372,6 +374,7 @@ func TestScanNext(t *testing.T) {
checkTok(t, s, 0, s.Next(), '=', "")
checkTok(t, s, 2, s.Scan(), Ident, "c")
checkTok(t, s, 3, s.Scan(), '}', "}")
+ checkTok(t, s, 3, s.Scan(), BOM, BOMs)
checkTok(t, s, 3, s.Scan(), -1, "")
if s.ErrorCount != 0 {
t.Errorf("%d errors", s.ErrorCount)
@@ -446,6 +449,9 @@ func TestError(t *testing.T) {
testError(t, `"\'"`, "1:3", "illegal char escape", String)
testError(t, `01238`, "1:6", "illegal octal number", Int)
+ testError(t, `01238123`, "1:9", "illegal octal number", Int)
+ testError(t, `0x`, "1:3", "illegal hexadecimal number", Int)
+ testError(t, `0xg`, "1:3", "illegal hexadecimal number", Int)
testError(t, `'aa'`, "1:4", "illegal char literal", Char)
testError(t, `'`, "1:2", "literal not terminated", Char)
diff --git a/libgo/go/text/template/doc.go b/libgo/go/text/template/doc.go
index 4a1682d97a3..807914c24c8 100644
--- a/libgo/go/text/template/doc.go
+++ b/libgo/go/text/template/doc.go
@@ -100,6 +100,7 @@ An argument is a simple value, denoted by one of the following.
- A boolean, string, character, integer, floating-point, imaginary
or complex constant in Go syntax. These behave like Go's untyped
constants, although raw strings may not span newlines.
+ - The keyword nil, representing an untyped Go nil.
- The character '.' (period):
.
The result is the value of dot.
@@ -147,6 +148,10 @@ An argument is a simple value, denoted by one of the following.
The result is the value of invoking the function, fun(). The return
types and values behave as in methods. Functions and function
names are described below.
+ - A parenthesized instance of one the above, for grouping. The result
+ may be accessed by a field or map key invocation.
+ print (.F1 arg1) (.F2 arg2)
+ (.StructValuedMethod "arg").Field
Arguments may evaluate to any type; if they are pointers the implementation
automatically indirects to the base type when required.
@@ -227,6 +232,8 @@ All produce the quoted word "output":
{{"output" | printf "%q"}}
A function call whose final argument comes from the previous
command.
+ {{printf "%q" (print "out" "put")}}
+ A parenthesized argument.
{{"put" | printf "%s%s" "out" | printf "%q"}}
A more elaborate call.
{{"output" | printf "%s" | printf "%q"}}
diff --git a/libgo/go/text/template/exec.go b/libgo/go/text/template/exec.go
index aba21ce28f5..b9c03d8f0b8 100644
--- a/libgo/go/text/template/exec.go
+++ b/libgo/go/text/template/exec.go
@@ -20,7 +20,7 @@ import (
type state struct {
tmpl *Template
wr io.Writer
- line int // line number for errors
+ node parse.Node // current node, for errors
vars []variable // push-down stack of variable values.
}
@@ -63,17 +63,32 @@ func (s *state) varValue(name string) reflect.Value {
var zero reflect.Value
+// at marks the state to be on node n, for error reporting.
+func (s *state) at(node parse.Node) {
+ s.node = node
+}
+
+// doublePercent returns the string with %'s replaced by %%, if necessary,
+// so it can be used safely inside a Printf format string.
+func doublePercent(str string) string {
+ if strings.Contains(str, "%") {
+ str = strings.Replace(str, "%", "%%", -1)
+ }
+ return str
+}
+
// errorf formats the error and terminates processing.
func (s *state) errorf(format string, args ...interface{}) {
- format = fmt.Sprintf("template: %s:%d: %s", s.tmpl.Name(), s.line, format)
+ name := doublePercent(s.tmpl.Name())
+ if s.node == nil {
+ format = fmt.Sprintf("template: %s: %s", name, format)
+ } else {
+ location, context := s.tmpl.ErrorContext(s.node)
+ format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format)
+ }
panic(fmt.Errorf(format, args...))
}
-// error terminates processing.
-func (s *state) error(err error) {
- s.errorf("%s", err)
-}
-
// errRecover is the handler that turns panics into returns from the top
// level of Parse.
func errRecover(errp *error) {
@@ -108,7 +123,6 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
state := &state{
tmpl: t,
wr: wr,
- line: 1,
vars: []variable{{"$", value}},
}
if t.Tree == nil || t.Root == nil {
@@ -120,38 +134,34 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
// Walk functions step through the major pieces of the template structure,
// generating output as they go.
-func (s *state) walk(dot reflect.Value, n parse.Node) {
- switch n := n.(type) {
+func (s *state) walk(dot reflect.Value, node parse.Node) {
+ s.at(node)
+ switch node := node.(type) {
case *parse.ActionNode:
- s.line = n.Line
// Do not pop variables so they persist until next end.
// Also, if the action declares variables, don't print the result.
- val := s.evalPipeline(dot, n.Pipe)
- if len(n.Pipe.Decl) == 0 {
- s.printValue(n, val)
+ val := s.evalPipeline(dot, node.Pipe)
+ if len(node.Pipe.Decl) == 0 {
+ s.printValue(node, val)
}
case *parse.IfNode:
- s.line = n.Line
- s.walkIfOrWith(parse.NodeIf, dot, n.Pipe, n.List, n.ElseList)
+ s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
case *parse.ListNode:
- for _, node := range n.Nodes {
+ for _, node := range node.Nodes {
s.walk(dot, node)
}
case *parse.RangeNode:
- s.line = n.Line
- s.walkRange(dot, n)
+ s.walkRange(dot, node)
case *parse.TemplateNode:
- s.line = n.Line
- s.walkTemplate(dot, n)
+ s.walkTemplate(dot, node)
case *parse.TextNode:
- if _, err := s.wr.Write(n.Text); err != nil {
- s.error(err)
+ if _, err := s.wr.Write(node.Text); err != nil {
+ s.errorf("%s", err)
}
case *parse.WithNode:
- s.line = n.Line
- s.walkIfOrWith(parse.NodeWith, dot, n.Pipe, n.List, n.ElseList)
+ s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
default:
- s.errorf("unknown node: %s", n)
+ s.errorf("unknown node: %s", node)
}
}
@@ -206,6 +216,7 @@ func isTrue(val reflect.Value) (truth, ok bool) {
}
func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
+ s.at(r)
defer s.pop(s.mark())
val, _ := indirect(s.evalPipeline(dot, r.Pipe))
// mark top of stack before any variables in the body are pushed.
@@ -266,6 +277,7 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
}
func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
+ s.at(t)
tmpl := s.tmpl.tmpl[t.Name]
if tmpl == nil {
s.errorf("template %q not defined", t.Name)
@@ -291,6 +303,7 @@ func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value ref
if pipe == nil {
return
}
+ s.at(pipe)
for _, cmd := range pipe.Cmds {
value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
// If the object has type interface{}, dig down one level to the thing inside.
@@ -315,18 +328,26 @@ func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final ref
switch n := firstWord.(type) {
case *parse.FieldNode:
return s.evalFieldNode(dot, n, cmd.Args, final)
+ case *parse.ChainNode:
+ return s.evalChainNode(dot, n, cmd.Args, final)
case *parse.IdentifierNode:
// Must be a function.
- return s.evalFunction(dot, n.Ident, cmd.Args, final)
+ return s.evalFunction(dot, n, cmd, cmd.Args, final)
+ case *parse.PipeNode:
+ // Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored.
+ return s.evalPipeline(dot, n)
case *parse.VariableNode:
return s.evalVariableNode(dot, n, cmd.Args, final)
}
+ s.at(firstWord)
s.notAFunction(cmd.Args, final)
switch word := firstWord.(type) {
case *parse.BoolNode:
return reflect.ValueOf(word.True)
case *parse.DotNode:
return dot
+ case *parse.NilNode:
+ s.errorf("nil is not a command")
case *parse.NumberNode:
return s.idealConstant(word)
case *parse.StringNode:
@@ -344,6 +365,7 @@ func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
// These are ideal constants but we don't know the type
// and we have no context. (If it was a method argument,
// we'd know what we need.) The syntax guides us to some extent.
+ s.at(constant)
switch {
case constant.IsComplex:
return reflect.ValueOf(constant.Complex128) // incontrovertible.
@@ -362,43 +384,57 @@ func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
}
func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value {
- return s.evalFieldChain(dot, dot, field.Ident, args, final)
+ s.at(field)
+ return s.evalFieldChain(dot, dot, field, field.Ident, args, final)
+}
+
+func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value {
+ s.at(chain)
+ // (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields.
+ pipe := s.evalArg(dot, nil, chain.Node)
+ if len(chain.Field) == 0 {
+ s.errorf("internal error: no fields in evalChainNode")
+ }
+ return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final)
}
-func (s *state) evalVariableNode(dot reflect.Value, v *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalVariableNode(dot reflect.Value, variable *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
// $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
- value := s.varValue(v.Ident[0])
- if len(v.Ident) == 1 {
+ s.at(variable)
+ value := s.varValue(variable.Ident[0])
+ if len(variable.Ident) == 1 {
s.notAFunction(args, final)
return value
}
- return s.evalFieldChain(dot, value, v.Ident[1:], args, final)
+ return s.evalFieldChain(dot, value, variable, variable.Ident[1:], args, final)
}
// evalFieldChain evaluates .X.Y.Z possibly followed by arguments.
// dot is the environment in which to evaluate arguments, while
// receiver is the value being walked along the chain.
-func (s *state) evalFieldChain(dot, receiver reflect.Value, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
n := len(ident)
for i := 0; i < n-1; i++ {
- receiver = s.evalField(dot, ident[i], nil, zero, receiver)
+ receiver = s.evalField(dot, ident[i], node, nil, zero, receiver)
}
// Now if it's a method, it gets the arguments.
- return s.evalField(dot, ident[n-1], args, final, receiver)
+ return s.evalField(dot, ident[n-1], node, args, final, receiver)
}
-func (s *state) evalFunction(dot reflect.Value, name string, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value {
+ s.at(node)
+ name := node.Ident
function, ok := findFunction(name, s.tmpl)
if !ok {
s.errorf("%q is not a defined function", name)
}
- return s.evalCall(dot, function, name, args, final)
+ return s.evalCall(dot, function, cmd, name, args, final)
}
// evalField evaluates an expression like (.Field) or (.Field arg1 arg2).
// The 'final' argument represents the return value from the preceding
// value of the pipeline, if any.
-func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node, final, receiver reflect.Value) reflect.Value {
+func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value {
if !receiver.IsValid() {
return zero
}
@@ -411,26 +447,31 @@ func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node
ptr = ptr.Addr()
}
if method := ptr.MethodByName(fieldName); method.IsValid() {
- return s.evalCall(dot, method, fieldName, args, final)
+ return s.evalCall(dot, method, node, fieldName, args, final)
}
hasArgs := len(args) > 1 || final.IsValid()
- // It's not a method; is it a field of a struct?
+ // It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
receiver, isNil := indirect(receiver)
- if receiver.Kind() == reflect.Struct {
+ if isNil {
+ s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
+ }
+ switch receiver.Kind() {
+ case reflect.Struct:
tField, ok := receiver.Type().FieldByName(fieldName)
if ok {
field := receiver.FieldByIndex(tField.Index)
- if tField.PkgPath == "" { // field is exported
- // If it's a function, we must call it.
- if hasArgs {
- s.errorf("%s has arguments but cannot be invoked as function", fieldName)
- }
- return field
+ if tField.PkgPath != "" { // field is unexported
+ s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
+ }
+ // If it's a function, we must call it.
+ if hasArgs {
+ s.errorf("%s has arguments but cannot be invoked as function", fieldName)
}
+ return field
}
- }
- // If it's a map, attempt to use the field name as a key.
- if receiver.Kind() == reflect.Map {
+ s.errorf("%s is not a field of struct type %s", fieldName, typ)
+ case reflect.Map:
+ // If it's a map, attempt to use the field name as a key.
nameVal := reflect.ValueOf(fieldName)
if nameVal.Type().AssignableTo(receiver.Type().Key()) {
if hasArgs {
@@ -439,9 +480,6 @@ func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node
return receiver.MapIndex(nameVal)
}
}
- if isNil {
- s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
- }
s.errorf("can't evaluate field %s in type %s", fieldName, typ)
panic("not reached")
}
@@ -454,7 +492,7 @@ var (
// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
// it looks just like a function call. The arg list, if non-nil, includes (in the manner of the shell), arg[0]
// as the function itself.
-func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value {
if args != nil {
args = args[1:] // Zeroth arg is function name/node; not passed to function.
}
@@ -473,7 +511,8 @@ func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node,
s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args))
}
if !goodFunc(typ) {
- s.errorf("can't handle multiple results from method/function %q", name)
+ // TODO: This could still be a confusing error; maybe goodFunc should provide info.
+ s.errorf("can't call method/function %q with %d results", name, typ.NumOut())
}
// Build the arg list.
argv := make([]reflect.Value, numIn)
@@ -500,24 +539,31 @@ func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node,
result := fun.Call(argv)
// If we have an error that is not nil, stop execution and return that error to the caller.
if len(result) == 2 && !result[1].IsNil() {
+ s.at(node)
s.errorf("error calling %s: %s", name, result[1].Interface().(error))
}
return result[0]
}
+// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
+func canBeNil(typ reflect.Type) bool {
+ switch typ.Kind() {
+ case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+ return true
+ }
+ return false
+}
+
// validateType guarantees that the value is valid and assignable to the type.
func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
if !value.IsValid() {
- switch typ.Kind() {
- case reflect.Interface, reflect.Ptr, reflect.Chan, reflect.Map, reflect.Slice, reflect.Func:
+ if typ == nil || canBeNil(typ) {
// An untyped nil interface{}. Accept as a proper nil value.
- // TODO: Can we delete the other types in this list? Should we?
- value = reflect.Zero(typ)
- default:
- s.errorf("invalid value; expected %s", typ)
+ return reflect.Zero(typ)
}
+ s.errorf("invalid value; expected %s", typ)
}
- if !value.Type().AssignableTo(typ) {
+ if typ != nil && !value.Type().AssignableTo(typ) {
if value.Kind() == reflect.Interface && !value.IsNil() {
value = value.Elem()
if value.Type().AssignableTo(typ) {
@@ -542,13 +588,21 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
}
func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
switch arg := n.(type) {
case *parse.DotNode:
return s.validateType(dot, typ)
+ case *parse.NilNode:
+ if canBeNil(typ) {
+ return reflect.Zero(typ)
+ }
+ s.errorf("cannot assign nil to %s", typ)
case *parse.FieldNode:
return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ)
case *parse.VariableNode:
return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
+ case *parse.PipeNode:
+ return s.validateType(s.evalPipeline(dot, arg), typ)
}
switch typ.Kind() {
case reflect.Bool:
@@ -573,6 +627,7 @@ func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) refle
}
func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
if n, ok := n.(*parse.BoolNode); ok {
value := reflect.New(typ).Elem()
value.SetBool(n.True)
@@ -583,6 +638,7 @@ func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
}
func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
if n, ok := n.(*parse.StringNode); ok {
value := reflect.New(typ).Elem()
value.SetString(n.Text)
@@ -593,6 +649,7 @@ func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
}
func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
if n, ok := n.(*parse.NumberNode); ok && n.IsInt {
value := reflect.New(typ).Elem()
value.SetInt(n.Int64)
@@ -603,6 +660,7 @@ func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
}
func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
if n, ok := n.(*parse.NumberNode); ok && n.IsUint {
value := reflect.New(typ).Elem()
value.SetUint(n.Uint64)
@@ -613,6 +671,7 @@ func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Valu
}
func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
if n, ok := n.(*parse.NumberNode); ok && n.IsFloat {
value := reflect.New(typ).Elem()
value.SetFloat(n.Float64)
@@ -633,6 +692,7 @@ func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value {
}
func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value {
+ s.at(n)
switch n := n.(type) {
case *parse.BoolNode:
return reflect.ValueOf(n.True)
@@ -641,13 +701,18 @@ func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Valu
case *parse.FieldNode:
return s.evalFieldNode(dot, n, nil, zero)
case *parse.IdentifierNode:
- return s.evalFunction(dot, n.Ident, nil, zero)
+ return s.evalFunction(dot, n, n, nil, zero)
+ case *parse.NilNode:
+ // NilNode is handled in evalArg, the only place that calls here.
+ s.errorf("evalEmptyInterface: nil (can't happen)")
case *parse.NumberNode:
return s.idealConstant(n)
case *parse.StringNode:
return reflect.ValueOf(n.Text)
case *parse.VariableNode:
return s.evalVariableNode(dot, n, nil, zero)
+ case *parse.PipeNode:
+ return s.evalPipeline(dot, n)
}
s.errorf("can't handle assignment of %s to empty interface argument", n)
panic("not reached")
@@ -671,6 +736,7 @@ func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
// printValue writes the textual representation of the value to the output of
// the template.
func (s *state) printValue(n parse.Node, v reflect.Value) {
+ s.at(n)
if v.Kind() == reflect.Ptr {
v, _ = indirect(v) // fmt.Fprint handles nil.
}
diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go
index 64149533b3e..683e9ac76b6 100644
--- a/libgo/go/text/template/exec_test.go
+++ b/libgo/go/text/template/exec_test.go
@@ -63,8 +63,11 @@ type T struct {
BinaryFunc func(string, string) string
VariadicFunc func(...string) string
VariadicFuncInt func(int, ...string) string
+ NilOKFunc func(*int) bool
// Template to test evaluation of templates.
Tmpl *Template
+ // Unexported field; cannot be accessed by template.
+ unexported int
}
type U struct {
@@ -125,6 +128,7 @@ var tVal = &T{
BinaryFunc: func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) },
VariadicFunc: func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
VariadicFuncInt: func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
+ NilOKFunc: func(s *int) bool { return s == nil },
Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X
}
@@ -220,6 +224,7 @@ var execTests = []execTest{
// Trivial cases.
{"empty", "", "", nil, true},
{"text", "some text", "some text", nil, true},
+ {"nil action", "{{nil}}", "", nil, false},
// Ideal constants.
{"ideal int", "{{typeOf 3}}", "int", 0, true},
@@ -228,10 +233,12 @@ var execTests = []execTest{
{"ideal complex", "{{typeOf 1i}}", "complex128", 0, true},
{"ideal int", "{{typeOf " + bigInt + "}}", "int", 0, true},
{"ideal too big", "{{typeOf " + bigUint + "}}", "", 0, false},
+ {"ideal nil without type", "{{nil}}", "", 0, false},
// Fields of structs.
{".X", "-{{.X}}-", "-x-", tVal, true},
{".U.V", "-{{.U.V}}-", "-v-", tVal, true},
+ {".unexported", "{{.unexported}}", "", tVal, false},
// Fields on maps.
{"map .one", "{{.MSI.one}}", "1", tVal, true},
@@ -292,7 +299,8 @@ var execTests = []execTest{
{".Method2(3, .X)", "-{{.Method2 3 .X}}-", "-Method2: 3 x-", tVal, true},
{".Method2(.U16, `str`)", "-{{.Method2 .U16 `str`}}-", "-Method2: 16 str-", tVal, true},
{".Method2(.U16, $x)", "{{if $x := .X}}-{{.Method2 .U16 $x}}{{end}}-", "-Method2: 16 x-", tVal, true},
- {".Method3(nil)", "-{{.Method3 .MXI.unset}}-", "-Method3: <nil>-", tVal, true},
+ {".Method3(nil constant)", "-{{.Method3 nil}}-", "-Method3: <nil>-", tVal, true},
+ {".Method3(nil value)", "-{{.Method3 .MXI.unset}}-", "-Method3: <nil>-", tVal, true},
{"method on var", "{{if $x := .}}-{{$x.Method2 .U16 $x.X}}{{end}}-", "-Method2: 16 x-", tVal, true},
{"method on chained var",
"{{range .MSIone}}{{if $.U.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}",
@@ -303,6 +311,8 @@ var execTests = []execTest{
{"chained method on variable",
"{{with $x := .}}{{with .SI}}{{$.GetU.TrueFalse $.True}}{{end}}{{end}}",
"true", tVal, true},
+ {".NilOKFunc not nil", "{{call .NilOKFunc .PI}}", "false", tVal, true},
+ {".NilOKFunc nil", "{{call .NilOKFunc nil}}", "true", tVal, true},
// Function call builtin.
{".BinaryFunc", "{{call .BinaryFunc `1` `2`}}", "[1=2]", tVal, true},
@@ -321,14 +331,25 @@ var execTests = []execTest{
{".VariadicFuncBad0", "{{call .VariadicFunc 3}}", "", tVal, false},
{".VariadicFuncIntBad0", "{{call .VariadicFuncInt}}", "", tVal, false},
{".VariadicFuncIntBad`", "{{call .VariadicFuncInt `x`}}", "", tVal, false},
+ {".VariadicFuncNilBad", "{{call .VariadicFunc nil}}", "", tVal, false},
// Pipelines.
{"pipeline", "-{{.Method0 | .Method2 .U16}}-", "-Method2: 16 M0-", tVal, true},
{"pipeline func", "-{{call .VariadicFunc `llo` | call .VariadicFunc `he` }}-", "-<he+<llo>>-", tVal, true},
+ // Parenthesized expressions
+ {"parens in pipeline", "{{printf `%d %d %d` (1) (2 | add 3) (add 4 (add 5 6))}}", "1 5 15", tVal, true},
+
+ // Parenthesized expressions with field accesses
+ {"parens: $ in paren", "{{($).X}}", "x", tVal, true},
+ {"parens: $.GetU in paren", "{{($.GetU).V}}", "v", tVal, true},
+ {"parens: $ in paren in pipe", "{{($ | echo).X}}", "x", tVal, true},
+ {"parens: spaces and args", `{{(makemap "up" "down" "left" "right").left}}`, "right", tVal, true},
+
// If.
{"if true", "{{if true}}TRUE{{end}}", "TRUE", tVal, true},
{"if false", "{{if false}}TRUE{{else}}FALSE{{end}}", "FALSE", tVal, true},
+ {"if nil", "{{if nil}}TRUE{{end}}", "", tVal, false},
{"if 1", "{{if 1}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
{"if 0", "{{if 0}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
{"if 1.5", "{{if 1.5}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
@@ -348,7 +369,8 @@ var execTests = []execTest{
// Print etc.
{"print", `{{print "hello, print"}}`, "hello, print", tVal, true},
- {"print", `{{print 1 2 3}}`, "1 2 3", tVal, true},
+ {"print 123", `{{print 1 2 3}}`, "1 2 3", tVal, true},
+ {"print nil", `{{print nil}}`, "<nil>", tVal, true},
{"println", `{{println 1 2 3}}`, "1 2 3\n", tVal, true},
{"printf int", `{{printf "%04x" 127}}`, "007f", tVal, true},
{"printf float", `{{printf "%g" 3.5}}`, "3.5", tVal, true},
@@ -388,6 +410,7 @@ var execTests = []execTest{
{"map[one]", "{{index .MSI `one`}}", "1", tVal, true},
{"map[two]", "{{index .MSI `two`}}", "2", tVal, true},
{"map[NO]", "{{index .MSI `XXX`}}", "0", tVal, true},
+ {"map[nil]", "{{index .MSI nil}}", "0", tVal, true},
{"map[WRONG]", "{{index .MSI 10}}", "", tVal, false},
{"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true},
@@ -474,6 +497,8 @@ var execTests = []execTest{
// Pipelined arg was not being type-checked.
{"bug8a", "{{3|oneArg}}", "", tVal, false},
{"bug8b", "{{4|dddArg 3}}", "", tVal, false},
+ // A bug was introduced that broke map lookups for lower-case names.
+ {"bug9", "{{.cause}}", "neglect", map[string]string{"cause": "neglect"}, true},
}
func zeroArgs() string {
@@ -508,6 +533,29 @@ func vfunc(V, *V) string {
return "vfunc"
}
+func add(args ...int) int {
+ sum := 0
+ for _, x := range args {
+ sum += x
+ }
+ return sum
+}
+
+func echo(arg interface{}) interface{} {
+ return arg
+}
+
+func makemap(arg ...string) map[string]string {
+ if len(arg)%2 != 0 {
+ panic("bad makemap")
+ }
+ m := make(map[string]string)
+ for i := 0; i < len(arg); i += 2 {
+ m[arg[i]] = arg[i+1]
+ }
+ return m
+}
+
func stringer(s fmt.Stringer) string {
return s.String()
}
@@ -515,8 +563,11 @@ func stringer(s fmt.Stringer) string {
func testExecute(execTests []execTest, template *Template, t *testing.T) {
b := new(bytes.Buffer)
funcs := FuncMap{
+ "add": add,
"count": count,
"dddArg": dddArg,
+ "echo": echo,
+ "makemap": makemap,
"oneArg": oneArg,
"typeOf": typeOf,
"vfunc": vfunc,
@@ -624,6 +675,32 @@ func TestExecuteError(t *testing.T) {
}
}
+const execErrorText = `line 1
+line 2
+line 3
+{{template "one" .}}
+{{define "one"}}{{template "two" .}}{{end}}
+{{define "two"}}{{template "three" .}}{{end}}
+{{define "three"}}{{index "hi" $}}{{end}}`
+
+// Check that an error from a nested template contains all the relevant information.
+func TestExecError(t *testing.T) {
+ tmpl, err := New("top").Parse(execErrorText)
+ if err != nil {
+ t.Fatal("parse error:", err)
+ }
+ var b bytes.Buffer
+ err = tmpl.Execute(&b, 5) // 5 is out of range indexing "hi"
+ if err == nil {
+ t.Fatal("expected error")
+ }
+ const want = `template: top:7:20: executing "three" at <index "hi" $>: error calling index: index out of range: 5`
+ got := err.Error()
+ if got != want {
+ t.Errorf("expected\n%q\ngot\n%q", want, got)
+ }
+}
+
func TestJSEscaping(t *testing.T) {
testCases := []struct {
in, exp string
@@ -734,3 +811,8 @@ func TestTree(t *testing.T) {
t.Errorf("expected %q got %q", expect, result)
}
}
+
+func TestExecuteOnNewTemplate(t *testing.T) {
+ // This is issue 3872.
+ _ = New("Name").Templates()
+}
diff --git a/libgo/go/text/template/funcs.go b/libgo/go/text/template/funcs.go
index e6fa0fb5f2a..31549dc45b8 100644
--- a/libgo/go/text/template/funcs.go
+++ b/libgo/go/text/template/funcs.go
@@ -54,7 +54,7 @@ func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
panic("value for " + name + " not a function")
}
if !goodFunc(v.Type()) {
- panic(fmt.Errorf("can't handle multiple results from method/function %q", name))
+ panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut()))
}
out[name] = v
}
@@ -107,7 +107,7 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
return nil, fmt.Errorf("index of nil pointer")
}
switch v.Kind() {
- case reflect.Array, reflect.Slice:
+ case reflect.Array, reflect.Slice, reflect.String:
var x int64
switch index.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -122,6 +122,9 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
}
v = v.Index(int(x))
case reflect.Map:
+ if !index.IsValid() {
+ index = reflect.Zero(v.Type().Key())
+ }
if !index.Type().AssignableTo(v.Type().Key()) {
return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
}
@@ -131,7 +134,7 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
v = reflect.Zero(v.Type().Elem())
}
default:
- return nil, fmt.Errorf("can't index item of type %s", index.Type())
+ return nil, fmt.Errorf("can't index item of type %s", v.Type())
}
}
return v.Interface(), nil
@@ -187,10 +190,13 @@ func call(fn interface{}, args ...interface{}) (interface{}, error) {
} else {
argType = dddType
}
+ if !value.IsValid() && canBeNil(argType) {
+ value = reflect.Zero(argType)
+ }
if !value.Type().AssignableTo(argType) {
return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType)
}
- argv[i] = reflect.ValueOf(arg)
+ argv[i] = value
}
result := v.Call(argv)
if len(result) == 2 {
diff --git a/libgo/go/text/template/parse/lex.go b/libgo/go/text/template/parse/lex.go
index c4e1a56a8d4..23c0cf0793c 100644
--- a/libgo/go/text/template/parse/lex.go
+++ b/libgo/go/text/template/parse/lex.go
@@ -13,8 +13,9 @@ import (
// item represents a token or text string returned from the scanner.
type item struct {
- typ itemType
- val string
+ typ itemType // The type of this item.
+ pos Pos // The starting position, in bytes, of this item in the input string.
+ val string // The value of this item.
}
func (i item) String() string {
@@ -42,65 +43,32 @@ const (
itemComplex // complex constant (1+2i); imaginary is just a number
itemColonEquals // colon-equals (':=') introducing a declaration
itemEOF
- itemField // alphanumeric identifier, starting with '.', possibly chained ('.x.y')
- itemIdentifier // alphanumeric identifier
+ itemField // alphanumeric identifier starting with '.'
+ itemIdentifier // alphanumeric identifier not starting with '.'
itemLeftDelim // left action delimiter
+ itemLeftParen // '(' inside action
itemNumber // simple number, including imaginary
itemPipe // pipe symbol
itemRawString // raw quoted string (includes quotes)
itemRightDelim // right action delimiter
+ itemRightParen // ')' inside action
+ itemSpace // run of spaces separating arguments
itemString // quoted string (includes quotes)
itemText // plain text
- itemVariable // variable starting with '$', such as '$' or '$1' or '$hello'.
+ itemVariable // variable starting with '$', such as '$' or '$1' or '$hello'
// Keywords appear after all the rest.
itemKeyword // used only to delimit the keywords
- itemDot // the cursor, spelled '.'.
+ itemDot // the cursor, spelled '.'
itemDefine // define keyword
itemElse // else keyword
itemEnd // end keyword
itemIf // if keyword
+ itemNil // the untyped nil constant, easiest to treat as a keyword
itemRange // range keyword
itemTemplate // template keyword
itemWith // with keyword
)
-// Make the types prettyprint.
-var itemName = map[itemType]string{
- itemError: "error",
- itemBool: "bool",
- itemChar: "char",
- itemCharConstant: "charconst",
- itemComplex: "complex",
- itemColonEquals: ":=",
- itemEOF: "EOF",
- itemField: "field",
- itemIdentifier: "identifier",
- itemLeftDelim: "left delim",
- itemNumber: "number",
- itemPipe: "pipe",
- itemRawString: "raw string",
- itemRightDelim: "right delim",
- itemString: "string",
- itemVariable: "variable",
- // keywords
- itemDot: ".",
- itemDefine: "define",
- itemElse: "else",
- itemIf: "if",
- itemEnd: "end",
- itemRange: "range",
- itemTemplate: "template",
- itemWith: "with",
-}
-
-func (i itemType) String() string {
- s := itemName[i]
- if s == "" {
- return fmt.Sprintf("item%d", int(i))
- }
- return s
-}
-
var key = map[string]itemType{
".": itemDot,
"define": itemDefine,
@@ -108,6 +76,7 @@ var key = map[string]itemType{
"end": itemEnd,
"if": itemIf,
"range": itemRange,
+ "nil": itemNil,
"template": itemTemplate,
"with": itemWith,
}
@@ -119,24 +88,27 @@ type stateFn func(*lexer) stateFn
// lexer holds the state of the scanner.
type lexer struct {
- name string // the name of the input; used only for error reports.
- input string // the string being scanned.
- leftDelim string // start of action.
- rightDelim string // end of action.
- state stateFn // the next lexing function to enter.
- pos int // current position in the input.
- start int // start position of this item.
- width int // width of last rune read from input.
- items chan item // channel of scanned items.
+ name string // the name of the input; used only for error reports
+ input string // the string being scanned
+ leftDelim string // start of action
+ rightDelim string // end of action
+ state stateFn // the next lexing function to enter
+ pos Pos // current position in the input
+ start Pos // start position of this item
+ width Pos // width of last rune read from input
+ lastPos Pos // position of most recent item returned by nextItem
+ items chan item // channel of scanned items
+ parenDepth int // nesting depth of ( ) exprs
}
// next returns the next rune in the input.
-func (l *lexer) next() (r rune) {
- if l.pos >= len(l.input) {
+func (l *lexer) next() rune {
+ if int(l.pos) >= len(l.input) {
l.width = 0
return eof
}
- r, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
+ r, w := utf8.DecodeRuneInString(l.input[l.pos:])
+ l.width = Pos(w)
l.pos += l.width
return r
}
@@ -155,7 +127,7 @@ func (l *lexer) backup() {
// emit passes an item back to the client.
func (l *lexer) emit(t itemType) {
- l.items <- item{t, l.input[l.start:l.pos]}
+ l.items <- item{t, l.start, l.input[l.start:l.pos]}
l.start = l.pos
}
@@ -180,30 +152,25 @@ func (l *lexer) acceptRun(valid string) {
l.backup()
}
-// lineNumber reports which line we're on. Doing it this way
+// lineNumber reports which line we're on, based on the position of
+// the previous item returned by nextItem. Doing it this way
// means we don't have to worry about peek double counting.
func (l *lexer) lineNumber() int {
- return 1 + strings.Count(l.input[:l.pos], "\n")
+ return 1 + strings.Count(l.input[:l.lastPos], "\n")
}
-// error returns an error token and terminates the scan by passing
+// errorf returns an error token and terminates the scan by passing
// back a nil pointer that will be the next state, terminating l.nextItem.
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
- l.items <- item{itemError, fmt.Sprintf(format, args...)}
+ l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
return nil
}
// nextItem returns the next item from the input.
func (l *lexer) nextItem() item {
- for {
- select {
- case item := <-l.items:
- return item
- default:
- l.state = l.state(l)
- }
- }
- panic("not reached")
+ item := <-l.items
+ l.lastPos = item.pos
+ return item
}
// lex creates a new scanner for the input string.
@@ -219,12 +186,19 @@ func lex(name, input, left, right string) *lexer {
input: input,
leftDelim: left,
rightDelim: right,
- state: lexText,
- items: make(chan item, 2), // Two items of buffering is sufficient for all state functions
+ items: make(chan item),
}
+ go l.run()
return l
}
+// run runs the state machine for the lexer.
+func (l *lexer) run() {
+ for l.state = lexText; l.state != nil; {
+ l.state = l.state(l)
+ }
+}
+
// state functions
const (
@@ -257,29 +231,30 @@ func lexText(l *lexer) stateFn {
// lexLeftDelim scans the left delimiter, which is known to be present.
func lexLeftDelim(l *lexer) stateFn {
- l.pos += len(l.leftDelim)
+ l.pos += Pos(len(l.leftDelim))
if strings.HasPrefix(l.input[l.pos:], leftComment) {
return lexComment
}
l.emit(itemLeftDelim)
+ l.parenDepth = 0
return lexInsideAction
}
// lexComment scans a comment. The left comment marker is known to be present.
func lexComment(l *lexer) stateFn {
- l.pos += len(leftComment)
+ l.pos += Pos(len(leftComment))
i := strings.Index(l.input[l.pos:], rightComment+l.rightDelim)
if i < 0 {
return l.errorf("unclosed comment")
}
- l.pos += i + len(rightComment) + len(l.rightDelim)
+ l.pos += Pos(i + len(rightComment) + len(l.rightDelim))
l.ignore()
return lexText
}
// lexRightDelim scans the right delimiter, which is known to be present.
func lexRightDelim(l *lexer) stateFn {
- l.pos += len(l.rightDelim)
+ l.pos += Pos(len(l.rightDelim))
l.emit(itemRightDelim)
return lexText
}
@@ -287,16 +262,19 @@ func lexRightDelim(l *lexer) stateFn {
// lexInsideAction scans the elements inside action delimiters.
func lexInsideAction(l *lexer) stateFn {
// Either number, quoted string, or identifier.
- // Spaces separate and are ignored.
+ // Spaces separate arguments; runs of spaces turn into itemSpace.
// Pipe symbols separate and are emitted.
if strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
- return lexRightDelim
+ if l.parenDepth == 0 {
+ return lexRightDelim
+ }
+ return l.errorf("unclosed left paren")
}
switch r := l.next(); {
- case r == eof || r == '\n':
+ case r == eof || isEndOfLine(r):
return l.errorf("unclosed action")
case isSpace(r):
- l.ignore()
+ return lexSpace
case r == ':':
if l.next() != '=' {
return l.errorf("expected :=")
@@ -309,15 +287,15 @@ func lexInsideAction(l *lexer) stateFn {
case r == '`':
return lexRawQuote
case r == '$':
- return lexIdentifier
+ return lexVariable
case r == '\'':
return lexChar
case r == '.':
// special look-ahead for ".field" so we don't break l.backup().
- if l.pos < len(l.input) {
+ if l.pos < Pos(len(l.input)) {
r := l.input[l.pos]
if r < '0' || '9' < r {
- return lexIdentifier // itemDot comes from the keyword table.
+ return lexField
}
}
fallthrough // '.' can start a number.
@@ -327,6 +305,17 @@ func lexInsideAction(l *lexer) stateFn {
case isAlphaNumeric(r):
l.backup()
return lexIdentifier
+ case r == '(':
+ l.emit(itemLeftParen)
+ l.parenDepth++
+ return lexInsideAction
+ case r == ')':
+ l.emit(itemRightParen)
+ l.parenDepth--
+ if l.parenDepth < 0 {
+ return l.errorf("unexpected right paren %#U", r)
+ }
+ return lexInsideAction
case r <= unicode.MaxASCII && unicode.IsPrint(r):
l.emit(itemChar)
return lexInsideAction
@@ -336,28 +325,34 @@ func lexInsideAction(l *lexer) stateFn {
return lexInsideAction
}
-// lexIdentifier scans an alphanumeric or field.
+// lexSpace scans a run of space characters.
+// One space has already been seen.
+func lexSpace(l *lexer) stateFn {
+ for isSpace(l.peek()) {
+ l.next()
+ }
+ l.emit(itemSpace)
+ return lexInsideAction
+}
+
+// lexIdentifier scans an alphanumeric.
func lexIdentifier(l *lexer) stateFn {
Loop:
for {
switch r := l.next(); {
case isAlphaNumeric(r):
// absorb.
- case r == '.' && (l.input[l.start] == '.' || l.input[l.start] == '$'):
- // field chaining; absorb into one token.
default:
l.backup()
word := l.input[l.start:l.pos]
if !l.atTerminator() {
- return l.errorf("unexpected character %+U", r)
+ return l.errorf("bad character %#U", r)
}
switch {
case key[word] > itemKeyword:
l.emit(key[word])
case word[0] == '.':
l.emit(itemField)
- case word[0] == '$':
- l.emit(itemVariable)
case word == "true", word == "false":
l.emit(itemBool)
default:
@@ -369,17 +364,59 @@ Loop:
return lexInsideAction
}
+// lexField scans a field: .Alphanumeric.
+// The . has been scanned.
+func lexField(l *lexer) stateFn {
+ return lexFieldOrVariable(l, itemField)
+}
+
+// lexVariable scans a Variable: $Alphanumeric.
+// The $ has been scanned.
+func lexVariable(l *lexer) stateFn {
+ if l.atTerminator() { // Nothing interesting follows -> "$".
+ l.emit(itemVariable)
+ return lexInsideAction
+ }
+ return lexFieldOrVariable(l, itemVariable)
+}
+
+// lexVariable scans a field or variable: [.$]Alphanumeric.
+// The . or $ has been scanned.
+func lexFieldOrVariable(l *lexer, typ itemType) stateFn {
+ if l.atTerminator() { // Nothing interesting follows -> "." or "$".
+ if typ == itemVariable {
+ l.emit(itemVariable)
+ } else {
+ l.emit(itemDot)
+ }
+ return lexInsideAction
+ }
+ var r rune
+ for {
+ r = l.next()
+ if !isAlphaNumeric(r) {
+ l.backup()
+ break
+ }
+ }
+ if !l.atTerminator() {
+ return l.errorf("bad character %#U", r)
+ }
+ l.emit(typ)
+ return lexInsideAction
+}
+
// atTerminator reports whether the input is at valid termination character to
-// appear after an identifier. Mostly to catch cases like "$x+2" not being
-// acceptable without a space, in case we decide one day to implement
-// arithmetic.
+// appear after an identifier. Breaks .X.Y into two pieces. Also catches cases
+// like "$x+2" not being acceptable without a space, in case we decide one
+// day to implement arithmetic.
func (l *lexer) atTerminator() bool {
r := l.peek()
- if isSpace(r) {
+ if isSpace(r) || isEndOfLine(r) {
return true
}
switch r {
- case eof, ',', '|', ':':
+ case eof, '.', ',', '|', ':', ')', '(':
return true
}
// Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will
@@ -392,7 +429,7 @@ func (l *lexer) atTerminator() bool {
}
// lexChar scans a character constant. The initial quote is already
-// scanned. Syntax checking is done by the parse.
+// scanned. Syntax checking is done by the parser.
func lexChar(l *lexer) stateFn {
Loop:
for {
@@ -412,7 +449,7 @@ Loop:
return lexInsideAction
}
-// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This
+// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This
// isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
// and "089" - but when it's wrong the input is invalid and the parser (via
// strconv) will notice.
@@ -421,7 +458,7 @@ func lexNumber(l *lexer) stateFn {
return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
}
if sign := l.peek(); sign == '+' || sign == '-' {
- // Complex: 1+2i. No spaces, must end in 'i'.
+ // Complex: 1+2i. No spaces, must end in 'i'.
if !l.scanNumber() || l.input[l.pos-1] != 'i' {
return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
}
@@ -495,11 +532,12 @@ Loop:
// isSpace reports whether r is a space character.
func isSpace(r rune) bool {
- switch r {
- case ' ', '\t', '\n', '\r':
- return true
- }
- return false
+ return r == ' ' || r == '\t'
+}
+
+// isEndOfLine reports whether r is an end-of-line character.
+func isEndOfLine(r rune) bool {
+ return r == '\r' || r == '\n'
}
// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
diff --git a/libgo/go/text/template/parse/lex_test.go b/libgo/go/text/template/parse/lex_test.go
index f3b23c91e43..d2264c991c9 100644
--- a/libgo/go/text/template/parse/lex_test.go
+++ b/libgo/go/text/template/parse/lex_test.go
@@ -5,10 +5,52 @@
package parse
import (
- "reflect"
+ "fmt"
"testing"
)
+// Make the types prettyprint.
+var itemName = map[itemType]string{
+ itemError: "error",
+ itemBool: "bool",
+ itemChar: "char",
+ itemCharConstant: "charconst",
+ itemComplex: "complex",
+ itemColonEquals: ":=",
+ itemEOF: "EOF",
+ itemField: "field",
+ itemIdentifier: "identifier",
+ itemLeftDelim: "left delim",
+ itemLeftParen: "(",
+ itemNumber: "number",
+ itemPipe: "pipe",
+ itemRawString: "raw string",
+ itemRightDelim: "right delim",
+ itemRightParen: ")",
+ itemSpace: "space",
+ itemString: "string",
+ itemVariable: "variable",
+
+ // keywords
+ itemDot: ".",
+ itemDefine: "define",
+ itemElse: "else",
+ itemIf: "if",
+ itemEnd: "end",
+ itemNil: "nil",
+ itemRange: "range",
+ itemTemplate: "template",
+ itemWith: "with",
+}
+
+func (i itemType) String() string {
+ s := itemName[i]
+ if s == "" {
+ return fmt.Sprintf("item%d", int(i))
+ }
+ return s
+}
+
type lexTest struct {
name string
input string
@@ -16,173 +58,265 @@ type lexTest struct {
}
var (
- tEOF = item{itemEOF, ""}
- tLeft = item{itemLeftDelim, "{{"}
- tRight = item{itemRightDelim, "}}"}
- tRange = item{itemRange, "range"}
- tPipe = item{itemPipe, "|"}
- tFor = item{itemIdentifier, "for"}
- tQuote = item{itemString, `"abc \n\t\" "`}
+ tEOF = item{itemEOF, 0, ""}
+ tFor = item{itemIdentifier, 0, "for"}
+ tLeft = item{itemLeftDelim, 0, "{{"}
+ tLpar = item{itemLeftParen, 0, "("}
+ tPipe = item{itemPipe, 0, "|"}
+ tQuote = item{itemString, 0, `"abc \n\t\" "`}
+ tRange = item{itemRange, 0, "range"}
+ tRight = item{itemRightDelim, 0, "}}"}
+ tRpar = item{itemRightParen, 0, ")"}
+ tSpace = item{itemSpace, 0, " "}
raw = "`" + `abc\n\t\" ` + "`"
- tRawQuote = item{itemRawString, raw}
+ tRawQuote = item{itemRawString, 0, raw}
)
var lexTests = []lexTest{
{"empty", "", []item{tEOF}},
- {"spaces", " \t\n", []item{{itemText, " \t\n"}, tEOF}},
- {"text", `now is the time`, []item{{itemText, "now is the time"}, tEOF}},
+ {"spaces", " \t\n", []item{{itemText, 0, " \t\n"}, tEOF}},
+ {"text", `now is the time`, []item{{itemText, 0, "now is the time"}, tEOF}},
{"text with comment", "hello-{{/* this is a comment */}}-world", []item{
- {itemText, "hello-"},
- {itemText, "-world"},
+ {itemText, 0, "hello-"},
+ {itemText, 0, "-world"},
tEOF,
}},
- {"punctuation", "{{,@%}}", []item{
+ {"punctuation", "{{,@% }}", []item{
tLeft,
- {itemChar, ","},
- {itemChar, "@"},
- {itemChar, "%"},
+ {itemChar, 0, ","},
+ {itemChar, 0, "@"},
+ {itemChar, 0, "%"},
+ tSpace,
+ tRight,
+ tEOF,
+ }},
+ {"parens", "{{((3))}}", []item{
+ tLeft,
+ tLpar,
+ tLpar,
+ {itemNumber, 0, "3"},
+ tRpar,
+ tRpar,
tRight,
tEOF,
}},
{"empty action", `{{}}`, []item{tLeft, tRight, tEOF}},
- {"for", `{{for }}`, []item{tLeft, tFor, tRight, tEOF}},
+ {"for", `{{for}}`, []item{tLeft, tFor, tRight, tEOF}},
{"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}},
{"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}},
{"numbers", "{{1 02 0x14 -7.2i 1e3 +1.2e-4 4.2i 1+2i}}", []item{
tLeft,
- {itemNumber, "1"},
- {itemNumber, "02"},
- {itemNumber, "0x14"},
- {itemNumber, "-7.2i"},
- {itemNumber, "1e3"},
- {itemNumber, "+1.2e-4"},
- {itemNumber, "4.2i"},
- {itemComplex, "1+2i"},
+ {itemNumber, 0, "1"},
+ tSpace,
+ {itemNumber, 0, "02"},
+ tSpace,
+ {itemNumber, 0, "0x14"},
+ tSpace,
+ {itemNumber, 0, "-7.2i"},
+ tSpace,
+ {itemNumber, 0, "1e3"},
+ tSpace,
+ {itemNumber, 0, "+1.2e-4"},
+ tSpace,
+ {itemNumber, 0, "4.2i"},
+ tSpace,
+ {itemComplex, 0, "1+2i"},
tRight,
tEOF,
}},
{"characters", `{{'a' '\n' '\'' '\\' '\u00FF' '\xFF' '本'}}`, []item{
tLeft,
- {itemCharConstant, `'a'`},
- {itemCharConstant, `'\n'`},
- {itemCharConstant, `'\''`},
- {itemCharConstant, `'\\'`},
- {itemCharConstant, `'\u00FF'`},
- {itemCharConstant, `'\xFF'`},
- {itemCharConstant, `'本'`},
+ {itemCharConstant, 0, `'a'`},
+ tSpace,
+ {itemCharConstant, 0, `'\n'`},
+ tSpace,
+ {itemCharConstant, 0, `'\''`},
+ tSpace,
+ {itemCharConstant, 0, `'\\'`},
+ tSpace,
+ {itemCharConstant, 0, `'\u00FF'`},
+ tSpace,
+ {itemCharConstant, 0, `'\xFF'`},
+ tSpace,
+ {itemCharConstant, 0, `'本'`},
tRight,
tEOF,
}},
{"bools", "{{true false}}", []item{
tLeft,
- {itemBool, "true"},
- {itemBool, "false"},
+ {itemBool, 0, "true"},
+ tSpace,
+ {itemBool, 0, "false"},
tRight,
tEOF,
}},
{"dot", "{{.}}", []item{
tLeft,
- {itemDot, "."},
+ {itemDot, 0, "."},
tRight,
tEOF,
}},
- {"dots", "{{.x . .2 .x.y}}", []item{
+ {"nil", "{{nil}}", []item{
tLeft,
- {itemField, ".x"},
- {itemDot, "."},
- {itemNumber, ".2"},
- {itemField, ".x.y"},
+ {itemNil, 0, "nil"},
+ tRight,
+ tEOF,
+ }},
+ {"dots", "{{.x . .2 .x.y.z}}", []item{
+ tLeft,
+ {itemField, 0, ".x"},
+ tSpace,
+ {itemDot, 0, "."},
+ tSpace,
+ {itemNumber, 0, ".2"},
+ tSpace,
+ {itemField, 0, ".x"},
+ {itemField, 0, ".y"},
+ {itemField, 0, ".z"},
tRight,
tEOF,
}},
{"keywords", "{{range if else end with}}", []item{
tLeft,
- {itemRange, "range"},
- {itemIf, "if"},
- {itemElse, "else"},
- {itemEnd, "end"},
- {itemWith, "with"},
+ {itemRange, 0, "range"},
+ tSpace,
+ {itemIf, 0, "if"},
+ tSpace,
+ {itemElse, 0, "else"},
+ tSpace,
+ {itemEnd, 0, "end"},
+ tSpace,
+ {itemWith, 0, "with"},
tRight,
tEOF,
}},
{"variables", "{{$c := printf $ $hello $23 $ $var.Field .Method}}", []item{
tLeft,
- {itemVariable, "$c"},
- {itemColonEquals, ":="},
- {itemIdentifier, "printf"},
- {itemVariable, "$"},
- {itemVariable, "$hello"},
- {itemVariable, "$23"},
- {itemVariable, "$"},
- {itemVariable, "$var.Field"},
- {itemField, ".Method"},
+ {itemVariable, 0, "$c"},
+ tSpace,
+ {itemColonEquals, 0, ":="},
+ tSpace,
+ {itemIdentifier, 0, "printf"},
+ tSpace,
+ {itemVariable, 0, "$"},
+ tSpace,
+ {itemVariable, 0, "$hello"},
+ tSpace,
+ {itemVariable, 0, "$23"},
+ tSpace,
+ {itemVariable, 0, "$"},
+ tSpace,
+ {itemVariable, 0, "$var"},
+ {itemField, 0, ".Field"},
+ tSpace,
+ {itemField, 0, ".Method"},
+ tRight,
+ tEOF,
+ }},
+ {"variable invocation", "{{$x 23}}", []item{
+ tLeft,
+ {itemVariable, 0, "$x"},
+ tSpace,
+ {itemNumber, 0, "23"},
tRight,
tEOF,
}},
{"pipeline", `intro {{echo hi 1.2 |noargs|args 1 "hi"}} outro`, []item{
- {itemText, "intro "},
+ {itemText, 0, "intro "},
tLeft,
- {itemIdentifier, "echo"},
- {itemIdentifier, "hi"},
- {itemNumber, "1.2"},
+ {itemIdentifier, 0, "echo"},
+ tSpace,
+ {itemIdentifier, 0, "hi"},
+ tSpace,
+ {itemNumber, 0, "1.2"},
+ tSpace,
tPipe,
- {itemIdentifier, "noargs"},
+ {itemIdentifier, 0, "noargs"},
tPipe,
- {itemIdentifier, "args"},
- {itemNumber, "1"},
- {itemString, `"hi"`},
+ {itemIdentifier, 0, "args"},
+ tSpace,
+ {itemNumber, 0, "1"},
+ tSpace,
+ {itemString, 0, `"hi"`},
tRight,
- {itemText, " outro"},
+ {itemText, 0, " outro"},
tEOF,
}},
{"declaration", "{{$v := 3}}", []item{
tLeft,
- {itemVariable, "$v"},
- {itemColonEquals, ":="},
- {itemNumber, "3"},
+ {itemVariable, 0, "$v"},
+ tSpace,
+ {itemColonEquals, 0, ":="},
+ tSpace,
+ {itemNumber, 0, "3"},
tRight,
tEOF,
}},
{"2 declarations", "{{$v , $w := 3}}", []item{
tLeft,
- {itemVariable, "$v"},
- {itemChar, ","},
- {itemVariable, "$w"},
- {itemColonEquals, ":="},
- {itemNumber, "3"},
+ {itemVariable, 0, "$v"},
+ tSpace,
+ {itemChar, 0, ","},
+ tSpace,
+ {itemVariable, 0, "$w"},
+ tSpace,
+ {itemColonEquals, 0, ":="},
+ tSpace,
+ {itemNumber, 0, "3"},
+ tRight,
+ tEOF,
+ }},
+ {"field of parenthesized expression", "{{(.X).Y}}", []item{
+ tLeft,
+ tLpar,
+ {itemField, 0, ".X"},
+ tRpar,
+ {itemField, 0, ".Y"},
tRight,
tEOF,
}},
// errors
{"badchar", "#{{\x01}}", []item{
- {itemText, "#"},
+ {itemText, 0, "#"},
tLeft,
- {itemError, "unrecognized character in action: U+0001"},
+ {itemError, 0, "unrecognized character in action: U+0001"},
}},
{"unclosed action", "{{\n}}", []item{
tLeft,
- {itemError, "unclosed action"},
+ {itemError, 0, "unclosed action"},
}},
{"EOF in action", "{{range", []item{
tLeft,
tRange,
- {itemError, "unclosed action"},
+ {itemError, 0, "unclosed action"},
}},
{"unclosed quote", "{{\"\n\"}}", []item{
tLeft,
- {itemError, "unterminated quoted string"},
+ {itemError, 0, "unterminated quoted string"},
}},
{"unclosed raw quote", "{{`xx\n`}}", []item{
tLeft,
- {itemError, "unterminated raw quoted string"},
+ {itemError, 0, "unterminated raw quoted string"},
}},
{"unclosed char constant", "{{'\n}}", []item{
tLeft,
- {itemError, "unterminated character constant"},
+ {itemError, 0, "unterminated character constant"},
}},
{"bad number", "{{3k}}", []item{
tLeft,
- {itemError, `bad number syntax: "3k"`},
+ {itemError, 0, `bad number syntax: "3k"`},
+ }},
+ {"unclosed paren", "{{(3}}", []item{
+ tLeft,
+ tLpar,
+ {itemNumber, 0, "3"},
+ {itemError, 0, `unclosed left paren`},
+ }},
+ {"extra right paren", "{{3)}}", []item{
+ tLeft,
+ {itemNumber, 0, "3"},
+ tRpar,
+ {itemError, 0, `unexpected right paren U+0029 ')'`},
}},
// Fixed bugs
@@ -199,8 +333,8 @@ var lexTests = []lexTest{
tEOF,
}},
{"text with bad comment", "hello-{{/*/}}-world", []item{
- {itemText, "hello-"},
- {itemError, `unclosed comment`},
+ {itemText, 0, "hello-"},
+ {itemError, 0, `unclosed comment`},
}},
}
@@ -217,11 +351,29 @@ func collect(t *lexTest, left, right string) (items []item) {
return
}
+func equal(i1, i2 []item, checkPos bool) bool {
+ if len(i1) != len(i2) {
+ return false
+ }
+ for k := range i1 {
+ if i1[k].typ != i2[k].typ {
+ return false
+ }
+ if i1[k].val != i2[k].val {
+ return false
+ }
+ if checkPos && i1[k].pos != i2[k].pos {
+ return false
+ }
+ }
+ return true
+}
+
func TestLex(t *testing.T) {
for _, test := range lexTests {
items := collect(&test, "", "")
- if !reflect.DeepEqual(items, test.items) {
- t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+ if !equal(items, test.items, false) {
+ t.Errorf("%s: got\n\t%+v\nexpected\n\t%v", test.name, items, test.items)
}
}
}
@@ -230,32 +382,74 @@ func TestLex(t *testing.T) {
var lexDelimTests = []lexTest{
{"punctuation", "$$,@%{{}}@@", []item{
tLeftDelim,
- {itemChar, ","},
- {itemChar, "@"},
- {itemChar, "%"},
- {itemChar, "{"},
- {itemChar, "{"},
- {itemChar, "}"},
- {itemChar, "}"},
+ {itemChar, 0, ","},
+ {itemChar, 0, "@"},
+ {itemChar, 0, "%"},
+ {itemChar, 0, "{"},
+ {itemChar, 0, "{"},
+ {itemChar, 0, "}"},
+ {itemChar, 0, "}"},
tRightDelim,
tEOF,
}},
{"empty action", `$$@@`, []item{tLeftDelim, tRightDelim, tEOF}},
- {"for", `$$for @@`, []item{tLeftDelim, tFor, tRightDelim, tEOF}},
+ {"for", `$$for@@`, []item{tLeftDelim, tFor, tRightDelim, tEOF}},
{"quote", `$$"abc \n\t\" "@@`, []item{tLeftDelim, tQuote, tRightDelim, tEOF}},
{"raw quote", "$$" + raw + "@@", []item{tLeftDelim, tRawQuote, tRightDelim, tEOF}},
}
var (
- tLeftDelim = item{itemLeftDelim, "$$"}
- tRightDelim = item{itemRightDelim, "@@"}
+ tLeftDelim = item{itemLeftDelim, 0, "$$"}
+ tRightDelim = item{itemRightDelim, 0, "@@"}
)
func TestDelims(t *testing.T) {
for _, test := range lexDelimTests {
items := collect(&test, "$$", "@@")
- if !reflect.DeepEqual(items, test.items) {
+ if !equal(items, test.items, false) {
+ t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+ }
+ }
+}
+
+var lexPosTests = []lexTest{
+ {"empty", "", []item{tEOF}},
+ {"punctuation", "{{,@%#}}", []item{
+ {itemLeftDelim, 0, "{{"},
+ {itemChar, 2, ","},
+ {itemChar, 3, "@"},
+ {itemChar, 4, "%"},
+ {itemChar, 5, "#"},
+ {itemRightDelim, 6, "}}"},
+ {itemEOF, 8, ""},
+ }},
+ {"sample", "0123{{hello}}xyz", []item{
+ {itemText, 0, "0123"},
+ {itemLeftDelim, 4, "{{"},
+ {itemIdentifier, 6, "hello"},
+ {itemRightDelim, 11, "}}"},
+ {itemText, 13, "xyz"},
+ {itemEOF, 16, ""},
+ }},
+}
+
+// The other tests don't check position, to make the test cases easier to construct.
+// This one does.
+func TestPos(t *testing.T) {
+ for _, test := range lexPosTests {
+ items := collect(&test, "", "")
+ if !equal(items, test.items, true) {
t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+ if len(items) == len(test.items) {
+ // Detailed print; avoid item.String() to expose the position value.
+ for i := range items {
+ if !equal(items[i:i+1], test.items[i:i+1], true) {
+ i1 := items[i]
+ i2 := test.items[i]
+ t.Errorf("\t#%d: got {%v %d %q} expected {%v %d %q}", i, i1.typ, i1.pos, i1.val, i2.typ, i2.pos, i2.val)
+ }
+ }
+ }
}
}
}
diff --git a/libgo/go/text/template/parse/node.go b/libgo/go/text/template/parse/node.go
index db645624c56..9d0d09eb5fa 100644
--- a/libgo/go/text/template/parse/node.go
+++ b/libgo/go/text/template/parse/node.go
@@ -13,7 +13,9 @@ import (
"strings"
)
-// A node is an element in the parse tree. The interface is trivial.
+// A Node is an element in the parse tree. The interface is trivial.
+// The interface contains an unexported method so that only
+// types local to this package can satisfy it.
type Node interface {
Type() NodeType
String() string
@@ -21,11 +23,27 @@ type Node interface {
// To avoid type assertions, some XxxNodes also have specialized
// CopyXxx methods that return *XxxNode.
Copy() Node
+ Position() Pos // byte position of start of node in full original input string
+ // Make sure only functions in this package can create Nodes.
+ unexported()
}
// NodeType identifies the type of a parse tree node.
type NodeType int
+// Pos represents a byte position in the original input text from which
+// this template was parsed.
+type Pos int
+
+func (p Pos) Position() Pos {
+ return p
+}
+
+// unexported keeps Node implementations local to the package.
+// All implementations embed Pos, so this takes care of it.
+func (Pos) unexported() {
+}
+
// Type returns itself and provides an easy default implementation
// for embedding in a Node. Embedded in all non-trivial Nodes.
func (t NodeType) Type() NodeType {
@@ -34,8 +52,9 @@ func (t NodeType) Type() NodeType {
const (
NodeText NodeType = iota // Plain text.
- NodeAction // A simple action such as field evaluation.
+ NodeAction // A non-control action such as a field evaluation.
NodeBool // A boolean constant.
+ NodeChain // A sequence of field accesses.
NodeCommand // An element of a pipeline.
NodeDot // The cursor, dot.
nodeElse // An else action. Not added to tree.
@@ -44,6 +63,7 @@ const (
NodeIdentifier // An identifier; always a function name.
NodeIf // An if action.
NodeList // A list of Nodes.
+ NodeNil // An untyped nil constant.
NodeNumber // A numerical constant.
NodePipe // A pipeline of commands.
NodeRange // A range action.
@@ -58,11 +78,12 @@ const (
// ListNode holds a sequence of nodes.
type ListNode struct {
NodeType
+ Pos
Nodes []Node // The element nodes in lexical order.
}
-func newList() *ListNode {
- return &ListNode{NodeType: NodeList}
+func newList(pos Pos) *ListNode {
+ return &ListNode{NodeType: NodeList, Pos: pos}
}
func (l *ListNode) append(n Node) {
@@ -81,7 +102,7 @@ func (l *ListNode) CopyList() *ListNode {
if l == nil {
return l
}
- n := newList()
+ n := newList(l.Pos)
for _, elem := range l.Nodes {
n.append(elem.Copy())
}
@@ -95,11 +116,12 @@ func (l *ListNode) Copy() Node {
// TextNode holds plain text.
type TextNode struct {
NodeType
+ Pos
Text []byte // The text; may span newlines.
}
-func newText(text string) *TextNode {
- return &TextNode{NodeType: NodeText, Text: []byte(text)}
+func newText(pos Pos, text string) *TextNode {
+ return &TextNode{NodeType: NodeText, Pos: pos, Text: []byte(text)}
}
func (t *TextNode) String() string {
@@ -113,13 +135,14 @@ func (t *TextNode) Copy() Node {
// PipeNode holds a pipeline with optional declaration
type PipeNode struct {
NodeType
- Line int // The line number in the input.
+ Pos
+ Line int // The line number in the input (deprecated; kept for compatibility)
Decl []*VariableNode // Variable declarations in lexical order.
Cmds []*CommandNode // The commands in lexical order.
}
-func newPipeline(line int, decl []*VariableNode) *PipeNode {
- return &PipeNode{NodeType: NodePipe, Line: line, Decl: decl}
+func newPipeline(pos Pos, line int, decl []*VariableNode) *PipeNode {
+ return &PipeNode{NodeType: NodePipe, Pos: pos, Line: line, Decl: decl}
}
func (p *PipeNode) append(command *CommandNode) {
@@ -154,7 +177,7 @@ func (p *PipeNode) CopyPipe() *PipeNode {
for _, d := range p.Decl {
decl = append(decl, d.Copy().(*VariableNode))
}
- n := newPipeline(p.Line, decl)
+ n := newPipeline(p.Pos, p.Line, decl)
for _, c := range p.Cmds {
n.append(c.Copy().(*CommandNode))
}
@@ -167,15 +190,16 @@ func (p *PipeNode) Copy() Node {
// ActionNode holds an action (something bounded by delimiters).
// Control actions have their own nodes; ActionNode represents simple
-// ones such as field evaluations.
+// ones such as field evaluations and parenthesized pipelines.
type ActionNode struct {
NodeType
- Line int // The line number in the input.
+ Pos
+ Line int // The line number in the input (deprecated; kept for compatibility)
Pipe *PipeNode // The pipeline in the action.
}
-func newAction(line int, pipe *PipeNode) *ActionNode {
- return &ActionNode{NodeType: NodeAction, Line: line, Pipe: pipe}
+func newAction(pos Pos, line int, pipe *PipeNode) *ActionNode {
+ return &ActionNode{NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe}
}
func (a *ActionNode) String() string {
@@ -184,18 +208,19 @@ func (a *ActionNode) String() string {
}
func (a *ActionNode) Copy() Node {
- return newAction(a.Line, a.Pipe.CopyPipe())
+ return newAction(a.Pos, a.Line, a.Pipe.CopyPipe())
}
// CommandNode holds a command (a pipeline inside an evaluating action).
type CommandNode struct {
NodeType
+ Pos
Args []Node // Arguments in lexical order: Identifier, field, or constant.
}
-func newCommand() *CommandNode {
- return &CommandNode{NodeType: NodeCommand}
+func newCommand(pos Pos) *CommandNode {
+ return &CommandNode{NodeType: NodeCommand, Pos: pos}
}
func (c *CommandNode) append(arg Node) {
@@ -208,6 +233,10 @@ func (c *CommandNode) String() string {
if i > 0 {
s += " "
}
+ if arg, ok := arg.(*PipeNode); ok {
+ s += "(" + arg.String() + ")"
+ continue
+ }
s += arg.String()
}
return s
@@ -217,7 +246,7 @@ func (c *CommandNode) Copy() Node {
if c == nil {
return c
}
- n := newCommand()
+ n := newCommand(c.Pos)
for _, c := range c.Args {
n.append(c.Copy())
}
@@ -227,6 +256,7 @@ func (c *CommandNode) Copy() Node {
// IdentifierNode holds an identifier.
type IdentifierNode struct {
NodeType
+ Pos
Ident string // The identifier's name.
}
@@ -235,23 +265,32 @@ func NewIdentifier(ident string) *IdentifierNode {
return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident}
}
+// SetPos sets the position. NewIdentifier is a public method so we can't modify its signature.
+// Chained for convenience.
+// TODO: fix one day?
+func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode {
+ i.Pos = pos
+ return i
+}
+
func (i *IdentifierNode) String() string {
return i.Ident
}
func (i *IdentifierNode) Copy() Node {
- return NewIdentifier(i.Ident)
+ return NewIdentifier(i.Ident).SetPos(i.Pos)
}
-// VariableNode holds a list of variable names. The dollar sign is
-// part of the name.
+// VariableNode holds a list of variable names, possibly with chained field
+// accesses. The dollar sign is part of the (first) name.
type VariableNode struct {
NodeType
- Ident []string // Variable names in lexical order.
+ Pos
+ Ident []string // Variable name and fields in lexical order.
}
-func newVariable(ident string) *VariableNode {
- return &VariableNode{NodeType: NodeVariable, Ident: strings.Split(ident, ".")}
+func newVariable(pos Pos, ident string) *VariableNode {
+ return &VariableNode{NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")}
}
func (v *VariableNode) String() string {
@@ -266,14 +305,16 @@ func (v *VariableNode) String() string {
}
func (v *VariableNode) Copy() Node {
- return &VariableNode{NodeType: NodeVariable, Ident: append([]string{}, v.Ident...)}
+ return &VariableNode{NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)}
}
-// DotNode holds the special identifier '.'. It is represented by a nil pointer.
-type DotNode bool
+// DotNode holds the special identifier '.'.
+type DotNode struct {
+ Pos
+}
-func newDot() *DotNode {
- return nil
+func newDot(pos Pos) *DotNode {
+ return &DotNode{Pos: pos}
}
func (d *DotNode) Type() NodeType {
@@ -285,7 +326,28 @@ func (d *DotNode) String() string {
}
func (d *DotNode) Copy() Node {
- return newDot()
+ return newDot(d.Pos)
+}
+
+// NilNode holds the special identifier 'nil' representing an untyped nil constant.
+type NilNode struct {
+ Pos
+}
+
+func newNil(pos Pos) *NilNode {
+ return &NilNode{Pos: pos}
+}
+
+func (n *NilNode) Type() NodeType {
+ return NodeNil
+}
+
+func (n *NilNode) String() string {
+ return "nil"
+}
+
+func (n *NilNode) Copy() Node {
+ return newNil(n.Pos)
}
// FieldNode holds a field (identifier starting with '.').
@@ -293,11 +355,12 @@ func (d *DotNode) Copy() Node {
// The period is dropped from each ident.
type FieldNode struct {
NodeType
+ Pos
Ident []string // The identifiers in lexical order.
}
-func newField(ident string) *FieldNode {
- return &FieldNode{NodeType: NodeField, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
+func newField(pos Pos, ident string) *FieldNode {
+ return &FieldNode{NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
}
func (f *FieldNode) String() string {
@@ -309,17 +372,59 @@ func (f *FieldNode) String() string {
}
func (f *FieldNode) Copy() Node {
- return &FieldNode{NodeType: NodeField, Ident: append([]string{}, f.Ident...)}
+ return &FieldNode{NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)}
+}
+
+// ChainNode holds a term followed by a chain of field accesses (identifier starting with '.').
+// The names may be chained ('.x.y').
+// The periods are dropped from each ident.
+type ChainNode struct {
+ NodeType
+ Pos
+ Node Node
+ Field []string // The identifiers in lexical order.
+}
+
+func newChain(pos Pos, node Node) *ChainNode {
+ return &ChainNode{NodeType: NodeChain, Pos: pos, Node: node}
+}
+
+// Add adds the named field (which should start with a period) to the end of the chain.
+func (c *ChainNode) Add(field string) {
+ if len(field) == 0 || field[0] != '.' {
+ panic("no dot in field")
+ }
+ field = field[1:] // Remove leading dot.
+ if field == "" {
+ panic("empty field")
+ }
+ c.Field = append(c.Field, field)
+}
+
+func (c *ChainNode) String() string {
+ s := c.Node.String()
+ if _, ok := c.Node.(*PipeNode); ok {
+ s = "(" + s + ")"
+ }
+ for _, field := range c.Field {
+ s += "." + field
+ }
+ return s
+}
+
+func (c *ChainNode) Copy() Node {
+ return &ChainNode{NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)}
}
// BoolNode holds a boolean constant.
type BoolNode struct {
NodeType
+ Pos
True bool // The value of the boolean constant.
}
-func newBool(true bool) *BoolNode {
- return &BoolNode{NodeType: NodeBool, True: true}
+func newBool(pos Pos, true bool) *BoolNode {
+ return &BoolNode{NodeType: NodeBool, Pos: pos, True: true}
}
func (b *BoolNode) String() string {
@@ -330,7 +435,7 @@ func (b *BoolNode) String() string {
}
func (b *BoolNode) Copy() Node {
- return newBool(b.True)
+ return newBool(b.Pos, b.True)
}
// NumberNode holds a number: signed or unsigned integer, float, or complex.
@@ -338,6 +443,7 @@ func (b *BoolNode) Copy() Node {
// This simulates in a small amount of code the behavior of Go's ideal constants.
type NumberNode struct {
NodeType
+ Pos
IsInt bool // Number has an integral value.
IsUint bool // Number has an unsigned integral value.
IsFloat bool // Number has a floating-point value.
@@ -349,8 +455,8 @@ type NumberNode struct {
Text string // The original textual representation from the input.
}
-func newNumber(text string, typ itemType) (*NumberNode, error) {
- n := &NumberNode{NodeType: NodeNumber, Text: text}
+func newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) {
+ n := &NumberNode{NodeType: NodeNumber, Pos: pos, Text: text}
switch typ {
case itemCharConstant:
rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
@@ -460,12 +566,13 @@ func (n *NumberNode) Copy() Node {
// StringNode holds a string constant. The value has been "unquoted".
type StringNode struct {
NodeType
+ Pos
Quoted string // The original text of the string, with quotes.
Text string // The string, after quote processing.
}
-func newString(orig, text string) *StringNode {
- return &StringNode{NodeType: NodeString, Quoted: orig, Text: text}
+func newString(pos Pos, orig, text string) *StringNode {
+ return &StringNode{NodeType: NodeString, Pos: pos, Quoted: orig, Text: text}
}
func (s *StringNode) String() string {
@@ -473,15 +580,17 @@ func (s *StringNode) String() string {
}
func (s *StringNode) Copy() Node {
- return newString(s.Quoted, s.Text)
+ return newString(s.Pos, s.Quoted, s.Text)
}
-// endNode represents an {{end}} action. It is represented by a nil pointer.
+// endNode represents an {{end}} action.
// It does not appear in the final parse tree.
-type endNode bool
+type endNode struct {
+ Pos
+}
-func newEnd() *endNode {
- return nil
+func newEnd(pos Pos) *endNode {
+ return &endNode{Pos: pos}
}
func (e *endNode) Type() NodeType {
@@ -493,17 +602,18 @@ func (e *endNode) String() string {
}
func (e *endNode) Copy() Node {
- return newEnd()
+ return newEnd(e.Pos)
}
// elseNode represents an {{else}} action. Does not appear in the final tree.
type elseNode struct {
NodeType
- Line int // The line number in the input.
+ Pos
+ Line int // The line number in the input (deprecated; kept for compatibility)
}
-func newElse(line int) *elseNode {
- return &elseNode{NodeType: nodeElse, Line: line}
+func newElse(pos Pos, line int) *elseNode {
+ return &elseNode{NodeType: nodeElse, Pos: pos, Line: line}
}
func (e *elseNode) Type() NodeType {
@@ -515,13 +625,14 @@ func (e *elseNode) String() string {
}
func (e *elseNode) Copy() Node {
- return newElse(e.Line)
+ return newElse(e.Pos, e.Line)
}
// BranchNode is the common representation of if, range, and with.
type BranchNode struct {
NodeType
- Line int // The line number in the input.
+ Pos
+ Line int // The line number in the input (deprecated; kept for compatibility)
Pipe *PipeNode // The pipeline to be evaluated.
List *ListNode // What to execute if the value is non-empty.
ElseList *ListNode // What to execute if the value is empty (nil if absent).
@@ -550,12 +661,12 @@ type IfNode struct {
BranchNode
}
-func newIf(line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
- return &IfNode{BranchNode{NodeType: NodeIf, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+func newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
+ return &IfNode{BranchNode{NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
func (i *IfNode) Copy() Node {
- return newIf(i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
+ return newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
}
// RangeNode represents a {{range}} action and its commands.
@@ -563,12 +674,12 @@ type RangeNode struct {
BranchNode
}
-func newRange(line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
- return &RangeNode{BranchNode{NodeType: NodeRange, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+func newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
+ return &RangeNode{BranchNode{NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
func (r *RangeNode) Copy() Node {
- return newRange(r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
+ return newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
}
// WithNode represents a {{with}} action and its commands.
@@ -576,24 +687,25 @@ type WithNode struct {
BranchNode
}
-func newWith(line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
- return &WithNode{BranchNode{NodeType: NodeWith, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+func newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
+ return &WithNode{BranchNode{NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
func (w *WithNode) Copy() Node {
- return newWith(w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
+ return newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
}
// TemplateNode represents a {{template}} action.
type TemplateNode struct {
NodeType
- Line int // The line number in the input.
+ Pos
+ Line int // The line number in the input (deprecated; kept for compatibility)
Name string // The name of the template (unquoted).
Pipe *PipeNode // The command to evaluate as dot for the template.
}
-func newTemplate(line int, name string, pipe *PipeNode) *TemplateNode {
- return &TemplateNode{NodeType: NodeTemplate, Line: line, Name: name, Pipe: pipe}
+func newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode {
+ return &TemplateNode{NodeType: NodeTemplate, Line: line, Pos: pos, Name: name, Pipe: pipe}
}
func (t *TemplateNode) String() string {
@@ -604,5 +716,5 @@ func (t *TemplateNode) String() string {
}
func (t *TemplateNode) Copy() Node {
- return newTemplate(t.Line, t.Name, t.Pipe.CopyPipe())
+ return newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe())
}
diff --git a/libgo/go/text/template/parse/parse.go b/libgo/go/text/template/parse/parse.go
index c0087b2785b..250cad5f353 100644
--- a/libgo/go/text/template/parse/parse.go
+++ b/libgo/go/text/template/parse/parse.go
@@ -13,17 +13,20 @@ import (
"fmt"
"runtime"
"strconv"
+ "strings"
"unicode"
)
// Tree is the representation of a single parsed template.
type Tree struct {
- Name string // name of the template represented by the tree.
- Root *ListNode // top-level root of the tree.
+ Name string // name of the template represented by the tree.
+ ParseName string // name of the top-level template during parsing, for error messages.
+ Root *ListNode // top-level root of the tree.
+ text string // text parsed to create the template (or its parent)
// Parsing only; cleared after parse.
funcs []map[string]interface{}
lex *lexer
- token [2]item // two-token lookahead for parser.
+ token [3]item // three-token lookahead for parser.
peekCount int
vars []string // variables defined at the moment.
}
@@ -34,7 +37,9 @@ type Tree struct {
// empty map is returned with the error.
func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (treeSet map[string]*Tree, err error) {
treeSet = make(map[string]*Tree)
- _, err = New(name).Parse(text, leftDelim, rightDelim, treeSet, funcs...)
+ t := New(name)
+ t.text = text
+ _, err = t.Parse(text, leftDelim, rightDelim, treeSet, funcs...)
return
}
@@ -53,12 +58,21 @@ func (t *Tree) backup() {
t.peekCount++
}
-// backup2 backs the input stream up two tokens
+// backup2 backs the input stream up two tokens.
+// The zeroth token is already there.
func (t *Tree) backup2(t1 item) {
t.token[1] = t1
t.peekCount = 2
}
+// backup3 backs the input stream up three tokens
+// The zeroth token is already there.
+func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back.
+ t.token[1] = t1
+ t.token[2] = t2
+ t.peekCount = 3
+}
+
// peek returns but does not consume the next token.
func (t *Tree) peek() item {
if t.peekCount > 0 {
@@ -69,6 +83,29 @@ func (t *Tree) peek() item {
return t.token[0]
}
+// nextNonSpace returns the next non-space token.
+func (t *Tree) nextNonSpace() (token item) {
+ for {
+ token = t.next()
+ if token.typ != itemSpace {
+ break
+ }
+ }
+ return token
+}
+
+// peekNonSpace returns but does not consume the next non-space token.
+func (t *Tree) peekNonSpace() (token item) {
+ for {
+ token = t.next()
+ if token.typ != itemSpace {
+ break
+ }
+ }
+ t.backup()
+ return token
+}
+
// Parsing.
// New allocates a new parse tree with the given name.
@@ -79,10 +116,29 @@ func New(name string, funcs ...map[string]interface{}) *Tree {
}
}
+// ErrorContext returns a textual representation of the location of the node in the input text.
+func (t *Tree) ErrorContext(n Node) (location, context string) {
+ pos := int(n.Position())
+ text := t.text[:pos]
+ byteNum := strings.LastIndex(text, "\n")
+ if byteNum == -1 {
+ byteNum = pos // On first line.
+ } else {
+ byteNum++ // After the newline.
+ byteNum = pos - byteNum
+ }
+ lineNum := 1 + strings.Count(text, "\n")
+ context = n.String()
+ if len(context) > 20 {
+ context = fmt.Sprintf("%.20s...", context)
+ }
+ return fmt.Sprintf("%s:%d:%d", t.ParseName, lineNum, byteNum), context
+}
+
// errorf formats the error and terminates processing.
func (t *Tree) errorf(format string, args ...interface{}) {
t.Root = nil
- format = fmt.Sprintf("template: %s:%d: %s", t.Name, t.lex.lineNumber(), format)
+ format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.lex.lineNumber(), format)
panic(fmt.Errorf(format, args...))
}
@@ -93,16 +149,16 @@ func (t *Tree) error(err error) {
// expect consumes the next token and guarantees it has the required type.
func (t *Tree) expect(expected itemType, context string) item {
- token := t.next()
+ token := t.nextNonSpace()
if token.typ != expected {
t.errorf("expected %s in %s; got %s", expected, context, token)
}
return token
}
-// expectEither consumes the next token and guarantees it has one of the required types.
+// expectOneOf consumes the next token and guarantees it has one of the required types.
func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
- token := t.next()
+ token := t.nextNonSpace()
if token.typ != expected1 && token.typ != expected2 {
t.errorf("expected %s or %s in %s; got %s", expected1, expected2, context, token)
}
@@ -169,9 +225,11 @@ func (t *Tree) atEOF() bool {
// the template for execution. If either action delimiter string is empty, the
// default ("{{" or "}}") is used. Embedded template definitions are added to
// the treeSet map.
-func (t *Tree) Parse(s, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
+func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
defer t.recover(&err)
- t.startParse(funcs, lex(t.Name, s, leftDelim, rightDelim))
+ t.ParseName = t.Name
+ t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim))
+ t.text = text
t.parse(treeSet)
t.add(treeSet)
t.stopParse()
@@ -219,12 +277,14 @@ func IsEmptyTree(n Node) bool {
// as itemList except it also parses {{define}} actions.
// It runs to EOF.
func (t *Tree) parse(treeSet map[string]*Tree) (next Node) {
- t.Root = newList()
+ t.Root = newList(t.peek().pos)
for t.peek().typ != itemEOF {
if t.peek().typ == itemLeftDelim {
delim := t.next()
- if t.next().typ == itemDefine {
+ if t.nextNonSpace().typ == itemDefine {
newT := New("definition") // name will be updated once we know it.
+ newT.text = t.text
+ newT.ParseName = t.ParseName
newT.startParse(t.funcs, t.lex)
newT.parseDefinition(treeSet)
continue
@@ -257,16 +317,16 @@ func (t *Tree) parseDefinition(treeSet map[string]*Tree) {
if end.Type() != nodeEnd {
t.errorf("unexpected %s in %s", end, context)
}
- t.stopParse()
t.add(treeSet)
+ t.stopParse()
}
// itemList:
// textOrAction*
// Terminates at {{end}} or {{else}}, returned separately.
func (t *Tree) itemList() (list *ListNode, next Node) {
- list = newList()
- for t.peek().typ != itemEOF {
+ list = newList(t.peekNonSpace().pos)
+ for t.peekNonSpace().typ != itemEOF {
n := t.textOrAction()
switch n.Type() {
case nodeEnd, nodeElse:
@@ -281,9 +341,9 @@ func (t *Tree) itemList() (list *ListNode, next Node) {
// textOrAction:
// text | action
func (t *Tree) textOrAction() Node {
- switch token := t.next(); token.typ {
+ switch token := t.nextNonSpace(); token.typ {
case itemText:
- return newText(token.val)
+ return newText(token.pos, token.val)
case itemLeftDelim:
return t.action()
default:
@@ -298,7 +358,7 @@ func (t *Tree) textOrAction() Node {
// Left delim is past. Now get actions.
// First word could be a keyword such as range.
func (t *Tree) action() (n Node) {
- switch token := t.next(); token.typ {
+ switch token := t.nextNonSpace(); token.typ {
case itemElse:
return t.elseControl()
case itemEnd:
@@ -314,24 +374,26 @@ func (t *Tree) action() (n Node) {
}
t.backup()
// Do not pop variables; they persist until "end".
- return newAction(t.lex.lineNumber(), t.pipeline("command"))
+ return newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
}
// Pipeline:
-// field or command
-// pipeline "|" pipeline
+// declarations? command ('|' command)*
func (t *Tree) pipeline(context string) (pipe *PipeNode) {
var decl []*VariableNode
+ pos := t.peekNonSpace().pos
// Are there declarations?
for {
- if v := t.peek(); v.typ == itemVariable {
+ if v := t.peekNonSpace(); v.typ == itemVariable {
t.next()
- if next := t.peek(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
- t.next()
- variable := newVariable(v.val)
- if len(variable.Ident) != 1 {
- t.errorf("illegal variable in declaration: %s", v.val)
- }
+ // Since space is a token, we need 3-token look-ahead here in the worst case:
+ // in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an
+ // argument variable rather than a declaration. So remember the token
+ // adjacent to the variable so we can push it back if necessary.
+ tokenAfterVariable := t.peek()
+ if next := t.peekNonSpace(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
+ t.nextNonSpace()
+ variable := newVariable(v.pos, v.val)
decl = append(decl, variable)
t.vars = append(t.vars, v.val)
if next.typ == itemChar && next.val == "," {
@@ -340,22 +402,27 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
}
t.errorf("too many declarations in %s", context)
}
+ } else if tokenAfterVariable.typ == itemSpace {
+ t.backup3(v, tokenAfterVariable)
} else {
t.backup2(v)
}
}
break
}
- pipe = newPipeline(t.lex.lineNumber(), decl)
+ pipe = newPipeline(pos, t.lex.lineNumber(), decl)
for {
- switch token := t.next(); token.typ {
- case itemRightDelim:
+ switch token := t.nextNonSpace(); token.typ {
+ case itemRightDelim, itemRightParen:
if len(pipe.Cmds) == 0 {
t.errorf("missing value for %s", context)
}
+ if token.typ == itemRightParen {
+ t.backup()
+ }
return
case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
- itemVariable, itemNumber, itemRawString, itemString:
+ itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen:
t.backup()
pipe.append(t.command())
default:
@@ -365,9 +432,9 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
return
}
-func (t *Tree) parseControl(context string) (lineNum int, pipe *PipeNode, list, elseList *ListNode) {
- lineNum = t.lex.lineNumber()
+func (t *Tree) parseControl(context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
defer t.popVars(len(t.vars))
+ line = t.lex.lineNumber()
pipe = t.pipeline(context)
var next Node
list, next = t.itemList()
@@ -380,7 +447,7 @@ func (t *Tree) parseControl(context string) (lineNum int, pipe *PipeNode, list,
}
elseList = elseList
}
- return lineNum, pipe, list, elseList
+ return pipe.Position(), line, pipe, list, elseList
}
// If:
@@ -411,16 +478,14 @@ func (t *Tree) withControl() Node {
// {{end}}
// End keyword is past.
func (t *Tree) endControl() Node {
- t.expect(itemRightDelim, "end")
- return newEnd()
+ return newEnd(t.expect(itemRightDelim, "end").pos)
}
// Else:
// {{else}}
// Else keyword is past.
func (t *Tree) elseControl() Node {
- t.expect(itemRightDelim, "else")
- return newElse(t.lex.lineNumber())
+ return newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
}
// Template:
@@ -429,7 +494,8 @@ func (t *Tree) elseControl() Node {
// to a string.
func (t *Tree) templateControl() Node {
var name string
- switch token := t.next(); token.typ {
+ token := t.nextNonSpace()
+ switch token.typ {
case itemString, itemRawString:
s, err := strconv.Unquote(token.val)
if err != nil {
@@ -440,57 +506,38 @@ func (t *Tree) templateControl() Node {
t.unexpected(token, "template invocation")
}
var pipe *PipeNode
- if t.next().typ != itemRightDelim {
+ if t.nextNonSpace().typ != itemRightDelim {
t.backup()
// Do not pop variables; they persist until "end".
pipe = t.pipeline("template")
}
- return newTemplate(t.lex.lineNumber(), name, pipe)
+ return newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
}
// command:
+// operand (space operand)*
// space-separated arguments up to a pipeline character or right delimiter.
// we consume the pipe character but leave the right delim to terminate the action.
func (t *Tree) command() *CommandNode {
- cmd := newCommand()
-Loop:
+ cmd := newCommand(t.peekNonSpace().pos)
for {
+ t.peekNonSpace() // skip leading spaces.
+ operand := t.operand()
+ if operand != nil {
+ cmd.append(operand)
+ }
switch token := t.next(); token.typ {
- case itemRightDelim:
- t.backup()
- break Loop
- case itemPipe:
- break Loop
+ case itemSpace:
+ continue
case itemError:
t.errorf("%s", token.val)
- case itemIdentifier:
- if !t.hasFunction(token.val) {
- t.errorf("function %q not defined", token.val)
- }
- cmd.append(NewIdentifier(token.val))
- case itemDot:
- cmd.append(newDot())
- case itemVariable:
- cmd.append(t.useVar(token.val))
- case itemField:
- cmd.append(newField(token.val))
- case itemBool:
- cmd.append(newBool(token.val == "true"))
- case itemCharConstant, itemComplex, itemNumber:
- number, err := newNumber(token.val, token.typ)
- if err != nil {
- t.error(err)
- }
- cmd.append(number)
- case itemString, itemRawString:
- s, err := strconv.Unquote(token.val)
- if err != nil {
- t.error(err)
- }
- cmd.append(newString(token.val, s))
+ case itemRightDelim, itemRightParen:
+ t.backup()
+ case itemPipe:
default:
- t.unexpected(token, "command")
+ t.errorf("unexpected %s in operand; missing space?", token)
}
+ break
}
if len(cmd.Args) == 0 {
t.errorf("empty command")
@@ -498,6 +545,88 @@ Loop:
return cmd
}
+// operand:
+// term .Field*
+// An operand is a space-separated component of a command,
+// a term possibly followed by field accesses.
+// A nil return means the next item is not an operand.
+func (t *Tree) operand() Node {
+ node := t.term()
+ if node == nil {
+ return nil
+ }
+ if t.peek().typ == itemField {
+ chain := newChain(t.peek().pos, node)
+ for t.peek().typ == itemField {
+ chain.Add(t.next().val)
+ }
+ // Compatibility with original API: If the term is of type NodeField
+ // or NodeVariable, just put more fields on the original.
+ // Otherwise, keep the Chain node.
+ // TODO: Switch to Chains always when we can.
+ switch node.Type() {
+ case NodeField:
+ node = newField(chain.Position(), chain.String())
+ case NodeVariable:
+ node = newVariable(chain.Position(), chain.String())
+ default:
+ node = chain
+ }
+ }
+ return node
+}
+
+// term:
+// literal (number, string, nil, boolean)
+// function (identifier)
+// .
+// .Field
+// $
+// '(' pipeline ')'
+// A term is a simple "expression".
+// A nil return means the next item is not a term.
+func (t *Tree) term() Node {
+ switch token := t.nextNonSpace(); token.typ {
+ case itemError:
+ t.errorf("%s", token.val)
+ case itemIdentifier:
+ if !t.hasFunction(token.val) {
+ t.errorf("function %q not defined", token.val)
+ }
+ return NewIdentifier(token.val).SetPos(token.pos)
+ case itemDot:
+ return newDot(token.pos)
+ case itemNil:
+ return newNil(token.pos)
+ case itemVariable:
+ return t.useVar(token.pos, token.val)
+ case itemField:
+ return newField(token.pos, token.val)
+ case itemBool:
+ return newBool(token.pos, token.val == "true")
+ case itemCharConstant, itemComplex, itemNumber:
+ number, err := newNumber(token.pos, token.val, token.typ)
+ if err != nil {
+ t.error(err)
+ }
+ return number
+ case itemLeftParen:
+ pipe := t.pipeline("parenthesized pipeline")
+ if token := t.next(); token.typ != itemRightParen {
+ t.errorf("unclosed right paren: unexpected %s", token)
+ }
+ return pipe
+ case itemString, itemRawString:
+ s, err := strconv.Unquote(token.val)
+ if err != nil {
+ t.error(err)
+ }
+ return newString(token.pos, token.val, s)
+ }
+ t.backup()
+ return nil
+}
+
// hasFunction reports if a function name exists in the Tree's maps.
func (t *Tree) hasFunction(name string) bool {
for _, funcMap := range t.funcs {
@@ -518,8 +647,8 @@ func (t *Tree) popVars(n int) {
// useVar returns a node for a variable reference. It errors if the
// variable is not defined.
-func (t *Tree) useVar(name string) Node {
- v := newVariable(name)
+func (t *Tree) useVar(pos Pos, name string) Node {
+ v := newVariable(pos, name)
for _, varName := range t.vars {
if varName == v.Ident[0] {
return v
diff --git a/libgo/go/text/template/parse/parse_test.go b/libgo/go/text/template/parse/parse_test.go
index b2e788238d3..695c76ebfe3 100644
--- a/libgo/go/text/template/parse/parse_test.go
+++ b/libgo/go/text/template/parse/parse_test.go
@@ -7,10 +7,11 @@ package parse
import (
"flag"
"fmt"
+ "strings"
"testing"
)
-var debug = flag.Bool("debug", false, "show the errors produced by the tests")
+var debug = flag.Bool("debug", false, "show the errors produced by the main tests")
type numberTest struct {
text string
@@ -84,7 +85,7 @@ func TestNumberParse(t *testing.T) {
typ = itemComplex
}
}
- n, err := newNumber(test.text, typ)
+ n, err := newNumber(0, test.text, typ)
ok := test.isInt || test.isUint || test.isFloat || test.isComplex
if ok && err != nil {
t.Errorf("unexpected error for %q: %s", test.text, err)
@@ -185,6 +186,10 @@ var parseTests = []parseTest{
`{{.X | .Y}}`},
{"pipeline with decl", "{{$x := .X|.Y}}", noError,
`{{$x := .X | .Y}}`},
+ {"nested pipeline", "{{.X (.Y .Z) (.A | .B .C) (.E)}}", noError,
+ `{{.X (.Y .Z) (.A | .B .C) (.E)}}`},
+ {"field applied to parentheses", "{{(.Y .Z).Field}}", noError,
+ `{{(.Y .Z).Field}}`},
{"simple if", "{{if .X}}hello{{end}}", noError,
`{{if .X}}"hello"{{end}}`},
{"if with else", "{{if .X}}true{{else}}false{{end}}", noError,
@@ -205,8 +210,8 @@ var parseTests = []parseTest{
`{{range $x := .SI}}{{.}}{{end}}`},
{"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
`{{range $x, $y := .SI}}{{.}}{{end}}`},
- {"constants", "{{range .SI 1 -3.2i true false 'a'}}{{end}}", noError,
- `{{range .SI 1 -3.2i true false 'a'}}{{end}}`},
+ {"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError,
+ `{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`},
{"template", "{{template `x`}}", noError,
`{{template "x"}}`},
{"template with arg", "{{template `x` .Y}}", noError,
@@ -230,6 +235,9 @@ var parseTests = []parseTest{
{"invalid punctuation", "{{printf 3, 4}}", hasError, ""},
{"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""},
{"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""},
+ {"dot applied to parentheses", "{{printf (printf .).}}", hasError, ""},
+ {"adjacent args", "{{printf 3`x`}}", hasError, ""},
+ {"adjacent args with .", "{{printf `x`.}}", hasError, ""},
// Equals (and other chars) do not assignments make (yet).
{"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"},
{"bug0b", "{{$x = 1}}{{$x}}", hasError, ""},
@@ -316,3 +324,74 @@ func TestIsEmpty(t *testing.T) {
}
}
}
+
+// All failures, and the result is a string that must appear in the error message.
+var errorTests = []parseTest{
+ // Check line numbers are accurate.
+ {"unclosed1",
+ "line1\n{{",
+ hasError, `unclosed1:2: unexpected unclosed action in command`},
+ {"unclosed2",
+ "line1\n{{define `x`}}line2\n{{",
+ hasError, `unclosed2:3: unexpected unclosed action in command`},
+ // Specific errors.
+ {"function",
+ "{{foo}}",
+ hasError, `function "foo" not defined`},
+ {"comment",
+ "{{/*}}",
+ hasError, `unclosed comment`},
+ {"lparen",
+ "{{.X (1 2 3}}",
+ hasError, `unclosed left paren`},
+ {"rparen",
+ "{{.X 1 2 3)}}",
+ hasError, `unexpected ")"`},
+ {"space",
+ "{{`x`3}}",
+ hasError, `missing space?`},
+ {"idchar",
+ "{{a#}}",
+ hasError, `'#'`},
+ {"charconst",
+ "{{'a}}",
+ hasError, `unterminated character constant`},
+ {"stringconst",
+ `{{"a}}`,
+ hasError, `unterminated quoted string`},
+ {"rawstringconst",
+ "{{`a}}",
+ hasError, `unterminated raw quoted string`},
+ {"number",
+ "{{0xi}}",
+ hasError, `number syntax`},
+ {"multidefine",
+ "{{define `a`}}a{{end}}{{define `a`}}b{{end}}",
+ hasError, `multiple definition of template`},
+ {"eof",
+ "{{range .X}}",
+ hasError, `unexpected EOF`},
+ {"variable",
+ // Declare $x so it's defined, to avoid that error, and then check we don't parse a declaration.
+ "{{$x := 23}}{{with $x.y := 3}}{{$x 23}}{{end}}",
+ hasError, `unexpected ":="`},
+ {"multidecl",
+ "{{$a,$b,$c := 23}}",
+ hasError, `too many declarations`},
+ {"undefvar",
+ "{{$a}}",
+ hasError, `undefined variable`},
+}
+
+func TestErrors(t *testing.T) {
+ for _, test := range errorTests {
+ _, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree))
+ if err == nil {
+ t.Errorf("%q: expected error", test.name)
+ continue
+ }
+ if !strings.Contains(err.Error(), test.result) {
+ t.Errorf("%q: error %q does not contain %q", test.name, err, test.result)
+ }
+ }
+}
diff --git a/libgo/go/text/template/template.go b/libgo/go/text/template/template.go
index 82fc9e5e39d..a2b9062ad14 100644
--- a/libgo/go/text/template/template.go
+++ b/libgo/go/text/template/template.go
@@ -117,6 +117,9 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error
// Templates returns a slice of the templates associated with t, including t
// itself.
func (t *Template) Templates() []*Template {
+ if t.common == nil {
+ return nil
+ }
// Return a slice so we don't expose the map.
m := make([]*Template, 0, len(t.tmpl))
for _, v := range t.tmpl {
diff --git a/libgo/go/time/format.go b/libgo/go/time/format.go
index efca3a92699..46f4fbc13b5 100644
--- a/libgo/go/time/format.go
+++ b/libgo/go/time/format.go
@@ -57,63 +57,74 @@ const (
)
const (
- stdLongMonth = "January"
- stdMonth = "Jan"
- stdNumMonth = "1"
- stdZeroMonth = "01"
- stdLongWeekDay = "Monday"
- stdWeekDay = "Mon"
- stdDay = "2"
- stdUnderDay = "_2"
- stdZeroDay = "02"
- stdHour = "15"
- stdHour12 = "3"
- stdZeroHour12 = "03"
- stdMinute = "4"
- stdZeroMinute = "04"
- stdSecond = "5"
- stdZeroSecond = "05"
- stdLongYear = "2006"
- stdYear = "06"
- stdPM = "PM"
- stdpm = "pm"
- stdTZ = "MST"
- stdISO8601TZ = "Z0700" // prints Z for UTC
- stdISO8601ColonTZ = "Z07:00" // prints Z for UTC
- stdNumTZ = "-0700" // always numeric
- stdNumShortTZ = "-07" // always numeric
- stdNumColonTZ = "-07:00" // always numeric
+ _ = iota
+ stdLongMonth = iota + stdNeedDate // "January"
+ stdMonth // "Jan"
+ stdNumMonth // "1"
+ stdZeroMonth // "01"
+ stdLongWeekDay // "Monday"
+ stdWeekDay // "Mon"
+ stdDay // "2"
+ stdUnderDay // "_2"
+ stdZeroDay // "02"
+ stdHour = iota + stdNeedClock // "15"
+ stdHour12 // "3"
+ stdZeroHour12 // "03"
+ stdMinute // "4"
+ stdZeroMinute // "04"
+ stdSecond // "5"
+ stdZeroSecond // "05"
+ stdLongYear = iota + stdNeedDate // "2006"
+ stdYear // "06"
+ stdPM = iota + stdNeedClock // "PM"
+ stdpm // "pm"
+ stdTZ = iota // "MST"
+ stdISO8601TZ // "Z0700" // prints Z for UTC
+ stdISO8601ColonTZ // "Z07:00" // prints Z for UTC
+ stdNumTZ // "-0700" // always numeric
+ stdNumShortTZ // "-07" // always numeric
+ stdNumColonTZ // "-07:00" // always numeric
+ stdFracSecond0 // ".0", ".00", ... , trailing zeros included
+ stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
+
+ stdNeedDate = 1 << 8 // need month, day, year
+ stdNeedClock = 2 << 8 // need hour, minute, second
+ stdArgShift = 16 // extra argument in high bits, above low stdArgShift
+ stdMask = 1<<stdArgShift - 1 // mask out argument
)
+// std0x records the std values for "01", "02", ..., "06".
+var std0x = [...]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear}
+
// nextStdChunk finds the first occurrence of a std string in
// layout and returns the text before, the std string, and the text after.
-func nextStdChunk(layout string) (prefix, std, suffix string) {
+func nextStdChunk(layout string) (prefix string, std int, suffix string) {
for i := 0; i < len(layout); i++ {
- switch layout[i] {
+ switch c := int(layout[i]); c {
case 'J': // January, Jan
- if len(layout) >= i+7 && layout[i:i+7] == stdLongMonth {
- return layout[0:i], stdLongMonth, layout[i+7:]
- }
- if len(layout) >= i+3 && layout[i:i+3] == stdMonth {
+ if len(layout) >= i+3 && layout[i:i+3] == "Jan" {
+ if len(layout) >= i+7 && layout[i:i+7] == "January" {
+ return layout[0:i], stdLongMonth, layout[i+7:]
+ }
return layout[0:i], stdMonth, layout[i+3:]
}
case 'M': // Monday, Mon, MST
- if len(layout) >= i+6 && layout[i:i+6] == stdLongWeekDay {
- return layout[0:i], stdLongWeekDay, layout[i+6:]
- }
if len(layout) >= i+3 {
- if layout[i:i+3] == stdWeekDay {
+ if layout[i:i+3] == "Mon" {
+ if len(layout) >= i+6 && layout[i:i+6] == "Monday" {
+ return layout[0:i], stdLongWeekDay, layout[i+6:]
+ }
return layout[0:i], stdWeekDay, layout[i+3:]
}
- if layout[i:i+3] == stdTZ {
+ if layout[i:i+3] == "MST" {
return layout[0:i], stdTZ, layout[i+3:]
}
}
case '0': // 01, 02, 03, 04, 05, 06
if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' {
- return layout[0:i], layout[i : i+2], layout[i+2:]
+ return layout[0:i], std0x[layout[i+1]-'1'], layout[i+2:]
}
case '1': // 15, 1
@@ -123,7 +134,7 @@ func nextStdChunk(layout string) (prefix, std, suffix string) {
return layout[0:i], stdNumMonth, layout[i+1:]
case '2': // 2006, 2
- if len(layout) >= i+4 && layout[i:i+4] == stdLongYear {
+ if len(layout) >= i+4 && layout[i:i+4] == "2006" {
return layout[0:i], stdLongYear, layout[i+4:]
}
return layout[0:i], stdDay, layout[i+1:]
@@ -133,35 +144,41 @@ func nextStdChunk(layout string) (prefix, std, suffix string) {
return layout[0:i], stdUnderDay, layout[i+2:]
}
- case '3', '4', '5': // 3, 4, 5
- return layout[0:i], layout[i : i+1], layout[i+1:]
+ case '3':
+ return layout[0:i], stdHour12, layout[i+1:]
+
+ case '4':
+ return layout[0:i], stdMinute, layout[i+1:]
+
+ case '5':
+ return layout[0:i], stdSecond, layout[i+1:]
case 'P': // PM
if len(layout) >= i+2 && layout[i+1] == 'M' {
- return layout[0:i], layout[i : i+2], layout[i+2:]
+ return layout[0:i], stdPM, layout[i+2:]
}
case 'p': // pm
if len(layout) >= i+2 && layout[i+1] == 'm' {
- return layout[0:i], layout[i : i+2], layout[i+2:]
+ return layout[0:i], stdpm, layout[i+2:]
}
case '-': // -0700, -07:00, -07
- if len(layout) >= i+5 && layout[i:i+5] == stdNumTZ {
- return layout[0:i], layout[i : i+5], layout[i+5:]
+ if len(layout) >= i+5 && layout[i:i+5] == "-0700" {
+ return layout[0:i], stdNumTZ, layout[i+5:]
}
- if len(layout) >= i+6 && layout[i:i+6] == stdNumColonTZ {
- return layout[0:i], layout[i : i+6], layout[i+6:]
+ if len(layout) >= i+6 && layout[i:i+6] == "-07:00" {
+ return layout[0:i], stdNumColonTZ, layout[i+6:]
}
- if len(layout) >= i+3 && layout[i:i+3] == stdNumShortTZ {
- return layout[0:i], layout[i : i+3], layout[i+3:]
+ if len(layout) >= i+3 && layout[i:i+3] == "-07" {
+ return layout[0:i], stdNumShortTZ, layout[i+3:]
}
case 'Z': // Z0700, Z07:00
- if len(layout) >= i+5 && layout[i:i+5] == stdISO8601TZ {
- return layout[0:i], layout[i : i+5], layout[i+5:]
+ if len(layout) >= i+5 && layout[i:i+5] == "Z0700" {
+ return layout[0:i], stdISO8601TZ, layout[i+5:]
}
- if len(layout) >= i+6 && layout[i:i+6] == stdISO8601ColonTZ {
- return layout[0:i], layout[i : i+6], layout[i+6:]
+ if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
+ return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
}
case '.': // .000 or .999 - repeated digits for fractional seconds.
if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
@@ -172,12 +189,17 @@ func nextStdChunk(layout string) (prefix, std, suffix string) {
}
// String of digits must end here - only fractional second is all digits.
if !isDigit(layout, j) {
- return layout[0:i], layout[i:j], layout[j:]
+ std := stdFracSecond0
+ if layout[i+1] == '9' {
+ std = stdFracSecond9
+ }
+ std |= (j - (i + 1)) << stdArgShift
+ return layout[0:i], std, layout[j:]
}
}
}
}
- return layout, "", ""
+ return layout, 0, ""
}
var longDayNames = []string{
@@ -259,27 +281,36 @@ func lookup(tab []string, val string) (int, string, error) {
return -1, val, errBad
}
+// appendUint appends the decimal form of x to b and returns the result.
+// If x is a single-digit number and pad != 0, appendUint inserts the pad byte
+// before the digit.
// Duplicates functionality in strconv, but avoids dependency.
-func itoa(x int) string {
+func appendUint(b []byte, x uint, pad byte) []byte {
+ if x < 10 {
+ if pad != 0 {
+ b = append(b, pad)
+ }
+ return append(b, byte('0'+x))
+ }
+ if x < 100 {
+ b = append(b, byte('0'+x/10))
+ b = append(b, byte('0'+x%10))
+ return b
+ }
+
var buf [32]byte
n := len(buf)
if x == 0 {
- return "0"
- }
- u := uint(x)
- if x < 0 {
- u = -u
+ return append(b, '0')
}
- for u > 0 {
+ for x >= 10 {
n--
- buf[n] = byte(u%10 + '0')
- u /= 10
+ buf[n] = byte(x%10 + '0')
+ x /= 10
}
- if x < 0 {
- n--
- buf[n] = '-'
- }
- return string(buf[n:])
+ n--
+ buf[n] = byte(x + '0')
+ return append(b, buf[n:]...)
}
// Never printed, just needs to be non-nil for return by atoi.
@@ -302,37 +333,30 @@ func atoi(s string) (x int, err error) {
return x, nil
}
-func pad(i int, padding string) string {
- s := itoa(i)
- if i < 10 {
- s = padding + s
+// formatNano appends a fractional second, as nanoseconds, to b
+// and returns the result.
+func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
+ u := nanosec
+ var buf [9]byte
+ for start := len(buf); start > 0; {
+ start--
+ buf[start] = byte(u%10 + '0')
+ u /= 10
}
- return s
-}
-
-func zeroPad(i int) string { return pad(i, "0") }
-// formatNano formats a fractional second, as nanoseconds.
-func formatNano(nanosec, n int, trim bool) string {
- // User might give us bad data. Make sure it's positive and in range.
- // They'll get nonsense output but it will have the right format.
- s := itoa(int(uint(nanosec) % 1e9))
- // Zero pad left without fmt.
- if len(s) < 9 {
- s = "000000000"[:9-len(s)] + s
- }
if n > 9 {
n = 9
}
if trim {
- for n > 0 && s[n-1] == '0' {
+ for n > 0 && buf[n-1] == '0' {
n--
}
if n == 0 {
- return ""
+ return b
}
}
- return "." + s[:n]
+ b = append(b, '.')
+ return append(b, buf[:n]...)
}
// String returns the time formatted using the format string
@@ -341,16 +365,6 @@ func (t Time) String() string {
return t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
}
-type buffer []byte
-
-func (b *buffer) WriteString(s string) {
- *b = append(*b, s...)
-}
-
-func (b *buffer) String() string {
- return string([]byte(*b))
-}
-
// Format returns a textual representation of the time value formatted
// according to layout. The layout defines the format by showing the
// representation of the standard time,
@@ -361,161 +375,172 @@ func (b *buffer) String() string {
// definition of the standard time, see the documentation for ANSIC.
func (t Time) Format(layout string) string {
var (
+ name, offset, abs = t.locabs()
+
year int = -1
month Month
day int
hour int = -1
min int
sec int
- b buffer
+
+ b []byte
+ buf [64]byte
)
+ max := len(layout) + 10
+ if max <= len(buf) {
+ b = buf[:0]
+ } else {
+ b = make([]byte, 0, max)
+ }
// Each iteration generates one std value.
- for {
+ for layout != "" {
prefix, std, suffix := nextStdChunk(layout)
- b.WriteString(prefix)
- if std == "" {
+ if prefix != "" {
+ b = append(b, prefix...)
+ }
+ if std == 0 {
break
}
+ layout = suffix
// Compute year, month, day if needed.
- if year < 0 {
- // Jan 01 02 2006
- if a, z := std[0], std[len(std)-1]; a == 'J' || a == 'j' || z == '1' || z == '2' || z == '6' {
- year, month, day = t.Date()
- }
+ if year < 0 && std&stdNeedDate != 0 {
+ year, month, day, _ = absDate(abs, true)
}
// Compute hour, minute, second if needed.
- if hour < 0 {
- // 03 04 05 15 pm
- if z := std[len(std)-1]; z == '3' || z == '4' || z == '5' || z == 'm' || z == 'M' {
- hour, min, sec = t.Clock()
- }
+ if hour < 0 && std&stdNeedClock != 0 {
+ hour, min, sec = absClock(abs)
}
- var p string
- switch std {
+ switch std & stdMask {
case stdYear:
- p = zeroPad(year % 100)
+ y := year
+ if y < 0 {
+ y = -y
+ }
+ b = appendUint(b, uint(y%100), '0')
case stdLongYear:
// Pad year to at least 4 digits.
- p = itoa(year)
+ y := year
switch {
case year <= -1000:
- // ok
+ b = append(b, '-')
+ y = -y
case year <= -100:
- p = p[:1] + "0" + p[1:]
+ b = append(b, "-0"...)
+ y = -y
case year <= -10:
- p = p[:1] + "00" + p[1:]
+ b = append(b, "-00"...)
+ y = -y
case year < 0:
- p = p[:1] + "000" + p[1:]
+ b = append(b, "-000"...)
+ y = -y
case year < 10:
- p = "000" + p
+ b = append(b, "000"...)
case year < 100:
- p = "00" + p
+ b = append(b, "00"...)
case year < 1000:
- p = "0" + p
+ b = append(b, '0')
}
+ b = appendUint(b, uint(y), 0)
case stdMonth:
- p = month.String()[:3]
+ b = append(b, month.String()[:3]...)
case stdLongMonth:
- p = month.String()
+ m := month.String()
+ b = append(b, m...)
case stdNumMonth:
- p = itoa(int(month))
+ b = appendUint(b, uint(month), 0)
case stdZeroMonth:
- p = zeroPad(int(month))
+ b = appendUint(b, uint(month), '0')
case stdWeekDay:
- p = t.Weekday().String()[:3]
+ b = append(b, absWeekday(abs).String()[:3]...)
case stdLongWeekDay:
- p = t.Weekday().String()
+ s := absWeekday(abs).String()
+ b = append(b, s...)
case stdDay:
- p = itoa(day)
+ b = appendUint(b, uint(day), 0)
case stdUnderDay:
- p = pad(day, " ")
+ b = appendUint(b, uint(day), ' ')
case stdZeroDay:
- p = zeroPad(day)
+ b = appendUint(b, uint(day), '0')
case stdHour:
- p = zeroPad(hour)
+ b = appendUint(b, uint(hour), '0')
case stdHour12:
// Noon is 12PM, midnight is 12AM.
hr := hour % 12
if hr == 0 {
hr = 12
}
- p = itoa(hr)
+ b = appendUint(b, uint(hr), 0)
case stdZeroHour12:
// Noon is 12PM, midnight is 12AM.
hr := hour % 12
if hr == 0 {
hr = 12
}
- p = zeroPad(hr)
+ b = appendUint(b, uint(hr), '0')
case stdMinute:
- p = itoa(min)
+ b = appendUint(b, uint(min), 0)
case stdZeroMinute:
- p = zeroPad(min)
+ b = appendUint(b, uint(min), '0')
case stdSecond:
- p = itoa(sec)
+ b = appendUint(b, uint(sec), 0)
case stdZeroSecond:
- p = zeroPad(sec)
+ b = appendUint(b, uint(sec), '0')
case stdPM:
if hour >= 12 {
- p = "PM"
+ b = append(b, "PM"...)
} else {
- p = "AM"
+ b = append(b, "AM"...)
}
case stdpm:
if hour >= 12 {
- p = "pm"
+ b = append(b, "pm"...)
} else {
- p = "am"
+ b = append(b, "am"...)
}
case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumColonTZ:
// Ugly special case. We cheat and take the "Z" variants
// to mean "the time zone as formatted for ISO 8601".
- _, offset := t.Zone()
- if offset == 0 && std[0] == 'Z' {
- p = "Z"
+ if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ) {
+ b = append(b, 'Z')
break
}
zone := offset / 60 // convert to minutes
if zone < 0 {
- p = "-"
+ b = append(b, '-')
zone = -zone
} else {
- p = "+"
+ b = append(b, '+')
}
- p += zeroPad(zone / 60)
+ b = appendUint(b, uint(zone/60), '0')
if std == stdISO8601ColonTZ || std == stdNumColonTZ {
- p += ":"
+ b = append(b, ':')
}
- p += zeroPad(zone % 60)
+ b = appendUint(b, uint(zone%60), '0')
case stdTZ:
- name, offset := t.Zone()
if name != "" {
- p = name
- } else {
- // No time zone known for this time, but we must print one.
- // Use the -0700 format.
- zone := offset / 60 // convert to minutes
- if zone < 0 {
- p = "-"
- zone = -zone
- } else {
- p = "+"
- }
- p += zeroPad(zone / 60)
- p += zeroPad(zone % 60)
+ b = append(b, name...)
+ break
}
- default:
- if len(std) >= 2 && (std[0:2] == ".0" || std[0:2] == ".9") {
- p = formatNano(t.Nanosecond(), len(std)-1, std[1] == '9')
+ // No time zone known for this time, but we must print one.
+ // Use the -0700 format.
+ zone := offset / 60 // convert to minutes
+ if zone < 0 {
+ b = append(b, '-')
+ zone = -zone
+ } else {
+ b = append(b, '+')
}
+ b = appendUint(b, uint(zone/60), '0')
+ b = appendUint(b, uint(zone%60), '0')
+ case stdFracSecond0, stdFracSecond9:
+ b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9)
}
- b.WriteString(p)
- layout = suffix
}
- return b.String()
+ return string(b)
}
var errBad = errors.New("bad value for field") // placeholder not passed to user
@@ -638,11 +663,12 @@ func Parse(layout, value string) (Time, error) {
for {
var err error
prefix, std, suffix := nextStdChunk(layout)
+ stdstr := layout[len(prefix) : len(layout)-len(suffix)]
value, err = skip(value, prefix)
if err != nil {
return Time{}, &ParseError{alayout, avalue, prefix, value, ""}
}
- if len(std) == 0 {
+ if std == 0 {
if len(value) != 0 {
return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
}
@@ -650,7 +676,7 @@ func Parse(layout, value string) (Time, error) {
}
layout = suffix
var p string
- switch std {
+ switch std & stdMask {
case stdYear:
if len(value) < 2 {
err = errBad
@@ -716,7 +742,8 @@ func Parse(layout, value string) (Time, error) {
// fractional second in the format?
if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
_, std, _ := nextStdChunk(layout)
- if len(std) > 0 && std[0] == '.' && isDigit(std, 1) {
+ std &= stdMask
+ if std == stdFracSecond0 || std == stdFracSecond9 {
// Fractional second in the layout; proceed normally
break
}
@@ -756,7 +783,7 @@ func Parse(layout, value string) (Time, error) {
err = errBad
}
case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ:
- if std[0] == 'Z' && len(value) >= 1 && value[0] == 'Z' {
+ if (std == stdISO8601TZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' {
value = value[1:]
z = UTC
break
@@ -824,21 +851,31 @@ func Parse(layout, value string) (Time, error) {
}
// It's a valid format.
zoneName = p
- default:
- if len(value) < len(std) {
- err = errBad
+
+ case stdFracSecond0:
+ ndigit := std >> stdArgShift
+ nsec, rangeErrString, err = parseNanoseconds(value, 1+ndigit)
+ value = value[1+ndigit:]
+
+ case stdFracSecond9:
+ if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] {
+ // Fractional second omitted.
break
}
- if len(std) >= 2 && std[0:2] == ".0" {
- nsec, rangeErrString, err = parseNanoseconds(value, len(std))
- value = value[len(std):]
+ // Take any number of digits, even more than asked for,
+ // because it is what the stdSecond case would do.
+ i := 0
+ for i < 9 && i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' {
+ i++
}
+ nsec, rangeErrString, err = parseNanoseconds(value, 1+i)
+ value = value[1+i:]
}
if rangeErrString != "" {
- return Time{}, &ParseError{alayout, avalue, std, value, ": " + rangeErrString + " out of range"}
+ return Time{}, &ParseError{alayout, avalue, stdstr, value, ": " + rangeErrString + " out of range"}
}
if err != nil {
- return Time{}, &ParseError{alayout, avalue, std, value, ""}
+ return Time{}, &ParseError{alayout, avalue, stdstr, value, ""}
}
}
if pmSet && hour < 12 {
diff --git a/libgo/go/time/time.go b/libgo/go/time/time.go
index d48ca0c269e..011a1e31e31 100644
--- a/libgo/go/time/time.go
+++ b/libgo/go/time/time.go
@@ -257,6 +257,30 @@ func (t Time) abs() uint64 {
return uint64(sec + (unixToInternal + internalToAbsolute))
}
+// locabs is a combination of the Zone and abs methods,
+// extracting both return values from a single zone lookup.
+func (t Time) locabs() (name string, offset int, abs uint64) {
+ l := t.loc
+ if l == nil {
+ l = &utcLoc
+ }
+ // Avoid function call if we hit the local time cache.
+ sec := t.sec + internalToUnix
+ if l != &utcLoc {
+ if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
+ name = l.cacheZone.name
+ offset = l.cacheZone.offset
+ } else {
+ name, offset, _, _, _ = l.lookup(sec)
+ }
+ sec += int64(offset)
+ } else {
+ name = "UTC"
+ }
+ abs = uint64(sec + (unixToInternal + internalToAbsolute))
+ return
+}
+
// Date returns the year, month, and day in which t occurs.
func (t Time) Date() (year int, month Month, day int) {
year, month, day, _ = t.date(true)
@@ -283,8 +307,13 @@ func (t Time) Day() int {
// Weekday returns the day of the week specified by t.
func (t Time) Weekday() Weekday {
+ return absWeekday(t.abs())
+}
+
+// absWeekday is like Weekday but operates on an absolute time.
+func absWeekday(abs uint64) Weekday {
// January 1 of the absolute year, like January 1 of 2001, was a Monday.
- sec := (t.abs() + uint64(Monday)*secondsPerDay) % secondsPerWeek
+ sec := (abs + uint64(Monday)*secondsPerDay) % secondsPerWeek
return Weekday(int(sec) / secondsPerDay)
}
@@ -349,7 +378,12 @@ func (t Time) ISOWeek() (year, week int) {
// Clock returns the hour, minute, and second within the day specified by t.
func (t Time) Clock() (hour, min, sec int) {
- sec = int(t.abs() % secondsPerDay)
+ return absClock(t.abs())
+}
+
+// absClock is like clock but operates on an absolute time.
+func absClock(abs uint64) (hour, min, sec int) {
+ sec = int(abs % secondsPerDay)
hour = sec / secondsPerHour
sec -= hour * secondsPerHour
min = sec / secondsPerMinute
@@ -378,6 +412,13 @@ func (t Time) Nanosecond() int {
return int(t.nsec)
}
+// YearDay returns the day of the year specified by t, in the range [1,365] for non-leap years,
+// and [1,366] in leap years.
+func (t Time) YearDay() int {
+ _, _, _, yday := t.date(false)
+ return yday + 1
+}
+
// A Duration represents the elapsed time between two instants
// as an int64 nanosecond count. The representation limits the
// largest representable duration to approximately 290 years.
@@ -607,11 +648,16 @@ const (
days1970To2001 = 31*365 + 8
)
-// date computes the year and, only when full=true,
+// date computes the year, day of year, and when full=true,
// the month and day in which t occurs.
func (t Time) date(full bool) (year int, month Month, day int, yday int) {
+ return absDate(t.abs(), full)
+}
+
+// absDate is like date but operates on an absolute time.
+func absDate(abs uint64, full bool) (year int, month Month, day int, yday int) {
// Split into time and day.
- d := t.abs() / secondsPerDay
+ d := abs / secondsPerDay
// Account for 400 year cycles.
n := d / daysPer400Years
diff --git a/libgo/go/time/time_test.go b/libgo/go/time/time_test.go
index c48e0a4300c..23bb6a55bc1 100644
--- a/libgo/go/time/time_test.go
+++ b/libgo/go/time/time_test.go
@@ -324,6 +324,16 @@ var parseTests = []ParseTest{
// Leading zeros in other places should not be taken as fractional seconds.
{"zero1", "2006.01.02.15.04.05.0", "2010.02.04.21.00.57.0", false, false, 1, 1},
{"zero2", "2006.01.02.15.04.05.00", "2010.02.04.21.00.57.01", false, false, 1, 2},
+
+ // Accept any number of fractional second digits (including none) for .999...
+ // In Go 1, .999... was completely ignored in the format, meaning the first two
+ // cases would succeed, but the next four would not. Go 1.1 accepts all six.
+ {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
+ {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
+ {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
+ {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
+ {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
+ {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
}
func TestParse(t *testing.T) {
@@ -601,6 +611,103 @@ func TestISOWeek(t *testing.T) {
}
}
+type YearDayTest struct {
+ year, month, day int
+ yday int
+}
+
+// Test YearDay in several different scenarios
+// and corner cases
+var yearDayTests = []YearDayTest{
+ // Non-leap-year tests
+ {2007, 1, 1, 1},
+ {2007, 1, 15, 15},
+ {2007, 2, 1, 32},
+ {2007, 2, 15, 46},
+ {2007, 3, 1, 60},
+ {2007, 3, 15, 74},
+ {2007, 4, 1, 91},
+ {2007, 12, 31, 365},
+
+ // Leap-year tests
+ {2008, 1, 1, 1},
+ {2008, 1, 15, 15},
+ {2008, 2, 1, 32},
+ {2008, 2, 15, 46},
+ {2008, 3, 1, 61},
+ {2008, 3, 15, 75},
+ {2008, 4, 1, 92},
+ {2008, 12, 31, 366},
+
+ // Looks like leap-year (but isn't) tests
+ {1900, 1, 1, 1},
+ {1900, 1, 15, 15},
+ {1900, 2, 1, 32},
+ {1900, 2, 15, 46},
+ {1900, 3, 1, 60},
+ {1900, 3, 15, 74},
+ {1900, 4, 1, 91},
+ {1900, 12, 31, 365},
+
+ // Year one tests (non-leap)
+ {1, 1, 1, 1},
+ {1, 1, 15, 15},
+ {1, 2, 1, 32},
+ {1, 2, 15, 46},
+ {1, 3, 1, 60},
+ {1, 3, 15, 74},
+ {1, 4, 1, 91},
+ {1, 12, 31, 365},
+
+ // Year minus one tests (non-leap)
+ {-1, 1, 1, 1},
+ {-1, 1, 15, 15},
+ {-1, 2, 1, 32},
+ {-1, 2, 15, 46},
+ {-1, 3, 1, 60},
+ {-1, 3, 15, 74},
+ {-1, 4, 1, 91},
+ {-1, 12, 31, 365},
+
+ // 400 BC tests (leap-year)
+ {-400, 1, 1, 1},
+ {-400, 1, 15, 15},
+ {-400, 2, 1, 32},
+ {-400, 2, 15, 46},
+ {-400, 3, 1, 61},
+ {-400, 3, 15, 75},
+ {-400, 4, 1, 92},
+ {-400, 12, 31, 366},
+
+ // Special Cases
+
+ // Gregorian calendar change (no effect)
+ {1582, 10, 4, 277},
+ {1582, 10, 15, 288},
+}
+
+// Check to see if YearDay is location sensitive
+var yearDayLocations = []*Location{
+ FixedZone("UTC-8", -8*60*60),
+ FixedZone("UTC-4", -4*60*60),
+ UTC,
+ FixedZone("UTC+4", 4*60*60),
+ FixedZone("UTC+8", 8*60*60),
+}
+
+func TestYearDay(t *testing.T) {
+ for _, loc := range yearDayLocations {
+ for _, ydt := range yearDayTests {
+ dt := Date(ydt.year, Month(ydt.month), ydt.day, 0, 0, 0, 0, loc)
+ yday := dt.YearDay()
+ if yday != ydt.yday {
+ t.Errorf("got %d, expected %d for %d-%02d-%02d in %v",
+ yday, ydt.yday, ydt.year, ydt.month, ydt.day, loc)
+ }
+ }
+ }
+}
+
var durationTests = []struct {
str string
d Duration
@@ -741,7 +848,7 @@ var gobTests = []Time{
Date(0, 1, 2, 3, 4, 5, 6, UTC),
Date(7, 8, 9, 10, 11, 12, 13, FixedZone("", 0)),
Unix(81985467080890095, 0x76543210), // Time.sec: 0x0123456789ABCDEF
- Time{}, // nil location
+ {}, // nil location
Date(1, 2, 3, 4, 5, 6, 7, FixedZone("", 32767*60)),
Date(1, 2, 3, 4, 5, 6, 7, FixedZone("", -32768*60)),
}
@@ -935,9 +1042,18 @@ func BenchmarkNow(b *testing.B) {
}
func BenchmarkFormat(b *testing.B) {
- time := Unix(1265346057, 0)
+ t := Unix(1265346057, 0)
+ for i := 0; i < b.N; i++ {
+ t.Format("Mon Jan 2 15:04:05 2006")
+ }
+}
+
+func BenchmarkFormatNow(b *testing.B) {
+ // Like BenchmarkFormat, but easier, because the time zone
+ // lookup cache is optimized for the present.
+ t := Now()
for i := 0; i < b.N; i++ {
- time.Format("Mon Jan 2 15:04:05 2006")
+ t.Format("Mon Jan 2 15:04:05 2006")
}
}
diff --git a/libgo/go/time/zoneinfo.go b/libgo/go/time/zoneinfo.go
index 3c57744043e..116d3430058 100644
--- a/libgo/go/time/zoneinfo.go
+++ b/libgo/go/time/zoneinfo.go
@@ -123,21 +123,23 @@ func (l *Location) lookup(sec int64) (name string, offset int, isDST bool, start
// Not using sort.Search to avoid dependencies.
tx := l.tx
end = 1<<63 - 1
- for len(tx) > 1 {
- m := len(tx) / 2
+ lo := 0
+ hi := len(tx)
+ for hi-lo > 1 {
+ m := lo + (hi-lo)/2
lim := tx[m].when
if sec < lim {
end = lim
- tx = tx[0:m]
+ hi = m
} else {
- tx = tx[m:]
+ lo = m
}
}
- zone := &l.zone[tx[0].index]
+ zone := &l.zone[tx[lo].index]
name = zone.name
offset = zone.offset
isDST = zone.isDST
- start = tx[0].when
+ start = tx[lo].when
// end = maintained during the search
return
}
diff --git a/libgo/go/time/zoneinfo_read.go b/libgo/go/time/zoneinfo_read.go
index ebb4205a98f..d57c09e115f 100644
--- a/libgo/go/time/zoneinfo_read.go
+++ b/libgo/go/time/zoneinfo_read.go
@@ -141,7 +141,7 @@ func loadZoneData(bytes []byte) (l *Location, err error) {
if n, ok = zonedata.big4(); !ok {
return nil, badData
}
- zone[i].offset = int(n)
+ zone[i].offset = int(int32(n))
var b byte
if b, ok = zonedata.byte(); !ok {
return nil, badData
diff --git a/libgo/go/unicode/digit.go b/libgo/go/unicode/digit.go
index 4800bd6ea8e..53171b3969d 100644
--- a/libgo/go/unicode/digit.go
+++ b/libgo/go/unicode/digit.go
@@ -9,5 +9,5 @@ func IsDigit(r rune) bool {
if r <= MaxLatin1 {
return '0' <= r && r <= '9'
}
- return Is(Digit, r)
+ return isExcludingLatin(Digit, r)
}
diff --git a/libgo/go/unicode/graphic.go b/libgo/go/unicode/graphic.go
index 0de90ebd80c..1105688d43a 100644
--- a/libgo/go/unicode/graphic.go
+++ b/libgo/go/unicode/graphic.go
@@ -78,13 +78,13 @@ func IsLetter(r rune) bool {
if uint32(r) <= MaxLatin1 {
return properties[uint8(r)]&(pLu|pLl) != 0
}
- return Is(Letter, r)
+ return isExcludingLatin(Letter, r)
}
// IsMark reports whether the rune is a mark character (category M).
func IsMark(r rune) bool {
// There are no mark characters in Latin-1.
- return Is(Mark, r)
+ return isExcludingLatin(Mark, r)
}
// IsNumber reports whether the rune is a number (category N).
@@ -92,7 +92,7 @@ func IsNumber(r rune) bool {
if uint32(r) <= MaxLatin1 {
return properties[uint8(r)]&pN != 0
}
- return Is(Number, r)
+ return isExcludingLatin(Number, r)
}
// IsPunct reports whether the rune is a Unicode punctuation character
@@ -119,7 +119,7 @@ func IsSpace(r rune) bool {
}
return false
}
- return Is(White_Space, r)
+ return isExcludingLatin(White_Space, r)
}
// IsSymbol reports whether the rune is a symbolic character.
@@ -127,5 +127,5 @@ func IsSymbol(r rune) bool {
if uint32(r) <= MaxLatin1 {
return properties[uint8(r)]&pS != 0
}
- return Is(Symbol, r)
+ return isExcludingLatin(Symbol, r)
}
diff --git a/libgo/go/unicode/letter.go b/libgo/go/unicode/letter.go
index be484553dc4..8239557e3fc 100644
--- a/libgo/go/unicode/letter.go
+++ b/libgo/go/unicode/letter.go
@@ -19,8 +19,9 @@ const (
// The two slices must be in sorted order and non-overlapping.
// Also, R32 should contain only values >= 0x10000 (1<<16).
type RangeTable struct {
- R16 []Range16
- R32 []Range32
+ R16 []Range16
+ R32 []Range32
+ LatinOffset int // number of entries in R16 with Hi <= MaxLatin1
}
// Range16 represents of a range of 16-bit Unicode code points. The range runs from Lo to Hi
@@ -80,14 +81,31 @@ const (
UpperLower = MaxRune + 1 // (Cannot be a valid delta.)
)
-// is16 uses binary search to test whether rune is in the specified slice of 16-bit ranges.
+// linearMax is the maximum size table for linear search for non-Latin1 rune.
+// Derived by running 'go test -calibrate'.
+const linearMax = 18
+
+// is16 reports whether r is in the sorted slice of 16-bit ranges.
func is16(ranges []Range16, r uint16) bool {
+ if len(ranges) <= linearMax || r <= MaxLatin1 {
+ for i := range ranges {
+ range_ := &ranges[i]
+ if r < range_.Lo {
+ return false
+ }
+ if r <= range_.Hi {
+ return (r-range_.Lo)%range_.Stride == 0
+ }
+ }
+ return false
+ }
+
// binary search over ranges
lo := 0
hi := len(ranges)
for lo < hi {
m := lo + (hi-lo)/2
- range_ := ranges[m]
+ range_ := &ranges[m]
if range_.Lo <= r && r <= range_.Hi {
return (r-range_.Lo)%range_.Stride == 0
}
@@ -100,8 +118,21 @@ func is16(ranges []Range16, r uint16) bool {
return false
}
-// is32 uses binary search to test whether rune is in the specified slice of 32-bit ranges.
+// is32 reports whether r is in the sorted slice of 32-bit ranges.
func is32(ranges []Range32, r uint32) bool {
+ if len(ranges) <= linearMax {
+ for i := range ranges {
+ range_ := &ranges[i]
+ if r < range_.Lo {
+ return false
+ }
+ if r <= range_.Hi {
+ return (r-range_.Lo)%range_.Stride == 0
+ }
+ }
+ return false
+ }
+
// binary search over ranges
lo := 0
hi := len(ranges)
@@ -122,21 +153,6 @@ func is32(ranges []Range32, r uint32) bool {
// Is tests whether rune is in the specified table of ranges.
func Is(rangeTab *RangeTable, r rune) bool {
- // common case: rune is ASCII or Latin-1.
- if uint32(r) <= MaxLatin1 {
- // Only need to check R16, since R32 is always >= 1<<16.
- r16 := uint16(r)
- for _, r := range rangeTab.R16 {
- if r16 > r.Hi {
- continue
- }
- if r16 < r.Lo {
- return false
- }
- return (r16-r.Lo)%r.Stride == 0
- }
- return false
- }
r16 := rangeTab.R16
if len(r16) > 0 && r <= rune(r16[len(r16)-1].Hi) {
return is16(r16, uint16(r))
@@ -148,13 +164,25 @@ func Is(rangeTab *RangeTable, r rune) bool {
return false
}
+func isExcludingLatin(rangeTab *RangeTable, r rune) bool {
+ r16 := rangeTab.R16
+ if off := rangeTab.LatinOffset; len(r16) > off && r <= rune(r16[len(r16)-1].Hi) {
+ return is16(r16[off:], uint16(r))
+ }
+ r32 := rangeTab.R32
+ if len(r32) > 0 && r >= rune(r32[0].Lo) {
+ return is32(r32, uint32(r))
+ }
+ return false
+}
+
// IsUpper reports whether the rune is an upper case letter.
func IsUpper(r rune) bool {
// See comment in IsGraphic.
if uint32(r) <= MaxLatin1 {
return properties[uint8(r)]&pLu != 0
}
- return Is(Upper, r)
+ return isExcludingLatin(Upper, r)
}
// IsLower reports whether the rune is a lower case letter.
@@ -163,7 +191,7 @@ func IsLower(r rune) bool {
if uint32(r) <= MaxLatin1 {
return properties[uint8(r)]&pLl != 0
}
- return Is(Lower, r)
+ return isExcludingLatin(Lower, r)
}
// IsTitle reports whether the rune is a title case letter.
@@ -171,7 +199,7 @@ func IsTitle(r rune) bool {
if r <= MaxLatin1 {
return false
}
- return Is(Title, r)
+ return isExcludingLatin(Title, r)
}
// to maps the rune using the specified case mapping.
diff --git a/libgo/go/unicode/letter_test.go b/libgo/go/unicode/letter_test.go
index 2d80562182c..0ec25ab7e2b 100644
--- a/libgo/go/unicode/letter_test.go
+++ b/libgo/go/unicode/letter_test.go
@@ -5,6 +5,10 @@
package unicode_test
import (
+ "flag"
+ "fmt"
+ "runtime"
+ "sort"
"testing"
. "unicode"
)
@@ -427,3 +431,117 @@ func TestSimpleFold(t *testing.T) {
}
}
}
+
+// Running 'go test -calibrate' runs the calibration to find a plausible
+// cutoff point for linear search of a range list vs. binary search.
+// We create a fake table and then time how long it takes to do a
+// sequence of searches within that table, for all possible inputs
+// relative to the ranges (something before all, in each, between each, after all).
+// This assumes that all possible runes are equally likely.
+// In practice most runes are ASCII so this is a conservative estimate
+// of an effective cutoff value. In practice we could probably set it higher
+// than what this function recommends.
+
+var calibrate = flag.Bool("calibrate", false, "compute crossover for linear vs. binary search")
+
+func TestCalibrate(t *testing.T) {
+ if !*calibrate {
+ return
+ }
+
+ if runtime.GOARCH == "amd64" {
+ fmt.Printf("warning: running calibration on %s\n", runtime.GOARCH)
+ }
+
+ // Find the point where binary search wins by more than 10%.
+ // The 10% bias gives linear search an edge when they're close,
+ // because on predominantly ASCII inputs linear search is even
+ // better than our benchmarks measure.
+ n := sort.Search(64, func(n int) bool {
+ tab := fakeTable(n)
+ blinear := func(b *testing.B) {
+ tab := tab
+ max := n*5 + 20
+ for i := 0; i < b.N; i++ {
+ for j := 0; j <= max; j++ {
+ linear(tab, uint16(j))
+ }
+ }
+ }
+ bbinary := func(b *testing.B) {
+ tab := tab
+ max := n*5 + 20
+ for i := 0; i < b.N; i++ {
+ for j := 0; j <= max; j++ {
+ binary(tab, uint16(j))
+ }
+ }
+ }
+ bmlinear := testing.Benchmark(blinear)
+ bmbinary := testing.Benchmark(bbinary)
+ fmt.Printf("n=%d: linear=%d binary=%d\n", n, bmlinear.NsPerOp(), bmbinary.NsPerOp())
+ return bmlinear.NsPerOp()*100 > bmbinary.NsPerOp()*110
+ })
+ fmt.Printf("calibration: linear cutoff = %d\n", n)
+}
+
+func fakeTable(n int) []Range16 {
+ var r16 []Range16
+ for i := 0; i < n; i++ {
+ r16 = append(r16, Range16{uint16(i*5 + 10), uint16(i*5 + 12), 1})
+ }
+ return r16
+}
+
+func linear(ranges []Range16, r uint16) bool {
+ for i := range ranges {
+ range_ := &ranges[i]
+ if r < range_.Lo {
+ return false
+ }
+ if r <= range_.Hi {
+ return (r-range_.Lo)%range_.Stride == 0
+ }
+ }
+ return false
+}
+
+func binary(ranges []Range16, r uint16) bool {
+ // binary search over ranges
+ lo := 0
+ hi := len(ranges)
+ for lo < hi {
+ m := lo + (hi-lo)/2
+ range_ := &ranges[m]
+ if range_.Lo <= r && r <= range_.Hi {
+ return (r-range_.Lo)%range_.Stride == 0
+ }
+ if r < range_.Lo {
+ hi = m
+ } else {
+ lo = m + 1
+ }
+ }
+ return false
+}
+
+func TestLatinOffset(t *testing.T) {
+ var maps = []map[string]*RangeTable{
+ Categories,
+ FoldCategory,
+ FoldScript,
+ Properties,
+ Scripts,
+ }
+ for _, m := range maps {
+ for name, tab := range m {
+ i := 0
+ for i < len(tab.R16) && tab.R16[i].Hi <= MaxLatin1 {
+ i++
+ }
+ if tab.LatinOffset != i {
+ t.Errorf("%s: LatinOffset=%d, want %d", name, tab.LatinOffset, i)
+ }
+ }
+ }
+}
diff --git a/libgo/go/unicode/tables.go b/libgo/go/unicode/tables.go
index ebd169b0991..859e53c3ce4 100644
--- a/libgo/go/unicode/tables.go
+++ b/libgo/go/unicode/tables.go
@@ -71,6 +71,7 @@ var _C = &RangeTable{
{0xf0000, 0xffffd, 1},
{0x100000, 0x10fffd, 1},
},
+ LatinOffset: 2,
}
var _Cc = &RangeTable{
@@ -78,6 +79,7 @@ var _Cc = &RangeTable{
{0x0001, 0x001f, 1},
{0x007f, 0x009f, 1},
},
+ LatinOffset: 2,
}
var _Cf = &RangeTable{
@@ -536,6 +538,7 @@ var _L = &RangeTable{
{0x2b740, 0x2b81d, 1},
{0x2f800, 0x2fa1d, 1},
},
+ LatinOffset: 6,
}
var _Ll = &RangeTable{
@@ -682,6 +685,7 @@ var _Ll = &RangeTable{
{0x1d7c4, 0x1d7c9, 1},
{0x1d7cb, 0x1d7cb, 1},
},
+ LatinOffset: 5,
}
var _Lm = &RangeTable{
@@ -1186,6 +1190,7 @@ var _Lu = &RangeTable{
{0x1d790, 0x1d7a8, 1},
{0x1d7ca, 0x1d7ca, 1},
},
+ LatinOffset: 3,
}
var _M = &RangeTable{
@@ -1769,6 +1774,7 @@ var _N = &RangeTable{
{0x1d7ce, 0x1d7ff, 1},
{0x1f100, 0x1f10a, 1},
},
+ LatinOffset: 4,
}
var _Nd = &RangeTable{
@@ -1814,6 +1820,7 @@ var _Nd = &RangeTable{
{0x11066, 0x1106f, 1},
{0x1d7ce, 0x1d7ff, 1},
},
+ LatinOffset: 1,
}
var _Nl = &RangeTable{
@@ -1879,6 +1886,7 @@ var _No = &RangeTable{
{0x1d360, 0x1d371, 1},
{0x1f100, 0x1f10a, 1},
},
+ LatinOffset: 3,
}
var _P = &RangeTable{
@@ -2003,6 +2011,7 @@ var _P = &RangeTable{
{0x110be, 0x110c1, 1},
{0x12470, 0x12473, 1},
},
+ LatinOffset: 10,
}
var _Pc = &RangeTable{
@@ -2053,6 +2062,7 @@ var _Pe = &RangeTable{
{0xff09, 0xff3d, 52},
{0xff5d, 0xff63, 3},
},
+ LatinOffset: 1,
}
var _Pf = &RangeTable{
@@ -2194,6 +2204,7 @@ var _Po = &RangeTable{
{0x110be, 0x110c1, 1},
{0x12470, 0x12473, 1},
},
+ LatinOffset: 7,
}
var _Ps = &RangeTable{
@@ -2222,6 +2233,7 @@ var _Ps = &RangeTable{
{0xff5b, 0xff5f, 4},
{0xff62, 0xff62, 1},
},
+ LatinOffset: 1,
}
var _S = &RangeTable{
@@ -2409,6 +2421,7 @@ var _S = &RangeTable{
{0x1f680, 0x1f6c5, 1},
{0x1f700, 0x1f773, 1},
},
+ LatinOffset: 9,
}
var _Sc = &RangeTable{
@@ -2425,6 +2438,7 @@ var _Sc = &RangeTable{
{0xffe0, 0xffe1, 1},
{0xffe5, 0xffe6, 1},
},
+ LatinOffset: 2,
}
var _Sk = &RangeTable{
@@ -2452,6 +2466,7 @@ var _Sk = &RangeTable{
{0xff3e, 0xff40, 2},
{0xffe3, 0xffe3, 1},
},
+ LatinOffset: 3,
}
var _Sm = &RangeTable{
@@ -2510,6 +2525,7 @@ var _Sm = &RangeTable{
{0x1d76f, 0x1d789, 26},
{0x1d7a9, 0x1d7c3, 26},
},
+ LatinOffset: 5,
}
var _So = &RangeTable{
@@ -2666,6 +2682,7 @@ var _So = &RangeTable{
{0x1f680, 0x1f6c5, 1},
{0x1f700, 0x1f773, 1},
},
+ LatinOffset: 3,
}
var _Z = &RangeTable{
@@ -2677,6 +2694,7 @@ var _Z = &RangeTable{
{0x202f, 0x205f, 48},
{0x3000, 0x3000, 1},
},
+ LatinOffset: 1,
}
var _Zl = &RangeTable{
@@ -2699,6 +2717,7 @@ var _Zs = &RangeTable{
{0x202f, 0x205f, 48},
{0x3000, 0x3000, 1},
},
+ LatinOffset: 1,
}
// These variables have type *RangeTable.
@@ -3179,6 +3198,7 @@ var _Common = &RangeTable{
{0xe0001, 0xe0001, 1},
{0xe0020, 0xe007f, 1},
},
+ LatinOffset: 7,
}
var _Coptic = &RangeTable{
@@ -3649,6 +3669,7 @@ var _Latin = &RangeTable{
{0xff21, 0xff3a, 1},
{0xff41, 0xff5a, 1},
},
+ LatinOffset: 6,
}
var _Lepcha = &RangeTable{
@@ -4199,6 +4220,7 @@ var _ASCII_Hex_Digit = &RangeTable{
{0x0041, 0x0046, 1},
{0x0061, 0x0066, 1},
},
+ LatinOffset: 3,
}
var _Bidi_Control = &RangeTable{
@@ -4230,6 +4252,7 @@ var _Dash = &RangeTable{
{0xfe63, 0xfe63, 1},
{0xff0d, 0xff0d, 1},
},
+ LatinOffset: 1,
}
var _Deprecated = &RangeTable{
@@ -4370,6 +4393,7 @@ var _Diacritic = &RangeTable{
{0x1d185, 0x1d18b, 1},
{0x1d1aa, 0x1d1ad, 1},
},
+ LatinOffset: 6,
}
var _Extender = &RangeTable{
@@ -4395,6 +4419,7 @@ var _Extender = &RangeTable{
{0xaadd, 0xaadd, 1},
{0xff70, 0xff70, 1},
},
+ LatinOffset: 1,
}
var _Hex_Digit = &RangeTable{
@@ -4406,6 +4431,7 @@ var _Hex_Digit = &RangeTable{
{0xff21, 0xff26, 1},
{0xff41, 0xff46, 1},
},
+ LatinOffset: 3,
}
var _Hyphen = &RangeTable{
@@ -4421,6 +4447,7 @@ var _Hyphen = &RangeTable{
{0xff0d, 0xff0d, 1},
{0xff65, 0xff65, 1},
},
+ LatinOffset: 2,
}
var _IDS_Binary_Operator = &RangeTable{
@@ -4695,6 +4722,7 @@ var _Other_ID_Continue = &RangeTable{
{0x1369, 0x1371, 1},
{0x19da, 0x19da, 1},
},
+ LatinOffset: 1,
}
var _Other_ID_Start = &RangeTable{
@@ -4828,6 +4856,7 @@ var _Other_Math = &RangeTable{
{0x1d7c4, 0x1d7cb, 1},
{0x1d7ce, 0x1d7ff, 1},
},
+ LatinOffset: 1,
}
var _Other_Uppercase = &RangeTable{
@@ -4868,6 +4897,7 @@ var _Pattern_Syntax = &RangeTable{
{0xfd3e, 0xfd3f, 1},
{0xfe45, 0xfe46, 1},
},
+ LatinOffset: 15,
}
var _Pattern_White_Space = &RangeTable{
@@ -4878,6 +4908,7 @@ var _Pattern_White_Space = &RangeTable{
{0x200e, 0x200f, 1},
{0x2028, 0x2029, 1},
},
+ LatinOffset: 3,
}
var _Quotation_Mark = &RangeTable{
@@ -4895,6 +4926,7 @@ var _Quotation_Mark = &RangeTable{
{0xff07, 0xff07, 1},
{0xff62, 0xff63, 1},
},
+ LatinOffset: 4,
}
var _Radical = &RangeTable{
@@ -4957,6 +4989,7 @@ var _STerm = &RangeTable{
{0x11047, 0x11048, 1},
{0x110be, 0x110c1, 1},
},
+ LatinOffset: 3,
}
var _Soft_Dotted = &RangeTable{
@@ -4995,6 +5028,7 @@ var _Soft_Dotted = &RangeTable{
{0x1d65e, 0x1d65f, 1},
{0x1d692, 0x1d693, 1},
},
+ LatinOffset: 1,
}
var _Terminal_Punctuation = &RangeTable{
@@ -5069,6 +5103,7 @@ var _Terminal_Punctuation = &RangeTable{
{0x110be, 0x110c1, 1},
{0x12470, 0x12473, 1},
},
+ LatinOffset: 5,
}
var _Unified_Ideograph = &RangeTable{
@@ -5114,6 +5149,7 @@ var _White_Space = &RangeTable{
{0x205f, 0x205f, 1},
{0x3000, 0x3000, 1},
},
+ LatinOffset: 4,
}
// These variables have type *RangeTable.
@@ -5887,6 +5923,7 @@ var foldLl = &RangeTable{
R32: []Range32{
{0x10400, 0x10427, 1},
},
+ LatinOffset: 3,
}
var foldLt = &RangeTable{
@@ -6001,6 +6038,7 @@ var foldLu = &RangeTable{
R32: []Range32{
{0x10428, 0x1044f, 1},
},
+ LatinOffset: 4,
}
var foldM = &RangeTable{
diff --git a/libgo/go/unicode/utf8/example_test.go b/libgo/go/unicode/utf8/example_test.go
new file mode 100644
index 00000000000..fe20373368e
--- /dev/null
+++ b/libgo/go/unicode/utf8/example_test.go
@@ -0,0 +1,192 @@
+package utf8_test
+
+import (
+ "fmt"
+ "unicode/utf8"
+)
+
+func ExampleDecodeLastRune() {
+ b := []byte("Hello, 世界")
+
+ for len(b) > 0 {
+ r, size := utf8.DecodeLastRune(b)
+ fmt.Printf("%c %v\n", r, size)
+
+ b = b[:len(b)-size]
+ }
+ // Output:
+ // 界 3
+ // 世 3
+ // 1
+ // , 1
+ // o 1
+ // l 1
+ // l 1
+ // e 1
+ // H 1
+}
+
+func ExampleDecodeLastRuneInString() {
+ str := "Hello, 世界"
+
+ for len(str) > 0 {
+ r, size := utf8.DecodeLastRuneInString(str)
+ fmt.Printf("%c %v\n", r, size)
+
+ str = str[:len(str)-size]
+ }
+ // Output:
+ // 界 3
+ // 世 3
+ // 1
+ // , 1
+ // o 1
+ // l 1
+ // l 1
+ // e 1
+ // H 1
+
+}
+
+func ExampleDecodeRune() {
+ b := []byte("Hello, 世界")
+
+ for len(b) > 0 {
+ r, size := utf8.DecodeRune(b)
+ fmt.Printf("%c %v\n", r, size)
+
+ b = b[size:]
+ }
+ // Output:
+ // H 1
+ // e 1
+ // l 1
+ // l 1
+ // o 1
+ // , 1
+ // 1
+ // 世 3
+ // 界 3
+}
+
+func ExampleDecodeRuneInString() {
+ str := "Hello, 世界"
+
+ for len(str) > 0 {
+ r, size := utf8.DecodeRuneInString(str)
+ fmt.Printf("%c %v\n", r, size)
+
+ str = str[size:]
+ }
+ // Output:
+ // H 1
+ // e 1
+ // l 1
+ // l 1
+ // o 1
+ // , 1
+ // 1
+ // 世 3
+ // 界 3
+}
+
+func ExampleEncodeRune() {
+ r := '世'
+ buf := make([]byte, 3)
+
+ n := utf8.EncodeRune(buf, r)
+
+ fmt.Println(buf)
+ fmt.Println(n)
+ // Output:
+ // [228 184 150]
+ // 3
+}
+
+func ExampleFullRune() {
+ buf := []byte{228, 184, 150} // 世
+ fmt.Println(utf8.FullRune(buf))
+ fmt.Println(utf8.FullRune(buf[:2]))
+ // Output:
+ // true
+ // false
+}
+
+func ExampleFullRuneInString() {
+ str := "世"
+ fmt.Println(utf8.FullRuneInString(str))
+ fmt.Println(utf8.FullRuneInString(str[:2]))
+ // Output:
+ // true
+ // false
+}
+
+func ExampleRuneCount() {
+ buf := []byte("Hello, 世界")
+ fmt.Println("bytes =", len(buf))
+ fmt.Println("runes =", utf8.RuneCount(buf))
+ // Output:
+ // bytes = 13
+ // runes = 9
+}
+
+func ExampleRuneCountInString() {
+ str := "Hello, 世界"
+ fmt.Println("bytes =", len(str))
+ fmt.Println("runes =", utf8.RuneCountInString(str))
+ // Output:
+ // bytes = 13
+ // runes = 9
+}
+
+func ExampleRuneLen() {
+ fmt.Println(utf8.RuneLen('a'))
+ fmt.Println(utf8.RuneLen('界'))
+ // Output:
+ // 1
+ // 3
+}
+
+func ExampleRuneStart() {
+ buf := []byte("a界")
+ fmt.Println(utf8.RuneStart(buf[0]))
+ fmt.Println(utf8.RuneStart(buf[1]))
+ fmt.Println(utf8.RuneStart(buf[2]))
+ // Output:
+ // true
+ // true
+ // false
+}
+
+func ExampleValid() {
+ valid := []byte("Hello, 世界")
+ invalid := []byte{0xff, 0xfe, 0xfd}
+
+ fmt.Println(utf8.Valid(valid))
+ fmt.Println(utf8.Valid(invalid))
+ // Output:
+ // true
+ // false
+}
+
+func ExampleValidRune() {
+ valid := 'a'
+ invalid := rune(0xfffffff)
+
+ fmt.Println(utf8.ValidRune(valid))
+ fmt.Println(utf8.ValidRune(invalid))
+ // Output:
+ // true
+ // false
+}
+
+func ExampleValidString() {
+ valid := "Hello, 世界"
+ invalid := string([]byte{0xff, 0xfe, 0xfd})
+
+ fmt.Println(utf8.ValidString(valid))
+ fmt.Println(utf8.ValidString(invalid))
+ // Output:
+ // true
+ // false
+}
diff --git a/libgo/go/unicode/utf8/utf8.go b/libgo/go/unicode/utf8/utf8.go
index 57ea19e96d4..ad235777406 100644
--- a/libgo/go/unicode/utf8/utf8.go
+++ b/libgo/go/unicode/utf8/utf8.go
@@ -18,6 +18,12 @@ const (
UTFMax = 4 // maximum number of bytes of a UTF-8 encoded Unicode character.
)
+// Code points in the surrogate range are not valid for UTF-8.
+const (
+ surrogateMin = 0xD800
+ surrogateMax = 0xDFFF
+)
+
const (
t1 = 0x00 // 0000 0000
tx = 0x80 // 1000 0000
@@ -34,7 +40,6 @@ const (
rune1Max = 1<<7 - 1
rune2Max = 1<<11 - 1
rune3Max = 1<<16 - 1
- rune4Max = 1<<21 - 1
)
func decodeRuneInternal(p []byte) (r rune, size int, short bool) {
@@ -87,6 +92,9 @@ func decodeRuneInternal(p []byte) (r rune, size int, short bool) {
if r <= rune2Max {
return RuneError, 1, false
}
+ if surrogateMin <= r && r <= surrogateMax {
+ return RuneError, 1, false
+ }
return r, 3, false
}
@@ -102,7 +110,7 @@ func decodeRuneInternal(p []byte) (r rune, size int, short bool) {
// 4-byte, 21-bit sequence?
if c0 < t5 {
r = rune(c0&mask4)<<18 | rune(c1&maskx)<<12 | rune(c2&maskx)<<6 | rune(c3&maskx)
- if r <= rune3Max {
+ if r <= rune3Max || MaxRune < r {
return RuneError, 1, false
}
return r, 4, false
@@ -162,6 +170,9 @@ func decodeRuneInStringInternal(s string) (r rune, size int, short bool) {
if r <= rune2Max {
return RuneError, 1, false
}
+ if surrogateMin <= r && r <= surrogateMax {
+ return RuneError, 1, false
+ }
return r, 3, false
}
@@ -177,7 +188,7 @@ func decodeRuneInStringInternal(s string) (r rune, size int, short bool) {
// 4-byte, 21-bit sequence?
if c0 < t5 {
r = rune(c0&mask4)<<18 | rune(c1&maskx)<<12 | rune(c2&maskx)<<6 | rune(c3&maskx)
- if r <= rune3Max {
+ if r <= rune3Max || MaxRune < r {
return RuneError, 1, false
}
return r, 4, false
@@ -202,6 +213,9 @@ func FullRuneInString(s string) bool {
// DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and its width in bytes.
// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
func DecodeRune(p []byte) (r rune, size int) {
r, size, _ = decodeRuneInternal(p)
return
@@ -209,6 +223,9 @@ func DecodeRune(p []byte) (r rune, size int) {
// DecodeRuneInString is like DecodeRune but its input is a string.
// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
func DecodeRuneInString(s string) (r rune, size int) {
r, size, _ = decodeRuneInStringInternal(s)
return
@@ -216,6 +233,9 @@ func DecodeRuneInString(s string) (r rune, size int) {
// DecodeLastRune unpacks the last UTF-8 encoding in p and returns the rune and its width in bytes.
// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
func DecodeLastRune(p []byte) (r rune, size int) {
end := len(p)
if end == 0 {
@@ -250,6 +270,9 @@ func DecodeLastRune(p []byte) (r rune, size int) {
// DecodeLastRuneInString is like DecodeLastRune but its input is a string.
// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
func DecodeLastRuneInString(s string) (r rune, size int) {
end := len(s)
if end == 0 {
@@ -283,15 +306,20 @@ func DecodeLastRuneInString(s string) (r rune, size int) {
}
// RuneLen returns the number of bytes required to encode the rune.
+// It returns -1 if the rune is not a valid value to encode in UTF-8.
func RuneLen(r rune) int {
switch {
+ case r < 0:
+ return -1
case r <= rune1Max:
return 1
case r <= rune2Max:
return 2
+ case surrogateMin <= r && r <= surrogateMax:
+ return -1
case r <= rune3Max:
return 3
- case r <= rune4Max:
+ case r <= MaxRune:
return 4
}
return -1
@@ -316,6 +344,10 @@ func EncodeRune(p []byte, r rune) int {
r = RuneError
}
+ if surrogateMin <= r && r <= surrogateMax {
+ r = RuneError
+ }
+
if uint32(r) <= rune3Max {
p[0] = t3 | byte(r>>12)
p[1] = tx | byte(r>>6)&maskx
@@ -395,3 +427,17 @@ func ValidString(s string) bool {
}
return true
}
+
+// ValidRune reports whether r can be legally encoded as UTF-8.
+// Code points that are out of range or a surrogate half are illegal.
+func ValidRune(r rune) bool {
+ switch {
+ case r < 0:
+ return false
+ case surrogateMin <= r && r <= surrogateMax:
+ return false
+ case r > MaxRune:
+ return false
+ }
+ return true
+}
diff --git a/libgo/go/unicode/utf8/utf8_test.go b/libgo/go/unicode/utf8/utf8_test.go
index 4f73c8fb81a..c516871c997 100644
--- a/libgo/go/unicode/utf8/utf8_test.go
+++ b/libgo/go/unicode/utf8/utf8_test.go
@@ -56,6 +56,8 @@ var utf8map = []Utf8Map{
{0x07ff, "\xdf\xbf"},
{0x0800, "\xe0\xa0\x80"},
{0x0801, "\xe0\xa0\x81"},
+ {0xd7ff, "\xed\x9f\xbf"}, // last code point before surrogate half.
+ {0xe000, "\xee\x80\x80"}, // first code point after surrogate half.
{0xfffe, "\xef\xbf\xbe"},
{0xffff, "\xef\xbf\xbf"},
{0x10000, "\xf0\x90\x80\x80"},
@@ -65,6 +67,11 @@ var utf8map = []Utf8Map{
{0xFFFD, "\xef\xbf\xbd"},
}
+var surrogateMap = []Utf8Map{
+ {0xd800, "\xed\xa0\x80"}, // surrogate min decodes to (RuneError, 1)
+ {0xdfff, "\xed\xbf\xbf"}, // surrogate max decodes to (RuneError, 1)
+}
+
var testStrings = []string{
"",
"abcd",
@@ -75,8 +82,7 @@ var testStrings = []string{
}
func TestFullRune(t *testing.T) {
- for i := 0; i < len(utf8map); i++ {
- m := utf8map[i]
+ for _, m := range utf8map {
b := []byte(m.str)
if !FullRune(b) {
t.Errorf("FullRune(%q) (%U) = false, want true", b, m.r)
@@ -97,8 +103,7 @@ func TestFullRune(t *testing.T) {
}
func TestEncodeRune(t *testing.T) {
- for i := 0; i < len(utf8map); i++ {
- m := utf8map[i]
+ for _, m := range utf8map {
b := []byte(m.str)
var buf [10]byte
n := EncodeRune(buf[0:], m.r)
@@ -110,8 +115,7 @@ func TestEncodeRune(t *testing.T) {
}
func TestDecodeRune(t *testing.T) {
- for i := 0; i < len(utf8map); i++ {
- m := utf8map[i]
+ for _, m := range utf8map {
b := []byte(m.str)
r, size := DecodeRune(b)
if r != m.r || size != len(b) {
@@ -168,6 +172,21 @@ func TestDecodeRune(t *testing.T) {
}
}
+func TestDecodeSurrogateRune(t *testing.T) {
+ for _, m := range surrogateMap {
+ b := []byte(m.str)
+ r, size := DecodeRune(b)
+ if r != RuneError || size != 1 {
+ t.Errorf("DecodeRune(%q) = %x, %d want %x, %d", b, r, size, RuneError, 1)
+ }
+ s := m.str
+ r, size = DecodeRuneInString(s)
+ if r != RuneError || size != 1 {
+ t.Errorf("DecodeRune(%q) = %x, %d want %x, %d", b, r, size, RuneError, 1)
+ }
+ }
+}
+
// Check that DecodeRune and DecodeLastRune correspond to
// the equivalent range loop.
func TestSequencing(t *testing.T) {
@@ -284,8 +303,7 @@ var runecounttests = []RuneCountTest{
}
func TestRuneCount(t *testing.T) {
- for i := 0; i < len(runecounttests); i++ {
- tt := runecounttests[i]
+ for _, tt := range runecounttests {
if out := RuneCountInString(tt.in); out != tt.out {
t.Errorf("RuneCountInString(%q) = %d, want %d", tt.in, out, tt.out)
}
@@ -295,6 +313,32 @@ func TestRuneCount(t *testing.T) {
}
}
+type RuneLenTest struct {
+ r rune
+ size int
+}
+
+var runelentests = []RuneLenTest{
+ {0, 1},
+ {'e', 1},
+ {'é', 2},
+ {'☺', 3},
+ {RuneError, 3},
+ {MaxRune, 4},
+ {0xD800, -1},
+ {0xDFFF, -1},
+ {MaxRune + 1, -1},
+ {-1, -1},
+}
+
+func TestRuneLen(t *testing.T) {
+ for _, tt := range runelentests {
+ if size := RuneLen(tt.r); size != tt.size {
+ t.Errorf("RuneLen(%#U) = %d, want %d", tt.r, size, tt.size)
+ }
+ }
+}
+
type ValidTest struct {
in string
out bool
@@ -311,15 +355,50 @@ var validTests = []ValidTest{
{string([]byte{66, 250}), false},
{string([]byte{66, 250, 67}), false},
{"a\uFFFDb", true},
+ {string("\xF4\x8F\xBF\xBF"), true}, // U+10FFFF
+ {string("\xF4\x90\x80\x80"), false}, // U+10FFFF+1; out of range
+ {string("\xF7\xBF\xBF\xBF"), false}, // 0x1FFFFF; out of range
+ {string("\xFB\xBF\xBF\xBF\xBF"), false}, // 0x3FFFFFF; out of range
+ {string("\xc0\x80"), false}, // U+0000 encoded in two bytes: incorrect
+ {string("\xed\xa0\x80"), false}, // U+D800 high surrogate (sic)
+ {string("\xed\xbf\xbf"), false}, // U+DFFF low surrogate (sic)
}
func TestValid(t *testing.T) {
- for i, tt := range validTests {
+ for _, tt := range validTests {
if Valid([]byte(tt.in)) != tt.out {
- t.Errorf("%d. Valid(%q) = %v; want %v", i, tt.in, !tt.out, tt.out)
+ t.Errorf("Valid(%q) = %v; want %v", tt.in, !tt.out, tt.out)
}
if ValidString(tt.in) != tt.out {
- t.Errorf("%d. ValidString(%q) = %v; want %v", i, tt.in, !tt.out, tt.out)
+ t.Errorf("ValidString(%q) = %v; want %v", tt.in, !tt.out, tt.out)
+ }
+ }
+}
+
+type ValidRuneTest struct {
+ r rune
+ ok bool
+}
+
+var validrunetests = []ValidRuneTest{
+ {0, true},
+ {'e', true},
+ {'é', true},
+ {'☺', true},
+ {RuneError, true},
+ {MaxRune, true},
+ {0xD7FF, true},
+ {0xD800, false},
+ {0xDFFF, false},
+ {0xE000, true},
+ {MaxRune + 1, false},
+ {-1, false},
+}
+
+func TestValidRune(t *testing.T) {
+ for _, tt := range validrunetests {
+ if ok := ValidRune(tt.r); ok != tt.ok {
+ t.Errorf("ValidRune(%#U) = %t, want %t", tt.r, ok, tt.ok)
}
}
}
diff --git a/libgo/merge.sh b/libgo/merge.sh
index fbc71188032..79ece626d1a 100755
--- a/libgo/merge.sh
+++ b/libgo/merge.sh
@@ -163,7 +163,7 @@ done
done
done
-runtime="chan.c cpuprof.c lock_futex.c lock_sema.c mcache.c mcentral.c mfinal.c mfixalloc.c mgc0.c mheap.c msize.c print.c proc.c runtime.c runtime.h signal_unix.c malloc.h malloc.goc mprof.goc runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
+runtime="chan.c cpuprof.c lock_futex.c lock_sema.c mcache.c mcentral.c mfinal.c mfixalloc.c mgc0.c mheap.c msize.c panic.c print.c proc.c race.h runtime.c runtime.h signal_unix.c malloc.h malloc.goc mprof.goc parfor.c runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
for f in $runtime; do
merge_c $f $f
done
diff --git a/libgo/runtime/chan.c b/libgo/runtime/chan.c
index 1e389a218de..de25e9fd834 100644
--- a/libgo/runtime/chan.c
+++ b/libgo/runtime/chan.c
@@ -4,8 +4,9 @@
#include "runtime.h"
#include "arch.h"
-#include "malloc.h"
#include "go-type.h"
+#include "race.h"
+#include "malloc.h"
#define NOSELGEN 1
@@ -24,6 +25,7 @@ struct SudoG
G* g; // g and selgen constitute
uint32 selgen; // a weak pointer to g
SudoG* link;
+ int64 releasetime;
byte* elem; // data element
};
@@ -35,13 +37,13 @@ struct WaitQ
struct Hchan
{
- uint32 qcount; // total data in the q
- uint32 dataqsiz; // size of the circular q
+ uintgo qcount; // total data in the q
+ uintgo dataqsiz; // size of the circular q
uint16 elemsize;
bool closed;
uint8 elemalign;
- uint32 sendx; // send index
- uint32 recvx; // receive index
+ uintgo sendx; // send index
+ uintgo recvx; // receive index
WaitQ recvq; // list of recv waiters
WaitQ sendq; // list of send waiters
Lock;
@@ -80,17 +82,22 @@ struct Select
static void dequeueg(WaitQ*);
static SudoG* dequeue(WaitQ*);
static void enqueue(WaitQ*, SudoG*);
+static void racesync(Hchan*, SudoG*);
Hchan*
runtime_makechan_c(ChanType *t, int64 hint)
{
Hchan *c;
- int32 n;
+ uintptr n;
const Type *elem;
elem = t->__element_type;
- if(hint < 0 || (int32)hint != hint || (elem->__size > 0 && (uintptr)hint > MaxMem / elem->__size))
+ // compiler checks this but be safe.
+ if(elem->__size >= (1<<16))
+ runtime_throw("makechan: invalid channel element type");
+
+ if(hint < 0 || (intgo)hint != hint || (elem->__size > 0 && (uintptr)hint > MaxMem / elem->__size))
runtime_panicstring("makechan: size out of range");
n = sizeof(*c);
@@ -102,19 +109,19 @@ runtime_makechan_c(ChanType *t, int64 hint)
c->dataqsiz = hint;
if(debug)
- runtime_printf("makechan: chan=%p; elemsize=%D; elemalign=%d; dataqsiz=%d\n",
- c, (int64)elem->__size, elem->__align, c->dataqsiz);
+ runtime_printf("makechan: chan=%p; elemsize=%D; elemalign=%d; dataqsiz=%D\n",
+ c, (int64)elem->__size, elem->__align, (int64)c->dataqsiz);
return c;
}
// For reflect
-// func makechan(typ *ChanType, size uint32) (chan)
-uintptr reflect_makechan(ChanType *, uint32)
+// func makechan(typ *ChanType, size uint64) (chan)
+uintptr reflect_makechan(ChanType *, uint64)
asm ("reflect.makechan");
uintptr
-reflect_makechan(ChanType *t, uint32 size)
+reflect_makechan(ChanType *t, uint64 size)
{
void *ret;
Hchan *c;
@@ -153,11 +160,12 @@ __go_new_channel_big(ChanType *t, uint64 hint)
* the operation; we'll see that it's now closed.
*/
void
-runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
+runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres, void *pc)
{
SudoG *sg;
SudoG mysg;
G* gp;
+ int64 t0;
G* g;
g = runtime_g();
@@ -168,9 +176,7 @@ runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
*pres = false;
return;
}
- g->status = Gwaiting;
- g->waitreason = "chan send (nil chan)";
- runtime_gosched();
+ runtime_park(nil, nil, "chan send (nil chan)");
return; // not reached
}
@@ -181,7 +187,17 @@ runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
runtime_printf("chansend: chan=%p\n", c);
}
+ t0 = 0;
+ mysg.releasetime = 0;
+ if(runtime_blockprofilerate > 0) {
+ t0 = runtime_cputicks();
+ mysg.releasetime = -1;
+ }
+
runtime_lock(c);
+ // TODO(dvyukov): add similar instrumentation to select.
+ if(raceenabled)
+ runtime_racereadpc(c, pc);
if(c->closed)
goto closed;
@@ -190,12 +206,16 @@ runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
sg = dequeue(&c->recvq);
if(sg != nil) {
+ if(raceenabled)
+ racesync(c, sg);
runtime_unlock(c);
gp = sg->g;
gp->param = sg;
if(sg->elem != nil)
runtime_memmove(sg->elem, ep, c->elemsize);
+ if(sg->releasetime)
+ sg->releasetime = runtime_cputicks();
runtime_ready(gp);
if(pres != nil)
@@ -213,11 +233,8 @@ runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
mysg.g = g;
mysg.selgen = NOSELGEN;
g->param = nil;
- g->status = Gwaiting;
- g->waitreason = "chan send";
enqueue(&c->sendq, &mysg);
- runtime_unlock(c);
- runtime_gosched();
+ runtime_park(runtime_unlock, c, "chan send");
if(g->param == nil) {
runtime_lock(c);
@@ -226,6 +243,9 @@ runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
goto closed;
}
+ if(mysg.releasetime > 0)
+ runtime_blockevent(mysg.releasetime - t0, 2);
+
return;
asynch:
@@ -241,15 +261,16 @@ asynch:
mysg.g = g;
mysg.elem = nil;
mysg.selgen = NOSELGEN;
- g->status = Gwaiting;
- g->waitreason = "chan send";
enqueue(&c->sendq, &mysg);
- runtime_unlock(c);
- runtime_gosched();
+ runtime_park(runtime_unlock, c, "chan send");
runtime_lock(c);
goto asynch;
}
+
+ if(raceenabled)
+ runtime_racerelease(chanbuf(c, c->sendx));
+
runtime_memmove(chanbuf(c, c->sendx), ep, c->elemsize);
if(++c->sendx == c->dataqsiz)
c->sendx = 0;
@@ -259,11 +280,15 @@ asynch:
if(sg != nil) {
gp = sg->g;
runtime_unlock(c);
+ if(sg->releasetime)
+ sg->releasetime = runtime_cputicks();
runtime_ready(gp);
} else
runtime_unlock(c);
if(pres != nil)
*pres = true;
+ if(mysg.releasetime > 0)
+ runtime_blockevent(mysg.releasetime - t0, 2);
return;
closed:
@@ -278,6 +303,7 @@ runtime_chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received
SudoG *sg;
SudoG mysg;
G *gp;
+ int64 t0;
G *g;
if(runtime_gcwaiting)
@@ -294,12 +320,17 @@ runtime_chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received
*selected = false;
return;
}
- g->status = Gwaiting;
- g->waitreason = "chan receive (nil chan)";
- runtime_gosched();
+ runtime_park(nil, nil, "chan receive (nil chan)");
return; // not reached
}
+ t0 = 0;
+ mysg.releasetime = 0;
+ if(runtime_blockprofilerate > 0) {
+ t0 = runtime_cputicks();
+ mysg.releasetime = -1;
+ }
+
runtime_lock(c);
if(c->dataqsiz > 0)
goto asynch;
@@ -309,12 +340,16 @@ runtime_chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received
sg = dequeue(&c->sendq);
if(sg != nil) {
+ if(raceenabled)
+ racesync(c, sg);
runtime_unlock(c);
if(ep != nil)
runtime_memmove(ep, sg->elem, c->elemsize);
gp = sg->g;
gp->param = sg;
+ if(sg->releasetime)
+ sg->releasetime = runtime_cputicks();
runtime_ready(gp);
if(selected != nil)
@@ -334,11 +369,8 @@ runtime_chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received
mysg.g = g;
mysg.selgen = NOSELGEN;
g->param = nil;
- g->status = Gwaiting;
- g->waitreason = "chan receive";
enqueue(&c->recvq, &mysg);
- runtime_unlock(c);
- runtime_gosched();
+ runtime_park(runtime_unlock, c, "chan receive");
if(g->param == nil) {
runtime_lock(c);
@@ -349,6 +381,8 @@ runtime_chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received
if(received != nil)
*received = true;
+ if(mysg.releasetime > 0)
+ runtime_blockevent(mysg.releasetime - t0, 2);
return;
asynch:
@@ -366,15 +400,16 @@ asynch:
mysg.g = g;
mysg.elem = nil;
mysg.selgen = NOSELGEN;
- g->status = Gwaiting;
- g->waitreason = "chan receive";
enqueue(&c->recvq, &mysg);
- runtime_unlock(c);
- runtime_gosched();
+ runtime_park(runtime_unlock, c, "chan receive");
runtime_lock(c);
goto asynch;
}
+
+ if(raceenabled)
+ runtime_raceacquire(chanbuf(c, c->recvx));
+
if(ep != nil)
runtime_memmove(ep, chanbuf(c, c->recvx), c->elemsize);
runtime_memclr(chanbuf(c, c->recvx), c->elemsize);
@@ -386,6 +421,8 @@ asynch:
if(sg != nil) {
gp = sg->g;
runtime_unlock(c);
+ if(sg->releasetime)
+ sg->releasetime = runtime_cputicks();
runtime_ready(gp);
} else
runtime_unlock(c);
@@ -394,6 +431,8 @@ asynch:
*selected = true;
if(received != nil)
*received = true;
+ if(mysg.releasetime > 0)
+ runtime_blockevent(mysg.releasetime - t0, 2);
return;
closed:
@@ -403,7 +442,11 @@ closed:
*selected = true;
if(received != nil)
*received = false;
+ if(raceenabled)
+ runtime_raceacquire(c);
runtime_unlock(c);
+ if(mysg.releasetime > 0)
+ runtime_blockevent(mysg.releasetime - t0, 2);
}
// The compiler generates a call to __go_send_small to send a value 8
@@ -424,7 +467,7 @@ __go_send_small(ChanType *t, Hchan* c, uint64 val)
#else
p = u.b + sizeof(uint64) - t->__element_type->__size;
#endif
- runtime_chansend(t, c, p, nil);
+ runtime_chansend(t, c, p, nil, runtime_getcallerpc(&t));
}
// The compiler generates a call to __go_send_big to send a value
@@ -432,7 +475,7 @@ __go_send_small(ChanType *t, Hchan* c, uint64 val)
void
__go_send_big(ChanType *t, Hchan* c, byte* p)
{
- runtime_chansend(t, c, p, nil);
+ runtime_chansend(t, c, p, nil, runtime_getcallerpc(&t));
}
// The compiler generates a call to __go_receive_small to receive a
@@ -500,7 +543,7 @@ runtime_selectnbsend(ChanType *t, Hchan *c, byte *p)
{
bool res;
- runtime_chansend(t, c, p, &res);
+ runtime_chansend(t, c, p, &res, runtime_getcallerpc(&t));
return res;
}
@@ -590,7 +633,7 @@ reflect_chansend(ChanType *t, Hchan *c, uintptr val, _Bool nb)
vp = (byte*)&val;
else
vp = (byte*)val;
- runtime_chansend(t, c, vp, sp);
+ runtime_chansend(t, c, vp, sp, runtime_getcallerpc(&t));
return selected;
}
@@ -643,10 +686,10 @@ static void newselect(int32, Select**);
// newselect(size uint32) (sel *byte);
-void* runtime_newselect(int) __asm__("runtime.newselect");
+void* runtime_newselect(int32) __asm__("runtime.newselect");
void*
-runtime_newselect(int size)
+runtime_newselect(int32 size)
{
Select *sel;
@@ -688,11 +731,11 @@ static void selectsend(Select *sel, Hchan *c, int index, void *elem);
// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
-void runtime_selectsend(Select *, Hchan *, void *, int)
+void runtime_selectsend(Select *, Hchan *, void *, int32)
__asm__("runtime.selectsend");
void
-runtime_selectsend(Select *sel, Hchan *c, void *elem, int index)
+runtime_selectsend(Select *sel, Hchan *c, void *elem, int32 index)
{
// nil cases do not compete
if(c == nil)
@@ -728,11 +771,11 @@ static void selectrecv(Select *sel, Hchan *c, int index, void *elem, bool*);
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
-void runtime_selectrecv(Select *, Hchan *, void *, int)
+void runtime_selectrecv(Select *, Hchan *, void *, int32)
__asm__("runtime.selectrecv");
void
-runtime_selectrecv(Select *sel, Hchan *c, void *elem, int index)
+runtime_selectrecv(Select *sel, Hchan *c, void *elem, int32 index)
{
// nil cases do not compete
if(c == nil)
@@ -743,11 +786,11 @@ runtime_selectrecv(Select *sel, Hchan *c, void *elem, int index)
// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
-void runtime_selectrecv2(Select *, Hchan *, void *, bool *, int)
+void runtime_selectrecv2(Select *, Hchan *, void *, bool *, int32)
__asm__("runtime.selectrecv2");
void
-runtime_selectrecv2(Select *sel, Hchan *c, void *elem, bool *received, int index)
+runtime_selectrecv2(Select *sel, Hchan *c, void *elem, bool *received, int32 index)
{
// nil cases do not compete
if(c == nil)
@@ -784,16 +827,16 @@ static void selectdefault(Select*, int);
// selectdefault(sel *byte) (selected bool);
-void runtime_selectdefault(Select *, int) __asm__("runtime.selectdefault");
+void runtime_selectdefault(Select *, int32) __asm__("runtime.selectdefault");
void
-runtime_selectdefault(Select *sel, int index)
+runtime_selectdefault(Select *sel, int32 index)
{
selectdefault(sel, index);
}
static void
-selectdefault(Select *sel, int index)
+selectdefault(Select *sel, int32 index)
{
int32 i;
Scase *cas;
@@ -848,12 +891,7 @@ selunlock(Select *sel)
void
runtime_block(void)
{
- G *g;
-
- g = runtime_g();
- g->status = Gwaiting; // forever
- g->waitreason = "select (no cases)";
- runtime_gosched();
+ runtime_park(nil, nil, "select (no cases)"); // forever
}
static int selectgo(Select**);
@@ -985,10 +1023,7 @@ loop:
}
g->param = nil;
- g->status = Gwaiting;
- g->waitreason = "select";
- selunlock(sel);
- runtime_gosched();
+ runtime_park((void(*)(Lock*))selunlock, (Lock*)sel, "select");
sellock(sel);
sg = g->param;
@@ -1029,6 +1064,8 @@ loop:
asyncrecv:
// can receive from buffer
+ if(raceenabled)
+ runtime_raceacquire(chanbuf(c, c->recvx));
if(cas->receivedp != nil)
*cas->receivedp = true;
if(cas->sg.elem != nil)
@@ -1049,6 +1086,8 @@ asyncrecv:
asyncsend:
// can send to buffer
+ if(raceenabled)
+ runtime_racerelease(chanbuf(c, c->sendx));
runtime_memmove(chanbuf(c, c->sendx), cas->sg.elem, c->elemsize);
if(++c->sendx == c->dataqsiz)
c->sendx = 0;
@@ -1065,6 +1104,8 @@ asyncsend:
syncrecv:
// can receive from sleeping sender (sg)
+ if(raceenabled)
+ racesync(c, sg);
selunlock(sel);
if(debug)
runtime_printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
@@ -1084,10 +1125,14 @@ rclose:
*cas->receivedp = false;
if(cas->sg.elem != nil)
runtime_memclr(cas->sg.elem, c->elemsize);
+ if(raceenabled)
+ runtime_raceacquire(c);
goto retc;
syncsend:
// can send to sleeping receiver (sg)
+ if(raceenabled)
+ racesync(c, sg);
selunlock(sel);
if(debug)
runtime_printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
@@ -1110,6 +1155,102 @@ sclose:
return 0; // not reached
}
+// This struct must match ../reflect/value.go:/runtimeSelect.
+typedef struct runtimeSelect runtimeSelect;
+struct runtimeSelect
+{
+ uintptr dir;
+ ChanType *typ;
+ Hchan *ch;
+ uintptr val;
+};
+
+// This enum must match ../reflect/value.go:/SelectDir.
+enum SelectDir {
+ SelectSend = 1,
+ SelectRecv,
+ SelectDefault,
+};
+
+struct rselect_ret {
+ intgo chosen;
+ uintptr word;
+ bool recvOK;
+};
+
+// func rselect(cases []runtimeSelect) (chosen int, word uintptr, recvOK bool)
+
+struct rselect_ret reflect_rselect(Slice)
+ asm("reflect.rselect");
+
+struct rselect_ret
+reflect_rselect(Slice cases)
+{
+ struct rselect_ret ret;
+ int32 i;
+ Select *sel;
+ runtimeSelect* rcase, *rc;
+ void *elem;
+ void *recvptr;
+ uintptr maxsize;
+ bool onlyptr;
+
+ ret.chosen = -1;
+ ret.word = 0;
+ ret.recvOK = false;
+
+ maxsize = 0;
+ onlyptr = true;
+ rcase = (runtimeSelect*)cases.__values;
+ for(i=0; i<cases.__count; i++) {
+ rc = &rcase[i];
+ if(rc->dir == SelectRecv && rc->ch != nil) {
+ if(maxsize < rc->typ->__element_type->__size)
+ maxsize = rc->typ->__element_type->__size;
+ if(!__go_is_pointer_type(rc->typ->__element_type))
+ onlyptr = false;
+ }
+ }
+
+ recvptr = nil;
+ if(!onlyptr)
+ recvptr = runtime_mal(maxsize);
+
+ newselect(cases.__count, &sel);
+ for(i=0; i<cases.__count; i++) {
+ rc = &rcase[i];
+ switch(rc->dir) {
+ case SelectDefault:
+ selectdefault(sel, i);
+ break;
+ case SelectSend:
+ if(rc->ch == nil)
+ break;
+ if(!__go_is_pointer_type(rc->typ->__element_type))
+ elem = (void*)rc->val;
+ else
+ elem = (void*)&rc->val;
+ selectsend(sel, rc->ch, i, elem);
+ break;
+ case SelectRecv:
+ if(rc->ch == nil)
+ break;
+ if(!__go_is_pointer_type(rc->typ->__element_type))
+ elem = recvptr;
+ else
+ elem = &ret.word;
+ selectrecv(sel, rc->ch, i, elem, &ret.recvOK);
+ break;
+ }
+ }
+
+ ret.chosen = (intgo)(uintptr)selectgo(&sel);
+ if(rcase[ret.chosen].dir == SelectRecv && !__go_is_pointer_type(rcase[ret.chosen].typ->__element_type))
+ ret.word = (uintptr)recvptr;
+
+ return ret;
+}
+
// closechan(sel *byte);
void
runtime_closechan(Hchan *c)
@@ -1129,6 +1270,11 @@ runtime_closechan(Hchan *c)
runtime_panicstring("close of closed channel");
}
+ if(raceenabled) {
+ runtime_racewritepc(c, runtime_getcallerpc(&c));
+ runtime_racerelease(c);
+ }
+
c->closed = true;
// release all readers
@@ -1172,15 +1318,15 @@ reflect_chanclose(uintptr c)
}
// For reflect
-// func chanlen(c chan) (len int32)
+// func chanlen(c chan) (len int)
-int32 reflect_chanlen(uintptr) __asm__("reflect.chanlen");
+intgo reflect_chanlen(uintptr) __asm__("reflect.chanlen");
-int32
+intgo
reflect_chanlen(uintptr ca)
{
Hchan *c;
- int32 len;
+ intgo len;
c = (Hchan*)ca;
if(c == nil)
@@ -1190,22 +1336,22 @@ reflect_chanlen(uintptr ca)
return len;
}
-int
+intgo
__go_chan_len(Hchan *c)
{
return reflect_chanlen((uintptr)c);
}
// For reflect
-// func chancap(c chan) (cap int32)
+// func chancap(c chan) (cap intgo)
-int32 reflect_chancap(uintptr) __asm__("reflect.chancap");
+intgo reflect_chancap(uintptr) __asm__("reflect.chancap");
-int32
+intgo
reflect_chancap(uintptr ca)
{
Hchan *c;
- int32 cap;
+ intgo cap;
c = (Hchan*)ca;
if(c == nil)
@@ -1215,7 +1361,7 @@ reflect_chancap(uintptr ca)
return cap;
}
-int
+intgo
__go_chan_cap(Hchan *c)
{
return reflect_chancap((uintptr)c);
@@ -1273,3 +1419,12 @@ enqueue(WaitQ *q, SudoG *sgp)
q->last->link = sgp;
q->last = sgp;
}
+
+static void
+racesync(Hchan *c, SudoG *sg)
+{
+ runtime_racerelease(chanbuf(c, 0));
+ runtime_raceacquireg(sg->g, chanbuf(c, 0));
+ runtime_racereleaseg(sg->g, chanbuf(c, 0));
+ runtime_raceacquire(chanbuf(c, 0));
+}
diff --git a/libgo/runtime/cpuprof.c b/libgo/runtime/cpuprof.c
index 9bf5d11e687..23af18b6c2b 100644
--- a/libgo/runtime/cpuprof.c
+++ b/libgo/runtime/cpuprof.c
@@ -130,7 +130,7 @@ extern void runtime_SetCPUProfileRate(int32)
// SetCPUProfileRate sets the CPU profiling rate.
// The user documentation is in debug.go.
void
-runtime_SetCPUProfileRate(int32 hz)
+runtime_SetCPUProfileRate(intgo hz)
{
uintptr *p;
uintptr n;
diff --git a/libgo/runtime/go-rune.c b/libgo/runtime/go-rune.c
index acdecb02467..2caf80061c0 100644
--- a/libgo/runtime/go-rune.c
+++ b/libgo/runtime/go-rune.c
@@ -15,7 +15,7 @@
int
__go_get_rune (const unsigned char *str, size_t len, int *rune)
{
- int c, c1, c2, c3;
+ int c, c1, c2, c3, l;
/* Default to the "replacement character". */
*rune = 0xfffd;
@@ -37,8 +37,10 @@ __go_get_rune (const unsigned char *str, size_t len, int *rune)
if ((c & 0xe0) == 0xc0
&& (c1 & 0xc0) == 0x80)
{
- *rune = (((c & 0x1f) << 6)
- + (c1 & 0x3f));
+ l = (((c & 0x1f) << 6) + (c1 & 0x3f));
+ if (l <= 0x7f)
+ return 1;
+ *rune = l;
return 2;
}
@@ -50,17 +52,21 @@ __go_get_rune (const unsigned char *str, size_t len, int *rune)
&& (c1 & 0xc0) == 0x80
&& (c2 & 0xc0) == 0x80)
{
- *rune = (((c & 0xf) << 12)
- + ((c1 & 0x3f) << 6)
- + (c2 & 0x3f));
+ l = (((c & 0xf) << 12)
+ + ((c1 & 0x3f) << 6)
+ + (c2 & 0x3f));
- if (*rune >= 0xd800 && *rune < 0xe000)
+ if (l <= 0x7ff)
+ return 1;
+
+ if (l >= 0xd800 && l < 0xe000)
{
/* Invalid surrogate half; return replace character. */
- *rune = 0xfffd;
return 1;
}
+ *rune = l;
+
return 3;
}
@@ -73,10 +79,15 @@ __go_get_rune (const unsigned char *str, size_t len, int *rune)
&& (c2 & 0xc0) == 0x80
&& (c3 & 0xc0) == 0x80)
{
- *rune = (((c & 0x7) << 18)
- + ((c1 & 0x3f) << 12)
- + ((c2 & 0x3f) << 6)
- + (c3 & 0x3f));
+ l = (((c & 0x7) << 18)
+ + ((c1 & 0x3f) << 12)
+ + ((c2 & 0x3f) << 6)
+ + (c3 & 0x3f));
+
+ if (l <= 0xffff || l > 0x10ffff)
+ return 1;
+
+ *rune = l;
return 4;
}
diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c
index 9fbe86e0c51..a1215f947e8 100644
--- a/libgo/runtime/go-signal.c
+++ b/libgo/runtime/go-signal.c
@@ -138,6 +138,19 @@ SigTab runtime_sigtab[] = {
#undef P
#undef D
+
+static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
+
+static void
+runtime_badsignal(int32 sig)
+{
+ if (sig == SIGPROF) {
+ return; // Ignore SIGPROFs intended for a non-Go thread.
+ }
+ runtime_write(2, badsignal, sizeof badsignal - 1);
+ runtime_exit(1);
+}
+
/* Handle a signal, for cases where we don't panic. We can split the
stack here. */
@@ -146,6 +159,12 @@ sig_handler (int sig)
{
int i;
+ if (runtime_m () == NULL)
+ {
+ runtime_badsignal (sig);
+ return;
+ }
+
#ifdef SIGPROF
if (sig == SIGPROF)
{
diff --git a/libgo/runtime/go-trampoline.c b/libgo/runtime/go-trampoline.c
index 292eff5c3f2..2d8d9e627e6 100644
--- a/libgo/runtime/go-trampoline.c
+++ b/libgo/runtime/go-trampoline.c
@@ -106,8 +106,8 @@ __go_allocate_trampoline (uintptr_t size, void *closure)
no other references to it. */
void
-runtime_trampoline_scan (void (*scan) (byte *, int64))
+runtime_trampoline_scan (void (*addroot) (byte *, uintptr))
{
if (trampoline_page != NULL)
- scan ((byte *) &trampoline_page, sizeof trampoline_page);
+ addroot ((byte *) &trampoline_page, sizeof trampoline_page);
}
diff --git a/libgo/runtime/lfstack.c b/libgo/runtime/lfstack.c
new file mode 100644
index 00000000000..c805be8932b
--- /dev/null
+++ b/libgo/runtime/lfstack.c
@@ -0,0 +1,66 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Lock-free stack.
+
+#include "runtime.h"
+#include "arch.h"
+
+#if __SIZEOF_POINTER__ == 8
+// Amd64 uses 48-bit virtual addresses, 47-th bit is used as kernel/user flag.
+// So we use 17msb of pointers as ABA counter.
+# define PTR_BITS 47
+#else
+# define PTR_BITS 32
+#endif
+#define PTR_MASK ((1ull<<PTR_BITS)-1)
+
+void
+runtime_lfstackpush(uint64 *head, LFNode *node)
+{
+ uint64 old, new;
+
+ if((uintptr)node != ((uintptr)node&PTR_MASK)) {
+ runtime_printf("p=%p\n", node);
+ runtime_throw("runtime_lfstackpush: invalid pointer");
+ }
+
+ node->pushcnt++;
+ new = (uint64)(uintptr)node|(((uint64)node->pushcnt)<<PTR_BITS);
+ old = runtime_atomicload64(head);
+ for(;;) {
+ node->next = (LFNode*)(uintptr)(old&PTR_MASK);
+ if(runtime_cas64(head, &old, new))
+ break;
+ }
+}
+
+LFNode*
+runtime_lfstackpop(uint64 *head)
+{
+ LFNode *node, *node2;
+ uint64 old, new;
+
+ old = runtime_atomicload64(head);
+ for(;;) {
+ if(old == 0)
+ return nil;
+ node = (LFNode*)(uintptr)(old&PTR_MASK);
+ node2 = runtime_atomicloadp(&node->next);
+ new = 0;
+ if(node2 != nil)
+ new = (uint64)(uintptr)node2|(((uint64)node2->pushcnt)<<PTR_BITS);
+ if(runtime_cas64(head, &old, new))
+ return node;
+ }
+}
+
+LFNode* runtime_lfstackpop2(uint64*)
+ asm("runtime.lfstackpop2");
+
+LFNode*
+runtime_lfstackpop2(uint64 *head)
+{
+ return runtime_lfstackpop(head);
+}
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc
index eb163469076..1b6828fd480 100644
--- a/libgo/runtime/malloc.goc
+++ b/libgo/runtime/malloc.goc
@@ -17,12 +17,13 @@ package runtime
#include "go-string.h"
#include "interface.h"
#include "go-type.h"
+#include "race.h"
MHeap runtime_mheap;
extern MStats mstats; // defined in extern.go
-extern volatile int32 runtime_MemProfileRate
+extern volatile intgo runtime_MemProfileRate
__asm__ ("runtime.MemProfileRate");
// Allocate an object of at least size bytes.
@@ -33,7 +34,8 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
{
M *m;
G *g;
- int32 sizeclass, rate;
+ int32 sizeclass;
+ intgo rate;
MCache *c;
uintptr npages;
MSpan *s;
@@ -53,6 +55,9 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
if(size == 0)
size = 1;
+ if(DebugTypeAtBlockEnd)
+ size += sizeof(uintptr);
+
c = m->mcache;
c->local_nmalloc++;
if(size <= MaxSmallSize) {
@@ -72,7 +77,7 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
npages = size >> PageShift;
if((size & PageMask) != 0)
npages++;
- s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1);
+ s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1, zeroed);
if(s == nil)
runtime_throw("out of memory");
size = npages<<PageShift;
@@ -83,9 +88,20 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
// setup for mark sweep
runtime_markspan(v, 0, 0, true);
}
+
+ if (sizeof(void*) == 4 && c->local_total_alloc >= (1<<30)) {
+ // purge cache stats to prevent overflow
+ runtime_lock(&runtime_mheap);
+ runtime_purgecachedstats(c);
+ runtime_unlock(&runtime_mheap);
+ }
+
if(!(flag & FlagNoGC))
runtime_markallocated(v, size, (flag&FlagNoPointers) != 0);
+ if(DebugTypeAtBlockEnd)
+ *(uintptr*)((uintptr)v+size-sizeof(uintptr)) = 0;
+
m->mallocing = 0;
if(!(flag & FlagNoProfiling) && (rate = runtime_MemProfileRate) > 0) {
@@ -107,6 +123,11 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
if(dogc && mstats.heap_alloc >= mstats.next_gc)
runtime_gc(0);
+
+ if(raceenabled) {
+ runtime_racemalloc(v, size, m->racepc);
+ m->racepc = nil;
+ }
return v;
}
@@ -144,6 +165,9 @@ __go_free(void *v)
}
prof = runtime_blockspecial(v);
+ if(raceenabled)
+ runtime_racefree(v);
+
// Find size class for v.
sizeclass = s->sizeclass;
c = m->mcache;
@@ -178,11 +202,21 @@ __go_free(void *v)
int32
runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
{
+ M *m;
uintptr n, i;
byte *p;
MSpan *s;
- runtime_m()->mcache->local_nlookup++;
+ m = runtime_m();
+
+ m->mcache->local_nlookup++;
+ if (sizeof(void*) == 4 && m->mcache->local_nlookup >= (1<<30)) {
+ // purge cache stats to prevent overflow
+ runtime_lock(&runtime_mheap);
+ runtime_purgecachedstats(m->mcache);
+ runtime_unlock(&runtime_mheap);
+ }
+
s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
if(sp)
*sp = s;
@@ -210,7 +244,7 @@ runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
return 0;
}
- n = runtime_class_to_size[s->sizeclass];
+ n = s->elemsize;
if(base) {
i = ((byte*)v - p)/n;
*base = p + i*n;
@@ -224,7 +258,7 @@ runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
MCache*
runtime_allocmcache(void)
{
- int32 rate;
+ intgo rate;
MCache *c;
runtime_lock(&runtime_mheap);
@@ -232,6 +266,7 @@ runtime_allocmcache(void)
mstats.mcache_inuse = runtime_mheap.cachealloc.inuse;
mstats.mcache_sys = runtime_mheap.cachealloc.sys;
runtime_unlock(&runtime_mheap);
+ runtime_memclr((byte*)c, sizeof(*c));
// Set first allocation sample size.
rate = runtime_MemProfileRate;
@@ -244,12 +279,19 @@ runtime_allocmcache(void)
}
void
-runtime_purgecachedstats(M* m)
+runtime_freemcache(MCache *c)
{
- MCache *c;
+ runtime_MCache_ReleaseAll(c);
+ runtime_lock(&runtime_mheap);
+ runtime_purgecachedstats(c);
+ runtime_FixAlloc_Free(&runtime_mheap.cachealloc, c);
+ runtime_unlock(&runtime_mheap);
+}
+void
+runtime_purgecachedstats(MCache *c)
+{
// Protected by either heap or GC lock.
- c = m->mcache;
mstats.heap_alloc += c->local_cachealloc;
c->local_cachealloc = 0;
mstats.heap_objects += c->local_objects;
@@ -445,6 +487,220 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
return p;
}
+static Lock settype_lock;
+
+void
+runtime_settype_flush(M *m, bool sysalloc)
+{
+ uintptr *buf, *endbuf;
+ uintptr size, ofs, j, t;
+ uintptr ntypes, nbytes2, nbytes3;
+ uintptr *data2;
+ byte *data3;
+ bool sysalloc3;
+ void *v;
+ uintptr typ, p;
+ MSpan *s;
+
+ buf = m->settype_buf;
+ endbuf = buf + m->settype_bufsize;
+
+ runtime_lock(&settype_lock);
+ while(buf < endbuf) {
+ v = (void*)*buf;
+ *buf = 0;
+ buf++;
+ typ = *buf;
+ buf++;
+
+ // (Manually inlined copy of runtime_MHeap_Lookup)
+ p = (uintptr)v>>PageShift;
+ if(sizeof(void*) == 8)
+ p -= (uintptr)runtime_mheap.arena_start >> PageShift;
+ s = runtime_mheap.map[p];
+
+ if(s->sizeclass == 0) {
+ s->types.compression = MTypes_Single;
+ s->types.data = typ;
+ continue;
+ }
+
+ size = s->elemsize;
+ ofs = ((uintptr)v - (s->start<<PageShift)) / size;
+
+ switch(s->types.compression) {
+ case MTypes_Empty:
+ ntypes = (s->npages << PageShift) / size;
+ nbytes3 = 8*sizeof(uintptr) + 1*ntypes;
+
+ if(!sysalloc) {
+ data3 = runtime_mallocgc(nbytes3, FlagNoPointers, 0, 1);
+ } else {
+ data3 = runtime_SysAlloc(nbytes3);
+ if(0) runtime_printf("settype(0->3): SysAlloc(%x) --> %p\n", (uint32)nbytes3, data3);
+ }
+
+ s->types.compression = MTypes_Bytes;
+ s->types.sysalloc = sysalloc;
+ s->types.data = (uintptr)data3;
+
+ ((uintptr*)data3)[1] = typ;
+ data3[8*sizeof(uintptr) + ofs] = 1;
+ break;
+
+ case MTypes_Words:
+ ((uintptr*)s->types.data)[ofs] = typ;
+ break;
+
+ case MTypes_Bytes:
+ data3 = (byte*)s->types.data;
+ for(j=1; j<8; j++) {
+ if(((uintptr*)data3)[j] == typ) {
+ break;
+ }
+ if(((uintptr*)data3)[j] == 0) {
+ ((uintptr*)data3)[j] = typ;
+ break;
+ }
+ }
+ if(j < 8) {
+ data3[8*sizeof(uintptr) + ofs] = j;
+ } else {
+ ntypes = (s->npages << PageShift) / size;
+ nbytes2 = ntypes * sizeof(uintptr);
+
+ if(!sysalloc) {
+ data2 = runtime_mallocgc(nbytes2, FlagNoPointers, 0, 1);
+ } else {
+ data2 = runtime_SysAlloc(nbytes2);
+ if(0) runtime_printf("settype.(3->2): SysAlloc(%x) --> %p\n", (uint32)nbytes2, data2);
+ }
+
+ sysalloc3 = s->types.sysalloc;
+
+ s->types.compression = MTypes_Words;
+ s->types.sysalloc = sysalloc;
+ s->types.data = (uintptr)data2;
+
+ // Move the contents of data3 to data2. Then deallocate data3.
+ for(j=0; j<ntypes; j++) {
+ t = data3[8*sizeof(uintptr) + j];
+ t = ((uintptr*)data3)[t];
+ data2[j] = t;
+ }
+ if(sysalloc3) {
+ nbytes3 = 8*sizeof(uintptr) + 1*ntypes;
+ if(0) runtime_printf("settype.(3->2): SysFree(%p,%x)\n", data3, (uint32)nbytes3);
+ runtime_SysFree(data3, nbytes3);
+ }
+
+ data2[ofs] = typ;
+ }
+ break;
+ }
+ }
+ runtime_unlock(&settype_lock);
+
+ m->settype_bufsize = 0;
+}
+
+// It is forbidden to use this function if it is possible that
+// explicit deallocation via calling runtime_free(v) may happen.
+void
+runtime_settype(void *v, uintptr t)
+{
+ M *m1;
+ uintptr *buf;
+ uintptr i;
+ MSpan *s;
+
+ if(t == 0)
+ runtime_throw("settype: zero type");
+
+ m1 = runtime_m();
+ buf = m1->settype_buf;
+ i = m1->settype_bufsize;
+ buf[i+0] = (uintptr)v;
+ buf[i+1] = t;
+ i += 2;
+ m1->settype_bufsize = i;
+
+ if(i == nelem(m1->settype_buf)) {
+ runtime_settype_flush(m1, false);
+ }
+
+ if(DebugTypeAtBlockEnd) {
+ s = runtime_MHeap_Lookup(&runtime_mheap, v);
+ *(uintptr*)((uintptr)v+s->elemsize-sizeof(uintptr)) = t;
+ }
+}
+
+void
+runtime_settype_sysfree(MSpan *s)
+{
+ uintptr ntypes, nbytes;
+
+ if(!s->types.sysalloc)
+ return;
+
+ nbytes = (uintptr)-1;
+
+ switch (s->types.compression) {
+ case MTypes_Words:
+ ntypes = (s->npages << PageShift) / s->elemsize;
+ nbytes = ntypes * sizeof(uintptr);
+ break;
+ case MTypes_Bytes:
+ ntypes = (s->npages << PageShift) / s->elemsize;
+ nbytes = 8*sizeof(uintptr) + 1*ntypes;
+ break;
+ }
+
+ if(nbytes != (uintptr)-1) {
+ if(0) runtime_printf("settype: SysFree(%p,%x)\n", (void*)s->types.data, (uint32)nbytes);
+ runtime_SysFree((void*)s->types.data, nbytes);
+ }
+}
+
+uintptr
+runtime_gettype(void *v)
+{
+ MSpan *s;
+ uintptr t, ofs;
+ byte *data;
+
+ s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
+ if(s != nil) {
+ t = 0;
+ switch(s->types.compression) {
+ case MTypes_Empty:
+ break;
+ case MTypes_Single:
+ t = s->types.data;
+ break;
+ case MTypes_Words:
+ ofs = (uintptr)v - (s->start<<PageShift);
+ t = ((uintptr*)s->types.data)[ofs/s->elemsize];
+ break;
+ case MTypes_Bytes:
+ ofs = (uintptr)v - (s->start<<PageShift);
+ data = (byte*)s->types.data;
+ t = data[8*sizeof(uintptr) + ofs/s->elemsize];
+ t = ((uintptr*)data)[t];
+ break;
+ default:
+ runtime_throw("runtime_gettype: invalid compression kind");
+ }
+ if(0) {
+ runtime_lock(&settype_lock);
+ runtime_printf("%p -> %d,%X\n", v, (int32)s->types.compression, (int64)t);
+ runtime_unlock(&settype_lock);
+ }
+ return t;
+ }
+ return 0;
+}
+
// Runtime stubs.
void*
@@ -453,9 +709,24 @@ runtime_mal(uintptr n)
return runtime_mallocgc(n, 0, 1, 1);
}
-func new(typ *Type) (ret *uint8) {
- uint32 flag = typ->__code&GO_NO_POINTERS ? FlagNoPointers : 0;
+void *
+runtime_new(Type *typ)
+{
+ void *ret;
+ uint32 flag;
+
+ runtime_m()->racepc = runtime_getcallerpc(&typ);
+ flag = typ->__code&GO_NO_POINTERS ? FlagNoPointers : 0;
ret = runtime_mallocgc(typ->__size, flag, 1, 1);
+
+ if(UseSpanType && !flag) {
+ if(false) {
+ runtime_printf("new %S: %p\n", *typ->__reflection, ret);
+ }
+ runtime_settype(ret, (uintptr)typ | TypeInfo_SingleObject);
+ }
+
+ return ret;
}
func GC() {
diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h
index 96cb609367f..61f0f703a24 100644
--- a/libgo/runtime/malloc.h
+++ b/libgo/runtime/malloc.h
@@ -85,6 +85,7 @@ typedef struct MHeap MHeap;
typedef struct MSpan MSpan;
typedef struct MStats MStats;
typedef struct MLink MLink;
+typedef struct MTypes MTypes;
enum
{
@@ -124,8 +125,8 @@ enum
// Max number of threads to run garbage collection.
// 2, 3, and 4 are all plausible maximums depending
// on the hardware details of the machine. The garbage
- // collector scales well to 4 cpus.
- MaxGcproc = 4,
+ // collector scales well to 8 cpus.
+ MaxGcproc = 8,
};
// Maximum memory allocation size, a hint for callers.
@@ -282,19 +283,19 @@ struct MCacheList
struct MCache
{
MCacheList list[NumSizeClasses];
- uint64 size;
- int64 local_cachealloc; // bytes allocated (or freed) from cache since last lock of heap
- int64 local_objects; // objects allocated (or freed) from cache since last lock of heap
- int64 local_alloc; // bytes allocated (or freed) since last lock of heap
- int64 local_total_alloc; // bytes allocated (even if freed) since last lock of heap
- int64 local_nmalloc; // number of mallocs since last lock of heap
- int64 local_nfree; // number of frees since last lock of heap
- int64 local_nlookup; // number of pointer lookups since last lock of heap
+ uintptr size;
+ intptr local_cachealloc; // bytes allocated (or freed) from cache since last lock of heap
+ intptr local_objects; // objects allocated (or freed) from cache since last lock of heap
+ intptr local_alloc; // bytes allocated (or freed) since last lock of heap
+ uintptr local_total_alloc; // bytes allocated (even if freed) since last lock of heap
+ uintptr local_nmalloc; // number of mallocs since last lock of heap
+ uintptr local_nfree; // number of frees since last lock of heap
+ uintptr local_nlookup; // number of pointer lookups since last lock of heap
int32 next_sample; // trigger heap sample after allocating this many bytes
// Statistics about allocation size classes since last lock of heap
struct {
- int64 nmalloc;
- int64 nfree;
+ uintptr nmalloc;
+ uintptr nfree;
} local_by_size[NumSizeClasses];
};
@@ -303,6 +304,44 @@ void* runtime_MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroe
void runtime_MCache_Free(MCache *c, void *p, int32 sizeclass, uintptr size);
void runtime_MCache_ReleaseAll(MCache *c);
+// MTypes describes the types of blocks allocated within a span.
+// The compression field describes the layout of the data.
+//
+// MTypes_Empty:
+// All blocks are free, or no type information is available for
+// allocated blocks.
+// The data field has no meaning.
+// MTypes_Single:
+// The span contains just one block.
+// The data field holds the type information.
+// The sysalloc field has no meaning.
+// MTypes_Words:
+// The span contains multiple blocks.
+// The data field points to an array of type [NumBlocks]uintptr,
+// and each element of the array holds the type of the corresponding
+// block.
+// MTypes_Bytes:
+// The span contains at most seven different types of blocks.
+// The data field points to the following structure:
+// struct {
+// type [8]uintptr // type[0] is always 0
+// index [NumBlocks]byte
+// }
+// The type of the i-th block is: data.type[data.index[i]]
+enum
+{
+ MTypes_Empty = 0,
+ MTypes_Single = 1,
+ MTypes_Words = 2,
+ MTypes_Bytes = 3,
+};
+struct MTypes
+{
+ byte compression; // one of MTypes_*
+ bool sysalloc; // whether (void*)data is from runtime_SysAlloc
+ uintptr data;
+};
+
// An MSpan is a run of pages.
enum
{
@@ -315,16 +354,17 @@ struct MSpan
{
MSpan *next; // in a span linked list
MSpan *prev; // in a span linked list
- MSpan *allnext; // in the list of all spans
PageID start; // starting page number
uintptr npages; // number of pages in span
MLink *freelist; // list of free objects
uint32 ref; // number of allocated objects in this span
uint32 sizeclass; // size class
+ uintptr elemsize; // computed from sizeclass or from npages
uint32 state; // MSpanInUse etc
int64 unusedsince; // First time spotted by GC in MSpanFree state
uintptr npreleased; // number of pages released to the OS
byte *limit; // end of data in span
+ MTypes types; // types of allocated objects in this span
};
void runtime_MSpan_Init(MSpan *span, PageID start, uintptr npages);
@@ -351,6 +391,7 @@ struct MCentral
void runtime_MCentral_Init(MCentral *c, int32 sizeclass);
int32 runtime_MCentral_AllocList(MCentral *c, int32 n, MLink **first);
void runtime_MCentral_FreeList(MCentral *c, int32 n, MLink *first);
+void runtime_MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end);
// Main malloc heap.
// The heap itself is the "free[]" and "large" arrays,
@@ -360,7 +401,9 @@ struct MHeap
Lock;
MSpan free[MaxMHeapList]; // free lists of given length
MSpan large; // free lists length >= MaxMHeapList
- MSpan *allspans;
+ MSpan **allspans;
+ uint32 nspan;
+ uint32 nspancap;
// span lookup
MSpan *map[1<<MHeapMap_Bits];
@@ -387,7 +430,7 @@ struct MHeap
extern MHeap runtime_mheap;
void runtime_MHeap_Init(MHeap *h, void *(*allocator)(uintptr));
-MSpan* runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct);
+MSpan* runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32 zeroed);
void runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct);
MSpan* runtime_MHeap_Lookup(MHeap *h, void *v);
MSpan* runtime_MHeap_LookupMaybe(MHeap *h, void *v);
@@ -408,7 +451,12 @@ void runtime_markspan(void *v, uintptr size, uintptr n, bool leftover);
void runtime_unmarkspan(void *v, uintptr size);
bool runtime_blockspecial(void*);
void runtime_setblockspecial(void*, bool);
-void runtime_purgecachedstats(M*);
+void runtime_purgecachedstats(MCache*);
+
+void runtime_settype(void*, uintptr);
+void runtime_settype_flush(M*, bool);
+void runtime_settype_sysfree(MSpan*);
+uintptr runtime_gettype(void*);
enum
{
@@ -421,10 +469,21 @@ enum
void runtime_MProf_Malloc(void*, uintptr);
void runtime_MProf_Free(void*, uintptr);
void runtime_MProf_GC(void);
-void runtime_MProf_Mark(void (*scan)(byte *, int64));
-int32 runtime_helpgc(bool*);
+void runtime_MProf_Mark(void (*addroot)(byte *, uintptr));
+int32 runtime_gcprocs(void);
+void runtime_helpgc(int32 nproc);
void runtime_gchelper(void);
struct __go_func_type;
bool runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft);
-void runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, int64));
+void runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, uintptr));
+
+enum
+{
+ TypeInfo_SingleObject = 0,
+ TypeInfo_Array = 1,
+ TypeInfo_Map = 2,
+
+ // Enables type information at the end of blocks allocated from heap
+ DebugTypeAtBlockEnd = 0,
+};
diff --git a/libgo/runtime/mcache.c b/libgo/runtime/mcache.c
index 6c60aebbe67..570c06a731b 100644
--- a/libgo/runtime/mcache.c
+++ b/libgo/runtime/mcache.c
@@ -43,11 +43,6 @@ runtime_MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed)
// block is zeroed iff second word is zero ...
if(size > sizeof(uintptr) && ((uintptr*)v)[1] != 0)
runtime_memclr((byte*)v, size);
- else {
- // ... except for the link pointer
- // that we used above; zero that.
- v->next = nil;
- }
}
c->local_cachealloc += size;
c->local_objects++;
diff --git a/libgo/runtime/mcentral.c b/libgo/runtime/mcentral.c
index 00c6f23a33d..670a647b961 100644
--- a/libgo/runtime/mcentral.c
+++ b/libgo/runtime/mcentral.c
@@ -88,9 +88,6 @@ MCentral_Alloc(MCentral *c)
}
// Free n objects back into the central free list.
-// Return the number of objects allocated.
-// The objects are linked together by their first words.
-// On return, *pstart points at the first object and *pend at the last.
void
runtime_MCentral_FreeList(MCentral *c, int32 n, MLink *start)
{
@@ -148,6 +145,42 @@ MCentral_Free(MCentral *c, void *v)
}
}
+// Free n objects from a span s back into the central free list c.
+// Called from GC.
+void
+runtime_MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end)
+{
+ int32 size;
+
+ runtime_lock(c);
+
+ // Move to nonempty if necessary.
+ if(s->freelist == nil) {
+ runtime_MSpanList_Remove(s);
+ runtime_MSpanList_Insert(&c->nonempty, s);
+ }
+
+ // Add the objects back to s's free list.
+ end->next = s->freelist;
+ s->freelist = start;
+ s->ref -= n;
+ c->nfree += n;
+
+ // If s is completely freed, return it to the heap.
+ if(s->ref == 0) {
+ size = runtime_class_to_size[c->sizeclass];
+ runtime_MSpanList_Remove(s);
+ *(uintptr*)(s->start<<PageShift) = 1; // needs zeroing
+ s->freelist = nil;
+ c->nfree -= (s->npages << PageShift) / size;
+ runtime_unlock(c);
+ runtime_unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift);
+ runtime_MHeap_Free(&runtime_mheap, s, 0);
+ } else {
+ runtime_unlock(c);
+ }
+}
+
void
runtime_MGetSizeClassInfo(int32 sizeclass, uintptr *sizep, int32 *npagesp, int32 *nobj)
{
@@ -174,7 +207,7 @@ MCentral_Grow(MCentral *c)
runtime_unlock(c);
runtime_MGetSizeClassInfo(c->sizeclass, &size, &npages, &n);
- s = runtime_MHeap_Alloc(&runtime_mheap, npages, c->sizeclass, 0);
+ s = runtime_MHeap_Alloc(&runtime_mheap, npages, c->sizeclass, 0, 1);
if(s == nil) {
// TODO(rsc): Log out of memory
runtime_lock(c);
diff --git a/libgo/runtime/mfinal.c b/libgo/runtime/mfinal.c
index e52ae3bce53..f2f640ad2fb 100644
--- a/libgo/runtime/mfinal.c
+++ b/libgo/runtime/mfinal.c
@@ -193,7 +193,7 @@ runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_fu
}
void
-runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, int64))
+runtime_walkfintab(void (*fn)(void*), void (*addroot)(byte *, uintptr))
{
void **key;
void **ekey;
@@ -206,8 +206,8 @@ runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, int64))
for(; key < ekey; key++)
if(*key != nil && *key != ((void*)-1))
fn(*key);
- scan((byte*)&fintab[i].fkey, sizeof(void*));
- scan((byte*)&fintab[i].val, sizeof(void*));
+ addroot((byte*)&fintab[i].fkey, sizeof(void*));
+ addroot((byte*)&fintab[i].val, sizeof(void*));
runtime_unlock(&fintab[i]);
}
}
diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c
index d35cc0ffbdd..72feb1f4481 100644
--- a/libgo/runtime/mgc0.c
+++ b/libgo/runtime/mgc0.c
@@ -9,6 +9,7 @@
#include "runtime.h"
#include "arch.h"
#include "malloc.h"
+#include "race.h"
#ifdef USING_SPLIT_STACK
@@ -22,8 +23,8 @@ extern void * __splitstack_find_context (void *context[10], size_t *, void **,
enum {
Debug = 0,
- PtrSize = sizeof(void*),
DebugMark = 0, // run second pass to check mark
+ DataBlock = 8*1024,
// Four bits per word (see #defines below).
wordsPerBitmapWord = sizeof(void*)*8/4,
@@ -78,17 +79,14 @@ enum {
//
uint32 runtime_worldsema = 1;
-// TODO: Make these per-M.
-static uint64 nhandoff;
-
static int32 gctrace;
typedef struct Workbuf Workbuf;
struct Workbuf
{
- Workbuf *next;
+ LFNode node; // must be first
uintptr nobj;
- byte *obj[512-2];
+ byte *obj[512-(sizeof(LFNode)+sizeof(uintptr))/sizeof(byte*)];
};
typedef struct Finalizer Finalizer;
@@ -122,22 +120,32 @@ static Workbuf* getfull(Workbuf*);
static void putempty(Workbuf*);
static Workbuf* handoff(Workbuf*);
+typedef struct GcRoot GcRoot;
+struct GcRoot
+{
+ byte *p;
+ uintptr n;
+};
+
static struct {
- Lock fmu;
- Workbuf *full;
- Lock emu;
- Workbuf *empty;
+ uint64 full; // lock-free list of full blocks
+ uint64 empty; // lock-free list of empty blocks
+ byte pad0[CacheLineSize]; // prevents false-sharing between full/empty and nproc/nwait
uint32 nproc;
volatile uint32 nwait;
volatile uint32 ndone;
+ volatile uint32 debugmarkdone;
Note alldone;
- Lock markgate;
- Lock sweepgate;
- MSpan *spans;
+ ParFor *markfor;
+ ParFor *sweepfor;
Lock;
byte *chunk;
uintptr nchunk;
+
+ GcRoot *roots;
+ uint32 nroot;
+ uint32 rootcap;
} work;
// scanblock scans a block of n bytes starting at pointer b for references
@@ -147,7 +155,7 @@ static struct {
// body. Keeping an explicit work list is easier on the stack allocator and
// more efficient.
static void
-scanblock(byte *b, int64 n)
+scanblock(byte *b, uintptr n)
{
byte *obj, *arena_start, *arena_used, *p;
void **vp;
@@ -158,8 +166,8 @@ scanblock(byte *b, int64 n)
Workbuf *wbuf;
bool keepworking;
- if((int64)(uintptr)n != n || n < 0) {
- runtime_printf("scanblock %p %D\n", b, n);
+ if((intptr)n < 0) {
+ runtime_printf("scanblock %p %D\n", b, (int64)n);
runtime_throw("scanblock");
}
@@ -173,7 +181,7 @@ scanblock(byte *b, int64 n)
nobj = 0; // number of queued objects
// Scanblock helpers pass b==nil.
- // The main proc needs to return to make more
+ // Procs needs to return to make more
// calls to scanblock. But if work.nproc==1 then
// might as well process blocks as soon as we
// have them.
@@ -190,7 +198,7 @@ scanblock(byte *b, int64 n)
// Each iteration scans the block b of length n, queueing pointers in
// the work buffer.
if(Debug > 1)
- runtime_printf("scanblock %p %D\n", b, n);
+ runtime_printf("scanblock %p %D\n", b, (int64)n);
vp = (void**)b;
n >>= (2+PtrSize/8); /* n /= PtrSize (4 or 8) */
@@ -257,6 +265,14 @@ scanblock(byte *b, int64 n)
bits = xbits >> shift;
found:
+ // If another proc wants a pointer, give it some.
+ if(work.nwait > 0 && nobj > 4 && work.full == 0) {
+ wbuf->nobj = nobj;
+ wbuf = handoff(wbuf);
+ nobj = wbuf->nobj;
+ wp = (void**)(wbuf->obj + nobj);
+ }
+
// Now we have bits, bitp, and shift correct for
// obj pointing at the base of the object.
// Only care about allocated and not marked.
@@ -278,13 +294,7 @@ scanblock(byte *b, int64 n)
if((bits & bitNoPointers) != 0)
continue;
- // If another proc wants a pointer, give it some.
- if(nobj > 4 && work.nwait > 0 && work.full == nil) {
- wbuf->nobj = nobj;
- wbuf = handoff(wbuf);
- nobj = wbuf->nobj;
- wp = (void**)(wbuf->obj + nobj);
- }
+ PREFETCH(obj);
// If buffer is full, get a new one.
if(wbuf == nil || nobj >= nelem(wbuf->obj)) {
@@ -305,7 +315,8 @@ scanblock(byte *b, int64 n)
// Fetch b from the work buffer.
if(nobj == 0) {
if(!keepworking) {
- putempty(wbuf);
+ if(wbuf)
+ putempty(wbuf);
return;
}
// Emptied our buffer: refill.
@@ -335,7 +346,7 @@ scanblock(byte *b, int64 n)
// it is simpler, slower, single-threaded, recursive,
// and uses bitSpecial as the mark bit.
static void
-debug_scanblock(byte *b, int64 n)
+debug_scanblock(byte *b, uintptr n)
{
byte *obj, *p;
void **vp;
@@ -345,8 +356,8 @@ debug_scanblock(byte *b, int64 n)
if(!DebugMark)
runtime_throw("debug_scanblock without DebugMark");
- if((int64)(uintptr)n != n || n < 0) {
- runtime_printf("debug_scanblock %p %D\n", b, n);
+ if((intptr)n < 0) {
+ runtime_printf("debug_scanblock %p %D\n", b, (int64)n);
runtime_throw("debug_scanblock");
}
@@ -374,7 +385,6 @@ debug_scanblock(byte *b, int64 n)
if(s == nil)
continue;
-
p = (byte*)((uintptr)s->start<<PageShift);
if(s->sizeclass == 0) {
obj = p;
@@ -411,53 +421,33 @@ debug_scanblock(byte *b, int64 n)
}
}
+static void
+markroot(ParFor *desc, uint32 i)
+{
+ USED(&desc);
+ scanblock(work.roots[i].p, work.roots[i].n);
+}
+
// Get an empty work buffer off the work.empty list,
// allocating new buffers as needed.
static Workbuf*
getempty(Workbuf *b)
{
- if(work.nproc == 1) {
- // Put b on full list.
- if(b != nil) {
- b->next = work.full;
- work.full = b;
- }
- // Grab from empty list if possible.
- b = work.empty;
- if(b != nil) {
- work.empty = b->next;
- goto haveb;
- }
- } else {
- // Put b on full list.
- if(b != nil) {
- runtime_lock(&work.fmu);
- b->next = work.full;
- work.full = b;
- runtime_unlock(&work.fmu);
+ if(b != nil)
+ runtime_lfstackpush(&work.full, &b->node);
+ b = (Workbuf*)runtime_lfstackpop(&work.empty);
+ if(b == nil) {
+ // Need to allocate.
+ runtime_lock(&work);
+ if(work.nchunk < sizeof *b) {
+ work.nchunk = 1<<20;
+ work.chunk = runtime_SysAlloc(work.nchunk);
}
- // Grab from empty list if possible.
- runtime_lock(&work.emu);
- b = work.empty;
- if(b != nil)
- work.empty = b->next;
- runtime_unlock(&work.emu);
- if(b != nil)
- goto haveb;
- }
-
- // Need to allocate.
- runtime_lock(&work);
- if(work.nchunk < sizeof *b) {
- work.nchunk = 1<<20;
- work.chunk = runtime_SysAlloc(work.nchunk);
+ b = (Workbuf*)work.chunk;
+ work.chunk += sizeof *b;
+ work.nchunk -= sizeof *b;
+ runtime_unlock(&work);
}
- b = (Workbuf*)work.chunk;
- work.chunk += sizeof *b;
- work.nchunk -= sizeof *b;
- runtime_unlock(&work);
-
-haveb:
b->nobj = 0;
return b;
}
@@ -465,112 +455,95 @@ haveb:
static void
putempty(Workbuf *b)
{
- if(b == nil)
- return;
-
- if(work.nproc == 1) {
- b->next = work.empty;
- work.empty = b;
- return;
- }
-
- runtime_lock(&work.emu);
- b->next = work.empty;
- work.empty = b;
- runtime_unlock(&work.emu);
+ runtime_lfstackpush(&work.empty, &b->node);
}
// Get a full work buffer off the work.full list, or return nil.
static Workbuf*
getfull(Workbuf *b)
{
+ M *m;
int32 i;
- Workbuf *b1;
- if(work.nproc == 1) {
- // Put b on empty list.
- if(b != nil) {
- b->next = work.empty;
- work.empty = b;
- }
- // Grab from full list if possible.
- // Since work.nproc==1, no one else is
- // going to give us work.
- b = work.full;
- if(b != nil)
- work.full = b->next;
+ if(b != nil)
+ runtime_lfstackpush(&work.empty, &b->node);
+ b = (Workbuf*)runtime_lfstackpop(&work.full);
+ if(b != nil || work.nproc == 1)
return b;
- }
-
- putempty(b);
-
- // Grab buffer from full list if possible.
- for(;;) {
- b1 = work.full;
- if(b1 == nil)
- break;
- runtime_lock(&work.fmu);
- if(work.full != nil) {
- b1 = work.full;
- work.full = b1->next;
- runtime_unlock(&work.fmu);
- return b1;
- }
- runtime_unlock(&work.fmu);
- }
+ m = runtime_m();
runtime_xadd(&work.nwait, +1);
for(i=0;; i++) {
- b1 = work.full;
- if(b1 != nil) {
- runtime_lock(&work.fmu);
- if(work.full != nil) {
- runtime_xadd(&work.nwait, -1);
- b1 = work.full;
- work.full = b1->next;
- runtime_unlock(&work.fmu);
- return b1;
- }
- runtime_unlock(&work.fmu);
- continue;
+ if(work.full != 0) {
+ runtime_xadd(&work.nwait, -1);
+ b = (Workbuf*)runtime_lfstackpop(&work.full);
+ if(b != nil)
+ return b;
+ runtime_xadd(&work.nwait, +1);
}
if(work.nwait == work.nproc)
return nil;
- if(i < 10)
+ if(i < 10) {
+ m->gcstats.nprocyield++;
runtime_procyield(20);
- else if(i < 20)
+ } else if(i < 20) {
+ m->gcstats.nosyield++;
runtime_osyield();
- else
+ } else {
+ m->gcstats.nsleep++;
runtime_usleep(100);
+ }
}
}
static Workbuf*
handoff(Workbuf *b)
{
+ M *m;
int32 n;
Workbuf *b1;
+ m = runtime_m();
+
// Make new buffer with half of b's pointers.
b1 = getempty(nil);
n = b->nobj/2;
b->nobj -= n;
b1->nobj = n;
runtime_memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]);
- nhandoff += n;
+ m->gcstats.nhandoff++;
+ m->gcstats.nhandoffcnt += n;
// Put b on full list - let first half of b get stolen.
- runtime_lock(&work.fmu);
- b->next = work.full;
- work.full = b;
- runtime_unlock(&work.fmu);
-
+ runtime_lfstackpush(&work.full, &b->node);
return b1;
}
-// Scanstack calls scanblock on each of gp's stack segments.
static void
-scanstack(void (*scanblock)(byte*, int64), G *gp)
+addroot(byte *p, uintptr n)
+{
+ uint32 cap;
+ GcRoot *new;
+
+ if(work.nroot >= work.rootcap) {
+ cap = PageSize/sizeof(GcRoot);
+ if(cap < 2*work.rootcap)
+ cap = 2*work.rootcap;
+ new = (GcRoot*)runtime_SysAlloc(cap*sizeof(GcRoot));
+ if(work.roots != nil) {
+ runtime_memmove(new, work.roots, work.rootcap*sizeof(GcRoot));
+ runtime_SysFree(work.roots, work.rootcap*sizeof(GcRoot));
+ }
+ work.roots = new;
+ work.rootcap = cap;
+ }
+ work.roots[work.nroot].p = p;
+ work.roots[work.nroot].n = n;
+ work.nroot++;
+}
+
+static void
+addstackroots(G *gp)
{
#ifdef USING_SPLIT_STACK
M *mp;
@@ -609,11 +582,11 @@ scanstack(void (*scanblock)(byte*, int64), G *gp)
}
}
if(sp != nil) {
- scanblock(sp, spsize);
+ addroot(sp, spsize);
while((sp = __splitstack_find(next_segment, next_sp,
&spsize, &next_segment,
&next_sp, &initial_sp)) != nil)
- scanblock(sp, spsize);
+ addroot(sp, spsize);
}
#else
M *mp;
@@ -635,16 +608,14 @@ scanstack(void (*scanblock)(byte*, int64), G *gp)
}
top = (byte*)gp->gcinitial_sp + gp->gcstack_size;
if(top > bottom)
- scanblock(bottom, top - bottom);
+ addroot(bottom, top - bottom);
else
- scanblock(top, bottom - top);
+ addroot(top, bottom - top);
#endif
}
-// Markfin calls scanblock on the blocks that have finalizers:
-// the things pointed at cannot be freed until the finalizers have run.
static void
-markfin(void *v)
+addfinroots(void *v)
{
uintptr size;
@@ -653,7 +624,7 @@ markfin(void *v)
runtime_throw("mark - finalizer inconsistency");
// do not mark the finalizer block itself. just mark the things it points at.
- scanblock(v, size);
+ addroot(v, size);
}
static struct root_list* roots;
@@ -668,22 +639,15 @@ __go_register_gc_roots (struct root_list* r)
}
static void
-debug_markfin(void *v)
-{
- uintptr size;
-
- if(!runtime_mlookup(v, (byte**)&v, &size, nil))
- runtime_throw("debug_mark - finalizer inconsistency");
- debug_scanblock(v, size);
-}
-
-// Mark
-static void
-mark(void (*scan)(byte*, int64))
+addroots(void)
{
struct root_list *pl;
G *gp;
FinBlock *fb;
+ MSpan *s, **allspans;
+ uint32 spanidx;
+
+ work.nroot = 0;
// mark data+bss.
for(pl = roots; pl != nil; pl = pl->next) {
@@ -692,20 +656,36 @@ mark(void (*scan)(byte*, int64))
void *decl = pr->decl;
if(decl == nil)
break;
- scanblock(decl, pr->size);
+ addroot(decl, pr->size);
pr++;
}
}
- scan((byte*)&runtime_m0, sizeof runtime_m0);
- scan((byte*)&runtime_g0, sizeof runtime_g0);
- scan((byte*)&runtime_allg, sizeof runtime_allg);
- scan((byte*)&runtime_allm, sizeof runtime_allm);
- runtime_MProf_Mark(scan);
- runtime_time_scan(scan);
- runtime_trampoline_scan(scan);
+ addroot((byte*)&runtime_m0, sizeof runtime_m0);
+ addroot((byte*)&runtime_g0, sizeof runtime_g0);
+ addroot((byte*)&runtime_allg, sizeof runtime_allg);
+ addroot((byte*)&runtime_allm, sizeof runtime_allm);
+ runtime_MProf_Mark(addroot);
+ runtime_time_scan(addroot);
+ runtime_trampoline_scan(addroot);
+
+ // MSpan.types
+ allspans = runtime_mheap.allspans;
+ for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) {
+ s = allspans[spanidx];
+ if(s->state == MSpanInUse) {
+ switch(s->types.compression) {
+ case MTypes_Empty:
+ case MTypes_Single:
+ break;
+ case MTypes_Words:
+ case MTypes_Bytes:
+ addroot((byte*)&s->types.data, sizeof(void*));
+ break;
+ }
+ }
+ }
- // mark stacks
for(gp=runtime_allg; gp!=nil; gp=gp->alllink) {
switch(gp->status){
default:
@@ -716,27 +696,22 @@ mark(void (*scan)(byte*, int64))
case Grunning:
if(gp != runtime_g())
runtime_throw("mark - world not stopped");
- scanstack(scan, gp);
+ addstackroots(gp);
break;
case Grunnable:
case Gsyscall:
case Gwaiting:
- scanstack(scan, gp);
+ addstackroots(gp);
break;
}
}
- // mark things pointed at by objects with finalizers
- if(scan == debug_scanblock)
- runtime_walkfintab(debug_markfin, scan);
- else
- runtime_walkfintab(markfin, scan);
+ runtime_walkfintab(addfinroots, addroot);
for(fb=allfin; fb; fb=fb->alllink)
- scanblock((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]));
+ addroot((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]));
- // in multiproc mode, join in the queued work.
- scan(nil, 0);
+ addroot((byte*)&work, sizeof work);
}
static bool
@@ -771,122 +746,149 @@ handlespecial(byte *p, uintptr size)
f->fn = fn;
f->ft = ft;
f->arg = p;
- runtime_unlock(&finlock);
+ runtime_unlock(&finlock);
return true;
}
// Sweep frees or collects finalizers for blocks not marked in the mark phase.
// It clears the mark bits in preparation for the next GC round.
static void
-sweep(void)
+sweepspan(ParFor *desc, uint32 idx)
{
M *m;
- MSpan *s;
int32 cl, n, npages;
uintptr size;
byte *p;
MCache *c;
byte *arena_start;
- int64 now;
+ MLink head, *end;
+ int32 nfree;
+ byte *type_data;
+ byte compression;
+ uintptr type_data_inc;
+ MSpan *s;
m = runtime_m();
+
+ USED(&desc);
+ s = runtime_mheap.allspans[idx];
+ // Stamp newly unused spans. The scavenger will use that
+ // info to potentially give back some pages to the OS.
+ if(s->state == MSpanFree && s->unusedsince == 0)
+ s->unusedsince = runtime_nanotime();
+ if(s->state != MSpanInUse)
+ return;
arena_start = runtime_mheap.arena_start;
- now = runtime_nanotime();
+ p = (byte*)(s->start << PageShift);
+ cl = s->sizeclass;
+ size = s->elemsize;
+ if(cl == 0) {
+ n = 1;
+ } else {
+ // Chunk full of small blocks.
+ npages = runtime_class_to_allocnpages[cl];
+ n = (npages << PageShift) / size;
+ }
+ nfree = 0;
+ end = &head;
+ c = m->mcache;
+
+ type_data = (byte*)s->types.data;
+ type_data_inc = sizeof(uintptr);
+ compression = s->types.compression;
+ switch(compression) {
+ case MTypes_Bytes:
+ type_data += 8*sizeof(uintptr);
+ type_data_inc = 1;
+ break;
+ }
- for(;;) {
- s = work.spans;
- if(s == nil)
- break;
- if(!runtime_casp(&work.spans, s, s->allnext))
- continue;
+ // Sweep through n objects of given size starting at p.
+ // This thread owns the span now, so it can manipulate
+ // the block bitmap without atomic operations.
+ for(; n > 0; n--, p += size, type_data+=type_data_inc) {
+ uintptr off, *bitp, shift, bits;
- // Stamp newly unused spans. The scavenger will use that
- // info to potentially give back some pages to the OS.
- if(s->state == MSpanFree && s->unusedsince == 0)
- s->unusedsince = now;
+ off = (uintptr*)p - (uintptr*)arena_start;
+ bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
+ shift = off % wordsPerBitmapWord;
+ bits = *bitp>>shift;
- if(s->state != MSpanInUse)
+ if((bits & bitAllocated) == 0)
continue;
- p = (byte*)(s->start << PageShift);
- cl = s->sizeclass;
- if(cl == 0) {
- size = s->npages<<PageShift;
- n = 1;
- } else {
- // Chunk full of small blocks.
- size = runtime_class_to_size[cl];
- npages = runtime_class_to_allocnpages[cl];
- n = (npages << PageShift) / size;
+ if((bits & bitMarked) != 0) {
+ if(DebugMark) {
+ if(!(bits & bitSpecial))
+ runtime_printf("found spurious mark on %p\n", p);
+ *bitp &= ~(bitSpecial<<shift);
+ }
+ *bitp &= ~(bitMarked<<shift);
+ continue;
}
- // Sweep through n objects of given size starting at p.
- // This thread owns the span now, so it can manipulate
- // the block bitmap without atomic operations.
- for(; n > 0; n--, p += size) {
- uintptr off, *bitp, shift, bits;
-
- off = (uintptr*)p - (uintptr*)arena_start;
- bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- bits = *bitp>>shift;
-
- if((bits & bitAllocated) == 0)
+ // Special means it has a finalizer or is being profiled.
+ // In DebugMark mode, the bit has been coopted so
+ // we have to assume all blocks are special.
+ if(DebugMark || (bits & bitSpecial) != 0) {
+ if(handlespecial(p, size))
continue;
+ }
- if((bits & bitMarked) != 0) {
- if(DebugMark) {
- if(!(bits & bitSpecial))
- runtime_printf("found spurious mark on %p\n", p);
- *bitp &= ~(bitSpecial<<shift);
- }
- *bitp &= ~(bitMarked<<shift);
- continue;
- }
-
- // Special means it has a finalizer or is being profiled.
- // In DebugMark mode, the bit has been coopted so
- // we have to assume all blocks are special.
- if(DebugMark || (bits & bitSpecial) != 0) {
- if(handlespecial(p, size))
- continue;
- }
-
- // Mark freed; restore block boundary bit.
- *bitp = (*bitp & ~(bitMask<<shift)) | (bitBlockBoundary<<shift);
+ // Mark freed; restore block boundary bit.
+ *bitp = (*bitp & ~(bitMask<<shift)) | (bitBlockBoundary<<shift);
- c = m->mcache;
- if(s->sizeclass == 0) {
- // Free large span.
- runtime_unmarkspan(p, 1<<PageShift);
- *(uintptr*)p = 1; // needs zeroing
- runtime_MHeap_Free(&runtime_mheap, s, 1);
- } else {
- // Free small object.
- if(size > sizeof(uintptr))
- ((uintptr*)p)[1] = 1; // mark as "needs to be zeroed"
- c->local_by_size[s->sizeclass].nfree++;
- runtime_MCache_Free(c, p, s->sizeclass, size);
- }
+ if(cl == 0) {
+ // Free large span.
+ runtime_unmarkspan(p, 1<<PageShift);
+ *(uintptr*)p = 1; // needs zeroing
+ runtime_MHeap_Free(&runtime_mheap, s, 1);
c->local_alloc -= size;
c->local_nfree++;
+ } else {
+ // Free small object.
+ switch(compression) {
+ case MTypes_Words:
+ *(uintptr*)type_data = 0;
+ break;
+ case MTypes_Bytes:
+ *(byte*)type_data = 0;
+ break;
+ }
+ if(size > sizeof(uintptr))
+ ((uintptr*)p)[1] = 1; // mark as "needs to be zeroed"
+
+ end->next = (MLink*)p;
+ end = (MLink*)p;
+ nfree++;
}
}
+
+ if(nfree) {
+ c->local_by_size[cl].nfree += nfree;
+ c->local_alloc -= size * nfree;
+ c->local_nfree += nfree;
+ c->local_cachealloc -= nfree * size;
+ c->local_objects -= nfree;
+ runtime_MCentral_FreeSpan(&runtime_mheap.central[cl], s, nfree, head.next, end);
+ }
}
void
runtime_gchelper(void)
{
- // Wait until main proc is ready for mark help.
- runtime_lock(&work.markgate);
- runtime_unlock(&work.markgate);
+ // parallel mark for over gc roots
+ runtime_parfordo(work.markfor);
+ // help other threads scan secondary blocks
scanblock(nil, 0);
- // Wait until main proc is ready for sweep help.
- runtime_lock(&work.sweepgate);
- runtime_unlock(&work.sweepgate);
- sweep();
+ if(DebugMark) {
+ // wait while the main thread executes mark(debug_scanblock)
+ while(runtime_atomicload(&work.debugmarkdone) == 0)
+ runtime_usleep(10);
+ }
+ runtime_parfordo(work.sweepfor);
if(runtime_xadd(&work.ndone, +1) == work.nproc-1)
runtime_notewakeup(&work.alldone);
}
@@ -912,21 +914,31 @@ stealcache(void)
}
static void
-cachestats(void)
+cachestats(GCStats *stats)
{
M *m;
MCache *c;
uint32 i;
uint64 stacks_inuse;
uint64 stacks_sys;
+ uint64 *src, *dst;
+ if(stats)
+ runtime_memclr((byte*)stats, sizeof(*stats));
stacks_inuse = 0;
stacks_sys = runtime_stacks_sys;
for(m=runtime_allm; m; m=m->alllink) {
- runtime_purgecachedstats(m);
+ c = m->mcache;
+ runtime_purgecachedstats(c);
// stacks_inuse += m->stackalloc->inuse;
// stacks_sys += m->stackalloc->sys;
- c = m->mcache;
+ if(stats) {
+ src = (uint64*)&m->gcstats;
+ dst = (uint64*)stats;
+ for(i=0; i<sizeof(*stats)/sizeof(uint64); i++)
+ dst[i] += src[i];
+ runtime_memclr((byte*)&m->gcstats, sizeof(m->gcstats));
+ }
for(i=0; i<nelem(c->local_by_size); i++) {
mstats.by_size[i].nmalloc += c->local_by_size[i].nmalloc;
c->local_by_size[i].nmalloc = 0;
@@ -945,7 +957,15 @@ runtime_gc(int32 force)
int64 t0, t1, t2, t3;
uint64 heap0, heap1, obj0, obj1;
const byte *p;
- bool extra;
+ GCStats stats;
+ M *m1;
+ uint32 i;
+
+ // The atomic operations are not atomic if the uint64s
+ // are not aligned on uint64 boundaries. This has been
+ // a problem in the past.
+ if((((uintptr)&work.empty) & 7) != 0)
+ runtime_throw("runtime: gc work buffer is misaligned");
// Make sure all registers are saved on stack so that
// scanstack sees them.
@@ -986,48 +1006,67 @@ runtime_gc(int32 force)
}
t0 = runtime_nanotime();
- nhandoff = 0;
m->gcing = 1;
runtime_stoptheworld();
- cachestats();
- heap0 = mstats.heap_alloc;
- obj0 = mstats.nmalloc - mstats.nfree;
+ for(m1=runtime_allm; m1; m1=m1->alllink)
+ runtime_settype_flush(m1, false);
- runtime_lock(&work.markgate);
- runtime_lock(&work.sweepgate);
-
- extra = false;
- work.nproc = 1;
- if(runtime_gomaxprocs > 1 && runtime_ncpu > 1) {
- runtime_noteclear(&work.alldone);
- work.nproc += runtime_helpgc(&extra);
+ heap0 = 0;
+ obj0 = 0;
+ if(gctrace) {
+ cachestats(nil);
+ heap0 = mstats.heap_alloc;
+ obj0 = mstats.nmalloc - mstats.nfree;
}
+
work.nwait = 0;
work.ndone = 0;
+ work.debugmarkdone = 0;
+ work.nproc = runtime_gcprocs();
+ addroots();
+ m->locks++; // disable gc during mallocs in parforalloc
+ if(work.markfor == nil)
+ work.markfor = runtime_parforalloc(MaxGcproc);
+ runtime_parforsetup(work.markfor, work.nproc, work.nroot, nil, false, markroot);
+ if(work.sweepfor == nil)
+ work.sweepfor = runtime_parforalloc(MaxGcproc);
+ runtime_parforsetup(work.sweepfor, work.nproc, runtime_mheap.nspan, nil, true, sweepspan);
+ m->locks--;
+ if(work.nproc > 1) {
+ runtime_noteclear(&work.alldone);
+ runtime_helpgc(work.nproc);
+ }
- runtime_unlock(&work.markgate); // let the helpers in
- mark(scanblock);
- if(DebugMark)
- mark(debug_scanblock);
+ runtime_parfordo(work.markfor);
+ scanblock(nil, 0);
+
+ if(DebugMark) {
+ for(i=0; i<work.nroot; i++)
+ debug_scanblock(work.roots[i].p, work.roots[i].n);
+ runtime_atomicstore(&work.debugmarkdone, 1);
+ }
t1 = runtime_nanotime();
- work.spans = runtime_mheap.allspans;
- runtime_unlock(&work.sweepgate); // let the helpers in
- sweep();
- if(work.nproc > 1)
- runtime_notesleep(&work.alldone);
+ runtime_parfordo(work.sweepfor);
t2 = runtime_nanotime();
stealcache();
- cachestats();
+ cachestats(&stats);
+
+ if(work.nproc > 1)
+ runtime_notesleep(&work.alldone);
+
+ stats.nprocyield += work.sweepfor->nprocyield;
+ stats.nosyield += work.sweepfor->nosyield;
+ stats.nsleep += work.sweepfor->nsleep;
mstats.next_gc = mstats.heap_alloc+(mstats.heap_alloc-runtime_stacks_sys)*gcpercent/100;
m->gcing = 0;
- m->locks++; // disable gc during the mallocs in newproc
if(finq != nil) {
+ m->locks++; // disable gc during the mallocs in newproc
// kick off or wake up goroutine to run queued finalizers
if(fing == nil)
fing = __go_go(runfinq, nil);
@@ -1035,10 +1074,9 @@ runtime_gc(int32 force)
fingwait = 0;
runtime_ready(fing);
}
+ m->locks--;
}
- m->locks--;
- cachestats();
heap1 = mstats.heap_alloc;
obj1 = mstats.nmalloc - mstats.nfree;
@@ -1051,26 +1089,22 @@ runtime_gc(int32 force)
runtime_printf("pause %D\n", t3-t0);
if(gctrace) {
- runtime_printf("gc%d(%d): %D+%D+%D ms, %D -> %D MB %D -> %D (%D-%D) objects\n",
+ runtime_printf("gc%d(%d): %D+%D+%D ms, %D -> %D MB %D -> %D (%D-%D) objects,"
+ " %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\n",
mstats.numgc, work.nproc, (t1-t0)/1000000, (t2-t1)/1000000, (t3-t2)/1000000,
heap0>>20, heap1>>20, obj0, obj1,
- mstats.nmalloc, mstats.nfree);
+ mstats.nmalloc, mstats.nfree,
+ stats.nhandoff, stats.nhandoffcnt,
+ work.sweepfor->nsteal, work.sweepfor->nstealcnt,
+ stats.nprocyield, stats.nosyield, stats.nsleep);
}
-
+
runtime_MProf_GC();
runtime_semrelease(&runtime_worldsema);
+ runtime_starttheworld();
- // If we could have used another helper proc, start one now,
- // in the hope that it will be available next time.
- // It would have been even better to start it before the collection,
- // but doing so requires allocating memory, so it's tricky to
- // coordinate. This lazy approach works out in practice:
- // we don't mind if the first couple gc rounds don't have quite
- // the maximum number of procs.
- runtime_starttheworld(extra);
-
- // give the queued finalizers, if any, a chance to run
- if(finq != nil)
+ // give the queued finalizers, if any, a chance to run
+ if(finq != nil)
runtime_gosched();
if(gctrace > 1 && !force)
@@ -1093,22 +1127,23 @@ runtime_ReadMemStats(MStats *stats)
m = runtime_m();
m->gcing = 1;
runtime_stoptheworld();
- cachestats();
+ cachestats(nil);
*stats = mstats;
m->gcing = 0;
runtime_semrelease(&runtime_worldsema);
- runtime_starttheworld(false);
+ runtime_starttheworld();
}
static void
runfinq(void* dummy __attribute__ ((unused)))
{
- G* gp;
Finalizer *f;
FinBlock *fb, *next;
uint32 i;
- gp = runtime_g();
+ if(raceenabled)
+ runtime_racefingo();
+
for(;;) {
// There's no need for a lock in this section
// because it only conflicts with the garbage
@@ -1120,9 +1155,7 @@ runfinq(void* dummy __attribute__ ((unused)))
finq = nil;
if(fb == nil) {
fingwait = 1;
- gp->status = Gwaiting;
- gp->waitreason = "finalizer wait";
- runtime_gosched();
+ runtime_park(nil, nil, "finalizer wait");
continue;
}
for(; fb; fb=next) {
diff --git a/libgo/runtime/mheap.c b/libgo/runtime/mheap.c
index 221c5af861e..61ef4dd7992 100644
--- a/libgo/runtime/mheap.c
+++ b/libgo/runtime/mheap.c
@@ -27,11 +27,24 @@ RecordSpan(void *vh, byte *p)
{
MHeap *h;
MSpan *s;
+ MSpan **all;
+ uint32 cap;
h = vh;
s = (MSpan*)p;
- s->allnext = h->allspans;
- h->allspans = s;
+ if(h->nspan >= h->nspancap) {
+ cap = 64*1024/sizeof(all[0]);
+ if(cap < h->nspancap*3/2)
+ cap = h->nspancap*3/2;
+ all = (MSpan**)runtime_SysAlloc(cap*sizeof(all[0]));
+ if(h->allspans) {
+ runtime_memmove(all, h->allspans, h->nspancap*sizeof(all[0]));
+ runtime_SysFree(h->allspans, h->nspancap*sizeof(all[0]));
+ }
+ h->allspans = all;
+ h->nspancap = cap;
+ }
+ h->allspans[h->nspan++] = s;
}
// Initialize the heap; fetch memory using alloc.
@@ -53,12 +66,12 @@ runtime_MHeap_Init(MHeap *h, void *(*alloc)(uintptr))
// Allocate a new span of npage pages from the heap
// and record its size class in the HeapMap and HeapMapCache.
MSpan*
-runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct)
+runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32 zeroed)
{
MSpan *s;
runtime_lock(h);
- runtime_purgecachedstats(runtime_m());
+ runtime_purgecachedstats(runtime_m()->mcache);
s = MHeap_AllocLocked(h, npage, sizeclass);
if(s != nil) {
mstats.heap_inuse += npage<<PageShift;
@@ -68,6 +81,8 @@ runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct)
}
}
runtime_unlock(h);
+ if(s != nil && *(uintptr*)(s->start<<PageShift) != 0 && zeroed)
+ runtime_memclr((byte*)(s->start<<PageShift), s->npages<<PageShift);
return s;
}
@@ -125,12 +140,11 @@ HaveSpan:
MHeap_FreeLocked(h, t);
}
- if(*(uintptr*)(s->start<<PageShift) != 0)
- runtime_memclr((byte*)(s->start<<PageShift), s->npages<<PageShift);
-
// Record span info, because gc needs to be
// able to map interior pointer to containing span.
s->sizeclass = sizeclass;
+ s->elemsize = (sizeclass==0 ? s->npages<<PageShift : (uintptr)runtime_class_to_size[sizeclass]);
+ s->types.compression = MTypes_Empty;
p = s->start;
if(sizeof(void*) == 8)
p -= ((uintptr)h->arena_start>>PageShift);
@@ -259,7 +273,7 @@ void
runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct)
{
runtime_lock(h);
- runtime_purgecachedstats(runtime_m());
+ runtime_purgecachedstats(runtime_m()->mcache);
mstats.heap_inuse -= s->npages<<PageShift;
if(acct) {
mstats.heap_alloc -= s->npages<<PageShift;
@@ -276,6 +290,10 @@ MHeap_FreeLocked(MHeap *h, MSpan *s)
MSpan *t;
PageID p;
+ if(s->types.sysalloc)
+ runtime_settype_sysfree(s);
+ s->types.compression = MTypes_Empty;
+
if(s->state != MSpanInUse || s->ref != 0) {
runtime_printf("MHeap_FreeLocked - span %p ptr %p state %d ref %d\n", s, s->start<<PageShift, s->state, s->ref);
runtime_throw("MHeap_FreeLocked - invalid free");
@@ -416,9 +434,11 @@ runtime_MSpan_Init(MSpan *span, PageID start, uintptr npages)
span->freelist = nil;
span->ref = 0;
span->sizeclass = 0;
+ span->elemsize = 0;
span->state = 0;
span->unusedsince = 0;
span->npreleased = 0;
+ span->types.compression = MTypes_Empty;
}
// Initialize an empty doubly-linked list.
diff --git a/libgo/runtime/mprof.goc b/libgo/runtime/mprof.goc
index 875abe38d61..edec3dc08dc 100644
--- a/libgo/runtime/mprof.goc
+++ b/libgo/runtime/mprof.goc
@@ -15,21 +15,35 @@ package runtime
// NOTE(rsc): Everything here could use cas if contention became an issue.
static Lock proflock;
-// Per-call-stack allocation information.
+enum { MProf, BProf }; // profile types
+
+// Per-call-stack profiling information.
// Lookup by hashing call stack into a linked-list hash table.
typedef struct Bucket Bucket;
struct Bucket
{
Bucket *next; // next in hash list
- Bucket *allnext; // next in list of all buckets
- uintptr allocs;
- uintptr frees;
- uintptr alloc_bytes;
- uintptr free_bytes;
- uintptr recent_allocs; // since last gc
- uintptr recent_frees;
- uintptr recent_alloc_bytes;
- uintptr recent_free_bytes;
+ Bucket *allnext; // next in list of all mbuckets/bbuckets
+ int32 typ;
+ union
+ {
+ struct // typ == MProf
+ {
+ uintptr allocs;
+ uintptr frees;
+ uintptr alloc_bytes;
+ uintptr free_bytes;
+ uintptr recent_allocs; // since last gc
+ uintptr recent_frees;
+ uintptr recent_alloc_bytes;
+ uintptr recent_free_bytes;
+ };
+ struct // typ == BProf
+ {
+ int64 count;
+ int64 cycles;
+ };
+ };
uintptr hash;
uintptr nstk;
uintptr stk[1];
@@ -38,12 +52,13 @@ enum {
BuckHashSize = 179999,
};
static Bucket **buckhash;
-static Bucket *buckets;
+static Bucket *mbuckets; // memory profile buckets
+static Bucket *bbuckets; // blocking profile buckets
static uintptr bucketmem;
// Return the bucket for stk[0:nstk], allocating new bucket if needed.
static Bucket*
-stkbucket(uintptr *stk, int32 nstk, bool alloc)
+stkbucket(int32 typ, uintptr *stk, int32 nstk, bool alloc)
{
int32 i;
uintptr h;
@@ -66,7 +81,7 @@ stkbucket(uintptr *stk, int32 nstk, bool alloc)
i = h%BuckHashSize;
for(b = buckhash[i]; b; b=b->next)
- if(b->hash == h && b->nstk == (uintptr)nstk &&
+ if(b->typ == typ && b->hash == h && b->nstk == (uintptr)nstk &&
runtime_mcmp((byte*)b->stk, (byte*)stk, nstk*sizeof stk[0]) == 0)
return b;
@@ -76,12 +91,18 @@ stkbucket(uintptr *stk, int32 nstk, bool alloc)
b = runtime_mallocgc(sizeof *b + nstk*sizeof stk[0], FlagNoProfiling, 0, 1);
bucketmem += sizeof *b + nstk*sizeof stk[0];
runtime_memmove(b->stk, stk, nstk*sizeof stk[0]);
+ b->typ = typ;
b->hash = h;
b->nstk = nstk;
b->next = buckhash[i];
buckhash[i] = b;
- b->allnext = buckets;
- buckets = b;
+ if(typ == MProf) {
+ b->allnext = mbuckets;
+ mbuckets = b;
+ } else {
+ b->allnext = bbuckets;
+ bbuckets = b;
+ }
return b;
}
@@ -92,7 +113,7 @@ runtime_MProf_GC(void)
Bucket *b;
runtime_lock(&proflock);
- for(b=buckets; b; b=b->allnext) {
+ for(b=mbuckets; b; b=b->allnext) {
b->allocs += b->recent_allocs;
b->frees += b->recent_frees;
b->alloc_bytes += b->recent_alloc_bytes;
@@ -107,20 +128,26 @@ runtime_MProf_GC(void)
// Map from pointer to Bucket* that allocated it.
// Three levels:
-// Linked-list hash table for top N-20 bits.
-// Array index for next 13 bits.
-// Linked list for next 7 bits.
+// Linked-list hash table for top N-AddrHashShift bits.
+// Array index for next AddrDenseBits bits.
+// Linked list for next AddrHashShift-AddrDenseBits bits.
// This is more efficient than using a general map,
// because of the typical clustering of the pointer keys.
typedef struct AddrHash AddrHash;
typedef struct AddrEntry AddrEntry;
+enum {
+ AddrHashBits = 12, // good for 4GB of used address space
+ AddrHashShift = 20, // each AddrHash knows about 1MB of address space
+ AddrDenseBits = 8, // good for a profiling rate of 4096 bytes
+};
+
struct AddrHash
{
AddrHash *next; // next in top-level hash table linked list
uintptr addr; // addr>>20
- AddrEntry *dense[1<<13];
+ AddrEntry *dense[1<<AddrDenseBits];
};
struct AddrEntry
@@ -130,9 +157,6 @@ struct AddrEntry
Bucket *b;
};
-enum {
- AddrHashBits = 12 // 1MB per entry, so good for 4GB of used address space
-};
static AddrHash *addrhash[1<<AddrHashBits];
static AddrEntry *addrfree;
static uintptr addrmem;
@@ -155,15 +179,15 @@ setaddrbucket(uintptr addr, Bucket *b)
AddrHash *ah;
AddrEntry *e;
- h = (uint32)((addr>>20)*HashMultiplier) >> (32-AddrHashBits);
+ h = (uint32)((addr>>AddrHashShift)*HashMultiplier) >> (32-AddrHashBits);
for(ah=addrhash[h]; ah; ah=ah->next)
- if(ah->addr == (addr>>20))
+ if(ah->addr == (addr>>AddrHashShift))
goto found;
ah = runtime_mallocgc(sizeof *ah, FlagNoProfiling, 0, 1);
addrmem += sizeof *ah;
ah->next = addrhash[h];
- ah->addr = addr>>20;
+ ah->addr = addr>>AddrHashShift;
addrhash[h] = ah;
found:
@@ -175,9 +199,9 @@ found:
e[63].next = nil;
}
addrfree = e->next;
- e->addr = (uint32)~(addr & ((1<<20)-1));
+ e->addr = (uint32)~(addr & ((1<<AddrHashShift)-1));
e->b = b;
- h = (addr>>7)&(nelem(ah->dense)-1); // entry in dense is top 13 bits of low 20.
+ h = (addr>>(AddrHashShift-AddrDenseBits))&(nelem(ah->dense)-1); // entry in dense is top 8 bits of low 20.
e->next = ah->dense[h];
ah->dense[h] = e;
}
@@ -191,16 +215,16 @@ getaddrbucket(uintptr addr)
AddrEntry *e, **l;
Bucket *b;
- h = (uint32)((addr>>20)*HashMultiplier) >> (32-AddrHashBits);
+ h = (uint32)((addr>>AddrHashShift)*HashMultiplier) >> (32-AddrHashBits);
for(ah=addrhash[h]; ah; ah=ah->next)
- if(ah->addr == (addr>>20))
+ if(ah->addr == (addr>>AddrHashShift))
goto found;
return nil;
found:
- h = (addr>>7)&(nelem(ah->dense)-1); // entry in dense is top 13 bits of low 20.
+ h = (addr>>(AddrHashShift-AddrDenseBits))&(nelem(ah->dense)-1); // entry in dense is top 8 bits of low 20.
for(l=&ah->dense[h]; (e=*l) != nil; l=&e->next) {
- if(e->addr == (uint32)~(addr & ((1<<20)-1))) {
+ if(e->addr == (uint32)~(addr & ((1<<AddrHashShift)-1))) {
*l = e->next;
b = e->b;
e->next = addrfree;
@@ -227,7 +251,7 @@ runtime_MProf_Malloc(void *p, uintptr size)
m->nomemprof++;
nstk = runtime_callers(1, stk, 32);
runtime_lock(&proflock);
- b = stkbucket(stk, nstk, true);
+ b = stkbucket(MProf, stk, nstk, true);
b->recent_allocs++;
b->recent_alloc_bytes += size;
setaddrbucket((uintptr)p, b);
@@ -259,6 +283,37 @@ runtime_MProf_Free(void *p, uintptr size)
m->nomemprof--;
}
+int64 runtime_blockprofilerate; // in CPU ticks
+
+void runtime_SetBlockProfileRate(intgo) asm("runtime.SetBlockProfileRate");
+
+void
+runtime_SetBlockProfileRate(intgo rate)
+{
+ runtime_atomicstore64((uint64*)&runtime_blockprofilerate, rate * runtime_tickspersecond() / (1000*1000*1000));
+}
+
+void
+runtime_blockevent(int64 cycles, int32 skip)
+{
+ int32 nstk;
+ int64 rate;
+ uintptr stk[32];
+ Bucket *b;
+
+ if(cycles <= 0)
+ return;
+ rate = runtime_atomicload64((uint64*)&runtime_blockprofilerate);
+ if(rate <= 0 || (rate > cycles && runtime_fastrand1()%rate > cycles))
+ return;
+
+ nstk = runtime_callers(skip, stk, 32);
+ runtime_lock(&proflock);
+ b = stkbucket(BProf, stk, nstk, true);
+ b->count++;
+ b->cycles += cycles;
+ runtime_unlock(&proflock);
+}
// Go interface to profile data. (Declared in extern.go)
// Assumes Go sizeof(int) == sizeof(int32)
@@ -287,20 +342,20 @@ record(Record *r, Bucket *b)
r->stk[i] = 0;
}
-func MemProfile(p Slice, include_inuse_zero bool) (n int32, ok bool) {
+func MemProfile(p Slice, include_inuse_zero bool) (n int, ok bool) {
Bucket *b;
Record *r;
runtime_lock(&proflock);
n = 0;
- for(b=buckets; b; b=b->allnext)
+ for(b=mbuckets; b; b=b->allnext)
if(include_inuse_zero || b->alloc_bytes != b->free_bytes)
n++;
ok = false;
if(n <= p.__count) {
ok = true;
r = (Record*)p.__values;
- for(b=buckets; b; b=b->allnext)
+ for(b=mbuckets; b; b=b->allnext)
if(include_inuse_zero || b->alloc_bytes != b->free_bytes)
record(r++, b);
}
@@ -308,12 +363,46 @@ func MemProfile(p Slice, include_inuse_zero bool) (n int32, ok bool) {
}
void
-runtime_MProf_Mark(void (*scan)(byte *, int64))
+runtime_MProf_Mark(void (*addroot)(byte *, uintptr))
{
// buckhash is not allocated via mallocgc.
- scan((byte*)&buckets, sizeof buckets);
- scan((byte*)&addrhash, sizeof addrhash);
- scan((byte*)&addrfree, sizeof addrfree);
+ addroot((byte*)&mbuckets, sizeof mbuckets);
+ addroot((byte*)&bbuckets, sizeof bbuckets);
+ addroot((byte*)&addrhash, sizeof addrhash);
+ addroot((byte*)&addrfree, sizeof addrfree);
+}
+
+// Must match BlockProfileRecord in debug.go.
+typedef struct BRecord BRecord;
+struct BRecord {
+ int64 count;
+ int64 cycles;
+ uintptr stk[32];
+};
+
+func BlockProfile(p Slice) (n int, ok bool) {
+ Bucket *b;
+ BRecord *r;
+ int32 i;
+
+ runtime_lock(&proflock);
+ n = 0;
+ for(b=bbuckets; b; b=b->allnext)
+ n++;
+ ok = false;
+ if(n <= p.__count) {
+ ok = true;
+ r = (BRecord*)p.__values;
+ for(b=bbuckets; b; b=b->allnext, r++) {
+ r->count = b->count;
+ r->cycles = b->cycles;
+ for(i=0; (uintptr)i<b->nstk && (uintptr)i<nelem(r->stk); i++)
+ r->stk[i] = b->stk[i];
+ for(; (uintptr)i<nelem(r->stk); i++)
+ r->stk[i] = 0;
+ }
+ }
+ runtime_unlock(&proflock);
}
// Must match StackRecord in debug.go.
@@ -322,7 +411,7 @@ struct TRecord {
uintptr stk[32];
};
-func ThreadCreateProfile(p Slice) (n int32, ok bool) {
+func ThreadCreateProfile(p Slice) (n int, ok bool) {
TRecord *r;
M *first, *m;
@@ -341,7 +430,7 @@ func ThreadCreateProfile(p Slice) (n int32, ok bool) {
}
}
-func Stack(b Slice, all bool) (n int32) {
+func Stack(b Slice, all bool) (n int) {
byte *pc, *sp;
bool enablegc;
@@ -378,7 +467,7 @@ func Stack(b Slice, all bool) (n int32) {
runtime_m()->gcing = 0;
mstats.enablegc = enablegc;
runtime_semrelease(&runtime_worldsema);
- runtime_starttheworld(false);
+ runtime_starttheworld();
}
}
@@ -397,7 +486,7 @@ saveg(G *g, TRecord *r)
r->stk[n] = 0;
}
-func GoroutineProfile(b Slice) (n int32, ok bool) {
+func GoroutineProfile(b Slice) (n int, ok bool) {
TRecord *r;
G *gp;
@@ -423,7 +512,7 @@ func GoroutineProfile(b Slice) (n int32, ok bool) {
runtime_m()->gcing = 0;
runtime_semrelease(&runtime_worldsema);
- runtime_starttheworld(false);
+ runtime_starttheworld();
}
}
diff --git a/libgo/runtime/panic.c b/libgo/runtime/panic.c
new file mode 100644
index 00000000000..98326c66a6e
--- /dev/null
+++ b/libgo/runtime/panic.c
@@ -0,0 +1,115 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "go-defer.h"
+
+// Code related to defer, panic and recover.
+
+uint32 runtime_panicking;
+static Lock paniclk;
+
+// Run all deferred functions for the current goroutine.
+static void
+rundefer(void)
+{
+ G *g;
+ Defer *d;
+
+ g = runtime_g();
+ while((d = g->defer) != nil) {
+ void (*pfn)(void*);
+
+ g->defer = d->__next;
+ pfn = d->__pfn;
+ d->__pfn = nil;
+ if (pfn != nil)
+ (*pfn)(d->__arg);
+ runtime_free(d);
+ }
+}
+
+void
+runtime_startpanic(void)
+{
+ M *m;
+
+ m = runtime_m();
+ if(m->dying) {
+ runtime_printf("panic during panic\n");
+ runtime_exit(3);
+ }
+ m->dying = 1;
+ runtime_xadd(&runtime_panicking, 1);
+ runtime_lock(&paniclk);
+}
+
+void
+runtime_dopanic(int32 unused __attribute__ ((unused)))
+{
+ G *g;
+ static bool didothers;
+
+ g = runtime_g();
+ if(g->sig != 0)
+ runtime_printf("[signal %x code=%p addr=%p]\n",
+ g->sig, (void*)g->sigcode0, (void*)g->sigcode1);
+
+ if(runtime_gotraceback()){
+ if(g != runtime_m()->g0) {
+ runtime_printf("\n");
+ runtime_goroutineheader(g);
+ runtime_traceback();
+ runtime_goroutinetrailer(g);
+ }
+ if(!didothers) {
+ didothers = true;
+ runtime_tracebackothers(g);
+ }
+ }
+ runtime_unlock(&paniclk);
+ if(runtime_xadd(&runtime_panicking, -1) != 0) {
+ // Some other m is panicking too.
+ // Let it print what it needs to print.
+ // Wait forever without chewing up cpu.
+ // It will exit when it's done.
+ static Lock deadlock;
+ runtime_lock(&deadlock);
+ runtime_lock(&deadlock);
+ }
+
+ runtime_exit(2);
+}
+
+void
+runtime_throw(const char *s)
+{
+ runtime_startpanic();
+ runtime_printf("throw: %s\n", s);
+ runtime_dopanic(0);
+ *(int32*)0 = 0; // not reached
+ runtime_exit(1); // even more not reached
+}
+
+void
+runtime_panicstring(const char *s)
+{
+ Eface err;
+
+ if(runtime_m()->gcing) {
+ runtime_printf("panic: %s\n", s);
+ runtime_throw("panic during gc");
+ }
+ runtime_newErrorString(runtime_gostringnocopy((const byte*)s), &err);
+ runtime_panic(err);
+}
+
+void runtime_Goexit (void) asm ("runtime.Goexit");
+
+void
+runtime_Goexit(void)
+{
+ rundefer();
+ runtime_goexit();
+}
diff --git a/libgo/runtime/parfor.c b/libgo/runtime/parfor.c
new file mode 100644
index 00000000000..98ebdebc559
--- /dev/null
+++ b/libgo/runtime/parfor.c
@@ -0,0 +1,232 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Parallel for algorithm.
+
+#include "runtime.h"
+#include "arch.h"
+
+struct ParForThread
+{
+ // the thread's iteration space [32lsb, 32msb)
+ uint64 pos;
+ // stats
+ uint64 nsteal;
+ uint64 nstealcnt;
+ uint64 nprocyield;
+ uint64 nosyield;
+ uint64 nsleep;
+ byte pad[CacheLineSize];
+};
+
+ParFor*
+runtime_parforalloc(uint32 nthrmax)
+{
+ ParFor *desc;
+
+ // The ParFor object is followed by CacheLineSize padding
+ // and then nthrmax ParForThread.
+ desc = (ParFor*)runtime_malloc(sizeof(ParFor) + CacheLineSize + nthrmax * sizeof(ParForThread));
+ desc->thr = (ParForThread*)((byte*)(desc+1) + CacheLineSize);
+ desc->nthrmax = nthrmax;
+ return desc;
+}
+
+// For testing from Go
+// func parforalloc2(nthrmax uint32) *ParFor
+
+ParFor *runtime_parforalloc2(uint32)
+ asm("runtime.parforalloc2");
+
+ParFor *
+runtime_parforalloc2(uint32 nthrmax)
+{
+ return runtime_parforalloc(nthrmax);
+}
+
+void
+runtime_parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32))
+{
+ uint32 i, begin, end;
+
+ if(desc == nil || nthr == 0 || nthr > desc->nthrmax || body == nil) {
+ runtime_printf("desc=%p nthr=%d count=%d body=%p\n", desc, nthr, n, body);
+ runtime_throw("parfor: invalid args");
+ }
+
+ desc->body = body;
+ desc->done = 0;
+ desc->nthr = nthr;
+ desc->thrseq = 0;
+ desc->cnt = n;
+ desc->ctx = ctx;
+ desc->wait = wait;
+ desc->nsteal = 0;
+ desc->nstealcnt = 0;
+ desc->nprocyield = 0;
+ desc->nosyield = 0;
+ desc->nsleep = 0;
+ for(i=0; i<nthr; i++) {
+ begin = (uint64)n*i / nthr;
+ end = (uint64)n*(i+1) / nthr;
+ desc->thr[i].pos = (uint64)begin | (((uint64)end)<<32);
+ }
+}
+
+// For testing from Go
+// func parforsetup2(desc *ParFor, nthr, n uint32, ctx *byte, wait bool, body func(*ParFor, uint32))
+
+void runtime_parforsetup2(ParFor *, uint32, uint32, void *, bool, void *)
+ asm("runtime.parforsetup2");
+
+void
+runtime_parforsetup2(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void *body)
+{
+ runtime_parforsetup(desc, nthr, n, ctx, wait, (void(*)(ParFor*, uint32))body);
+}
+
+void
+runtime_parfordo(ParFor *desc)
+{
+ ParForThread *me;
+ uint32 tid, begin, end, begin2, try, victim, i;
+ uint64 *mypos, *victimpos, pos, newpos;
+ void (*body)(ParFor*, uint32);
+ bool idle;
+
+ // Obtain 0-based thread index.
+ tid = runtime_xadd(&desc->thrseq, 1) - 1;
+ if(tid >= desc->nthr) {
+ runtime_printf("tid=%d nthr=%d\n", tid, desc->nthr);
+ runtime_throw("parfor: invalid tid");
+ }
+
+ // If single-threaded, just execute the for serially.
+ if(desc->nthr==1) {
+ for(i=0; i<desc->cnt; i++)
+ desc->body(desc, i);
+ return;
+ }
+
+ body = desc->body;
+ me = &desc->thr[tid];
+ mypos = &me->pos;
+ for(;;) {
+ for(;;) {
+ // While there is local work,
+ // bump low index and execute the iteration.
+ pos = runtime_xadd64(mypos, 1);
+ begin = (uint32)pos-1;
+ end = (uint32)(pos>>32);
+ if(begin < end) {
+ body(desc, begin);
+ continue;
+ }
+ break;
+ }
+
+ // Out of work, need to steal something.
+ idle = false;
+ for(try=0;; try++) {
+ // If we don't see any work for long enough,
+ // increment the done counter...
+ if(try > desc->nthr*4 && !idle) {
+ idle = true;
+ runtime_xadd(&desc->done, 1);
+ }
+ // ...if all threads have incremented the counter,
+ // we are done.
+ if(desc->done + !idle == desc->nthr) {
+ if(!idle)
+ runtime_xadd(&desc->done, 1);
+ goto exit;
+ }
+ // Choose a random victim for stealing.
+ victim = runtime_fastrand1() % (desc->nthr-1);
+ if(victim >= tid)
+ victim++;
+ victimpos = &desc->thr[victim].pos;
+ pos = runtime_atomicload64(victimpos);
+ for(;;) {
+ // See if it has any work.
+ begin = (uint32)pos;
+ end = (uint32)(pos>>32);
+ if(begin >= end-1) {
+ begin = end = 0;
+ break;
+ }
+ if(idle) {
+ runtime_xadd(&desc->done, -1);
+ idle = false;
+ }
+ begin2 = begin + (end-begin)/2;
+ newpos = (uint64)begin | (uint64)begin2<<32;
+ if(runtime_cas64(victimpos, &pos, newpos)) {
+ begin = begin2;
+ break;
+ }
+ }
+ if(begin < end) {
+ // Has successfully stolen some work.
+ if(idle)
+ runtime_throw("parfor: should not be idle");
+ runtime_atomicstore64(mypos, (uint64)begin | (uint64)end<<32);
+ me->nsteal++;
+ me->nstealcnt += end-begin;
+ break;
+ }
+ // Backoff.
+ if(try < desc->nthr) {
+ // nothing
+ } else if (try < 4*desc->nthr) {
+ me->nprocyield++;
+ runtime_procyield(20);
+ // If a caller asked not to wait for the others, exit now
+ // (assume that most work is already done at this point).
+ } else if (!desc->wait) {
+ if(!idle)
+ runtime_xadd(&desc->done, 1);
+ goto exit;
+ } else if (try < 6*desc->nthr) {
+ me->nosyield++;
+ runtime_osyield();
+ } else {
+ me->nsleep++;
+ runtime_usleep(1);
+ }
+ }
+ }
+exit:
+ runtime_xadd64(&desc->nsteal, me->nsteal);
+ runtime_xadd64(&desc->nstealcnt, me->nstealcnt);
+ runtime_xadd64(&desc->nprocyield, me->nprocyield);
+ runtime_xadd64(&desc->nosyield, me->nosyield);
+ runtime_xadd64(&desc->nsleep, me->nsleep);
+ me->nsteal = 0;
+ me->nstealcnt = 0;
+ me->nprocyield = 0;
+ me->nosyield = 0;
+ me->nsleep = 0;
+}
+
+// For testing from Go
+// func parforiters(desc *ParFor, tid uintptr) (uintptr, uintptr)
+
+struct parforiters_ret {
+ uintptr start;
+ uintptr end;
+};
+
+struct parforiters_ret runtime_parforiters(ParFor *, uintptr)
+ asm("runtime.parforiters");
+
+struct parforiters_ret
+runtime_parforiters(ParFor *desc, uintptr tid)
+{
+ struct parforiters_ret ret;
+
+ ret.start = (uint32)desc->thr[tid].pos;
+ ret.end = (uint32)(desc->thr[tid].pos>>32);
+ return ret;
+}
diff --git a/libgo/runtime/print.c b/libgo/runtime/print.c
index 5a8e47e5373..690bcaf0331 100644
--- a/libgo/runtime/print.c
+++ b/libgo/runtime/print.c
@@ -156,15 +156,16 @@ runtime_printfloat(double v)
int32 e, s, i, n;
float64 h;
- if(runtime_isNaN(v)) {
+ if(ISNAN(v)) {
gwrite("NaN", 3);
return;
}
- if(runtime_isInf(v, 1)) {
+ i = __builtin_isinf_sign(v);
+ if(i > 0) {
gwrite("+Inf", 4);
return;
}
- if(runtime_isInf(v, -1)) {
+ if(i < 0) {
gwrite("-Inf", 4);
return;
}
@@ -290,8 +291,8 @@ runtime_printstring(String v)
// extern uint32 runtime_maxstring;
// if(v.len > runtime_maxstring) {
- // gwrite("[invalid string]", 16);
- // return;
+ // gwrite("[string too long]", 17);
+ // return;
// }
if(v.__length > 0)
gwrite(v.__data, v.__length);
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 224dce95ba0..620cd10c1c3 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -17,6 +17,7 @@
#include "arch.h"
#include "defs.h"
#include "malloc.h"
+#include "race.h"
#include "go-defer.h"
#ifdef USING_SPLIT_STACK
@@ -330,6 +331,9 @@ kickoff(void)
{
void (*fn)(void*);
+ if(g->traceback != nil)
+ gtraceback(g);
+
fn = (void (*)(void*))(g->entry);
fn(g->param);
runtime_goexit();
@@ -471,6 +475,9 @@ runtime_schedinit(void)
// Can not enable GC until all roots are registered.
// mstats.enablegc = 1;
m->nomemprof--;
+
+ if(raceenabled)
+ runtime_raceinit();
}
extern void main_init(void) __asm__ ("__go_init_main");
@@ -507,6 +514,8 @@ runtime_main(void)
runtime_gosched();
main_main();
+ if(raceenabled)
+ runtime_racefini();
runtime_exit(0);
for(;;)
*(int32*)0 = 0;
@@ -540,11 +549,11 @@ runtime_goexit(void)
}
void
-runtime_goroutineheader(G *g)
+runtime_goroutineheader(G *gp)
{
const char *status;
- switch(g->status) {
+ switch(gp->status) {
case Gidle:
status = "idle";
break;
@@ -558,8 +567,8 @@ runtime_goroutineheader(G *g)
status = "syscall";
break;
case Gwaiting:
- if(g->waitreason)
- status = g->waitreason;
+ if(gp->waitreason)
+ status = gp->waitreason;
else
status = "waiting";
break;
@@ -570,7 +579,7 @@ runtime_goroutineheader(G *g)
status = "???";
break;
}
- runtime_printf("goroutine %d [%s]:\n", g->goid, status);
+ runtime_printf("goroutine %d [%s]:\n", gp->goid, status);
}
void
@@ -598,15 +607,15 @@ struct Traceback
void
runtime_tracebackothers(G * volatile me)
{
- G * volatile g;
+ G * volatile gp;
Traceback traceback;
traceback.gp = me;
- for(g = runtime_allg; g != nil; g = g->alllink) {
- if(g == me || g->status == Gdead)
+ for(gp = runtime_allg; gp != nil; gp = gp->alllink) {
+ if(gp == me || gp->status == Gdead)
continue;
runtime_printf("\n");
- runtime_goroutineheader(g);
+ runtime_goroutineheader(gp);
// Our only mechanism for doing a stack trace is
// _Unwind_Backtrace. And that only works for the
@@ -616,25 +625,25 @@ runtime_tracebackothers(G * volatile me)
// This means that if g is running or in a syscall, we
// can't reliably print a stack trace. FIXME.
- if(g->status == Gsyscall || g->status == Grunning) {
+ if(gp->status == Gsyscall || gp->status == Grunning) {
runtime_printf("no stack trace available\n");
- runtime_goroutinetrailer(g);
+ runtime_goroutinetrailer(gp);
continue;
}
- g->traceback = &traceback;
+ gp->traceback = &traceback;
#ifdef USING_SPLIT_STACK
__splitstack_getcontext(&me->stack_context[0]);
#endif
getcontext(&me->context);
- if(g->traceback != nil) {
- runtime_gogo(g);
+ if(gp->traceback != nil) {
+ runtime_gogo(gp);
}
runtime_printtrace(traceback.pcbuf, traceback.c);
- runtime_goroutinetrailer(g);
+ runtime_goroutinetrailer(gp);
}
}
@@ -666,22 +675,22 @@ runtime_idlegoroutine(void)
}
static void
-mcommoninit(M *m)
+mcommoninit(M *mp)
{
- m->id = runtime_sched.mcount++;
- m->fastrand = 0x49f6428aUL + m->id + runtime_cputicks();
+ mp->id = runtime_sched.mcount++;
+ mp->fastrand = 0x49f6428aUL + mp->id + runtime_cputicks();
- if(m->mcache == nil)
- m->mcache = runtime_allocmcache();
+ if(mp->mcache == nil)
+ mp->mcache = runtime_allocmcache();
- runtime_callers(1, m->createstack, nelem(m->createstack));
+ runtime_callers(1, mp->createstack, nelem(mp->createstack));
// Add to runtime_allm so garbage collector doesn't free m
// when it is just in a register or thread-local storage.
- m->alllink = runtime_allm;
+ mp->alllink = runtime_allm;
// runtime_NumCgoCall() iterates over allm w/o schedlock,
// so we need to publish it safely.
- runtime_atomicstorep(&runtime_allm, m);
+ runtime_atomicstorep(&runtime_allm, mp);
}
// Try to increment mcpu. Report whether succeeded.
@@ -701,34 +710,34 @@ canaddmcpu(void)
// Put on `g' queue. Sched must be locked.
static void
-gput(G *g)
+gput(G *gp)
{
- M *m;
+ M *mp;
// If g is wired, hand it off directly.
- if((m = g->lockedm) != nil && canaddmcpu()) {
- mnextg(m, g);
+ if((mp = gp->lockedm) != nil && canaddmcpu()) {
+ mnextg(mp, gp);
return;
}
// If g is the idle goroutine for an m, hand it off.
- if(g->idlem != nil) {
- if(g->idlem->idleg != nil) {
+ if(gp->idlem != nil) {
+ if(gp->idlem->idleg != nil) {
runtime_printf("m%d idle out of sync: g%d g%d\n",
- g->idlem->id,
- g->idlem->idleg->goid, g->goid);
+ gp->idlem->id,
+ gp->idlem->idleg->goid, gp->goid);
runtime_throw("runtime: double idle");
}
- g->idlem->idleg = g;
+ gp->idlem->idleg = gp;
return;
}
- g->schedlink = nil;
+ gp->schedlink = nil;
if(runtime_sched.ghead == nil)
- runtime_sched.ghead = g;
+ runtime_sched.ghead = gp;
else
- runtime_sched.gtail->schedlink = g;
- runtime_sched.gtail = g;
+ runtime_sched.gtail->schedlink = gp;
+ runtime_sched.gtail = gp;
// increment gwait.
// if it transitions to nonzero, set atomic gwaiting bit.
@@ -747,11 +756,11 @@ haveg(void)
static G*
gget(void)
{
- G *g;
+ G *gp;
- g = runtime_sched.ghead;
- if(g){
- runtime_sched.ghead = g->schedlink;
+ gp = runtime_sched.ghead;
+ if(gp) {
+ runtime_sched.ghead = gp->schedlink;
if(runtime_sched.ghead == nil)
runtime_sched.gtail = nil;
// decrement gwait.
@@ -759,45 +768,45 @@ gget(void)
if(--runtime_sched.gwait == 0)
runtime_xadd(&runtime_sched.atomic, -1<<gwaitingShift);
} else if(m->idleg != nil) {
- g = m->idleg;
+ gp = m->idleg;
m->idleg = nil;
}
- return g;
+ return gp;
}
// Put on `m' list. Sched must be locked.
static void
-mput(M *m)
+mput(M *mp)
{
- m->schedlink = runtime_sched.mhead;
- runtime_sched.mhead = m;
+ mp->schedlink = runtime_sched.mhead;
+ runtime_sched.mhead = mp;
runtime_sched.mwait++;
}
// Get an `m' to run `g'. Sched must be locked.
static M*
-mget(G *g)
+mget(G *gp)
{
- M *m;
+ M *mp;
// if g has its own m, use it.
- if(g && (m = g->lockedm) != nil)
- return m;
+ if(gp && (mp = gp->lockedm) != nil)
+ return mp;
// otherwise use general m pool.
- if((m = runtime_sched.mhead) != nil){
- runtime_sched.mhead = m->schedlink;
+ if((mp = runtime_sched.mhead) != nil) {
+ runtime_sched.mhead = mp->schedlink;
runtime_sched.mwait--;
}
- return m;
+ return mp;
}
// Mark g ready to run.
void
-runtime_ready(G *g)
+runtime_ready(G *gp)
{
schedlock();
- readylocked(g);
+ readylocked(gp);
schedunlock();
}
@@ -805,23 +814,23 @@ runtime_ready(G *g)
// G might be running already and about to stop.
// The sched lock protects g->status from changing underfoot.
static void
-readylocked(G *g)
+readylocked(G *gp)
{
- if(g->m){
+ if(gp->m) {
// Running on another machine.
// Ready it when it stops.
- g->readyonstop = 1;
+ gp->readyonstop = 1;
return;
}
// Mark runnable.
- if(g->status == Grunnable || g->status == Grunning) {
- runtime_printf("goroutine %d has status %d\n", g->goid, g->status);
+ if(gp->status == Grunnable || gp->status == Grunning) {
+ runtime_printf("goroutine %d has status %d\n", gp->goid, gp->status);
runtime_throw("bad g->status in ready");
}
- g->status = Grunnable;
+ gp->status = Grunnable;
- gput(g);
+ gput(gp);
matchmg();
}
@@ -829,23 +838,23 @@ readylocked(G *g)
// debuggers can set a breakpoint here and catch all
// new goroutines.
static void
-newprocreadylocked(G *g)
+newprocreadylocked(G *gp)
{
- readylocked(g);
+ readylocked(gp);
}
// Pass g to m for running.
// Caller has already incremented mcpu.
static void
-mnextg(M *m, G *g)
+mnextg(M *mp, G *gp)
{
runtime_sched.grunning++;
- m->nextg = g;
- if(m->waitnextg) {
- m->waitnextg = 0;
+ mp->nextg = gp;
+ if(mp->waitnextg) {
+ mp->waitnextg = 0;
if(mwakeup != nil)
runtime_notewakeup(&mwakeup->havenextg);
- mwakeup = m;
+ mwakeup = mp;
}
}
@@ -969,35 +978,38 @@ top:
}
int32
-runtime_helpgc(bool *extra)
+runtime_gcprocs(void)
{
- M *mp;
- int32 n, max;
-
- // Figure out how many CPUs to use.
+ int32 n;
+
+ // Figure out how many CPUs to use during GC.
// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
- max = runtime_gomaxprocs;
- if(max > runtime_ncpu)
- max = runtime_ncpu > 0 ? runtime_ncpu : 1;
- if(max > MaxGcproc)
- max = MaxGcproc;
+ n = runtime_gomaxprocs;
+ if(n > runtime_ncpu)
+ n = runtime_ncpu > 0 ? runtime_ncpu : 1;
+ if(n > MaxGcproc)
+ n = MaxGcproc;
+ if(n > runtime_sched.mwait+1) // one M is currently running
+ n = runtime_sched.mwait+1;
+ return n;
+}
- // We're going to use one CPU no matter what.
- // Figure out the max number of additional CPUs.
- max--;
+void
+runtime_helpgc(int32 nproc)
+{
+ M *mp;
+ int32 n;
runtime_lock(&runtime_sched);
- n = 0;
- while(n < max && (mp = mget(nil)) != nil) {
- n++;
+ for(n = 1; n < nproc; n++) { // one M is currently running
+ mp = mget(nil);
+ if(mp == nil)
+ runtime_throw("runtime_gcprocs inconsistency");
mp->helpgc = 1;
mp->waitnextg = 0;
runtime_notewakeup(&mp->havenextg);
}
runtime_unlock(&runtime_sched);
- if(extra)
- *extra = n != max;
- return n;
}
void
@@ -1037,26 +1049,38 @@ runtime_stoptheworld(void)
}
void
-runtime_starttheworld(bool extra)
+runtime_starttheworld(void)
{
- M *m;
+ M *mp;
+ int32 max;
+
+ // Figure out how many CPUs GC could possibly use.
+ max = runtime_gomaxprocs;
+ if(max > runtime_ncpu)
+ max = runtime_ncpu > 0 ? runtime_ncpu : 1;
+ if(max > MaxGcproc)
+ max = MaxGcproc;
schedlock();
runtime_gcwaiting = 0;
setmcpumax(runtime_gomaxprocs);
matchmg();
- if(extra && canaddmcpu()) {
- // Start a new m that will (we hope) be idle
- // and so available to help when the next
- // garbage collection happens.
+ if(runtime_gcprocs() < max && canaddmcpu()) {
+ // If GC could have used another helper proc, start one now,
+ // in the hope that it will be available next time.
+ // It would have been even better to start it before the collection,
+ // but doing so requires allocating memory, so it's tricky to
+ // coordinate. This lazy approach works out in practice:
+ // we don't mind if the first couple gc rounds don't have quite
+ // the maximum number of procs.
// canaddmcpu above did mcpu++
// (necessary, because m will be doing various
// initialization work so is definitely running),
// but m is not running a specific goroutine,
// so set the helpgc flag as a signal to m's
// first schedule(nil) to mcpu-- and grunning--.
- m = runtime_newm();
- m->helpgc = 1;
+ mp = runtime_newm();
+ mp->helpgc = 1;
runtime_sched.grunning++;
}
schedunlock();
@@ -1110,6 +1134,11 @@ runtime_mstart(void* mp)
runtime_initsig();
schedule(nil);
+
+ // TODO(brainman): This point is never reached, because scheduler
+ // does not release os threads at the moment. But once this path
+ // is enabled, we must remove our seh here.
+
return nil;
}
@@ -1148,14 +1177,14 @@ matchmg(void)
M*
runtime_newm(void)
{
- M *m;
+ M *mp;
pthread_attr_t attr;
pthread_t tid;
size_t stacksize;
- m = runtime_malloc(sizeof(M));
- mcommoninit(m);
- m->g0 = runtime_malg(-1, nil, nil);
+ mp = runtime_malloc(sizeof(M));
+ mcommoninit(mp);
+ mp->g0 = runtime_malg(-1, nil, nil);
if(pthread_attr_init(&attr) != 0)
runtime_throw("pthread_attr_init");
@@ -1175,10 +1204,10 @@ runtime_newm(void)
if(pthread_attr_setstacksize(&attr, stacksize) != 0)
runtime_throw("pthread_attr_setstacksize");
- if(pthread_create(&tid, &attr, runtime_mstart, m) != 0)
+ if(pthread_create(&tid, &attr, runtime_mstart, mp) != 0)
runtime_throw("pthread_create");
- return m;
+ return mp;
}
// One round of scheduler: find a goroutine and run it.
@@ -1202,7 +1231,7 @@ schedule(G *gp)
if(atomic_mcpu(v) > maxgomaxprocs)
runtime_throw("negative mcpu in scheduler");
- switch(gp->status){
+ switch(gp->status) {
case Grunnable:
case Gdead:
// Shouldn't have been running!
@@ -1212,6 +1241,8 @@ schedule(G *gp)
gput(gp);
break;
case Gmoribund:
+ if(raceenabled)
+ runtime_racegoend(gp->goid);
gp->status = Gdead;
if(gp->lockedm) {
gp->lockedm = nil;
@@ -1224,7 +1255,7 @@ schedule(G *gp)
runtime_exit(0);
break;
}
- if(gp->readyonstop){
+ if(gp->readyonstop) {
gp->readyonstop = 0;
readylocked(gp);
}
@@ -1272,6 +1303,18 @@ runtime_gosched(void)
runtime_mcall(schedule);
}
+// Puts the current goroutine into a waiting state and unlocks the lock.
+// The goroutine can be made runnable again by calling runtime_ready(gp).
+void
+runtime_park(void (*unlockf)(Lock*), Lock *lock, const char *reason)
+{
+ g->status = Gwaiting;
+ g->waitreason = reason;
+ if(unlockf)
+ unlockf(lock);
+ runtime_gosched();
+}
+
// The goroutine g is about to enter a system call.
// Record that it's not using the cpu anymore.
// This is called only from the go syscall library and cgocall,
@@ -1448,10 +1491,15 @@ __go_go(void (*fn)(void*), void* arg)
byte *sp;
size_t spsize;
G *newg;
+ int32 goid;
+
+ goid = runtime_xadd((uint32*)&runtime_sched.goidgen, 1);
+ if(raceenabled)
+ runtime_racegostart(goid, runtime_getcallerpc(&fn));
schedlock();
- if((newg = gfget()) != nil){
+ if((newg = gfget()) != nil) {
#ifdef USING_SPLIT_STACK
int dont_block_signals = 0;
@@ -1482,8 +1530,7 @@ __go_go(void (*fn)(void*), void* arg)
newg->gopc = (uintptr)__builtin_return_address(0);
runtime_sched.gcount++;
- runtime_sched.goidgen++;
- newg->goid = runtime_sched.goidgen;
+ newg->goid = goid;
if(sp == nil)
runtime_throw("nil g->stack0");
@@ -1512,49 +1559,22 @@ __go_go(void (*fn)(void*), void* arg)
// Put on gfree list. Sched must be locked.
static void
-gfput(G *g)
+gfput(G *gp)
{
- g->schedlink = runtime_sched.gfree;
- runtime_sched.gfree = g;
+ gp->schedlink = runtime_sched.gfree;
+ runtime_sched.gfree = gp;
}
// Get from gfree list. Sched must be locked.
static G*
gfget(void)
{
- G *g;
-
- g = runtime_sched.gfree;
- if(g)
- runtime_sched.gfree = g->schedlink;
- return g;
-}
-
-// Run all deferred functions for the current goroutine.
-static void
-rundefer(void)
-{
- Defer *d;
-
- while((d = g->defer) != nil) {
- void (*pfn)(void*);
-
- pfn = d->__pfn;
- d->__pfn = nil;
- if (pfn != nil)
- (*pfn)(d->__arg);
- g->defer = d->__next;
- runtime_free(d);
- }
-}
-
-void runtime_Goexit (void) asm ("runtime.Goexit");
+ G *gp;
-void
-runtime_Goexit(void)
-{
- rundefer();
- runtime_goexit();
+ gp = runtime_sched.gfree;
+ if(gp)
+ runtime_sched.gfree = gp->schedlink;
+ return gp;
}
void runtime_Gosched (void) asm ("runtime.Gosched");
@@ -1651,10 +1671,10 @@ runtime_mid()
return m->id;
}
-int32 runtime_NumGoroutine (void)
+intgo runtime_NumGoroutine (void)
__asm__ ("runtime.NumGoroutine");
-int32
+intgo
runtime_NumGoroutine()
{
return runtime_sched.gcount;
diff --git a/libgo/runtime/race.h b/libgo/runtime/race.h
new file mode 100644
index 00000000000..4bb7163f42c
--- /dev/null
+++ b/libgo/runtime/race.h
@@ -0,0 +1,30 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Definitions related to data race detection.
+
+#ifdef RACE
+enum { raceenabled = 1 };
+#else
+enum { raceenabled = 0 };
+#endif
+
+// Initialize race detection subsystem.
+void runtime_raceinit(void);
+// Finalize race detection subsystem, does not return.
+void runtime_racefini(void);
+
+void runtime_racemalloc(void *p, uintptr sz, void *pc);
+void runtime_racefree(void *p);
+void runtime_racegostart(int32 goid, void *pc);
+void runtime_racegoend(int32 goid);
+void runtime_racewritepc(void *addr, void *pc);
+void runtime_racereadpc(void *addr, void *pc);
+void runtime_racefingo(void);
+void runtime_raceacquire(void *addr);
+void runtime_raceacquireg(G *gp, void *addr);
+void runtime_racerelease(void *addr);
+void runtime_racereleaseg(G *gp, void *addr);
+void runtime_racereleasemerge(void *addr);
+void runtime_racereleasemergeg(G *gp, void *addr);
diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c
index 86115965734..c5716ab8fc1 100644
--- a/libgo/runtime/runtime.c
+++ b/libgo/runtime/runtime.c
@@ -4,13 +4,13 @@
#include <unistd.h>
+#include "config.h"
+
#include "runtime.h"
#include "array.h"
#include "go-panic.h"
#include "go-string.h"
-uint32 runtime_panicking;
-
int32
runtime_gotraceback(void)
{
@@ -22,84 +22,6 @@ runtime_gotraceback(void)
return runtime_atoi(p);
}
-static Lock paniclk;
-
-void
-runtime_startpanic(void)
-{
- M *m;
-
- m = runtime_m();
- if(m->dying) {
- runtime_printf("panic during panic\n");
- runtime_exit(3);
- }
- m->dying = 1;
- runtime_xadd(&runtime_panicking, 1);
- runtime_lock(&paniclk);
-}
-
-void
-runtime_dopanic(int32 unused __attribute__ ((unused)))
-{
- G* g;
- static bool didothers;
-
- g = runtime_g();
- if(g->sig != 0)
- runtime_printf("[signal %x code=%p addr=%p]\n",
- g->sig, (void*)(g->sigcode0), (void*)(g->sigcode1));
-
- if(runtime_gotraceback()){
- if(g != runtime_m()->g0) {
- runtime_printf("\n");
- runtime_goroutineheader(g);
- runtime_traceback();
- runtime_goroutinetrailer(g);
- }
- if(!didothers) {
- didothers = true;
- runtime_tracebackothers(g);
- }
- }
-
- runtime_unlock(&paniclk);
- if(runtime_xadd(&runtime_panicking, -1) != 0) {
- // Some other m is panicking too.
- // Let it print what it needs to print.
- // Wait forever without chewing up cpu.
- // It will exit when it's done.
- static Lock deadlock;
- runtime_lock(&deadlock);
- runtime_lock(&deadlock);
- }
-
- runtime_exit(2);
-}
-
-void
-runtime_throw(const char *s)
-{
- runtime_startpanic();
- runtime_printf("throw: %s\n", s);
- runtime_dopanic(0);
- *(int32*)0 = 0; // not reached
- runtime_exit(1); // even more not reached
-}
-
-void
-runtime_panicstring(const char *s)
-{
- Eface err;
-
- if(runtime_m()->gcing) {
- runtime_printf("panic: %s\n", s);
- runtime_throw("panic during gc");
- }
- runtime_newErrorString(runtime_gostringnocopy((const byte*)s), &err);
- runtime_panic(err);
-}
-
static int32 argc;
static byte** argv;
@@ -247,14 +169,41 @@ runtime_showframe(const unsigned char *s)
return traceback > 1 || (s != nil && __builtin_strchr((const char*)s, '.') != nil && __builtin_memcmp(s, "runtime.", 7) != 0);
}
-bool
-runtime_isInf(float64 f, int32 sign)
+static Lock ticksLock;
+static int64 ticks;
+
+int64
+runtime_tickspersecond(void)
+{
+ int64 res, t0, t1, c0, c1;
+
+ res = (int64)runtime_atomicload64((uint64*)&ticks);
+ if(res != 0)
+ return ticks;
+ runtime_lock(&ticksLock);
+ res = ticks;
+ if(res == 0) {
+ t0 = runtime_nanotime();
+ c0 = runtime_cputicks();
+ runtime_usleep(100*1000);
+ t1 = runtime_nanotime();
+ c1 = runtime_cputicks();
+ if(t1 == t0)
+ t1++;
+ res = (c1-c0)*1000*1000*1000/(t1-t0);
+ if(res == 0)
+ res++;
+ runtime_atomicstore64((uint64*)&ticks, res);
+ }
+ runtime_unlock(&ticksLock);
+ return res;
+}
+
+int64 runtime_pprof_runtime_cyclesPerSecond(void)
+ asm("runtime_pprof.runtime_cyclesPerSecond");
+
+int64
+runtime_pprof_runtime_cyclesPerSecond(void)
{
- if(!__builtin_isinf(f))
- return false;
- if(sign == 0)
- return true;
- if(sign > 0)
- return f > 0;
- return f < 0;
+ return runtime_tickspersecond();
}
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index 74050da9e98..defe792c761 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -1,8 +1,6 @@
-/* runtime.h -- runtime support for Go.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
#include "config.h"
@@ -42,8 +40,12 @@ typedef signed int int64 __attribute__ ((mode (DI)));
typedef unsigned int uint64 __attribute__ ((mode (DI)));
typedef float float32 __attribute__ ((mode (SF)));
typedef double float64 __attribute__ ((mode (DF)));
+typedef signed int intptr __attribute__ ((mode (pointer)));
typedef unsigned int uintptr __attribute__ ((mode (pointer)));
+typedef int intgo; // Go's int
+typedef unsigned int uintgo; // Go's uint
+
/* Defined types. */
typedef uint8 bool;
@@ -59,6 +61,10 @@ typedef struct FixAlloc FixAlloc;
typedef struct Hchan Hchan;
typedef struct Timers Timers;
typedef struct Timer Timer;
+typedef struct GCStats GCStats;
+typedef struct LFNode LFNode;
+typedef struct ParFor ParFor;
+typedef struct ParForThread ParForThread;
typedef struct __go_open_array Slice;
typedef struct __go_string String;
@@ -105,6 +111,10 @@ enum
true = 1,
false = 0,
};
+enum
+{
+ PtrSize = sizeof(void*),
+};
/*
* structures
@@ -119,6 +129,16 @@ union Note
uint32 key; // futex-based impl
M* waitm; // waiting M (sema-based impl)
};
+struct GCStats
+{
+ // the struct must consist of only uint64's,
+ // because it is casted to uint64[].
+ uint64 nhandoff;
+ uint64 nhandoffcnt;
+ uint64 nprocyield;
+ uint64 nosyield;
+ uint64 nsleep;
+};
struct G
{
Defer* defer;
@@ -142,6 +162,7 @@ struct G
G* schedlink;
bool readyonstop;
bool ispanic;
+ int8 raceignore; // ignore race detection events
M* m; // for debuggers, but offset not hard-coded
M* lockedm;
M* idlem;
@@ -190,6 +211,14 @@ struct M
uintptr waitsema; // semaphore for parking on locks
uint32 waitsemacount;
uint32 waitsemalock;
+ GCStats gcstats;
+ bool racecall;
+ void* racepc;
+
+ uintptr settype_buf[1024];
+ uintptr settype_bufsize;
+
+ uintptr end[];
};
struct SigTab
@@ -218,7 +247,6 @@ struct Func
uintptr entry; // entry pc
};
-/* Macros. */
#ifdef GOOS_windows
enum {
@@ -257,6 +285,34 @@ struct Timer
Eface arg;
};
+// Lock-free stack node.
+struct LFNode
+{
+ LFNode *next;
+ uintptr pushcnt;
+};
+
+// Parallel for descriptor.
+struct ParFor
+{
+ void (*body)(ParFor*, uint32); // executed for each element
+ uint32 done; // number of idle threads
+ uint32 nthr; // total number of threads
+ uint32 nthrmax; // maximum number of threads
+ uint32 thrseq; // thread id sequencer
+ uint32 cnt; // iteration space [0, cnt)
+ void *ctx; // arbitrary user context
+ bool wait; // if true, wait while all threads finish processing,
+ // otherwise parfor may return while other threads are still working
+ ParForThread *thr; // array of thread descriptors
+ // stats
+ uint64 nsteal;
+ uint64 nstealcnt;
+ uint64 nprocyield;
+ uint64 nosyield;
+ uint64 nsleep;
+};
+
/*
* defined macros
* you need super-gopher-guru privilege
@@ -265,6 +321,7 @@ struct Timer
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
#define nil ((void*)0)
#define USED(v) ((void) v)
+#define ROUND(x, n) (((x)+(n)-1)&~((n)-1)) /* all-caps to mark as macro: it evaluates n twice */
/*
* external data
@@ -312,7 +369,8 @@ G* runtime_malg(int32, byte**, size_t*);
void runtime_minit(void);
void runtime_mallocinit(void);
void runtime_gosched(void);
-void runtime_tsleep(int64);
+void runtime_park(void(*)(Lock*), Lock*, const char*);
+void runtime_tsleep(int64, const char*);
M* runtime_newm(void);
void runtime_goexit(void);
void runtime_entersyscall(void) __asm__("syscall.Entersyscall");
@@ -322,9 +380,12 @@ bool __go_sigsend(int32 sig);
int32 runtime_callers(int32, uintptr*, int32);
int64 runtime_nanotime(void);
int64 runtime_cputicks(void);
+int64 runtime_tickspersecond(void);
+void runtime_blockevent(int64, int32);
+extern int64 runtime_blockprofilerate;
void runtime_stoptheworld(void);
-void runtime_starttheworld(bool);
+void runtime_starttheworld(void);
extern uint32 runtime_worldsema;
G* __go_go(void (*pfn)(void*), void*);
@@ -372,6 +433,28 @@ void runtime_futexsleep(uint32*, uint32, int64);
void runtime_futexwakeup(uint32*, uint32);
/*
+ * Lock-free stack.
+ * Initialize uint64 head to 0, compare with 0 to test for emptiness.
+ * The stack does not keep pointers to nodes,
+ * so they can be garbage collected if there are no other pointers to nodes.
+ */
+void runtime_lfstackpush(uint64 *head, LFNode *node)
+ asm("runtime.lfstackpush");
+LFNode* runtime_lfstackpop(uint64 *head);
+
+/*
+ * Parallel for over [0, n).
+ * body() is executed for each iteration.
+ * nthr - total number of worker threads.
+ * ctx - arbitrary user context.
+ * if wait=true, threads return from parfor() when all work is done;
+ * otherwise, threads can return while other threads are still finishing processing.
+ */
+ParFor* runtime_parforalloc(uint32 nthrmax);
+void runtime_parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32));
+void runtime_parfordo(ParFor *desc) asm("runtime.parfordo");
+
+/*
* low level C-called
*/
#define runtime_mmap mmap
@@ -432,12 +515,17 @@ MCache* runtime_allocmcache(void);
void free(void *v);
#define runtime_cas(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
#define runtime_casp(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
+#define runtime_cas64(pval, pold, new) __atomic_compare_exchange_n (pval, pold, new, 1, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)
#define runtime_xadd(p, v) __sync_add_and_fetch (p, v)
+#define runtime_xadd64(p, v) __sync_add_and_fetch (p, v)
#define runtime_xchg(p, v) __atomic_exchange_n (p, v, __ATOMIC_SEQ_CST)
#define runtime_atomicload(p) __atomic_load_n (p, __ATOMIC_SEQ_CST)
#define runtime_atomicstore(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST)
#define runtime_atomicloadp(p) __atomic_load_n (p, __ATOMIC_SEQ_CST)
#define runtime_atomicstorep(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST)
+#define runtime_atomicload64(p) __atomic_load_n (p, __ATOMIC_SEQ_CST)
+#define runtime_atomicstore64(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST)
+#define PREFETCH(p) __builtin_prefetch(p)
struct __go_func_type;
bool runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *);
@@ -469,8 +557,7 @@ void runtime_newErrorString(String, Eface*)
/*
* wrapped for go users
*/
-bool runtime_isInf(float64 f, int32 sign);
-#define runtime_isNaN(f) __builtin_isnan(f)
+#define ISNAN(f) __builtin_isnan(f)
void runtime_semacquire(uint32 volatile *);
void runtime_semrelease(uint32 volatile *);
int32 runtime_gomaxprocsfunc(int32 n);
@@ -493,8 +580,13 @@ uintptr runtime_memlimit(void);
// This is a no-op on other systems.
void runtime_setprof(bool);
-void runtime_time_scan(void (*)(byte*, int64));
-void runtime_trampoline_scan(void (*)(byte *, int64));
+enum
+{
+ UseSpanType = 1,
+};
+
+void runtime_time_scan(void (*)(byte*, uintptr));
+void runtime_trampoline_scan(void (*)(byte *, uintptr));
void runtime_setsig(int32, bool, bool);
#define runtime_setitimer setitimer
diff --git a/libgo/runtime/runtime1.goc b/libgo/runtime/runtime1.goc
index fd8918ed577..9ce83000b83 100644
--- a/libgo/runtime/runtime1.goc
+++ b/libgo/runtime/runtime1.goc
@@ -5,10 +5,10 @@
package runtime
#include "runtime.h"
-func GOMAXPROCS(n int32) (ret int32) {
+func GOMAXPROCS(n int) (ret int) {
ret = runtime_gomaxprocsfunc(n);
}
-func NumCPU() (ret int32) {
+func NumCPU() (ret int) {
ret = runtime_ncpu;
}
diff --git a/libgo/runtime/sema.goc b/libgo/runtime/sema.goc
index ff9c4f2e19e..4622f6c8a61 100644
--- a/libgo/runtime/sema.goc
+++ b/libgo/runtime/sema.goc
@@ -24,30 +24,32 @@ package sync
typedef struct Sema Sema;
struct Sema
{
- uint32 volatile *addr;
- G *g;
- Sema *prev;
- Sema *next;
+ uint32 volatile* addr;
+ G* g;
+ int64 releasetime;
+ Sema* prev;
+ Sema* next;
};
typedef struct SemaRoot SemaRoot;
struct SemaRoot
{
- Lock;
- Sema *head;
- Sema *tail;
+ Lock;
+ Sema* head;
+ Sema* tail;
// Number of waiters. Read w/o the lock.
- uint32 volatile nwait;
+ uint32 volatile nwait;
};
// Prime to not correlate with any user patterns.
#define SEMTABLESZ 251
-static union
+union semtable
{
SemaRoot;
uint8 pad[CacheLineSize];
-} semtable[SEMTABLESZ];
+};
+static union semtable semtable[SEMTABLESZ];
static SemaRoot*
semroot(uint32 volatile *addr)
@@ -95,13 +97,13 @@ cansemacquire(uint32 volatile *addr)
return 0;
}
-void
-runtime_semacquire(uint32 volatile *addr)
+static void
+semacquireimpl(uint32 volatile *addr, int32 profile)
{
- G *g;
- Sema s;
+ Sema s; // Needs to be allocated on stack, otherwise garbage collector could deallocate it
SemaRoot *root;
-
+ int64 t0;
+
// Easy case.
if(cansemacquire(addr))
return;
@@ -112,8 +114,13 @@ runtime_semacquire(uint32 volatile *addr)
// enqueue itself as a waiter
// sleep
// (waiter descriptor is dequeued by signaler)
- g = runtime_g();
root = semroot(addr);
+ t0 = 0;
+ s.releasetime = 0;
+ if(profile && runtime_blockprofilerate > 0) {
+ t0 = runtime_cputicks();
+ s.releasetime = -1;
+ }
for(;;) {
runtime_lock(root);
@@ -128,16 +135,22 @@ runtime_semacquire(uint32 volatile *addr)
// Any semrelease after the cansemacquire knows we're waiting
// (we set nwait above), so go to sleep.
semqueue(root, addr, &s);
- g->status = Gwaiting;
- g->waitreason = "semacquire";
- runtime_unlock(root);
- runtime_gosched();
- if(cansemacquire(addr))
+ runtime_park(runtime_unlock, root, "semacquire");
+ if(cansemacquire(addr)) {
+ if(t0)
+ runtime_blockevent(s.releasetime - t0, 3);
return;
+ }
}
}
void
+runtime_semacquire(uint32 volatile *addr)
+{
+ semacquireimpl(addr, 0);
+}
+
+void
runtime_semrelease(uint32 volatile *addr)
{
Sema *s;
@@ -168,12 +181,15 @@ runtime_semrelease(uint32 volatile *addr)
}
}
runtime_unlock(root);
- if(s)
+ if(s) {
+ if(s->releasetime)
+ s->releasetime = runtime_cputicks();
runtime_ready(s->g);
+ }
}
func runtime_Semacquire(addr *uint32) {
- runtime_semacquire(addr);
+ semacquireimpl(addr, 1);
}
func runtime_Semrelease(addr *uint32) {
diff --git a/libgo/runtime/string.goc b/libgo/runtime/string.goc
index 486caf09a42..4e616c7a165 100644
--- a/libgo/runtime/string.goc
+++ b/libgo/runtime/string.goc
@@ -32,8 +32,8 @@ enum
Runeself = 0x80,
};
-func stringiter(s String, k int32) (retk int32) {
- int32 l, n;
+func stringiter(s String, k int) (retk int) {
+ int32 l;
if(k >= s.__length) {
// retk=0 is end of iteration
@@ -48,15 +48,12 @@ func stringiter(s String, k int32) (retk int32) {
}
// multi-char rune
- n = charntorune(&l, s.__data+k, s.__length-k);
- retk = k + (n ? n : 1);
+ retk = k + charntorune(&l, s.__data+k, s.__length-k);
out:
}
-func stringiter2(s String, k int32) (retk int32, retv int32) {
- int32 n;
-
+func stringiter2(s String, k int) (retk int, retv int) {
if(k >= s.__length) {
// retk=0 is end of iteration
retk = 0;
@@ -71,8 +68,7 @@ func stringiter2(s String, k int32) (retk int32, retv int32) {
}
// multi-char rune
- n = charntorune(&retv, s.__data+k, s.__length-k);
- retk = k + (n ? n : 1);
+ retk = k + charntorune(&retv, s.__data+k, s.__length-k);
out:
}
diff --git a/libgo/runtime/time.goc b/libgo/runtime/time.goc
index b3f0fb0278f..5077b719fcf 100644
--- a/libgo/runtime/time.goc
+++ b/libgo/runtime/time.goc
@@ -10,6 +10,7 @@ package time
#include "defs.h"
#include "arch.h"
#include "malloc.h"
+#include "race.h"
static Timers timers;
static void addtimer(Timer*);
@@ -22,17 +23,16 @@ static bool deltimer(Timer*);
// Sleep puts the current goroutine to sleep for at least ns nanoseconds.
func Sleep(ns int64) {
- G *g;
-
- g = runtime_g();
- g->status = Gwaiting;
- g->waitreason = "sleep";
- runtime_tsleep(ns);
+ runtime_tsleep(ns, "sleep");
}
// startTimer adds t to the timer heap.
func startTimer(t *Timer) {
+ if(raceenabled)
+ runtime_racerelease(t);
+ runtime_lock(&timers);
addtimer(t);
+ runtime_unlock(&timers);
}
// stopTimer removes t from the timer heap if it is there.
@@ -57,27 +57,24 @@ ready(int64 now, Eface e)
}
// Put the current goroutine to sleep for ns nanoseconds.
-// The caller must have set g->status and g->waitreason.
void
-runtime_tsleep(int64 ns)
+runtime_tsleep(int64 ns, const char *reason)
{
G* g;
Timer t;
g = runtime_g();
- if(ns <= 0) {
- g->status = Grunning;
- g->waitreason = nil;
+ if(ns <= 0)
return;
- }
t.when = runtime_nanotime() + ns;
t.period = 0;
t.f = ready;
t.arg.__object = g;
+ runtime_lock(&timers);
addtimer(&t);
- runtime_gosched();
+ runtime_park(runtime_unlock, &timers, reason);
}
// Add a timer to the heap and start or kick the timer proc
@@ -88,7 +85,6 @@ addtimer(Timer *t)
int32 n;
Timer **nt;
- runtime_lock(&timers);
if(timers.len >= timers.cap) {
// Grow slice.
n = 16;
@@ -116,7 +112,6 @@ addtimer(Timer *t)
}
if(timers.timerproc == nil)
timers.timerproc = __go_go(timerproc, nil);
- runtime_unlock(&timers);
}
// Delete timer t from the heap.
@@ -159,13 +154,11 @@ deltimer(Timer *t)
static void
timerproc(void* dummy __attribute__ ((unused)))
{
- G *g;
int64 delta, now;
Timer *t;
void (*f)(int64, Eface);
Eface arg;
- g = runtime_g();
for(;;) {
runtime_lock(&timers);
now = runtime_nanotime();
@@ -192,16 +185,15 @@ timerproc(void* dummy __attribute__ ((unused)))
f = t->f;
arg = t->arg;
runtime_unlock(&timers);
+ if(raceenabled)
+ runtime_raceacquire(t);
f(now, arg);
runtime_lock(&timers);
}
if(delta < 0) {
// No timers left - put goroutine to sleep.
timers.rescheduling = true;
- g->status = Gwaiting;
- g->waitreason = "timer goroutine (idle)";
- runtime_unlock(&timers);
- runtime_gosched();
+ runtime_park(runtime_unlock, &timers, "timer goroutine (idle)");
continue;
}
// At least one timer pending. Sleep until then.
@@ -263,7 +255,7 @@ siftdown(int32 i)
}
void
-runtime_time_scan(void (*scan)(byte*, int64))
+runtime_time_scan(void (*addroot)(byte*, uintptr))
{
- scan((byte*)&timers, sizeof timers);
+ addroot((byte*)&timers, sizeof timers);
}
diff --git a/libgo/testsuite/gotest b/libgo/testsuite/gotest
index 208cbaf8af3..bbe77cce09d 100755
--- a/libgo/testsuite/gotest
+++ b/libgo/testsuite/gotest
@@ -346,6 +346,11 @@ fi
# They all compile; now generate the code to call them.
+testname() {
+ # Remove the package from the name used with the -test option.
+ echo $1 | sed 's/^.*\.//'
+}
+
localname() {
# The package main has been renamed to __main__ when imported.
# Adjust its uses.
@@ -373,7 +378,7 @@ localname() {
fi
# benchmarks are named BenchmarkFoo.
pattern='Benchmark([^a-z].*)?'
- benchmarks=$($NM -p -v _gotest_.o $xofile | egrep " $test .*\."$pattern'$' | grep -v '\..*\..*\.' | fgrep -v '$' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo)
+ benchmarks=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | grep -v '\..*\..*\.' | fgrep -v '$' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo)
# examples are named ExampleFoo
pattern='Example([^a-z].*)?'
@@ -396,8 +401,9 @@ localname() {
echo 'var tests = []testing.InternalTest {'
for i in $tests
do
+ n=$(testname $i)
j=$(localname $i)
- echo ' {"'$i'", '$j'},'
+ echo ' {"'$n'", '$j'},'
done
echo '}'
@@ -407,8 +413,9 @@ localname() {
echo 'var benchmarks = []testing.InternalBenchmark{ //'
for i in $benchmarks
do
+ n=$(testname $i)
j=$(localname $i)
- echo ' {"'$i'", '$j'},'
+ echo ' {"'$n'", '$j'},'
done
echo '}'
@@ -417,8 +424,9 @@ localname() {
# This doesn't work because we don't pick up the output.
#for i in $examples
#do
+ # n=$(testname $i)
# j=$(localname $i)
- # echo ' {"'$i'", '$j', ""},'
+ # echo ' {"'$n'", '$j', ""},'
#done
echo '}'